summaryrefslogtreecommitdiff
path: root/chromium/third_party/angle/src/libANGLE/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/angle/src/libANGLE/renderer')
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h65
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h65
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/Renderer.h1
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp139
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h26
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp76
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp61
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp1447
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h97
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp30
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp67
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h35
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp21
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp130
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h18
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp1074
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h194
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp117
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h83
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp19
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp27
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h26
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp47
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp397
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h175
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp18
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp53
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp176
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h19
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp44
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp16
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp127
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h11
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h17
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp102
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp1387
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h132
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp582
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h107
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp324
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h27
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp15
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py199
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py133
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py303
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp170
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h31
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json1107
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h30
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp2079
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp63
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h36
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json77
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp118
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp203
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json686
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp1775
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp29
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h39
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp112
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp18
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp10
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp573
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h121
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp898
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h192
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp25
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h10
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp953
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h130
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp63
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp36
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp38
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp188
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp145
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h28
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp35
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp178
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h17
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp115
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h10
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm16
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h53
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm394
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp47
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp349
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h41
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md32
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp93
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h9
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp40
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp72
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp24
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp46
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h19
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp2
138 files changed, 16244 insertions, 3886 deletions
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h
index eb150549e14..550bc1e2d9a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/DeviceImpl.h
@@ -26,9 +26,10 @@ class DeviceImpl : angle::NonCopyable
DeviceImpl();
virtual ~DeviceImpl();
- virtual egl::Error getDevice(EGLAttrib *value) = 0;
+ virtual egl::Error getDevice(void **outValue) = 0;
virtual EGLint getType() = 0;
virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
+ virtual bool deviceExternallySourced() = 0;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp b/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp
index 2eb44eb5ba1..8061189f0a7 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/DisplayImpl.cpp
@@ -21,10 +21,7 @@ DisplayImpl::DisplayImpl()
DisplayImpl::~DisplayImpl()
{
- while (!mSurfaceSet.empty())
- {
- destroySurface(*mSurfaceSet.begin());
- }
+ ASSERT(mSurfaceSet.empty());
}
void DisplayImpl::destroySurface(egl::Surface *surface)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h
index dddd9b87788..a9ae37891ea 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl.h
@@ -44,10 +44,23 @@ class FramebufferImpl : angle::NonCopyable
virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
- virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0;
- virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0;
- virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0;
- virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
+ virtual gl::Error clearBufferfv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) = 0;
+ virtual gl::Error clearBufferuiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) = 0;
+ virtual gl::Error clearBufferiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) = 0;
+ virtual gl::Error clearBufferfi(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) = 0;
virtual GLenum getImplementationColorReadFormat() const = 0;
virtual GLenum getImplementationColorReadType() const = 0;
@@ -56,7 +69,7 @@ class FramebufferImpl : angle::NonCopyable
virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0;
- virtual GLenum checkStatus() const = 0;
+ virtual bool checkStatus() const = 0;
const gl::Framebuffer::Data &getData() const { return mData; }
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
new file mode 100644
index 00000000000..b5a1eded586
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -0,0 +1,65 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FramebufferImpl_mock.h:
+// Defines a mock of the FramebufferImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+class MockFramebufferImpl : public rx::FramebufferImpl
+{
+ public:
+ MockFramebufferImpl() : rx::FramebufferImpl(gl::Framebuffer::Data()) {}
+ virtual ~MockFramebufferImpl() { destroy(); }
+
+ MOCK_METHOD1(onUpdateColorAttachment, void(size_t));
+ MOCK_METHOD0(onUpdateDepthAttachment, void());
+ MOCK_METHOD0(onUpdateStencilAttachment, void());
+ MOCK_METHOD0(onUpdateDepthStencilAttachment, void());
+
+ MOCK_METHOD2(setDrawBuffers, void(size_t, const GLenum *));
+ MOCK_METHOD1(setReadBuffer, void(GLenum));
+
+ MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
+ MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
+ MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
+
+ MOCK_METHOD2(clear, gl::Error(const gl::Data &, GLbitfield));
+ MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Data &, GLenum, GLint, const GLfloat *));
+ MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Data &, GLenum, GLint, const GLuint *));
+ MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Data &, GLenum, GLint, const GLint *));
+ MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Data &, GLenum, GLint, GLfloat, GLint));
+
+ MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
+ MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
+ MOCK_CONST_METHOD5(
+ readPixels,
+ gl::Error(const gl::State &, const gl::Rectangle &, GLenum, GLenum, GLvoid *));
+
+ MOCK_METHOD6(blit,
+ gl::Error(const gl::State &,
+ const gl::Rectangle &,
+ const gl::Rectangle &,
+ GLbitfield,
+ GLenum,
+ const gl::Framebuffer *));
+
+ MOCK_CONST_METHOD0(checkStatus, bool());
+
+ MOCK_METHOD0(destroy, void());
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
index a94f04b20c4..1e688045a1b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable
virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
+ virtual void setBinaryRetrievableHint(bool retrievable) = 0;
virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0;
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
@@ -66,9 +67,14 @@ class ProgramImpl : angle::NonCopyable
// TODO: synchronize in syncState when dirty bits exist.
virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
- // Gather uniform block active uniform indices, and uniform block offset info.
- virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
- std::vector<gl::LinkedUniform> *uniforms) = 0;
+ // May only be called after a successful link operation.
+ // Return false for inactive blocks.
+ virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
+
+ // May only be called after a successful link operation.
+ // Returns false for inactive members.
+ virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const = 0;
protected:
const gl::Program::Data &mData;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h
new file mode 100644
index 00000000000..0db2330228d
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl_mock.h
@@ -0,0 +1,65 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramImpl_mock.h:
+// Defines a mock of the ProgramImpl class.
+//
+
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+class MockProgramImpl : public rx::ProgramImpl
+{
+ public:
+ MockProgramImpl() : ProgramImpl(gl::Program::Data()) {}
+ virtual ~MockProgramImpl() { destroy(); }
+
+ MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
+ MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
+ MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
+
+ MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &));
+ MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
+
+ MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform2fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform3fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform4fv, void(GLint, GLsizei, const GLfloat *));
+ MOCK_METHOD3(setUniform1iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform2iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform3iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform4iv, void(GLint, GLsizei, const GLint *));
+ MOCK_METHOD3(setUniform1uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform2uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform3uiv, void(GLint, GLsizei, const GLuint *));
+ MOCK_METHOD3(setUniform4uiv, void(GLint, GLsizei, const GLuint *));
+
+ MOCK_METHOD4(setUniformMatrix2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix2x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix2x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+
+ MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
+ MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *));
+ MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *));
+
+ MOCK_METHOD0(destroy, void());
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h b/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h
index 06fe560d5c2..b20dcaf0fc3 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/Renderer.h
@@ -82,7 +82,6 @@ class Renderer : public ImplFactory
virtual bool testDeviceLost() = 0;
virtual bool testDeviceResettable() = 0;
- virtual VendorID getVendorId() const = 0;
virtual std::string getVendorString() const = 0;
virtual std::string getRendererDescription() const = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
index ec164f3f7fc..5a466377a53 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -22,12 +22,15 @@ class ShaderImpl : angle::NonCopyable
virtual ~ShaderImpl() { }
// Returns additional ShCompile options.
- virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream) = 0;
+ virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) = 0;
// Returns success for compiling on the driver. Returns success.
virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0;
virtual std::string getDebugInfo() const = 0;
+ const gl::Shader::Data &getData() const { return mData; }
+
protected:
const gl::Shader::Data &mData;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h
index 1d5211bb9a9..32125d542c4 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/SurfaceImpl.h
@@ -36,7 +36,7 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual egl::Error swap() = 0;
virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
- virtual egl::Error bindTexImage(EGLint buffer) = 0;
+ virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0;
virtual egl::Error releaseTexImage(EGLint buffer) = 0;
virtual void setSwapInterval(EGLint interval) = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
index 693b27116fa..ffca99c3ac6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -8,6 +8,7 @@
#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/VertexBuffer.h"
@@ -22,6 +23,9 @@ BufferD3D::BufferD3D(BufferFactoryD3D *factory)
mFactory(factory),
mStaticVertexBuffer(nullptr),
mStaticIndexBuffer(nullptr),
+ mStaticBufferCache(nullptr),
+ mStaticBufferCacheTotalSize(0),
+ mStaticVertexBufferOutOfDate(false),
mUnmodifiedDataUse(0),
mUsage(D3D_BUFFER_USAGE_STATIC)
{
@@ -32,6 +36,19 @@ BufferD3D::~BufferD3D()
{
SafeDelete(mStaticVertexBuffer);
SafeDelete(mStaticIndexBuffer);
+
+ emptyStaticBufferCache();
+}
+
+void BufferD3D::emptyStaticBufferCache()
+{
+ if (mStaticBufferCache != nullptr)
+ {
+ SafeDeleteContainer(*mStaticBufferCache);
+ SafeDelete(mStaticBufferCache);
+ }
+
+ mStaticBufferCacheTotalSize = 0;
}
void BufferD3D::updateSerial()
@@ -75,8 +92,124 @@ void BufferD3D::initializeStaticData()
}
}
-void BufferD3D::invalidateStaticData()
+StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer()
+{
+ return mStaticIndexBuffer;
+}
+
+StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(
+ const gl::VertexAttribute &attribute,
+ D3DStaticBufferCreationType creationType)
+{
+ if (!mStaticVertexBuffer)
+ {
+ // Early out if there aren't any static buffers at all
+ ASSERT(mStaticBufferCache == nullptr);
+ return nullptr;
+ }
+
+ if (mStaticBufferCache == nullptr && !mStaticVertexBuffer->isCommitted())
+ {
+ // Early out, the attribute can be added to mStaticVertexBuffer or is already in there
+ return mStaticVertexBuffer;
+ }
+
+ // At this point, see if any of the existing static buffers contains the attribute data
+
+ // If the default static vertex buffer contains the attribute, then return it
+ if (mStaticVertexBuffer->lookupAttribute(attribute, nullptr))
+ {
+ return mStaticVertexBuffer;
+ }
+
+ if (mStaticBufferCache != nullptr)
+ {
+ // If there is a cached static buffer that already contains the attribute, then return it
+ for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache)
+ {
+ if (staticBuffer->lookupAttribute(attribute, nullptr))
+ {
+ return staticBuffer;
+ }
+ }
+ }
+
+ if (!mStaticVertexBuffer->isCommitted())
+ {
+ // None of the existing static buffers contain the attribute data and we are able to add
+ // the data to mStaticVertexBuffer, so we should just do so
+ return mStaticVertexBuffer;
+ }
+
+ // At this point, we must create a new static buffer for the attribute data
+ if (creationType != D3D_BUFFER_CREATE_IF_NECESSARY)
+ {
+ return nullptr;
+ }
+
+ ASSERT(mStaticVertexBuffer);
+ ASSERT(mStaticVertexBuffer->isCommitted());
+ unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize();
+ if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize))
+ {
+ // Ensure that the total size of the static buffer cache remains less than 4x the
+ // size of the original buffer
+ unsigned int maxStaticCacheSize =
+ IsUnsignedMultiplicationSafe(static_cast<unsigned int>(getSize()), 4u)
+ ? 4u * static_cast<unsigned int>(getSize())
+ : std::numeric_limits<unsigned int>::max();
+
+ // We can't reuse the default static vertex buffer, so we add it to the cache
+ if (staticVertexBufferSize + mStaticBufferCacheTotalSize <= maxStaticCacheSize)
+ {
+ if (mStaticBufferCache == nullptr)
+ {
+ mStaticBufferCache = new std::vector<StaticVertexBufferInterface *>();
+ }
+
+ mStaticBufferCacheTotalSize += staticVertexBufferSize;
+ (*mStaticBufferCache).push_back(mStaticVertexBuffer);
+ mStaticVertexBuffer = nullptr;
+
+ // Then reinitialize the static buffers to create a new static vertex buffer
+ initializeStaticData();
+
+ // Return the default static vertex buffer
+ return mStaticVertexBuffer;
+ }
+ }
+
+ // At this point:
+ // - mStaticVertexBuffer is committed and can't be altered
+ // - mStaticBufferCache is full (or nearly overflowing)
+ // The inputted attribute should be put in some static buffer at some point, but it can't
+ // go in one right now, since mStaticBufferCache is full and we can't delete mStaticVertexBuffer
+ // in case another attribute is relying upon it for the current draw.
+ // We therefore mark mStaticVertexBuffer for deletion at the next possible time.
+ mStaticVertexBufferOutOfDate = true;
+ return nullptr;
+}
+
+void BufferD3D::reinitOutOfDateStaticData()
{
+ if (mStaticVertexBufferOutOfDate)
+ {
+ // During the last draw the caller tried to use some attribute with static data, but neither
+ // the static buffer cache nor mStaticVertexBuffer contained that data.
+ // Therefore, invalidate mStaticVertexBuffer so that if the caller tries to use that
+ // attribute in the next draw, it'll successfully get put into mStaticVertexBuffer.
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY);
+ mStaticVertexBufferOutOfDate = false;
+ }
+}
+
+void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType)
+{
+ if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr)
+ {
+ emptyStaticBufferCache();
+ }
+
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
{
SafeDelete(mStaticVertexBuffer);
@@ -98,6 +231,10 @@ void BufferD3D::promoteStaticUsage(int dataSize)
{
if (!mStaticVertexBuffer && !mStaticIndexBuffer)
{
+ // There isn't any scenario that involves promoting static usage and the static buffer cache
+ // being non-empty
+ ASSERT(mStaticBufferCache == nullptr);
+
mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * getSize())
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h
index 239b7fb9f0c..a27ca9857af 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -13,6 +13,7 @@
#include "libANGLE/renderer/BufferImpl.h"
#include <stdint.h>
+#include <vector>
namespace rx
{
@@ -26,6 +27,18 @@ enum D3DBufferUsage
D3D_BUFFER_USAGE_DYNAMIC,
};
+enum D3DBufferInvalidationType
+{
+ D3D_BUFFER_INVALIDATE_WHOLE_CACHE,
+ D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY,
+};
+
+enum D3DStaticBufferCreationType
+{
+ D3D_BUFFER_CREATE_IF_NECESSARY,
+ D3D_BUFFER_DO_NOT_CREATE,
+};
+
class BufferD3D : public BufferImpl
{
public:
@@ -39,11 +52,14 @@ class BufferD3D : public BufferImpl
virtual void markTransformFeedbackUsage() = 0;
virtual gl::Error getData(const uint8_t **outData) = 0;
- StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
- StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
+ StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+ D3DStaticBufferCreationType creationType);
+ StaticIndexBufferInterface *getStaticIndexBuffer();
void initializeStaticData();
- void invalidateStaticData();
+ void invalidateStaticData(D3DBufferInvalidationType invalidationType);
+ void reinitOutOfDateStaticData();
+
void promoteStaticUsage(int dataSize);
gl::Error getIndexRange(GLenum type,
@@ -55,6 +71,7 @@ class BufferD3D : public BufferImpl
protected:
void updateSerial();
void updateD3DBufferUsage(GLenum usage);
+ void emptyStaticBufferCache();
BufferFactoryD3D *mFactory;
unsigned int mSerial;
@@ -62,6 +79,9 @@ class BufferD3D : public BufferImpl
StaticVertexBufferInterface *mStaticVertexBuffer;
StaticIndexBufferInterface *mStaticIndexBuffer;
+ std::vector<StaticVertexBufferInterface *> *mStaticBufferCache;
+ unsigned int mStaticBufferCacheTotalSize;
+ unsigned int mStaticVertexBufferOutOfDate;
unsigned int mUnmodifiedDataUse;
D3DBufferUsage mUsage;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
index 938703ac151..f40e6e6cab5 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
@@ -17,33 +17,81 @@
namespace rx
{
-DeviceD3D::DeviceD3D(rx::RendererD3D *renderer)
- : mRenderer(renderer)
+DeviceD3D::DeviceD3D()
+ : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false)
{
}
-egl::Error DeviceD3D::getDevice(EGLAttrib *value)
+DeviceD3D::~DeviceD3D()
{
- *value = reinterpret_cast<EGLAttrib>(mRenderer->getD3DDevice());
- if (*value == 0)
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
{
+ // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
+ ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice);
+ device->Release();
+ }
+#endif
+}
+
+egl::Error DeviceD3D::getDevice(void **outValue)
+{
+ if (!mIsInitialized)
+ {
+ *outValue = nullptr;
return egl::Error(EGL_BAD_DEVICE_EXT);
}
+
+ *outValue = mDevice;
return egl::Error(EGL_SUCCESS);
}
-EGLint DeviceD3D::getType()
+egl::Error DeviceD3D::initialize(void *device,
+ EGLint deviceType,
+ EGLBoolean deviceExternallySourced)
{
- switch (mRenderer->getRendererClass())
+ ASSERT(!mIsInitialized);
+ if (mIsInitialized)
{
- case RENDERER_D3D11:
- return EGL_D3D11_DEVICE_ANGLE;
- case RENDERER_D3D9:
- return EGL_D3D9_DEVICE_ANGLE;
- default:
- UNREACHABLE();
- return EGL_NONE;
+ return egl::Error(EGL_BAD_DEVICE_EXT);
}
+
+ mDevice = device;
+ mDeviceType = deviceType;
+ mDeviceExternallySourced = !!deviceExternallySourced;
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ // Validate the device
+ IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
+
+ ID3D11Device *d3dDevice = nullptr;
+ HRESULT hr =
+ iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
+ if (FAILED(hr))
+ {
+ return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT");
+ }
+
+ // The QI to ID3D11Device adds a ref to the D3D11 device.
+ // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the
+ // D3D11 device.
+ }
+ else
+#endif
+ {
+ ASSERT(!mDeviceExternallySourced);
+ }
+
+ mIsInitialized = true;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+EGLint DeviceD3D::getType()
+{
+ return mDeviceType;
}
void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
index 5f985463452..1dd99797085 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
@@ -18,14 +18,20 @@ namespace rx
class DeviceD3D : public DeviceImpl
{
public:
- DeviceD3D(RendererD3D *renderer);
+ DeviceD3D();
+ ~DeviceD3D() override;
- egl::Error getDevice(EGLAttrib *value) override;
+ egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external);
+ egl::Error getDevice(void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+ bool deviceExternallySourced() override { return mDeviceExternallySourced; }
private:
- RendererD3D *mRenderer;
+ void *mDevice;
+ EGLint mDeviceType;
+ bool mDeviceExternallySourced;
+ bool mIsInitialized;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
index 46d08a3d4d7..740bc761c65 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -55,10 +55,13 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
- const auto &attribMap = display->getAttributeMap();
- EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
+ if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ const auto &attribMap = display->getAttributeMap();
+ EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
- EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ EGLint requestedDisplayType =
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
# if defined(ANGLE_ENABLE_D3D11)
if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
@@ -77,27 +80,41 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
}
# endif
- if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
- nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
- requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
- {
+ if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
+ nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+ {
// The default display is requested, try the D3D9 and D3D11 renderers, order them using
// the definition of ANGLE_DEFAULT_D3D11
# if ANGLE_DEFAULT_D3D11
# if defined(ANGLE_ENABLE_D3D11)
- rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
# endif
# if defined(ANGLE_ENABLE_D3D9)
- rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
# endif
# else
# if defined(ANGLE_ENABLE_D3D9)
- rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
# endif
# if defined(ANGLE_ENABLE_D3D11)
- rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
# endif
# endif
+ }
+ }
+ else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+ {
+#if defined(ANGLE_ENABLE_D3D11)
+ if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+ }
+#endif
+ }
+ else
+ {
+ UNIMPLEMENTED();
}
egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
@@ -141,9 +158,7 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
return result;
}
-DisplayD3D::DisplayD3D()
- : mRenderer(nullptr),
- mDevice(nullptr)
+DisplayD3D::DisplayD3D() : mRenderer(nullptr)
{
}
@@ -157,6 +172,8 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration,
EGLint width = attribs.get(EGL_WIDTH, 0);
EGLint height = attribs.get(EGL_HEIGHT, 0);
EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE);
+ EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
+ EGLint directComposition = attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE);
if (!fixedSize)
{
@@ -164,8 +181,8 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration,
height = -1;
}
- return SurfaceD3D::createFromWindow(
- mRenderer, mDisplay, configuration, window, fixedSize, width, height);
+ return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize,
+ directComposition, width, height, orientation);
}
SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration,
@@ -209,9 +226,7 @@ ImageImpl *DisplayD3D::createImage(EGLenum target,
egl::Error DisplayD3D::getDevice(DeviceImpl **device)
{
- *device = reinterpret_cast<DeviceImpl*>(mDevice);
- ASSERT(*device != nullptr);
- return egl::Error(EGL_SUCCESS);
+ return mRenderer->getEGLDevice(device);
}
egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
@@ -222,8 +237,10 @@ egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Contex
EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT);
bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
+ bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
- *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
+ *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets,
+ robustAccess, debug);
return egl::Error(EGL_SUCCESS);
}
@@ -242,15 +259,11 @@ egl::Error DisplayD3D::initialize(egl::Display *display)
return error;
}
- ASSERT(mDevice == nullptr);
- mDevice = new DeviceD3D(mRenderer);
-
return egl::Error(EGL_SUCCESS);
}
void DisplayD3D::terminate()
{
- SafeDelete(mDevice);
SafeDelete(mRenderer);
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
index 973b77aa1a5..7ce78daea5b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -65,8 +65,6 @@ class DisplayD3D : public DisplayImpl
egl::Display *mDisplay;
rx::RendererD3D *mRenderer;
-
- DeviceImpl *mDevice;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 6e386f937c2..1d07b95c333 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -13,11 +13,10 @@
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
-
-// For use with ArrayString, see angleutils.h
-static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int.");
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
using namespace gl;
@@ -31,12 +30,17 @@ 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";
+ 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";
}
}
@@ -49,16 +53,27 @@ 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";
+ 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";
}
}
@@ -69,11 +84,13 @@ std::string HLSLTypeString(GLenum type)
return HLSLMatrixTypeString(type);
}
- return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type));
+ return HLSLComponentTypeString(gl::VariableComponentType(type),
+ gl::VariableComponentCount(type));
}
-const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables,
- unsigned int location)
+const PixelShaderOutputVariable *FindOutputAtLocation(
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ unsigned int location)
{
for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
{
@@ -83,329 +100,102 @@ const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelSha
}
}
- return NULL;
+ return nullptr;
}
-typedef const PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
-
-bool PackVarying(PackedVarying *packedVarying, const int maxVaryingVectors, VaryingPacking &packing)
+void WriteArrayString(std::stringstream &strstr, unsigned int i)
{
- // Make sure we use transposed matrix types to count registers correctly.
- int registers = 0;
- int elements = 0;
-
- const sh::Varying &varying = *packedVarying->varying;
-
- if (varying.isStruct())
- {
- registers = HLSLVariableRegisterCount(varying, true) * varying.elementCount();
- elements = 4;
- }
- else
- {
- GLenum transposedType = TransposeMatrixType(varying.type);
- registers = VariableRowCount(transposedType) * varying.elementCount();
- elements = 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)
- {
- packedVarying->registerIndex = r;
- packedVarying->columnIndex = 0;
-
- for (int y = 0; y < registers; y++)
- {
- for (int x = 0; x < elements; x++)
- {
- packing[r + y][x] = packedVarying;
- }
- }
-
- 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)
- {
- packedVarying->registerIndex = r;
- packedVarying->columnIndex = 2;
-
- for (int y = 0; y < registers; y++)
- {
- for (int x = 2; x < 4; x++)
- {
- packing[r + y][x] = packedVarying;
- }
- }
-
- return true;
- }
- }
- }
- }
- else if (elements == 1)
+ static_assert(GL_INVALID_INDEX == UINT_MAX,
+ "GL_INVALID_INDEX must be equal to the max unsigned int.");
+ if (i == UINT_MAX)
{
- 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])
- {
- packedVarying->registerIndex = r;
- packedVarying->columnIndex = column;
-
- for (int y = r; y < r + registers; y++)
- {
- packing[y][column] = packedVarying;
- }
-
- break;
- }
- }
-
- return true;
- }
+ return;
}
- else UNREACHABLE();
- return false;
+ strstr << "[";
+ strstr << i;
+ strstr << "]";
}
const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
-}
+} // anonymous namespace
-DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
+std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
{
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
}
-// 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,
- std::vector<PackedVarying> *packedVaryings,
- const std::vector<std::string> &transformFeedbackVaryings)
-{
- // TODO (geofflang): Use context's caps
- const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
-
- VaryingPacking packing = {};
-
- std::set<std::string> uniqueVaryingNames;
+// DynamicHLSL implementation
- for (PackedVarying &packedVarying : *packedVaryings)
- {
- const sh::Varying &varying = *packedVarying.varying;
-
- // Do not assign registers to built-in or unreferenced varyings
- if (varying.isBuiltIn() || !varying.staticUse)
- {
- continue;
- }
-
- ASSERT(uniqueVaryingNames.count(varying.name) == 0);
-
- if (PackVarying(&packedVarying, maxVaryingVectors, packing))
- {
- uniqueVaryingNames.insert(varying.name);
- }
- else
- {
- infoLog << "Could not pack varying " << varying.name;
- return -1;
- }
- }
-
- for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
- {
- if (transformFeedbackVaryingName == "gl_Position" ||
- transformFeedbackVaryingName == "gl_PointSize")
- {
- // do not pack builtin XFB varyings
- continue;
- }
-
- if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
- {
- bool found = false;
- for (PackedVarying &packedVarying : *packedVaryings)
- {
- const sh::Varying &varying = *packedVarying.varying;
- if (transformFeedbackVaryingName == varying.name)
- {
- if (!PackVarying(&packedVarying, maxVaryingVectors, packing))
- {
- infoLog << "Could not pack varying " << varying.name;
- return -1;
- }
-
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- infoLog << "Transform feedback varying " << transformFeedbackVaryingName
- << " does not exist in the vertex shader.";
- 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;
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
+{
}
-std::string DynamicHLSL::generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
- bool shaderUsesPointSize) const
+void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
+ std::stringstream &hlslStream) const
{
- std::string varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
- std::string varyingHLSL;
-
- for (const PackedVarying &packedVarying : varyings)
- {
- if (!packedVarying.registerAssigned())
- {
- continue;
- }
-
- const sh::Varying &varying = *packedVarying.varying;
-
- 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 +
- packedVarying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors +
- packedVarying.registerIndex + row;
- std::string n = Str(semanticIndex);
-
- std::string typeString;
-
- if (varying.isStruct())
- {
- // TODO(jmadill): pass back translated name from the shader translator
- typeString = decorateVariable(varying.structName);
- }
- else
- {
- GLenum componentType = VariableComponentType(transposedType);
- int columnCount = VariableColumnCount(transposedType);
- typeString = HLSLComponentTypeString(componentType, columnCount);
- }
- varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
- }
- }
+ std::string varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());
+
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &varying = *registerInfo.packedVarying->varying;
+ ASSERT(!varying.isStruct());
+
+ // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
+ // registers being used.
+ // For example, if there are N registers, and we have N vec3 varyings and 1 float
+ // varying, then D3D will pack them into N registers.
+ // If the float varying has the 'nointerpolation' modifier on it then we would need
+ // N + 1 registers, and D3D compilation will fail.
+
+ switch (registerInfo.packedVarying->interpolation)
+ {
+ case sh::INTERPOLATION_SMOOTH:
+ hlslStream << " ";
+ break;
+ case sh::INTERPOLATION_FLAT:
+ hlslStream << " nointerpolation ";
+ break;
+ case sh::INTERPOLATION_CENTROID:
+ hlslStream << " centroid ";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ GLenum componentType = gl::VariableComponentType(transposedType);
+ int columnCount = gl::VariableColumnCount(transposedType);
+ hlslStream << HLSLComponentTypeString(componentType, columnCount);
+ unsigned int semanticIndex = registerInfo.semanticIndex;
+ hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
}
-
- return varyingHLSL;
}
-std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader,
- const InputLayout &inputLayout,
- const std::vector<sh::Attribute> &shaderAttributes) const
+std::string DynamicHLSL::generateVertexShaderForInputLayout(
+ const std::string &sourceShader,
+ const InputLayout &inputLayout,
+ const std::vector<sh::Attribute> &shaderAttributes) const
{
- std::string structHLSL, initHLSL;
+ std::stringstream structStream;
+ std::stringstream initStream;
+
+ structStream << "struct VS_INPUT\n"
+ << "{\n";
- int semanticIndex = 0;
+ int semanticIndex = 0;
unsigned int inputIndex = 0;
// If gl_PointSize is used in the shader then pointsprites rendering is expected.
// If the renderer does not support Geometry shaders then Instanced PointSprite emulation
// must be used.
bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos;
- bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+ bool useInstancedPointSpriteEmulation =
+ usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
// Instanced PointSprite emulation requires additional entries in the
// VS_INPUT structure to support the vertices that make up the quad vertices.
@@ -417,8 +207,8 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
// before per instance data in the shader.
if (useInstancedPointSpriteEmulation)
{
- structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n";
- structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
+ structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n"
+ << " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
}
for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
@@ -434,7 +224,8 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
if (IsMatrixType(shaderAttribute.type))
{
// Matrix types are always transposed
- structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
+ structStream << " "
+ << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
}
else
{
@@ -442,31 +233,34 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
if (shaderAttribute.name == "gl_InstanceID")
{
- // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int).
- structHLSL += " uint";
+ // The input type of the instance ID in HLSL (uint) differs from the one in ESSL
+ // (int).
+ structStream << " uint";
}
else
{
- structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type));
+ structStream << " " << HLSLComponentTypeString(
+ componentType,
+ VariableComponentCount(shaderAttribute.type));
}
}
- structHLSL += " " + decorateVariable(shaderAttribute.name) + " : ";
+ structStream << " " << decorateVariable(shaderAttribute.name) << " : ";
if (shaderAttribute.name == "gl_InstanceID")
{
- structHLSL += "SV_InstanceID";
+ structStream << "SV_InstanceID";
}
else
{
- structHLSL += "TEXCOORD" + Str(semanticIndex);
+ structStream << "TEXCOORD" << semanticIndex;
semanticIndex += VariableRegisterCount(shaderAttribute.type);
}
- structHLSL += ";\n";
+ structStream << ";\n";
// HLSL code for initialization
- initHLSL += " " + decorateVariable(shaderAttribute.name) + " = ";
+ initStream << " " << decorateVariable(shaderAttribute.name) << " = ";
// Mismatched vertex attribute to vertex input may result in an undefined
// data reinterpretation (eg for pure integer->float, float->pure integer)
@@ -474,46 +268,48 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
if (IsMatrixType(shaderAttribute.type) ||
(mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0)
{
- initHLSL += generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
+ initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
}
else
{
- initHLSL += "input." + decorateVariable(shaderAttribute.name);
+ initStream << "input." << decorateVariable(shaderAttribute.name);
}
- initHLSL += ";\n";
+ initStream << ";\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";
+ structStream << "};\n"
+ "\n"
+ "void initAttributes(VS_INPUT input)\n"
+ "{\n"
+ << initStream.str() << "}\n";
std::string vertexHLSL(sourceShader);
size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
- vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL);
+ vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str());
return vertexHLSL;
}
-std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
- bool usesFragDepth, const std::vector<GLenum> &outputLayout) const
+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();
+ const int shaderModel = mRenderer->getMajorShaderModel();
std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
- std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
+ std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
- std::string declarationHLSL;
- std::string copyHLSL;
+ std::stringstream declarationStream;
+ std::stringstream copyStream;
+
+ declarationStream << "struct PS_OUTPUT\n"
+ "{\n";
for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex)
{
@@ -523,702 +319,576 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string
{
unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
- const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location);
+ const PixelShaderOutputVariable *outputVariable =
+ FindOutputAtLocation(outputVariables, location);
// OpenGL ES 3.0 spec $4.2.1
- // If [...] not all user-defined output variables are written, the values of fragment colors
+ // If [...] not all user-defined output variables are written, the values of fragment
+ // colors
// corresponding to unwritten variables are similarly undefined.
if (outputVariable)
{
- declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " +
- outputVariable->name + " : " + targetSemantic +
- Str(static_cast<int>(layoutIndex)) + ";\n";
+ declarationStream << " " + HLSLTypeString(outputVariable->type) << " "
+ << outputVariable->name << " : " << targetSemantic
+ << static_cast<int>(layoutIndex) << ";\n";
- copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n";
+ copyStream << " output." << outputVariable->name << " = "
+ << outputVariable->source << ";\n";
}
}
}
if (usesFragDepth)
{
- declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n";
- copyHLSL += " output.gl_Depth = gl_Depth; \n";
+ declarationStream << " float gl_Depth : " << depthSemantic << ";\n";
+ copyStream << " 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";
+ declarationStream << "};\n"
+ "\n"
+ "PS_OUTPUT generateOutput()\n"
+ "{\n"
+ " PS_OUTPUT output;\n"
+ << copyStream.str() << " return output;\n"
+ "}\n";
std::string pixelHLSL(sourceShader);
size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
- pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL);
+ pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(),
+ declarationStream.str());
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 position, 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");
- }
-
- if (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
+void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType,
+ const VaryingPacking &varyingPacking,
+ std::stringstream &linkStream) const
{
- std::string linkHLSL = "{\n";
-
- ASSERT(info.dxPosition.enabled);
- linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n";
-
- if (info.glPosition.enabled)
- {
- 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";
- }
+ const auto &builtins = varyingPacking.builtins(shaderType);
+ ASSERT(builtins.dxPosition.enabled);
+ linkStream << "{\n"
+ << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
- if (info.glPointSize.enabled)
+ if (builtins.glPosition.enabled)
{
- linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n";
+ linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
}
- // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register.
- linkHLSL += varyingHLSL;
-
- linkHLSL += "};\n";
-
- return linkHLSL;
-}
-
-void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info,
- std::vector<LinkedVarying> *linkedVaryings) const
-{
- if (info.glPosition.enabled)
+ if (builtins.glFragCoord.enabled)
{
- linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic,
- info.glPosition.index, 1));
+ linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
}
- if (info.glFragCoord.enabled)
+ if (builtins.glPointCoord.enabled)
{
- linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic,
- info.glFragCoord.index, 1));
+ linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
}
- if (info.glPointSize.enabled)
+ if (builtins.glPointSize.enabled)
{
- linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
+ linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
}
-}
-
-void DynamicHLSL::storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
- bool shaderUsesPointSize,
- std::vector<LinkedVarying> *linkedVaryings) const
-{
- const std::string &varyingSemantic = getVaryingSemantic(shaderUsesPointSize);
-
- for (const PackedVarying &packedVarying : packedVaryings)
- {
- if (packedVarying.registerAssigned())
- {
- const sh::Varying &varying = *packedVarying.varying;
- ASSERT(!varying.isBuiltIn());
- GLenum transposedType = TransposeMatrixType(varying.type);
- int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
+ // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the
+ // same register.
+ generateVaryingHLSL(varyingPacking, linkStream);
- linkedVaryings->push_back(
- LinkedVarying(varying.name, varying.type, varying.elementCount(), varyingSemantic,
- packedVarying.registerIndex, variableRows * varying.elementCount()));
- }
- }
+ linkStream << "};\n";
}
bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
- InfoLog &infoLog,
- int registers,
- std::string &pixelHLSL,
- std::string &vertexHLSL,
- const std::vector<PackedVarying> &packedVaryings,
- std::vector<LinkedVarying> *linkedVaryings,
- std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
- bool *outUsesFragDepth) const
+ const ProgramD3DMetadata &programMetadata,
+ const VaryingPacking &varyingPacking,
+ std::string *pixelHLSL,
+ std::string *vertexHLSL) const
{
- if (pixelHLSL.empty() || vertexHLSL.empty())
- {
- return false;
- }
+ ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader();
const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(vertexShaderGL);
const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
+ const int shaderModel = mRenderer->getMajorShaderModel();
- bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
- bool usesFragCoord = fragmentShader->mUsesFragCoord;
- bool usesPointCoord = fragmentShader->mUsesPointCoord;
- bool usesPointSize = vertexShader->mUsesPointSize;
- bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+ bool useInstancedPointSpriteEmulation =
+ programMetadata.usesPointSize() &&
+ mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
// Validation done in the compiler
- ASSERT(!fragmentShader->mUsesFragColor || !fragmentShader->mUsesFragData);
-
- // Write the HLSL input/output declarations
- const int shaderModel = mRenderer->getMajorShaderModel();
- 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 && data.clientVersion < 3);
- const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1);
-
- // gl_Position only needs to be outputted from the vertex shader if transform feedback is active.
- // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case.
- // This saves us 1 output vector.
- bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "");
-
- int shaderVersion = vertexShaderGL->getShaderVersion();
-
- if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors)
- {
- infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
- return false;
- }
+ ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
- const std::string &varyingHLSL = generateVaryingHLSL(packedVaryings, usesPointSize);
-
- // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT
- // structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
- // GeometryShader PointSprite emulation does not require this additional entry because the
- // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the PS_INPUT of the
- // generated pixel shader.
- // The Geometry Shader point sprite implementation needs gl_PointSize to be in VS_OUTPUT and GS_INPUT.
- // Instanced point sprites doesn't need gl_PointSize in VS_OUTPUT.
- const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS,
- usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord),
- (!useInstancedPointSpriteEmulation && usesPointSize), false);
-
- storeUserLinkedVaryings(packedVaryings, usesPointSize, linkedVaryings);
- storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
+ std::stringstream vertexStream;
+ vertexStream << vertexShaderGL->getTranslatedSource();
// Instanced PointSprite emulation requires additional entries originally generated in the
- // GeometryShader HLSL. These include pointsize clamp values.
+ // GeometryShader HLSL. These include pointsize clamp values.
if (useInstancedPointSpriteEmulation)
{
- vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n"
- "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n";
+ vertexStream << "static float minPointSize = "
+ << static_cast<int>(data.caps->minAliasedPointSize) << ".0f;\n"
+ << "static float maxPointSize = "
+ << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n";
}
// 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";
+ vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n";
+
+ // Write the HLSL input/output declarations
+ vertexStream << "struct VS_OUTPUT\n";
+ generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream);
+ vertexStream << "\n"
+ << "VS_OUTPUT main(VS_INPUT input)\n"
+ << "{\n"
+ << " initAttributes(input);\n";
if (vertexShader->usesDeferredInit())
{
- vertexHLSL += "\n"
- " initializeDeferredGlobals();\n";
+ vertexStream << "\n"
+ << " initializeDeferredGlobals();\n";
}
- vertexHLSL += "\n"
- " gl_main();\n"
- "\n"
- " VS_OUTPUT output;\n";
+ vertexStream << "\n"
+ << " gl_main();\n"
+ << "\n"
+ << " VS_OUTPUT output;\n";
+
+ const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX);
- if (outputPositionFromVS)
+ if (vertexBuiltins.glPosition.enabled)
{
- vertexHLSL += " output.gl_Position = gl_Position;\n";
+ vertexStream << " output.gl_Position = gl_Position;\n";
}
// On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
- if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
{
- vertexHLSL += " 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";
+ vertexStream << " 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 += " 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";
+ vertexStream << " 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";
}
// We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
- if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation)
+ if (vertexBuiltins.glPointSize.enabled)
{
- vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
+ vertexStream << " output.gl_PointSize = gl_PointSize;\n";
}
- if (usesFragCoord)
+ if (vertexBuiltins.glFragCoord.enabled)
{
- vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
+ vertexStream << " output.gl_FragCoord = gl_Position;\n";
}
- for (const PackedVarying &packedVarying : packedVaryings)
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{
- if (!packedVarying.registerAssigned())
- {
- continue;
- }
+ const auto &packedVarying = *registerInfo.packedVarying;
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isStruct());
- const sh::Varying &varying = *packedVarying.varying;
+ vertexStream << " output.v" << registerInfo.semanticIndex << " = ";
- for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
+ if (packedVarying.isStructField())
{
- int variableRows =
- (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type)));
-
- for (int row = 0; row < variableRows; row++)
- {
- int r = packedVarying.registerIndex +
- packedVarying.columnIndex * data.caps->maxVaryingVectors +
- elementIndex * variableRows + row;
- vertexHLSL += " output.v" + Str(r);
-
- vertexHLSL += " = _" + varying.name;
+ vertexStream << decorateVariable(packedVarying.parentStructName) << ".";
+ }
- if (varying.isArray())
- {
- vertexHLSL += ArrayString(elementIndex);
- }
+ vertexStream << decorateVariable(varying.name);
- if (variableRows > 1)
- {
- vertexHLSL += ArrayString(row);
- }
+ if (varying.isArray())
+ {
+ WriteArrayString(vertexStream, registerInfo.varyingArrayIndex);
+ }
- vertexHLSL += ";\n";
- }
+ if (VariableRowCount(varying.type) > 1)
+ {
+ WriteArrayString(vertexStream, registerInfo.varyingRowIndex);
}
+
+ vertexStream << ";\n";
}
// Instanced PointSprite emulation requires additional entries to calculate
// the final output vertex positions of the quad that represents each sprite.
if (useInstancedPointSpriteEmulation)
{
- vertexHLSL += "\n"
- " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"
- " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n";
+ vertexStream << "\n"
+ << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"
+ << " output.dx_Position.xyz += float3(input.spriteVertexPos.x * "
+ "gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * "
+ "gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * "
+ "output.dx_Position.w;\n";
- if (usesPointCoord)
+ if (programMetadata.usesPointCoord())
{
- vertexHLSL += "\n"
- " output.gl_PointCoord = input.spriteTexCoord;\n";
+ vertexStream << "\n"
+ << " output.gl_PointCoord = input.spriteTexCoord;\n";
}
}
- vertexHLSL += "\n"
- " return output;\n"
- "}\n";
-
- const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord,
- (!useInstancedPointSpriteEmulation && usesPointSize), true);
-
- pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n";
-
- if (shaderVersion < 300)
+ // Renderers that enable instanced pointsprite emulation require the vertex shader output member
+ // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
+ // default value used in the generated pixel shader.
+ if (programMetadata.usesInsertedPointCoordValue())
{
- 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;
+ ASSERT(!useInstancedPointSpriteEmulation);
+ vertexStream << "\n"
+ << " output.gl_PointCoord = float2(0.5, 0.5);\n";
}
- else
- {
- const auto &shaderOutputVars = fragmentShaderGL->getActiveOutputVariables();
-
- for (auto outputPair : programData.getOutputVariables())
- {
- const VariableLocation &outputLocation = outputPair.second;
- const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
- const std::string &variableName = "out_" + outputLocation.name;
- const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
- ASSERT(outputVariable.staticUse);
+ vertexStream << "\n"
+ << " return output;\n"
+ << "}\n";
- PixelShaderOutputVariable outputKeyVariable;
- outputKeyVariable.type = outputVariable.type;
- outputKeyVariable.name = variableName + elementString;
- outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
- outputKeyVariable.outputIndex = outputPair.first;
-
- outPixelShaderKey->push_back(outputKeyVariable);
- }
-
- *outUsesFragDepth = false;
- }
+ std::stringstream pixelStream;
+ pixelStream << fragmentShaderGL->getTranslatedSource();
+ pixelStream << "struct PS_INPUT\n";
+ generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream);
+ pixelStream << "\n";
- pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n";
+ pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n";
- if (fragmentShader->mUsesFrontFacing)
+ if (fragmentShader->usesFrontFacing())
{
if (shaderModel >= 4)
{
- pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
- "{\n";
+ pixelStream << "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";
+ pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
+ << "{\n";
}
}
else
{
- pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
- "{\n";
+ pixelStream << "PS_OUTPUT main(PS_INPUT input)\n"
+ << "{\n";
}
- if (usesFragCoord)
+ const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL);
+
+ if (pixelBuiltins.glFragCoord.enabled)
{
- pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
+ pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n";
// Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
- // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords.
+ // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
+ // dx_ViewCoords.
if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
{
- pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n"
- " gl_FragCoord.y = input.dx_Position.y;\n";
+ pixelStream << " 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";
+ pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
+ << " gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
}
else
{
- // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
- 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";
+ // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
+ // Renderer::setViewport()
+ pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
+ "dx_ViewCoords.z;\n"
+ << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
+ "dx_ViewCoords.w;\n";
}
- pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
- " gl_FragCoord.w = rhw;\n";
+ pixelStream << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
+ "dx_DepthFront.y;\n"
+ << " gl_FragCoord.w = rhw;\n";
}
- if (usesPointCoord && shaderModel >= 3)
+ if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
{
- pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
- pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+ pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n"
+ << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
}
- if (fragmentShader->mUsesFrontFacing)
+ if (fragmentShader->usesFrontFacing())
{
if (shaderModel <= 3)
{
- pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
+ pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
}
else
{
- pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
+ pixelStream << " gl_FrontFacing = isFrontFace;\n";
}
}
- for (const PackedVarying &packedVarying : packedVaryings)
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
{
- const sh::Varying &varying = *packedVarying.varying;
+ const auto &packedVarying = *registerInfo.packedVarying;
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isBuiltIn() && !varying.isStruct());
- if (!packedVarying.registerAssigned())
- {
- ASSERT(varying.isBuiltIn() || !varying.staticUse);
+ // Don't reference VS-only transform feedback varyings in the PS.
+ if (registerInfo.packedVarying->vertexOnly)
continue;
+
+ pixelStream << " ";
+
+ if (packedVarying.isStructField())
+ {
+ pixelStream << decorateVariable(packedVarying.parentStructName) << ".";
}
- // Don't reference VS-only transform feedback varyings in the PS.
- if (packedVarying.vertexOnly)
- continue;
+ pixelStream << decorateVariable(varying.name);
- ASSERT(!varying.isBuiltIn());
- for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++)
+ if (varying.isArray())
{
- GLenum transposedType = TransposeMatrixType(varying.type);
- int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
- for (int row = 0; row < variableRows; row++)
- {
- std::string n = Str(packedVarying.registerIndex +
- packedVarying.columnIndex * data.caps->maxVaryingVectors +
- elementIndex * variableRows + row);
- pixelHLSL += " _" + varying.name;
+ WriteArrayString(pixelStream, registerInfo.varyingArrayIndex);
+ }
- if (varying.isArray())
- {
- pixelHLSL += ArrayString(elementIndex);
- }
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ if (VariableRowCount(transposedType) > 1)
+ {
+ WriteArrayString(pixelStream, registerInfo.varyingRowIndex);
+ }
- if (variableRows > 1)
- {
- pixelHLSL += ArrayString(row);
- }
+ pixelStream << " = input.v" << registerInfo.semanticIndex;
- 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();
- }
- }
- }
+ switch (VariableColumnCount(transposedType))
+ {
+ case 1:
+ pixelStream << ".x";
+ break;
+ case 2:
+ pixelStream << ".xy";
+ break;
+ case 3:
+ pixelStream << ".xyz";
+ break;
+ case 4:
+ break;
+ default:
+ UNREACHABLE();
}
+ pixelStream << ";\n";
}
if (fragmentShader->usesDeferredInit())
{
- pixelHLSL += "\n"
- " initializeDeferredGlobals();\n";
+ pixelStream << "\n"
+ << " initializeDeferredGlobals();\n";
}
- pixelHLSL += "\n"
- " gl_main();\n"
- "\n"
- " return generateOutput();\n"
- "}\n";
+ pixelStream << "\n"
+ << " gl_main();\n"
+ << "\n"
+ << " return generateOutput();\n"
+ << "}\n";
+
+ *vertexHLSL = vertexStream.str();
+ *pixelHLSL = pixelStream.str();
return true;
}
-std::string DynamicHLSL::generateGeometryShaderHLSL(
- int registers,
- const ShaderD3D *fragmentShader,
- const std::vector<PackedVarying> &packedVaryings) const
+std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const
{
- // for now we only handle point sprite emulation
ASSERT(mRenderer->getMajorShaderModel() >= 4);
- return generatePointSpriteHLSL(registers, fragmentShader, packedVaryings);
+
+ std::stringstream preambleStream;
+
+ const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
+
+ preambleStream << "struct GS_INPUT\n";
+ generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream);
+ preambleStream << "\n"
+ << "struct GS_OUTPUT\n";
+ generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream);
+ preambleStream
+ << "\n"
+ << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
+ << "{\n"
+ << " output.gl_Position = input.gl_Position;\n";
+
+ if (builtins.glPointSize.enabled)
+ {
+ preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
+ }
+
+ for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
+ {
+ preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
+ if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
+ {
+ preambleStream << "flat";
+ }
+ preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
+ }
+
+ if (builtins.glFragCoord.enabled)
+ {
+ preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
+ }
+
+ // Only write the dx_Position if we aren't using point sprites
+ preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
+ << " output.dx_Position = input.dx_Position;\n"
+ << "#endif // ANGLE_POINT_SPRITE_SHADER\n"
+ << "}\n";
+
+ return preambleStream.str();
}
-std::string DynamicHLSL::generatePointSpriteHLSL(
- int registers,
- const ShaderD3D *fragmentShader,
- const std::vector<PackedVarying> &packedVaryings) const
+std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+ const gl::Data &data,
+ const gl::Program::Data &programData,
+ const std::string &preambleString) const
{
- ASSERT(registers >= 0);
ASSERT(mRenderer->getMajorShaderModel() >= 4);
- std::string geomHLSL;
-
- const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
- false, true, false);
- const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
- fragmentShader->mUsesPointCoord, true, false);
-
- // If we're generating the geometry shader, we assume the vertex shader uses point size.
- std::string varyingHLSL = generateVaryingHLSL(packedVaryings, true);
- 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(static_cast<int>(mRenderer->getRendererCaps().minAliasedPointSize)) + ".0f;\n"
- "static float maxPointSize = " + Str(static_cast<int>(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++)
+ std::stringstream shaderStream;
+
+ const bool pointSprites = (primitiveType == PRIMITIVE_POINTS);
+ const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
+
+ const char *inputPT = nullptr;
+ const char *outputPT = nullptr;
+ int inputSize = 0;
+ int maxVertexOutput = 0;
+
+ switch (primitiveType)
+ {
+ case PRIMITIVE_POINTS:
+ inputPT = "point";
+ outputPT = "Triangle";
+ inputSize = 1;
+ maxVertexOutput = 4;
+ break;
+
+ case PRIMITIVE_LINES:
+ case PRIMITIVE_LINE_STRIP:
+ case PRIMITIVE_LINE_LOOP:
+ inputPT = "line";
+ outputPT = "Line";
+ inputSize = 2;
+ maxVertexOutput = 2;
+ break;
+
+ case PRIMITIVE_TRIANGLES:
+ case PRIMITIVE_TRIANGLE_STRIP:
+ case PRIMITIVE_TRIANGLE_FAN:
+ inputPT = "triangle";
+ outputPT = "Triangle";
+ inputSize = 3;
+ maxVertexOutput = 3;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (pointSprites)
+ {
+ shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
+ "\n"
+ "uniform float4 dx_ViewCoords : register(c1);\n"
+ "\n"
+ "static float2 pointSpriteCorners[] = \n"
+ "{\n"
+ " float2( 0.5f, -0.5f),\n"
+ " float2( 0.5f, 0.5f),\n"
+ " float2(-0.5f, -0.5f),\n"
+ " float2(-0.5f, 0.5f)\n"
+ "};\n"
+ "\n"
+ "static float2 pointSpriteTexcoords[] = \n"
+ "{\n"
+ " float2(1.0f, 1.0f),\n"
+ " float2(1.0f, 0.0f),\n"
+ " float2(0.0f, 1.0f),\n"
+ " float2(0.0f, 0.0f)\n"
+ "};\n"
+ "\n"
+ "static float minPointSize = "
+ << static_cast<int>(data.caps->minAliasedPointSize)
+ << ".0f;\n"
+ "static float maxPointSize = "
+ << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n"
+ << "\n";
+ }
+
+ shaderStream << preambleString << "\n"
+ << "[maxvertexcount(" << maxVertexOutput << ")]\n"
+ << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
+
+ if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+ {
+ shaderStream << "uint primitiveID : SV_PrimitiveID, ";
+ }
+
+ shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
+ << "{\n"
+ << " GS_OUTPUT output = (GS_OUTPUT)0;\n";
+
+ if (primitiveType == PRIMITIVE_TRIANGLE_STRIP)
+ {
+ shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
+ }
+ else
{
- geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n";
+ shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n";
}
- if (fragmentShader->mUsesFragCoord)
+ for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
{
- geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
- }
+ shaderStream << " copyVertex(output, input[" << vertexIndex
+ << "], input[lastVertexIndex]);\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";
+ if (!pointSprites)
+ {
+ ASSERT(inputSize == maxVertexOutput);
+ shaderStream << " outStream.Append(output);\n";
+ }
+ }
- for (int corner = 0; corner < 4; corner++)
+ if (pointSprites)
{
- geomHLSL += " \n"
- " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+ shaderStream << "\n"
+ " float4 dx_Position = input[0].dx_Position;\n"
+ " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
+ "maxPointSize);\n"
+ " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
+ "dx_ViewCoords.y) * dx_Position.w;\n";
- if (fragmentShader->mUsesPointCoord)
+ for (int corner = 0; corner < 4; corner++)
{
- geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n";
- }
+ shaderStream << "\n"
+ " output.dx_Position = dx_Position + float4(pointSpriteCorners["
+ << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
- geomHLSL += " outStream.Append(output);\n";
+ if (usesPointCoord)
+ {
+ shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner
+ << "];\n";
+ }
+
+ shaderStream << " outStream.Append(output);\n";
+ }
}
- geomHLSL += " \n"
- " outStream.RestartStrip();\n"
- "}\n";
+ shaderStream << " \n"
+ " outStream.RestartStrip();\n"
+ "}\n";
- return geomHLSL;
+ return shaderStream.str();
}
// This method needs to match OutputHLSL::decorate
@@ -1232,11 +902,12 @@ std::string DynamicHLSL::decorateVariable(const std::string &name)
return name;
}
-std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
- const sh::ShaderVariable &shaderAttrib) const
+std::string DynamicHLSL::generateAttributeConversionHLSL(
+ gl::VertexFormatType vertexFormatType,
+ const sh::ShaderVariable &shaderAttrib) const
{
const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
- std::string attribString = "input." + decorateVariable(shaderAttrib.name);
+ std::string attribString = "input." + decorateVariable(shaderAttrib.name);
// Matrix
if (IsMatrixType(shaderAttrib.type))
@@ -1245,10 +916,11 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType ve
}
GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
- int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
+ int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
// Perform integer to float conversion (if necessary)
- bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
+ bool requiresTypeConversion =
+ (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
if (requiresTypeConversion)
{
@@ -1261,4 +933,57 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(gl::VertexFormatType ve
return attribString;
}
+void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
+ const gl::Program::Data &programData,
+ const ProgramD3DMetadata &metadata,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
+{
+ // Two cases when writing to gl_FragColor and using ESSL 1.0:
+ // - with a 3.0 context, the output color is copied to channel 0
+ // - with a 2.0 context, the output color is broadcast to all channels
+ bool broadcast = metadata.usesBroadcast(data);
+ const unsigned int numRenderTargets =
+ (broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1);
+
+ if (metadata.getMajorShaderVersion() < 300)
+ {
+ for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
+ renderTargetIndex++)
+ {
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = GL_FLOAT_VEC4;
+ outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
+ outputKeyVariable.source =
+ broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
+ outputKeyVariable.outputIndex = renderTargetIndex;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
+ else
+ {
+ const auto &shaderOutputVars =
+ metadata.getFragmentShader()->getData().getActiveOutputVariables();
+
+ for (auto outputPair : programData.getOutputVariables())
+ {
+ const VariableLocation &outputLocation = outputPair.second;
+ const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+ const std::string &variableName = "out_" + outputLocation.name;
+ const std::string &elementString =
+ (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
+
+ ASSERT(outputVariable.staticUse);
+
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = outputVariable.type;
+ outputKeyVariable.name = variableName + elementString;
+ outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
+ outputKeyVariable.outputIndex = outputPair.first;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 45290339207..df52d245cfc 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -17,6 +17,7 @@
#include "libANGLE/Constants.h"
#include "libANGLE/Program.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace sh
{
@@ -28,15 +29,16 @@ namespace gl
{
class InfoLog;
struct VariableLocation;
-struct LinkedVarying;
struct VertexAttribute;
struct Data;
}
namespace rx
{
-class RendererD3D;
+struct PackedVarying;
+class ProgramD3DMetadata;
class ShaderD3D;
+class VaryingPacking;
struct PixelShaderOutputVariable
{
@@ -46,75 +48,47 @@ struct PixelShaderOutputVariable
size_t outputIndex;
};
-struct PackedVarying
-{
- PackedVarying(const sh::Varying &varyingIn)
- : varying(&varyingIn), registerIndex(GL_INVALID_INDEX), columnIndex(0), vertexOnly(false)
- {
- }
-
- bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
-
- void resetRegisterAssignment() { registerIndex = GL_INVALID_INDEX; }
-
- const sh::Varying *varying;
-
- // Assigned during link
- unsigned int registerIndex;
-
- // Assigned during link, Defaults to 0
- unsigned int columnIndex;
-
- // Transform feedback varyings can be only referenced in the VS.
- bool vertexOnly;
-};
-
class DynamicHLSL : angle::NonCopyable
{
public:
explicit DynamicHLSL(RendererD3D *const renderer);
- int packVaryings(gl::InfoLog &infoLog,
- std::vector<PackedVarying> *packedVaryings,
- const std::vector<std::string> &transformFeedbackVaryings);
- std::string generateVertexShaderForInputLayout(const std::string &sourceShader,
- const gl::InputLayout &inputLayout,
- const std::vector<sh::Attribute> &shaderAttributes) const;
- std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
- bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
+ std::string generateVertexShaderForInputLayout(
+ const std::string &sourceShader,
+ const gl::InputLayout &inputLayout,
+ const std::vector<sh::Attribute> &shaderAttributes) const;
+ std::string generatePixelShaderForOutputSignature(
+ const std::string &sourceShader,
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ bool usesFragDepth,
+ const std::vector<GLenum> &outputLayout) const;
bool generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
- gl::InfoLog &infoLog,
- int registers,
- std::string &pixelHLSL,
- std::string &vertexHLSL,
- const std::vector<PackedVarying> &packedVaryings,
- std::vector<gl::LinkedVarying> *linkedVaryings,
- std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
- bool *outUsesFragDepth) const;
-
- std::string generateGeometryShaderHLSL(int registers,
- const ShaderD3D *fragmentShader,
- const std::vector<PackedVarying> &packedVaryings) const;
+ const ProgramD3DMetadata &programMetadata,
+ const VaryingPacking &varyingPacking,
+ std::string *pixelHLSL,
+ std::string *vertexHLSL) const;
+
+ std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
+
+ std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
+ const gl::Data &data,
+ const gl::Program::Data &programData,
+ const std::string &preambleString) const;
+
+ void getPixelShaderOutputKey(const gl::Data &data,
+ const gl::Program::Data &programData,
+ const ProgramD3DMetadata &metadata,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
private:
RendererD3D *const mRenderer;
- struct SemanticInfo;
-
- std::string getVaryingSemantic(bool pointSize) const;
- SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord,
- bool pointSize, bool pixelShader) const;
- std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
- std::string generateVaryingHLSL(const std::vector<PackedVarying> &varyings,
- bool shaderUsesPointSize) const;
- void storeUserLinkedVaryings(const std::vector<PackedVarying> &packedVaryings,
- bool shaderUsesPointSize,
- std::vector<gl::LinkedVarying> *linkedVaryings) const;
- void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
- std::string generatePointSpriteHLSL(int registers,
- const ShaderD3D *fragmentShader,
- const std::vector<PackedVarying> &packedVaryings) const;
+ void generateVaryingLinkHLSL(ShaderType shaderType,
+ const VaryingPacking &varyingPacking,
+ std::stringstream &linkStream) const;
+ void generateVaryingHLSL(const VaryingPacking &varyingPacking,
+ std::stringstream &hlslStream) const;
// Prepend an underscore
static std::string decorateVariable(const std::string &name);
@@ -123,6 +97,7 @@ class DynamicHLSL : angle::NonCopyable
const sh::ShaderVariable &shaderAttrib) const;
};
+std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize);
}
-#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
deleted file mode 100644
index ea7a331812d..00000000000
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/DynamicHLSL_unittest.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// DynamicHLSL unittests:
-// Tests for DynamicHLSL and related classes.
-//
-
-#include <gtest/gtest.h>
-
-#include "libANGLE/renderer/d3d/DynamicHLSL.h"
-
-using namespace rx;
-
-namespace
-{
-
-TEST(PackedVarying, DefaultInitialization)
-{
- sh::Varying defaultVarying;
- PackedVarying pv(defaultVarying);
-
- EXPECT_EQ(&defaultVarying, pv.varying);
- EXPECT_EQ(GL_INVALID_INDEX, pv.registerIndex);
- EXPECT_EQ(0, pv.columnIndex);
- EXPECT_FALSE(pv.vertexOnly);
-}
-
-} // anonymous namespace
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index b5cc1beeb35..5be3c16faf6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -125,13 +125,16 @@ gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
{
const gl::State &state = *data.state;
ClearParameters clearParams = GetClearParameters(state, mask);
- return clear(state, clearParams);
+ return clear(data, clearParams);
}
-gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
{
// glClearBufferfv can be called to clear the color buffer or depth buffer
- ClearParameters clearParams = GetClearParameters(state, 0);
+ ClearParameters clearParams = GetClearParameters(*data.state, 0);
if (buffer == GL_COLOR)
{
@@ -149,13 +152,16 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, G
clearParams.depthClearValue = values[0];
}
- return clear(state, clearParams);
+ return clear(data, clearParams);
}
-gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
+gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
{
// glClearBufferuiv can only be called to clear a color buffer
- ClearParameters clearParams = GetClearParameters(state, 0);
+ ClearParameters clearParams = GetClearParameters(*data.state, 0);
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
@@ -163,13 +169,16 @@ gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer,
clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
clearParams.colorClearType = GL_UNSIGNED_INT;
- return clear(state, clearParams);
+ return clear(data, clearParams);
}
-gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
+gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
{
// glClearBufferiv can be called to clear the color buffer or stencil buffer
- ClearParameters clearParams = GetClearParameters(state, 0);
+ ClearParameters clearParams = GetClearParameters(*data.state, 0);
if (buffer == GL_COLOR)
{
@@ -187,19 +196,23 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, G
clearParams.stencilClearValue = values[1];
}
- return clear(state, clearParams);
+ return clear(data, clearParams);
}
-gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
{
// glClearBufferfi can only be called to clear a depth stencil buffer
- ClearParameters clearParams = GetClearParameters(state, 0);
+ ClearParameters clearParams = GetClearParameters(*data.state, 0);
clearParams.clearDepth = true;
clearParams.depthClearValue = depth;
clearParams.clearStencil = true;
clearParams.stencilClearValue = stencil;
- return clear(state, clearParams);
+ return clear(data, clearParams);
}
GLenum FramebufferD3D::getImplementationColorReadFormat() const
@@ -250,17 +263,15 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle
{
const gl::PixelPackState &packState = state.getPackState();
- if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
- }
-
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
+ GLuint outputPitch =
+ sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
+ GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
+ outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
- return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
+ return readPixelsImpl(area, format, type, outputPitch, packState,
+ reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
}
gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
@@ -304,14 +315,14 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour
return gl::Error(GL_NO_ERROR);
}
-GLenum FramebufferD3D::checkStatus() const
+bool FramebufferD3D::checkStatus() const
{
// if we have both a depth and stencil buffer, they must refer to the same object
// since we only support packed_depth_stencil and not separate depth and stencil
if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
mData.getDepthStencilAttachment() == nullptr)
{
- return GL_FRAMEBUFFER_UNSUPPORTED;
+ return false;
}
// D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
@@ -328,13 +339,19 @@ GLenum FramebufferD3D::checkStatus() const
(attachment.id() == prevAttachment.id() &&
attachment.type() == prevAttachment.type()))
{
- return GL_FRAMEBUFFER_UNSUPPORTED;
+ return false;
}
}
}
}
- return GL_FRAMEBUFFER_COMPLETE;
+ // D3D requires all render targets to have the same dimensions.
+ if (!mData.attachmentsHaveSameDimensions())
+ {
+ return false;
+ }
+
+ return true;
}
const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
index 42f76ff3a3d..6b98cee7e7e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -67,10 +67,23 @@ class FramebufferD3D : public FramebufferImpl
void setReadBuffer(GLenum buffer) override;
gl::Error clear(const gl::Data &data, GLbitfield mask) override;
- gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
- gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
- gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override;
- gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
+ gl::Error clearBufferfv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
GLenum getImplementationColorReadFormat() const override;
GLenum getImplementationColorReadType() const override;
@@ -79,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl
gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
- GLenum checkStatus() const override;
+ bool checkStatus() const override;
const gl::AttachmentList &getColorAttachmentsForRender(const WorkaroundsD3D &workarounds) const;
@@ -89,10 +102,14 @@ class FramebufferD3D : public FramebufferImpl
mutable bool mInvalidateColorAttachmentCache;
private:
- virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0;
-
- virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
- const gl::PixelPackState &pack, uint8_t *pixels) const = 0;
+ virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0;
+
+ virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const = 0;
virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
index 7559b94b6ac..e8b1af31291 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -12,12 +12,9 @@
#include "libANGLE/histogram_macros.h"
#include "third_party/trace_event/trace_event.h"
-// Definitions local to the translation unit
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
namespace
{
-
-#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
-
#ifdef CREATE_COMPILER_FLAG_INFO
#undef CREATE_COMPILER_FLAG_INFO
#endif
@@ -78,10 +75,8 @@ bool IsCompilerFlagSet(UINT mask, UINT flag)
return isFlagSet;
}
}
-
-#endif
-
-}
+} // anonymous namespace
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
namespace rx
{
@@ -247,8 +242,9 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
{
*outCompiledBlob = binary;
-#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
(*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n";
+
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
(*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n";
(*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n";
for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx)
@@ -279,7 +275,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
return error;
}
(*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
-#endif
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
return gl::Error(GL_NO_ERROR);
}
@@ -289,7 +285,8 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
}
- infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags.";
+ infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. ("
+ << profile << ")";
if (i + 1 < configs.size())
{
@@ -332,4 +329,4 @@ gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *d
return gl::Error(GL_NO_ERROR);
}
-}
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
index 19cdbec7249..c18ffe1639b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -18,57 +18,82 @@
namespace rx
{
-static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input,
- GLsizei count, void *output)
+namespace
{
- if (sourceType == GL_UNSIGNED_BYTE)
- {
- ASSERT(destinationType == GL_UNSIGNED_SHORT);
- const GLubyte *in = static_cast<const GLubyte*>(input);
- GLushort *out = static_cast<GLushort*>(output);
+template <typename InputT, typename DestT>
+void ConvertIndexArray(const void *input,
+ GLenum sourceType,
+ void *output,
+ GLenum destinationType,
+ GLsizei count,
+ bool usePrimitiveRestartFixedIndex)
+{
+ const InputT *in = static_cast<const InputT *>(input);
+ DestT *out = static_cast<DestT *>(output);
+
+ if (usePrimitiveRestartFixedIndex)
+ {
+ InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType));
+ DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType));
for (GLsizei i = 0; i < count; i++)
{
- out[i] = in[i];
+ out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(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)
+ else
{
- if (destinationType == GL_UNSIGNED_SHORT)
+ for (GLsizei i = 0; i < count; i++)
{
- memcpy(output, input, count * sizeof(GLushort));
+ out[i] = static_cast<DestT>(in[i]);
}
- 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();
+void ConvertIndices(GLenum sourceType,
+ GLenum destinationType,
+ const void *input,
+ GLsizei count,
+ void *output,
+ bool usePrimitiveRestartFixedIndex)
+{
+ if (sourceType == destinationType)
+ {
+ const gl::Type &typeInfo = gl::GetTypeInfo(destinationType);
+ memcpy(output, input, count * typeInfo.bytes);
+ return;
+ }
+
+ if (sourceType == GL_UNSIGNED_BYTE)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_SHORT);
+ ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
+ }
+ else if (sourceType == GL_UNSIGNED_SHORT)
+ {
+ ASSERT(destinationType == GL_UNSIGNED_INT);
+ ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
}
else UNREACHABLE();
}
-static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid *data,
- unsigned int count, GLenum srcType, GLenum dstType,
- unsigned int *offset)
+gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
+ const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ unsigned int *offset)
{
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift))
{
return gl::Error(GL_OUT_OF_MEMORY,
- "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
- count, dstTypeInfo.bytes);
+ "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
+ count, dstTypeInfo.bytes);
}
unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift;
@@ -85,7 +110,7 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid
return error;
}
- ConvertIndices(srcType, dstType, data, count, output);
+ ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
error = buffer->unmapBuffer();
if (error.isError())
@@ -96,6 +121,8 @@ static gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, const GLvoid
return gl::Error(GL_NO_ERROR);
}
+} // anonymous namespace
+
IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
: mFactory(factory),
mRendererClass(rendererClass),
@@ -118,9 +145,13 @@ IndexDataManager::~IndexDataManager()
// When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
// we will start by falling back to streaming, and after a while will start using a static translated
// copy of the index buffer.
-gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer,
- const GLvoid *indices, TranslatedIndexData *translated,
- SourceIndexData *sourceData)
+gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const GLvoid *indices,
+ TranslatedIndexData *translated,
+ SourceIndexData *sourceData,
+ bool primitiveRestartFixedIndexEnabled)
{
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
@@ -128,8 +159,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 &&
+ !primitiveRestartFixedIndexEnabled &&
hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT;
+ // We should never have to deal with MAX_UINT indices, since we restrict it via
+ // MAX_ELEMENT_INDEX.
+ ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
+ hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT));
+
const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ?
GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
@@ -151,7 +188,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
if (glBuffer == nullptr)
{
translated->storage = nullptr;
- return streamIndexData(indices, count, srcType, dstType, translated);
+ return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled,
+ translated);
}
// Case 2: the indices are already in a buffer
@@ -193,7 +231,7 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
if (staticBufferInitialized && !staticBufferUsable)
{
- buffer->invalidateStaticData();
+ buffer->invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
staticBuffer = nullptr;
}
@@ -207,7 +245,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
}
ASSERT(bufferData != nullptr);
- error = streamIndexData(bufferData + offset, count, srcType, dstType, translated);
+ error = streamIndexData(bufferData + offset, count, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, translated);
if (error.isError())
{
return error;
@@ -227,8 +266,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
unsigned int convertCount =
static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift;
- error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount,
- srcType, dstType, nullptr);
+ error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, nullptr);
if (error.isError())
{
return error;
@@ -245,8 +284,12 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
return gl::Error(GL_NO_ERROR);
}
-gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType,
- GLenum dstType, TranslatedIndexData *translated)
+gl::Error IndexDataManager::streamIndexData(const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated)
{
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
@@ -259,7 +302,8 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data, unsigned int cou
ASSERT(indexBuffer != nullptr);
unsigned int offset;
- StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, &offset);
+ StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex,
+ &offset);
translated->indexBuffer = indexBuffer->getIndexBuffer();
translated->serial = indexBuffer->getSerial();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
index cd9c8b7110f..c3741cfe3fc 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -63,13 +63,21 @@ class IndexDataManager : angle::NonCopyable
explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
virtual ~IndexDataManager();
- gl::Error prepareIndexData(GLenum srcType, GLsizei count, gl::Buffer *glBuffer,
- const GLvoid *indices, TranslatedIndexData *translated,
- SourceIndexData *sourceData);
+ gl::Error prepareIndexData(GLenum srcType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const GLvoid *indices,
+ TranslatedIndexData *translated,
+ SourceIndexData *sourceData,
+ bool primitiveRestartFixedIndexEnabled);
private:
- gl::Error streamIndexData(const GLvoid *data, unsigned int count, GLenum srcType,
- GLenum dstType, TranslatedIndexData *translated);
+ gl::Error streamIndexData(const GLvoid *data,
+ unsigned int count,
+ GLenum srcType,
+ GLenum dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated);
gl::Error getStreamingIndexBuffer(GLenum destinationIndexType,
IndexBufferInterface **outBuffer);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 0a182ae9543..7f44d585a30 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -20,6 +20,7 @@
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
namespace rx
@@ -38,14 +39,13 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
for (size_t rowIndex = 0;
- static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType);
- ++rowIndex)
+ static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
{
GLenum componentType = gl::VariableComponentType(transposedType);
- GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
+ GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
bool pureInt = (componentType != GL_FLOAT);
- gl::VertexFormatType defaultType = gl::GetVertexFormatType(
- componentType, GL_FALSE, components, pureInt);
+ gl::VertexFormatType defaultType =
+ gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
defaultLayout.push_back(defaultType);
}
@@ -55,7 +55,8 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
return defaultLayout;
}
-std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+std::vector<GLenum> GetDefaultOutputLayoutFromShader(
+ const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
{
std::vector<GLenum> defaultPixelOutput;
@@ -90,14 +91,22 @@ struct AttributeSorter
int indexA = (*originalIndices)[a];
int indexB = (*originalIndices)[b];
- if (indexA == -1) return false;
- if (indexB == -1) return true;
+ if (indexA == -1)
+ return false;
+ if (indexB == -1)
+ return true;
return (indexA < indexB);
}
const ProgramD3D::SemanticIndexArray *originalIndices;
};
+// true if varying x has a higher priority in packing than y
+bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
+{
+ return gl::CompareShaderVar(*x.varying, *y.varying);
+}
+
std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
const gl::Shader &fragmentShader,
const std::vector<std::string> &tfVaryings)
@@ -118,7 +127,20 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
{
if (output.name == input.name)
{
- packedVaryings.push_back(PackedVarying(input));
+ if (output.isStruct())
+ {
+ ASSERT(!output.isArray());
+ for (const auto &field : output.fields)
+ {
+ ASSERT(!field.isStruct() && !field.isArray());
+ packedVaryings.push_back(
+ PackedVarying(field, input.interpolation, input.name));
+ }
+ }
+ else
+ {
+ packedVaryings.push_back(PackedVarying(input, input.interpolation));
+ }
packed = true;
break;
}
@@ -131,14 +153,22 @@ std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
{
if (tfVarying == output.name)
{
- packedVaryings.push_back(PackedVarying(output));
- packedVaryings.back().vertexOnly = true;
+ // Transform feedback for varying structs is underspecified.
+ // See Khronos bug 9856.
+ // TODO(jmadill): Figure out how to be spec-compliant here.
+ if (!output.isStruct())
+ {
+ packedVaryings.push_back(PackedVarying(output, output.interpolation));
+ packedVaryings.back().vertexOnly = true;
+ }
break;
}
}
}
}
+ std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
+
return packedVaryings;
}
@@ -178,8 +208,129 @@ void GetUniformBlockInfo(const std::vector<VarT> &fields,
}
}
+template <typename T>
+static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
+{
+ ASSERT(dest != NULL);
+ ASSERT(dirtyFlag != NULL);
+
+ *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
+ *dest = source;
+}
+
+template <typename T>
+bool TransposeMatrix(T *target,
+ const GLfloat *value,
+ int targetWidth,
+ int targetHeight,
+ int srcWidth,
+ int srcHeight)
+{
+ bool dirty = false;
+ int copyWidth = std::min(targetHeight, srcWidth);
+ int copyHeight = std::min(targetWidth, srcHeight);
+
+ for (int x = 0; x < copyWidth; x++)
+ {
+ for (int y = 0; y < copyHeight; y++)
+ {
+ SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
+ &dirty);
+ }
+ }
+ // clear unfilled right side
+ for (int y = 0; y < copyWidth; y++)
+ {
+ for (int x = copyHeight; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+ // clear unfilled bottom.
+ for (int y = copyWidth; y < targetHeight; y++)
+ {
+ for (int x = 0; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+
+ return dirty;
+}
+
+template <typename T>
+bool ExpandMatrix(T *target,
+ const GLfloat *value,
+ int targetWidth,
+ int targetHeight,
+ int srcWidth,
+ int srcHeight)
+{
+ bool dirty = false;
+ int copyWidth = std::min(targetWidth, srcWidth);
+ int copyHeight = std::min(targetHeight, srcHeight);
+
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = 0; x < copyWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
+ &dirty);
+ }
+ }
+ // clear unfilled right side
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = copyWidth; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+ // clear unfilled bottom.
+ for (int y = copyHeight; y < targetHeight; y++)
+ {
+ for (int x = 0; x < targetWidth; x++)
+ {
+ SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ }
+ }
+
+ return dirty;
+}
+
+gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
+{
+ switch (drawMode)
+ {
+ // Uses the point sprite geometry shader.
+ case GL_POINTS:
+ return gl::PRIMITIVE_POINTS;
+
+ // All line drawing uses the same geometry shader.
+ case GL_LINES:
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ return gl::PRIMITIVE_LINES;
+
+ // The triangle fan primitive is emulated with strips in D3D11.
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ return gl::PRIMITIVE_TRIANGLES;
+
+ // Special case for triangle strips.
+ case GL_TRIANGLE_STRIP:
+ return gl::PRIMITIVE_TRIANGLE_STRIP;
+
+ default:
+ UNREACHABLE();
+ return gl::PRIMITIVE_TYPE_MAX;
+ }
+}
+
} // anonymous namespace
+// D3DUniform Implementation
+
D3DUniform::D3DUniform(GLenum typeIn,
const std::string &nameIn,
unsigned int arraySizeIn,
@@ -228,12 +379,120 @@ bool D3DUniform::isReferencedByFragmentShader() const
return psRegisterIndex != GL_INVALID_INDEX;
}
+// D3DVarying Implementation
+
+D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
+{
+}
+
+D3DVarying::D3DVarying(const std::string &semanticNameIn,
+ unsigned int semanticIndexIn,
+ unsigned int componentCountIn,
+ unsigned int outputSlotIn)
+ : semanticName(semanticNameIn),
+ semanticIndex(semanticIndexIn),
+ componentCount(componentCountIn),
+ outputSlot(outputSlotIn)
+{
+}
+
+// ProgramD3DMetadata Implementation
+
+ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel,
+ const std::string &shaderModelSuffix,
+ bool usesInstancedPointSpriteEmulation,
+ const ShaderD3D *vertexShader,
+ const ShaderD3D *fragmentShader)
+ : mRendererMajorShaderModel(rendererMajorShaderModel),
+ mShaderModelSuffix(shaderModelSuffix),
+ mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation),
+ mVertexShader(vertexShader),
+ mFragmentShader(fragmentShader)
+{
+}
+
+int ProgramD3DMetadata::getRendererMajorShaderModel() const
+{
+ return mRendererMajorShaderModel;
+}
+
+bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const
+{
+ return (mFragmentShader->usesFragColor() && data.clientVersion < 3);
+}
+
+bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const
+{
+ return mFragmentShader->usesFragDepth();
+}
+
+bool ProgramD3DMetadata::usesPointCoord() const
+{
+ return mFragmentShader->usesPointCoord();
+}
+
+bool ProgramD3DMetadata::usesFragCoord() const
+{
+ return mFragmentShader->usesFragCoord();
+}
+
+bool ProgramD3DMetadata::usesPointSize() const
+{
+ return mVertexShader->usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
+{
+ return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4;
+}
+
+bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
+{
+ // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader
+ // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
+ // GeometryShader PointSprite emulation does not require this additional entry because the
+ // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the
+ // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs
+ // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
+ // gl_PointSize in VS_OUTPUT.
+ return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
+ usesInsertedPointCoordValue();
+}
+
+bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
+{
+ // gl_Position only needs to be outputted from the vertex shader if transform feedback is
+ // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
+ // the vertex shader in this case. This saves us 1 output vector.
+ return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
+}
+
+bool ProgramD3DMetadata::usesSystemValuePointSize() const
+{
+ return !mUsesInstancedPointSpriteEmulation && usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
+{
+ return mFragmentShader->usesMultipleRenderTargets();
+}
+
+GLint ProgramD3DMetadata::getMajorShaderVersion() const
+{
+ return mVertexShader->getData().getShaderVersion();
+}
+
+const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
+{
+ return mFragmentShader;
+}
+
+// ProgramD3D Implementation
+
ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
const Signature &signature,
ShaderExecutableD3D *shaderExecutable)
- : mInputs(inputLayout),
- mSignature(signature),
- mShaderExecutable(shaderExecutable)
+ : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
{
}
@@ -281,8 +540,7 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature)
ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
ShaderExecutableD3D *shaderExecutable)
- : mOutputSignature(outputSignature),
- mShaderExecutable(shaderExecutable)
+ : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
{
}
@@ -301,8 +559,9 @@ ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
: ProgramImpl(data),
mRenderer(renderer),
mDynamicHLSL(NULL),
- mGeometryExecutable(NULL),
+ mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
mUsesPointSize(false),
+ mUsesFlatInterpolation(false),
mVertexUniformStorage(NULL),
mFragmentUniformStorage(NULL),
mUsedVertexSamplerRange(0),
@@ -324,8 +583,13 @@ bool ProgramD3D::usesPointSpriteEmulation() const
return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
}
-bool ProgramD3D::usesGeometryShader() const
+bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
{
+ if (drawMode != GL_POINTS)
+ {
+ return mUsesFlatInterpolation;
+ }
+
return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
}
@@ -334,30 +598,34 @@ bool ProgramD3D::usesInstancedPointSpriteEmulation() const
return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
}
-GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
+GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const
{
GLint logicalTextureUnit = -1;
switch (type)
{
- case gl::SAMPLER_PIXEL:
- ASSERT(samplerIndex < caps.maxTextureImageUnits);
- if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
- {
- logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
- }
- break;
- case gl::SAMPLER_VERTEX:
- ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
- if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
- {
- logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
- }
- break;
- default: UNREACHABLE();
+ case gl::SAMPLER_PIXEL:
+ ASSERT(samplerIndex < caps.maxTextureImageUnits);
+ if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ case gl::SAMPLER_VERTEX:
+ ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+ if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ default:
+ UNREACHABLE();
}
- if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
+ if (logicalTextureUnit >= 0 &&
+ logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
{
return logicalTextureUnit;
}
@@ -371,15 +639,16 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp
{
switch (type)
{
- case gl::SAMPLER_PIXEL:
- ASSERT(samplerIndex < mSamplersPS.size());
- ASSERT(mSamplersPS[samplerIndex].active);
- return mSamplersPS[samplerIndex].textureType;
- case gl::SAMPLER_VERTEX:
- ASSERT(samplerIndex < mSamplersVS.size());
- ASSERT(mSamplersVS[samplerIndex].active);
- return mSamplersVS[samplerIndex].textureType;
- default: UNREACHABLE();
+ case gl::SAMPLER_PIXEL:
+ ASSERT(samplerIndex < mSamplersPS.size());
+ ASSERT(mSamplersPS[samplerIndex].active);
+ return mSamplersPS[samplerIndex].textureType;
+ case gl::SAMPLER_VERTEX:
+ ASSERT(samplerIndex < mSamplersVS.size());
+ ASSERT(mSamplersVS[samplerIndex].active);
+ return mSamplersVS[samplerIndex].textureType;
+ default:
+ UNREACHABLE();
}
return GL_TEXTURE_2D;
@@ -389,13 +658,13 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
{
switch (type)
{
- case gl::SAMPLER_PIXEL:
- return mUsedPixelSamplerRange;
- case gl::SAMPLER_VERTEX:
- return mUsedVertexSamplerRange;
- default:
- UNREACHABLE();
- return 0;
+ case gl::SAMPLER_PIXEL:
+ return mUsedPixelSamplerRange;
+ case gl::SAMPLER_VERTEX:
+ return mUsedVertexSamplerRange;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
@@ -458,8 +727,9 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
{
reset();
- DeviceIdentifier binaryDeviceIdentifier = { 0 };
- stream->readBytes(reinterpret_cast<unsigned char*>(&binaryDeviceIdentifier), sizeof(DeviceIdentifier));
+ DeviceIdentifier binaryDeviceIdentifier = {0};
+ stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
+ sizeof(DeviceIdentifier));
DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
@@ -527,30 +797,48 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
mD3DUniforms.push_back(d3dUniform);
}
- const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
- mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
- for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
+ const unsigned int blockCount = stream->readInt<unsigned int>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
+ }
+
+ ASSERT(mD3DUniformBlocks.empty());
+ for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ D3DUniformBlock uniformBlock;
+ stream->readInt(&uniformBlock.psRegisterIndex);
+ stream->readInt(&uniformBlock.vsRegisterIndex);
+ mD3DUniformBlocks.push_back(uniformBlock);
+ }
+
+ const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
+ mStreamOutVaryings.resize(streamOutVaryingCount);
+ for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
{
- gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
+ D3DVarying *varying = &mStreamOutVaryings[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);
+ stream->readString(&varying->semanticName);
+ stream->readInt(&varying->semanticIndex);
+ stream->readInt(&varying->componentCount);
+ stream->readInt(&varying->outputSlot);
}
stream->readString(&mVertexHLSL);
- stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
+ stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
stream->readString(&mPixelHLSL);
- stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
+ stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
stream->readBool(&mUsesFragDepth);
stream->readBool(&mUsesPointSize);
+ stream->readBool(&mUsesFlatInterpolation);
const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
mPixelShaderKey.resize(pixelShaderKeySize);
- for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
+ for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
+ pixelShaderKeyIndex++)
{
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
@@ -558,10 +846,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
}
- const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
+ stream->readString(&mGeometryShaderPreamble);
+
+ const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
- for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+ for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
+ vertexShaderIndex++)
{
size_t inputLayoutSize = stream->readInt<size_t>();
gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
@@ -571,13 +862,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
}
- unsigned int vertexShaderSize = stream->readInt<unsigned int>();
+ unsigned int vertexShaderSize = stream->readInt<unsigned int>();
const unsigned char *vertexShaderFunction = binary + stream->offset();
ShaderExecutableD3D *shaderExecutable = nullptr;
gl::Error error = mRenderer->loadExecutable(
- vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
+ vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
if (error.isError())
{
@@ -595,7 +886,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
// add new binary
- mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
+ mVertexExecutables.push_back(
+ new VertexExecutable(inputLayout, signature, shaderExecutable));
stream->skip(vertexShaderSize);
}
@@ -610,12 +902,12 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->readInt(&outputs[outputIndex]);
}
- const size_t pixelShaderSize = stream->readInt<unsigned int>();
+ const size_t pixelShaderSize = stream->readInt<unsigned int>();
const unsigned char *pixelShaderFunction = binary + stream->offset();
ShaderExecutableD3D *shaderExecutable = nullptr;
gl::Error error = mRenderer->loadExecutable(
- pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
+ pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
if (error.isError())
{
@@ -634,21 +926,28 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->skip(pixelShaderSize);
}
- unsigned int geometryShaderSize = stream->readInt<unsigned int>();
-
- if (geometryShaderSize > 0)
+ for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
+ ++geometryExeIndex)
{
+ unsigned int geometryShaderSize = stream->readInt<unsigned int>();
+ if (geometryShaderSize == 0)
+ {
+ mGeometryExecutables[geometryExeIndex] = nullptr;
+ continue;
+ }
+
const unsigned char *geometryShaderFunction = binary + stream->offset();
- gl::Error error = mRenderer->loadExecutable(
- geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
- mTransformFeedbackLinkedVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
+ bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
+
+ gl::Error error = mRenderer->loadExecutable(
+ geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings,
+ splitAttribs, &mGeometryExecutables[geometryExeIndex]);
if (error.isError())
{
return LinkResult(false, error);
}
- if (!mGeometryExecutable)
+ if (!mGeometryExecutables[geometryExeIndex])
{
infoLog << "Could not create geometry shader.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
@@ -665,9 +964,11 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
{
// Output the DeviceIdentifier before we output any shader code
- // When we load the binary again later, we can validate the device identifier before trying to compile any HLSL
+ // When we load the binary again later, we can validate the device identifier before trying to
+ // compile any HLSL
DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
- stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(DeviceIdentifier));
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
+ sizeof(DeviceIdentifier));
stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
@@ -697,40 +998,45 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(mUsedPixelSamplerRange);
stream->writeInt(mD3DUniforms.size());
- for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
+ for (const D3DUniform *uniform : mD3DUniforms)
{
- const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
-
// Type, name and arraySize are redundant, so aren't stored in the binary.
- stream->writeInt(uniform.psRegisterIndex);
- stream->writeInt(uniform.vsRegisterIndex);
- stream->writeInt(uniform.registerCount);
- stream->writeInt(uniform.registerElement);
+ stream->writeInt(uniform->psRegisterIndex);
+ stream->writeInt(uniform->vsRegisterIndex);
+ stream->writeInt(uniform->registerCount);
+ stream->writeInt(uniform->registerElement);
}
- stream->writeInt(mTransformFeedbackLinkedVaryings.size());
- for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
+ stream->writeInt(mD3DUniformBlocks.size());
+ for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
{
- const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
+ stream->writeInt(uniformBlock.psRegisterIndex);
+ stream->writeInt(uniformBlock.vsRegisterIndex);
+ }
- stream->writeString(varying.name);
- stream->writeInt(varying.type);
- stream->writeInt(varying.size);
+ stream->writeInt(mStreamOutVaryings.size());
+ for (const auto &varying : mStreamOutVaryings)
+ {
stream->writeString(varying.semanticName);
stream->writeInt(varying.semanticIndex);
- stream->writeInt(varying.semanticIndexCount);
+ stream->writeInt(varying.componentCount);
+ stream->writeInt(varying.outputSlot);
}
stream->writeString(mVertexHLSL);
- stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
stream->writeString(mPixelHLSL);
- stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
+ sizeof(D3DCompilerWorkarounds));
stream->writeInt(mUsesFragDepth);
stream->writeInt(mUsesPointSize);
+ stream->writeInt(mUsesFlatInterpolation);
const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
stream->writeInt(pixelShaderKey.size());
- for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
+ for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
+ pixelShaderKeyIndex++)
{
const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
stream->writeInt(variable.type);
@@ -739,8 +1045,11 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(variable.outputIndex);
}
+ stream->writeString(mGeometryShaderPreamble);
+
stream->writeInt(mVertexExecutables.size());
- for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
+ for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
+ vertexExecutableIndex++)
{
VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
@@ -760,7 +1069,8 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
}
stream->writeInt(mPixelExecutables.size());
- for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
+ for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
+ pixelExecutableIndex++)
{
PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
@@ -778,24 +1088,34 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeBytes(pixelBlob, pixelShaderSize);
}
- size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
- stream->writeInt(geometryShaderSize);
-
- if (mGeometryExecutable != NULL && geometryShaderSize > 0)
+ for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
{
- const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
- stream->writeBytes(geometryBlob, geometryShaderSize);
+ if (geometryExe == nullptr)
+ {
+ stream->writeInt(0);
+ continue;
+ }
+
+ size_t geometryShaderSize = geometryExe->getLength();
+ stream->writeInt(geometryShaderSize);
+ stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
}
return gl::Error(GL_NO_ERROR);
}
-gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
+void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
+{
+}
+
+gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+ ShaderExecutableD3D **outExecutable)
{
mPixelShaderOutputFormatCache.clear();
const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
- const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
+ const gl::AttachmentList &colorbuffers =
+ fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
@@ -803,7 +1123,9 @@ gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fb
if (colorbuffer)
{
- mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
+ mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
+ ? GL_COLOR_ATTACHMENT0
+ : colorbuffer->getBinding());
}
else
{
@@ -827,8 +1149,8 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum
}
}
- std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
- outputSignature);
+ std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
+ mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
// Generate new pixel executable
ShaderExecutableD3D *pixelExecutable = NULL;
@@ -837,7 +1159,7 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable(
- *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
+ *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
&pixelExecutable);
if (error.isError())
@@ -886,7 +1208,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable(
- *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
+ *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
&vertexExecutable);
if (error.isError())
@@ -896,7 +1218,8 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i
if (vertexExecutable)
{
- mVertexExecutables.push_back(new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
+ mVertexExecutables.push_back(
+ new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
}
else if (!infoLog)
{
@@ -909,53 +1232,96 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i
return gl::Error(GL_NO_ERROR);
}
-LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
- int registers,
- const std::vector<PackedVarying> &packedVaryings)
+gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
+ GLenum drawMode,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
{
- const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
+ if (outExecutable)
+ {
+ *outExecutable = nullptr;
+ }
+
+ // We only uses a geometry shader for point sprite emulation, or for fixing the provoking
+ // vertex problem. Otherwise, return a null shader.
+ if (drawMode != GL_POINTS && !mUsesFlatInterpolation)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+
+ if (mGeometryExecutables[geometryShaderType] != nullptr)
+ {
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType];
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
+ geometryShaderType, data, mData, mGeometryShaderPreamble);
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(
+ *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
+ (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
+ &mGeometryExecutables[geometryShaderType]);
+
+ if (!infoLog && error.isError())
+ {
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
+ }
+
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType];
+ }
+ return error;
+}
+LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
+{
const gl::InputLayout &defaultInputLayout =
GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
ShaderExecutableD3D *defaultVertexExecutable = NULL;
- gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
+ gl::Error error =
+ getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
if (error.isError())
{
return LinkResult(false, error);
}
- std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
+ std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
ShaderExecutableD3D *defaultPixelExecutable = NULL;
- error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
+ error =
+ getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
if (error.isError())
{
return LinkResult(false, error);
}
- if (usesGeometryShader())
+ // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
+ ShaderExecutableD3D *pointGS = nullptr;
+ if (usesGeometryShader(GL_POINTS))
{
- std::string geometryHLSL =
- mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, packedVaryings);
-
- error = mRenderer->compileToExecutable(
- infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
- D3DCompilerWorkarounds(), &mGeometryExecutable);
- if (error.isError())
- {
- return LinkResult(false, error);
- }
+ getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog);
}
-#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
- if (usesGeometryShader() && mGeometryExecutable)
+ if (usesGeometryShader(GL_POINTS) && pointGS)
{
- // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
- // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
+ // Geometry shaders are currently only used internally, so there is no corresponding shader
+ // object at the interface level. For now the geometry shader debug info is prepended to
+ // the vertex shader.
vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
- vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
+ vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
}
@@ -966,11 +1332,13 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog,
if (defaultPixelExecutable)
{
+ const ShaderD3D *fragmentShaderD3D =
+ GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
}
-#endif
- bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
+ bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
+ (!usesGeometryShader(GL_POINTS) || pointGS));
return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
}
@@ -997,10 +1365,7 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
mSamplersPS.resize(data.caps->maxTextureImageUnits);
- mVertexHLSL = vertexShader->getTranslatedSource();
vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
-
- mPixelHLSL = fragmentShader->getTranslatedSource();
fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
if (mRenderer->getRendererLimitations().noFrontFacingSupport)
@@ -1016,37 +1381,78 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
// Map the varyings to the register file
- int registers = mDynamicHLSL->packVaryings(infoLog, &packedVaryings,
- mData.getTransformFeedbackVaryingNames());
+ VaryingPacking varyingPacking(data.caps->maxVaryingVectors);
+ if (!varyingPacking.packVaryings(infoLog, packedVaryings,
+ mData.getTransformFeedbackVaryingNames()))
+ {
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
+ }
+
+ ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(),
+ usesInstancedPointSpriteEmulation(), vertexShaderD3D,
+ fragmentShaderD3D);
+
+ varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
+ varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
- if (registers < 0)
+ if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors)
{
+ infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
- std::vector<gl::LinkedVarying> linkedVaryings;
- if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, mPixelHLSL,
- mVertexHLSL, packedVaryings, &linkedVaryings,
- &mPixelShaderKey, &mUsesFragDepth))
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
+ // intelligently, but D3D9 assumes one semantic per register.
+ if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
+ varyingPacking.getMaxSemanticIndex() > data.caps->maxVaryingVectors)
+ {
+ infoLog << "Cannot pack these varyings on D3D9.";
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
+ }
+
+ if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL,
+ &mVertexHLSL))
{
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUsesPointSize = vertexShaderD3D->usesPointSize();
+ mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey);
+ mUsesFragDepth = metadata.usesFragDepth(mData);
+
+ // Cache if we use flat shading
+ mUsesFlatInterpolation = false;
+ for (const auto &varying : packedVaryings)
+ {
+ if (varying.interpolation == sh::INTERPOLATION_FLAT)
+ {
+ mUsesFlatInterpolation = true;
+ break;
+ }
+ }
+
+ if (mRenderer->getMajorShaderModel() >= 4)
+ {
+ varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata);
+ mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking);
+ }
initSemanticIndex();
defineUniformsAndAssignRegisters();
- gatherTransformFeedbackVaryings(linkedVaryings);
+ gatherTransformFeedbackVaryings(varyingPacking);
- LinkResult result = compileProgramExecutables(infoLog, registers, packedVaryings);
+ LinkResult result = compileProgramExecutables(data, infoLog);
if (result.error.isError() || !result.linkSuccess)
{
infoLog << "Failed to create D3D shaders.";
return result;
}
+ initUniformBlockInfo();
+
return LinkResult(true, gl::Error(GL_NO_ERROR));
}
@@ -1056,24 +1462,20 @@ GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLo
return GL_TRUE;
}
-void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
- std::vector<gl::LinkedUniform> *uniforms)
+void ProgramD3D::initUniformBlockInfo()
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
- BlockInfoMap blockInfo;
- std::map<std::string, size_t> blockDataSizes;
-
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
{
if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
- if (blockDataSizes.count(vertexBlock.name) > 0)
+ if (mBlockDataSizes.count(vertexBlock.name) > 0)
continue;
- size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
- blockDataSizes[vertexBlock.name] = dataSize;
+ size_t dataSize = getUniformBlockInfo(vertexBlock);
+ mBlockDataSizes[vertexBlock.name] = dataSize;
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
@@ -1083,55 +1485,50 @@ void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBl
if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
- if (blockDataSizes.count(fragmentBlock.name) > 0)
+ if (mBlockDataSizes.count(fragmentBlock.name) > 0)
continue;
- size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
- blockDataSizes[fragmentBlock.name] = dataSize;
+ size_t dataSize = getUniformBlockInfo(fragmentBlock);
+ mBlockDataSizes[fragmentBlock.name] = dataSize;
}
+}
- // Copy block info out to uniforms.
- for (gl::LinkedUniform &linkedUniform : *uniforms)
- {
- const auto &infoEntry = blockInfo.find(linkedUniform.name);
-
- if (infoEntry != blockInfo.end())
- {
- linkedUniform.blockInfo = infoEntry->second;
- }
- }
+void ProgramD3D::assignUniformBlockRegisters()
+{
+ mD3DUniformBlocks.clear();
// Assign registers and update sizes.
- const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
- const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
+ const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
- for (gl::UniformBlock &uniformBlock : *uniformBlocks)
+ for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
{
unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
+ D3DUniformBlock d3dUniformBlock;
+
if (uniformBlock.vertexStaticUse)
{
unsigned int baseRegister =
vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
- uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
+ d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
}
if (uniformBlock.fragmentStaticUse)
{
unsigned int baseRegister =
fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
- uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
+ d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
}
- ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
- uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
+ mD3DUniformBlocks.push_back(d3dUniformBlock);
}
}
void ProgramD3D::initializeUniformStorage()
{
// Compute total default block size
- unsigned int vertexRegisters = 0;
+ unsigned int vertexRegisters = 0;
unsigned int fragmentRegisters = 0;
for (const D3DUniform *d3dUniform : mD3DUniforms)
{
@@ -1150,15 +1547,15 @@ void ProgramD3D::initializeUniformStorage()
}
}
- mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
+ mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
}
-gl::Error ProgramD3D::applyUniforms()
+gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
{
updateSamplerMapping();
- gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
+ gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
if (error.isError())
{
return error;
@@ -1174,26 +1571,36 @@ gl::Error ProgramD3D::applyUniforms()
gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
{
+ if (mData.getUniformBlocks().empty())
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ // Lazy init.
+ if (mD3DUniformBlocks.empty())
+ {
+ assignUniformBlockRegisters();
+ }
+
mVertexUBOCache.clear();
mFragmentUBOCache.clear();
const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
- const auto &uniformBlocks = mData.getUniformBlocks();
- for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
uniformBlockIndex++)
{
- const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
- GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
+ const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
+ GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
// Unnecessary to apply an unreferenced standard or shared UBO
- if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
+ if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
{
continue;
}
- if (uniformBlock.vertexStaticUse)
+ if (uniformBlock.vertexStaticUse())
{
unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
@@ -1207,7 +1614,7 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
mVertexUBOCache[registerIndex] = blockBinding;
}
- if (uniformBlock.fragmentStaticUse)
+ if (uniformBlock.fragmentStaticUse())
{
unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
@@ -1233,7 +1640,7 @@ void ProgramD3D::dirtyAllUniforms()
}
}
-void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
setUniform(location, count, v, GL_FLOAT);
}
@@ -1253,47 +1660,74 @@ void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
setUniform(location, count, v, GL_FLOAT_VEC4);
}
-void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
}
-void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
}
-void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
}
-void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
}
-void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
}
-void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
}
-void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
}
-void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
}
-void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramD3D::setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
}
@@ -1338,14 +1772,15 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
}
-void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
+ GLuint /*uniformBlockBinding*/)
{
}
void ProgramD3D::defineUniformsAndAssignRegisters()
{
D3DUniformMap uniformMap;
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
+ const gl::Shader *vertexShader = mData.getAttachedVertexShader();
for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
{
@@ -1355,7 +1790,7 @@ void ProgramD3D::defineUniformsAndAssignRegisters()
}
}
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
+ const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
{
if (fragmentUniform.staticUse)
@@ -1429,7 +1864,7 @@ void ProgramD3D::defineUniform(GLenum shaderType,
for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
{
- const sh::ShaderVariable &field = uniform.fields[fieldIndex];
+ const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
@@ -1490,19 +1925,9 @@ void ProgramD3D::defineUniform(GLenum shaderType,
}
template <typename T>
-static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
-{
- ASSERT(dest != NULL);
- ASSERT(dirtyFlag != NULL);
-
- *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
- *dest = source;
-}
-
-template <typename T>
void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
{
- const int components = gl::VariableComponentCount(targetUniformType);
+ const int components = gl::VariableComponentCount(targetUniformType);
const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
@@ -1517,7 +1942,7 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
for (unsigned int i = 0; i < count; i++)
{
- T *dest = target + (i * 4);
+ T *dest = target + (i * 4);
const T *source = v + (i * components);
for (int c = 0; c < components; c++)
@@ -1536,12 +1961,13 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
for (unsigned int i = 0; i < count; i++)
{
- GLint *dest = boolParams + (i * 4);
+ 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);
+ SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
+ &targetUniform->dirty);
}
for (int c = components; c < 4; c++)
{
@@ -1559,8 +1985,8 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
for (unsigned int i = 0; i < count; i++)
{
- GLint *dest = target + (i * 4);
- const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
+ 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);
@@ -1573,75 +1999,8 @@ void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum
mDirtySamplerMapping = true;
}
}
- else UNREACHABLE();
-}
-
-template<typename T>
-bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
-{
- bool dirty = false;
- int copyWidth = std::min(targetHeight, srcWidth);
- int copyHeight = std::min(targetWidth, srcHeight);
-
- for (int x = 0; x < copyWidth; x++)
- {
- for (int y = 0; y < copyHeight; y++)
- {
- SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
- }
- }
- // clear unfilled right side
- for (int y = 0; y < copyWidth; y++)
- {
- for (int x = copyHeight; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
- }
- // clear unfilled bottom.
- for (int y = copyWidth; y < targetHeight; y++)
- {
- for (int x = 0; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
- }
-
- return dirty;
-}
-
-template<typename T>
-bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
-{
- bool dirty = false;
- int copyWidth = std::min(targetWidth, srcWidth);
- int copyHeight = std::min(targetHeight, srcHeight);
-
- for (int y = 0; y < copyHeight; y++)
- {
- for (int x = 0; x < copyWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
- }
- }
- // clear unfilled right side
- for (int y = 0; y < copyHeight; y++)
- {
- for (int x = copyWidth; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
- }
- // clear unfilled bottom.
- for (int y = copyHeight; y < targetHeight; y++)
- {
- for (int x = 0; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
- }
-
- return dirty;
+ else
+ UNREACHABLE();
}
template <int cols, int rows>
@@ -1666,19 +2025,20 @@ void ProgramD3D::setUniformMatrixfv(GLint location,
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
if (transpose == GL_FALSE)
{
- targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
+ targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
+ targetUniform->dirty;
}
else
{
- targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
+ targetUniform->dirty =
+ ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
}
target += targetMatrixStride;
value += cols * rows;
}
}
-size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
- BlockInfoMap *blockInfoOut)
+size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
{
ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
@@ -1697,7 +2057,7 @@ size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
}
GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
- blockInfoOut);
+ &mBlockInfo);
return encoder->getBlockSize();
}
@@ -1757,7 +2117,11 @@ void ProgramD3D::reset()
{
SafeDeleteContainer(mVertexExecutables);
SafeDeleteContainer(mPixelExecutables);
- SafeDelete(mGeometryExecutable);
+
+ for (auto &element : mGeometryExecutables)
+ {
+ SafeDelete(element);
+ }
mVertexHLSL.clear();
mVertexWorkarounds = D3DCompilerWorkarounds();
@@ -1767,8 +2131,10 @@ void ProgramD3D::reset()
mUsesFragDepth = false;
mPixelShaderKey.clear();
mUsesPointSize = false;
+ mUsesFlatInterpolation = false;
SafeDeleteContainer(mD3DUniforms);
+ mD3DUniformBlocks.clear();
SafeDelete(mVertexUniformStorage);
SafeDelete(mFragmentUniformStorage);
@@ -1777,13 +2143,15 @@ void ProgramD3D::reset()
mSamplersVS.clear();
mUsedVertexSamplerRange = 0;
- mUsedPixelSamplerRange = 0;
- mDirtySamplerMapping = true;
+ mUsedPixelSamplerRange = 0;
+ mDirtySamplerMapping = true;
std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
- mTransformFeedbackLinkedVaryings.clear();
+ mStreamOutVaryings.clear();
+
+ mGeometryShaderPreamble.clear();
}
unsigned int ProgramD3D::getSerial() const
@@ -1828,15 +2196,16 @@ void ProgramD3D::initAttributesByLayout()
AttributeSorter(mSemanticIndexes));
}
-void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
- int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
- const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
+void ProgramD3D::sortAttributesByLayout(
+ const std::vector<TranslatedAttribute> &unsortedAttributes,
+ int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
+ const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
{
for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
{
- int oldIndex = mAttributesByLayout[attribIndex];
+ int oldIndex = mAttributesByLayout[attribIndex];
sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
- sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
+ sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
}
}
@@ -1862,19 +2231,66 @@ void ProgramD3D::updateCachedInputLayout(const gl::State &state)
}
}
-void ProgramD3D::gatherTransformFeedbackVaryings(
- const std::vector<gl::LinkedVarying> &linkedVaryings)
+void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking)
{
+ const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
+
+ const std::string &varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
+
// Gather the linked varyings that are used for transform feedback, they should all exist.
- mTransformFeedbackLinkedVaryings.clear();
- for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
+ mStreamOutVaryings.clear();
+
+ const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames();
+ for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
+ ++outputSlot)
{
- for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
+ const auto &tfVaryingName = tfVaryingNames[outputSlot];
+ if (tfVaryingName == "gl_Position")
{
- if (tfVaryingName == linkedVarying.name)
+ if (builtins.glPosition.enabled)
{
- mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
- break;
+ mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
+ builtins.glPosition.index, 4, outputSlot));
+ }
+ }
+ else if (tfVaryingName == "gl_FragCoord")
+ {
+ if (builtins.glFragCoord.enabled)
+ {
+ mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
+ builtins.glFragCoord.index, 4, outputSlot));
+ }
+ }
+ else if (tfVaryingName == "gl_PointSize")
+ {
+ if (builtins.glPointSize.enabled)
+ {
+ mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
+ }
+ }
+ else
+ {
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &varying = *registerInfo.packedVarying->varying;
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ int componentCount = gl::VariableColumnCount(transposedType);
+ ASSERT(!varying.isBuiltIn());
+
+ // Transform feedback for varying structs is underspecified.
+ // See Khronos bug 9856.
+ // TODO(jmadill): Figure out how to be spec-compliant here.
+ if (registerInfo.packedVarying->isStructField() || varying.isStruct())
+ continue;
+
+ // There can be more than one register assigned to a particular varying, and each
+ // register needs its own stream out entry.
+ if (tfVaryingName == varying.name)
+ {
+ mStreamOutVaryings.push_back(D3DVarying(
+ varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
+ }
}
}
}
@@ -1884,4 +2300,34 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
{
return mD3DUniforms[mData.getUniformLocations()[location].index];
}
+
+bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+{
+ std::string baseName = blockName;
+ gl::ParseAndStripArrayIndex(&baseName);
+
+ auto sizeIter = mBlockDataSizes.find(baseName);
+ if (sizeIter == mBlockDataSizes.end())
+ {
+ *sizeOut = 0;
+ return false;
+ }
+
+ *sizeOut = sizeIter->second;
+ return true;
+}
+
+bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ auto infoIter = mBlockInfo.find(memberUniformName);
+ if (infoIter == mBlockInfo.end())
+ {
+ *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return false;
+ }
+
+ *memberInfoOut = infoIter->second;
+ return true;
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
index ba0530f2c06..5ea15aa8b96 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -68,6 +68,66 @@ struct D3DUniform : angle::NonCopyable
unsigned int registerElement;
};
+struct D3DUniformBlock
+{
+ D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {}
+
+ bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
+
+ bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
+
+ unsigned int vsRegisterIndex;
+ unsigned int psRegisterIndex;
+};
+
+struct D3DVarying final
+{
+ D3DVarying();
+ D3DVarying(const std::string &semanticNameIn,
+ unsigned int semanticIndexIn,
+ unsigned int componentCountIn,
+ unsigned int outputSlotIn);
+
+ D3DVarying(const D3DVarying &) = default;
+ D3DVarying &operator=(const D3DVarying &) = default;
+
+ std::string semanticName;
+ unsigned int semanticIndex;
+ unsigned int componentCount;
+ unsigned int outputSlot;
+};
+
+class ProgramD3DMetadata : angle::NonCopyable
+{
+ public:
+ ProgramD3DMetadata(int rendererMajorShaderModel,
+ const std::string &shaderModelSuffix,
+ bool usesInstancedPointSpriteEmulation,
+ const ShaderD3D *vertexShader,
+ const ShaderD3D *fragmentShader);
+
+ int getRendererMajorShaderModel() const;
+ bool usesBroadcast(const gl::Data &data) const;
+ bool usesFragDepth(const gl::Program::Data &programData) const;
+ bool usesPointCoord() const;
+ bool usesFragCoord() const;
+ bool usesPointSize() const;
+ bool usesInsertedPointCoordValue() const;
+ bool addsPointCoordToVertexShader() const;
+ bool usesTransformFeedbackGLPosition() const;
+ bool usesSystemValuePointSize() const;
+ bool usesMultipleFragmentOuts() const;
+ GLint getMajorShaderVersion() const;
+ const ShaderD3D *getFragmentShader() const;
+
+ private:
+ const int mRendererMajorShaderModel;
+ const std::string mShaderModelSuffix;
+ const bool mUsesInstancedPointSpriteEmulation;
+ const ShaderD3D *mVertexShader;
+ const ShaderD3D *mFragmentShader;
+};
+
class ProgramD3D : public ProgramImpl
{
public:
@@ -78,32 +138,44 @@ class ProgramD3D : public ProgramImpl
const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
- GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const;
+ GLint getSamplerMapping(gl::SamplerType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const;
GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
GLint getUsedSamplerRange(gl::SamplerType type) const;
void updateSamplerMapping();
bool usesPointSize() const { return mUsesPointSize; }
bool usesPointSpriteEmulation() const;
- bool usesGeometryShader() const;
+ bool usesGeometryShader(GLenum drawMode) const;
bool usesInstancedPointSpriteEmulation() const;
- LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
- gl::Error save(gl::BinaryOutputStream *stream);
-
- gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable);
- gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
- gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
- ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; }
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
+ gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+
+ gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
+ ShaderExecutableD3D **outExectuable);
+ gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data,
+ GLenum drawMode,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog);
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
- void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
- std::vector<gl::LinkedUniform> *uniforms) override;
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
void initializeUniformStorage();
- gl::Error applyUniforms();
+ gl::Error applyUniforms(GLenum drawMode);
gl::Error applyUniformBuffers(const gl::Data &data);
void dirtyAllUniforms();
@@ -119,15 +191,42 @@ class ProgramD3D : public ProgramImpl
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 setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
@@ -136,9 +235,10 @@ class ProgramD3D : public ProgramImpl
unsigned int getSerial() const;
- void sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
- int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
- const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const;
+ void sortAttributesByLayout(
+ const std::vector<TranslatedAttribute> &unsortedAttributes,
+ int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
+ const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const;
const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndexes; }
const SemanticIndexArray &getAttributesByLayout() const { return mAttributesByLayout; }
@@ -174,10 +274,14 @@ class ProgramD3D : public ProgramImpl
class PixelExecutable
{
public:
- PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable);
+ PixelExecutable(const std::vector<GLenum> &outputSignature,
+ ShaderExecutableD3D *shaderExecutable);
~PixelExecutable();
- bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
+ bool matchesSignature(const std::vector<GLenum> &signature) const
+ {
+ return mOutputSignature == signature;
+ }
const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
@@ -197,7 +301,6 @@ class ProgramD3D : public ProgramImpl
};
typedef std::map<std::string, D3DUniform *> D3DUniformMap;
- typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
void defineUniformsAndAssignRegisters();
void defineUniformBase(const gl::Shader *shader,
@@ -217,19 +320,19 @@ class ProgramD3D : public ProgramImpl
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
- size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
-
template <typename T>
- void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
+ 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);
+ void setUniformMatrixfv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ GLenum targetUniformType);
- LinkResult compileProgramExecutables(gl::InfoLog &infoLog,
- int registers,
- const std::vector<PackedVarying> &packedVaryings);
+ LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog);
- void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
+ void gatherTransformFeedbackVaryings(const VaryingPacking &varyings);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
@@ -237,13 +340,17 @@ class ProgramD3D : public ProgramImpl
void initAttributesByLayout();
void reset();
+ void assignUniformBlockRegisters();
+
+ void initUniformBlockInfo();
+ size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
std::vector<VertexExecutable *> mVertexExecutables;
std::vector<PixelExecutable *> mPixelExecutables;
- ShaderExecutableD3D *mGeometryExecutable;
+ std::vector<ShaderExecutableD3D *> mGeometryExecutables;
std::string mVertexHLSL;
D3DCompilerWorkarounds mVertexWorkarounds;
@@ -253,7 +360,13 @@ class ProgramD3D : public ProgramImpl
bool mUsesFragDepth;
std::vector<PixelShaderOutputVariable> mPixelShaderKey;
+ // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output
+ // structures, built from the linked varying info. We store the string itself instead of the
+ // packed varyings for simplicity.
+ std::string mGeometryShaderPreamble;
+
bool mUsesPointSize;
+ bool mUsesFlatInterpolation;
UniformStorageD3D *mVertexUniformStorage;
UniformStorageD3D *mFragmentUniformStorage;
@@ -277,13 +390,16 @@ class ProgramD3D : public ProgramImpl
VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout;
- std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
+ std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
+ std::vector<D3DUniformBlock> mD3DUniformBlocks;
+
+ std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
+ std::map<std::string, size_t> mBlockDataSizes;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
};
-
}
-#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
index 26740aadc99..575ecd636e9 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -8,22 +8,23 @@
#include "libANGLE/renderer/d3d/RendererD3D.h"
-#include "common/MemoryBuffer.h"
#include "common/debug.h"
+#include "common/MemoryBuffer.h"
#include "common/utilities.h"
#include "libANGLE/Display.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/ResourceManager.h"
-#include "libANGLE/State.h"
-#include "libANGLE/VertexArray.h"
-#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
namespace rx
{
@@ -134,12 +135,6 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
GLsizei instances,
const gl::IndexRange &indexRange)
{
- if (data.state->isPrimitiveRestartEnabled())
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented");
- }
-
gl::Program *program = data.state->getProgram();
ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
@@ -158,25 +153,18 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
return gl::Error(GL_NO_ERROR);
}
- error = applyRenderTarget(data, mode, false);
- if (error.isError())
- {
- return error;
- }
-
- error = applyState(data, mode);
+ error = updateState(data, mode);
if (error.isError())
{
return error;
}
- gl::VertexArray *vao = data.state->getVertexArray();
TranslatedIndexData indexInfo;
indexInfo.indexRange = indexRange;
SourceIndexData sourceIndexInfo;
- error = applyIndexBuffer(indices, vao->getElementArrayBuffer().get(), count, mode, type, &indexInfo, &sourceIndexInfo);
+ error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo, &sourceIndexInfo);
if (error.isError())
{
return error;
@@ -195,7 +183,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
return error;
}
- error = applyShaders(data);
+ error = applyShaders(data, mode);
if (error.isError())
{
return error;
@@ -215,8 +203,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
if (!skipDraw(data, mode))
{
- error = drawElementsImpl(mode, count, type, indices, vao->getElementArrayBuffer().get(),
- indexInfo, instances, usesPointSize);
+ error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances);
if (error.isError())
{
return error;
@@ -250,13 +237,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
return gl::Error(GL_NO_ERROR);
}
- error = applyRenderTarget(data, mode, false);
- if (error.isError())
- {
- return error;
- }
-
- error = applyState(data, mode);
+ error = updateState(data, mode);
if (error.isError())
{
return error;
@@ -270,7 +251,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
return error;
}
- error = applyShaders(data);
+ error = applyShaders(data, mode);
if (error.isError())
{
return error;
@@ -290,7 +271,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
if (!skipDraw(data, mode))
{
- error = drawArraysImpl(data, mode, count, instances, usesPointSize);
+ error = drawArraysImpl(data, mode, count, instances);
if (error.isError())
{
return error;
@@ -350,45 +331,8 @@ gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
return gl::Error(GL_NO_ERROR);
}
-// Applies the render target surface, depth stencil surface, viewport rectangle and
-// scissor rectangle to the renderer
-gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport)
-{
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
-
- gl::Error error = applyRenderTarget(framebufferObject);
- if (error.isError())
- {
- return error;
- }
-
- float nearZ = data.state->getNearPlane();
- float farZ = data.state->getFarPlane();
- setViewport(data.state->getViewport(), nearZ, farZ, drawMode,
- data.state->getRasterizerState().frontFace, ignoreViewport);
-
- setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
-
- return gl::Error(GL_NO_ERROR);
-}
-
-// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device
-gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
+unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples)
{
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- int samples = framebufferObject->getSamples(data);
-
- gl::RasterizerState rasterizer = data.state->getRasterizerState();
- rasterizer.pointDrawMode = (drawMode == GL_POINTS);
- rasterizer.multiSample = (samples != 0);
-
- gl::Error error = setRasterizerState(rasterizer);
- if (error.isError())
- {
- return error;
- }
-
unsigned int mask = 0;
if (data.state->isSampleCoverageEnabled())
{
@@ -419,38 +363,24 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
{
mask = 0xFFFFFFFF;
}
- error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask);
- if (error.isError())
- {
- return error;
- }
-
- error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(),
- data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW);
- if (error.isError())
- {
- return error;
- }
- return gl::Error(GL_NO_ERROR);
+ return mask;
}
// Applies the shaders and shader constants to the Direct3D device
-gl::Error RendererD3D::applyShaders(const gl::Data &data)
+gl::Error RendererD3D::applyShaders(const gl::Data &data, GLenum drawMode)
{
gl::Program *program = data.state->getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
programD3D->updateCachedInputLayout(*data.state);
- const gl::Framebuffer *fbo = data.state->getDrawFramebuffer();
-
- gl::Error error = applyShaders(program, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused());
+ gl::Error error = applyShadersImpl(data, drawMode);
if (error.isError())
{
return error;
}
- return programD3D->applyUniforms();
+ return programD3D->applyUniforms(drawMode);
}
// For each Direct3D sampler of either the pixel or vertex stage,
@@ -497,7 +427,15 @@ gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shade
{
// Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
gl::Texture *incompleteTexture = getIncompleteTexture(textureType);
- gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture);
+
+ gl::Error error = setSamplerState(shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState());
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = setTexture(shaderType, samplerIndex, incompleteTexture);
if (error.isError())
{
return error;
@@ -742,5 +680,4 @@ gl::DebugAnnotator *RendererD3D::getAnnotator()
ASSERT(mAnnotator);
return mAnnotator;
}
-
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
index b6c29b934b9..4a90fd12d94 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -12,7 +12,8 @@
#include "common/debug.h"
#include "common/MemoryBuffer.h"
#include "libANGLE/Data.h"
-#include "libANGLe/formatutils.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/Renderer.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
@@ -29,15 +30,17 @@ class ConfigSet;
namespace gl
{
+class DebugAnnotator;
class InfoLog;
-struct LinkedVarying;
class Texture;
-class DebugAnnotator;
+struct LinkedVarying;
}
namespace rx
{
struct D3DUniform;
+struct D3DVarying;
+class DeviceD3D;
class EGLImageD3D;
class ImageD3D;
class IndexBuffer;
@@ -53,7 +56,8 @@ enum ShaderType
{
SHADER_VERTEX,
SHADER_PIXEL,
- SHADER_GEOMETRY
+ SHADER_GEOMETRY,
+ SHADER_TYPE_MAX
};
struct DeviceIdentifier
@@ -139,7 +143,11 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// Direct3D Specific methods
virtual DeviceIdentifier getAdapterIdentifier() const = 0;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
+ virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) = 0;
virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
@@ -149,26 +157,21 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
const std::vector<GLint> &vertexUniformBuffers,
const std::vector<GLint> &fragmentUniformBuffers) = 0;
- virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
- virtual gl::Error setBlendState(const 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 void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport) = 0;
+ virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0;
virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0;
- virtual gl::Error applyShaders(gl::Program *program,
- const gl::Framebuffer *framebuffer,
- bool rasterizerDiscard,
- bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo) = 0;
- virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo) = 0;
+ virtual gl::Error applyIndexBuffer(const gl::Data &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo,
+ SourceIndexData *sourceIndexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
virtual void markAllStateDirty() = 0;
@@ -197,12 +200,18 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0;
// Shader operations
- virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0;
- virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ virtual gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) = 0;
+ virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable) = 0;
virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
@@ -223,11 +232,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
- void syncState(const gl::State & /*state*/, const gl::State::DirtyBits &bitmask) override
- {
- // TODO(jmadill): implement state sync for D3D renderers;
- }
-
// Device lost
void notifyDeviceLost() override;
virtual bool resetDevice() = 0;
@@ -244,13 +248,17 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// In D3D11, faster than calling setTexture a jillion times
virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
+ virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
+
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
+ virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0;
void cleanup();
virtual void createAnnotator() = 0;
+ static unsigned int GetBlendSampleMask(const gl::Data &data, int samples);
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
static const uintptr_t DirtyPointer;
@@ -280,16 +288,14 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLsizei count,
- GLsizei instances,
- bool usesPointSize) = 0;
- virtual gl::Error drawElementsImpl(GLenum mode,
+ GLsizei instances) = 0;
+ virtual gl::Error drawElementsImpl(const gl::Data &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- gl::Buffer *elementArrayBuffer,
- const TranslatedIndexData &indexInfo,
- GLsizei instances,
- bool usesPointSize) = 0;
+ GLsizei instances) = 0;
//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
@@ -297,9 +303,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type);
gl::Error generateSwizzles(const gl::Data &data);
- gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
gl::Error applyState(const gl::Data &data, GLenum drawMode);
- gl::Error applyShaders(const gl::Data &data);
+ gl::Error applyShaders(const gl::Data &data, GLenum drawMode);
gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount);
gl::Error applyTextures(const gl::Data &data);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index 07bd10d134e..1ecbfb74104 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -117,23 +117,24 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const
return mCompilerOutputType;
}
-int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream)
+int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
+ std::string *sourcePath)
{
uncompile();
int additionalOptions = 0;
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
const std::string &source = mData.getSource();
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (gl::DebugAnnotationsActive())
{
- std::string sourcePath = getTempPath();
- writeFile(sourcePath.c_str(), source.c_str(), source.length());
+ *sourcePath = getTempPath();
+ writeFile(sourcePath->c_str(), source.c_str(), source.length());
additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH;
- *shaderSourceStream << sourcePath;
}
#endif
+
*shaderSourceStream << source;
return additionalOptions;
}
@@ -191,15 +192,11 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo
}
}
-#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
mDebugInfo +=
- std::string("// ") + GetShaderTypeString(mData->getShaderType()) + " SHADER BEGIN\n";
- mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n";
+ std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n";
+ mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n";
mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
// Successive steps will append more info
-#else
- mDebugInfo += translatedSource;
-#endif
return true;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
index f61917a7efc..47a73dc27b4 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -21,14 +21,13 @@ struct D3DCompilerWorkarounds;
class ShaderD3D : public ShaderImpl
{
- friend class DynamicHLSL;
-
public:
ShaderD3D(const gl::Shader::Data &data);
virtual ~ShaderD3D();
// ShaderImpl implementation
- int prepareSourceAndReturnOptions(std::stringstream *sourceStream) override;
+ int prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override;
@@ -36,13 +35,20 @@ class ShaderD3D : public ShaderImpl
void uncompile();
unsigned int getUniformRegister(const std::string &uniformName) const;
unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
- void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
+ void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const;
- bool usesDepthRange() const { return mUsesDepthRange; }
+
+ bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
+ bool usesFragColor() const { return mUsesFragColor; }
+ bool usesFragData() const { return mUsesFragData; }
+ bool usesFragCoord() const { return mUsesFragCoord; }
+ bool usesFrontFacing() const { return mUsesFrontFacing; }
bool usesPointSize() const { return mUsesPointSize; }
+ bool usesPointCoord() const { return mUsesPointCoord; }
+ bool usesDepthRange() const { return mUsesDepthRange; }
+ bool usesFragDepth() const { return mUsesFragDepth; }
bool usesDeferredInit() const { return mUsesDeferredInit; }
- bool usesFrontFacing() const { return mUsesFrontFacing; }
ShShaderOutput getCompilerOutputType() const;
@@ -62,11 +68,10 @@ class ShaderD3D : public ShaderImpl
bool mRequiresIEEEStrictCompiling;
ShShaderOutput mCompilerOutputType;
- std::string mDebugInfo;
+ mutable std::string mDebugInfo;
std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
};
-
}
-#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index 77685f06d70..93f69904a3d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -24,13 +24,22 @@ namespace rx
SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle,
EGLint width, EGLint height)
{
- return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL);
+ return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, EGL_FALSE,
+ shareHandle, NULL);
}
-SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window,
- EGLint fixedSize, EGLint width, EGLint height)
+SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ EGLint fixedSize,
+ EGLint directComposition,
+ EGLint width,
+ EGLint height,
+ EGLint orientation)
{
- return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast<EGLClientBuffer>(0), window);
+ return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation,
+ directComposition, static_cast<EGLClientBuffer>(0), window);
}
SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
@@ -39,17 +48,20 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
EGLint width,
EGLint height,
EGLint fixedSize,
+ EGLint orientation,
+ EGLint directComposition,
EGLClientBuffer shareHandle,
EGLNativeWindowType window)
: SurfaceImpl(),
mRenderer(renderer),
mDisplay(display),
mFixedSize(fixedSize == EGL_TRUE),
+ mOrientation(orientation),
mRenderTargetFormat(config->renderTargetFormat),
mDepthStencilFormat(config->depthStencilFormat),
mSwapChain(nullptr),
mSwapIntervalDirty(true),
- mNativeWindow(window, config),
+ mNativeWindow(window, config, directComposition == EGL_TRUE),
mWidth(width),
mHeight(height),
mSwapInterval(1),
@@ -91,7 +103,7 @@ FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Dat
return mRenderer->createFramebuffer(data);
}
-egl::Error SurfaceD3D::bindTexImage(EGLint)
+egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint)
{
return egl::Error(EGL_SUCCESS);
}
@@ -128,7 +140,8 @@ egl::Error SurfaceD3D::resetSwapChain()
height = mHeight;
}
- mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat);
+ mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat,
+ mDepthStencilFormat, mOrientation);
if (!mSwapChain)
{
return egl::Error(EGL_BAD_ALLOC);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
index e6f727aeacf..b925bfc8cc7 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -25,8 +25,15 @@ class RendererD3D;
class SurfaceD3D : public SurfaceImpl
{
public:
- static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
- EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height);
+ static SurfaceD3D *createFromWindow(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ EGLint fixedSize,
+ EGLint directComposition,
+ EGLint width,
+ EGLint height,
+ EGLint orientation);
static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
EGLClientBuffer shareHandle, EGLint width, EGLint height);
~SurfaceD3D() override;
@@ -38,7 +45,7 @@ class SurfaceD3D : public SurfaceImpl
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
@@ -60,8 +67,16 @@ class SurfaceD3D : public SurfaceImpl
FramebufferAttachmentRenderTarget **rtOut) override;
private:
- SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
- EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window);
+ SurfaceD3D(RendererD3D *renderer,
+ egl::Display *display,
+ const egl::Config *config,
+ EGLint width,
+ EGLint height,
+ EGLint fixedSize,
+ EGLint orientation,
+ EGLint directComposition,
+ EGLClientBuffer shareHandle,
+ EGLNativeWindowType window);
egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
@@ -71,6 +86,7 @@ class SurfaceD3D : public SurfaceImpl
egl::Display *mDisplay;
bool mFixedSize;
+ GLint mOrientation;
GLenum mRenderTargetFormat;
GLenum mDepthStencilFormat;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 0687ac89c81..cdb2c474715 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -165,14 +165,6 @@ gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
const uint8_t *pixels,
ptrdiff_t layerOffset)
{
- if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
- {
- // TODO(jmadill): additional unpack parameters
- // return no error here to work around dEQP-GLES3 failing to state reset.
- UNIMPLEMENTED();
- return gl::Error(GL_NO_ERROR);
- }
-
ImageD3D *image = getImage(index);
ASSERT(image);
@@ -258,12 +250,6 @@ gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index,
const uint8_t *pixels,
ptrdiff_t layerOffset)
{
- if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
- }
-
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
const uint8_t *pixelData = NULL;
@@ -295,12 +281,6 @@ gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::
const gl::PixelUnpackState &unpack, const uint8_t *pixels,
ptrdiff_t layerOffset)
{
- if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
- }
-
const uint8_t *pixelData = NULL;
gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
if (error.isError())
@@ -333,6 +313,15 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz
gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
{
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
+ unpack.skipImages != 0)
+ {
+ // TODO(jmadill): additional unpack parameters
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION,
+ "Unimplemented pixel store parameters in fastUnpackPixels");
+ }
+
// No-op
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
{
@@ -765,12 +754,6 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target,
{
ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
- if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
- }
-
GLint level = static_cast<GLint>(imageLevel);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
@@ -2563,7 +2546,8 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target,
redefineImage(level, sizedInternalFormat, size);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+ type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
for (int i = 0; i < size.depth; i++)
{
@@ -2590,7 +2574,8 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target,
ASSERT(target == GL_TEXTURE_2D_ARRAY);
GLint level = static_cast<GLint>(imageLevel);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+ type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
for (int i = 0; i < area.depth; i++)
{
@@ -2625,7 +2610,8 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target,
redefineImage(level, internalFormat, size);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0);
+ GLsizei inputDepthPitch =
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0);
for (int i = 0; i < size.depth; i++)
{
@@ -2648,7 +2634,8 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level,
ASSERT(target == GL_TEXTURE_2D_ARRAY);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+ GLsizei inputDepthPitch =
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
for (int i = 0; i < area.depth; i++)
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
new file mode 100644
index 00000000000..f2654d34e33
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
@@ -0,0 +1,397 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers in D3D
+// for linking between shader stages.
+//
+
+#include "libANGLE/renderer/d3d/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+namespace rx
+{
+
+// Implementation of VaryingPacking::BuiltinVarying
+VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
+{
+}
+
+std::string VaryingPacking::BuiltinVarying::str() const
+{
+ return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
+{
+ enabled = true;
+ semantic = systemValueSemantic;
+ systemValue = true;
+}
+
+void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+ enabled = true;
+ semantic = semanticVal;
+ index = indexVal;
+}
+
+// Implementation of VaryingPacking
+VaryingPacking::VaryingPacking(GLuint maxVaryingVectors)
+ : mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX)
+{
+}
+
+// Packs varyings into generic varying registers, using the algorithm from
+// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
+// Returns false if unsuccessful.
+bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+ unsigned int varyingColumns = 0;
+
+ const auto &varying = *packedVarying.varying;
+
+ // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
+ // where N is the greater of C and R.Variables of type mat2 occupies 2 complete rows."
+ // Here we are a bit more conservative and allow packing non-square matrices more tightly.
+ // Make sure we use transposed matrix types to count registers correctly.
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ varyingRows = gl::VariableRowCount(transposedType);
+ varyingColumns = gl::VariableColumnCount(transposedType);
+
+ // "Arrays of size N are assumed to take N times the size of the base type"
+ varyingRows *= varying.elementCount();
+
+ unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
+
+ // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
+ // Variables are then allocated to successive rows, aligning them to the 1st column."
+ if (varyingColumns >= 2 && varyingColumns <= 4)
+ {
+ for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
+ {
+ if (isFree(row, 0, varyingRows, varyingColumns))
+ {
+ insert(row, 0, packedVarying);
+ return true;
+ }
+ }
+
+ // "For 2 component variables, when there are no spare rows, the strategy is switched to
+ // using the highest numbered row and the lowest numbered column where the variable will
+ // fit."
+ if (varyingColumns == 2)
+ {
+ for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
+ {
+ if (isFree(r, 2, varyingRows, 2))
+ {
+ insert(r, 2, packedVarying);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // "1 component variables have their own packing rule. They are packed in order of size, largest
+ // first. Each variable is placed in the column that leaves the least amount of space in the
+ // column and aligned to the lowest available rows within that column."
+ ASSERT(varyingColumns == 1);
+ unsigned int contiguousSpace[4] = {0};
+ unsigned int bestContiguousSpace[4] = {0};
+ unsigned int totalSpace[4] = {0};
+
+ for (unsigned int row = 0; row < maxVaryingVectors; ++row)
+ {
+ for (unsigned int column = 0; column < 4; ++column)
+ {
+ if (mRegisterMap[row][column])
+ {
+ contiguousSpace[column] = 0;
+ }
+ else
+ {
+ contiguousSpace[column]++;
+ totalSpace[column]++;
+
+ if (contiguousSpace[column] > bestContiguousSpace[column])
+ {
+ bestContiguousSpace[column] = contiguousSpace[column];
+ }
+ }
+ }
+ }
+
+ unsigned int bestColumn = 0;
+ for (unsigned int column = 1; column < 4; ++column)
+ {
+ if (bestContiguousSpace[column] >= varyingRows &&
+ (bestContiguousSpace[bestColumn] < varyingRows ||
+ totalSpace[column] < totalSpace[bestColumn]))
+ {
+ bestColumn = column;
+ }
+ }
+
+ if (bestContiguousSpace[bestColumn] >= varyingRows)
+ {
+ for (unsigned int row = 0; row < maxVaryingVectors; row++)
+ {
+ if (isFree(row, bestColumn, varyingRows, 1))
+ {
+ for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
+ {
+ // If varyingRows > 1, it must be an array.
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerRow = row + arrayIndex;
+ registerInfo.registerColumn = bestColumn;
+ registerInfo.varyingArrayIndex = arrayIndex;
+ registerInfo.varyingRowIndex = 0;
+ mRegisterList.push_back(registerInfo);
+ mRegisterMap[row + arrayIndex][bestColumn] = true;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool VaryingPacking::isFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const
+{
+ for (unsigned int row = 0; row < varyingRows; ++row)
+ {
+ ASSERT(registerRow + row < mRegisterMap.size());
+ for (unsigned int column = 0; column < varyingColumns; ++column)
+ {
+ ASSERT(registerColumn + column < 4);
+ if (mRegisterMap[registerRow + row][registerColumn + column])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void VaryingPacking::insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+ unsigned int varyingColumns = 0;
+
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ varyingRows = gl::VariableRowCount(transposedType);
+ varyingColumns = gl::VariableColumnCount(transposedType);
+
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerColumn = registerColumn;
+
+ for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement)
+ {
+ for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
+ {
+ registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
+ registerInfo.varyingRowIndex = varyingRow;
+ registerInfo.varyingArrayIndex = arrayElement;
+ mRegisterList.push_back(registerInfo);
+
+ for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
+ {
+ mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
+ }
+ }
+ }
+}
+
+// See comment on packVarying.
+bool VaryingPacking::packVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryings)
+{
+ std::set<std::string> uniqueVaryingNames;
+
+ // "Variables are packed into the registers one at a time so that they each occupy a contiguous
+ // subrectangle. No splitting of variables is permitted."
+ for (const PackedVarying &packedVarying : packedVaryings)
+ {
+ const auto &varying = *packedVarying.varying;
+
+ // Do not assign registers to built-in or unreferenced varyings
+ if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField()))
+ {
+ continue;
+ }
+
+ ASSERT(!varying.isStruct());
+ ASSERT(uniqueVaryingNames.count(varying.name) == 0);
+
+ if (packVarying(packedVarying))
+ {
+ uniqueVaryingNames.insert(varying.name);
+ }
+ else
+ {
+ infoLog << "Could not pack varying " << varying.name;
+ return false;
+ }
+ }
+
+ for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
+ {
+ if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
+ {
+ // do not pack builtin XFB varyings
+ continue;
+ }
+
+ for (const PackedVarying &packedVarying : packedVaryings)
+ {
+ const auto &varying = *packedVarying.varying;
+
+ // Make sure transform feedback varyings aren't optimized out.
+ if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
+ {
+ bool found = false;
+ if (transformFeedbackVaryingName == varying.name)
+ {
+ if (!packVarying(packedVarying))
+ {
+ infoLog << "Could not pack varying " << varying.name;
+ return false;
+ }
+
+ found = true;
+ break;
+ }
+ if (!found)
+ {
+ infoLog << "Transform feedback varying " << transformFeedbackVaryingName
+ << " does not exist in the vertex shader.";
+ return false;
+ }
+ }
+ }
+ }
+
+ // Sort the packed register list
+ std::sort(mRegisterList.begin(), mRegisterList.end());
+
+ // Assign semantic indices
+ for (unsigned int semanticIndex = 0;
+ semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
+ {
+ mRegisterList[semanticIndex].semanticIndex = semanticIndex;
+ }
+
+ return true;
+}
+
+unsigned int VaryingPacking::getRegisterCount() const
+{
+ unsigned int count = 0;
+
+ for (const Register &reg : mRegisterMap)
+ {
+ if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
+ {
+ ++count;
+ }
+ }
+
+ if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled)
+ {
+ ++count;
+ }
+
+ if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled)
+ {
+ ++count;
+ }
+
+ return count;
+}
+
+void VaryingPacking::enableBuiltins(ShaderType shaderType,
+ const ProgramD3DMetadata &programMetadata)
+{
+ int majorShaderModel = programMetadata.getRendererMajorShaderModel();
+ bool position = programMetadata.usesTransformFeedbackGLPosition();
+ bool fragCoord = programMetadata.usesFragCoord();
+ bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
+ : programMetadata.usesPointCoord();
+ bool pointSize = programMetadata.usesSystemValuePointSize();
+ bool hlsl4 = (majorShaderModel >= 4);
+ const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
+
+ unsigned int reservedSemanticIndex = getMaxSemanticIndex();
+
+ BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
+
+ if (hlsl4)
+ {
+ builtins->dxPosition.enableSystem("SV_Position");
+ }
+ else if (shaderType == SHADER_PIXEL)
+ {
+ builtins->dxPosition.enableSystem("VPOS");
+ }
+ else
+ {
+ builtins->dxPosition.enableSystem("POSITION");
+ }
+
+ if (position)
+ {
+ builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (fragCoord)
+ {
+ builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (pointCoord)
+ {
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ if (hlsl4)
+ {
+ builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+ else
+ {
+ builtins->glPointCoord.enable("TEXCOORD", 0);
+ }
+ }
+
+ // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+ if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
+ {
+ builtins->glPointSize.enableSystem("PSIZE");
+ }
+}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
new file mode 100644
index 00000000000..ca4640b0002
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
@@ -0,0 +1,175 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers in D3D
+// for linking between shader stages.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class ProgramD3DMetadata;
+
+struct PackedVarying
+{
+ PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
+ : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn)
+ {
+ }
+ PackedVarying(const sh::ShaderVariable &varyingIn,
+ sh::InterpolationType interpolationIn,
+ const std::string &parentStructNameIn)
+ : varying(&varyingIn),
+ vertexOnly(false),
+ interpolation(interpolationIn),
+ parentStructName(parentStructNameIn)
+ {
+ }
+
+ bool isStructField() const { return !parentStructName.empty(); }
+
+ const sh::ShaderVariable *varying;
+
+ // Transform feedback varyings can be only referenced in the VS.
+ bool vertexOnly;
+
+ // Cached so we can store sh::ShaderVariable to point to varying fields.
+ sh::InterpolationType interpolation;
+
+ // Struct name
+ std::string parentStructName;
+};
+
+struct PackedVaryingRegister final
+{
+ PackedVaryingRegister()
+ : packedVarying(nullptr),
+ varyingArrayIndex(0),
+ varyingRowIndex(0),
+ registerRow(0),
+ registerColumn(0)
+ {
+ }
+
+ PackedVaryingRegister(const PackedVaryingRegister &) = default;
+ PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
+
+ bool operator<(const PackedVaryingRegister &other) const
+ {
+ return sortOrder() < other.sortOrder();
+ }
+
+ unsigned int sortOrder() const
+ {
+ // TODO(jmadill): Handle interpolation types
+ return registerRow * 4 + registerColumn;
+ }
+
+ bool isStructField() const { return !structFieldName.empty(); }
+
+ // Index to the array of varyings.
+ const PackedVarying *packedVarying;
+
+ // The array element of the packed varying.
+ unsigned int varyingArrayIndex;
+
+ // The row of the array element of the packed varying.
+ unsigned int varyingRowIndex;
+
+ // The register row to which we've assigned this packed varying.
+ unsigned int registerRow;
+
+ // The column of the register row into which we've packed this varying.
+ unsigned int registerColumn;
+
+ // Assigned after packing
+ unsigned int semanticIndex;
+
+ // Struct member this varying corresponds to.
+ std::string structFieldName;
+};
+
+class VaryingPacking final : angle::NonCopyable
+{
+ public:
+ VaryingPacking(GLuint maxVaryingVectors);
+
+ bool packVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryings);
+
+ struct Register
+ {
+ Register() { data[0] = data[1] = data[2] = data[3] = false; }
+
+ bool &operator[](unsigned int index) { return data[index]; }
+ bool operator[](unsigned int index) const { return data[index]; }
+
+ bool data[4];
+ };
+
+ Register &operator[](unsigned int index) { return mRegisterMap[index]; }
+ const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
+
+ const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
+ unsigned int getMaxSemanticIndex() const
+ {
+ return static_cast<unsigned int>(mRegisterList.size());
+ }
+ unsigned int getRegisterCount() const;
+
+ void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata);
+
+ struct BuiltinVarying final : angle::NonCopyable
+ {
+ BuiltinVarying();
+
+ std::string str() const;
+ void enableSystem(const std::string &systemValueSemantic);
+ void enable(const std::string &semanticVal, unsigned int indexVal);
+
+ bool enabled;
+ std::string semantic;
+ unsigned int index;
+ bool systemValue;
+ };
+
+ struct BuiltinInfo
+ {
+ BuiltinVarying dxPosition;
+ BuiltinVarying glPosition;
+ BuiltinVarying glFragCoord;
+ BuiltinVarying glPointCoord;
+ BuiltinVarying glPointSize;
+ };
+
+ const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
+
+ bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
+
+ private:
+ bool packVarying(const PackedVarying &packedVarying);
+ bool isFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const;
+ void insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying);
+
+ std::vector<Register> mRegisterMap;
+ std::vector<PackedVaryingRegister> mRegisterList;
+
+ std::vector<BuiltinInfo> mBuiltinInfo;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
index 51ea6ef475b..9efee9db7ca 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -243,7 +243,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
}
StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
- : VertexBufferInterface(factory, false)
+ : VertexBufferInterface(factory, false), mIsCommitted(false)
{
}
@@ -255,13 +255,14 @@ bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &att
{
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) &&
+ size_t attribStride = ComputeVertexAttributeStride(attrib);
+
+ if (mCache[element].type == attrib.type && mCache[element].size == attrib.size &&
+ mCache[element].stride == attribStride &&
mCache[element].normalized == attrib.normalized &&
mCache[element].pureInteger == attrib.pureInteger)
{
- size_t offset = (static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib));
+ size_t offset = (static_cast<size_t>(attrib.offset) % attribStride);
if (mCache[element].attributeOffset == offset)
{
if (outStreamOffset)
@@ -321,4 +322,11 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt
return gl::Error(GL_NO_ERROR);
}
+void StaticVertexBufferInterface::commit()
+{
+ if (getBufferSize() > 0)
+ {
+ mIsCommitted = true;
+ }
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
index 81a90f68245..692b6ac5062 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -135,6 +135,11 @@ class StaticVertexBufferInterface : public VertexBufferInterface
bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset);
+ // If a static vertex buffer is committed then no more attribute data can be added to it
+ // A new static vertex buffer should be created instead
+ void commit();
+ bool isCommitted() { return mIsCommitted; }
+
protected:
gl::Error reserveSpace(unsigned int size);
@@ -151,6 +156,7 @@ class StaticVertexBufferInterface : public VertexBufferInterface
unsigned int streamOffset;
};
+ bool mIsCommitted;
std::vector<VertexElement> mCache;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index 559e633eaa8..b392d0f4da2 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -88,10 +88,17 @@ void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttrib
{
gl::Buffer *buffer = translated->attribute->buffer.get();
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
- StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : nullptr;
+ StaticVertexBufferInterface *staticBuffer =
+ storage
+ ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE)
+ : nullptr;
if (staticBuffer)
{
+ // Commit all the static vertex buffers. This fixes them in size/contents, and forces
+ // ANGLE to use a new static buffer (or recreate the static buffers) next time
+ staticBuffer->commit();
+
staticBuffer->getVertexBuffer()->hintUnmapResource();
}
}
@@ -146,10 +153,14 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
{
mActiveEnabledAttributes.push_back(translated);
- // Also invalidate static buffers that don't contain matching attributes
- invalidateMatchingStaticData(
- vertexAttributes[attribIndex],
- state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)));
+ gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get();
+ if (buffer)
+ {
+ // Also reinitialize static buffers which didn't contain matching data
+ // last time they were used
+ BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
+ bufferImpl->reinitOutOfDateStaticData();
+ }
}
else
{
@@ -215,26 +226,6 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
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 = GetImplAs<BufferD3D>(buffer);
- StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
-
- if (staticBuffer &&
- staticBuffer->getBufferSize() > 0 &&
- !staticBuffer->lookupAttribute(attrib, NULL) &&
- !staticBuffer->directStoragePossible(attrib, currentValue.Type))
- {
- bufferImpl->invalidateStaticData();
- }
- }
-}
-
gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
GLsizei count,
GLsizei instances) const
@@ -242,7 +233,9 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &tr
const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
gl::Buffer *buffer = attrib.buffer.get();
BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
- StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
+ StaticVertexBufferInterface *staticBuffer =
+ bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY)
+ : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType))
@@ -291,12 +284,13 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
ASSERT(attrib.enabled);
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
- StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
+ StaticVertexBufferInterface *staticBuffer =
+ storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType);
// Instanced vertices do not apply the 'start' offset
- GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start);
+ GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start);
translated->vertexBuffer = vertexBuffer->getVertexBuffer();
@@ -363,7 +357,8 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
(static_cast<unsigned int>(attrib.offset) /
static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
outputElementSize;
- unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0;
+ ASSERT(attrib.divisor == 0 || firstVertexIndex == 0);
+ unsigned int startOffset = firstVertexIndex * outputElementSize;
if (streamOffset + firstElementOffset + startOffset < streamOffset)
{
return gl::Error(GL_OUT_OF_MEMORY);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
index f03c777bee3..fb349c4cc2e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -82,9 +82,6 @@ class VertexDataManager : angle::NonCopyable
GLsizei count,
GLsizei instances) const;
- void invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
- const gl::VertexAttribCurrentValueData &currentValue) const;
-
gl::Error storeAttribute(TranslatedAttribute *translated,
GLint start,
GLsizei count,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
index 3b42c981777..68776774a28 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -196,6 +196,23 @@ inline unsigned int GetSwizzleIndex(GLenum swizzle)
return colorIndex;
}
+D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
+{
+ D3D11_BLEND_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.RenderTarget[0].BlendEnable = TRUE;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
+ D3D11_COLOR_WRITE_ENABLE_GREEN |
+ D3D11_COLOR_WRITE_ENABLE_BLUE;
+ return desc;
+}
+
D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
@@ -213,21 +230,57 @@ D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
Blit11::Blit11(Renderer11 *renderer)
: mRenderer(renderer),
+ mResourcesInitialized(false),
mVertexBuffer(nullptr),
mPointSampler(nullptr),
mLinearSampler(nullptr),
mScissorEnabledRasterizerState(nullptr),
mScissorDisabledRasterizerState(nullptr),
mDepthStencilState(nullptr),
- mQuad2DIL(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D input layout"),
+ mQuad2DIL(quad2DLayout,
+ ArraySize(quad2DLayout),
+ g_VS_Passthrough2D,
+ ArraySize(g_VS_Passthrough2D),
+ "Blit11 2D input layout"),
mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
- mDepthPS(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), "Blit11 2D depth pixel shader"),
- mQuad3DIL(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D input layout"),
+ mDepthPS(g_PS_PassthroughDepth2D,
+ ArraySize(g_PS_PassthroughDepth2D),
+ "Blit11 2D depth pixel shader"),
+ mQuad3DIL(quad3DLayout,
+ ArraySize(quad3DLayout),
+ g_VS_Passthrough3D,
+ ArraySize(g_VS_Passthrough3D),
+ "Blit11 3D input layout"),
mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
+ mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
mSwizzleCB(nullptr)
{
- TRACE_EVENT0("gpu.angle", "Blit11::Blit11");
+}
+
+Blit11::~Blit11()
+{
+ freeResources();
+
+ mQuad2DIL.release();
+ mQuad2DVS.release();
+ mDepthPS.release();
+
+ mQuad3DIL.release();
+ mQuad3DVS.release();
+ mQuad3DGS.release();
+
+ clearShaderMap();
+}
+
+gl::Error Blit11::initResources()
+{
+ if (mResourcesInitialized)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ TRACE_EVENT0("gpu.angle", "Blit11::initResources");
HRESULT result;
ID3D11Device *device = mRenderer->getDevice();
@@ -236,7 +289,7 @@ Blit11::Blit11(Renderer11 *renderer)
vbDesc.ByteWidth =
static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
sizeof(d3d11::PositionTexCoordVertex)) *
- 6 * renderer->getRendererCaps().max3DTextureSize);
+ 6 * mRenderer->getRendererCaps().max3DTextureSize);
vbDesc.Usage = D3D11_USAGE_DYNAMIC;
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
@@ -245,6 +298,12 @@ Blit11::Blit11(Renderer11 *renderer)
result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X",
+ result);
+ }
d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
D3D11_SAMPLER_DESC pointSamplerDesc;
@@ -264,6 +323,12 @@ Blit11::Blit11(Renderer11 *renderer)
result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit point sampler state, HRESULT: 0x%X", result);
+ }
d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
D3D11_SAMPLER_DESC linearSamplerDesc;
@@ -283,6 +348,12 @@ Blit11::Blit11(Renderer11 *renderer)
result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit linear sampler state, HRESULT: 0x%X", result);
+ }
d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
// Use a rasterizer state that will not cull so that inverted quads will not be culled
@@ -300,11 +371,25 @@ Blit11::Blit11(Renderer11 *renderer)
rasterDesc.ScissorEnable = TRUE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X",
+ result);
+ }
d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
rasterDesc.ScissorEnable = FALSE;
result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X",
+ result);
+ }
d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
@@ -325,6 +410,12 @@ Blit11::Blit11(Renderer11 *renderer)
result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create blit depth stencil state, HRESULT: 0x%X", result);
+ }
d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
D3D11_BUFFER_DESC swizzleBufferDesc;
@@ -337,10 +428,20 @@ Blit11::Blit11(Renderer11 *renderer)
result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB);
ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ freeResources();
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X",
+ result);
+ }
d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
+
+ mResourcesInitialized = true;
+
+ return gl::Error(GL_NO_ERROR);
}
-Blit11::~Blit11()
+void Blit11::freeResources()
{
SafeRelease(mVertexBuffer);
SafeRelease(mPointSampler);
@@ -348,18 +449,9 @@ Blit11::~Blit11()
SafeRelease(mScissorEnabledRasterizerState);
SafeRelease(mScissorDisabledRasterizerState);
SafeRelease(mDepthStencilState);
-
- mQuad2DIL.release();
- mQuad2DVS.release();
- mDepthPS.release();
-
- mQuad3DIL.release();
- mQuad3DVS.release();
- mQuad3DGS.release();
-
SafeRelease(mSwizzleCB);
- clearShaderMap();
+ mResourcesInitialized = false;
}
// static
@@ -521,6 +613,12 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
GLenum swizzleBlue,
GLenum swizzleAlpha)
{
+ gl::Error error = initResources();
+ if (error.isError())
+ {
+ return error;
+ }
+
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -550,7 +648,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
}
const Shader *shader = nullptr;
- gl::Error error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader);
+ error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader);
if (error.isError())
{
return error;
@@ -649,10 +747,23 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
return gl::Error(GL_NO_ERROR);
}
-gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
- const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
+gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11RenderTargetView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum filter,
+ bool maskOffAlpha)
{
+ gl::Error error = initResources();
+ if (error.isError())
+ {
+ return error;
+ }
+
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -668,7 +779,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s
ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
const Shader *shader = nullptr;
- gl::Error error = getBlitShader(destFormat, isSigned, dimension, &shader);
+ error = getBlitShader(destFormat, isSigned, dimension, &shader);
if (error.isError())
{
return error;
@@ -698,7 +809,16 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
// Apply state
- deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ if (maskOffAlpha)
+ {
+ ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
+ ASSERT(blendState);
+ deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
+ }
+ else
+ {
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ }
deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
if (scissor)
@@ -787,6 +907,12 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou
ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
+ gl::Error error = initResources();
+ if (error.isError())
+ {
+ return error;
+ }
+
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -898,6 +1024,12 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor, bool stencilOnly)
{
+ gl::Error error = initResources();
+ if (error.isError())
+ {
+ return error;
+ }
+
ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
index d3be7917c69..906616131ec 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -29,9 +29,16 @@ class Blit11 : angle::NonCopyable
gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
- gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
- const gl::Rectangle *scissor, GLenum destFormat, GLenum filter);
+ gl::Error copyTexture(ID3D11ShaderResourceView *source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ ID3D11RenderTargetView *dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum filter,
+ bool maskOffAlpha);
gl::Error 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,
@@ -125,6 +132,9 @@ class Blit11 : angle::NonCopyable
WriteVertexFunction vertexWriteFunction;
};
+ gl::Error initResources();
+ void freeResources();
+
ShaderSupport getShaderSupport(const Shader &shader);
static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension);
@@ -148,6 +158,7 @@ class Blit11 : angle::NonCopyable
std::map<BlitShaderType, Shader> mBlitShaderMap;
std::map<SwizzleShaderType, Shader> mSwizzleShaderMap;
+ bool mResourcesInitialized;
ID3D11Buffer *mVertexBuffer;
ID3D11SamplerState *mPointSampler;
ID3D11SamplerState *mLinearSampler;
@@ -163,6 +174,8 @@ class Blit11 : angle::NonCopyable
d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS;
d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS;
+ d3d11::LazyBlendState mAlphaMaskBlendState;
+
ID3D11Buffer *mSwizzleCB;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 670561afb1d..7ce85f2a0a5 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -361,7 +361,7 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
}
mSize = std::max(mSize, requiredSize);
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
return gl::Error(GL_NO_ERROR);
}
@@ -417,7 +417,7 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
copyDest->setDataRevision(copyDest->getDataRevision() + 1);
mSize = std::max<size_t>(mSize, destOffset + size);
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
return gl::Error(GL_NO_ERROR);
}
@@ -457,7 +457,7 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL
{
// Update the data revision immediately, since the data might be changed at any time
mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
}
uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access);
@@ -492,7 +492,7 @@ void Buffer11::markTransformFeedbackUsage()
transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
}
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
}
void Buffer11::markBufferUsage()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index 9adef8a59ea..03b28c2a56e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -229,21 +229,15 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
if (colorAttachment != nullptr)
{
- framebufferSize.width = colorAttachment->getWidth();
- framebufferSize.height = colorAttachment->getHeight();
- framebufferSize.depth = 1;
+ framebufferSize = colorAttachment->getSize();
}
else if (depthAttachment != nullptr)
{
- framebufferSize.width = depthAttachment->getWidth();
- framebufferSize.height = depthAttachment->getHeight();
- framebufferSize.depth = 1;
+ framebufferSize = depthAttachment->getSize();
}
else if (stencilAttachment != nullptr)
{
- framebufferSize.width = stencilAttachment->getWidth();
- framebufferSize.height = stencilAttachment->getHeight();
- framebufferSize.depth = 1;
+ framebufferSize = stencilAttachment->getSize();
}
else
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
index da4cf3947dd..f9d28e84082 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -39,32 +39,53 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName)
{
initializeDevice();
- mUserDefinedAnnotation->BeginEvent(eventName);
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->BeginEvent(eventName);
+ }
}
void DebugAnnotator11::endEvent()
{
initializeDevice();
- mUserDefinedAnnotation->EndEvent();
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->EndEvent();
+ }
}
void DebugAnnotator11::setMarker(const wchar_t *markerName)
{
initializeDevice();
- mUserDefinedAnnotation->SetMarker(markerName);
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ mUserDefinedAnnotation->SetMarker(markerName);
+ }
}
bool DebugAnnotator11::getStatus()
{
- // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#if (NTDDI_VERSION == NTDDI_WIN10)
+ initializeDevice();
+
+ if (mUserDefinedAnnotation != nullptr)
+ {
+ return !!(mUserDefinedAnnotation->GetStatus());
+ }
+
+ return true; // Default if initializeDevice() failed
+#elif defined(_DEBUG)
static bool underCapture = true;
-#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
- // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
+ // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in
+ // Windows 8.1/Visual Studio 2013. We can use IDXGraphicsAnalysis, though.
+ // The call to GetDebugInterface1 only succeeds if the app is under capture.
// This should only be called in DEBUG mode.
- // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
+ // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows
+ // Store ingestion checks.
// Cache the result to reduce the number of calls to DXGIGetDebugInterface1
static bool triedIDXGraphicsAnalysis = false;
@@ -82,9 +103,16 @@ bool DebugAnnotator11::getStatus()
SafeRelease(graphicsAnalysis);
triedIDXGraphicsAnalysis = true;
}
-#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE
return underCapture;
+#else
+ // We can't detect GetStatus() on release WinRT 8.1 builds, so always return true.
+ return true;
+#endif // (NTDDI_VERSION == NTDDI_WIN10) or _DEBUG
+#else
+ // We can't detect GetStatus() on desktop ANGLE builds so always return true.
+ return true;
+#endif // ANGLE_ENABLE_WINDOWS_STORE
}
void DebugAnnotator11::initializeDevice()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index 76bb15c193b..4a8d39a500f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -91,7 +91,7 @@ gl::Error Framebuffer11::invalidateSwizzles() const
return gl::Error(GL_NO_ERROR);
}
-gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams)
+gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams)
{
Clear11 *clearer = mRenderer->getClearer();
gl::Error error = clearer->clearFramebuffer(clearParams, mData);
@@ -289,7 +289,12 @@ gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectang
return gl::Error(GL_NO_ERROR);
}
-gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const
{
ID3D11Texture2D *colorBufferTexture = nullptr;
unsigned int subresourceIndex = 0;
@@ -306,6 +311,13 @@ gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GL
gl::Buffer *packBuffer = pack.pixelBuffer.get();
if (packBuffer != nullptr)
{
+ if (pack.rowLength != 0 || pack.skipRows != 0 || pack.skipPixels != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION,
+ "Unimplemented pixel store parameters in readPixelsImpl");
+ }
+
Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
reinterpret_cast<ptrdiff_t>(pixels));
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
index dfadd58603d..c8a33ec7e59 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -29,10 +29,14 @@ class Framebuffer11 : public FramebufferD3D
gl::Error invalidateSwizzles() const;
private:
- gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
-
- gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
- const gl::PixelPackState &pack, uint8_t *pixels) const override;
+ gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
+
+ gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const override;
gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index 0d7ae743a91..8d5efed2fa6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -247,7 +247,10 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
+ type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
+ GLsizei inputSkipBytes = formatInfo.computeSkipPixels(
+ inputRowPitch, inputDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
@@ -264,8 +267,8 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp
uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch));
loadFunction(area.width, area.height, area.depth,
- reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
- offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+ reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
+ inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
unmap();
@@ -276,7 +279,8 @@ gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+ GLsizei inputDepthPitch =
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
index 5868612717b..2c86b4842b6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -317,58 +317,11 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
}
ID3D11InputLayout *inputLayout = nullptr;
-
- auto layoutMapIt = mLayoutMap.find(layout);
- if (layoutMapIt != mLayoutMap.end())
+ gl::Error error = findInputLayout(layout, inputElementCount, inputElements, programD3D,
+ sortedAttributes, unsortedAttributes.size(), &inputLayout);
+ if (error.isError())
{
- inputLayout = layoutMapIt->second;
- }
- else
- {
- const gl::InputLayout &shaderInputLayout =
- GetInputLayout(sortedAttributes, unsortedAttributes.size());
-
- ShaderExecutableD3D *shader = nullptr;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
- if (error.isError())
- {
- return error;
- }
-
- ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
-
- D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
- for (unsigned int j = 0; j < inputElementCount; ++j)
- {
- descs[j] = inputElements[j];
- }
-
- HRESULT result = mDevice->CreateInputLayout(descs, inputElementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
- }
-
- if (mLayoutMap.size() >= mCacheSize)
- {
- TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize);
-
- // Randomly release every second element
- auto it = mLayoutMap.begin();
- while (it != mLayoutMap.end())
- {
- it++;
- if (it != mLayoutMap.end())
- {
- // Calling std::map::erase invalidates the current iterator, so make a copy.
- auto eraseIt = it++;
- SafeRelease(eraseIt->second);
- mLayoutMap.erase(eraseIt);
- }
- }
- }
-
- mLayoutMap[layout] = inputLayout;
+ return error;
}
if (inputLayout != mCurrentIL)
@@ -406,7 +359,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
if (sourceInfo->srcBuffer != nullptr)
{
const uint8_t *bufferData = nullptr;
- gl::Error error = sourceInfo->srcBuffer->getData(&bufferData);
+ error = sourceInfo->srcBuffer->getData(&bufferData);
if (error.isError())
{
return error;
@@ -500,6 +453,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
instancedPointSpritesActive ? pointSpriteVertexStride : 0;
mCurrentVertexOffsets[nextAvailableIndex] = 0;
+ // Update maxDiff to include the additional point sprite vertex buffer
+ // to ensure that IASetVertexBuffers uses the correct buffer count.
+ maxDiff = std::max(maxDiff, nextAvailableIndex);
+
if (!mPointSpriteIndexBuffer)
{
// Create an index buffer and set it for pointsprite rendering
@@ -557,4 +514,70 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
return gl::Error(GL_NO_ERROR);
}
+gl::Error InputLayoutCache::findInputLayout(
+ const PackedAttributeLayout &layout,
+ unsigned int inputElementCount,
+ const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS],
+ ProgramD3D *programD3D,
+ const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS],
+ size_t attributeCount,
+ ID3D11InputLayout **inputLayout)
+{
+ if (inputElementCount == 0)
+ {
+ *inputLayout = nullptr;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ auto layoutMapIt = mLayoutMap.find(layout);
+ if (layoutMapIt != mLayoutMap.end())
+ {
+ *inputLayout = layoutMapIt->second;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attributeCount);
+
+ ShaderExecutableD3D *shader = nullptr;
+ gl::Error error =
+ programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
+
+ HRESULT result =
+ mDevice->CreateInputLayout(inputElements, inputElementCount, shader11->getFunction(),
+ shader11->getLength(), inputLayout);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Failed to create internal input layout, HRESULT: 0x%08x", result);
+ }
+
+ if (mLayoutMap.size() >= mCacheSize)
+ {
+ TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize);
+
+ // Randomly release every second element
+ auto it = mLayoutMap.begin();
+ while (it != mLayoutMap.end())
+ {
+ it++;
+ if (it != mLayoutMap.end())
+ {
+ // Calling std::map::erase invalidates the current iterator, so make a copy.
+ auto eraseIt = it++;
+ SafeRelease(eraseIt->second);
+ mLayoutMap.erase(eraseIt);
+ }
+ }
+ }
+
+ mLayoutMap[layout] = *inputLayout;
+ return gl::Error(GL_NO_ERROR);
}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
index 4cc0ec9b68a..58edb9c1136 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -31,6 +31,7 @@ namespace rx
struct TranslatedAttribute;
struct TranslatedIndexData;
struct SourceIndexData;
+class ProgramD3D;
class InputLayoutCache : angle::NonCopyable
{
@@ -76,6 +77,14 @@ class InputLayoutCache : angle::NonCopyable
uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS];
};
+ gl::Error findInputLayout(const PackedAttributeLayout &layout,
+ unsigned int inputElementCount,
+ const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS],
+ ProgramD3D *programD3D,
+ const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS],
+ size_t attributeCount,
+ ID3D11InputLayout **inputLayout);
+
std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
ID3D11InputLayout *mCurrentIL;
@@ -94,6 +103,6 @@ class InputLayoutCache : angle::NonCopyable
D3D_FEATURE_LEVEL mFeatureLevel;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
index adaa9d9acac..f28ce4f8275 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
@@ -44,14 +44,21 @@ typedef IDXGISwapChain DXGISwapChain;
typedef IDXGIFactory DXGIFactory;
#endif
+typedef interface IDCompositionDevice IDCompositionDevice;
+typedef interface IDCompositionTarget IDCompositionTarget;
+typedef interface IDCompositionVisual IDCompositionVisual;
+
namespace rx
{
class NativeWindow
{
public:
- explicit NativeWindow(EGLNativeWindowType window, const egl::Config *config);
+ explicit NativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ bool directComposition);
+ ~NativeWindow();
bool initialize();
bool getClientRect(LPRECT rect);
bool isIconic();
@@ -63,11 +70,17 @@ class NativeWindow
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+ void commitChange();
+
private:
EGLNativeWindowType mWindow;
-#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+ bool mDirectComposition;
+ IDCompositionDevice *mDevice;
+ IDCompositionTarget *mCompositionTarget;
+ IDCompositionVisual *mVisual;
const egl::Config *mConfig;
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
std::shared_ptr<InspectableNativeWindow> mImpl;
#endif
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
index 5678581031d..0ab5980e1ff 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -21,6 +21,7 @@
namespace rx
{
+using namespace gl_d3d11;
template <typename mapType>
static void ClearStateMap(mapType &map)
@@ -297,14 +298,31 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a,
return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
}
-gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState)
+gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState,
+ bool disableDepth,
+ bool disableStencil,
+ ID3D11DepthStencilState **outDSState)
{
if (!mDevice)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
- DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState);
+ gl::DepthStencilState glState = originalState;
+ if (disableDepth)
+ {
+ glState.depthTest = false;
+ glState.depthMask = false;
+ }
+
+ if (disableStencil)
+ {
+ glState.stencilWritemask = 0;
+ glState.stencilBackWritemask = 0;
+ glState.stencilTest = false;
+ }
+
+ auto keyIter = mDepthStencilStateCache.find(glState);
if (keyIter != mDepthStencilStateCache.end())
{
DepthStencilStateCounterPair &state = keyIter->second;
@@ -312,53 +330,55 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &ds
*outDSState = state.first;
return gl::Error(GL_NO_ERROR);
}
- else
+
+ if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
{
- if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
- {
- TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used "
- "to make room.", kMaxDepthStencilStates);
+ TRACE(
+ "Overflowed the limit of %u depth stencil states, removing the least recently used "
+ "to make room.",
+ kMaxDepthStencilStates);
- DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin();
- for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+ auto leastRecentlyUsed = mDepthStencilStateCache.begin();
+ for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
{
- if (i->second.second < leastRecentlyUsed->second.second)
- {
- leastRecentlyUsed = i;
- }
+ leastRecentlyUsed = i;
}
- SafeRelease(leastRecentlyUsed->second.first);
- mDepthStencilStateCache.erase(leastRecentlyUsed);
}
+ SafeRelease(leastRecentlyUsed->second.first);
+ mDepthStencilStateCache.erase(leastRecentlyUsed);
+ }
- D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
- dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE;
- dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask);
- dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc);
- dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE;
- dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask);
- dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask);
- dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail);
- dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail);
- dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass);
- dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc);
- dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail);
- dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail);
- dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass);
- dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc);
-
- ID3D11DepthStencilState *dx11DepthStencilState = NULL;
- HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
- if (FAILED(result) || !dx11DepthStencilState)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
- }
+ D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
+ dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE;
+ dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask);
+ dsDesc.DepthFunc = ConvertComparison(glState.depthFunc);
+ dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE;
+ dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask);
+ dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask);
+ dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail);
+ dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail);
+ dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass);
+ dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc);
+ dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail);
+ dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail);
+ dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass);
+ dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc);
+
+ ID3D11DepthStencilState *dx11DepthStencilState = NULL;
+ HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
+ if (FAILED(result) || !dx11DepthStencilState)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY,
+ "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ }
- mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
+ mDepthStencilStateCache.insert(
+ std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++)));
- *outDSState = dx11DepthStencilState;
- return gl::Error(GL_NO_ERROR);
- }
+ *outDSState = dx11DepthStencilState;
+ return gl::Error(GL_NO_ERROR);
}
std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
index 0099b94a04d..82cb13903cf 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -36,7 +36,10 @@ class RenderStateCache : angle::NonCopyable
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 getDepthStencilState(const gl::DepthStencilState &dsState,
+ bool disableDepth,
+ bool disableStencil,
+ ID3D11DepthStencilState **outDSState);
gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
private:
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index ab01482cdfb..c4ca8f39b2e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -41,6 +41,7 @@
#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
@@ -194,8 +195,239 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
}
}
+void SetLineLoopIndices(GLuint *dest, size_t count)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ dest[i] = static_cast<GLuint>(i);
+ }
+ dest[count] = 0;
+}
+
+template <typename T>
+void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count)
+{
+ const T *srcPtr = static_cast<const T *>(indices);
+ for (size_t i = 0; i < count; ++i)
+ {
+ dest[i] = static_cast<GLuint>(srcPtr[i]);
+ }
+ dest[count] = static_cast<GLuint>(srcPtr[0]);
+}
+
+void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
+{
+ for (size_t i = 0; i < numTris; i++)
+ {
+ destPtr[i * 3 + 0] = 0;
+ destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
+ destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
+ }
+}
+
+template <typename T>
+void CopyLineLoopIndicesWithRestart(const GLvoid *indices,
+ size_t count,
+ GLenum indexType,
+ std::vector<GLuint> *bufferOut)
+{
+ GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
+ GLuint d3dRestartIndex = static_cast<GLuint>(d3d11::GetPrimitiveRestartIndex());
+ const T *srcPtr = static_cast<const T *>(indices);
+ Optional<GLuint> currentLoopStart;
+
+ bufferOut->clear();
+
+ for (size_t indexIdx = 0; indexIdx < count; ++indexIdx)
+ {
+ GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+ if (value == restartIndex)
+ {
+ if (currentLoopStart.valid())
+ {
+ bufferOut->push_back(currentLoopStart.value());
+ bufferOut->push_back(d3dRestartIndex);
+ currentLoopStart.reset();
+ }
+ }
+ else
+ {
+ bufferOut->push_back(value);
+ if (!currentLoopStart.valid())
+ {
+ currentLoopStart = value;
+ }
+ }
+ }
+
+ if (currentLoopStart.valid())
+ {
+ bufferOut->push_back(currentLoopStart.value());
+ }
+}
+
+void GetLineLoopIndices(const GLvoid *indices,
+ GLenum indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+ {
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ CopyLineLoopIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyLineLoopIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyLineLoopIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+
+ // For non-primitive-restart draws, the index count is static.
+ bufferOut->resize(static_cast<size_t>(count) + 1);
+
+ switch (indexType)
+ {
+ // Non-indexed draw
+ case GL_NONE:
+ SetLineLoopIndices(&(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_BYTE:
+ CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename T>
+void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris)
+{
+ const T *srcPtr = static_cast<const T *>(indices);
+
+ for (size_t i = 0; i < numTris; i++)
+ {
+ destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
+ destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
+ destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
+ }
+}
+
+template <typename T>
+void CopyTriangleFanIndicesWithRestart(const GLvoid *indices,
+ GLuint indexCount,
+ GLenum indexType,
+ std::vector<GLuint> *bufferOut)
+{
+ GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
+ GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT);
+ const T *srcPtr = static_cast<const T *>(indices);
+ Optional<GLuint> vertexA;
+ Optional<GLuint> vertexB;
+
+ bufferOut->clear();
+
+ for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
+ {
+ GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+ if (value == restartIndex)
+ {
+ bufferOut->push_back(d3dRestartIndex);
+ vertexA.reset();
+ vertexB.reset();
+ }
+ else
+ {
+ if (!vertexA.valid())
+ {
+ vertexA = value;
+ }
+ else if (!vertexB.valid())
+ {
+ vertexB = value;
+ }
+ else
+ {
+ bufferOut->push_back(vertexA.value());
+ bufferOut->push_back(vertexB.value());
+ bufferOut->push_back(value);
+ vertexB = value;
+ }
+ }
+ }
}
+void GetTriFanIndices(const GLvoid *indices,
+ GLenum indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != GL_NONE && usePrimitiveRestartFixedIndex)
+ {
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+
+ // For non-primitive-restart draws, the index count is static.
+ GLuint numTris = count - 2;
+ bufferOut->resize(numTris * 3);
+
+ switch (indexType)
+ {
+ // Non-indexed draw
+ case GL_NONE:
+ SetTriangleFanIndices(&(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_BYTE:
+ CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case GL_UNSIGNED_INT:
+ CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+} // anonymous namespace
+
void Renderer11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
{
ASSERT(resourceIndex < mCurrentSRVs.size());
@@ -238,6 +470,7 @@ void Renderer11::SRVCache::clear()
Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display),
mStateCache(this),
+ mStateManager(),
mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
mDebug(nullptr)
{
@@ -266,6 +499,9 @@ Renderer11::Renderer11(egl::Display *display)
mD3d11Module = NULL;
mDxgiModule = NULL;
+ mDCompModule = NULL;
+ mCreatedWithDeviceEXT = false;
+ mEGLDevice = nullptr;
mDevice = NULL;
mDeviceContext = NULL;
@@ -284,58 +520,69 @@ Renderer11::Renderer11(egl::Display *display)
ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
- const auto &attributes = mDisplay->getAttributeMap();
+ if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ const auto &attributes = mDisplay->getAttributeMap();
- EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
- EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMajorVersion =
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMinorVersion =
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
{
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
+ }
}
- }
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
{
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
+ }
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
+ }
}
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+
+ if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
{
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
}
- }
-
- if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
- }
- EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
- switch (requestedDeviceType)
- {
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
- mDriverType = D3D_DRIVER_TYPE_HARDWARE;
- break;
+ EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+ switch (requestedDeviceType)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_HARDWARE;
+ break;
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
- mDriverType = D3D_DRIVER_TYPE_WARP;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_WARP;
+ break;
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
- mDriverType = D3D_DRIVER_TYPE_REFERENCE;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_REFERENCE;
+ break;
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
- mDriverType = D3D_DRIVER_TYPE_NULL;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_NULL;
+ break;
- default:
- UNREACHABLE();
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+ {
+ mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
+ ASSERT(mEGLDevice != nullptr);
+ mCreatedWithDeviceEXT = true;
}
initializeDebugAnnotator();
@@ -352,68 +599,12 @@ Renderer11::~Renderer11()
egl::Error Renderer11::initialize()
{
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
- {
- SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
- TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
- mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
- mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
-
- if (mD3d11Module == nullptr || mDxgiModule == nullptr)
- {
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_MISSING_DEP,
- "Could not load D3D11 or DXGI library.");
- }
-
- // create the D3D11 device
- ASSERT(mDevice == nullptr);
- D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
-
- if (D3D11CreateDevice == nullptr)
- {
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_MISSING_DEP,
- "Could not retrieve D3D11CreateDevice address.");
- }
- }
-#endif
-
HRESULT result = S_OK;
-#ifdef _DEBUG
- {
- TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
- result = D3D11CreateDevice(
- NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
- static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
- &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
- }
- if (!mDevice || FAILED(result))
- {
- ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
- }
-
- if (!mDevice || FAILED(result))
-#endif
+ egl::Error error = initializeD3DDevice();
+ if (error.isError())
{
- SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
- TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
-
- result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(),
- static_cast<unsigned int>(mAvailableFeatureLevels.size()),
- D3D11_SDK_VERSION, &mDevice,
- &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
-
- // Cleanup done by destructor
- if (!mDevice || FAILED(result))
- {
- ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", static_cast<int>(result));
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_CREATEDEVICE_ERROR,
- "Could not create D3D11 device.");
- }
+ return error;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
@@ -562,6 +753,107 @@ egl::Error Renderer11::initialize()
return egl::Error(EGL_SUCCESS);
}
+egl::Error Renderer11::initializeD3DDevice()
+{
+ HRESULT result = S_OK;
+
+ if (!mCreatedWithDeviceEXT)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
+ {
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
+ TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
+
+ if (mD3d11Module == nullptr || mDxgiModule == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+ "Could not load D3D11 or DXGI library.");
+ }
+
+ // create the D3D11 device
+ ASSERT(mDevice == nullptr);
+ D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+
+ if (D3D11CreateDevice == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
+ "Could not retrieve D3D11CreateDevice address.");
+ }
+ }
+#endif
+
+#ifdef _DEBUG
+ {
+ TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
+ result = D3D11CreateDevice(
+ NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
+ &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+ }
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ }
+
+ if (!mDevice || FAILED(result))
+#endif
+ {
+ SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
+ TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
+
+ result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+ D3D11_SDK_VERSION, &mDevice,
+ &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+
+ // Cleanup done by destructor
+ if (!mDevice || FAILED(result))
+ {
+ ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
+ static_cast<int>(result));
+ return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
+ "Could not create D3D11 device.");
+ }
+ }
+ }
+ else
+ {
+ // We should use the inputted D3D11 device instead
+ void *device = nullptr;
+ egl::Error error = mEGLDevice->getDevice(&device);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
+ if (FAILED(d3dDevice->GetDeviceRemovedReason()))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
+ }
+
+ if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Inputted D3D11 device must be Feature Level 9_3 or greater.");
+ }
+
+ // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
+ mDevice = d3dDevice;
+ mDevice->AddRef();
+ mDevice->GetImmediateContext(&mDeviceContext);
+ mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
// do any one-time device initialization
// NOTE: this is also needed after a device lost/reset
// to reset the scene status and ensure the default states are reset.
@@ -600,6 +892,8 @@ void Renderer11::initializeDevice()
ASSERT(!mPixelTransfer);
mPixelTransfer = new PixelTransfer11(this);
+ mStateManager.initialize(mDeviceContext, &mStateCache, &mRenderer11DeviceCaps);
+
const gl::Caps &rendererCaps = getRendererCaps();
mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
@@ -697,6 +991,8 @@ egl::ConfigSet Renderer11::generateConfigs() const
const gl::Caps &rendererCaps = getRendererCaps();
const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+ const EGLint optimalSurfaceOrientation = EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
+
egl::ConfigSet configs;
for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
{
@@ -751,6 +1047,7 @@ egl::ConfigSet Renderer11::generateConfigs() const
config.transparentRedValue = 0;
config.transparentGreenValue = 0;
config.transparentBlueValue = 0;
+ config.optimalOrientation = optimalSurfaceOrientation;
configs.add(config);
}
@@ -778,6 +1075,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->querySurfacePointer = true;
outExtensions->windowFixedSize = true;
+ outExtensions->surfaceOrientation = true;
// D3D11 does not support present with dirty rectangles until DXGI 1.2.
outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
@@ -791,6 +1089,9 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->glTexture2DImage = true;
outExtensions->glTextureCubemapImage = true;
outExtensions->glRenderbufferImage = true;
+
+ outExtensions->flexibleSurfaceCompatibility = true;
+ outExtensions->directComposition = !!mDCompModule;
}
gl::Error Renderer11::flush()
@@ -842,9 +1143,14 @@ gl::Error Renderer11::finish()
return gl::Error(GL_NO_ERROR);
}
-SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
{
- return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
+ return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
+ orientation);
}
void *Renderer11::getD3DDevice()
@@ -1124,229 +1430,54 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
+gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode)
{
- if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
+ // Applies the render target surface, depth stencil surface, viewport rectangle and
+ // scissor rectangle to the renderer
+ const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+ ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
+ gl::Error error = applyRenderTarget(framebufferObject);
+ if (error.isError())
{
- ID3D11RasterizerState *dxRasterState = NULL;
- gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState);
- if (error.isError())
- {
- return error;
- }
-
- mDeviceContext->RSSetState(dxRasterState);
-
- mCurRasterState = rasterState;
+ return error;
}
- mForceSetRasterState = false;
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::setBlendState(const 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);
+ // Setting viewport state
+ mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
+ data.state->getFarPlane());
- mCurBlendState = blendState;
- mCurBlendColor = blendColor;
- mCurSampleMask = sampleMask;
- }
+ // Setting scissor state
+ mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
- mForceSetBlendState = false;
+ // Applying rasterizer state to D3D11 device
+ int samples = framebufferObject->getSamples(data);
+ gl::RasterizerState rasterizer = data.state->getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
- 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)
+ error = mStateManager.setRasterizerState(rasterizer);
+ if (error.isError())
{
- 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
- static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
- static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
- UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
-
- mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
-
- mCurDepthStencilState = depthStencilState;
- mCurStencilRef = stencilRef;
- mCurStencilBackRef = stencilBackRef;
+ return error;
}
- 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)
+ // Setting blend state
+ unsigned int mask = GetBlendSampleMask(data, samples);
+ error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(),
+ data.state->getBlendColor(), mask);
+ if (error.isError())
{
- 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;
+ return error;
}
- mForceSetScissor = false;
+ // Setting depth stencil state
+ error = mStateManager.setDepthStencilState(*data.state);
+ return error;
}
-void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport)
+void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask)
{
- gl::Rectangle actualViewport = viewport;
- float actualZNear = gl::clamp01(zNear);
- float actualZFar = gl::clamp01(zFar);
- if (ignoreViewport)
- {
- actualViewport.x = 0;
- actualViewport.y = 0;
- actualViewport.width = static_cast<int>(mRenderTargetDesc.width);
- actualViewport.height = static_cast<int>(mRenderTargetDesc.height);
- actualZNear = 0.0f;
- actualZFar = 1.0f;
- }
-
- bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
- actualZNear != mCurNear || actualZFar != mCurFar;
-
- if (viewportChanged)
- {
- const gl::Caps& caps = getRendererCaps();
-
- int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
- int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
- int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
- int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
-
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
- dxMaxViewportBoundsX = static_cast<int>(mRenderTargetDesc.width);
- dxMaxViewportBoundsY = static_cast<int>(mRenderTargetDesc.height);
- dxMinViewportBoundsX = 0;
- dxMinViewportBoundsY = 0;
- }
-
- int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
- int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
- int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
- int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
-
- D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
- dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
- dxViewport.Width = static_cast<float>(dxViewportWidth);
- dxViewport.Height = static_cast<float>(dxViewportHeight);
- dxViewport.MinDepth = actualZNear;
- dxViewport.MaxDepth = actualZFar;
-
- mDeviceContext->RSSetViewports(1, &dxViewport);
-
- mCurViewport = actualViewport;
- mCurNear = actualZNear;
- mCurFar = actualZFar;
-
- // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer).
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width;
- mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height;
- mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
- mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
- }
-
- 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);
-
- // Instanced pointsprite emulation requires ViewCoords to be defined in the
- // the vertex shader.
- mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
- mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
- mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
- mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
-
- mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
- mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
-
- mVertexConstants.depthRange[0] = actualZNear;
- mVertexConstants.depthRange[1] = actualZFar;
- mVertexConstants.depthRange[2] = actualZFar - actualZNear;
-
- mPixelConstants.depthRange[0] = actualZNear;
- mPixelConstants.depthRange[1] = actualZFar;
- mPixelConstants.depthRange[2] = actualZFar - actualZNear;
- }
-
- mForceSetViewport = false;
+ mStateManager.syncState(state, bitmask);
}
bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
@@ -1408,7 +1539,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
// Also extract the render target dimensions and view
unsigned int renderTargetWidth = 0;
unsigned int renderTargetHeight = 0;
- DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN;
ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
bool missingColorRenderTarget = true;
@@ -1426,7 +1556,8 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
// 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)
+ const gl::Extents &size = colorbuffer->getSize();
+ if (size.width == 0 || size.height == 0)
{
return gl::Error(GL_NO_ERROR);
}
@@ -1447,7 +1578,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
{
renderTargetWidth = renderTarget->getWidth();
renderTargetHeight = renderTarget->getHeight();
- renderTargetFormat = renderTarget->getDXGIFormat();
missingColorRenderTarget = false;
}
@@ -1487,7 +1617,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
{
renderTargetWidth = depthStencilRenderTarget->getWidth();
renderTargetHeight = depthStencilRenderTarget->getHeight();
- renderTargetFormat = depthStencilRenderTarget->getDXGIFormat();
}
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
@@ -1500,25 +1629,23 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index);
unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index);
}
+
+ unsigned int stencilSize = depthStencil->getStencilSize();
+ mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
}
// Apply the render target and depth stencil
- if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
+ if (!mDepthStencilInitialized ||
memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 ||
reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV)
{
mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
-
- mRenderTargetDesc.width = renderTargetWidth;
- mRenderTargetDesc.height = renderTargetHeight;
- mRenderTargetDesc.format = renderTargetFormat;
- mForceSetViewport = true;
- mForceSetScissor = true;
- mForceSetBlendState = true;
+ mStateManager.setViewportBounds(renderTargetWidth, renderTargetHeight);
+ mStateManager.forceSetBlendState();
if (!mDepthStencilInitialized)
{
- mForceSetRasterState = true;
+ mStateManager.forceSetRasterState();
}
for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++)
@@ -1526,7 +1653,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]);
}
mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV);
- mRenderTargetDescInitialized = true;
mDepthStencilInitialized = true;
}
@@ -1557,9 +1683,19 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLi
return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), sourceInfo);
}
-gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo)
+gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo,
+ SourceIndexData *sourceIndexInfo)
{
- gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo);
+ gl::VertexArray *vao = data.state->getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+ indexInfo, sourceIndexInfo,
+ data.state->isPrimitiveRestartEnabled());
if (error.isError())
{
return error;
@@ -1656,18 +1792,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
GLenum mode,
GLsizei count,
- GLsizei instances,
- bool usesPointSize)
+ GLsizei instances)
{
- bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
- if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused())
- {
- // 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.
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
- mDeviceContext->PSSetShader(NULL, NULL, 0);
+ if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused())
+ {
+ // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
+ // won't get the correct output. To work around this, draw with *only* the stream out
+ // first (no pixel shader) to feed the stream out buffers and then draw again with the
+ // geometry shader + pixel shader to rasterize the primitives.
+ mDeviceContext->PSSetShader(nullptr, nullptr, 0);
if (instances > 0)
{
@@ -1678,124 +1813,143 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
mDeviceContext->Draw(count, 0);
}
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
-
- rx::ShaderExecutableD3D *pixelExe = NULL;
+ rx::ShaderExecutableD3D *pixelExe = nullptr;
gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe);
if (error.isError())
{
return error;
}
- // Skip this step if we're doing rasterizer discard.
- if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize)
+ // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
+ if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard)
{
- ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
- ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+ return gl::Error(GL_NO_ERROR);
+ }
- // Retrieve the point sprite geometry shader
- rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
- ID3D11GeometryShader *geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
- mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
- ASSERT(geometryShader);
- mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+ ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
+ ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- if (instances > 0)
- {
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
+ // Retrieve the geometry shader.
+ rx::ShaderExecutableD3D *geometryExe = nullptr;
+ error =
+ programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr);
+ if (error.isError())
+ {
+ return error;
}
+ ID3D11GeometryShader *geometryShader =
+ (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
+ mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+ ASSERT(geometryShader);
+ mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
return gl::Error(GL_NO_ERROR);
}
- else if (mode == GL_LINE_LOOP)
+
+ if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances);
}
- else if (mode == GL_TRIANGLE_FAN)
+
+ if (mode == GL_TRIANGLE_FAN)
{
- return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
+ return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
}
- else if (instances > 0)
+
+ if (instances > 0)
{
mDeviceContext->DrawInstanced(count, instances, 0, 0);
return gl::Error(GL_NO_ERROR);
}
+
+ bool useInstancedPointSpriteEmulation =
+ programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
+
+ // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+ // Emulating instanced point sprites for FL9_3 requires the topology to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+ if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ {
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
else
{
- // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
- // Emulating instanced point sprites for FL9_3 requires the topology to be
- // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
- {
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
- return gl::Error(GL_NO_ERROR);
+ mDeviceContext->Draw(count, 0);
}
+ return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::drawElementsImpl(GLenum mode,
+gl::Error Renderer11::drawElementsImpl(const gl::Data &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- gl::Buffer *elementArrayBuffer,
- const TranslatedIndexData &indexInfo,
- GLsizei instances,
- bool usesPointSize)
+ GLsizei instances)
{
- bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
int minIndex = static_cast<int>(indexInfo.indexRange.start);
if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+ return drawLineLoop(data, count, type, indices, &indexInfo, instances);
}
- else if (mode == GL_TRIANGLE_FAN)
+
+ if (mode == GL_TRIANGLE_FAN)
{
- return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances);
+ return drawTriangleFan(data, count, type, indices, minIndex, instances);
}
- else if (instances > 0)
+
+ if (instances > 0)
{
mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
return gl::Error(GL_NO_ERROR);
}
+
+ // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+ // Emulating instanced point sprites for FL9_3 requires the topology to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+ const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
+ if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+ {
+ // The count parameter passed to drawElements represents the total number of instances
+ // to be rendered. Each instance is referenced by the bound index buffer from the
+ // the caller.
+ //
+ // Indexed pointsprite emulation replicates data for duplicate entries found
+ // in the index buffer.
+ // This is not an efficent rendering mechanism and is only used on downlevel renderers
+ // that do not support geometry shaders.
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
else
{
- // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
- // Emulating instanced point sprites for FL9_3 requires the topology to be
- // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
- {
- // The count parameter passed to drawElements represents the total number of instances
- // to be rendered. Each instance is referenced by the bound index buffer from the
- // the caller.
- //
- // Indexed pointsprite emulation replicates data for duplicate entries found
- // in the index buffer.
- // This is not an efficent rendering mechanism and is only used on downlevel renderers
- // that do not support geometry shaders.
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- mDeviceContext->DrawIndexed(count, 0, -minIndex);
- return gl::Error(GL_NO_ERROR);
- }
+ mDeviceContext->DrawIndexed(count, 0, -minIndex);
}
+ return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+gl::Error Renderer11::drawLineLoop(const gl::Data &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indexPointer,
+ const TranslatedIndexData *indexInfo,
+ int instances)
{
+ gl::VertexArray *vao = data.state->getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ const GLvoid *indices = indexPointer;
+
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
@@ -1831,7 +1985,11 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
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);
+ GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
+ data.state->isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
+
+ unsigned int spaceNeeded =
+ static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
if (error.isError())
{
@@ -1846,41 +2004,9 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
return error;
}
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
- unsigned int indexBufferOffset = offset;
-
- 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();
- }
+ // Copy over the converted index data.
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
+ sizeof(GLuint) * mScratchIndexDataBuffer.size());
error = mLineLoopIB->unmapBuffer();
if (error.isError())
@@ -1892,21 +2018,42 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
- if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+ mAppliedIBOffset != offset)
{
- mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
mAppliedIB = d3dIndexBuffer;
mAppliedIBFormat = indexFormat;
- mAppliedIBOffset = indexBufferOffset;
+ mAppliedIBOffset = offset;
}
- mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
+ INT baseVertexLocation = (indexInfo ? -static_cast<int>(indexInfo->indexRange.start) : 0);
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation);
+ }
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
+gl::Error Renderer11::drawTriangleFan(const gl::Data &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ int minIndex,
+ int instances)
{
+ gl::VertexArray *vao = data.state->getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ const GLvoid *indexPointer = indices;
+
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
@@ -1920,7 +2067,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return error;
}
- indices = bufferData + offset;
+ indexPointer = bufferData + offset;
}
if (!mTriangleFanIB)
@@ -1937,21 +2084,25 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 3);
- const unsigned int numTris = count - 2;
+ const GLuint numTris = count - 2;
if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
}
- const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
+ GetTriFanIndices(indexPointer, type, count, data.state->isPrimitiveRestartEnabled(),
+ &mScratchIndexDataBuffer);
+
+ const unsigned int spaceNeeded =
+ static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
if (error.isError())
{
return error;
}
- void* mappedMemory = NULL;
+ void *mappedMemory = nullptr;
unsigned int offset;
error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
if (error.isError())
@@ -1959,45 +2110,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return error;
}
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
- unsigned int indexBufferOffset = offset;
-
- 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();
- }
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
error = mTriangleFanIB->unmapBuffer();
if (error.isError())
@@ -2009,32 +2122,32 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
- if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset)
+ if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
+ mAppliedIBOffset != offset)
{
- mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset);
+ mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
mAppliedIB = d3dIndexBuffer;
mAppliedIBFormat = indexFormat;
- mAppliedIBOffset = indexBufferOffset;
+ mAppliedIBOffset = offset;
}
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
if (instances > 0)
{
- mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0);
}
else
{
- mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
+ mDeviceContext->DrawIndexed(indexCount, 0, -minIndex);
}
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::applyShaders(gl::Program *program,
- const gl::Framebuffer *framebuffer,
- bool rasterizerDiscard,
- bool transformFeedbackActive)
+gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode)
{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
const auto &inputLayout = programD3D->getCachedInputLayout();
ShaderExecutableD3D *vertexExe = NULL;
@@ -2044,30 +2157,39 @@ gl::Error Renderer11::applyShaders(gl::Program *program,
return error;
}
+ const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
ShaderExecutableD3D *pixelExe = NULL;
- error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
+ error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe);
if (error.isError())
{
return error;
}
- ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
+ ShaderExecutableD3D *geometryExe = nullptr;
+ error =
+ programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr);
+ if (error.isError())
+ {
+ return error;
+ }
ID3D11VertexShader *vertexShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : NULL);
ID3D11PixelShader *pixelShader = NULL;
// Skip pixel shader if we're doing rasterizer discard.
+ bool rasterizerDiscard = data.state->getRasterizerState().rasterizerDiscard;
if (!rasterizerDiscard)
{
pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : NULL);
}
ID3D11GeometryShader *geometryShader = NULL;
+ bool transformFeedbackActive = data.state->isTransformFeedbackActiveUnpaused();
if (transformFeedbackActive)
{
geometryShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : NULL);
}
- else if (mCurRasterState.pointDrawMode)
+ else
{
geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
}
@@ -2104,6 +2226,7 @@ gl::Error Renderer11::applyShaders(gl::Program *program,
}
gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray)
{
unsigned int totalRegisterCountVS = 0;
@@ -2242,28 +2365,32 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
}
- if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
+ const dx_VertexConstants &vertexConstants = mStateManager.getVertexConstants();
+ if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
{
ASSERT(mDriverConstantBufferVS != nullptr);
if (mDriverConstantBufferVS)
{
- mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
- memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants,
+ 16, 0);
+ memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants));
}
}
- if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
+ const dx_PixelConstants &pixelConstants = mStateManager.getPixelConstants();
+ if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
{
ASSERT(mDriverConstantBufferPS != nullptr);
if (mDriverConstantBufferPS)
{
- mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
- memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16,
+ 0);
+ memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants));
}
}
// GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
- if (programD3D.usesGeometryShader())
+ if (programD3D.usesGeometryShader(drawMode))
{
// needed for the point sprite geometry shader
if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
@@ -2284,13 +2411,7 @@ void Renderer11::markAllStateDirty()
{
TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
- for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
- {
- mAppliedRTVs[rtIndex] = DirtyPointer;
- }
- mAppliedDSV = DirtyPointer;
- mDepthStencilInitialized = false;
- mRenderTargetDescInitialized = false;
+ markRenderTargetStateDirty();
// We reset the current SRV data because it might not be in sync with D3D's state
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
@@ -2310,11 +2431,11 @@ void Renderer11::markAllStateDirty()
mForceSetPixelSamplerStates[fsamplerId] = true;
}
- mForceSetBlendState = true;
- mForceSetRasterState = true;
- mForceSetDepthStencilState = true;
- mForceSetScissor = true;
- mForceSetViewport = true;
+ mStateManager.forceSetBlendState();
+ mStateManager.forceSetDepthStencilState();
+ mStateManager.forceSetRasterState();
+ mStateManager.forceSetScissorState();
+ mStateManager.forceSetViewportState();
mAppliedIB = NULL;
mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
@@ -2354,6 +2475,16 @@ void Renderer11::markAllStateDirty()
mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}
+void Renderer11::markRenderTargetStateDirty()
+{
+ for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
+ {
+ mAppliedRTVs[rtIndex] = DirtyPointer;
+ }
+ mAppliedDSV = DirtyPointer;
+ mDepthStencilInitialized = false;
+}
+
void Renderer11::releaseDeviceResources()
{
mStateCache.clear();
@@ -2442,6 +2573,13 @@ void Renderer11::release()
releaseDeviceResources();
+ if (!mCreatedWithDeviceEXT)
+ {
+ // Only delete the device if the Renderer11 owns it
+ // Otherwise we should keep it around in case we try to reinitialize the renderer later
+ SafeDelete(mEGLDevice);
+ }
+
SafeRelease(mDxgiFactory);
SafeRelease(mDxgiAdapter);
@@ -2469,6 +2607,12 @@ void Renderer11::release()
mDxgiModule = NULL;
}
+ if (mDCompModule)
+ {
+ FreeLibrary(mDCompModule);
+ mDCompModule = NULL;
+ }
+
mCompiler.release();
}
@@ -2489,11 +2633,6 @@ bool Renderer11::resetDevice()
return true;
}
-VendorID Renderer11::getVendorId() const
-{
- return static_cast<VendorID>(mAdapterDescription.VendorId);
-}
-
std::string Renderer11::getRendererDescription() const
{
std::ostringstream rendererString;
@@ -2661,7 +2800,8 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::
// Use nearest filtering because source and destination are the same size for the direct
// copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+ error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
@@ -2712,7 +2852,8 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl
// Use nearest filtering because source and destination are the same size for the direct
// copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+ error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
@@ -2763,7 +2904,8 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::
// Use nearest filtering because source and destination are the same size for the direct
// copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+ error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
@@ -2814,7 +2956,8 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const
// Use nearest filtering because source and destination are the same size for the direct
// copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+ error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
+ destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
@@ -3018,9 +3161,12 @@ ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data)
return new ProgramD3D(data, this);
}
-gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable)
+gl::Error Renderer11::loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable)
{
switch (type)
{
@@ -3036,25 +3182,22 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
}
- if (transformFeedbackVaryings.size() > 0)
+ if (!streamOutVaryings.empty())
{
std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
- for (size_t i = 0; i < transformFeedbackVaryings.size(); i++)
+ soDeclaration.reserve(streamOutVaryings.size());
+
+ for (const auto &streamOutVarying : streamOutVaryings)
{
- const gl::LinkedVarying &varying = transformFeedbackVaryings[i];
- GLenum transposedType = gl::TransposeMatrixType(varying.type);
-
- for (unsigned int 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 = static_cast<BYTE>(gl::VariableColumnCount(transposedType));
- entry.OutputSlot = static_cast<BYTE>((separatedOutputBuffers ? i : 0));
- soDeclaration.push_back(entry);
- }
+ D3D11_SO_DECLARATION_ENTRY entry = {0};
+ entry.Stream = 0;
+ entry.SemanticName = streamOutVarying.semanticName.c_str();
+ entry.SemanticIndex = streamOutVarying.semanticIndex;
+ entry.StartComponent = 0;
+ entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
+ entry.OutputSlot = static_cast<BYTE>(
+ (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
+ soDeclaration.push_back(entry);
}
result = mDevice->CreateGeometryShaderWithStreamOutput(
@@ -3107,9 +3250,12 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
{
const char *profileType = NULL;
@@ -3152,6 +3298,15 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" ));
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
+ if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
+ {
+ // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
+ // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
+ // Using the [unroll] directive works around this, as does this D3DCompile flag.
+ configs.push_back(
+ CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
+ }
+
D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} };
ID3DBlob *binary = NULL;
@@ -3171,7 +3326,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
}
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
- transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
+ streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
@@ -3551,9 +3706,15 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
- RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
- bool colorBlit, bool depthBlit, bool stencilBlit)
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
+ const gl::Rectangle &drawRectIn,
+ RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget,
+ GLenum filter,
+ const gl::Rectangle *scissor,
+ bool colorBlit,
+ bool depthBlit,
+ bool stencilBlit)
{
// Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
// it should never be the case that both color and depth/stencil need to be blitted at
@@ -3619,13 +3780,94 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+ // From the spec:
+ // "The actual region taken from the read framebuffer is limited to the intersection of the
+ // source buffers being transferred, which may include the color buffer selected by the read
+ // buffer, the depth buffer, and / or the stencil buffer depending on mask."
+ // This means negative x and y are out of bounds, and not to be read from. We handle this here
+ // by internally scaling the read and draw rectangles.
+ gl::Rectangle readRect = readRectIn;
+ gl::Rectangle drawRect = drawRectIn;
+ auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset)
+ {
+ double readToDrawScale =
+ static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
+ return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+ };
+ if (readRect.x < 0)
+ {
+ int readOffset = -readRect.x;
+ readRect.x += readOffset;
+ readRect.width -= readOffset;
+
+ int drawOffset = readToDrawX(readOffset);
+ drawRect.x += drawOffset;
+ drawRect.width -= drawOffset;
+ }
+
+ auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset)
+ {
+ double readToDrawScale =
+ static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
+ return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
+ };
+ if (readRect.y < 0)
+ {
+ int readOffset = -readRect.y;
+ readRect.y += readOffset;
+ readRect.height -= readOffset;
+
+ int drawOffset = readToDrawY(readOffset);
+ drawRect.y += drawOffset;
+ drawRect.height -= drawOffset;
+ }
+
+ if (readRect.x1() < 0)
+ {
+ int readOffset = -readRect.x1();
+ readRect.width += readOffset;
+
+ int drawOffset = readToDrawX(readOffset);
+ drawRect.width += drawOffset;
+ }
+
+ if (readRect.y1() < 0)
+ {
+ int readOffset = -readRect.y1();
+ readRect.height += readOffset;
+
+ int drawOffset = readToDrawY(readOffset);
+ drawRect.height += drawOffset;
+ }
+
bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, 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;
+ const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat());
+ const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat());
+ const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
+
+ // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
+ // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
+
+ gl::Color<bool> colorMask;
+ colorMask.red = (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) &&
+ (dxgiFormatInfo.redBits > 0);
+ colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
+ (dxgiFormatInfo.greenBits > 0);
+ colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
+ (dxgiFormatInfo.blueBits > 0);
+ colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
+ (dxgiFormatInfo.alphaBits > 0);
+
+ // We only currently support masking off the alpha channel.
+ bool colorMaskingNeeded = colorMask.alpha;
+ ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
+
+ bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
+ readRect.width == readSize.width && readRect.y == 0 &&
+ readRect.height == readSize.height && drawRect.x == 0 &&
+ drawRect.width == drawSize.width && drawRect.y == 0 &&
+ drawRect.height == drawSize.height;
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
@@ -3636,14 +3878,13 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit);
gl::Error result(GL_NO_ERROR);
if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
- (!(depthBlit || stencilBlit) || wholeBufferCopy))
+ !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
{
UINT dstX = drawRect.x;
UINT dstY = drawRect.y;
@@ -3713,9 +3954,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
}
else
{
- GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format;
+ // We don't currently support masking off any other channel than alpha
+ bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
- scissor, format, filter);
+ scissor, destFormatInfo.format, filter, maskOffAlpha);
}
}
@@ -3919,4 +4161,23 @@ gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeSta
return gl::Error(GL_NO_ERROR);
}
+egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
+{
+ if (mEGLDevice == nullptr)
+ {
+ ASSERT(mDevice != nullptr);
+ mEGLDevice = new DeviceD3D();
+ egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+ EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
+
+ if (error.isError())
+ {
+ SafeDelete(mEGLDevice);
+ return error;
+ }
+ }
+
+ *device = static_cast<DeviceImpl *>(mEGLDevice);
+ return egl::Error(EGL_SUCCESS);
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index c0b3964a0d4..8759f8075b2 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -19,6 +19,7 @@
#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
namespace gl
{
@@ -110,7 +111,11 @@ class Renderer11 : public RendererD3D
gl::Error flush() override;
gl::Error finish() override;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) override;
virtual gl::Error generateSwizzle(gl::Texture *texture);
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
@@ -120,36 +125,30 @@ class Renderer11 : public RendererD3D
const std::vector<GLint> &vertexUniformBuffers,
const std::vector<GLint> &fragmentUniformBuffers) override;
- virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
- gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
- unsigned int sampleMask) override;
- 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);
+ gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
- gl::Error applyShaders(gl::Program *program,
- const gl::Framebuffer *framebuffer,
- bool rasterizerDiscard,
- bool transformFeedbackActive) override;
-
gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo);
- virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
+ gl::Error applyIndexBuffer(const gl::Data &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo,
+ SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual void markAllStateDirty();
+ void markRenderTargetStateDirty();
// lost device
bool testDeviceLost() override;
bool testDeviceResettable() override;
- VendorID getVendorId() const override;
std::string getRendererDescription() const override;
DeviceIdentifier getAdapterIdentifier() const override;
@@ -186,14 +185,20 @@ class Renderer11 : public RendererD3D
ProgramImpl *createProgram(const gl::Program::Data &data) override;
// Shader operations
- virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
- virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
- ShaderExecutableD3D **outExectuable);
- virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
+ gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
// Image operations
virtual ImageD3D *createImage();
@@ -236,6 +241,8 @@ class Renderer11 : public RendererD3D
ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+ RenderStateCache &getStateCache() { return mStateCache; }
+
Blit11 *getBlitter() { return mBlit; }
Clear11 *getClearer() { return mClear; }
@@ -270,24 +277,27 @@ class Renderer11 : public RendererD3D
void onSwap();
void onBufferDelete(const Buffer11 *deleted);
+ egl::Error getEGLDevice(DeviceImpl **device) override;
+
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
+ gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
+
+ void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLsizei count,
- GLsizei instances,
- bool usesPointSize) override;
- gl::Error drawElementsImpl(GLenum mode,
+ GLsizei instances) override;
+ gl::Error drawElementsImpl(const gl::Data &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- gl::Buffer *elementArrayBuffer,
- const TranslatedIndexData &indexInfo,
- GLsizei instances,
- bool usesPointSize) override;
+ GLsizei instances) override;
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
@@ -295,8 +305,18 @@ class Renderer11 : public RendererD3D
WorkaroundsD3D generateWorkarounds() const override;
- 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 drawLineLoop(const gl::Data &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ const TranslatedIndexData *indexInfo,
+ int instances);
+ gl::Error drawTriangleFan(const gl::Data &data,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ int minIndex,
+ int instances);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex &index);
@@ -307,11 +327,15 @@ class Renderer11 : public RendererD3D
HMODULE mD3d11Module;
HMODULE mDxgiModule;
+ HMODULE mDCompModule;
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
D3D_DRIVER_TYPE mDriverType;
+ bool mCreatedWithDeviceEXT;
+ DeviceD3D *mEGLDevice;
HLSLCompiler mCompiler;
+ egl::Error initializeD3DDevice();
void initializeDevice();
void releaseDeviceResources();
void release();
@@ -322,15 +346,6 @@ class Renderer11 : public RendererD3D
uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
uintptr_t mAppliedDSV;
bool mDepthStencilInitialized;
- bool mRenderTargetDescInitialized;
-
- struct RenderTargetDesc
- {
- size_t width;
- size_t height;
- DXGI_FORMAT format;
- };
- RenderTargetDesc mRenderTargetDesc;
// Currently applied sampler states
std::vector<bool> mForceSetVertexSamplerStates;
@@ -382,32 +397,7 @@ class Renderer11 : public RendererD3D
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView*> mNullSRVs;
- // 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;
+ StateManager11 mStateManager;
// Currently applied primitive topology
D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
@@ -434,7 +424,6 @@ class Renderer11 : public RendererD3D
uintptr_t mAppliedGeometryShader;
uintptr_t mAppliedPixelShader;
- dx_VertexConstants mVertexConstants;
dx_VertexConstants mAppliedVertexConstants;
ID3D11Buffer *mDriverConstantBufferVS;
ID3D11Buffer *mCurrentVertexConstantBuffer;
@@ -442,7 +431,6 @@ class Renderer11 : public RendererD3D
GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
- dx_PixelConstants mPixelConstants;
dx_PixelConstants mAppliedPixelConstants;
ID3D11Buffer *mDriverConstantBufferPS;
ID3D11Buffer *mCurrentPixelConstantBuffer;
@@ -487,6 +475,8 @@ class Renderer11 : public RendererD3D
char mDescription[128];
DXGIFactory *mDxgiFactory;
ID3D11Debug *mDebug;
+
+ std::vector<GLuint> mScratchIndexDataBuffer;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
new file mode 100644
index 00000000000..7351c2ad0c0
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -0,0 +1,582 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.cpp: Defines a class for caching D3D11 state
+
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+
+#include "common/BitSetIterator.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+StateManager11::StateManager11()
+ : mBlendStateIsDirty(false),
+ mCurBlendColor(0, 0, 0, 0),
+ mCurSampleMask(0),
+ mDepthStencilStateIsDirty(false),
+ mCurStencilRef(0),
+ mCurStencilBackRef(0),
+ mCurStencilSize(0),
+ mRasterizerStateIsDirty(false),
+ mScissorStateIsDirty(false),
+ mCurScissorEnabled(false),
+ mCurScissorRect(),
+ mViewportStateIsDirty(false),
+ mCurViewport(),
+ mCurNear(0.0f),
+ mCurFar(0.0f),
+ mViewportBounds(),
+ mRenderer11DeviceCaps(nullptr),
+ mDeviceContext(nullptr),
+ mStateCache(nullptr)
+{
+ mCurBlendState.blend = false;
+ mCurBlendState.sourceBlendRGB = GL_ONE;
+ mCurBlendState.destBlendRGB = GL_ZERO;
+ mCurBlendState.sourceBlendAlpha = GL_ONE;
+ mCurBlendState.destBlendAlpha = GL_ZERO;
+ mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
+ mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
+ mCurBlendState.colorMaskRed = true;
+ mCurBlendState.colorMaskBlue = true;
+ mCurBlendState.colorMaskGreen = true;
+ mCurBlendState.colorMaskAlpha = true;
+ mCurBlendState.sampleAlphaToCoverage = false;
+ mCurBlendState.dither = false;
+
+ mCurDepthStencilState.depthTest = false;
+ mCurDepthStencilState.depthFunc = GL_LESS;
+ mCurDepthStencilState.depthMask = true;
+ mCurDepthStencilState.stencilTest = false;
+ mCurDepthStencilState.stencilMask = true;
+ mCurDepthStencilState.stencilFail = GL_KEEP;
+ mCurDepthStencilState.stencilPassDepthFail = GL_KEEP;
+ mCurDepthStencilState.stencilPassDepthPass = GL_KEEP;
+ mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1);
+ mCurDepthStencilState.stencilBackFunc = GL_ALWAYS;
+ mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1);
+ mCurDepthStencilState.stencilBackFail = GL_KEEP;
+ mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
+ mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
+ mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1);
+
+ mCurRasterState.rasterizerDiscard = false;
+ mCurRasterState.cullFace = false;
+ mCurRasterState.cullMode = GL_BACK;
+ mCurRasterState.frontFace = GL_CCW;
+ mCurRasterState.polygonOffsetFill = false;
+ mCurRasterState.polygonOffsetFactor = 0.0f;
+ mCurRasterState.polygonOffsetUnits = 0.0f;
+ mCurRasterState.pointDrawMode = false;
+ mCurRasterState.multiSample = false;
+}
+
+StateManager11::~StateManager11()
+{
+}
+
+void StateManager11::initialize(ID3D11DeviceContext *deviceContext,
+ RenderStateCache *stateCache,
+ Renderer11DeviceCaps *renderer11DeviceCaps)
+{
+ mDeviceContext = deviceContext;
+ mStateCache = stateCache;
+ mRenderer11DeviceCaps = renderer11DeviceCaps;
+}
+
+void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
+{
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ mDepthStencilStateIsDirty = true;
+ }
+}
+
+void StateManager11::setViewportBounds(const int width, const int height)
+{
+ if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
+ (mViewportBounds.width != width || mViewportBounds.height != height))
+ {
+ mViewportBounds = gl::Extents(width, height, 1);
+ mViewportStateIsDirty = true;
+ }
+}
+
+void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+ blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_FUNCS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
+ blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
+ blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
+ blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ if (state.getBlendState().blend != mCurBlendState.blend)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ if (state.getBlendState().sampleAlphaToCoverage !=
+ mCurBlendState.sampleAlphaToCoverage)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ if (state.getBlendState().dither != mCurBlendState.dither)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_COLOR_MASK:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
+ blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
+ blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
+ blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ if (state.getBlendColor() != mCurBlendColor)
+ {
+ mBlendStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
+ depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
+ state.getStencilRef() != mCurStencilRef)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+ depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+ state.getStencilBackRef() != mCurStencilBackRef)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ if (state.getDepthStencilState().stencilWritemask !=
+ mCurDepthStencilState.stencilWritemask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ if (state.getDepthStencilState().stencilBackWritemask !=
+ mCurDepthStencilState.stencilBackWritemask)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
+ depthStencil.stencilPassDepthFail !=
+ mCurDepthStencilState.stencilPassDepthFail ||
+ depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ {
+ const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
+ if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+ depthStencil.stencilBackPassDepthFail !=
+ mCurDepthStencilState.stencilBackPassDepthFail ||
+ depthStencil.stencilBackPassDepthPass !=
+ mCurDepthStencilState.stencilBackPassDepthPass)
+ {
+ mDepthStencilStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ if (state.getRasterizerState().polygonOffsetFill !=
+ mCurRasterState.polygonOffsetFill)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const gl::RasterizerState &rasterState = state.getRasterizerState();
+ if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+ rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+ if (state.getRasterizerState().rasterizerDiscard !=
+ mCurRasterState.rasterizerDiscard)
+ {
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ if (state.getScissor() != mCurScissorRect)
+ {
+ mScissorStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ if (state.isScissorTestEnabled() != mCurScissorEnabled)
+ {
+ mScissorStateIsDirty = true;
+ // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
+ mRasterizerStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+ {
+ mViewportStateIsDirty = true;
+ }
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ mViewportStateIsDirty = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask)
+{
+ if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ID3D11BlendState *dxBlendState = nullptr;
+ gl::Error error = mStateCache->getBlendState(framebuffer, blendState, &dxBlendState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(dxBlendState != nullptr);
+
+ float blendColors[4] = {0.0f};
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ blendColors[0] = blendColor.red;
+ blendColors[1] = blendColor.green;
+ blendColors[2] = blendColor.blue;
+ blendColors[3] = blendColor.alpha;
+ }
+ else
+ {
+ blendColors[0] = blendColor.alpha;
+ blendColors[1] = blendColor.alpha;
+ blendColors[2] = blendColor.alpha;
+ blendColors[3] = blendColor.alpha;
+ }
+
+ mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+
+ mCurBlendState = blendState;
+ mCurBlendColor = blendColor;
+ mCurSampleMask = sampleMask;
+
+ mBlendStateIsDirty = false;
+
+ return error;
+}
+
+gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
+{
+ const auto &fbo = *glState.getDrawFramebuffer();
+
+ // Disable the depth test/depth write if we are using a stencil-only attachment.
+ // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
+ // nor write to the unused depth part of this emulated texture.
+ bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil());
+
+ // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
+ bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil());
+
+ // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
+ if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
+ disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
+ disableStencil == mCurDisableStencil.value())
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ const auto &depthStencilState = glState.getDepthStencilState();
+ int stencilRef = glState.getStencilRef();
+ int stencilBackRef = glState.getStencilBackRef();
+
+ // get the maximum size of the stencil ref
+ unsigned int maxStencil = 0;
+ if (depthStencilState.stencilTest && mCurStencilSize > 0)
+ {
+ maxStencil = (1 << mCurStencilSize) - 1;
+ }
+ ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
+ (depthStencilState.stencilBackWritemask & maxStencil));
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT((depthStencilState.stencilMask & maxStencil) ==
+ (depthStencilState.stencilBackMask & maxStencil));
+
+ ID3D11DepthStencilState *dxDepthStencilState = NULL;
+ gl::Error error = mStateCache->getDepthStencilState(depthStencilState, disableDepth,
+ disableStencil, &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
+ static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
+ "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
+ static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
+ "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
+ UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
+
+ mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
+
+ mCurDepthStencilState = depthStencilState;
+ mCurStencilRef = stencilRef;
+ mCurStencilBackRef = stencilBackRef;
+ mCurDisableDepth = disableDepth;
+ mCurDisableStencil = disableStencil;
+
+ mDepthStencilStateIsDirty = false;
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+ if (!mRasterizerStateIsDirty)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ ID3D11RasterizerState *dxRasterState = nullptr;
+ gl::Error error =
+ mStateCache->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mDeviceContext->RSSetState(dxRasterState);
+
+ mCurRasterState = rasterState;
+ mRasterizerStateIsDirty = false;
+
+ return error;
+}
+
+void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ if (!mScissorStateIsDirty)
+ return;
+
+ 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);
+ }
+
+ mCurScissorRect = scissor;
+ mCurScissorEnabled = enabled;
+ mScissorStateIsDirty = false;
+}
+
+void StateManager11::setViewport(const gl::Caps *caps,
+ const gl::Rectangle &viewport,
+ float zNear,
+ float zFar)
+{
+ if (!mViewportStateIsDirty)
+ return;
+
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+
+ int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
+ int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
+ int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
+ int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
+
+ if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
+ dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
+ dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
+ dxMinViewportBoundsX = 0;
+ dxMinViewportBoundsY = 0;
+ }
+
+ int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
+ int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
+ int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+ int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+ dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
+ dxViewport.Width = static_cast<float>(dxViewportWidth);
+ dxViewport.Height = static_cast<float>(dxViewportHeight);
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+
+ mDeviceContext->RSSetViewports(1, &dxViewport);
+
+ mCurViewport = viewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+
+ // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
+ // using viewAdjust (like the D3D9 renderer).
+ if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
+ 2 * (viewport.x - dxViewportTopLeftX)) /
+ dxViewport.Width;
+ mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
+ 2 * (viewport.y - dxViewportTopLeftY)) /
+ dxViewport.Height;
+ mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
+ mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
+ }
+
+ mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
+ mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
+ mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
+ mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
+
+ // Instanced pointsprite emulation requires ViewCoords to be defined in the
+ // the vertex shader.
+ mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
+ mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
+ mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
+ mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
+
+ mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+
+ mVertexConstants.depthRange[0] = actualZNear;
+ mVertexConstants.depthRange[1] = actualZFar;
+ mVertexConstants.depthRange[2] = actualZFar - actualZNear;
+
+ mPixelConstants.depthRange[0] = actualZNear;
+ mPixelConstants.depthRange[1] = actualZFar;
+ mPixelConstants.depthRange[2] = actualZFar - actualZNear;
+
+ mViewportStateIsDirty = false;
+}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
new file mode 100644
index 00000000000..b432c9d9ef3
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.h: Defines a class for caching D3D11 state
+
+#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+struct RenderTargetDesc;
+struct Renderer11DeviceCaps;
+
+class StateManager11 final : angle::NonCopyable
+{
+ public:
+ StateManager11();
+ ~StateManager11();
+
+ void initialize(ID3D11DeviceContext *deviceContext,
+ RenderStateCache *stateCache,
+ Renderer11DeviceCaps *renderer11DeviceCaps);
+
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+ gl::Error setBlendState(const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask);
+
+ gl::Error setDepthStencilState(const gl::State &glState);
+
+ gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+
+ void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+
+ void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
+
+ void forceSetBlendState() { mBlendStateIsDirty = true; }
+ void forceSetDepthStencilState() { mDepthStencilStateIsDirty = true; }
+ void forceSetRasterState() { mRasterizerStateIsDirty = true; }
+ void forceSetScissorState() { mScissorStateIsDirty = true; }
+ void forceSetViewportState() { mViewportStateIsDirty = true; }
+ void setViewportBounds(const int width, const int height);
+
+ const dx_VertexConstants &getVertexConstants() const { return mVertexConstants; }
+ const dx_PixelConstants &getPixelConstants() const { return mPixelConstants; }
+
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+ private:
+ // Blend State
+ bool mBlendStateIsDirty;
+ // TODO(dianx) temporary representation of a dirty bit. once we move enough states in,
+ // try experimenting with dirty bit instead of a bool
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+
+ // Currently applied depth stencil state
+ bool mDepthStencilStateIsDirty;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ unsigned int mCurStencilSize;
+ Optional<bool> mCurDisableDepth;
+ Optional<bool> mCurDisableStencil;
+
+ // Currenly applied rasterizer state
+ bool mRasterizerStateIsDirty;
+ gl::RasterizerState mCurRasterState;
+
+ // Currently applied scissor rectangle state
+ bool mScissorStateIsDirty;
+ bool mCurScissorEnabled;
+ gl::Rectangle mCurScissorRect;
+
+ // Currently applied viewport state
+ bool mViewportStateIsDirty;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+
+ // Things needed in viewport state
+ dx_VertexConstants mVertexConstants;
+ dx_PixelConstants mPixelConstants;
+
+ // Render target variables
+ gl::Extents mViewportBounds;
+
+ Renderer11DeviceCaps *mRenderer11DeviceCaps;
+ ID3D11DeviceContext *mDeviceContext;
+ RenderStateCache *mStateCache;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 8a4b6199d18..b6c9c667610 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -8,6 +8,8 @@
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include <EGL/eglext.h>
+
#include "libANGLE/features.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
@@ -29,40 +31,43 @@
namespace rx
{
-SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain11::SwapChain11(Renderer11 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
: SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mOrientation(orientation),
+ mAppCreatedShareHandle(mShareHandle != nullptr),
+ mSwapInterval(0),
mPassThroughResourcesInit(false),
+ mFirstSwap(true),
+ mSwapChain(nullptr),
+ mSwapChain1(nullptr),
+ mKeyedMutex(nullptr),
+ mBackBufferTexture(nullptr),
+ mBackBufferRTView(nullptr),
+ mBackBufferSRView(nullptr),
+ mNeedsOffscreenTexture(orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE),
+ mOffscreenTexture(nullptr),
+ mOffscreenRTView(nullptr),
+ mOffscreenSRView(nullptr),
+ mDepthStencilTexture(nullptr),
+ mDepthStencilDSView(nullptr),
+ mDepthStencilSRView(nullptr),
+ mQuadVB(nullptr),
+ mPassThroughSampler(nullptr),
+ mPassThroughIL(nullptr),
+ mPassThroughVS(nullptr),
+ mPassThroughPS(nullptr),
+ mPassThroughRS(nullptr),
mColorRenderTarget(this, renderer, false),
mDepthStencilRenderTarget(this, renderer, true)
{
- mHeight = -1;
- mWidth = -1;
- mAppCreatedShareHandle = mShareHandle != NULL;
- mSwapInterval = 0;
-
- mSwapChain = NULL;
- mSwapChain1 = nullptr;
-
- mKeyedMutex = nullptr;
-
- mBackBufferTexture = NULL;
- mBackBufferRTView = NULL;
-
- mOffscreenTexture = NULL;
- mOffscreenRTView = NULL;
- mOffscreenSRView = NULL;
-
- mDepthStencilTexture = NULL;
- mDepthStencilDSView = NULL;
- mDepthStencilSRView = NULL;
-
- mQuadVB = NULL;
- mPassThroughSampler = NULL;
- mPassThroughIL = NULL;
- mPassThroughVS = NULL;
- mPassThroughPS = NULL;
}
SwapChain11::~SwapChain11()
@@ -77,6 +82,7 @@ void SwapChain11::release()
SafeRelease(mKeyedMutex);
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
SafeRelease(mOffscreenTexture);
SafeRelease(mOffscreenRTView);
SafeRelease(mOffscreenSRView);
@@ -88,6 +94,7 @@ void SwapChain11::release()
SafeRelease(mPassThroughIL);
SafeRelease(mPassThroughVS);
SafeRelease(mPassThroughPS);
+ SafeRelease(mPassThroughRS);
if (!mAppCreatedShareHandle)
{
@@ -95,18 +102,47 @@ void SwapChain11::release()
}
}
-void SwapChain11::releaseOffscreenTexture()
+void SwapChain11::releaseOffscreenColorBuffer()
{
SafeRelease(mOffscreenTexture);
SafeRelease(mOffscreenRTView);
SafeRelease(mOffscreenSRView);
+}
+
+void SwapChain11::releaseOffscreenDepthBuffer()
+{
SafeRelease(mDepthStencilTexture);
SafeRelease(mDepthStencilDSView);
SafeRelease(mDepthStencilSRView);
}
-EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
+EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight)
{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(mNeedsOffscreenTexture);
+
TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
ID3D11Device *device = mRenderer->getDevice();
@@ -125,7 +161,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
const int previousWidth = mWidth;
const int previousHeight = mHeight;
- releaseOffscreenTexture();
+ releaseOffscreenColorBuffer();
const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
@@ -230,7 +266,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);
}
-
D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
@@ -250,10 +285,41 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
- const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+ if (previousOffscreenTexture != nullptr)
+ {
+ D3D11_BOX sourceBox = {0};
+ sourceBox.left = 0;
+ sourceBox.right = std::min(previousWidth, backbufferWidth);
+ sourceBox.top = std::max(previousHeight - backbufferHeight, 0);
+ sourceBox.bottom = previousHeight;
+ sourceBox.front = 0;
+ sourceBox.back = 1;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ const int yoffset = std::max(backbufferHeight - previousHeight, 0);
+ deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0,
+ previousOffscreenTexture, 0, &sourceBox);
+
+ SafeRelease(previousOffscreenTexture);
+
+ if (mSwapChain)
+ {
+ swapRect(0, 0, backbufferWidth, backbufferHeight);
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight)
+{
+ releaseOffscreenDepthBuffer();
if (mDepthBufferFormat != GL_NONE)
{
+ const d3d11::TextureFormat &depthBufferFormatInfo =
+ d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
depthStencilTextureDesc.Width = backbufferWidth;
depthStencilTextureDesc.Height = backbufferHeight;
@@ -273,7 +339,9 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
depthStencilTextureDesc.CPUAccessFlags = 0;
depthStencilTextureDesc.MiscFlags = 0;
- result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result =
+ device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
if (FAILED(result))
{
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
@@ -314,31 +382,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
}
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
-
- if (previousOffscreenTexture != NULL)
- {
- D3D11_BOX sourceBox = {0};
- sourceBox.left = 0;
- sourceBox.right = std::min(previousWidth, mWidth);
- sourceBox.top = std::max(previousHeight - mHeight, 0);
- sourceBox.bottom = previousHeight;
- sourceBox.front = 0;
- sourceBox.back = 1;
-
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- const int yoffset = std::max(mHeight - previousHeight, 0);
- deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
-
- SafeRelease(previousOffscreenTexture);
-
- if (mSwapChain)
- {
- swapRect(0, 0, mWidth, mHeight);
- }
- }
-
return EGL_SUCCESS;
}
@@ -358,11 +401,18 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
return EGL_SUCCESS;
}
+ // Don't resize unnecessarily
+ if (mWidth == backbufferWidth && mHeight == backbufferHeight)
+ {
+ return EGL_SUCCESS;
+ }
+
// Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
+ ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView);
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
+ SafeRelease(mBackBufferSRView);
// Resize swap chain
DXGI_SWAP_CHAIN_DESC desc;
@@ -398,14 +448,22 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
ASSERT(SUCCEEDED(result));
- }
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ }
- if (SUCCEEDED(result))
- {
- d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource");
+ }
}
- return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
}
DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
@@ -417,6 +475,20 @@ DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
{
+ mSwapInterval = static_cast<unsigned int>(swapInterval);
+ if (mSwapInterval > 4)
+ {
+ // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4]
+ // range
+ return EGL_BAD_PARAMETER;
+ }
+
+ // If the swap chain already exists, just resize
+ if (mSwapChain != nullptr)
+ {
+ return resize(backbufferWidth, backbufferHeight);
+ }
+
TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
ID3D11Device *device = mRenderer->getDevice();
@@ -432,17 +504,10 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
- mSwapInterval = static_cast<unsigned int>(swapInterval);
- if (mSwapInterval > 4)
- {
- // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
- return EGL_BAD_PARAMETER;
- }
-
// EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
if (backbufferWidth < 1 || backbufferHeight < 1)
{
- releaseOffscreenTexture();
+ releaseOffscreenColorBuffer();
return EGL_SUCCESS;
}
@@ -479,9 +544,15 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+
+ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view");
}
- return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
}
void SwapChain11::initPassThroughResources()
@@ -549,12 +620,50 @@ void SwapChain11::initPassThroughResources()
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+ // Use the default rasterizer state but without culling
+ D3D11_RASTERIZER_DESC rasterizerDesc;
+ rasterizerDesc.FillMode = D3D11_FILL_SOLID;
+ rasterizerDesc.CullMode = D3D11_CULL_NONE;
+ rasterizerDesc.FrontCounterClockwise = FALSE;
+ rasterizerDesc.DepthBias = 0;
+ rasterizerDesc.SlopeScaledDepthBias = 0.0f;
+ rasterizerDesc.DepthBiasClamp = 0.0f;
+ rasterizerDesc.DepthClipEnable = TRUE;
+ rasterizerDesc.ScissorEnable = FALSE;
+ rasterizerDesc.MultisampleEnable = FALSE;
+ rasterizerDesc.AntialiasedLineEnable = FALSE;
+ result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state");
+
mPassThroughResourcesInit = true;
}
// parameters should be validated/clamped by caller
EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = copyOffscreenToBackbuffer(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = present(x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mRenderer->onSwap();
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
if (!mSwapChain)
{
return EGL_SUCCESS;
@@ -562,7 +671,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
initPassThroughResources();
- ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// Set vertices
@@ -586,6 +694,16 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
float u2 = (x + width) / float(mWidth);
float v2 = (y + height) / float(mHeight);
+ // Invert the quad vertices depending on the surface orientation.
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
+ {
+ std::swap(x1, x2);
+ }
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0)
+ {
+ std::swap(y1, y2);
+ }
+
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
@@ -603,7 +721,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
- deviceContext->RSSetState(NULL);
+ deviceContext->RSSetState(mPassThroughRS);
// Apply shaders
deviceContext->IASetInputLayout(mPassThroughIL);
@@ -640,28 +758,54 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
mRenderer->unapplyRenderTargets();
mRenderer->markAllStateDirty();
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ UINT swapInterval = mSwapInterval;
#if ANGLE_VSYNC == ANGLE_DISABLED
- result = mSwapChain->Present(0, 0);
-#else
+ swapInterval = 0;
+#endif
+
+ HRESULT result = S_OK;
+
// Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
if (mSwapChain1 != nullptr)
{
- RECT rect =
+ if (mFirstSwap)
{
- static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
- static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)
- };
- DXGI_PRESENT_PARAMETERS params = { 1, &rect, nullptr, nullptr };
- result = mSwapChain1->Present1(mSwapInterval, 0, &params);
+ // Can't swap with a dirty rect if this swap chain has never swapped before
+ DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, &params);
+ }
+ else
+ {
+ RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+ static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+ DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, &params);
+ }
}
else
{
- result = mSwapChain->Present(mSwapInterval, 0);
+ result = mSwapChain->Present(swapInterval, 0);
}
-#endif
+
+ mFirstSwap = false;
+
+ // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
+ // target. Mark it dirty.
+ mRenderer->markRenderTargetStateDirty();
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
+ ID3D11Device *device = mRenderer->getDevice();
HRESULT removedReason = device->GetDeviceRemovedReason();
UNUSED_TRACE_VARIABLE(removedReason);
ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
@@ -677,24 +821,24 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
ERR("Present failed with error code 0x%08X", result);
}
- mRenderer->onSwap();
+ mNativeWindow.commitChange();
return EGL_SUCCESS;
}
ID3D11Texture2D *SwapChain11::getOffscreenTexture()
{
- return mOffscreenTexture;
+ return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
}
ID3D11RenderTargetView *SwapChain11::getRenderTarget()
{
- return mOffscreenRTView;
+ return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
}
ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
{
- return mOffscreenSRView;
+ return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView;
}
ID3D11DepthStencilView *SwapChain11::getDepthStencil()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
index 24c21e10e8c..583e29c3c81 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -20,8 +20,12 @@ class Renderer11;
class SwapChain11 : public SwapChainD3D
{
public:
- SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChain11(Renderer11 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation);
virtual ~SwapChain11();
EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
@@ -47,24 +51,36 @@ class SwapChain11 : public SwapChainD3D
private:
void release();
void initPassThroughResources();
- void releaseOffscreenTexture();
- EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight);
+
+ void releaseOffscreenColorBuffer();
+ void releaseOffscreenDepthBuffer();
+ EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight);
+
DXGI_FORMAT getSwapChainNativeFormat() const;
+ EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ EGLint present(EGLint x, EGLint y, EGLint width, EGLint height);
+
Renderer11 *mRenderer;
- EGLint mHeight;
EGLint mWidth;
+ EGLint mHeight;
+ const EGLint mOrientation;
bool mAppCreatedShareHandle;
unsigned int mSwapInterval;
bool mPassThroughResourcesInit;
+ bool mFirstSwap;
DXGISwapChain *mSwapChain;
IDXGISwapChain1 *mSwapChain1;
IDXGIKeyedMutex *mKeyedMutex;
ID3D11Texture2D *mBackBufferTexture;
ID3D11RenderTargetView *mBackBufferRTView;
+ ID3D11ShaderResourceView *mBackBufferSRView;
+ const bool mNeedsOffscreenTexture;
ID3D11Texture2D *mOffscreenTexture;
ID3D11RenderTargetView *mOffscreenRTView;
ID3D11ShaderResourceView *mOffscreenSRView;
@@ -78,6 +94,7 @@ class SwapChain11 : public SwapChainD3D
ID3D11InputLayout *mPassThroughIL;
ID3D11VertexShader *mPassThroughVS;
ID3D11PixelShader *mPassThroughPS;
+ ID3D11RasterizerState *mPassThroughRS;
SurfaceRenderTarget11 mColorRenderTarget;
SurfaceRenderTarget11 mDepthStencilRenderTarget;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 42b1b3b6585..580a59cf144 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -554,8 +554,9 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co
gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
Blit11 *blitter = mRenderer->getBlitter();
- return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
- gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
+ return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
+ NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format,
+ GL_LINEAR, false);
}
void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
@@ -649,7 +650,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
- UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength);
+ UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment,
+ unpack.rowLength, unpack.imageHeight);
+ GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels(
+ srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
@@ -669,8 +673,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
// TODO: fast path
LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type);
- loadFunction(width, height, depth,
- pixelData, srcRowPitch, srcDepthPitch,
+ loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, srcDepthPitch,
conversionBuffer->data(), bufferRowPitch, bufferDepthPitch);
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
@@ -2223,7 +2226,7 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO
{
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
- srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.MipLevels = mipLevels;
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py
new file mode 100644
index 00000000000..0985ba8c687
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py
@@ -0,0 +1,199 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_load_functions_table.py:
+# Code generation for the load function tables used for texture formats
+#
+
+import json
+
+template = """// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/loadimage_etc.h"
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+namespace
+{{
+
+// ES3 image loading functions vary based on:
+// - the GL internal format (supplied to glTex*Image*D)
+// - the GL data type given (supplied to glTex*Image*D)
+// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+// device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{{
+ UNIMPLEMENTED();
+}}
+
+void UnreachableLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{{
+ UNREACHABLE();
+}}
+
+}} // namespace
+
+// TODO we can replace these maps with more generated code
+const std::map<GLenum, LoadImageFunction> &GetLoadFunctionsMap(GLenum {internal_format},
+ DXGI_FORMAT {dxgi_format})
+{{
+ // clang-format off
+ switch ({internal_format})
+ {{
+{data}
+ default:
+ {{
+ static std::map<GLenum, LoadImageFunction> emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+ }}
+ }}
+ // clang-format on
+
+}} // GetLoadFunctionsMap
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+internal_format_param = 'internalFormat'
+dxgi_format_param = 'dxgiFormat'
+dxgi_format_unknown = "DXGI_FORMAT_UNKNOWN"
+
+def get_function_maps_string(typestr, function):
+ return ' loadMap[' + typestr + '] = ' + function + ';\n'
+
+def get_unknown_format_string(dxgi_to_type_map, dxgi_unknown_string):
+ if dxgi_unknown_string not in dxgi_to_type_map:
+ return ''
+
+ table_data = ''
+
+ for unknown_type_function in dxgi_to_type_map[dxgi_unknown_string]:
+ table_data += get_function_maps_string(unknown_type_function['type'], unknown_type_function['loadFunction'])
+
+ return table_data
+
+# Making map from dxgi to type map for a particular internalFormat
+def create_dxgi_to_type_map(dst, json_data, internal_format_str):
+ for type_item in sorted(json_data[internal_format_str].iteritems()):
+ for entry_in_type_item in type_item[1]:
+ dxgi_format_str = entry_in_type_item['dxgiFormat']
+
+ if dxgi_format_str not in dst:
+ dst[dxgi_format_str] = []
+
+ type_dxgi_load_function = entry_in_type_item.copy();
+ type_dxgi_load_function['type'] = type_item[0]
+ dst[dxgi_format_str].append(type_dxgi_load_function)
+
+def get_load_function_map_snippet(insert_map_string):
+ load_function_map_snippet = ''
+ load_function_map_snippet += ' static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {\n'
+ load_function_map_snippet += ' std::map<GLenum, LoadImageFunction> loadMap;\n'
+ load_function_map_snippet += insert_map_string
+ load_function_map_snippet += ' return loadMap;\n'
+ load_function_map_snippet += ' }();\n\n'
+ load_function_map_snippet += ' return loadFunctionsMap;\n'
+
+ return load_function_map_snippet
+
+def parse_json_into_switch_string(json_data):
+ table_data = ''
+ for internal_format_item in sorted(json_data.iteritems()):
+ internal_format_str = internal_format_item[0]
+ table_data += ' case ' + internal_format_str + ':\n'
+ table_data += ' {\n'
+ table_data += ' switch (' + dxgi_format_param + ')\n'
+ table_data += ' {\n'
+
+ dxgi_to_type_map = {};
+ create_dxgi_to_type_map(dxgi_to_type_map, json_data, internal_format_str)
+
+ dxgi_unknown_str = get_unknown_format_string(dxgi_to_type_map, dxgi_format_unknown);
+
+ for dxgi_format_item in sorted(dxgi_to_type_map.iteritems()):
+ dxgi_format_str = dxgi_format_item[0]
+
+ # Main case statements
+ table_data += ' case ' + dxgi_format_str + ':\n'
+ table_data += ' {\n'
+ insert_map_string = ''
+ types_already_in_loadmap = set()
+ for type_function in sorted(dxgi_format_item[1]):
+ # type_function['requiresConversion'] element is not in use at the moment but may be needed later
+ insert_map_string += get_function_maps_string(type_function['type'], type_function['loadFunction'])
+ types_already_in_loadmap.add(type_function['type'])
+
+ # DXGI_FORMAT_UNKNOWN add ons
+ if dxgi_format_unknown in dxgi_to_type_map:
+ for unknown_type_function in dxgi_to_type_map[dxgi_format_unknown]:
+ # Check that it's not already in the loadmap so it doesn't override the value
+ if unknown_type_function['type'] not in types_already_in_loadmap:
+ insert_map_string += get_function_maps_string(unknown_type_function['type'], unknown_type_function['loadFunction'])
+
+ table_data += get_load_function_map_snippet(insert_map_string)
+ table_data += ' }\n'
+
+ table_data += ' default:\n'
+
+ if dxgi_unknown_str:
+ table_data += ' {\n'
+ table_data += get_load_function_map_snippet(dxgi_unknown_str)
+ table_data += ' }\n'
+ else:
+ table_data += ' break;\n'
+ table_data += ' }\n'
+ table_data += ' }\n'
+
+ return table_data
+
+with open('load_functions_data.json') as functions_json_file:
+ functions_data = functions_json_file.read();
+ functions_json_file.close()
+ json_data = json.loads(functions_data)
+
+ table_data = parse_json_into_switch_string(json_data)
+ output = template.format(internal_format = internal_format_param,
+ dxgi_format = dxgi_format_param,
+ data=table_data)
+
+ with open('load_functions_table_autogen.cpp', 'wt') as out_file:
+ out_file.write(output)
+ out_file.close()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py
new file mode 100644
index 00000000000..212b19edd16
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_swizzle_format_table.py
@@ -0,0 +1,133 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_swizzle_format_table.py:
+# Code generation for the swizzle format table used for texture formats
+#
+
+import json
+import pprint
+
+template = """// GENERATED FILE - DO NOT EDIT
+// Generated by gen_swizzle_format_table.py using data from swizzle_format_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// swizzle_format_info:
+// Provides information for swizzle format and a map from type->formatinfo
+//
+
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+
+#include <GLES3/gl3.h>
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE)
+{{
+}}
+
+SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
+ : maxComponentSize(maxComponentSize), componentType(componentType)
+{{
+}}
+
+bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const
+{{
+ return (maxComponentSize != other.maxComponentSize)
+ ? (maxComponentSize < other.maxComponentSize)
+ : (componentType < other.componentType);
+}}
+
+SwizzleFormatInfo::SwizzleFormatInfo()
+ : mTexFormat(DXGI_FORMAT_UNKNOWN),
+ mSRVFormat(DXGI_FORMAT_UNKNOWN),
+ mRTVFormat(DXGI_FORMAT_UNKNOWN)
+{{
+}}
+
+SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat)
+ : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
+{{
+}}
+
+const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType)
+{{
+ // clang-format off
+ switch ({component_type_param})
+ {{
+{data}
+ default:
+ {{
+ static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return defaultInfo;
+ }}
+ }}
+ // clang-format on
+
+}} // GetSwizzleFormatInfo
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+max_bits_param = 'maxBits'
+component_type_param = 'componentType'
+
+tex_format_key = 'texFormat'
+srv_format_key = 'srvFormat'
+rtv_format_key = 'rtvFormat'
+
+
+def parse_json_into_switch_string(json_data):
+ table_data = ''
+ for component_type in sorted(json_data.iteritems()):
+ type_str = component_type[0]
+ table_data += ' case ' + type_str + ':\n'
+ table_data += ' {\n'
+
+ table_data += ' switch (' + max_bits_param + ')\n'
+ table_data += ' {\n'
+
+ for max_width_item in sorted(json_data[type_str].iteritems()):
+ max_width = max_width_item[0]
+ table_data += ' case ' + max_width + ':\n'
+ table_data += ' {\n'
+ table_data += ' static const SwizzleFormatInfo formatInfo(' + json_data[type_str][max_width][tex_format_key] + ',\n'
+ table_data += ' ' + json_data[type_str][max_width][srv_format_key] + ',\n'
+ table_data += ' ' + json_data[type_str][max_width][rtv_format_key] + ');\n'
+ table_data += ' return formatInfo;\n'
+
+ table_data += ' }\n'
+ table_data += ' default:\n'
+ table_data += ' break;\n'
+ table_data += ' }\n'
+ table_data += ' }\n'
+
+ return table_data
+
+with open('swizzle_format_data.json') as functions_json_file:
+ functions_data = functions_json_file.read();
+ functions_json_file.close()
+ json_data = json.loads(functions_data)
+
+ table_data = parse_json_into_switch_string(json_data)
+ output = template.format(component_type_param=component_type_param,
+ data=table_data)
+
+ with open('swizzle_format_info_autogen.cpp', 'wt') as out_file:
+ out_file.write(output)
+ out_file.close()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
new file mode 100644
index 00000000000..d0ad86b62ed
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
@@ -0,0 +1,303 @@
+#!/usr/bin/python
+# Copyright 2015 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# gen_texture_format_table.py:
+# Code generation for texture format map
+#
+
+import json
+import pprint
+
+template = """// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_texture_format_table.py using data from texture_format_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+// Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h"
+#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+namespace rx
+{{
+
+namespace d3d11
+{{
+
+namespace
+{{
+
+typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &);
+
+bool AnyDevice(const Renderer11DeviceCaps &deviceCaps)
+{{
+ return true;
+}}
+
+bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{{
+ return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}}
+
+bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{{
+ return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}}
+
+template <DXGI_FORMAT format, bool requireSupport>
+bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps)
+{{
+ // Must support texture, SRV and RTV support
+ UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+ D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+
+ if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
+ {{
+ mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+ }}
+
+ bool fullSupport = false;
+ if (format == DXGI_FORMAT_B5G6R5_UNORM)
+ {{
+ // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+ // check anyway.
+ mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
+ }}
+ else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+ {{
+ fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
+ }}
+ else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {{
+ fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
+ }}
+ else
+ {{
+ UNREACHABLE();
+ return false;
+ }}
+
+ // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below,
+ // which maps GL formats to DXGI formats.
+ if (requireSupport)
+ {{
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *IS* supported.
+ // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+ // DXGI_FORMAT_B5G5R5A1 is supported.
+ // In this case, we should only return 'true' if the format *IS* supported.
+ return fullSupport;
+ }}
+ else
+ {{
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *ISN'T* supported.
+ // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if
+ // DXGI_FORMAT_B5G5R5A1 isn't supported.
+ // In this case, we should only return 'true' if the format *ISN'T* supported.
+ return !fullSupport;
+ }}
+}}
+
+// End Format Support Functions
+
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This function allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+const TextureFormat GetD3D11FormatInfo(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);
+
+ const SwizzleFormatInfo &swizzleInfo =
+ GetSwizzleFormatInfo(maxBits, formatInfo.componentType);
+ 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
+ info.dataInitializerFunction = GetInternalFormatInitializer(internalFormat, texFormat);
+ // Gather all the load functions for this internal format
+ info.loadFunctions = GetLoadFunctionsMap(internalFormat, texFormat);
+
+ ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE);
+
+ return info;
+}}
+
+}} // namespace
+
+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()
+{{
+}}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps)
+{{
+ // clang-format off
+ switch (internalFormat)
+ {{
+{data}
+ default:
+ break;
+ }}
+ // clang-format on
+
+ static const TextureFormat defaultInfo;
+ return defaultInfo;
+}} // GetTextureFormatInfo
+
+}} // namespace d3d11
+
+}} // namespace rx
+"""
+
+def get_texture_format_item(idx, texture_format):
+ table_data = '';
+
+ tex_format = texture_format["texFormat"] if "texFormat" in texture_format else "DXGI_FORMAT_UNKNOWN"
+ srv_format = texture_format["srvFormat"] if "srvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN"
+ rtv_format = texture_format["rtvFormat"] if "rtvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN"
+ dsv_format = texture_format["dsvFormat"] if "dsvFormat" in texture_format else "DXGI_FORMAT_UNKNOWN"
+ requirements_fn = texture_format["requirementsFcn"] if "requirementsFcn" in texture_format else "AnyDevice"
+
+ if idx == 0:
+ table_data += ' if (' + requirements_fn + '(renderer11DeviceCaps))\n'
+ else:
+ table_data += ' else if (' + requirements_fn + '(renderer11DeviceCaps))\n'
+ table_data += ' {\n'
+ table_data += ' static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,\n'
+ table_data += ' ' + tex_format + ',\n'
+ table_data += ' ' + srv_format + ',\n'
+ table_data += ' ' + rtv_format + ',\n'
+ table_data += ' ' + dsv_format + ');\n'
+ table_data += ' return textureFormat;\n'
+ table_data += ' }\n'
+
+ return table_data
+
+def parse_json_into_switch_string(json_data):
+ table_data = ''
+ for internal_format_item in sorted(json_data.iteritems()):
+ internal_format = internal_format_item[0]
+ table_data += ' case ' + internal_format + ':\n'
+ table_data += ' {\n'
+
+ for idx, texture_format in enumerate(sorted(json_data[internal_format])):
+ table_data += get_texture_format_item(idx, texture_format)
+
+ table_data += ' else\n'
+ table_data += ' {\n'
+ table_data += ' break;\n'
+ table_data += ' }\n'
+ table_data += ' }\n'
+
+ return table_data
+
+with open('texture_format_data.json') as texture_format_json_file:
+ texture_format_data = texture_format_json_file.read();
+ texture_format_json_file.close()
+ json_data = json.loads(texture_format_data)
+
+ table_data = parse_json_into_switch_string(json_data)
+ output = template.format(data=table_data)
+
+ with open('texture_format_table_autogen.cpp', 'wt') as out_file:
+ out_file.write(output)
+ out_file.close()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp
new file mode 100644
index 00000000000..adb20a5e60f
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp
@@ -0,0 +1,170 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// internal_format_initializer_table:
+// Contains table to go from internal format and dxgi format to initializer function
+// for TextureFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+// TODO: This should be generated by a JSON file
+InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat,
+ DXGI_FORMAT dxgiFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_RGB8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB565:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ return Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ return Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000,
+ gl::Float32One>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ return Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ return Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ return Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ return Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001>;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ return Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001>;
+ }
+ default:
+ break;
+ }
+ }
+ default:
+ {
+ return nullptr;
+ }
+ }
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h
new file mode 100644
index 00000000000..2d538e1d82f
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// internal_format_initializer_table:
+// Contains table to go from internal format and dxgi format to initializer function
+// for TextureFormat
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include <map>
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat,
+ DXGI_FORMAT dxgiFormat);
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
new file mode 100644
index 00000000000..cb1d8595a23
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
@@ -0,0 +1,1107 @@
+{
+ "GL_RG8_SNORM": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,2>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_SRGB8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA8I": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_R8_SNORM": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,1>",
+ "dxgiFormat": "DXGI_FORMAT_R8_SNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGBA8_SNORM": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_R16I": {
+ "GL_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLshort,1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2SRGBA8ToSRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2RGB8A1ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB32UI": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLuint,0x00000001>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_ALPHA32F_EXT": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadA32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R16UI": {
+ "GL_UNSIGNED_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLushort,1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB9_E5": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadRGB16FToRGB9E5",
+ "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_INT_5_9_9_9_REV": [
+ {
+ "loadFunction": "LoadToNative<GLuint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadRGB32FToRGB9E5",
+ "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadRGB16FToRGB9E5",
+ "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_R11_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadEACR11ToR8",
+ "dxgiFormat": "DXGI_FORMAT_R8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA32UI": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadToNative<GLuint,4>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RG8UI": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,2>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE32F_EXT": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadL32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2SRGB8A1ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R16F": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "Load32FTo16F<1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGBA8UI": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_BGRA4_ANGLEX": {
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": [
+ {
+ "loadFunction": "LoadRGBA4ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGBA16F": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,4>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "Load32FTo16F<4>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,4>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE8_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadL8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadCompressedToNative<4,4,16>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_5_6_5": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB5_A1": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": [
+ {
+ "loadFunction": "LoadRGB10A2ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_5_5_5_1": [
+ {
+ "loadFunction": "LoadRGB5A1ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ },
+ {
+ "loadFunction": "LoadRGB5A1ToA1RGB5",
+ "dxgiFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB16UI": {
+ "GL_UNSIGNED_SHORT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLushort,0x0001>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_BGRA_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGB8_ETC2": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2RGB8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA32F": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLfloat,4>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGBA32I": {
+ "GL_INT": [
+ {
+ "loadFunction": "LoadToNative<GLint,4>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE8_ALPHA8_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadLA8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,2>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB10_A2": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": [
+ {
+ "loadFunction": "LoadToNative<GLuint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_COMPRESSED_SIGNED_RG11_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadEACRG11SToRG8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_DEPTH_COMPONENT16": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadR32ToR16",
+ "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLushort,1>",
+ "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS",
+ "requiresConversion": "false"
+ },
+ {
+ "loadFunction": "LoadToNative<GLushort,1>",
+ "dxgiFormat": "DXGI_FORMAT_D16_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB32I": {
+ "GL_INT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLint,0x00000001>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,1>",
+ "dxgiFormat": "DXGI_FORMAT_R8_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB32F": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLfloat,gl::Float32One>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R11F_G11F_B10F": {
+ "GL_UNSIGNED_INT_10F_11F_11F_REV": [
+ {
+ "loadFunction": "LoadToNative<GLuint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadRGB16FToRG11B10F",
+ "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadRGB32FToRG11B10F",
+ "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadRGB16FToRG11B10F",
+ "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_LUMINANCE_ALPHA": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadLA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadLA32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadLA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA16I": {
+ "GL_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLshort,4>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_R8I": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,1>",
+ "dxgiFormat": "DXGI_FORMAT_R8_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB8_SNORM": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLbyte,0x7F>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG32F": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLfloat,2>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_DEPTH_COMPONENT32F": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLfloat,1>",
+ "dxgiFormat": "DXGI_FORMAT_R32_TYPELESS",
+ "requiresConversion": "false"
+ },
+ {
+ "loadFunction": "UnimplementedLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG32I": {
+ "GL_INT": [
+ {
+ "loadFunction": "LoadToNative<GLint,2>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_ALPHA8_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,1>",
+ "dxgiFormat": "DXGI_FORMAT_A8_UNORM",
+ "requiresConversion": "false"
+ },
+ {
+ "loadFunction": "LoadA8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG32UI": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadToNative<GLuint,2>",
+ "dxgiFormat": "DXGI_FORMAT_R32G32_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGBA16UI": {
+ "GL_UNSIGNED_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLushort,4>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2RGBA8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB8I": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLbyte,0x01>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_SRGB8_ETC2": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC2SRGB8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_DEPTH32F_STENCIL8": {
+ "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": [
+ {
+ "loadFunction": "LoadToNative<GLuint,2>",
+ "dxgiFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "requiresConversion": "false"
+ },
+ {
+ "loadFunction": "UnimplementedLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG8I": {
+ "GL_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLbyte,2>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_R32UI": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadToNative<GLuint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R32_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_BGR5_A1_ANGLEX": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": [
+ {
+ "loadFunction": "LoadRGB5A1ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RG11_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadEACRG11ToRG8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_SRGB8_ALPHA8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE_ALPHA16F_EXT": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadLA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadLA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_4_4_4_4": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_5_5_5_1": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_DEPTH24_STENCIL8": {
+ "GL_UNSIGNED_INT_24_8": [
+ {
+ "loadFunction": "LoadR32ToR24G8",
+ "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "requiresConversion": "true"
+ },
+ {
+ "loadFunction": "LoadR32ToR24G8",
+ "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB16I": {
+ "GL_SHORT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLshort,0x0001>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R8UI": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,1>",
+ "dxgiFormat": "DXGI_FORMAT_R8_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_ALPHA": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadA32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB16F": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadRGB32FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_SIGNED_R11_EAC": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadEACR11SToR8",
+ "dxgiFormat": "DXGI_FORMAT_R8_SNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadCompressedToNative<4,4,8>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadCompressedToNative<4,4,8>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_STENCIL_INDEX8": {
+ "DXGI_FORMAT_R24G8_TYPELESS": [
+ {
+ "loadFunction": "UnimplementedLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "DXGI_FORMAT_D24_UNORM_S8_UINT": [
+ {
+ "loadFunction": "UnimplementedLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_LUMINANCE_ALPHA32F_EXT": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadLA32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB8UI": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLubyte,0x01>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_DEPTH_COMPONENT24": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadR32ToR24G8",
+ "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "requiresConversion": "true"
+ },
+ {
+ "loadFunction": "LoadR32ToR24G8",
+ "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R32I": {
+ "GL_INT": [
+ {
+ "loadFunction": "LoadToNative<GLint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R32_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_DEPTH_COMPONENT32_OES": {
+ "GL_UNSIGNED_INT": [
+ {
+ "loadFunction": "LoadR32ToR24G8",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_R32F": {
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLfloat,1>",
+ "dxgiFormat": "DXGI_FORMAT_R32_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RG16F": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,2>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "Load32FTo16F<2>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadToNative<GLhalf,2>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_RGB565": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_5_6_5": [
+ {
+ "loadFunction": "LoadR5G6B5ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ },
+ {
+ "loadFunction": "LoadToNative<GLushort,1>",
+ "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE16F_EXT": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadL16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadL16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG16UI": {
+ "GL_UNSIGNED_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLushort,2>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadCompressedToNative<4,4,16>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RG16I": {
+ "GL_SHORT": [
+ {
+ "loadFunction": "LoadToNative<GLshort,2>",
+ "dxgiFormat": "DXGI_FORMAT_R16G16_SINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_BGRA8_EXT": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_ALPHA16F_EXT": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadA16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA4": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "false"
+ }
+ ],
+ "GL_UNSIGNED_SHORT_4_4_4_4": [
+ {
+ "loadFunction": "LoadRGBA4ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ },
+ {
+ "loadFunction": "LoadRGBA4ToARGB4",
+ "dxgiFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGBA8": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadToNative<GLubyte,4>",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_LUMINANCE": {
+ "GL_HALF_FLOAT": [
+ {
+ "loadFunction": "LoadL16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "UnreachableLoadFunction",
+ "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_FLOAT": [
+ {
+ "loadFunction": "LoadL32FToRGBA32F",
+ "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "requiresConversion": "true"
+ }
+ ],
+ "GL_HALF_FLOAT_OES": [
+ {
+ "loadFunction": "LoadL16FToRGBA16F",
+ "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "requiresConversion": "true"
+ }
+ ]
+ },
+ "GL_RGB10_A2UI": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": [
+ {
+ "loadFunction": "LoadToNative<GLuint,1>",
+ "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "requiresConversion": "false"
+ }
+ ]
+ },
+ "GL_ETC1_RGB8_OES": {
+ "GL_UNSIGNED_BYTE": [
+ {
+ "loadFunction": "LoadETC1RGB8ToRGBA8",
+ "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requiresConversion": "true"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h
new file mode 100644
index 00000000000..60ab41fd838
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains load functions table depending on internal format and dxgi format
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
+
+#include <map>
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+const std::map<GLenum, LoadImageFunction> &GetLoadFunctionsMap(GLenum internalFormat,
+ DXGI_FORMAT dxgiFormat);
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
new file mode 100644
index 00000000000..788f792e7b2
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
@@ -0,0 +1,2079 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/loadimage_etc.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+namespace
+{
+
+// ES3 image loading functions vary based on:
+// - the GL internal format (supplied to glTex*Image*D)
+// - the GL data type given (supplied to glTex*Image*D)
+// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+// device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNIMPLEMENTED();
+}
+
+void UnreachableLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNREACHABLE();
+}
+
+} // namespace
+
+// TODO we can replace these maps with more generated code
+const std::map<GLenum, LoadImageFunction> &GetLoadFunctionsMap(GLenum internalFormat,
+ DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadA32FToRGBA32F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_ALPHA16F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadA16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_ALPHA32F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadA32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadA32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_ALPHA8_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadA8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_BGR5_A1_ANGLEX:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadRGB5A1ToRGBA8;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadRGB5A1ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_BGRA4_ANGLEX:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadRGBA4ToRGBA8;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadRGBA4ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_BGRA8_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_BGRA_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_COMPRESSED_R11_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadEACR11ToR8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadEACRG11ToRG8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGB8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGB8A1ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2RGBA8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,16>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadCompressedToNative<4,4,8>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadEACR11SToR8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadEACRG11SToRG8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGBA8ToSRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGB8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC2SRGB8A1ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH24_STENCIL8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT_24_8] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT_24_8] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadToNative<GLuint,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadR32ToR16;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadToNative<GLfloat,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadR32ToR24G8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadETC1RGB8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_LUMINANCE:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadL32FToRGBA32F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE16F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadL16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadL16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE32F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadL32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadL32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadLA8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadLA8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE8_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadL8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadL8ToRGBA8;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE_ALPHA:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadLA32FToRGBA32F;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadLA16FToRGBA16F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadLA16FToRGBA16F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadLA32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadLA32FToRGBA32F;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_R11F_G11F_B10F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadRGB16FToRG11B10F;
+ loadMap[GL_HALF_FLOAT_OES] = LoadRGB16FToRG11B10F;
+ loadMap[GL_FLOAT] = LoadRGB32FToRG11B10F;
+ loadMap[GL_UNSIGNED_INT_10F_11F_11F_REV] = LoadToNative<GLuint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R16F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = Load32FTo16F<1>;
+ loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,1>;
+ loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R16I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_SHORT] = LoadToNative<GLshort,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R16UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadToNative<GLfloat,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R32I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_INT] = LoadToNative<GLint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R32UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R8I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R8UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_R8_SNORM:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG16F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = Load32FTo16F<2>;
+ loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,2>;
+ loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG16I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_SHORT] = LoadToNative<GLshort,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG16UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadToNative<GLfloat,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG32I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_INT] = LoadToNative<GLint,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG32UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG8I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG8UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RG8_SNORM:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,2>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_5_6_5] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_5_6_5] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_RGB10_A2:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadToNative<GLuint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB10_A2UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadToNative<GLuint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadRGB32FToRGBA16F;
+ loadMap[GL_HALF_FLOAT] = LoadToNative3To4<GLhalf,gl::Float16One>;
+ loadMap[GL_HALF_FLOAT_OES] = LoadToNative3To4<GLhalf,gl::Float16One>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_SHORT] = LoadToNative3To4<GLshort,0x0001>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB16UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative3To4<GLushort,0x0001>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadToNative3To4<GLfloat,gl::Float32One>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_INT] = LoadToNative3To4<GLint,0x00000001>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB32UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadToNative3To4<GLuint,0x00000001>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB565:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadToNative<GLushort,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadR5G6B5ToRGBA8;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB5_A1:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadRGB5A1ToA1RGB5;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadRGB10A2ToRGBA8;
+ loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadRGB5A1ToRGBA8;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative3To4<GLbyte,0x01>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0x01>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB8_SNORM:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative3To4<GLbyte,0x7F>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGB9_E5:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_HALF_FLOAT] = LoadRGB16FToRGB9E5;
+ loadMap[GL_HALF_FLOAT_OES] = LoadRGB16FToRGB9E5;
+ loadMap[GL_FLOAT] = LoadRGB32FToRGB9E5;
+ loadMap[GL_UNSIGNED_INT_5_9_9_9_REV] = LoadToNative<GLuint,1>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = UnreachableLoadFunction;
+ loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = UnreachableLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+ case GL_RGBA16F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = Load32FTo16F<4>;
+ loadMap[GL_HALF_FLOAT] = LoadToNative<GLhalf,4>;
+ loadMap[GL_HALF_FLOAT_OES] = LoadToNative<GLhalf,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_SHORT] = LoadToNative<GLshort,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT] = LoadToNative<GLushort,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32F:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_FLOAT] = LoadToNative<GLfloat,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_INT] = LoadToNative<GLint,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_INT] = LoadToNative<GLuint,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA4:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadRGBA4ToARGB4;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadRGBA4ToRGBA8;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8I:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8UI:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8_SNORM:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_BYTE] = LoadToNative<GLbyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative3To4<GLubyte,0xFF>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[GL_UNSIGNED_BYTE] = LoadToNative<GLubyte,4>;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_STENCIL_INDEX8:
+ {
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = UnimplementedLoadFunction;
+ loadMap[DXGI_FORMAT_R24G8_TYPELESS] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ default:
+ {
+ static const std::map<GLenum, LoadImageFunction> loadFunctionsMap = []() {
+ std::map<GLenum, LoadImageFunction> loadMap;
+ loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = UnimplementedLoadFunction;
+ loadMap[DXGI_FORMAT_R24G8_TYPELESS] = UnimplementedLoadFunction;
+ return loadMap;
+ }();
+
+ return loadFunctionsMap;
+ }
+ }
+ }
+
+ default:
+ {
+ static std::map<GLenum, LoadImageFunction> emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+ }
+ }
+ // clang-format on
+
+} // GetLoadFunctionsMap
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index 26b10265304..8b351e1c33f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1070,7 +1070,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
}
// GL core feature limits
- caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+ // Reserve MAX_UINT for D3D11's primitive restart.
+ caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
caps->max3DTextureSize = static_cast<GLuint>(GetMaximum3DTextureSize(featureLevel));
caps->max2DTextureSize = static_cast<GLuint>(GetMaximum2DTextureSize(featureLevel));
caps->maxCubeMapTextureSize = static_cast<GLuint>(GetMaximumCubeMapTextureSize(featureLevel));
@@ -1208,11 +1209,14 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
extensions->fragDepth = true;
extensions->textureUsage = true; // This could be false since it has no effect in D3D11
- extensions->discardFramebuffer = false; // TODO: enable this once BUG:497445 is fixed (Chrome WebGL video tests fail with this extension active)
+ extensions->discardFramebuffer = true;
extensions->translatedShaderSource = true;
extensions->fboRenderMipmap = false;
extensions->debugMarker = true;
extensions->eglImage = true;
+ extensions->unpackSubimage = true;
+ extensions->packSubimage = true;
+ extensions->vertexArrayObject = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
@@ -1296,6 +1300,11 @@ void GenerateInitialTextureData(GLint internalFormat, const Renderer11DeviceCaps
}
}
+UINT GetPrimitiveRestartIndex()
+{
+ return std::numeric_limits<UINT>::max();
+}
+
void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v)
{
vertex->x = x;
@@ -1325,6 +1334,56 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
#endif
}
+LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+ size_t inputDescLen,
+ const BYTE *byteCode,
+ size_t byteCodeLen,
+ const char *debugName)
+ : mInputDesc(inputDescLen),
+ mByteCodeLen(byteCodeLen),
+ mByteCode(byteCode),
+ mDebugName(debugName)
+{
+ memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
+}
+
+ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+
+ if (mResource == nullptr)
+ {
+ HRESULT result =
+ device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
+ mByteCode, mByteCodeLen, &mResource);
+ ASSERT(SUCCEEDED(result));
+ UNUSED_ASSERTION_VARIABLE(result);
+ d3d11::SetDebugName(mResource, mDebugName);
+ }
+
+ return mResource;
+}
+
+LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
+ : mDesc(desc), mDebugName(debugName)
+{
+}
+
+ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
+{
+ checkAssociatedDevice(device);
+
+ if (mResource == nullptr)
+ {
+ HRESULT result = device->CreateBlendState(&mDesc, &mResource);
+ ASSERT(SUCCEEDED(result));
+ UNUSED_ASSERTION_VARIABLE(result);
+ d3d11::SetDebugName(mResource, mDebugName);
+ }
+
+ return mResource;
+}
+
WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
{
WorkaroundsD3D workarounds;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
index 3949b644c2f..809b1af31c4 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -71,6 +71,8 @@ void GenerateInitialTextureData(GLint internalFormat, const Renderer11DeviceCaps
GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
std::vector< std::vector<BYTE> > *outData);
+UINT GetPrimitiveRestartIndex();
+
struct PositionTexCoordVertex
{
float x, y;
@@ -294,35 +296,17 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
const char *mDebugName;
};
-inline LazyInputLayout::LazyInputLayout(
- const D3D11_INPUT_ELEMENT_DESC *inputDesc,
- size_t inputDescLen,
- const BYTE *byteCode,
- size_t byteCodeLen,
- const char *debugName)
- : mInputDesc(inputDescLen),
- mByteCodeLen(byteCodeLen),
- mByteCode(byteCode),
- mDebugName(debugName)
-{
- memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
-}
-
-inline ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
+class LazyBlendState final : public LazyResource<ID3D11BlendState>
{
- checkAssociatedDevice(device);
+ public:
+ LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
- if (mResource == nullptr)
- {
- HRESULT result = device->CreateInputLayout(
- &mInputDesc[0], static_cast<UINT>(mInputDesc.size()), mByteCode, mByteCodeLen, &mResource);
- ASSERT(SUCCEEDED(result));
- UNUSED_ASSERTION_VARIABLE(result);
- d3d11::SetDebugName(mResource, mDebugName);
- }
+ ID3D11BlendState *resolve(ID3D11Device *device) override;
- return mResource;
-}
+ private:
+ D3D11_BLEND_DESC mDesc;
+ const char *mDebugName;
+};
// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
// represent an entire buffer.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json
new file mode 100644
index 00000000000..3e9e6877d99
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json
@@ -0,0 +1,77 @@
+{
+ "GL_UNSIGNED_NORMALIZED": {
+ "8": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ },
+ "16": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM"
+ },
+ "24": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ },
+ "32": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ },
+ "GL_SIGNED_NORMALIZED": {
+ "8": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
+ }
+ },
+ "GL_FLOAT": {
+ "16": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ },
+ "32": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ },
+ "GL_UNSIGNED_INT": {
+ "8": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
+ },
+ "16": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
+ },
+ "32": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
+ }
+ },
+ "GL_INT": {
+ "8": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
+ },
+ "16": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
+ },
+ "32": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
+ }
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp
deleted file mode 100644
index 39b0ad70c2e..00000000000
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// swizzle_format_info:
-// Provides information for swizzle format and a map from type->formatinfo
-//
-
-#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
-
-#include <GLES3/gl3.h>
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE)
-{
-}
-
-SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
- : maxComponentSize(maxComponentSize), componentType(componentType)
-{
-}
-
-bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const
-{
- return (maxComponentSize != other.maxComponentSize)
- ? (maxComponentSize < other.maxComponentSize)
- : (componentType < other.componentType);
-}
-
-SwizzleFormatInfo::SwizzleFormatInfo()
- : mTexFormat(DXGI_FORMAT_UNKNOWN),
- mSRVFormat(DXGI_FORMAT_UNKNOWN),
- mRTVFormat(DXGI_FORMAT_UNKNOWN)
-{
-}
-
-SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat,
- DXGI_FORMAT srvFormat,
- DXGI_FORMAT rtvFormat)
- : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
-{
-}
-
-typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair;
-
-const SwizzleInfoMap &BuildSwizzleInfoMap()
-{
- static 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;
-}
-
-} // namespace d3d11
-
-} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
index 4b1f0244950..df9a30ff505 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
@@ -42,9 +42,7 @@ struct SwizzleFormatInfo
SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat);
};
-typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap;
-
-const SwizzleInfoMap &BuildSwizzleInfoMap();
+const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType);
} // namespace d3d11
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp
new file mode 100644
index 00000000000..84d6fada976
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp
@@ -0,0 +1,203 @@
+// GENERATED FILE - DO NOT EDIT
+// Generated by gen_swizzle_format_table.py using data from swizzle_format_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// swizzle_format_info:
+// Provides information for swizzle format and a map from type->formatinfo
+//
+
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+
+#include <GLES3/gl3.h>
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE)
+{
+}
+
+SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
+ : maxComponentSize(maxComponentSize), componentType(componentType)
+{
+}
+
+bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const
+{
+ return (maxComponentSize != other.maxComponentSize)
+ ? (maxComponentSize < other.maxComponentSize)
+ : (componentType < other.componentType);
+}
+
+SwizzleFormatInfo::SwizzleFormatInfo()
+ : mTexFormat(DXGI_FORMAT_UNKNOWN),
+ mSRVFormat(DXGI_FORMAT_UNKNOWN),
+ mRTVFormat(DXGI_FORMAT_UNKNOWN)
+{
+}
+
+SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat)
+ : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
+{
+}
+
+const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType)
+{
+ // clang-format off
+ switch (componentType)
+ {
+ case GL_FLOAT:
+ {
+ switch (maxBits)
+ {
+ case 16:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT);
+ return formatInfo;
+ }
+ case 32:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT);
+ return formatInfo;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_INT:
+ {
+ switch (maxBits)
+ {
+ case 16:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT);
+ return formatInfo;
+ }
+ case 32:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT);
+ return formatInfo;
+ }
+ case 8:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT);
+ return formatInfo;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_SIGNED_NORMALIZED:
+ {
+ switch (maxBits)
+ {
+ case 8:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM);
+ return formatInfo;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (maxBits)
+ {
+ case 16:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT);
+ return formatInfo;
+ }
+ case 32:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT);
+ return formatInfo;
+ }
+ case 8:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT);
+ return formatInfo;
+ }
+ default:
+ break;
+ }
+ }
+ case GL_UNSIGNED_NORMALIZED:
+ {
+ switch (maxBits)
+ {
+ case 16:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM);
+ return formatInfo;
+ }
+ case 24:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT);
+ return formatInfo;
+ }
+ case 32:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT);
+ return formatInfo;
+ }
+ case 8:
+ {
+ static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM);
+ return formatInfo;
+ }
+ default:
+ break;
+ }
+ }
+
+ default:
+ {
+ static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return defaultInfo;
+ }
+ }
+ // clang-format on
+
+} // GetSwizzleFormatInfo
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
new file mode 100644
index 00000000000..79f6f864fc2
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
@@ -0,0 +1,686 @@
+{
+ "GL_ALPHA": [
+ {
+ "texFormat": "DXGI_FORMAT_A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_A8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_ALPHA16F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ }
+ ],
+ "GL_ALPHA32F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ ],
+ "GL_ALPHA8_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_A8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_BGR5_A1_ANGLEX": [
+ {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
+ }
+ ],
+ "GL_BGRA4_ANGLEX": [
+ {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
+ }
+ ],
+ "GL_BGRA8_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
+ }
+ ],
+ "GL_BGRA_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
+ }
+ ],
+ "GL_COMPRESSED_R11_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_RG11_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_RGB8_ETC2": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM"
+ }
+ ],
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": [
+ {
+ "texFormat": "DXGI_FORMAT_BC2_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC2_UNORM"
+ }
+ ],
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": [
+ {
+ "texFormat": "DXGI_FORMAT_BC3_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC3_UNORM"
+ }
+ ],
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM"
+ }
+ ],
+ "GL_COMPRESSED_SIGNED_R11_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8_SNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_SIGNED_RG11_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_SRGB8_ETC2": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_DEPTH24_STENCIL8": [
+ {
+ "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_DEPTH32F_STENCIL8": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_DEPTH_COMPONENT16": [
+ {
+ "texFormat": "DXGI_FORMAT_R16_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R16_UNORM",
+ "dsvFormat": "DXGI_FORMAT_D16_UNORM",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_D16_UNORM",
+ "dsvFormat": "DXGI_FORMAT_D16_UNORM",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_DEPTH_COMPONENT24": [
+ {
+ "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_DEPTH_COMPONENT32F": [
+ {
+ "texFormat": "DXGI_FORMAT_R32_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ],
+ "GL_DEPTH_COMPONENT32_OES": [
+ {
+ "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL10Plus"
+ }
+ ],
+ "GL_ETC1_RGB8_OES": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_LUMINANCE": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_LUMINANCE16F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ }
+ ],
+ "GL_LUMINANCE32F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ ],
+ "GL_LUMINANCE8_ALPHA8_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_LUMINANCE8_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_LUMINANCE_ALPHA": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_LUMINANCE_ALPHA16F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ }
+ ],
+ "GL_LUMINANCE_ALPHA32F_EXT": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ ],
+ "GL_NONE": [
+ {
+ }
+ ],
+ "GL_R11F_G11F_B10F": [
+ {
+ "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT"
+ }
+ ],
+ "GL_R16F": [
+ {
+ "texFormat": "DXGI_FORMAT_R16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16_FLOAT"
+ }
+ ],
+ "GL_R16I": [
+ {
+ "texFormat": "DXGI_FORMAT_R16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16_SINT"
+ }
+ ],
+ "GL_R16UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16_UINT"
+ }
+ ],
+ "GL_R32F": [
+ {
+ "texFormat": "DXGI_FORMAT_R32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32_FLOAT"
+ }
+ ],
+ "GL_R32I": [
+ {
+ "texFormat": "DXGI_FORMAT_R32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32_SINT"
+ }
+ ],
+ "GL_R32UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32_UINT"
+ }
+ ],
+ "GL_R8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8_UNORM"
+ }
+ ],
+ "GL_R8I": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8_SINT"
+ }
+ ],
+ "GL_R8UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8_UINT"
+ }
+ ],
+ "GL_R8_SNORM": [
+ {
+ "texFormat": "DXGI_FORMAT_R8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8_SNORM"
+ }
+ ],
+ "GL_RG16F": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT"
+ }
+ ],
+ "GL_RG16I": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_SINT"
+ }
+ ],
+ "GL_RG16UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_UINT"
+ }
+ ],
+ "GL_RG32F": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT"
+ }
+ ],
+ "GL_RG32I": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_SINT"
+ }
+ ],
+ "GL_RG32UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_UINT"
+ }
+ ],
+ "GL_RG8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UNORM"
+ }
+ ],
+ "GL_RG8I": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_SINT"
+ }
+ ],
+ "GL_RG8UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UINT"
+ }
+ ],
+ "GL_RG8_SNORM": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_SNORM"
+ }
+ ],
+ "GL_RGB": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_RGB10_A2": [
+ {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM"
+ }
+ ],
+ "GL_RGB10_A2UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT"
+ }
+ ],
+ "GL_RGB16F": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ }
+ ],
+ "GL_RGB16I": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
+ }
+ ],
+ "GL_RGB16UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
+ }
+ ],
+ "GL_RGB32F": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ ],
+ "GL_RGB32I": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
+ }
+ ],
+ "GL_RGB32UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
+ }
+ ],
+ "GL_RGB565": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,false>"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>"
+ }
+ ],
+ "GL_RGB5_A1": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,false>"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>"
+ }
+ ],
+ "GL_RGB8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_RGB8I": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
+ }
+ ],
+ "GL_RGB8UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
+ }
+ ],
+ "GL_RGB8_SNORM": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
+ }
+ ],
+ "GL_RGB9_E5": [
+ {
+ "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP"
+ }
+ ],
+ "GL_RGBA": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_RGBA16F": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
+ }
+ ],
+ "GL_RGBA16I": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
+ }
+ ],
+ "GL_RGBA16UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
+ }
+ ],
+ "GL_RGBA32F": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
+ }
+ ],
+ "GL_RGBA32I": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
+ }
+ ],
+ "GL_RGBA32UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
+ }
+ ],
+ "GL_RGBA4": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,false>"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>"
+ }
+ ],
+ "GL_RGBA8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
+ }
+ ],
+ "GL_RGBA8I": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
+ }
+ ],
+ "GL_RGBA8UI": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
+ }
+ ],
+ "GL_RGBA8_SNORM": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
+ }
+ ],
+ "GL_SRGB8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"
+ }
+ ],
+ "GL_SRGB8_ALPHA8": [
+ {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"
+ }
+ ],
+ "GL_STENCIL_INDEX8": [
+ {
+ "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_X24_TYPELESS_G8_UINT",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL10Plus"
+ },
+ {
+ "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "requirementsFcn": "OnlyFL9_3"
+ }
+ ]
+}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
index aae0d8ca86d..c37a89150a8 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
@@ -340,16 +340,19 @@ const D3D11ES3FormatMap &BuildD3D11FormatMap()
// 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 | Requirements
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
- InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+ InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, OnlyFL10Plus);
+
+ // From GL_ETC1_RGB8_OES
+ InsertD3D11FormatInfo(&map, GL_ETC1_RGB8_OES, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, AnyDevice);
// 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, AnyDevice);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
new file mode 100644
index 00000000000..ecaa3fd28be
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -0,0 +1,1775 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_texture_format_table.py using data from texture_format_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+// Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h"
+#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+namespace
+{
+
+typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &);
+
+bool AnyDevice(const Renderer11DeviceCaps &deviceCaps)
+{
+ return true;
+}
+
+bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}
+
+bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}
+
+template <DXGI_FORMAT format, bool requireSupport>
+bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps)
+{
+ // Must support texture, SRV and RTV support
+ UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+ D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+
+ if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
+ {
+ mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+ }
+
+ bool fullSupport = false;
+ if (format == DXGI_FORMAT_B5G6R5_UNORM)
+ {
+ // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+ // check anyway.
+ mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
+ }
+ else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+ {
+ fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
+ }
+ else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+
+ // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below,
+ // which maps GL formats to DXGI formats.
+ if (requireSupport)
+ {
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *IS* supported.
+ // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+ // DXGI_FORMAT_B5G5R5A1 is supported.
+ // In this case, we should only return 'true' if the format *IS* supported.
+ return fullSupport;
+ }
+ else
+ {
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *ISN'T* supported.
+ // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if
+ // DXGI_FORMAT_B5G5R5A1 isn't supported.
+ // In this case, we should only return 'true' if the format *ISN'T* supported.
+ return !fullSupport;
+ }
+}
+
+// End Format Support Functions
+
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This function allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+const TextureFormat GetD3D11FormatInfo(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);
+
+ const SwizzleFormatInfo &swizzleInfo =
+ GetSwizzleFormatInfo(maxBits, formatInfo.componentType);
+ 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
+ info.dataInitializerFunction = GetInternalFormatInitializer(internalFormat, texFormat);
+ // Gather all the load functions for this internal format
+ info.loadFunctions = GetLoadFunctionsMap(internalFormat, texFormat);
+
+ ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE);
+
+ return info;
+}
+
+} // namespace
+
+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()
+{
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_ALPHA16F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_ALPHA32F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_ALPHA8_EXT:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_BGR5_A1_ANGLEX:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_BGRA4_ANGLEX:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_BGRA8_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_BGRA_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_R11_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH24_STENCIL8:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G8X24_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16_TYPELESS,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ {
+ if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE16F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE32F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE8_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE_ALPHA:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_NONE:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R11F_G11F_B10F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R16F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R16I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R16UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R32F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R32I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R32UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R8I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R8UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_R8_SNORM:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG16F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG16I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG16UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG32F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG32I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG32UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG8I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG8UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RG8_SNORM:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB10_A2:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB10_A2UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB16F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB16I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB16UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB32F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB32I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB32UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB565:
+ {
+ if (SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,false>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB5_A1:
+ {
+ if (SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,false>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB8I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB8UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB8_SNORM:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGB9_E5:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA16F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA16I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA16UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA32F:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA32I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA32UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA4:
+ {
+ if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,false>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA8I:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA8UI:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_RGBA8_SNORM:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_SRGB8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ if (AnyDevice(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+ case GL_STENCIL_INDEX8:
+ {
+ if (OnlyFL9_3(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else if (OnlyFL10Plus(renderer11DeviceCaps))
+ {
+ static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT);
+ return textureFormat;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ default:
+ break;
+ }
+ // clang-format on
+
+ static const TextureFormat defaultInfo;
+ return defaultInfo;
+} // GetTextureFormatInfo
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
index 17cbcc1c8c7..6479f408493 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
@@ -10,6 +10,7 @@
#include "libANGLE/renderer/d3d/d3d11/texture_format_util.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/loadimage_etc.h"
namespace rx
{
@@ -67,6 +68,7 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap()
{
static D3D11LoadFunctionMap map;
+ // clang-format off
// | Internal format | Type | Target DXGI Format | Load function |
InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadToNative<GLubyte, 4> );
InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadToNative<GLubyte, 4> );
@@ -205,18 +207,20 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap()
InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, 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, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
- InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, UnimplementedLoadFunction );
+ // | Internal format | Type | Target DXGI Format | Load function
+ InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8_UNORM, LoadEACR11ToR8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8_SNORM, LoadEACR11SToR8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8_UNORM, LoadEACRG11ToRG8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8_SNORM, LoadEACRG11SToRG8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGB8ToRGBA8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGB8ToRGBA8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGB8A1ToRGBA8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGB8A1ToRGBA8);
+ InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC2RGBA8ToRGBA8 );
+ InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, LoadETC2SRGBA8ToSRGBA8);
+
+ // From GL_ETC1_RGB8_OES
+ InsertLoadFunction(&map, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, DXGI_FORMAT_R8G8B8A8_UNORM, LoadETC1RGB8ToRGBA8 );
// From GL_EXT_texture_compression_dxt1
InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, LoadCompressedToNative<4, 4, 8> );
@@ -227,6 +231,7 @@ const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap()
// From GL_ANGLE_texture_compression_dxt5
InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, DXGI_FORMAT_UNKNOWN, LoadCompressedToNative<4, 4, 16> );
+ // clang-format on
return map;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h
deleted file mode 100644
index e6c7d9923e0..00000000000
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// texture_format_util:
-// Contains helper functions for texture_format_table
-//
-
-#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
-#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
-
-#include <map>
-
-#include "libANGLE/renderer/d3d/d3d11/renderer11.h"
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-typedef std::pair<DXGI_FORMAT, LoadImageFunction> DxgiFormatLoadFunctionPair;
-typedef std::pair<GLenum, DxgiFormatLoadFunctionPair> GLTypeDXGIFunctionPair;
-typedef std::map<GLenum, std::vector<GLTypeDXGIFunctionPair>> D3D11LoadFunctionMap;
-
-const D3D11LoadFunctionMap &BuildD3D11LoadFunctionMap();
-
-typedef std::pair<GLint, DXGI_FORMAT> InitializeTextureFormatPair;
-typedef std::map<InitializeTextureFormatPair, InitializeTextureDataFunction>
- InternalFormatInitializerMap;
-
-const InternalFormatInitializerMap &BuildInternalFormatInitializerMap();
-
-} // namespace d3d11
-
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATUTIL_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
index 2b8b48caedd..bb66dc2faa6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
@@ -11,14 +11,31 @@
#include "common/debug.h"
+#include <initguid.h>
+#include <dcomp.h>
+
namespace rx
{
-NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *)
- : mWindow(window)
+NativeWindow::NativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ bool directComposition)
+ : mWindow(window),
+ mDirectComposition(directComposition),
+ mDevice(nullptr),
+ mCompositionTarget(nullptr),
+ mVisual(nullptr),
+ mConfig(config)
{
}
+NativeWindow::~NativeWindow()
+{
+ SafeRelease(mCompositionTarget);
+ SafeRelease(mDevice);
+ SafeRelease(mVisual);
+}
+
bool NativeWindow::initialize()
{
return true;
@@ -48,6 +65,83 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
return E_INVALIDARG;
}
+ if (mDirectComposition)
+ {
+ HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
+ if (!dcomp)
+ {
+ return E_INVALIDARG;
+ }
+
+ typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
+ IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
+ PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
+ reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
+ GetProcAddress(dcomp, "DCompositionCreateDevice"));
+ if (!createDComp)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!mDevice)
+ {
+ IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
+ HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
+ reinterpret_cast<void **>(&mDevice));
+ SafeRelease(dxgiDevice);
+
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mCompositionTarget)
+ {
+ HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mVisual)
+ {
+ HRESULT result = mDevice->CreateVisual(&mVisual);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode =
+ mConfig->alphaSize == 0 ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
+ swapChainDesc.Flags = 0;
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result =
+ factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+ if (SUCCEEDED(result))
+ {
+ *swapChain = static_cast<DXGISwapChain *>(swapChain1);
+ }
+ mVisual->SetContent(swapChain1);
+ mCompositionTarget->SetRoot(mVisual);
+ SafeRelease(factory2);
+ return result;
+ }
+
// Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
if (factory2 != nullptr)
@@ -59,7 +153,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 1;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
@@ -84,7 +179,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = mWindow;
swapChainDesc.SampleDesc.Count = 1;
@@ -94,4 +190,12 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
}
+
+void NativeWindow::commitChange()
+{
+ if (mDevice)
+ {
+ mDevice->Commit();
+ }
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
index 5eb1d8c4409..47a6daed2d0 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -11,12 +11,22 @@
namespace rx
{
-NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *config)
+NativeWindow::NativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ bool directComposition)
{
mWindow = window;
mConfig = config;
}
+NativeWindow::~NativeWindow()
+{
+}
+
+void NativeWindow::commitChange()
+{
+}
+
bool NativeWindow::initialize()
{
// If the native window type is a IPropertySet, extract the
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
index 69d3cf5e0d9..804b6971ced 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -38,7 +38,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
memcpy(mMemory.data(), data, size);
}
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
updateD3DBufferUsage(usage);
return gl::Error(GL_NO_ERROR);
@@ -66,7 +66,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
memcpy(mMemory.data() + offset, data, size);
}
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
return gl::Error(GL_NO_ERROR);
}
@@ -79,7 +79,7 @@ gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintp
memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
- invalidateStaticData();
+ invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
return gl::Error(GL_NO_ERROR);
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
index e4dfd41cec0..c8d5d8bb075 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -53,7 +53,7 @@ gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangl
return gl::Error(GL_NO_ERROR);
}
-gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
+gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams)
{
const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0);
const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment();
@@ -64,16 +64,22 @@ gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &cle
return error;
}
- float nearZ = state.getNearPlane();
- float farZ = state.getFarPlane();
- mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true);
+ float nearZ = data.state->getNearPlane();
+ float farZ = data.state->getFarPlane();
+ mRenderer->setViewport(data.caps, data.state->getViewport(), nearZ, farZ, GL_TRIANGLES,
+ data.state->getRasterizerState().frontFace, true);
- mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled());
+ mRenderer->setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
}
-gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const
{
ASSERT(pack.pixelBuffer.get() == nullptr);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
index 223259de0f2..fe12079ae0b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -26,10 +26,14 @@ class Framebuffer9 : public FramebufferD3D
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
private:
- gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
-
- gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
- const gl::PixelPackState &pack, uint8_t *pixels) const override;
+ gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
+
+ gl::Error readPixelsImpl(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels) const override;
gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
index a64f6ca4e01..df0fae41937 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -480,6 +480,8 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
+ GLsizei inputSkipBytes = formatInfo.computeSkipPixels(inputRowPitch, 0, unpack.skipImages,
+ unpack.skipRows, unpack.skipPixels);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
ASSERT(d3dFormatInfo.loadFunction != NULL);
@@ -498,8 +500,9 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa
}
d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
- reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0,
- reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
+ reinterpret_cast<const uint8_t *>(input) + inputSkipBytes,
+ inputRowPitch, 0, reinterpret_cast<uint8_t *>(locked.pBits),
+ locked.Pitch, 0);
unlock();
@@ -513,7 +516,8 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
+ GLsizei inputDepthPitch =
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index fad3e29b2cf..47187816b98 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -8,49 +8,49 @@
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include <sstream>
+#include <EGL/eglext.h>
+
#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Display.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Program.h"
#include "libANGLE/Renderbuffer.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Surface.h"
-#include "libANGLE/Texture.h"
-#include "libANGLE/angletypes.h"
-#include "libANGLE/features.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/IndexDataManager.h"
-#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
-#include "libANGLE/renderer/d3d/ShaderD3D.h"
-#include "libANGLE/renderer/d3d/SurfaceD3D.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Image9.h"
#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
-#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
-
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
#include "third_party/trace_event/trace_event.h"
-#include <sstream>
-#include <EGL/eglext.h>
-#include <EGL/eglext.h>
#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
@@ -76,8 +76,7 @@ enum
MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
};
-Renderer9::Renderer9(egl::Display *display)
- : RendererD3D(display)
+Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
{
mD3d9Module = NULL;
@@ -132,6 +131,8 @@ Renderer9::Renderer9(egl::Display *display)
mAppliedProgramSerial = 0;
initializeDebugAnnotator();
+
+ mEGLDevice = nullptr;
}
Renderer9::~Renderer9()
@@ -154,6 +155,7 @@ void Renderer9::release()
releaseDeviceResources();
+ SafeDelete(mEGLDevice);
SafeRelease(mDevice);
SafeRelease(mDeviceEx);
SafeRelease(mD3d9);
@@ -527,6 +529,8 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions)
outExtensions->imageBase = true;
outExtensions->glTexture2DImage = true;
outExtensions->glRenderbufferImage = true;
+
+ outExtensions->flexibleSurfaceCompatibility = true;
}
void Renderer9::startScene()
@@ -648,9 +652,14 @@ gl::Error Renderer9::finish()
return gl::Error(GL_NO_ERROR);
}
-SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
{
- return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
+ return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
+ orientation);
}
void *Renderer9::getD3DDevice()
@@ -883,349 +892,77 @@ gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/,
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
+void Renderer9::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask)
{
- bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
-
- if (rasterStateChanged)
- {
- // Set the cull mode
- if (rasterState.cullFace)
- {
- mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
- }
- else
- {
- mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- }
-
- if (rasterState.polygonOffsetFill)
- {
- if (mCurDepthSize > 0)
- {
- mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
-
- float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
- mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
- }
- }
- else
- {
- mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
- mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
- }
-
- mCurRasterState = rasterState;
- }
-
- mForceSetRasterState = false;
-
- return gl::Error(GL_NO_ERROR);
+ mStateManager.syncState(state, bitmask);
}
-gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
- unsigned int sampleMask)
+gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode)
{
- bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
- bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0;
- bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
-
- if (blendStateChanged || blendColorChanged)
- {
- if (blendState.blend)
- {
- mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-
- 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)
- {
- mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
- }
- else
- {
- mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
- gl::unorm<8>(blendColor.alpha),
- gl::unorm<8>(blendColor.alpha),
- gl::unorm<8>(blendColor.alpha)));
- }
-
- mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
- mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
- mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
-
- if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
- blendState.destBlendRGB != blendState.destBlendAlpha ||
- blendState.blendEquationRGB != blendState.blendEquationAlpha)
- {
- mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-
- mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
- mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
- mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
- }
- else
- {
- mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
- }
- }
- else
- {
- mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- }
-
- if (blendState.sampleAlphaToCoverage)
- {
- FIXME("Sample alpha to coverage is unimplemented.");
- }
-
- const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer();
- GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE;
-
- // Set the color mask
- bool zeroColorMaskAllowed = getVendorId() != VENDOR_ID_AMD;
- // Apparently some ATI cards have a bug where a draw with a zero color
- // write mask can cause later draws to have incorrect results. Instead,
- // set a nonzero color write mask but modify the blend state so that no
- // drawing is done.
- // http://code.google.com/p/angleproject/issues/detail?id=169
-
- 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.
- mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
- mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ // Applies the render target surface, depth stencil surface, viewport rectangle and
+ // scissor rectangle to the renderer
+ const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+ ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
- mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
- mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
- mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
- }
- else
- {
- mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
- }
-
- mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
-
- mCurBlendState = blendState;
- mCurBlendColor = blendColor;
- }
-
- if (sampleMaskChanged)
+ gl::Error error = applyRenderTarget(framebufferObject);
+ if (error.isError())
{
- // Set the multisample mask
- mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
- mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
-
- mCurSampleMask = sampleMask;
+ return error;
}
- mForceSetBlendState = false;
+ // Setting viewport state
+ setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
+ data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace,
+ false);
- return gl::Error(GL_NO_ERROR);
-}
+ // Setting scissors state
+ setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
-gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW)
-{
- bool depthStencilStateChanged = mForceSetDepthStencilState ||
- memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
- bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
- stencilBackRef != mCurStencilBackRef;
- bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
+ // Setting blend, depth stencil, and rasterizer states
+ int samples = framebufferObject->getSamples(data);
+ gl::RasterizerState rasterizer = data.state->getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
- if (depthStencilStateChanged)
- {
- if (depthStencilState.depthTest)
- {
- mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
- mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
- }
- else
- {
- mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
- }
+ unsigned int mask = GetBlendSampleMask(data, samples);
+ error = setBlendDepthRasterStates(data, mask);
- mCurDepthStencilState = depthStencilState;
- }
-
- if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
+ if (error.isError())
{
- if (depthStencilState.stencilTest && mCurStencilSize > 0)
- {
- mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
- mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
-
- // FIXME: Unsupported by D3D9
- const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
- const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
- const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
-
- 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;
-
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
- depthStencilState.stencilWritemask);
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
- gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
-
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
- (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
- depthStencilState.stencilMask);
-
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
- mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
-
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
- depthStencilState.stencilBackWritemask);
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
- gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
-
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
- (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
- depthStencilState.stencilBackMask);
-
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
- mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
- gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
- }
- else
- {
- mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
- }
-
- mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
-
- mCurStencilRef = stencilRef;
- mCurStencilBackRef = stencilBackRef;
- mCurFrontFaceCCW = frontFaceCCW;
+ return error;
}
- mForceSetDepthStencilState = false;
+ mStateManager.resetDirtyBits();
- return gl::Error(GL_NO_ERROR);
+ return error;
}
void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
{
- bool scissorChanged = mForceSetScissor ||
- memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
- enabled != mScissorEnabled;
-
- if (scissorChanged)
- {
- if (enabled)
- {
- RECT rect;
- rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
- rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
- rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
- rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
- mDevice->SetScissorRect(&rect);
- }
-
- mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
+ mStateManager.setScissorState(scissor, enabled);
+}
- mScissorEnabled = enabled;
- mCurScissor = scissor;
- }
+gl::Error Renderer9::setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode)
+{
+ int samples = glData.state->getDrawFramebuffer()->getSamples(glData);
+ gl::RasterizerState rasterizer = glData.state->getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
- mForceSetScissor = false;
+ unsigned int mask = GetBlendSampleMask(glData, samples);
+ return mStateManager.setBlendDepthRasterStates(*glData.state, mask);
}
-void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+void Renderer9::setViewport(const gl::Caps *caps,
+ 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 = static_cast<int>(mRenderTargetDesc.width);
- actualViewport.height = static_cast<int>(mRenderTargetDesc.height);
- actualZNear = 0.0f;
- actualZFar = 1.0f;
- }
-
- D3DVIEWPORT9 dxViewport;
- dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
- dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
- dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
- dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
- dxViewport.MinZ = actualZNear;
- dxViewport.MaxZ = actualZFar;
-
- float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
-
- bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
- actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront;
- if (viewportChanged)
- {
- mDevice->SetViewport(&dxViewport);
-
- mCurViewport = actualViewport;
- mCurNear = actualZNear;
- mCurFar = actualZFar;
- mCurDepthFront = depthFront;
-
- dx_VertexConstants vc = {};
- dx_PixelConstants pc = {};
-
- vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
- vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
- vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
- vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
-
- pc.viewCoords[0] = actualViewport.width * 0.5f;
- pc.viewCoords[1] = actualViewport.height * 0.5f;
- pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
- pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
-
- pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
- pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
- pc.depthFront[2] = depthFront;
-
- vc.depthRange[0] = actualZNear;
- vc.depthRange[1] = actualZFar;
- vc.depthRange[2] = actualZFar - actualZNear;
-
- pc.depthRange[0] = actualZNear;
- pc.depthRange[1] = actualZFar;
- pc.depthRange[2] = actualZFar - actualZNear;
-
- if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
- {
- mVertexConstants = vc;
- mDxUniformsDirty = true;
- }
-
- if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
- {
- mPixelConstants = pc;
- mDxUniformsDirty = true;
- }
- }
-
- mForceSetViewport = false;
+ mStateManager.setViewportState(caps, viewport, zNear, zFar, drawMode, frontFace,
+ ignoreViewport);
}
bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
@@ -1273,15 +1010,14 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
{
ASSERT(depthbuffer);
- GLsizei width = depthbuffer->getWidth();
- GLsizei height = depthbuffer->getHeight();
+ const gl::Extents &size = depthbuffer->getSize();
// search cached nullcolorbuffers
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
{
if (mNullColorbufferCache[i].buffer != NULL &&
- mNullColorbufferCache[i].width == width &&
- mNullColorbufferCache[i].height == height)
+ mNullColorbufferCache[i].width == size.width &&
+ mNullColorbufferCache[i].height == size.height)
{
mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
*outColorBuffer = mNullColorbufferCache[i].buffer;
@@ -1290,7 +1026,7 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
}
gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
- gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height);
+ gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
if (error.isError())
{
SafeDelete(nullRenderbuffer);
@@ -1312,8 +1048,8 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
delete oldest->buffer;
oldest->buffer = nullbuffer;
oldest->lruCount = ++mMaxNullColorbufferLRU;
- oldest->width = width;
- oldest->height = height;
+ oldest->width = size.width;
+ oldest->height = size.height;
*outColorBuffer = nullbuffer;
return gl::Error(GL_NO_ERROR);
@@ -1405,17 +1141,8 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
mDevice->SetDepthStencilSurface(NULL);
}
- if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
- {
- mCurDepthSize = depthSize;
- mForceSetRasterState = true;
- }
-
- if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
- {
- mCurStencilSize = stencilSize;
- mForceSetDepthStencilState = true;
- }
+ mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
+ mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
mAppliedDepthStencilSerial = depthStencilSerial;
mDepthStencilInitialized = true;
@@ -1423,13 +1150,9 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
if (renderTargetChanged || !mRenderTargetDescInitialized)
{
- mForceSetScissor = true;
- mForceSetViewport = true;
- mForceSetBlendState = true;
-
- mRenderTargetDesc.width = renderTargetWidth;
- mRenderTargetDesc.height = renderTargetHeight;
- mRenderTargetDesc.format = renderTargetFormat;
+ mStateManager.forceSetBlendState();
+ mStateManager.forceSetScissorState();
+ mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight);
mRenderTargetDescInitialized = true;
}
@@ -1453,9 +1176,18 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLin
}
// Applies the indices and element array bindings to the Direct3D 9 device
-gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo)
+gl::Error Renderer9::applyIndexBuffer(const gl::Data &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo,
+ SourceIndexData *sourceIndexInfo)
{
- gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, sourceIndexInfo);
+ gl::VertexArray *vao = data.state->getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
+ indexInfo, sourceIndexInfo, false);
if (error.isError())
{
return error;
@@ -1483,8 +1215,7 @@ void Renderer9::applyTransformFeedbackBuffers(const gl::State& state)
gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
GLenum mode,
GLsizei count,
- GLsizei instances,
- bool usesPointSize)
+ GLsizei instances)
{
ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
@@ -1525,19 +1256,21 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
}
}
-gl::Error Renderer9::drawElementsImpl(GLenum mode,
+gl::Error Renderer9::drawElementsImpl(const gl::Data &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- gl::Buffer *elementArrayBuffer,
- const TranslatedIndexData &indexInfo,
- GLsizei /*instances*/,
- bool /*usesPointSize*/)
+ GLsizei /*instances*/)
{
startScene();
int minIndex = static_cast<int>(indexInfo.indexRange.start);
+ gl::VertexArray *vao = data.state->getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
if (mode == GL_POINTS)
{
return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
@@ -1860,15 +1593,9 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::applyShaders(gl::Program *program,
- const gl::Framebuffer *framebuffer,
- bool rasterizerDiscard,
- bool transformFeedbackActive)
+gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/)
{
- ASSERT(!transformFeedbackActive);
- ASSERT(!rasterizerDiscard);
-
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
const auto &inputLayout = programD3D->getCachedInputLayout();
ShaderExecutableD3D *vertexExe = NULL;
@@ -1878,8 +1605,9 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
return error;
}
+ const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
ShaderExecutableD3D *pixelExe = NULL;
- error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
+ error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe);
if (error.isError())
{
return error;
@@ -1909,7 +1637,7 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
if (programSerial != mAppliedProgramSerial)
{
programD3D->dirtyAllUniforms();
- mDxUniformsDirty = true;
+ mStateManager.forceSetDXUniformsState();
mAppliedProgramSerial = programSerial;
}
@@ -1917,6 +1645,7 @@ gl::Error Renderer9::applyShaders(gl::Program *program,
}
gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
+ GLenum /*drawMode*/,
const std::vector<D3DUniform *> &uniformArray)
{
for (const D3DUniform *targetUniform : uniformArray)
@@ -1959,12 +1688,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
}
// Driver uniforms
- if (mDxUniformsDirty)
- {
- mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
- mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
- mDxUniformsDirty = false;
- }
+ mStateManager.setShaderConstants();
return gl::Error(GL_NO_ERROR);
}
@@ -2198,14 +1922,17 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
mDevice->SetStreamSourceFreq(i, 1);
}
+ int renderTargetWidth = mStateManager.getRenderTargetWidth();
+ int renderTargetHeight = mStateManager.getRenderTargetHeight();
+
float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
quad[0][0] = -0.5f;
- quad[0][1] = mRenderTargetDesc.height - 0.5f;
+ quad[0][1] = renderTargetHeight - 0.5f;
quad[0][2] = 0.0f;
quad[0][3] = 1.0f;
- quad[1][0] = mRenderTargetDesc.width - 0.5f;
- quad[1][1] = mRenderTargetDesc.height - 0.5f;
+ quad[1][0] = renderTargetWidth - 0.5f;
+ quad[1][1] = renderTargetHeight - 0.5f;
quad[1][2] = 0.0f;
quad[1][3] = 1.0f;
@@ -2214,7 +1941,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
quad[2][2] = 0.0f;
quad[2][3] = 1.0f;
- quad[3][0] = mRenderTargetDesc.width - 0.5f;
+ quad[3][0] = renderTargetWidth - 0.5f;
quad[3][1] = -0.5f;
quad[3][2] = 0.0f;
quad[3][3] = 1.0f;
@@ -2263,11 +1990,11 @@ void Renderer9::markAllStateDirty()
mDepthStencilInitialized = false;
mRenderTargetDescInitialized = false;
- mForceSetDepthStencilState = true;
- mForceSetRasterState = true;
- mForceSetScissor = true;
- mForceSetViewport = true;
- mForceSetBlendState = true;
+ mStateManager.forceSetRasterState();
+ mStateManager.forceSetDepthStencilState();
+ mStateManager.forceSetBlendState();
+ mStateManager.forceSetScissorState();
+ mStateManager.forceSetViewportState();
ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size());
for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
@@ -2287,7 +2014,7 @@ void Renderer9::markAllStateDirty()
mAppliedVertexShader = NULL;
mAppliedPixelShader = NULL;
mAppliedProgramSerial = 0;
- mDxUniformsDirty = true;
+ mStateManager.forceSetDXUniformsState();
mVertexDeclarationCache.markStateDirty();
}
@@ -2723,12 +2450,15 @@ ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data)
return new ProgramD3D(data, this);
}
-gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable)
+gl::Error Renderer9::loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable)
{
// Transform feedback is not supported in ES2 or D3D9
- ASSERT(transformFeedbackVaryings.size() == 0);
+ ASSERT(streamOutVaryings.empty());
switch (type)
{
@@ -2762,13 +2492,16 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
ShaderExecutableD3D **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
- ASSERT(transformFeedbackVaryings.size() == 0);
+ ASSERT(streamOutVaryings.empty());
const char *profileType = NULL;
switch (type)
@@ -2831,7 +2564,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string
}
error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
- transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
+ streamOutVaryings, separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
@@ -3042,6 +2775,26 @@ gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStar
return gl::Error(GL_NO_ERROR);
}
+egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
+{
+ if (mEGLDevice == nullptr)
+ {
+ ASSERT(mDevice != nullptr);
+ mEGLDevice = new DeviceD3D();
+ egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
+ EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
+
+ if (error.isError())
+ {
+ SafeDelete(mEGLDevice);
+ return error;
+ }
+ }
+
+ *device = static_cast<DeviceImpl *>(mEGLDevice);
+ return egl::Error(EGL_SUCCESS);
+}
+
Renderer9::CurSamplerState::CurSamplerState()
: forceSet(true),
baseLevel(std::numeric_limits<size_t>::max()),
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index e7d8a3f1af9..4e3fb9cea86 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -17,6 +17,7 @@
#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
namespace gl
{
@@ -78,7 +79,11 @@ class Renderer9 : public RendererD3D
gl::Error flush() override;
gl::Error finish() override;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation) override;
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
void freeEventQuery(IDirect3DQuery9* query);
@@ -96,28 +101,32 @@ class Renderer9 : public RendererD3D
const std::vector<GLint> &vertexUniformBuffers,
const std::vector<GLint> &fragmentUniformBuffers) override;
- virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
- gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
- unsigned int sampleMask) override;
- virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW);
+ gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
- 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);
+ void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ void setViewport(const gl::Caps *caps,
+ const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum drawMode,
+ GLenum frontFace,
+ bool ignoreViewport);
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorAttachment,
const gl::FramebufferAttachment *depthStencilAttachment);
- gl::Error applyShaders(gl::Program *program,
- const gl::Framebuffer *framebuffer,
- bool rasterizerDiscard,
- bool transformFeedbackActive) override;
gl::Error applyUniforms(const ProgramD3D &programD3D,
+ GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo);
- virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo, SourceIndexData *sourceIndexInfo);
+ gl::Error applyIndexBuffer(const gl::Data &data,
+ const GLvoid *indices,
+ GLsizei count,
+ GLenum mode,
+ GLenum type,
+ TranslatedIndexData *indexInfo,
+ SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override;
@@ -131,7 +140,7 @@ class Renderer9 : public RendererD3D
bool testDeviceLost() override;
bool testDeviceResettable() override;
- VendorID getVendorId() const override;
+ VendorID getVendorId() const;
std::string getRendererDescription() const override;
DeviceIdentifier getAdapterIdentifier() const override;
@@ -173,14 +182,20 @@ class Renderer9 : public RendererD3D
ProgramImpl *createProgram(const gl::Program::Data &data) override;
// Shader operations
- virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
- virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
- const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
- ShaderExecutableD3D **outExectuable);
- virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
+ gl::Error loadExecutable(const void *function,
+ size_t length,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ gl::Error compileToExecutable(gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
// Image operations
virtual ImageD3D *createImage();
@@ -221,6 +236,8 @@ class Renderer9 : public RendererD3D
virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+ void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
+
// D3D9-renderer specific methods
gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
@@ -236,24 +253,25 @@ class Renderer9 : public RendererD3D
D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
+ egl::Error getEGLDevice(DeviceImpl **device) override;
+
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
+ gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
GLsizei count,
- GLsizei instances,
- bool usesPointSize) override;
- gl::Error drawElementsImpl(GLenum mode,
+ GLsizei instances) override;
+ gl::Error drawElementsImpl(const gl::Data &data,
+ const TranslatedIndexData &indexInfo,
+ GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
- gl::Buffer *elementArrayBuffer,
- const TranslatedIndexData &indexInfo,
- GLsizei instances,
- bool usesPointSize) override;
+ GLsizei instances) override;
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
@@ -261,6 +279,8 @@ class Renderer9 : public RendererD3D
WorkaroundsD3D generateWorkarounds() const override;
+ gl::Error setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode);
+
void release();
void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
@@ -315,43 +335,10 @@ class Renderer9 : public RendererD3D
unsigned int mAppliedDepthStencilSerial;
bool mDepthStencilInitialized;
bool mRenderTargetDescInitialized;
- unsigned int mCurStencilSize;
- unsigned int mCurDepthSize;
-
- struct RenderTargetDesc
- {
- size_t width;
- size_t height;
- D3DFORMAT format;
- };
- RenderTargetDesc mRenderTargetDesc;
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;
+ StateManager9 mStateManager;
// Currently applied sampler states
struct CurSamplerState
@@ -374,10 +361,6 @@ class Renderer9 : public RendererD3D
IDirect3DPixelShader9 *mAppliedPixelShader;
unsigned int mAppliedProgramSerial;
- dx_VertexConstants mVertexConstants;
- dx_PixelConstants mPixelConstants;
- bool mDxUniformsDirty;
-
// A pool of event queries that are currently unused.
std::vector<IDirect3DQuery9*> mEventQueryPool;
VertexShaderCache mVertexShaderCache;
@@ -399,6 +382,8 @@ class Renderer9 : public RendererD3D
gl::FramebufferAttachment *buffer;
} mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
UINT mMaxNullColorbufferLRU;
+
+ DeviceD3D *mEGLDevice;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
new file mode 100644
index 00000000000..1ae98f7d266
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
@@ -0,0 +1,898 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.cpp: Defines a class for caching D3D9 state
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+
+#include "common/BitSetIterator.h"
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+StateManager9::StateManager9(Renderer9 *renderer9)
+ : mCurBlendState(),
+ mCurBlendColor(0, 0, 0, 0),
+ mCurSampleMask(0),
+ mCurRasterState(),
+ mCurDepthSize(0),
+ mCurDepthStencilState(),
+ mCurStencilRef(0),
+ mCurStencilBackRef(0),
+ mCurFrontFaceCCW(0),
+ mCurStencilSize(0),
+ mCurScissorRect(),
+ mCurScissorEnabled(false),
+ mCurViewport(),
+ mCurNear(0.0f),
+ mCurFar(0.0f),
+ mCurDepthFront(0.0f),
+ mCurIgnoreViewport(false),
+ mRenderer9(renderer9),
+ mDirtyBits()
+{
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+ mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ mBlendStateDirtyBits.set(DIRTY_BIT_DITHER);
+ mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+
+ mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+
+ mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+ mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+}
+
+StateManager9::~StateManager9()
+{
+}
+
+void StateManager9::forceSetBlendState()
+{
+ mDirtyBits |= mBlendStateDirtyBits;
+}
+
+void StateManager9::forceSetRasterState()
+{
+ mDirtyBits |= mRasterizerStateDirtyBits;
+}
+
+void StateManager9::forceSetDepthStencilState()
+{
+ mDirtyBits |= mDepthStencilStateDirtyBits;
+}
+
+void StateManager9::forceSetScissorState()
+{
+ mDirtyBits |= mScissorStateDirtyBits;
+}
+
+void StateManager9::forceSetViewportState()
+{
+ mForceSetViewport = true;
+}
+
+void StateManager9::forceSetDXUniformsState()
+{
+ mDxUniformsDirty = true;
+}
+
+void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
+{
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ forceSetDepthStencilState();
+ }
+}
+
+void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ if (state.getBlendState().blend != mCurBlendState.blend)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ // BlendColor and funcs and equations has to be set if blend is enabled
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ }
+ break;
+ case gl::State::DIRTY_BIT_BLEND_FUNCS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
+ blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
+ blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
+ blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ // BlendColor depends on the values of blend funcs
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+ blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ if (state.getBlendState().sampleAlphaToCoverage !=
+ mCurBlendState.sampleAlphaToCoverage)
+ {
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_COLOR_MASK:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
+ blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
+ blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
+ blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ if (state.getBlendState().dither != mCurBlendState.dither)
+ {
+ mDirtyBits.set(DIRTY_BIT_DITHER);
+ }
+ break;
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ if (state.getBlendColor() != mCurBlendColor)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+
+ // Viewport state depends on rasterizer.frontface
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ if (state.getRasterizerState().polygonOffsetFill !=
+ mCurRasterState.polygonOffsetFill)
+ {
+ mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const gl::RasterizerState &rasterizerState = state.getRasterizerState();
+ if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+ rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+ {
+ mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+ }
+ }
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+ // If we enable the stencil test, all of these must be set
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc ||
+ depthStencilState.stencilMask != mCurDepthStencilState.stencilMask ||
+ state.getStencilRef() != mCurStencilRef)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
+ depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
+ state.getStencilBackRef() != mCurStencilBackRef)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ if (state.getDepthStencilState().stencilWritemask !=
+ mCurDepthStencilState.stencilWritemask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ if (state.getDepthStencilState().stencilBackWritemask !=
+ mCurDepthStencilState.stencilBackWritemask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ }
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail ||
+ depthStencilState.stencilPassDepthFail !=
+ mCurDepthStencilState.stencilPassDepthFail ||
+ depthStencilState.stencilPassDepthPass !=
+ mCurDepthStencilState.stencilPassDepthPass)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ {
+ const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
+ depthStencilState.stencilBackPassDepthFail !=
+ mCurDepthStencilState.stencilBackPassDepthFail ||
+ depthStencilState.stencilBackPassDepthPass !=
+ mCurDepthStencilState.stencilBackPassDepthPass)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ if (state.isScissorTestEnabled() != mCurScissorEnabled)
+ {
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+ // If scissor is enabled, we have to set the scissor rect
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ if (state.getScissor() != mCurScissorRect)
+ {
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
+ {
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
+ unsigned int sampleMask)
+{
+ const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+
+ const gl::BlendState &blendState = glState.getBlendState();
+ const gl::ColorF &blendColor = glState.getBlendColor();
+ const gl::RasterizerState &rasterState = glState.getRasterizerState();
+
+ const auto &depthStencilState = glState.getDepthStencilState();
+ bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW);
+ unsigned int maxStencil = (1 << mCurStencilSize) - 1;
+
+ // All the depth stencil states depends on the front face ccw variable
+ if (frontFaceCCW != mCurFrontFaceCCW)
+ {
+ forceSetDepthStencilState();
+ mCurFrontFaceCCW = frontFaceCCW;
+ }
+
+ for (auto dirtyBit : angle::IterateBitSet(mDirtyBits))
+ {
+ switch (dirtyBit)
+ {
+ case DIRTY_BIT_BLEND_ENABLED:
+ setBlendEnabled(blendState.blend);
+ break;
+ case DIRTY_BIT_BLEND_COLOR:
+ setBlendColor(blendState, blendColor);
+ break;
+ case DIRTY_BIT_BLEND_FUNCS_EQUATIONS:
+ setBlendFuncsEquations(blendState);
+ break;
+ case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE:
+ setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage);
+ break;
+ case DIRTY_BIT_COLOR_MASK:
+ setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue,
+ blendState.colorMaskGreen, blendState.colorMaskAlpha);
+ break;
+ case DIRTY_BIT_DITHER:
+ setDither(blendState.dither);
+ break;
+ case DIRTY_BIT_CULL_MODE:
+ setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace);
+ break;
+ case DIRTY_BIT_DEPTH_BIAS:
+ setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor,
+ rasterState.polygonOffsetUnits);
+ break;
+ case DIRTY_BIT_STENCIL_DEPTH_MASK:
+ setDepthMask(depthStencilState.depthMask);
+ break;
+ case DIRTY_BIT_STENCIL_DEPTH_FUNC:
+ setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc);
+ break;
+ case DIRTY_BIT_STENCIL_TEST_ENABLED:
+ setStencilTestEnabled(depthStencilState.stencilTest);
+ break;
+ case DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask,
+ glState.getStencilRef(), frontFaceCCW, maxStencil);
+ break;
+ case DIRTY_BIT_STENCIL_FUNCS_BACK:
+ setStencilFuncsBack(depthStencilState.stencilBackFunc,
+ depthStencilState.stencilBackMask, glState.getStencilBackRef(),
+ frontFaceCCW, maxStencil);
+ break;
+ case DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_OPS_FRONT:
+ setStencilOpsFront(depthStencilState.stencilFail,
+ depthStencilState.stencilPassDepthFail,
+ depthStencilState.stencilPassDepthPass, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_OPS_BACK:
+ setStencilOpsBack(depthStencilState.stencilBackFail,
+ depthStencilState.stencilBackPassDepthFail,
+ depthStencilState.stencilBackPassDepthPass, frontFaceCCW);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (sampleMask != mCurSampleMask)
+ {
+ setSampleMask(sampleMask);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void StateManager9::setViewportState(const gl::Caps *caps,
+ const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum drawMode,
+ GLenum frontFace,
+ bool ignoreViewport)
+{
+ if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport)
+ return;
+
+ gl::Rectangle actualViewport = viewport;
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+
+ if (ignoreViewport)
+ {
+ actualViewport.x = 0;
+ actualViewport.y = 0;
+ actualViewport.width = static_cast<int>(mRenderTargetBounds.width);
+ actualViewport.height = static_cast<int>(mRenderTargetBounds.height);
+ actualZNear = 0.0f;
+ actualZFar = 1.0f;
+ }
+
+ D3DVIEWPORT9 dxViewport;
+ dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width));
+ dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height));
+ dxViewport.Width =
+ gl::clamp(actualViewport.width, 0,
+ static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X));
+ dxViewport.Height =
+ gl::clamp(actualViewport.height, 0,
+ static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y));
+ dxViewport.MinZ = actualZNear;
+ dxViewport.MaxZ = actualZFar;
+
+ float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
+
+ mRenderer9->getDevice()->SetViewport(&dxViewport);
+
+ mCurViewport = actualViewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+ mCurDepthFront = depthFront;
+ mCurIgnoreViewport = ignoreViewport;
+
+ // Setting shader constants
+ dx_VertexConstants vc = {};
+ dx_PixelConstants pc = {};
+
+ vc.viewAdjust[0] =
+ static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) +
+ 2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) /
+ dxViewport.Width;
+ vc.viewAdjust[1] =
+ static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) +
+ 2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) /
+ dxViewport.Height;
+ vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
+ vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
+
+ pc.viewCoords[0] = actualViewport.width * 0.5f;
+ pc.viewCoords[1] = actualViewport.height * 0.5f;
+ pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+ pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+ pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+ pc.depthFront[2] = depthFront;
+
+ vc.depthRange[0] = actualZNear;
+ vc.depthRange[1] = actualZFar;
+ vc.depthRange[2] = actualZFar - actualZNear;
+
+ pc.depthRange[0] = actualZNear;
+ pc.depthRange[1] = actualZFar;
+ pc.depthRange[2] = actualZFar - actualZNear;
+
+ if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
+ {
+ mVertexConstants = vc;
+ mDxUniformsDirty = true;
+ }
+
+ if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
+ {
+ mPixelConstants = pc;
+ mDxUniformsDirty = true;
+ }
+
+ mForceSetViewport = false;
+}
+
+void StateManager9::setShaderConstants()
+{
+ if (!mDxUniformsDirty)
+ return;
+
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants),
+ sizeof(dx_VertexConstants) / sizeof(float[4]));
+ device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants),
+ sizeof(dx_PixelConstants) / sizeof(float[4]));
+ mDxUniformsDirty = false;
+}
+
+// This is separate from the main state loop because other functions
+// outside call only setScissorState to update scissor state
+void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled)
+{
+ if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED))
+ setScissorEnabled(enabled);
+
+ if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT))
+ setScissorRect(scissor, enabled);
+}
+
+void StateManager9::setRenderTargetBounds(size_t width, size_t height)
+{
+ mRenderTargetBounds.width = (int)width;
+ mRenderTargetBounds.height = (int)height;
+ forceSetViewportState();
+}
+
+void StateManager9::setScissorEnabled(bool scissorEnabled)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
+ mCurScissorEnabled = scissorEnabled;
+}
+
+void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled)
+{
+ if (!enabled)
+ return;
+
+ RECT rect;
+ rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width));
+ rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height));
+ rect.right =
+ gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width));
+ rect.bottom =
+ gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height));
+ mRenderer9->getDevice()->SetScissorRect(&rect);
+}
+
+void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc)
+{
+ if (depthTest)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+ device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ }
+
+ mCurDepthStencilState.depthTest = depthTest;
+ mCurDepthStencilState.depthFunc = depthFunc;
+}
+
+void StateManager9::setStencilOpsFront(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass,
+ bool frontFaceCCW)
+{
+ // TODO(dianx) It may be slightly more efficient todo these and other similar areas
+ // with separate dirty bits.
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(stencilFail));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(stencilPassDepthFail));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(stencilPassDepthPass));
+
+ mCurDepthStencilState.stencilFail = stencilFail;
+ mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail;
+ mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass;
+}
+
+void StateManager9::setStencilOpsBack(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass,
+ bool frontFaceCCW)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(stencilBackFail));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass));
+
+ mCurDepthStencilState.stencilBackFail = stencilBackFail;
+ mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail;
+ mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass;
+}
+
+void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW)
+{
+ mRenderer9->getDevice()->SetRenderState(
+ !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask);
+
+ mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask;
+}
+
+void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc,
+ GLuint stencilBackMask,
+ GLint stencilBackRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(stencilBackFunc));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
+ stencilBackMask);
+
+ mCurDepthStencilState.stencilBackFunc = stencilBackFunc;
+ mCurStencilBackRef = stencilBackRef;
+ mCurDepthStencilState.stencilBackMask = stencilBackMask;
+}
+
+void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW)
+{
+ mRenderer9->getDevice()->SetRenderState(
+ frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask);
+ mCurDepthStencilState.stencilWritemask = stencilWriteMask;
+}
+
+void StateManager9::setStencilFuncsFront(GLenum stencilFunc,
+ GLuint stencilMask,
+ GLint stencilRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(stencilFunc));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil);
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
+
+ mCurDepthStencilState.stencilFunc = stencilFunc;
+ mCurStencilRef = stencilRef;
+ mCurDepthStencilState.stencilMask = stencilMask;
+}
+void StateManager9::setStencilTestEnabled(bool stencilTestEnabled)
+{
+ if (stencilTestEnabled && mCurStencilSize > 0)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mCurDepthStencilState.stencilTest = stencilTestEnabled;
+}
+
+void StateManager9::setDepthMask(bool depthMask)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
+ mCurDepthStencilState.depthMask = depthMask;
+}
+
+// TODO(dianx) one bit for sampleAlphaToCoverage
+void StateManager9::setSampleAlphaToCoverage(bool enabled)
+{
+ if (enabled)
+ {
+ FIXME("Sample alpha to coverage is unimplemented.");
+ }
+}
+
+void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor)
+{
+ if (!blendState.blend)
+ return;
+
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR,
+ gl_d3d9::ConvertColor(blendColor));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(
+ D3DRS_BLENDFACTOR,
+ D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha),
+ gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha)));
+ }
+ mCurBlendColor = blendColor;
+}
+
+void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState)
+{
+ if (!blendState.blend)
+ return;
+
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+
+ device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
+ device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
+ device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
+
+ if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
+ blendState.destBlendRGB != blendState.destBlendAlpha ||
+ blendState.blendEquationRGB != blendState.blendEquationAlpha)
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLENDALPHA,
+ gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
+ device->SetRenderState(D3DRS_DESTBLENDALPHA,
+ gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
+ device->SetRenderState(D3DRS_BLENDOPALPHA,
+ gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+ }
+
+ mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB;
+ mCurBlendState.destBlendRGB = blendState.destBlendRGB;
+ mCurBlendState.blendEquationRGB = blendState.blendEquationRGB;
+ mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
+}
+
+void StateManager9::setBlendEnabled(bool enabled)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
+ mCurBlendState.blend = enabled;
+}
+
+void StateManager9::setDither(bool dither)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
+ mCurBlendState.dither = dither;
+}
+
+// TODO(dianx) one bit for color mask
+void StateManager9::setColorMask(const gl::Framebuffer *framebuffer,
+ bool red,
+ bool blue,
+ bool green,
+ bool alpha)
+{
+ // Set the color mask
+ bool zeroColorMaskAllowed = mRenderer9->getVendorId() != VENDOR_ID_AMD;
+ // Apparently some ATI cards have a bug where a draw with a zero color
+ // write mask can cause later draws to have incorrect results. Instead,
+ // set a nonzero color write mask but modify the blend state so that no
+ // drawing is done.
+ // http://code.google.com/p/angleproject/issues/detail?id=169
+
+ const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer();
+ GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+
+ DWORD colorMask = gl_d3d9::ConvertColorMask(
+ formatInfo.redBits > 0 && red, formatInfo.greenBits > 0 && green,
+ formatInfo.blueBits > 0 && blue, formatInfo.alphaBits > 0 && alpha);
+
+ if (colorMask == 0 && !zeroColorMaskAllowed)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ // Enable green channel, but set blending so nothing will be drawn.
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+ }
+
+ mCurBlendState.colorMaskRed = red;
+ mCurBlendState.colorMaskGreen = green;
+ mCurBlendState.colorMaskBlue = blue;
+ mCurBlendState.colorMaskAlpha = alpha;
+}
+
+void StateManager9::setSampleMask(unsigned int sampleMask)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ // Set the multisample mask
+ device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+ device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
+
+ mCurSampleMask = sampleMask;
+}
+
+void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace)
+{
+ if (cullFace)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE,
+ gl_d3d9::ConvertCullMode(cullMode, frontFace));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ }
+
+ mCurRasterState.cullFace = cullFace;
+ mCurRasterState.cullMode = cullMode;
+ mCurRasterState.frontFace = frontFace;
+}
+
+void StateManager9::setDepthBias(bool polygonOffsetFill,
+ GLfloat polygonOffsetFactor,
+ GLfloat polygonOffsetUnits)
+{
+ if (polygonOffsetFill)
+ {
+ if (mCurDepthSize > 0)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor);
+
+ float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
+ device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias);
+ }
+ }
+ else
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+ device->SetRenderState(D3DRS_DEPTHBIAS, 0);
+ }
+
+ mCurRasterState.polygonOffsetFill = polygonOffsetFill;
+ mCurRasterState.polygonOffsetFactor = polygonOffsetFactor;
+ mCurRasterState.polygonOffsetUnits = polygonOffsetUnits;
+}
+
+void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize)
+{
+ if (!depthStencilInitialized || depthSize != mCurDepthSize)
+ {
+ mCurDepthSize = depthSize;
+ forceSetRasterState();
+ }
+}
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
new file mode 100644
index 00000000000..630685587cb
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
@@ -0,0 +1,192 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.h: Defines a class for caching D3D9 state
+
+#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+class StateManager9 final : angle::NonCopyable
+{
+ public:
+ StateManager9(Renderer9 *renderer9);
+ ~StateManager9();
+
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+ gl::Error setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask);
+ void setScissorState(const gl::Rectangle &scissor, bool enabled);
+ void setViewportState(const gl::Caps *caps,
+ const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ GLenum drawMode,
+ GLenum frontFace,
+ bool ignoreViewport);
+
+ void setShaderConstants();
+
+ void forceSetBlendState();
+ void forceSetRasterState();
+ void forceSetDepthStencilState();
+ void forceSetScissorState();
+ void forceSetViewportState();
+ void forceSetDXUniformsState();
+
+ void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize);
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+ void setRenderTargetBounds(size_t width, size_t height);
+
+ int getRenderTargetWidth() const { return mRenderTargetBounds.width; }
+ int getRenderTargetHeight() const { return mRenderTargetBounds.height; }
+
+ void resetDirtyBits() { mDirtyBits.reset(); }
+
+ private:
+ // Blend state functions
+ void setBlendEnabled(bool enabled);
+ void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor);
+ void setBlendFuncsEquations(const gl::BlendState &blendState);
+ void setColorMask(const gl::Framebuffer *framebuffer,
+ bool red,
+ bool blue,
+ bool green,
+ bool alpha);
+ void setSampleAlphaToCoverage(bool enabled);
+ void setDither(bool dither);
+ void setSampleMask(unsigned int sampleMask);
+
+ // Current raster state functions
+ void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace);
+ void setDepthBias(bool polygonOffsetFill,
+ GLfloat polygonOffsetFactor,
+ GLfloat polygonOffsetUnits);
+
+ // Depth stencil state functions
+ void setStencilOpsFront(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass,
+ bool frontFaceCCW);
+ void setStencilOpsBack(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass,
+ bool frontFaceCCW);
+ void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW);
+ void setDepthFunc(bool depthTest, GLenum depthFunc);
+ void setStencilTestEnabled(bool enabled);
+ void setDepthMask(bool depthMask);
+ void setStencilFuncsFront(GLenum stencilFunc,
+ GLuint stencilMask,
+ GLint stencilRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil);
+ void setStencilFuncsBack(GLenum stencilBackFunc,
+ GLuint stencilBackMask,
+ GLint stencilBackRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil);
+ void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW);
+
+ void setScissorEnabled(bool scissorEnabled);
+ void setScissorRect(const gl::Rectangle &scissor, bool enabled);
+
+ enum DirtyBitType
+ {
+ // Blend dirty bits
+ DIRTY_BIT_BLEND_ENABLED,
+ DIRTY_BIT_BLEND_COLOR,
+ DIRTY_BIT_BLEND_FUNCS_EQUATIONS,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE,
+ DIRTY_BIT_COLOR_MASK,
+ DIRTY_BIT_DITHER,
+ DIRTY_BIT_SAMPLE_MASK,
+
+ // Rasterizer dirty bits
+ DIRTY_BIT_CULL_MODE,
+ DIRTY_BIT_DEPTH_BIAS,
+
+ // Depth stencil dirty bits
+ DIRTY_BIT_STENCIL_DEPTH_MASK,
+ DIRTY_BIT_STENCIL_DEPTH_FUNC,
+ DIRTY_BIT_STENCIL_TEST_ENABLED,
+ DIRTY_BIT_STENCIL_FUNCS_FRONT,
+ DIRTY_BIT_STENCIL_FUNCS_BACK,
+ DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
+ DIRTY_BIT_STENCIL_WRITEMASK_BACK,
+ DIRTY_BIT_STENCIL_OPS_FRONT,
+ DIRTY_BIT_STENCIL_OPS_BACK,
+
+ // Scissor dirty bits
+ DIRTY_BIT_SCISSOR_ENABLED,
+ DIRTY_BIT_SCISSOR_RECT,
+
+ // Viewport dirty bits
+ DIRTY_BIT_VIEWPORT,
+
+ DIRTY_BIT_MAX
+ };
+
+ typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+
+ // Currently applied blend state
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+ DirtyBits mBlendStateDirtyBits;
+
+ // Currently applied raster state
+ gl::RasterizerState mCurRasterState;
+ unsigned int mCurDepthSize;
+ DirtyBits mRasterizerStateDirtyBits;
+
+ // Currently applied depth stencil state
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ bool mCurFrontFaceCCW;
+ unsigned int mCurStencilSize;
+ DirtyBits mDepthStencilStateDirtyBits;
+
+ // Currently applied scissor states
+ gl::Rectangle mCurScissorRect;
+ bool mCurScissorEnabled;
+ gl::Extents mRenderTargetBounds;
+ DirtyBits mScissorStateDirtyBits;
+
+ // Currently applied viewport states
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+ float mCurDepthFront;
+ bool mCurIgnoreViewport;
+
+ dx_VertexConstants mVertexConstants;
+ dx_PixelConstants mPixelConstants;
+ bool mDxUniformsDirty;
+
+ // FIXME: Unsupported by D3D9
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+
+ Renderer9 *mRenderer9;
+ DirtyBits mDirtyBits;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
index 5ce76f8ae9b..be6a9c424ca 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -15,21 +15,26 @@
namespace rx
{
-SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain9::SwapChain9(Renderer9 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
: SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mSwapInterval(-1),
+ mSwapChain(nullptr),
+ mBackBuffer(nullptr),
+ mRenderTarget(nullptr),
+ mDepthStencil(nullptr),
+ mOffscreenTexture(nullptr),
mColorRenderTarget(this, false),
mDepthStencilRenderTarget(this, true)
{
- mSwapChain = NULL;
- mBackBuffer = NULL;
- mDepthStencil = NULL;
- mRenderTarget = NULL;
- mOffscreenTexture = NULL;
- mWidth = -1;
- mHeight = -1;
- mSwapInterval = -1;
+ ASSERT(orientation == 0);
}
SwapChain9::~SwapChain9()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
index 9c67f7165b2..55a700c2d64 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -20,8 +20,12 @@ class Renderer9;
class SwapChain9 : public SwapChainD3D
{
public:
- SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
- GLenum backBufferFormat, GLenum depthBufferFormat);
+ SwapChain9(Renderer9 *renderer,
+ NativeWindow nativeWindow,
+ HANDLE shareHandle,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation);
virtual ~SwapChain9();
EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
@@ -45,8 +49,8 @@ class SwapChain9 : public SwapChainD3D
void release();
Renderer9 *mRenderer;
- EGLint mHeight;
EGLint mWidth;
+ EGLint mHeight;
EGLint mSwapInterval;
IDirect3DSwapChain9 *mSwapChain;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index afa01811024..b931035ef62 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -574,6 +574,9 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->colorBufferFloat = false;
extensions->debugMarker = true;
extensions->eglImage = true;
+ extensions->unpackSubimage = true;
+ extensions->packSubimage = true;
+ extensions->vertexArrayObject = true;
// D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
// state.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp
new file mode 100644
index 00000000000..97eb9929951
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp
@@ -0,0 +1,953 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage_etc.cpp: Decodes ETC and EAC encoded textures.
+
+#include "libANGLE/renderer/d3d/loadimage_etc.h"
+
+#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/imageformats.h"
+
+namespace rx
+{
+namespace
+{
+
+struct ETC2Block
+{
+ // Decodes unsigned single or dual channel block to bytes
+ void decodeAsSingleChannel(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destPixelStride,
+ size_t destRowPitch,
+ bool isSigned) const
+ {
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ uint8_t *row = dest + (j * destRowPitch);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ uint8_t *pixel = row + (i * destPixelStride);
+ if (isSigned)
+ {
+ *pixel = clampSByte(getSingleChannel(i, j, isSigned));
+ }
+ else
+ {
+ *pixel = clampByte(getSingleChannel(i, j, isSigned));
+ }
+ }
+ }
+ }
+
+ // Decodes RGB block to rgba8
+ void decodeAsRGB(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool punchThroughAlpha) const
+ {
+ bool opaqueBit = u.idht.mode.idm.diffbit;
+ bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
+ // Select mode
+ if (u.idht.mode.idm.diffbit || punchThroughAlpha)
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int r = (block.R + block.dR);
+ int g = (block.G + block.dG);
+ int b = (block.B + block.dB);
+ if (r < 0 || r > 31)
+ {
+ decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ else if (g < 0 || g > 31)
+ {
+ decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ else if (b < 0 || b > 31)
+ {
+ decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues);
+ }
+ else
+ {
+ decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+ else
+ {
+ decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+
+ private:
+ union
+ {
+ // Individual, differential, H and T modes
+ struct
+ {
+ union
+ {
+ // Individual and differential modes
+ struct
+ {
+ union
+ {
+ struct // Individual colors
+ {
+ unsigned char R2 : 4;
+ unsigned char R1 : 4;
+ unsigned char G2 : 4;
+ unsigned char G1 : 4;
+ unsigned char B2 : 4;
+ unsigned char B1 : 4;
+ } indiv;
+ struct // Differential colors
+ {
+ signed char dR : 3;
+ unsigned char R : 5;
+ signed char dG : 3;
+ unsigned char G : 5;
+ signed char dB : 3;
+ unsigned char B : 5;
+ } diff;
+ } colors;
+ bool flipbit : 1;
+ bool diffbit : 1;
+ unsigned char cw2 : 3;
+ unsigned char cw1 : 3;
+ } idm;
+ // T mode
+ struct
+ {
+ // Byte 1
+ unsigned char TR1b : 2;
+ unsigned char TdummyB : 1;
+ unsigned char TR1a : 2;
+ unsigned char TdummyA : 3;
+ // Byte 2
+ unsigned char TB1 : 4;
+ unsigned char TG1 : 4;
+ // Byte 3
+ unsigned char TG2 : 4;
+ unsigned char TR2 : 4;
+ // Byte 4
+ unsigned char Tdb : 1;
+ bool Tflipbit : 1;
+ unsigned char Tda : 2;
+ unsigned char TB2 : 4;
+ } tm;
+ // H mode
+ struct
+ {
+ // Byte 1
+ unsigned char HG1a : 3;
+ unsigned char HR1 : 4;
+ unsigned char HdummyA : 1;
+ // Byte 2
+ unsigned char HB1b : 2;
+ unsigned char HdummyC : 1;
+ unsigned char HB1a : 1;
+ unsigned char HG1b : 1;
+ unsigned char HdummyB : 3;
+ // Byte 3
+ unsigned char HG2a : 3;
+ unsigned char HR2 : 4;
+ unsigned char HB1c : 1;
+ // Byte 4
+ unsigned char Hdb : 1;
+ bool Hflipbit : 1;
+ unsigned char Hda : 1;
+ unsigned char HB2 : 4;
+ unsigned char HG2b : 1;
+ } hm;
+ } mode;
+ unsigned char pixelIndexMSB[2];
+ unsigned char pixelIndexLSB[2];
+ } idht;
+ // planar mode
+ struct
+ {
+ // Byte 1
+ unsigned char GO1 : 1;
+ unsigned char RO : 6;
+ unsigned char PdummyA : 1;
+ // Byte 2
+ unsigned char BO1 : 1;
+ unsigned char GO2 : 6;
+ unsigned char PdummyB : 1;
+ // Byte 3
+ unsigned char BO3a : 2;
+ unsigned char PdummyD : 1;
+ unsigned char BO2 : 2;
+ unsigned char PdummyC : 3;
+ // Byte 4
+ unsigned char RH2 : 1;
+ bool Pflipbit : 1;
+ unsigned char RH1 : 5;
+ unsigned char BO3b : 1;
+ // Byte 5
+ unsigned char BHa : 1;
+ unsigned char GH : 7;
+ // Byte 6
+ unsigned char RVa : 3;
+ unsigned char BHb : 5;
+ // Byte 7
+ unsigned char GVa : 5;
+ unsigned char RVb : 3;
+ // Byte 8
+ unsigned char BV : 6;
+ unsigned char GVb : 2;
+ } pblk;
+ // Single channel block
+ struct
+ {
+ union
+ {
+ unsigned char us;
+ signed char s;
+ } base_codeword;
+ unsigned char table_index : 4;
+ unsigned char multiplier : 4;
+ unsigned char mc1 : 2;
+ unsigned char mb : 3;
+ unsigned char ma : 3;
+ unsigned char mf1 : 1;
+ unsigned char me : 3;
+ unsigned char md : 3;
+ unsigned char mc2 : 1;
+ unsigned char mh : 3;
+ unsigned char mg : 3;
+ unsigned char mf2 : 2;
+ unsigned char mk1 : 2;
+ unsigned char mj : 3;
+ unsigned char mi : 3;
+ unsigned char mn1 : 1;
+ unsigned char mm : 3;
+ unsigned char ml : 3;
+ unsigned char mk2 : 1;
+ unsigned char mp : 3;
+ unsigned char mo : 3;
+ unsigned char mn2 : 2;
+ } scblk;
+ } u;
+
+ static unsigned char clampByte(int value)
+ {
+ return static_cast<unsigned char>(gl::clamp(value, 0, 255));
+ }
+
+ static signed char clampSByte(int value)
+ {
+ return static_cast<signed char>(gl::clamp(value, -128, 127));
+ }
+
+ static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha)
+ {
+ R8G8B8A8 rgba;
+ rgba.R = clampByte(red);
+ rgba.G = clampByte(green);
+ rgba.B = clampByte(blue);
+ rgba.A = clampByte(alpha);
+ return rgba;
+ }
+
+ static R8G8B8A8 createRGBA(int red, int green, int blue)
+ {
+ return createRGBA(red, green, blue, 255);
+ }
+
+ static int extend_4to8bits(int x) { return (x << 4) | x; }
+ static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
+ static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
+ static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
+
+ void decodeIndividualBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.indiv;
+ int r1 = extend_4to8bits(block.R1);
+ int g1 = extend_4to8bits(block.G1);
+ int b1 = extend_4to8bits(block.B1);
+ int r2 = extend_4to8bits(block.R2);
+ int g2 = extend_4to8bits(block.G2);
+ int b2 = extend_4to8bits(block.B2);
+ decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void decodeDifferentialBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int b1 = extend_5to8bits(block.B);
+ int g1 = extend_5to8bits(block.G);
+ int r1 = extend_5to8bits(block.R);
+ int r2 = extend_5to8bits(block.R + block.dR);
+ int g2 = extend_5to8bits(block.G + block.dG);
+ int b2 = extend_5to8bits(block.B + block.dB);
+ decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void decodeIndividualOrDifferentialBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ int r1,
+ int g1,
+ int b1,
+ int r2,
+ int g2,
+ int b2,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Table 3.17.2 sorted according to table 3.17.3
+ // clang-format off
+ static const int intensityModifierDefault[8][4] =
+ {
+ { 2, 8, -2, -8 },
+ { 5, 17, -5, -17 },
+ { 9, 29, -9, -29 },
+ { 13, 42, -13, -42 },
+ { 18, 60, -18, -60 },
+ { 24, 80, -24, -80 },
+ { 33, 106, -33, -106 },
+ { 47, 183, -47, -183 },
+ };
+ // clang-format on
+
+ // Table C.12, intensity modifier for non opaque punchthrough alpha
+ // clang-format off
+ static const int intensityModifierNonOpaque[8][4] =
+ {
+ { 0, 8, 0, -8 },
+ { 0, 17, 0, -17 },
+ { 0, 29, 0, -29 },
+ { 0, 42, 0, -42 },
+ { 0, 60, 0, -60 },
+ { 0, 80, 0, -80 },
+ { 0, 106, 0, -106 },
+ { 0, 183, 0, -183 },
+ };
+ // clang-format on
+
+ const int(&intensityModifier)[8][4] =
+ nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
+
+ R8G8B8A8 subblockColors0[4];
+ R8G8B8A8 subblockColors1[4];
+ for (size_t blockIdx = 0; blockIdx < 4; blockIdx++)
+ {
+ const int i1 = intensityModifier[u.idht.mode.idm.cw1][blockIdx];
+ subblockColors0[blockIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
+
+ const int i2 = intensityModifier[u.idht.mode.idm.cw2][blockIdx];
+ subblockColors1[blockIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
+ }
+
+ if (u.idht.mode.idm.flipbit)
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 2 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors0[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ for (size_t j = 2; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors1[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ }
+ else
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 2 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors0[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ for (size_t i = 2; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors1[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ }
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodeTBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.tm;
+
+ int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
+ int g1 = extend_4to8bits(block.TG1);
+ int b1 = extend_4to8bits(block.TB1);
+ int r2 = extend_4to8bits(block.TR2);
+ int g2 = extend_4to8bits(block.TG2);
+ int b2 = extend_4to8bits(block.TB2);
+
+ static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int d = distance[block.Tda << 1 | block.Tdb];
+
+ const R8G8B8A8 paintColors[4] = {
+ createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2),
+ createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = paintColors[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodeHBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.hm;
+
+ int r1 = extend_4to8bits(block.HR1);
+ int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
+ int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
+ int r2 = extend_4to8bits(block.HR2);
+ int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
+ int b2 = extend_4to8bits(block.HB2);
+
+ static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int d = distance[(block.Hda << 2) | (block.Hdb << 1) |
+ ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)];
+
+ const R8G8B8A8 paintColors[4] = {
+ createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
+ createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = paintColors[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodePlanarBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t pitch,
+ const uint8_t alphaValues[4][4]) const
+ {
+ int ro = extend_6to8bits(u.pblk.RO);
+ int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2);
+ int bo =
+ extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b);
+ int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2);
+ int gh = extend_7to8bits(u.pblk.GH);
+ int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb);
+ int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb);
+ int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb);
+ int bv = extend_6to8bits(u.pblk.BV);
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+
+ int ry = static_cast<int>(j) * (rv - ro) + 2;
+ int gy = static_cast<int>(j) * (gv - go) + 2;
+ int by = static_cast<int>(j) * (bv - bo) + 2;
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro,
+ ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go,
+ ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo,
+ alphaValues[j][i]);
+ }
+ curPixel += pitch;
+ }
+ }
+
+ // Index for individual, differential, H and T modes
+ size_t getIndex(size_t x, size_t y) const
+ {
+ size_t bitIndex = x * 4 + y;
+ size_t bitOffset = bitIndex & 7;
+ size_t lsb = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+ size_t msb = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+ return (msb << 1) | lsb;
+ }
+
+ void decodePunchThroughAlphaBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch) const
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ if (getIndex(i, j) == 2) // msb == 1 && lsb == 0
+ {
+ row[i] = createRGBA(0, 0, 0, 0);
+ }
+ }
+ curPixel += destRowPitch;
+ }
+ }
+
+ // Single channel utility functions
+ int getSingleChannel(size_t x, size_t y, bool isSigned) const
+ {
+ int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
+ return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier;
+ }
+
+ int getSingleChannelIndex(size_t x, size_t y) const
+ {
+ ASSERT(x < 4 && y < 4);
+
+ // clang-format off
+ switch (x * 4 + y)
+ {
+ case 0: return u.scblk.ma;
+ case 1: return u.scblk.mb;
+ case 2: return u.scblk.mc1 << 1 | u.scblk.mc2;
+ case 3: return u.scblk.md;
+ case 4: return u.scblk.me;
+ case 5: return u.scblk.mf1 << 2 | u.scblk.mf2;
+ case 6: return u.scblk.mg;
+ case 7: return u.scblk.mh;
+ case 8: return u.scblk.mi;
+ case 9: return u.scblk.mj;
+ case 10: return u.scblk.mk1 << 1 | u.scblk.mk2;
+ case 11: return u.scblk.ml;
+ case 12: return u.scblk.mm;
+ case 13: return u.scblk.mn1 << 2 | u.scblk.mn2;
+ case 14: return u.scblk.mo;
+ case 15: return u.scblk.mp;
+ default: UNREACHABLE(); return 0;
+ }
+ // clang-format on
+ }
+
+ int getSingleChannelModifier(size_t x, size_t y) const
+ {
+ // clang-format off
+ static const int modifierTable[16][8] =
+ {
+ { -3, -6, -9, -15, 2, 5, 8, 14 },
+ { -3, -7, -10, -13, 2, 6, 9, 12 },
+ { -2, -5, -8, -13, 1, 4, 7, 12 },
+ { -2, -4, -6, -13, 1, 3, 5, 12 },
+ { -3, -6, -8, -12, 2, 5, 7, 11 },
+ { -3, -7, -9, -11, 2, 6, 8, 10 },
+ { -4, -7, -8, -11, 3, 6, 7, 10 },
+ { -3, -5, -8, -11, 2, 4, 7, 10 },
+ { -2, -6, -8, -10, 1, 5, 7, 9 },
+ { -2, -5, -8, -10, 1, 4, 7, 9 },
+ { -2, -4, -8, -10, 1, 3, 7, 9 },
+ { -2, -5, -7, -10, 1, 4, 6, 9 },
+ { -3, -4, -7, -10, 2, 3, 6, 9 },
+ { -1, -2, -3, -10, 0, 1, 2, 9 },
+ { -4, -6, -8, -9, 3, 5, 7, 8 },
+ { -3, -5, -7, -9, 2, 4, 6, 8 }
+ };
+ // clang-format on
+
+ return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)];
+ }
+};
+
+// clang-format off
+static const uint8_t DefaultETCAlphaValues[4][4] =
+{
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+};
+// clang-format on
+
+void LoadR11EACToR8(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,
+ bool isSigned)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlock = sourceRow + (x / 4);
+ uint8_t *destPixels = destRow + x;
+
+ sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1,
+ outputRowPitch, isSigned);
+ }
+ }
+ }
+}
+
+void LoadRG11EACToRG8(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,
+ bool isSigned)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ uint8_t *destPixelsRed = destRow + (x * 2);
+ const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
+ sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2,
+ outputRowPitch, isSigned);
+
+ uint8_t *destPixelsGreen = destPixelsRed + 1;
+ const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
+ sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2,
+ outputRowPitch, isSigned);
+ }
+ }
+ }
+}
+
+void LoadETC2RGB8ToRGBA8(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,
+ bool punchthroughAlpha)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlock = sourceRow + (x / 4);
+ uint8_t *destPixels = destRow + (x * 4);
+
+ sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+ DefaultETCAlphaValues, punchthroughAlpha);
+ }
+ }
+ }
+}
+
+void LoadETC2RGBA8ToRGBA8(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,
+ bool srgb)
+{
+ uint8_t decodedAlphaValues[4][4];
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
+ sourceBlockAlpha->decodeAsSingleChannel(
+ reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
+ false);
+
+ uint8_t *destPixels = destRow + (x * 4);
+ const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
+ sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+ decodedAlphaValues, false);
+ }
+ }
+ }
+}
+
+} // anonymous namespace
+
+void LoadETC1RGB8ToRGBA8(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)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11ToR8(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)
+{
+ LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11SToR8(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)
+{
+ LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadEACRG11ToRG8(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)
+{
+ LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACRG11SToRG8(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)
+{
+ LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGB8ToRGBA8(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)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGB8ToRGBA8(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)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2RGB8A1ToRGBA8(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)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2SRGB8A1ToRGBA8(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)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGBA8ToRGBA8(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)
+{
+ LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGBA8ToSRGBA8(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)
+{
+ LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h
new file mode 100644
index 00000000000..2ada743a243
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/loadimage_etc.h
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage_etc.h: Decodes ETC and EAC encoded textures.
+
+#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
+#define LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
+
+#include "libANGLE/angletypes.h"
+
+#include <stdint.h>
+
+namespace rx
+{
+
+void LoadETC1RGB8ToRGBA8(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 LoadEACR11ToR8(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 LoadEACR11SToR8(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 LoadEACRG11ToRG8(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 LoadEACRG11SToRG8(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 LoadETC2RGB8ToRGBA8(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 LoadETC2SRGB8ToRGBA8(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 LoadETC2RGB8A1ToRGBA8(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 LoadETC2SRGB8A1ToRGBA8(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 LoadETC2RGBA8ToRGBA8(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 LoadETC2SRGBA8ToSRGBA8(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);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp
index b6aa401fc53..0a624dcb17d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -58,10 +58,14 @@ BlitGL::BlitGL(const FunctionsGL *functions,
mWorkarounds(workarounds),
mStateManager(stateManager),
mBlitProgram(0),
- mScratchTexture(0),
mScratchFBO(0),
mVAO(0)
{
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
+ {
+ mScratchTextures[i] = 0;
+ }
+
ASSERT(mFunctions);
ASSERT(mStateManager);
}
@@ -70,25 +74,28 @@ BlitGL::~BlitGL()
{
if (mBlitProgram != 0)
{
- mFunctions->deleteProgram(mBlitProgram);
+ mStateManager->deleteProgram(mBlitProgram);
mBlitProgram = 0;
}
- if (mScratchTexture != 0)
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
{
- mFunctions->deleteTextures(1, &mScratchTexture);
- mScratchTexture = 0;
+ if (mScratchTextures[i] != 0)
+ {
+ mStateManager->deleteTexture(mScratchTextures[i]);
+ mScratchTextures[i] = 0;
+ }
}
if (mScratchFBO != 0)
{
- mFunctions->deleteFramebuffers(1, &mScratchFBO);
+ mStateManager->deleteFramebuffer(mScratchFBO);
mScratchFBO = 0;
}
if (mVAO != 0)
{
- mFunctions->deleteVertexArrays(1, &mVAO);
+ mStateManager->deleteVertexArray(mVAO);
mVAO = 0;
}
}
@@ -129,16 +136,18 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
return error;
}
- // Blit the framebuffer to the scratch texture
+ // Blit the framebuffer to the first scratch texture
const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
mFunctions, mWorkarounds, source->getImplementationColorReadFormat(),
source->getImplementationColorReadType());
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat);
mStateManager->activeTexture(0);
- mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
sourceArea.y, sourceArea.width, sourceArea.height, 0);
@@ -150,15 +159,20 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
};
mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
- // Make a temporary framebuffer using the destination texture
+ // Make a temporary framebuffer using the second scratch texture to render the swizzled result
+ // to.
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[1]);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width,
+ sourceArea.height, 0, internalFormatInfo.format,
+ source->getImplementationColorReadType(), nullptr);
+
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
- mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture,
- static_cast<GLint>(level));
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mScratchTextures[1], 0);
// Render to the destination texture, sampling from the scratch texture
mStateManager->useProgram(mBlitProgram);
- mStateManager->setViewport(
- gl::Rectangle(destOffset.x, destOffset.y, sourceArea.width, sourceArea.height));
+ mStateManager->setViewport(gl::Rectangle(0, 0, sourceArea.width, sourceArea.height));
mStateManager->setScissorTestEnabled(false);
mStateManager->setDepthRange(0.0f, 1.0f);
mStateManager->setBlendEnabled(false);
@@ -170,11 +184,17 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
mStateManager->setCullFaceEnabled(false);
mStateManager->setPolygonOffsetFillEnabled(false);
mStateManager->setRasterizerDiscardEnabled(false);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
mStateManager->bindVertexArray(mVAO, 0);
mFunctions->drawArrays(GL_TRIANGLES, 0, 6);
+ // Finally, copy the swizzled texture to the destination texture
+ mStateManager->bindTexture(textureType, texture);
+ mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y, 0,
+ 0, sourceArea.width, sourceArea.height);
+
return gl::Error(GL_NO_ERROR);
}
@@ -256,14 +276,17 @@ gl::Error BlitGL::initializeResources()
mFunctions->uniform1i(textureUniform, 0);
}
- if (mScratchTexture == 0)
+ for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
{
- mFunctions->genTextures(1, &mScratchTexture);
- mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTexture);
+ if (mScratchTextures[i] == 0)
+ {
+ mFunctions->genTextures(1, &mScratchTextures[i]);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[i]);
- // Use nearest, non-mipmapped sampling with the scratch texture
- mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ // Use nearest, non-mipmapped sampling with the scratch texture
+ mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
}
if (mScratchFBO == 0)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h
index 6d7d34f9256..3ab8319bb13 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/BlitGL.h
@@ -61,7 +61,7 @@ class BlitGL : public angle::NonCopyable
GLuint mBlitProgram;
- GLuint mScratchTexture;
+ GLuint mScratchTextures[2];
GLuint mScratchFBO;
GLuint mVAO;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
index 8c809d6ce8b..16cbc3c7345 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
@@ -62,8 +62,10 @@ egl::Error DisplayGL::createContext(const egl::Config *config, const gl::Context
EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT);
bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
+ bool debug = (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
- *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
+ *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets,
+ robustAccess, debug);
return egl::Error(EGL_SUCCESS);
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 92e08cc06f3..1f4f4e03fcd 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -19,6 +19,7 @@
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "platform/Platform.h"
namespace rx
{
@@ -212,7 +213,10 @@ gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
return gl::Error(GL_NO_ERROR);
}
-gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+gl::Error FramebufferGL::clearBufferfv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
{
syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
@@ -221,7 +225,10 @@ gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GL
return gl::Error(GL_NO_ERROR);
}
-gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
+gl::Error FramebufferGL::clearBufferuiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
{
syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
@@ -230,7 +237,10 @@ gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, G
return gl::Error(GL_NO_ERROR);
}
-gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
+gl::Error FramebufferGL::clearBufferiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
{
syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
@@ -239,7 +249,11 @@ gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GL
return gl::Error(GL_NO_ERROR);
}
-gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+gl::Error FramebufferGL::clearBufferfi(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
{
syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
@@ -285,17 +299,21 @@ gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourc
mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
- mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
- destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
- mask, filter);
+ mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
+ destArea.x, destArea.y, destArea.x1(), destArea.y1(), mask, filter);
return gl::Error(GL_NO_ERROR);
}
-GLenum FramebufferGL::checkStatus() const
+bool FramebufferGL::checkStatus() const
{
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
- return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
+ GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
+ }
+ return (status == GL_FRAMEBUFFER_COMPLETE);
}
GLuint FramebufferGL::getFramebufferID() const
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h
index edc4fa7fafe..f8d006ac697 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -49,10 +49,23 @@ class FramebufferGL : public FramebufferImpl
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
gl::Error clear(const gl::Data &data, GLbitfield mask) override;
- gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
- gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
- gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override;
- gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
+ gl::Error clearBufferfv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ gl::Error clearBufferuiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ gl::Error clearBufferiv(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ gl::Error clearBufferfi(const gl::Data &data,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
GLenum getImplementationColorReadFormat() const override;
GLenum getImplementationColorReadType() const override;
@@ -61,7 +74,7 @@ class FramebufferGL : public FramebufferImpl
gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
- GLenum checkStatus() const override;
+ bool checkStatus() const override;
void syncDrawState() const;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
index d3b6f824635..37e13a4d3b1 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -788,14 +788,11 @@ void FunctionsGL::initialize()
}
// Check the context profile
+ profile = 0;
if (isAtLeastGL(gl::Version(3, 2)))
{
getIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
}
- else
- {
- profile = 0;
- }
// clang-format off
@@ -908,6 +905,39 @@ void FunctionsGL::initialize()
AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIiv"), &getSamplerParameterIiv);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_sampler_objects", loadProcAddress("glGetSamplerParameterIuiv"), &getSamplerParameterIuiv);
+ // GL_ARB_occlusion_query
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGenQueriesARB"), &genQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glDeleteQueriesARB"), &deleteQueries);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glIsQueryARB"), &isQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glBeginQueryARB"), &beginQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glEndQueryARB"), &endQuery);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryivARB"), &getQueryiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv);
+
+ // EXT_transform_feedback
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferRangeEXT"), &bindBufferRange);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferBaseEXT"), &bindBufferBase);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBeginTransformFeedbackEXT"), &beginTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glEndTransformFeedbackEXT"), &endTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glTransformFeedbackVaryingsEXT"), &transformFeedbackVaryings);
+ AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glGetTransformFeedbackVaryingEXT"), &getTransformFeedbackVarying);
+
+ // GL_ARB_transform_feedback2
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glIsTransformFeedback"), &isTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback);
+
+ // GL_ARB_transform_feedback3
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glEndQueryIndexed"), &endQueryIndexed);
+ AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv);
+
// 1.0
if (isAtLeastGL(gl::Version(1, 0)))
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
index b05d7f5b509..f5adc3b29bd 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -13,6 +13,7 @@
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "platform/Platform.h"
namespace rx
{
@@ -46,11 +47,39 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_INVALID_OPERATION);
}
+void ProgramGL::setBinaryRetrievableHint(bool retrievable)
+{
+ UNIMPLEMENTED();
+}
+
LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
{
// Reset the program state, delete the current program if one exists
reset();
+ // Set the transform feedback state
+ std::vector<const GLchar *> transformFeedbackVaryings;
+ for (const auto &tfVarying : mData.getTransformFeedbackVaryingNames())
+ {
+ transformFeedbackVaryings.push_back(tfVarying.c_str());
+ }
+
+ if (transformFeedbackVaryings.empty())
+ {
+ if (mFunctions->transformFeedbackVaryings)
+ {
+ mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
+ mData.getTransformFeedbackBufferMode());
+ }
+ }
+ else
+ {
+ ASSERT(mFunctions->transformFeedbackVaryings);
+ mFunctions->transformFeedbackVaryings(
+ mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
+ &transformFeedbackVaryings[0], mData.getTransformFeedbackBufferMode());
+ }
+
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
@@ -82,7 +111,6 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
// Verify the link
GLint linkStatus = GL_FALSE;
mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
- ASSERT(linkStatus == GL_TRUE);
if (linkStatus == GL_FALSE)
{
// Linking failed, put the error into the info log
@@ -95,8 +123,11 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
mFunctions->deleteProgram(mProgramID);
mProgramID = 0;
- infoLog << &buf[0];
- TRACE("\n%s", &buf[0]);
+ infoLog << buf.data();
+
+ std::string warning = FormatString("Program link failed unexpectedly: %s", buf.data());
+ ANGLEPlatformCurrent()->logWarning(warning.c_str());
+ TRACE("\n%s", warning.c_str());
// TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
return LinkResult(false, gl::Error(GL_NO_ERROR));
@@ -289,13 +320,29 @@ void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean t
void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
- mFunctions->uniformBlockBinding(mProgramID, mUniformBlockRealLocationMap[uniformBlockIndex],
- uniformBlockBinding);
+ // Lazy init
+ if (mUniformBlockRealLocationMap.empty())
+ {
+ mUniformBlockRealLocationMap.reserve(mData.getUniformBlocks().size());
+ for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
+ {
+ const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
+ GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
+ mUniformBlockRealLocationMap.push_back(blockIndex);
+ }
+ }
+
+ GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
+ if (realBlockIndex != GL_INVALID_INDEX)
+ {
+ mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
+ }
}
void ProgramGL::reset()
{
mUniformRealLocationMap.clear();
+ mUniformBlockRealLocationMap.clear();
mSamplerBindings.clear();
mUniformIndexToSamplerIndex.clear();
}
@@ -310,105 +357,50 @@ const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() cons
return mSamplerBindings;
}
-void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
- std::vector<gl::LinkedUniform> *uniforms)
+bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
{
- mUniformBlockRealLocationMap.resize(uniformBlocks->size(), 0);
+ ASSERT(mProgramID != 0u);
- for (int i = 0; i < static_cast<int>(uniformBlocks->size()); i++)
+ GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
+ if (blockIndex == GL_INVALID_INDEX)
{
- auto &uniformBlock = uniformBlocks->at(i);
-
- std::stringstream fullNameStr;
- fullNameStr << uniformBlock.name;
- if (uniformBlock.isArray)
- {
- fullNameStr << "[" << uniformBlock.arrayElement << "]";
- }
-
- GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, fullNameStr.str().c_str());
- if (blockIndex != GL_INVALID_INDEX)
- {
- mUniformBlockRealLocationMap[i] = blockIndex;
-
- GLint dataSize = 0;
- mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
- &dataSize);
- uniformBlock.dataSize = dataSize;
- }
- else
- {
- // Remove this uniform block
- uniformBlocks->erase(uniformBlocks->begin() + i);
- i--;
- }
+ *sizeOut = 0;
+ return false;
}
- for (int uniformIdx = 0; uniformIdx < static_cast<int>(uniforms->size()); uniformIdx++)
- {
- auto &uniform = uniforms->at(uniformIdx);
- if (uniform.isInDefaultBlock())
- {
- continue;
- }
+ GLint dataSize = 0;
+ mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
+ &dataSize);
+ *sizeOut = static_cast<size_t>(dataSize);
+ return true;
+}
- const GLchar *uniformName = uniform.name.c_str();
- GLuint uniformIndex = 0;
- mFunctions->getUniformIndices(mProgramID, 1, &uniformName, &uniformIndex);
+bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const
+{
+ GLuint uniformIndex;
+ const GLchar *memberNameGLStr = memberUniformName.c_str();
+ mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
- if (uniformIndex == GL_INVALID_INDEX)
- {
- // Uniform member has been optimized out, remove it from the list
- // TODO: Clean this up by using a class to wrap around the uniforms so manual removal is
- // not needed.
- for (size_t uniformBlockIdx = 0; uniformBlockIdx < uniformBlocks->size();
- uniformBlockIdx++)
- {
- auto &uniformBlock = uniformBlocks->at(uniformBlockIdx);
- for (int memberIndex = 0;
- memberIndex < static_cast<int>(uniformBlock.memberUniformIndexes.size());
- memberIndex++)
- {
- if (uniformBlock.memberUniformIndexes[memberIndex] ==
- static_cast<unsigned int>(uniformIdx))
- {
- uniformBlock.memberUniformIndexes.erase(
- uniformBlock.memberUniformIndexes.begin() + memberIndex);
- memberIndex--;
- }
- else if (uniformBlock.memberUniformIndexes[memberIndex] >
- static_cast<unsigned int>(uniformIdx))
- {
- uniformBlock.memberUniformIndexes[memberIndex]--;
- }
- }
- }
- uniforms->erase(uniforms->begin() + uniformIdx);
- uniformIdx--;
- }
- else
- {
- GLint offset = 0;
- mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
- &offset);
- uniform.blockInfo.offset = offset;
-
- GLint arrayStride = 0;
- mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
- &arrayStride);
- uniform.blockInfo.arrayStride = arrayStride;
-
- GLint matrixStride = 0;
- mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
- &matrixStride);
- uniform.blockInfo.matrixStride = matrixStride;
-
- // TODO: determine this at the gl::Program level.
- GLint isRowMajorMatrix = 0;
- mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
- &isRowMajorMatrix);
- uniform.blockInfo.isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
- }
+ if (uniformIndex == GL_INVALID_INDEX)
+ {
+ *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return false;
}
+
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
+ &memberInfoOut->offset);
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
+ &memberInfoOut->arrayStride);
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
+ &memberInfoOut->matrixStride);
+
+ // TODO(jmadill): possibly determine this at the gl::Program level.
+ GLint isRowMajorMatrix = 0;
+ mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
+ &isRowMajorMatrix);
+ memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
+ return true;
}
-}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
index 35c755ed6f1..fa343688a61 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
@@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
gl::Error save(gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
@@ -61,8 +62,9 @@ class ProgramGL : public ProgramImpl
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
- void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
- std::vector<gl::LinkedUniform> *uniforms) override;
+ bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
+ bool getUniformBlockMemberInfo(const std::string &memberUniformName,
+ sh::BlockMemberInfo *memberInfoOut) const override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
index 8f1d25f3bbd..a8c9a9b9885 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
@@ -9,39 +9,160 @@
#include "libANGLE/renderer/gl/QueryGL.h"
#include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+
+namespace
+{
+
+GLuint MergeQueryResults(GLenum type, GLuint currentResult, GLuint newResult)
+{
+ switch (type)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return currentResult + newResult;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // anonymous namespace
namespace rx
{
-QueryGL::QueryGL(GLenum type)
- : QueryImpl(type)
-{}
+QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
+ : QueryImpl(type),
+ mType(type),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mActiveQuery(0),
+ mPendingQueries(),
+ mResultSum(0)
+{
+}
QueryGL::~QueryGL()
-{}
+{
+ mStateManager->deleteQuery(mActiveQuery);
+ mStateManager->onDeleteQueryObject(this);
+ while (!mPendingQueries.empty())
+ {
+ mStateManager->deleteQuery(mPendingQueries.front());
+ mPendingQueries.pop_front();
+ }
+}
gl::Error QueryGL::begin()
{
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION);
+ mResultSum = 0;
+ return gl::Error(GL_NO_ERROR);
}
gl::Error QueryGL::end()
{
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION);
+ return pause();
}
gl::Error QueryGL::getResult(GLuint *params)
{
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION);
+ ASSERT(mActiveQuery == 0);
+
+ gl::Error error = flush(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(mPendingQueries.empty());
+ *params = mResultSum;
+
+ return gl::Error(GL_NO_ERROR);
}
gl::Error QueryGL::isResultAvailable(GLuint *available)
{
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION);
+ ASSERT(mActiveQuery == 0);
+
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *available = mPendingQueries.empty() ? GL_TRUE : GL_FALSE;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::pause()
+{
+ if (mActiveQuery != 0)
+ {
+ mStateManager->endQuery(mType, mActiveQuery);
+
+ mPendingQueries.push_back(mActiveQuery);
+ mActiveQuery = 0;
+ }
+
+ // Flush to make sure the pending queries don't add up too much.
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::resume()
+{
+ if (mActiveQuery == 0)
+ {
+ // Flush to make sure the pending queries don't add up too much.
+ gl::Error error = flush(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mFunctions->genQueries(1, &mActiveQuery);
+ mStateManager->beginQuery(mType, mActiveQuery);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error QueryGL::flush(bool force)
+{
+ while (!mPendingQueries.empty())
+ {
+ GLuint id = mPendingQueries.front();
+ if (!force)
+ {
+ GLuint resultAvailable = 0;
+ mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
+ if (resultAvailable == GL_FALSE)
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+ }
+
+ GLuint result = 0;
+ mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
+ mResultSum = MergeQueryResults(mType, mResultSum, result);
+
+ mStateManager->deleteQuery(id);
+
+ mPendingQueries.pop_front();
+ }
+
+ return gl::Error(GL_NO_ERROR);
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h
index c6b7cfbfef4..7385ff9dcfc 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.h
@@ -9,21 +9,47 @@
#ifndef LIBANGLE_RENDERER_GL_QUERYGL_H_
#define LIBANGLE_RENDERER_GL_QUERYGL_H_
+#include <deque>
+
#include "libANGLE/renderer/QueryImpl.h"
namespace rx
{
+class FunctionsGL;
+class StateManagerGL;
+
class QueryGL : public QueryImpl
{
public:
- QueryGL(GLenum type);
+ QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager);
~QueryGL() override;
gl::Error begin() override;
gl::Error end() override;
gl::Error getResult(GLuint *params) override;
gl::Error isResultAvailable(GLuint *available) override;
+
+ // OpenGL is only allowed to have one query of each type active at any given time. Since ANGLE
+ // virtualizes contexts, queries need to be able to be paused and resumed.
+ // A query is "paused" by ending it and pushing the ID into a list of queries awaiting readback.
+ // When it is "resumed", a new query is generated and started.
+ // When a result is required, the queries are "flushed" by iterating over the list of pending
+ // queries and merging their results.
+ gl::Error pause();
+ gl::Error resume();
+
+ private:
+ gl::Error flush(bool force);
+
+ GLenum mType;
+
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mActiveQuery;
+ std::deque<GLuint> mPendingQueries;
+ GLuint mResultSum;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
index 6a8ab11a3d5..0661b8d3bf6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -86,6 +86,7 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
mFunctions(functions),
mStateManager(nullptr),
mBlitter(nullptr),
+ mHasDebugOutput(false),
mSkipDrawCalls(false)
{
ASSERT(mFunctions);
@@ -93,8 +94,12 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
mBlitter = new BlitGL(functions, mWorkarounds, mStateManager);
+ mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
+ mFunctions->hasGLExtension("GL_KHR_debug") ||
+ mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
+ mFunctions->hasGLESExtension("GL_KHR_debug");
#ifndef NDEBUG
- if (mFunctions->debugMessageControl && mFunctions->debugMessageCallback)
+ if (mHasDebugOutput)
{
mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE);
@@ -114,8 +119,8 @@ RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &at
RendererGL::~RendererGL()
{
- SafeDelete(mStateManager);
SafeDelete(mBlitter);
+ SafeDelete(mStateManager);
}
gl::Error RendererGL::flush()
@@ -126,7 +131,22 @@ gl::Error RendererGL::flush()
gl::Error RendererGL::finish()
{
+#ifdef NDEBUG
+ if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+ {
+ mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
+#endif
+
mFunctions->finish();
+
+#ifdef NDEBUG
+ if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
+ {
+ mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
+#endif
+
return gl::Error(GL_NO_ERROR);
}
@@ -280,7 +300,7 @@ VertexArrayImpl *RendererGL::createVertexArray(const gl::VertexArray::Data &data
QueryImpl *RendererGL::createQuery(GLenum type)
{
- return new QueryGL(type);
+ return new QueryGL(type, mFunctions, mStateManager);
}
FenceNVImpl *RendererGL::createFenceNV()
@@ -295,7 +315,8 @@ FenceSyncImpl *RendererGL::createFenceSync()
TransformFeedbackImpl *RendererGL::createTransformFeedback()
{
- return new TransformFeedbackGL();
+ return new TransformFeedbackGL(mFunctions, mStateManager,
+ getRendererCaps().maxTransformFeedbackSeparateComponents);
}
SamplerImpl *RendererGL::createSampler()
@@ -342,12 +363,6 @@ bool RendererGL::testDeviceResettable()
return bool();
}
-VendorID RendererGL::getVendorId() const
-{
- UNIMPLEMENTED();
- return VendorID();
-}
-
std::string RendererGL::getVendorString() const
{
return std::string(reinterpret_cast<const char*>(mFunctions->getString(GL_VENDOR)));
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
index e52502dc873..4d51bb5ac6e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
@@ -99,7 +99,6 @@ class RendererGL : public Renderer
bool testDeviceLost() override;
bool testDeviceResettable() override;
- VendorID getVendorId() const override;
std::string getVendorString() const override;
std::string getRendererDescription() const override;
@@ -124,6 +123,8 @@ class RendererGL : public Renderer
WorkaroundsGL mWorkarounds;
+ bool mHasDebugOutput;
+
// For performance debugging
bool mSkipDrawCalls;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
index 52efd449fd6..4a6e2f14dd6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
@@ -36,7 +36,8 @@ ShaderGL::~ShaderGL()
}
}
-int ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream)
+int ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string * /*sourcePath*/)
{
// Reset the previous state
if (mShaderID != 0)
@@ -70,7 +71,6 @@ bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog
// Check for compile errors from the native driver
GLint compileStatus = GL_FALSE;
mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus);
- ASSERT(compileStatus == GL_TRUE);
if (compileStatus == GL_FALSE)
{
// Compilation failed, put the error into the info log
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
index c3e0982e87c..76139ace8f3 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
@@ -25,7 +25,8 @@ class ShaderGL : public ShaderImpl
~ShaderGL() override;
// ShaderImpl implementation
- int prepareSourceAndReturnOptions(std::stringstream *sourceStream) override;
+ int prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
index 33dc97cf0ee..037f5d57254 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -11,18 +11,25 @@
#include "common/BitSetIterator.h"
#include "libANGLE/Data.h"
#include "libANGLE/Framebuffer.h"
+#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
+#include "libANGLE/Query.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/SamplerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "libANGLE/renderer/gl/VertexArrayGL.h"
+#include "libANGLE/renderer/gl/QueryGL.h"
namespace rx
{
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
+
StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0)
{
}
@@ -37,6 +44,11 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mTextureUnitIndex(0),
mTextures(),
mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
+ mTransformFeedback(0),
+ mQueries(),
+ mPrevDrawTransformFeedback(nullptr),
+ mPrevDrawQueries(),
+ mPrevDrawContext(0),
mUnpackAlignment(4),
mUnpackRowLength(0),
mUnpackSkipRows(0),
@@ -111,6 +123,11 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
+ for (GLenum queryType : QueryTypes)
+ {
+ mQueries[queryType] = 0;
+ }
+
// Initialize point sprite state for desktop GL
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
@@ -246,6 +263,41 @@ void StateManagerGL::deleteRenderbuffer(GLuint rbo)
}
}
+void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
+{
+ if (transformFeedback != 0)
+ {
+ if (mTransformFeedback == transformFeedback)
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+ }
+
+ if (mPrevDrawTransformFeedback != nullptr &&
+ mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback)
+ {
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
+ }
+}
+
+void StateManagerGL::deleteQuery(GLuint query)
+{
+ if (query != 0)
+ {
+ for (auto &activeQuery : mQueries)
+ {
+ GLuint activeQueryID = activeQuery.second;
+ if (activeQueryID == query)
+ {
+ GLenum type = activeQuery.first;
+ endQuery(type, query);
+ }
+ }
+ }
+}
+
void StateManagerGL::useProgram(GLuint program)
{
if (mProgram != program)
@@ -487,6 +539,49 @@ void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
}
}
+void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
+{
+ ASSERT(type == GL_TRANSFORM_FEEDBACK);
+ if (mTransformFeedback != transformFeedback)
+ {
+ // Pause the current transform feedback if one is active.
+ // To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
+ // feedback at any time, even if there is one active.
+ if (mPrevDrawTransformFeedback != nullptr &&
+ mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback)
+ {
+ mPrevDrawTransformFeedback->syncPausedState(true);
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ mTransformFeedback = transformFeedback;
+ mFunctions->bindTransformFeedback(type, mTransformFeedback);
+ }
+}
+
+void StateManagerGL::beginQuery(GLenum type, GLuint query)
+{
+ // Make sure this is a valid query type and there is no current active query of this type
+ ASSERT(mQueries.find(type) != mQueries.end());
+ ASSERT(mQueries[type] == 0);
+ ASSERT(query != 0);
+
+ mQueries[type] = query;
+ mFunctions->beginQuery(type, query);
+}
+
+void StateManagerGL::endQuery(GLenum type, GLuint query)
+{
+ ASSERT(mQueries[type] == query);
+ mQueries[type] = 0;
+ mFunctions->endQuery(type);
+}
+
+void StateManagerGL::onDeleteQueryObject(QueryGL *query)
+{
+ mPrevDrawQueries.erase(query);
+}
+
gl::Error StateManagerGL::setDrawArraysState(const gl::Data &data,
GLint first,
GLsizei count,
@@ -542,12 +637,30 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
{
const gl::State &state = *data.state;
+ // If the context has changed, pause the previous context's transform feedback and queries
+ if (data.context != mPrevDrawContext)
+ {
+ if (mPrevDrawTransformFeedback != nullptr)
+ {
+ mPrevDrawTransformFeedback->syncPausedState(true);
+ }
+
+ for (QueryGL *prevQuery : mPrevDrawQueries)
+ {
+ prevQuery->pause();
+ }
+ }
+ mPrevDrawTransformFeedback = nullptr;
+ mPrevDrawQueries.clear();
+
+ mPrevDrawContext = data.context;
+
+ // Sync the current program state
const gl::Program *program = state.getProgram();
const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID());
- for (size_t uniformBlockIndex = 0;
- uniformBlockIndex < gl::IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS;
+ for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
uniformBlockIndex++)
{
GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
@@ -620,6 +733,37 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
// Seamless cubemaps are required for ES3 and higher contexts.
setTextureCubemapSeamlessEnabled(data.clientVersion >= 3);
+ // Set the current transform feedback state
+ gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+ if (transformFeedback)
+ {
+ TransformFeedbackGL *transformFeedbackGL =
+ GetImplAs<TransformFeedbackGL>(transformFeedback);
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
+ transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
+ transformFeedback->getPrimitiveMode());
+ transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
+ mPrevDrawTransformFeedback = transformFeedbackGL;
+ }
+ else
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+ mPrevDrawTransformFeedback = nullptr;
+ }
+
+ // Set the current query state
+ for (GLenum queryType : QueryTypes)
+ {
+ gl::Query *query = state.getActiveQuery(queryType);
+ if (query != nullptr)
+ {
+ QueryGL *queryGL = GetImplAs<QueryGL>(query);
+ queryGL->resume();
+
+ mPrevDrawQueries.insert(queryGL);
+ }
+ }
+
return gl::Error(GL_NO_ERROR);
}
@@ -1133,7 +1277,7 @@ void StateManagerGL::setClearStencil(GLint clearStencil)
void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
{
// TODO(jmadill): Investigate only syncing vertex state for active attributes
- for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits))
+ for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits))
{
switch (dirtyBit)
{
@@ -1277,6 +1421,22 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
// TODO(jmadill): split this
setPixelUnpackState(state.getUnpackState());
break;
+ case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
+ case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS:
+ // TODO(jmadill): split this
+ setPixelUnpackState(state.getUnpackState());
+ break;
case gl::State::DIRTY_BIT_PACK_ALIGNMENT:
// TODO(jmadill): split this
setPixelPackState(state.getPackState());
@@ -1285,6 +1445,18 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
// TODO(jmadill): split this
setPixelPackState(state.getPackState());
break;
+ case gl::State::DIRTY_BIT_PACK_ROW_LENGTH:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_SKIP_ROWS:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
+ case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS:
+ // TODO(jmadill): split this
+ setPixelPackState(state.getPackState());
+ break;
case gl::State::DIRTY_BIT_DITHER_ENABLED:
// TODO(jmadill): implement this
break;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
index 2697acc872c..b430208ae20 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -28,6 +28,8 @@ namespace rx
{
class FunctionsGL;
+class TransformFeedbackGL;
+class QueryGL;
class StateManagerGL final : angle::NonCopyable
{
@@ -41,6 +43,8 @@ class StateManagerGL final : angle::NonCopyable
void deleteBuffer(GLuint buffer);
void deleteFramebuffer(GLuint fbo);
void deleteRenderbuffer(GLuint rbo);
+ void deleteTransformFeedback(GLuint transformFeedback);
+ void deleteQuery(GLuint query);
void useProgram(GLuint program);
void bindVertexArray(GLuint vao, GLuint elementArrayBuffer);
@@ -52,6 +56,9 @@ class StateManagerGL final : angle::NonCopyable
void bindSampler(size_t unit, GLuint sampler);
void bindFramebuffer(GLenum type, GLuint framebuffer);
void bindRenderbuffer(GLenum type, GLuint renderbuffer);
+ void bindTransformFeedback(GLenum type, GLuint transformFeedback);
+ void beginQuery(GLenum type, GLuint query);
+ void endQuery(GLenum type, GLuint query);
void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data);
@@ -115,6 +122,8 @@ class StateManagerGL final : angle::NonCopyable
void setFramebufferSRGBEnabled(bool enabled);
+ void onDeleteQueryObject(QueryGL *query);
+
gl::Error setDrawArraysState(const gl::Data &data,
GLint first,
GLsizei count,
@@ -156,6 +165,14 @@ class StateManagerGL final : angle::NonCopyable
std::map<GLenum, std::vector<GLuint>> mTextures;
std::vector<GLuint> mSamplers;
+ GLuint mTransformFeedback;
+
+ std::map<GLenum, GLuint> mQueries;
+
+ TransformFeedbackGL *mPrevDrawTransformFeedback;
+ std::set<QueryGL *> mPrevDrawQueries;
+ uintptr_t mPrevDrawContext;
+
GLint mUnpackAlignment;
GLint mUnpackRowLength;
GLint mUnpackSkipRows;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
index 62754448c19..c325bb199a9 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
@@ -9,51 +9,134 @@
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "common/debug.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/renderer/gl/BufferGL.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
namespace rx
{
-TransformFeedbackGL::TransformFeedbackGL()
- : TransformFeedbackImpl()
-{}
+TransformFeedbackGL::TransformFeedbackGL(const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ size_t maxTransformFeedbackBufferBindings)
+ : TransformFeedbackImpl(),
+ mFunctions(functions),
+ mStateManager(stateManager),
+ mTransformFeedbackID(0),
+ mIsActive(false),
+ mIsPaused(false),
+ mCurrentIndexedBuffers(maxTransformFeedbackBufferBindings)
+{
+ mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
+}
TransformFeedbackGL::~TransformFeedbackGL()
-{}
+{
+ mStateManager->deleteTransformFeedback(mTransformFeedbackID);
+ mTransformFeedbackID = 0;
+
+ for (auto &bufferBinding : mCurrentIndexedBuffers)
+ {
+ bufferBinding.set(nullptr);
+ }
+}
void TransformFeedbackGL::begin(GLenum primitiveMode)
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
+ // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback.
}
void TransformFeedbackGL::end()
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
+ syncActiveState(false, GL_NONE);
}
void TransformFeedbackGL::pause()
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
+ syncPausedState(true);
}
void TransformFeedbackGL::resume()
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
+ // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback.
}
void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
}
void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
{
- // Skipped to prevent assertions in tests
- // UNIMPLEMENTED();
+ // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
+ // tracked per transform feedback object
+ if (binding != mCurrentIndexedBuffers[index])
+ {
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (binding.get() != nullptr)
+ {
+ const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
+ if (binding.getSize() != 0)
+ {
+ mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
+ static_cast<GLuint>(index), bufferGL->getBufferID(),
+ binding.getOffset(), binding.getSize());
+ }
+ else
+ {
+ mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
+ bufferGL->getBufferID());
+ }
+ }
+ else
+ {
+ mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
+ }
+
+ mCurrentIndexedBuffers[index] = binding;
+ }
+}
+
+GLuint TransformFeedbackGL::getTransformFeedbackID() const
+{
+ return mTransformFeedbackID;
+}
+
+void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const
+{
+ if (mIsActive != active)
+ {
+ mIsActive = active;
+ mIsPaused = false;
+
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (mIsActive)
+ {
+ mFunctions->beginTransformFeedback(primitiveMode);
+ }
+ else
+ {
+ mFunctions->endTransformFeedback();
+ }
+ }
+}
+
+void TransformFeedbackGL::syncPausedState(bool paused) const
+{
+ if (mIsActive && mIsPaused != paused)
+ {
+ mIsPaused = paused;
+
+ mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
+ if (mIsPaused)
+ {
+ mFunctions->pauseTransformFeedback();
+ }
+ else
+ {
+ mFunctions->resumeTransformFeedback();
+ }
+ }
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
index 9008d4e5aee..7f72077e83b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
@@ -14,10 +14,15 @@
namespace rx
{
+class FunctionsGL;
+class StateManagerGL;
+
class TransformFeedbackGL : public TransformFeedbackImpl
{
public:
- TransformFeedbackGL();
+ TransformFeedbackGL(const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ size_t maxTransformFeedbackBufferBindings);
~TransformFeedbackGL() override;
void begin(GLenum primitiveMode) override;
@@ -27,6 +32,22 @@ class TransformFeedbackGL : public TransformFeedbackImpl
void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+
+ GLuint getTransformFeedbackID() const;
+
+ void syncActiveState(bool active, GLenum primitiveMode) const;
+ void syncPausedState(bool paused) const;
+
+ private:
+ const FunctionsGL *mFunctions;
+ StateManagerGL *mStateManager;
+
+ GLuint mTransformFeedbackID;
+
+ mutable bool mIsActive;
+ mutable bool mIsPaused;
+
+ std::vector<OffsetBindingPointer<gl::Buffer>> mCurrentIndexedBuffers;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 6227a511c15..255b41f565b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -50,7 +50,7 @@ VertexArrayGL::VertexArrayGL(const VertexArray::Data &data,
mFunctions->genVertexArrays(1, &mVertexArrayID);
// Set the cached vertex attribute array size
- GLint maxVertexAttribs;
+ GLint maxVertexAttribs = 0;
mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
mAppliedAttributes.resize(maxVertexAttribs);
}
@@ -232,7 +232,7 @@ void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &act
ASSERT(mAttributesNeedStreaming.any());
const auto &attribs = mData.getVertexAttributes();
- for (unsigned int idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
+ for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
{
const auto &attrib = attribs[idx];
ASSERT(AttributeNeedsStreaming(attrib));
@@ -292,8 +292,7 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
size_t curBufferOffset = bufferEmptySpace;
const auto &attribs = mData.getVertexAttributes();
- for (unsigned int idx :
- angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
+ for (auto idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
{
const auto &attrib = attribs[idx];
ASSERT(AttributeNeedsStreaming(attrib));
@@ -334,13 +333,14 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
{
ASSERT(!attrib.normalized);
mFunctions->vertexAttribIPointer(
- idx, attrib.size, attrib.type, static_cast<GLsizei>(destStride),
+ static_cast<GLuint>(idx), attrib.size, attrib.type,
+ static_cast<GLsizei>(destStride),
reinterpret_cast<const GLvoid *>(vertexStartOffset));
}
else
{
mFunctions->vertexAttribPointer(
- idx, attrib.size, attrib.type, attrib.normalized,
+ static_cast<GLuint>(idx), attrib.size, attrib.type, attrib.normalized,
static_cast<GLsizei>(destStride),
reinterpret_cast<const GLvoid *>(vertexStartOffset));
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
index 17a17795546..e05d4700482 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/WorkaroundsGL.h
@@ -18,7 +18,8 @@ struct WorkaroundsGL
: avoid1BitAlphaTextureFormats(false),
rgba4IsNotSupportedForColorRendering(false),
doesSRGBClearsOnLinearFramebufferAttachments(false),
- doWhileGLSLCausesGPUHang(false)
+ doWhileGLSLCausesGPUHang(false),
+ finishDoesNotCauseQueriesToBeAvailable(false)
{
}
@@ -40,8 +41,8 @@ struct WorkaroundsGL
// driver clears to the linearized clear color despite the framebuffer not supporting SRGB
// blending. It only seems to do this when the framebuffer has only linear attachments, mixed
// attachments appear to get the correct clear color.
-
bool doesSRGBClearsOnLinearFramebufferAttachments;
+
// On Mac some GLSL constructs involving do-while loops cause GPU hangs, such as the following:
// int i = 1;
// do {
@@ -50,6 +51,11 @@ struct WorkaroundsGL
// } while (i > 0)
// Work around this by rewriting the do-while to use another GLSL construct (block + while)
bool doWhileGLSLCausesGPUHang;
+
+ // Calling glFinish doesn't cause all queries to report that the result is available on some
+ // (NVIDIA) drivers. It was found that enabling GL_DEBUG_OUTPUT_SYNCHRONOUS before the finish
+ // causes it to fully finish.
+ bool finishDoesNotCauseQueriesToBeAvailable;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
index 7e25a9bcad2..2f8ebb68fa3 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
@@ -6,15 +6,15 @@
// DisplayCGL.mm: CGL implementation of egl::Display
-#include "libANGLE/renderer/gl/CGL/DisplayCGL.h"
+#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
#import <Cocoa/Cocoa.h>
#include <dlfcn.h>
#include <EGL/eglext.h>
#include "common/debug.h"
-#include "libANGLE/renderer/gl/CGL/PbufferSurfaceCGL.h"
-#include "libANGLE/renderer/gl/CGL/WindowSurfaceCGL.h"
+#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
+#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
namespace
{
@@ -113,7 +113,7 @@ SurfaceImpl *DisplayCGL::createWindowSurface(const egl::Config *configuration,
EGLNativeWindowType window,
const egl::AttributeMap &attribs)
{
- return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions);
+ return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions, mContext);
}
SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::Config *configuration,
@@ -151,6 +151,10 @@ egl::ConfigSet DisplayCGL::generateConfigs() const
// TODO(cwallez): generate more config permutations
egl::ConfigSet configs;
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
egl::Config config;
// Native stuff
@@ -197,8 +201,8 @@ egl::ConfigSet DisplayCGL::generateConfigs() const
config.renderTargetFormat = GL_RGBA8;
config.depthStencilFormat = GL_DEPTH24_STENCIL8;
- config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
- config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.renderableType = config.conformant;
config.matchNativePixmap = EGL_NONE;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
index 7bfd488ec68..80b5f58ecde 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h
@@ -34,7 +34,7 @@ class PbufferSurfaceCGL : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
index b1cff47e665..ec936a60a48 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.mm
@@ -95,7 +95,7 @@ egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **
return egl::Error(EGL_SUCCESS);
}
-egl::Error PbufferSurfaceCGL::bindTexImage(EGLint buffer)
+egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
{
UNIMPLEMENTED();
return egl::Error(EGL_SUCCESS);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
index a6e0a0900e4..83cbe8f092c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
@@ -11,10 +11,14 @@
#include "libANGLE/renderer/gl/SurfaceGL.h"
+struct _CGLContextObject;
+typedef _CGLContextObject *CGLContextObj;
@class CALayer;
struct __IOSurface;
typedef __IOSurface *IOSurfaceRef;
+@class SwapLayer;
+
namespace rx
{
@@ -24,12 +28,36 @@ class FunctionsGL;
class StateManagerGL;
struct WorkaroundsGL;
-class DisplayLink;
+struct SharedSwapState
+{
+ struct SwapTexture
+ {
+ GLuint texture;
+ unsigned int width;
+ unsigned int height;
+ uint64_t swapId;
+ };
+
+ SwapTexture textures[3];
+
+ // This code path is not going to be used by Chrome so we take the liberty
+ // to use pthreads directly instead of using mutexes and condition variables
+ // via the Platform API.
+ pthread_mutex_t mutex;
+ // The following members should be accessed only when holding the mutex
+ // (or doing construction / destruction)
+ SwapTexture *beingRendered;
+ SwapTexture *lastRendered;
+ SwapTexture *beingPresented;
+};
class WindowSurfaceCGL : public SurfaceGL
{
public:
- WindowSurfaceCGL(RendererGL *renderer, CALayer *layer, const FunctionsGL *functions);
+ WindowSurfaceCGL(RendererGL *renderer,
+ CALayer *layer,
+ const FunctionsGL *functions,
+ CGLContextObj context);
~WindowSurfaceCGL() override;
egl::Error initialize() override;
@@ -38,7 +66,7 @@ class WindowSurfaceCGL : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
@@ -51,27 +79,16 @@ class WindowSurfaceCGL : public SurfaceGL
FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override;
private:
- struct Surface
- {
- IOSurfaceRef ioSurface;
- GLuint texture;
- uint64_t lastPresentNanos;
- };
-
- void freeSurfaceData(Surface *surface);
- egl::Error initializeSurfaceData(Surface *surface, int width, int height);
+ SwapLayer *mSwapLayer;
+ SharedSwapState mSwapState;
+ uint64_t mCurrentSwapId;
CALayer *mLayer;
+ CGLContextObj mContext;
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
const WorkaroundsGL &mWorkarounds;
- DisplayLink *mDisplayLink;
- // CGL doesn't have a default framebuffer, we instead render to an IOSurface
- // that will be set as the content of the CALayer which is our native window.
- // We use two IOSurfaces to do double buffering.
- Surface mSurfaces[2];
- int mCurrentSurface;
GLuint mFramebuffer;
GLuint mDSRenderbuffer;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
index 04cd88e3fe5..f80bb1aa251 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
@@ -9,8 +9,6 @@
#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h"
#import <Cocoa/Cocoa.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
#include <OpenGL/OpenGL.h>
#import <QuartzCore/QuartzCore.h>
@@ -20,146 +18,151 @@
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
-#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
-
-#include <iostream>
-
-namespace
+@interface SwapLayer : CAOpenGLLayer
{
+ CGLContextObj mDisplayContext;
-// All time computations in the file are done in nanoseconds but both the
-// current time and the screen's present time are given as "mach time".
-// The first thing we will do after receiving a mach time is convert it.
-uint64_t MachTimeToNanoseconds(uint64_t machTime)
-{
- static mach_timebase_info_data_t timebaseInfo;
-
- if (timebaseInfo.denom == 0)
- {
- mach_timebase_info(&timebaseInfo);
- }
-
- return (machTime * timebaseInfo.numer) / timebaseInfo.denom;
-}
-
-uint64_t NowInNanoseconds()
-{
- return MachTimeToNanoseconds(mach_absolute_time());
-}
+ bool initialized;
+ rx::SharedSwapState *mSwapState;
+ const rx::FunctionsGL *mFunctions;
+ GLuint mReadFramebuffer;
}
-
-namespace rx
-{
-
-// A wrapper around CoreVideo's DisplayLink. It polls the screen vsync time,
-// and allows computing when is the next present time after a given time point.
-class DisplayLink
-{
- public:
- DisplayLink() : mDisplayLink(nullptr), mHostTimeRemainderNanos(0), mPresentIntervalNanos(0) {}
-
- ~DisplayLink()
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+ withContext:(CGLContextObj)displayContext
+ withFunctions:(const rx::FunctionsGL *)functions;
+@end
+
+@implementation SwapLayer
+- (id)initWithSharedState:(rx::SharedSwapState *)swapState
+ withContext:(CGLContextObj)displayContext
+ withFunctions:(const rx::FunctionsGL *)functions
{
- if (mDisplayLink != nullptr)
+ self = [super init];
+ if (self != nil)
{
- stop();
- CVDisplayLinkRelease(mDisplayLink);
- mDisplayLink = nullptr;
+ self.asynchronous = YES;
+ mDisplayContext = displayContext;
+
+ initialized = false;
+ mSwapState = swapState;
+ mFunctions = functions;
+
+ [self setFrame:CGRectMake(0, 0, mSwapState->textures[0].width,
+ mSwapState->textures[0].height)];
}
+ return self;
}
- void start()
+ - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
{
- CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink);
- ASSERT(mDisplayLink != nullptr);
- CVDisplayLinkSetOutputCallback(mDisplayLink, &Callback, this);
- CVDisplayLinkStart(mDisplayLink);
+ CGLPixelFormatAttribute attribs[] = {
+ kCGLPFADisplayMask, static_cast<CGLPixelFormatAttribute>(mask), kCGLPFAOpenGLProfile,
+ static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core),
+ static_cast<CGLPixelFormatAttribute>(0)};
+
+ CGLPixelFormatObj pixelFormat = nullptr;
+ GLint numFormats = 0;
+ CGLChoosePixelFormat(attribs, &pixelFormat, &numFormats);
+
+ return pixelFormat;
}
- void stop()
+ - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
{
- ASSERT(mDisplayLink != nullptr);
- CVDisplayLinkStop(mDisplayLink);
+ CGLContextObj context = nullptr;
+ CGLCreateContext(pixelFormat, mDisplayContext, &context);
+ return context;
}
- uint64_t nextPresentAfter(uint64_t time)
+ - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp
{
- // Load the two variables locally to avoid them changing in the middle of the computation.
- uint64_t presentInterval = mPresentIntervalNanos;
- uint64_t remainder = mHostTimeRemainderNanos;
+ BOOL result = NO;
- if (presentInterval == 0)
+ pthread_mutex_lock(&mSwapState->mutex);
{
- return time;
+ if (mSwapState->lastRendered->swapId > mSwapState->beingPresented->swapId)
+ {
+ std::swap(mSwapState->lastRendered, mSwapState->beingPresented);
+ result = YES;
+ }
}
+ pthread_mutex_unlock(&mSwapState->mutex);
- uint64_t nextSwapNumber = (time - remainder) / presentInterval + 1;
- return nextSwapNumber * presentInterval + remainder;
+ return result;
}
- uint64_t getPresentInterval() const { return mPresentIntervalNanos; }
-
- private:
- static CVReturn Callback(CVDisplayLinkRef displayLink,
- const CVTimeStamp *now,
- const CVTimeStamp *outputTime,
- CVOptionFlags flagsIn,
- CVOptionFlags *flagsOut,
- void *userData)
+ - (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp
{
- DisplayLink *link = reinterpret_cast<DisplayLink *>(userData);
- link->tick(*outputTime);
- return kCVReturnSuccess;
+ CGLSetCurrentContext(glContext);
+ if (!initialized)
+ {
+ initialized = true;
+
+ mFunctions->genFramebuffers(1, &mReadFramebuffer);
+ }
+
+ const auto &texture = *mSwapState->beingPresented;
+ if ([self frame].size.width != texture.width || [self frame].size.height != texture.height)
+ {
+ [self setFrame:CGRectMake(0, 0, texture.width, texture.height)];
+
+ // Without this, the OSX compositor / window system doesn't see the resize.
+ [self setNeedsDisplay];
+ }
+
+ // TODO(cwallez) support 2.1 contexts too that don't have blitFramebuffer nor the
+ // GL_DRAW_FRAMEBUFFER_BINDING query
+ GLint drawFBO;
+ mFunctions->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBO);
+
+ mFunctions->bindFramebuffer(GL_FRAMEBUFFER, mReadFramebuffer);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ texture.texture, 0);
+
+ mFunctions->bindFramebuffer(GL_READ_FRAMEBUFFER, mReadFramebuffer);
+ mFunctions->bindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
+ mFunctions->blitFramebuffer(0, 0, texture.width, texture.height, 0, 0, texture.width,
+ texture.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ // Call the super method to flush the context
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
}
+ @end
- void tick(const CVTimeStamp &outputTime)
+ namespace rx
{
- // This is called from a special high priority thread so by setting
- // both member variables here we have a data race. However if we assume
- // the present interval doesn't change, the data race disappears after
- // the first tick.
- // In addition computations using these member variables are made to
- // produce a sensible result if one of the two members has the default
- // value of 0.
- uint64_t hostTimeNanos = MachTimeToNanoseconds(outputTime.hostTime);
-
- uint64_t numerator = outputTime.videoRefreshPeriod;
- uint64_t denominator = outputTime.videoTimeScale;
- uint64_t presentIntervalNanos = (1000000000 * numerator) / denominator;
-
- mHostTimeRemainderNanos = hostTimeNanos % presentIntervalNanos;
- mPresentIntervalNanos = presentIntervalNanos;
- }
- CVDisplayLinkRef mDisplayLink;
-
- uint64_t mHostTimeRemainderNanos;
- uint64_t mPresentIntervalNanos;
-};
-
-WindowSurfaceCGL::WindowSurfaceCGL(RendererGL *renderer,
- CALayer *layer,
- const FunctionsGL *functions)
- : SurfaceGL(renderer),
- mLayer(layer),
- mFunctions(functions),
- mStateManager(renderer->getStateManager()),
- mWorkarounds(renderer->getWorkarounds()),
- mDisplayLink(nullptr),
- mCurrentSurface(0),
- mFramebuffer(0),
- mDSRenderbuffer(0)
+ WindowSurfaceCGL::WindowSurfaceCGL(RendererGL *renderer,
+ CALayer *layer,
+ const FunctionsGL *functions,
+ CGLContextObj context)
+ : SurfaceGL(renderer),
+ mSwapLayer(nil),
+ mCurrentSwapId(0),
+ mLayer(layer),
+ mContext(context),
+ mFunctions(functions),
+ mStateManager(renderer->getStateManager()),
+ mWorkarounds(renderer->getWorkarounds()),
+ mFramebuffer(0),
+ mDSRenderbuffer(0)
{
- for (auto &surface : mSurfaces)
- {
- surface.texture = 0;
- surface.ioSurface = nil;
- }
+ pthread_mutex_init(&mSwapState.mutex, nullptr);
}
WindowSurfaceCGL::~WindowSurfaceCGL()
{
+ pthread_mutex_destroy(&mSwapState.mutex);
if (mFramebuffer != 0)
{
mFunctions->deleteFramebuffers(1, &mFramebuffer);
@@ -172,14 +175,19 @@ WindowSurfaceCGL::~WindowSurfaceCGL()
mDSRenderbuffer = 0;
}
- for (auto &surface : mSurfaces)
+ if (mSwapLayer != nil)
{
- freeSurfaceData(&surface);
+ [mSwapLayer release];
+ mSwapLayer = nil;
}
- if (mDisplayLink != nullptr)
+ for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
{
- SafeDelete(mDisplayLink);
+ if (mSwapState.textures[i].texture != 0)
+ {
+ mFunctions->deleteTextures(1, &mSwapState.textures[i].texture);
+ mSwapState.textures[i].texture = 0;
+ }
}
}
@@ -188,11 +196,24 @@ egl::Error WindowSurfaceCGL::initialize()
unsigned width = getWidth();
unsigned height = getHeight();
- for (auto &surface : mSurfaces)
+ for (size_t i = 0; i < ArraySize(mSwapState.textures); ++i)
{
- surface.lastPresentNanos = 0;
- initializeSurfaceData(&surface, width, height);
+ mFunctions->genTextures(1, &mSwapState.textures[i].texture);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mSwapState.textures[i].texture);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ mSwapState.textures[i].width = width;
+ mSwapState.textures[i].height = height;
+ mSwapState.textures[i].swapId = 0;
}
+ mSwapState.beingRendered = &mSwapState.textures[0];
+ mSwapState.lastRendered = &mSwapState.textures[1];
+ mSwapState.beingPresented = &mSwapState.textures[2];
+
+ mSwapLayer = [[SwapLayer alloc] initWithSharedState:&mSwapState
+ withContext:mContext
+ withFunctions:mFunctions];
+ [mLayer addSublayer:mSwapLayer];
mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
@@ -200,93 +221,51 @@ egl::Error WindowSurfaceCGL::initialize()
mFunctions->genFramebuffers(1, &mFramebuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
- mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB,
- mSurfaces[0].texture, 0);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mSwapState.beingRendered->texture, 0);
mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer);
- mDisplayLink = new DisplayLink;
- mDisplayLink->start();
-
return egl::Error(EGL_SUCCESS);
}
egl::Error WindowSurfaceCGL::makeCurrent()
{
- // TODO(cwallez) if it is the first makeCurrent set the viewport and scissor?
return egl::Error(EGL_SUCCESS);
}
egl::Error WindowSurfaceCGL::swap()
{
- // Because we are rendering to IOSurfaces we have to implement swapBuffers ourselves
- // (contrary to GLX, WGL or EGL) and have to send the IOSurfaces for presentation at the
- // right time to avoid causing tearing or flickering. Likewise we must make sure we do
- // not render to an IOSurface that is still being presented.
- // ANGLE standalone cannot post function to be executed at a later time so we can only
- // implement basic synchronization with the present time by sleeping.
- uint64_t presentInterval = mDisplayLink->getPresentInterval();
- uint64_t now = NowInNanoseconds();
+ mFunctions->flush();
+ mSwapState.beingRendered->swapId = ++mCurrentSwapId;
+ pthread_mutex_lock(&mSwapState.mutex);
{
- Surface &surface = mSurfaces[mCurrentSurface];
- // A flush is needed for the IOSurface to get the result of the GL operations
- // as specified in the documentation of CGLTexImageIOSurface2D
- mFunctions->flush();
-
- // We can only send the IOSurface to the CALayer during a present window
- // that is in the middle of two vsyncs, otherwise flickering can happen.
- {
- // The present window was determined empirically.
- static const double kPresentWindowMin = 0.3;
- static const double kPresentWindowMax = 0.7;
-
- uint64_t nextPresent = mDisplayLink->nextPresentAfter(now);
- uint64_t presentWindowMin = nextPresent - presentInterval * (1.0 - kPresentWindowMin);
- uint64_t presentWindowMax = nextPresent - presentInterval * (1.0 - kPresentWindowMax);
- if (now <= presentWindowMin)
- {
- usleep((presentWindowMin - now) / 1000);
- }
- else if (now >= presentWindowMax)
- {
- uint64_t presentTarget = nextPresent + presentInterval * kPresentWindowMin;
- usleep((presentTarget - now) / 1000);
- }
- }
-
- // Put the IOSurface as the content of the layer
- [CATransaction begin];
- [mLayer setContents:(id)surface.ioSurface];
- [CATransaction commit];
-
- surface.lastPresentNanos = NowInNanoseconds();
+ std::swap(mSwapState.beingRendered, mSwapState.lastRendered);
}
+ pthread_mutex_unlock(&mSwapState.mutex);
- mCurrentSurface = (mCurrentSurface + 1) % ArraySize(mSurfaces);
+ unsigned width = getWidth();
+ unsigned height = getHeight();
+ auto &texture = *mSwapState.beingRendered;
+ if (texture.width != width || texture.height != texture.height)
{
- Surface &surface = mSurfaces[mCurrentSurface];
+ mStateManager->bindTexture(GL_TEXTURE_2D, texture.texture);
+ mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
- {
- // We need to wait a bit after a swap before rendering to the IOSurface again
- // otherwise with a small desync between clocks could cause a flickering.
- static const double kDrawWindowStart = 0.05;
-
- uint64_t timePresentFinishes = mDisplayLink->nextPresentAfter(surface.lastPresentNanos);
- timePresentFinishes += presentInterval * kDrawWindowStart;
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
+ mFunctions->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
- if (now < timePresentFinishes)
- {
- usleep((timePresentFinishes - now) / 1000);
- }
- }
-
- mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
- mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_RECTANGLE_ARB, surface.texture, 0);
+ texture.width = width;
+ texture.height = height;
}
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ mSwapState.beingRendered->texture, 0);
+
return egl::Error(EGL_SUCCESS);
}
@@ -302,7 +281,7 @@ egl::Error WindowSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **v
return egl::Error(EGL_SUCCESS);
}
-egl::Error WindowSurfaceCGL::bindTexImage(EGLint buffer)
+egl::Error WindowSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
{
UNIMPLEMENTED();
return egl::Error(EGL_SUCCESS);
@@ -316,7 +295,7 @@ egl::Error WindowSurfaceCGL::releaseTexImage(EGLint buffer)
void WindowSurfaceCGL::setSwapInterval(EGLint interval)
{
- // TODO(cwallez) investigate the need for swapIntervals other than 1
+ // TODO(cwallez) investigate implementing swap intervals other than 0
}
EGLint WindowSurfaceCGL::getWidth() const
@@ -346,53 +325,4 @@ FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Framebuffe
return new FramebufferGL(mFramebuffer, data, mFunctions, mWorkarounds, mStateManager);
}
-void WindowSurfaceCGL::freeSurfaceData(Surface *surface)
-{
- if (surface->texture != 0)
- {
- mFunctions->deleteTextures(1, &surface->texture);
- surface->texture = 0;
- }
- if (surface->ioSurface != nil)
- {
- CFRelease(surface->ioSurface);
- surface->ioSurface = nil;
- }
-}
-
-egl::Error WindowSurfaceCGL::initializeSurfaceData(Surface *surface, int width, int height)
-{
- CFDictionaryRef ioSurfaceOptions = nil;
- {
- unsigned pixelFormat = 'BGRA';
- const unsigned kBytesPerElement = 4;
-
- NSDictionary *options = @{
- (id) kIOSurfaceWidth : @(width),
- (id) kIOSurfaceHeight : @(height),
- (id) kIOSurfacePixelFormat : @(pixelFormat),
- (id) kIOSurfaceBytesPerElement : @(kBytesPerElement),
- };
- ioSurfaceOptions = reinterpret_cast<CFDictionaryRef>(options);
- }
-
- surface->ioSurface = IOSurfaceCreate(ioSurfaceOptions);
-
- mFunctions->genTextures(1, &surface->texture);
- mFunctions->bindTexture(GL_TEXTURE_RECTANGLE_ARB, surface->texture);
-
- CGLError error =
- CGLTexImageIOSurface2D(CGLGetCurrentContext(), GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, width,
- height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface->ioSurface, 0);
-
- if (error != kCGLNoError)
- {
- std::string errorMessage =
- "Could not create the IOSurfaces: " + std::string(CGLErrorString(error));
- return egl::Error(EGL_BAD_NATIVE_WINDOW, errorMessage.c_str());
- }
-
- return egl::Error(EGL_SUCCESS);
-}
-
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
index 75e24f0f4aa..b2f24f2af99 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
@@ -227,15 +227,19 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
InsertFormatMapping(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), Always(), Never(), VersionOnly(3, 0), Always(), Never());
// From GL_EXT_texture_compression_dxt1
- // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render |
- InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never());
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never());
+ // | Format | OpenGL texture support | Filter | Render | OpenGL ES texture support | Filter | Render |
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_EXT_texture_compression_dxt1"), Always(), Never());
// From GL_ANGLE_texture_compression_dxt3
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), Always(), Never());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt3"), Always(), Never());
// From GL_ANGLE_texture_compression_dxt5
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), Always(), Never());
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, ExtsOnly("GL_EXT_texture_compression_s3tc"), Always(), Never(), ExtsOnly("GL_ANGLE_texture_compression_dxt5"), Always(), Never());
+
+ // From GL_ETC1_RGB8_OES
+ InsertFormatMapping(&map, GL_ETC1_RGB8_OES, VersionOrExts(4, 3, "GL_ARB_ES3_compatibility"), Always(), Never(), VersionOrExts(3, 0, "GL_ETC1_RGB8_OES"), Always(), Never());
+
// clang-format on
return map;
@@ -372,6 +376,35 @@ static GLenum GetNativeFormat(const FunctionsGL *functions,
return result;
}
+static GLenum GetNativeCompressedFormat(const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
+ GLenum format)
+{
+ GLenum result = format;
+
+ if (functions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (format == GL_ETC1_RGB8_OES)
+ {
+ // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression
+ // format is forwards compatible so just use the ETC2 format.
+ result = GL_COMPRESSED_RGB8_ETC2;
+ }
+ }
+
+ if (functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ if (format == GL_ETC1_RGB8_OES)
+ {
+ // Pass GL_COMPRESSED_RGB8_ETC2 as the target format in ES3 and higher because it
+ // becomes a core format.
+ result = GL_COMPRESSED_RGB8_ETC2;
+ }
+ }
+
+ return result;
+}
+
static GLenum GetNativeType(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum type)
@@ -429,7 +462,7 @@ CompressedTexImageFormat GetCompressedTexImageFormat(const FunctionsGL *function
GLenum internalFormat)
{
CompressedTexImageFormat result;
- result.internalFormat = internalFormat;
+ result.internalFormat = GetNativeCompressedFormat(functions, workarounds, internalFormat);
return result;
}
@@ -438,7 +471,7 @@ CompressedTexSubImageFormat GetCompressedSubTexImageFormat(const FunctionsGL *fu
GLenum format)
{
CompressedTexSubImageFormat result;
- result.format = format;
+ result.format = GetNativeCompressedFormat(functions, workarounds, format);
return result;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
index 1d2d073ea8e..b3fa1e29941 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -21,6 +21,18 @@
namespace rx
{
+static int IgnoreX11Errors(Display *, XErrorEvent *)
+{
+ return 0;
+}
+
+SwapControlData::SwapControlData()
+ : targetSwapInterval(0),
+ maxSwapInterval(-1),
+ currentSwapInterval(-1)
+{
+}
+
class FunctionsGLGLX : public FunctionsGL
{
public:
@@ -45,10 +57,18 @@ class FunctionsGLGLX : public FunctionsGL
DisplayGLX::DisplayGLX()
: DisplayGL(),
mFunctionsGL(nullptr),
+ mRequestedVisual(-1),
mContextConfig(nullptr),
mContext(nullptr),
mDummyPbuffer(0),
mUsesNewXDisplay(false),
+ mIsMesa(false),
+ mHasMultisample(false),
+ mHasARBCreateContext(false),
+ mSwapControl(SwapControl::Absent),
+ mMinSwapInterval(0),
+ mMaxSwapInterval(0),
+ mCurrentSwapInterval(-1),
mEGLDisplay(nullptr)
{
}
@@ -61,6 +81,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
{
mEGLDisplay = display;
Display *xDisplay = display->getNativeDisplayId();
+ const auto &attribMap = display->getAttributeMap();
// ANGLE_platform_angle allows the creation of a default display
// using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open
@@ -81,29 +102,79 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
}
- // Check we have the needed extensions
+ mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
+ mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
+
+ // Choose the swap_control extension to use, if any.
+ // The EXT version is better as it allows glXSwapInterval to be called per
+ // window, while we'll potentially need to change the swap interval on each
+ // swap buffers when using the SGI or MESA versions.
+ if (mGLX.hasExtension("GLX_EXT_swap_control"))
+ {
+ mSwapControl = SwapControl::EXT;
+
+ // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just
+ // set default values.
+ mMinSwapInterval = 0;
+ mMaxSwapInterval = 4;
+ }
+ else if (mGLX.hasExtension("GLX_MESA_swap_control"))
+ {
+ // If we have the Mesa or SGI extension, assume that you can at least set
+ // a swap interval of 0 or 1.
+ mSwapControl = SwapControl::Mesa;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else if (mGLX.hasExtension("GLX_SGI_swap_control"))
+ {
+ mSwapControl = SwapControl::SGI;
+ mMinSwapInterval = 0;
+ mMinSwapInterval = 1;
+ }
+ else
+ {
+ mSwapControl = SwapControl::Absent;
+ mMinSwapInterval = 1;
+ mMinSwapInterval = 1;
+ }
+
+ if (attribMap.contains(EGL_X11_VISUAL_ID_ANGLE))
{
- if (mGLX.minorVersion == 3 && !mGLX.hasExtension("GLX_ARB_multisample"))
+ mRequestedVisual = attribMap.get(EGL_X11_VISUAL_ID_ANGLE, -1);
+
+ // There is no direct way to get the GLXFBConfig matching an X11 visual ID
+ // so we have to iterate over all the GLXFBConfigs to find the right one.
+ int nConfigs;
+ int attribList[] = {
+ None,
+ };
+ glx::FBConfig *allConfigs = mGLX.chooseFBConfig(attribList, &nConfigs);
+
+ for (int i = 0; i < nConfigs; ++i)
{
- return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_multisample.");
+ if (getGLXFBConfigAttrib(allConfigs[i], GLX_VISUAL_ID) == mRequestedVisual)
+ {
+ mContextConfig = allConfigs[i];
+ break;
+ }
}
- // Require ARB_create_context which has been supported since Mesa 9 unconditionnaly
- // and is present in Mesa 8 in an almost always on compile flag. Also assume proprietary
- // drivers have it.
- if (!mGLX.hasExtension("GLX_ARB_create_context"))
+ XFree(allConfigs);
+
+ if (mContextConfig == nullptr)
{
- return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_create_context.");
+ return egl::Error(EGL_NOT_INITIALIZED, "Invalid visual ID requested.");
}
}
-
- // When glXMakeCurrent is called, the context and the surface must be
- // compatible which in glX-speak means that their config have the same
- // color buffer type, are both RGBA or ColorIndex, and their buffers have
- // the same depth, if they exist.
- // Since our whole EGL implementation is backed by only one GL context, this
- // context must be compatible with all the GLXFBConfig corresponding to the
- // EGLconfigs that we will be exposing.
+ else
{
+ // When glXMakeCurrent is called, the context and the surface must be
+ // compatible which in glX-speak means that their config have the same
+ // color buffer type, are both RGBA or ColorIndex, and their buffers have
+ // the same depth, if they exist.
+ // Since our whole EGL implementation is backed by only one GL context, this
+ // context must be compatible with all the GLXFBConfig corresponding to the
+ // EGLconfigs that we will be exposing.
int nConfigs;
int attribList[] =
{
@@ -127,7 +198,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
GLX_CONFIG_CAVEAT, GLX_NONE,
None
};
- glx::FBConfig* candidates = mGLX.chooseFBConfig(attribList, &nConfigs);
+ glx::FBConfig *candidates = mGLX.chooseFBConfig(attribList, &nConfigs);
if (nConfigs == 0)
{
XFree(candidates);
@@ -137,7 +208,27 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
XFree(candidates);
}
- mContext = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, nullptr);
+ if (mHasARBCreateContext)
+ {
+ mContext = initializeContext(mContextConfig, display->getAttributeMap());
+ }
+ else
+ {
+ XVisualInfo visualTemplate;
+ visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
+
+ int numVisuals = 0;
+ XVisualInfo *visuals = XGetVisualInfo(xDisplay, VisualIDMask, &visualTemplate, &numVisuals);
+ if (numVisuals <= 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Could not get the visual info from the fb config");
+ }
+ ASSERT(numVisuals == 1);
+
+ mContext = mGLX.createContext(&visuals[0], nullptr, true);
+ XFree(visuals);
+ }
if (!mContext)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
@@ -146,11 +237,20 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
// FunctionsGL and DisplayGL need to make a few GL calls, for example to
// query the version of the context so we need to make the context current.
// glXMakeCurrent requires a GLXDrawable so we create a temporary Pbuffer
- // (of size 0, 0) for the duration of these calls.
-
- // to query things like limits. Ideally we would want to unset the current context
- // and destroy the pbuffer before going back to the application but this is TODO
- mDummyPbuffer = mGLX.createPbuffer(mContextConfig, nullptr);
+ // (of size 1, 1) for the duration of these calls.
+ // Ideally we would want to unset the current context and destroy the pbuffer
+ // before going back to the application but this is TODO
+ // We could use a pbuffer of size (0, 0) but it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (1, 1) instead.
+
+ int dummyPbufferAttribs[] =
+ {
+ GLX_PBUFFER_WIDTH, 1,
+ GLX_PBUFFER_HEIGHT, 1,
+ None,
+ };
+ mDummyPbuffer = mGLX.createPbuffer(mContextConfig, dummyPbufferAttribs);
if (!mDummyPbuffer)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not create the dummy pbuffer.");
@@ -166,6 +266,10 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
syncXCommands();
+ std::string rendererString =
+ reinterpret_cast<const char*>(mFunctionsGL->getString(GL_RENDERER));
+ mIsMesa = rendererString.find("Mesa") != std::string::npos;
+
return DisplayGL::initialize(display);
}
@@ -237,15 +341,103 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device)
return egl::Error(EGL_BAD_DISPLAY);
}
+glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
+ const egl::AttributeMap &eglAttributes)
+{
+ // Create a context of the requested version, if any.
+ EGLint requestedMajorVersion =
+ eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMinorVersion =
+ eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+ if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
+ {
+ std::vector<int> contextAttributes;
+ contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ contextAttributes.push_back(requestedMajorVersion);
+
+ contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ contextAttributes.push_back(requestedMinorVersion);
+
+ contextAttributes.push_back(None);
+ return createContextAttribs(config, contextAttributes);
+ }
+
+ // It is commonly assumed that glXCreateContextAttrib will create a context
+ // of the highest version possible but it is not specified in the spec and
+ // is not true on the Mesa drivers. Instead we try to create a context per
+ // desktop GL version until we succeed, starting from newer version.
+ // clang-format off
+ const gl::Version desktopVersions[] = {
+ gl::Version(4, 5),
+ gl::Version(4, 4),
+ gl::Version(4, 3),
+ gl::Version(4, 2),
+ gl::Version(4, 1),
+ gl::Version(4, 0),
+ gl::Version(3, 3),
+ gl::Version(3, 2),
+ gl::Version(3, 1),
+ gl::Version(3, 0),
+ gl::Version(2, 0),
+ gl::Version(1, 5),
+ gl::Version(1, 4),
+ gl::Version(1, 3),
+ gl::Version(1, 2),
+ gl::Version(1, 1),
+ gl::Version(1, 0),
+ };
+ // clang-format on
+
+ bool useProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
+ for (size_t i = 0; i < ArraySize(desktopVersions); ++i)
+ {
+ const auto &version = desktopVersions[i];
+
+ std::vector<int> contextAttributes;
+ contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ contextAttributes.push_back(version.major);
+
+ contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ contextAttributes.push_back(version.minor);
+
+ if (useProfile && version >= gl::Version(3, 2))
+ {
+ contextAttributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ contextAttributes.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
+ }
+
+ contextAttributes.push_back(None);
+ auto context = createContextAttribs(config, contextAttributes);
+
+ if (context)
+ {
+ return context;
+ }
+ }
+
+ return nullptr;
+}
+
egl::ConfigSet DisplayGLX::generateConfigs() const
{
egl::ConfigSet configs;
configIdToGLXConfig.clear();
- bool hasSwapControl = mGLX.hasExtension("GLX_EXT_swap_control");
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ int contextRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_RED_SIZE);
+ int contextGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_GREEN_SIZE);
+ int contextBlueSize = getGLXFBConfigAttrib(mContextConfig, GLX_BLUE_SIZE);
+ int contextAlphaSize = getGLXFBConfigAttrib(mContextConfig, GLX_ALPHA_SIZE);
- int contextSamples = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES);
- int contextSampleBuffers = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS);
+ int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE);
+ int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE);
+
+ int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0;
+ int contextSampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0;
int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE);
int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE);
@@ -273,6 +465,14 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
config.nativeVisualType = getGLXFBConfigAttrib(glxConfig, GLX_X_VISUAL_TYPE);
config.nativeRenderable = EGL_TRUE;
+ // When a visual ID has been specified with EGL_ANGLE_x11_visual we should
+ // only return configs with this visual: it will maximize performance by avoid
+ // blits in the driver when showing the window on the screen.
+ if (mRequestedVisual != -1 && config.nativeVisualID != mRequestedVisual)
+ {
+ continue;
+ }
+
// Buffer sizes
config.redSize = getGLXFBConfigAttrib(glxConfig, GLX_RED_SIZE);
config.greenSize = getGLXFBConfigAttrib(glxConfig, GLX_GREEN_SIZE);
@@ -282,11 +482,19 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
config.stencilSize = getGLXFBConfigAttrib(glxConfig, GLX_STENCIL_SIZE);
// We require RGBA8 and the D24S8 (or no DS buffer)
- if (config.redSize != 8 || config.greenSize != 8 || config.blueSize != 8 || config.alphaSize != 8)
+ if (config.redSize != contextRedSize || config.greenSize != contextGreenSize ||
+ config.blueSize != contextBlueSize || config.alphaSize != contextAlphaSize)
{
continue;
}
- if (!(config.depthSize == 24 && config.stencilSize == 8) && !(config.depthSize == 0 && config.stencilSize == 0))
+ // The GLX spec says that it is ok for a whole buffer to not be present
+ // however the Mesa Intel driver (and probably on other Mesa drivers)
+ // fails to make current when the Depth stencil doesn't exactly match the
+ // configuration.
+ bool hasSameDepthStencil =
+ config.depthSize == contextDepthSize && config.stencilSize == contextStencilSize;
+ bool hasNoDepthStencil = config.depthSize == 0 && config.stencilSize == 0;
+ if (!hasSameDepthStencil && (mIsMesa || !hasNoDepthStencil))
{
continue;
}
@@ -298,8 +506,9 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
// Multisample and accumulation buffers
- int samples = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES);
- int sampleBuffers = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS);
+ int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0;
+ int sampleBuffers =
+ mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0;
int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE);
int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE);
@@ -362,23 +571,16 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
(glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) |
(glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0);
- if (hasSwapControl)
- {
- // In GLX_EXT_swap_control querying these is done on a GLXWindow so we just set a default value.
- config.minSwapInterval = 0;
- config.maxSwapInterval = 4;
- }
- else
- {
- config.minSwapInterval = 1;
- config.maxSwapInterval = 1;
- }
+ config.minSwapInterval = mMinSwapInterval;
+ config.maxSwapInterval = mMaxSwapInterval;
+
// TODO(cwallez) wildly guessing these formats, another TODO says they should be removed anyway
config.renderTargetFormat = GL_RGBA8;
config.depthStencilFormat = GL_DEPTH24_STENCIL8;
- // TODO(cwallez) Fill after determining the GL version we are using and what ES version it supports
- config.conformant = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
- config.renderableType = EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
+
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.renderableType = config.conformant;
+
// TODO(cwallez) I have no idea what this is
config.matchNativePixmap = EGL_NONE;
@@ -445,6 +647,54 @@ void DisplayGLX::syncXCommands() const
}
}
+void DisplayGLX::setSwapInterval(glx::Drawable drawable, SwapControlData *data)
+{
+ ASSERT(data != nullptr);
+
+ // TODO(cwallez) error checking?
+ if (mSwapControl == SwapControl::EXT)
+ {
+ // Prefer the EXT extension, it gives per-drawable swap intervals, which will
+ // minimize the number of driver calls.
+ if (data->maxSwapInterval < 0)
+ {
+ unsigned int maxSwapInterval = 0;
+ mGLX.queryDrawable(drawable, GLX_MAX_SWAP_INTERVAL_EXT, &maxSwapInterval);
+ data->maxSwapInterval = static_cast<int>(maxSwapInterval);
+ }
+
+ // When the egl configs were generated we had to guess what the max swap interval
+ // was because we didn't have a window to query it one (and that this max could
+ // depend on the monitor). This means that the target interval might be higher
+ // than the max interval and needs to be clamped.
+ const int realInterval = std::min(data->targetSwapInterval, data->maxSwapInterval);
+ if (data->currentSwapInterval != realInterval)
+ {
+ mGLX.swapIntervalEXT(drawable, realInterval);
+ data->currentSwapInterval = realInterval;
+ }
+ }
+ else if (mCurrentSwapInterval != data->targetSwapInterval)
+ {
+ // With the Mesa or SGI extensions we can still do per-drawable swap control
+ // manually but it is more expensive in number of driver calls.
+ if (mSwapControl == SwapControl::Mesa)
+ {
+ mGLX.swapIntervalMESA(data->targetSwapInterval);
+ }
+ else if (mSwapControl == SwapControl::Mesa)
+ {
+ mGLX.swapIntervalSGI(data->targetSwapInterval);
+ }
+ mCurrentSwapInterval = data->targetSwapInterval;
+ }
+}
+
+bool DisplayGLX::isValidWindowVisualId(unsigned long visualId) const
+{
+ return mRequestedVisual == -1 || static_cast<unsigned long>(mRequestedVisual) == visualId;
+}
+
const FunctionsGL *DisplayGLX::getFunctionsGL() const
{
return mFunctionsGL;
@@ -468,4 +718,15 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
return result;
}
+glx::Context DisplayGLX::createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const
+{
+ // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
+ // be generated. To prevent these errors from crashing our process, we simply ignore
+ // them and only look if GLXContext was created.
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ auto context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
+ XSetErrorHandler(oldErrorHandler);
+
+ return context;
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
index e72d9a90b3a..41a985a9d04 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
@@ -20,6 +20,20 @@ namespace rx
class FunctionsGLX;
+// State-tracking data for the swap control to allow DisplayGLX to remember per
+// drawable information for swap control.
+struct SwapControlData
+{
+ SwapControlData();
+
+ // Set by the drawable
+ int targetSwapInterval;
+
+ // DisplayGLX-side state-tracking
+ int maxSwapInterval;
+ int currentSwapInterval;
+};
+
class DisplayGLX : public DisplayGL
{
public:
@@ -59,25 +73,52 @@ class DisplayGLX : public DisplayGL
// between the application's display and ANGLE's one.
void syncXCommands() const;
+ // Depending on the supported GLX extension, swap interval can be set
+ // globally or per drawable. This function will make sure the drawable's
+ // swap interval is the one required so that the subsequent swapBuffers
+ // acts as expected.
+ void setSwapInterval(glx::Drawable drawable, SwapControlData *data);
+
+ bool isValidWindowVisualId(unsigned long visualId) const;
+
private:
const FunctionsGL *getFunctionsGL() const override;
+ glx::Context initializeContext(glx::FBConfig config, const egl::AttributeMap &eglAttributes);
+
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override;
int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
+ glx::Context createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const;
FunctionsGL *mFunctionsGL;
//TODO(cwallez) yuck, change generateConfigs to be non-const or add a userdata member to egl::Config?
mutable std::map<int, glx::FBConfig> configIdToGLXConfig;
+ EGLint mRequestedVisual;
glx::FBConfig mContextConfig;
glx::Context mContext;
// A pbuffer the context is current on during ANGLE initialization
glx::Pbuffer mDummyPbuffer;
bool mUsesNewXDisplay;
+ bool mIsMesa;
+ bool mHasMultisample;
+ bool mHasARBCreateContext;
+
+ enum class SwapControl
+ {
+ Absent,
+ EXT,
+ Mesa,
+ SGI,
+ };
+ SwapControl mSwapControl;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+ int mCurrentSwapInterval;
FunctionsGLX mGLX;
egl::Display *mEGLDisplay;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
index e5af46aff77..204a4881c49 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FBConfigCompatibility.md
@@ -155,6 +155,37 @@ have the same multisample and accumulation buffers gives the following:
0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
```
+Mesa Intel driver
+-----------------
+In GLX, a criterium for context and surface compatibility is that buffers
+should have the same depth, if they exist at all in the surface. This means
+that it should be possible to make a context with a D24S8 depth-stencil
+buffer to a surface without a depth-stencil buffer. This doesn't work on the
+Mesa Intel driver. The list before the workaround was the following, with
+0x020 being the fbconfig chosen for the context:
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
+After the workaround that list becomes the following:
+```
+ visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav
+ id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat
+----------------------------------------------------------------------------
+0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
+```
+
Future investigation
--------------------
All the non-conformant configs have a multisampled buffer, so it could be interesting
@@ -167,3 +198,4 @@ drivers and hardware.
The drivers tested were:
- the proprietary NVIDIA driver
- the proprietary AMD driver
+ - the open source Intel (Broadwell) Mesa driver
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
index 4dfc4351d8c..a93cea2287c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
@@ -35,34 +35,42 @@ static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
struct FunctionsGLX::GLXFunctionTable
{
GLXFunctionTable()
- : destroyContextPtr(nullptr),
- makeCurrentPtr(nullptr),
- swapBuffersPtr(nullptr),
- queryExtensionPtr(nullptr),
- queryVersionPtr(nullptr),
- waitXPtr(nullptr),
- waitGLPtr(nullptr),
- queryExtensionsStringPtr(nullptr),
- getFBConfigsPtr(nullptr),
- chooseFBConfigPtr(nullptr),
- getFBConfigAttribPtr(nullptr),
- getVisualFromFBConfigPtr(nullptr),
- createWindowPtr(nullptr),
- destroyWindowPtr(nullptr),
- createPbufferPtr(nullptr),
- destroyPbufferPtr(nullptr),
- queryDrawablePtr(nullptr),
- createContextAttribsARBPtr(nullptr),
- swapIntervalEXTPtr(nullptr)
+ : createContextPtr(nullptr),
+ destroyContextPtr(nullptr),
+ makeCurrentPtr(nullptr),
+ swapBuffersPtr(nullptr),
+ queryExtensionPtr(nullptr),
+ queryVersionPtr(nullptr),
+ getCurrentContextPtr(nullptr),
+ getCurrentDrawablePtr(nullptr),
+ waitXPtr(nullptr),
+ waitGLPtr(nullptr),
+ queryExtensionsStringPtr(nullptr),
+ getFBConfigsPtr(nullptr),
+ chooseFBConfigPtr(nullptr),
+ getFBConfigAttribPtr(nullptr),
+ getVisualFromFBConfigPtr(nullptr),
+ createWindowPtr(nullptr),
+ destroyWindowPtr(nullptr),
+ createPbufferPtr(nullptr),
+ destroyPbufferPtr(nullptr),
+ queryDrawablePtr(nullptr),
+ createContextAttribsARBPtr(nullptr),
+ swapIntervalEXTPtr(nullptr),
+ swapIntervalMESAPtr(nullptr),
+ swapIntervalSGIPtr(nullptr)
{
}
// GLX 1.0
+ PFNGLXCREATECONTEXTPROC createContextPtr;
PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
PFNGLXMAKECURRENTPROC makeCurrentPtr;
PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
PFNGLXQUERYVERSIONPROC queryVersionPtr;
+ PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
+ PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
PFNGLXWAITXPROC waitXPtr;
PFNGLXWAITGLPROC waitGLPtr;
@@ -85,6 +93,12 @@ struct FunctionsGLX::GLXFunctionTable
// GLX_EXT_swap_control
PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;
+
+ // GLX_MESA_swap_control
+ PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;
+
+ // GLX_SGI_swap_control
+ PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;
};
FunctionsGLX::FunctionsGLX()
@@ -149,11 +163,14 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
#endif
// GLX 1.0
+ GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
+ GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
@@ -207,17 +224,17 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
{
GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
}
- else
- {
- mFnPtrs->createContextAttribsARBPtr = nullptr;
- }
if (hasExtension("GLX_EXT_swap_control"))
{
GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
}
- else
+ if (hasExtension("GLX_MESA_swap_control"))
{
- mFnPtrs->swapIntervalEXTPtr = nullptr;
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
+ }
+ if (hasExtension("GLX_SGI_swap_control"))
+ {
+ GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
}
#undef GET_FNPTR_OR_ERROR
@@ -249,6 +266,12 @@ int FunctionsGLX::getScreen() const
// GLX functions
// GLX 1.0
+glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
+{
+ GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
+ GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
+ return reinterpret_cast<glx::Context>(context);
+}
void FunctionsGLX::destroyContext(glx::Context context) const
{
GLXContext ctx = reinterpret_cast<GLXContext>(context);
@@ -271,6 +294,16 @@ Bool FunctionsGLX::queryVersion(int *major, int *minor) const
{
return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
}
+glx::Context FunctionsGLX::getCurrentContext() const
+{
+ GLXContext context = mFnPtrs->getCurrentContextPtr();
+ return reinterpret_cast<glx::Context>(context);
+}
+glx::Drawable FunctionsGLX::getCurrentDrawable() const
+{
+ GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
+ return reinterpret_cast<glx::Drawable>(drawable);
+}
void FunctionsGLX::waitX() const
{
mFnPtrs->waitXPtr();
@@ -344,4 +377,14 @@ void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
}
+int FunctionsGLX::swapIntervalMESA(int intervals) const
+{
+ return mFnPtrs->swapIntervalMESAPtr(intervals);
+}
+
+int FunctionsGLX::swapIntervalSGI(int intervals) const
+{
+ return mFnPtrs->swapIntervalSGIPtr(intervals);
+}
+
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
index 0afbbbbbd94..a919f4c88b0 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.h
@@ -37,11 +37,14 @@ class FunctionsGLX
PFNGETPROCPROC getProc;
// GLX 1.0
+ glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const;
void destroyContext(glx::Context context) const;
Bool makeCurrent(glx::Drawable drawable, glx::Context context) const;
void swapBuffers(glx::Drawable drawable) const;
Bool queryExtension(int *errorBase, int *event) const;
Bool queryVersion(int *major, int *minor) const;
+ glx::Context getCurrentContext() const;
+ glx::Drawable getCurrentDrawable() const;
void waitX() const;
void waitGL() const;
@@ -65,6 +68,12 @@ class FunctionsGLX
// GLX_EXT_swap_control
void swapIntervalEXT(glx::Drawable drawable, int interval) const;
+ // GLX_MESA_swap_control
+ int swapIntervalMESA(int interval) const;
+
+ // GLX_SGI_swap_control
+ int swapIntervalSGI(int interval) const;
+
private:
// So as to isolate GLX from angle we do not include angleutils.h and cannot
// use angle::NonCopyable so we replicated it here instead.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
index d876c6d7a40..1648ecccb56 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
@@ -43,10 +43,16 @@ PbufferSurfaceGLX::~PbufferSurfaceGLX()
egl::Error PbufferSurfaceGLX::initialize()
{
+ // Avoid creating 0-sized PBuffers as it fails on the Intel Mesa driver
+ // as commented on https://bugs.freedesktop.org/show_bug.cgi?id=38869 so we
+ // use (w, 1) or (1, h) instead.
+ int width = std::max(1, static_cast<int>(mWidth));
+ int height = std::max(1, static_cast<int>(mHeight));
+
const int attribs[] =
{
- GLX_PBUFFER_WIDTH, static_cast<int>(mWidth),
- GLX_PBUFFER_HEIGHT, static_cast<int>(mHeight),
+ GLX_PBUFFER_WIDTH, width,
+ GLX_PBUFFER_HEIGHT, height,
GLX_LARGEST_PBUFFER, mLargest,
None
};
@@ -91,7 +97,7 @@ egl::Error PbufferSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **
return egl::Error(EGL_SUCCESS);
}
-egl::Error PbufferSurfaceGLX::bindTexImage(EGLint buffer)
+egl::Error PbufferSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
{
UNIMPLEMENTED();
return egl::Error(EGL_SUCCESS);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
index f8d1bf76eae..aae313e293f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
@@ -36,7 +36,7 @@ class PbufferSurfaceGLX : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
index 4224eebecc8..b4c5fd6c9e2 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
@@ -28,11 +28,10 @@ WindowSurfaceGLX::WindowSurfaceGLX(const FunctionsGLX &glx,
mWindow(0),
mDisplay(display),
mGLX(glx),
- mGLXDisplay(*glxDisplay),
+ mGLXDisplay(glxDisplay),
mContext(context),
mFBConfig(fbConfig),
- mGLXWindow(0),
- mMaxSwapInterval(1)
+ mGLXWindow(0)
{
}
@@ -48,17 +47,31 @@ WindowSurfaceGLX::~WindowSurfaceGLX()
XDestroyWindow(mDisplay, mWindow);
}
- mGLXDisplay.syncXCommands();
+ mGLXDisplay->syncXCommands();
}
egl::Error WindowSurfaceGLX::initialize()
{
+ // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual
+ // extension.
+ {
+ XWindowAttributes windowAttributes;
+ XGetWindowAttributes(mDisplay, mParent, &windowAttributes);
+ unsigned long visualId = windowAttributes.visual->visualid;
+
+ if (!mGLXDisplay->isValidWindowVisualId(visualId))
+ {
+ return egl::Error(EGL_BAD_MATCH,
+ "The visual of native_window doesn't match the visual given with "
+ "ANGLE_X11_VISUAL_ID");
+ }
+ }
+
// The visual of the X window, GLX window and GLX context must match,
// however we received a user-created window that can have any visual
// and wouldn't work with our GLX context. To work in all cases, we
// create a child window with the right visual that covers all of its
// parent.
-
XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig);
if (!visualInfo)
{
@@ -95,18 +108,13 @@ egl::Error WindowSurfaceGLX::initialize()
0, visualInfo->depth, InputOutput, visual, attributeMask, &attributes);
mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr);
- if (mGLX.hasExtension("GLX_EXT_swap_control"))
- {
- mGLX.queryDrawable(mGLXWindow, GLX_MAX_SWAP_INTERVAL_EXT, &mMaxSwapInterval);
- }
-
XMapWindow(mDisplay, mWindow);
XFlush(mDisplay);
XFree(visualInfo);
XFreeColormap(mDisplay, colormap);
- mGLXDisplay.syncXCommands();
+ mGLXDisplay->syncXCommands();
return egl::Error(EGL_SUCCESS);
}
@@ -140,6 +148,7 @@ egl::Error WindowSurfaceGLX::swap()
mGLX.waitX();
}
+ mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl);
mGLX.swapBuffers(mGLXWindow);
return egl::Error(EGL_SUCCESS);
@@ -157,7 +166,7 @@ egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **v
return egl::Error(EGL_SUCCESS);
}
-egl::Error WindowSurfaceGLX::bindTexImage(EGLint buffer)
+egl::Error WindowSurfaceGLX::bindTexImage(gl::Texture *texture, EGLint buffer)
{
UNIMPLEMENTED();
return egl::Error(EGL_SUCCESS);
@@ -171,12 +180,7 @@ egl::Error WindowSurfaceGLX::releaseTexImage(EGLint buffer)
void WindowSurfaceGLX::setSwapInterval(EGLint interval)
{
- if (mGLX.hasExtension("GLX_EXT_swap_control"))
- {
- // TODO(cwallez) error checking?
- const int realInterval = std::min(interval, static_cast<int>(mMaxSwapInterval));
- mGLX.swapIntervalEXT(mGLXWindow, realInterval);
- }
+ mSwapControl.targetSwapInterval = interval;
}
EGLint WindowSurfaceGLX::getWidth() const
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
index f8447abd683..025a83f78de 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
#include "libANGLE/renderer/gl/SurfaceGL.h"
+#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
#include "libANGLE/renderer/gl/glx/platform_glx.h"
namespace rx
@@ -36,7 +37,7 @@ class WindowSurfaceGLX : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
@@ -55,12 +56,13 @@ class WindowSurfaceGLX : public SurfaceGL
Display *mDisplay;
const FunctionsGLX &mGLX;
- const DisplayGLX &mGLXDisplay;
+ DisplayGLX *mGLXDisplay;
glx::Context mContext;
glx::FBConfig mFBConfig;
glx::Window mGLXWindow;
- unsigned int mMaxSwapInterval;
+
+ SwapControlData mSwapControl;
};
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
index d54f07124ec..b0ba033c78c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h
@@ -32,6 +32,8 @@ typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx);
typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value);
typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
+typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
+typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
typedef void (*PFNGLXWAITGLPROC) ();
typedef void (*PFNGLXWAITXPROC) ();
typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
index facacf1a523..a8d9cdec004 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
@@ -111,6 +111,11 @@
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GLX_CONTEXT_FLAGS_ARB 0x2094
+// GLX_ARB_create_context_profile
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
// GLX_EXT_texture_from_pixmap
#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 0209795e6bc..a93f75eb589 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -111,35 +111,35 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G
static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name)
{
- GLint result;
+ GLint result = 0;
functions->getIntegerv(name, &result);
return result;
}
static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index)
{
- GLint result[2];
+ GLint result[2] = {};
functions->getIntegerv(name, result);
return result[index];
}
static GLint64 QuerySingleGLInt64(const FunctionsGL *functions, GLenum name)
{
- GLint64 result;
+ GLint64 result = 0;
functions->getInteger64v(name, &result);
return result;
}
static GLfloat QuerySingleGLFloat(const FunctionsGL *functions, GLenum name)
{
- GLfloat result;
+ GLfloat result = 0.0f;
functions->getFloatv(name, &result);
return result;
}
static GLfloat QueryGLFloatRange(const FunctionsGL *functions, GLenum name, size_t index)
{
- GLfloat result[2];
+ GLfloat result[2] = {};
functions->getFloatv(name, result);
return result[index];
}
@@ -478,7 +478,8 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
// Table 6.34, implementation dependent transform feedback limits
- if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_transform_feedback") ||
+ if (functions->isAtLeastGL(gl::Version(4, 0)) ||
+ functions->hasGLExtension("GL_ARB_transform_feedback2") ||
functions->isAtLeastGLES(gl::Version(3, 0)))
{
caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
@@ -511,6 +512,52 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
}
+ // Can't support ES3 without texture swizzling
+ if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+ !functions->hasGLExtension("GL_ARB_texture_swizzle") &&
+ !functions->hasGLExtension("GL_EXT_texture_swizzle") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+
+ // Texture swizzling is required to work around the luminance texture format not being
+ // present in the core profile
+ if (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT)
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(0, 0));
+ }
+ }
+
+ // Can't support ES3 without the GLSL packing builtins. We have a workaround for all
+ // desktop OpenGL versions starting from 3.3 with the bit packing extension.
+ if (!functions->isAtLeastGL(gl::Version(4, 2)) &&
+ !(functions->isAtLeastGL(gl::Version(3, 2)) &&
+ functions->hasGLExtension("GL_ARB_shader_bit_encoding")) &&
+ !functions->hasGLExtension("GL_ARB_shading_language_packing") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // ES3 needs to support explicit layout location qualifiers, while it might be possible to
+ // fake them in our side, we currently don't support that.
+ if (!functions->isAtLeastGL(gl::Version(3, 3)) &&
+ !functions->hasGLExtension("GL_ARB_explicit_attrib_location") &&
+ !functions->isAtLeastGLES(gl::Version(3, 0)))
+ {
+ LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
+ }
+
+ // TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time
+ // if the max uniform vectors is too large. Artificially limit the maximum until the test is
+ // updated.
+ caps->maxVertexUniformVectors = std::min(1024u, caps->maxVertexUniformVectors);
+ caps->maxVertexUniformComponents =
+ std::min(caps->maxVertexUniformVectors / 4, caps->maxVertexUniformComponents);
+ caps->maxFragmentUniformVectors = std::min(1024u, caps->maxFragmentUniformVectors);
+ caps->maxFragmentUniformComponents =
+ std::min(caps->maxFragmentUniformVectors / 4, caps->maxFragmentUniformComponents);
+
// Extension support
extensions->setTextureExtensionSupport(*textureCapsMap);
extensions->elementIndexUint = functions->standard == STANDARD_GL_DESKTOP ||
@@ -527,6 +574,11 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_draw_buffers");
extensions->textureStorage = true;
extensions->textureFilterAnisotropic = functions->hasGLExtension("GL_EXT_texture_filter_anisotropic") || functions->hasGLESExtension("GL_EXT_texture_filter_anisotropic");
+ extensions->occlusionQueryBoolean =
+ functions->isAtLeastGL(gl::Version(1, 5)) ||
+ functions->hasGLExtension("GL_ARB_occlusion_query2") ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_EXT_occlusion_query_boolean");
extensions->maxTextureAnisotropy = extensions->textureFilterAnisotropic ? QuerySingleGLFloat(functions, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0.0f;
extensions->fence = functions->hasGLExtension("GL_NV_fence") || functions->hasGLESExtension("GL_NV_fence");
extensions->blendMinMax = functions->isAtLeastGL(gl::Version(1, 5)) || functions->hasGLExtension("GL_EXT_blend_minmax") ||
@@ -556,6 +608,9 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
extensions->debugMarker =
functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") ||
functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug");
+
+ // ANGLE emulates vertex array objects in its GL layer
+ extensions->vertexArrayObject = true;
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
@@ -574,9 +629,12 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
functions->standard == STANDARD_GL_DESKTOP &&
(vendor == VENDOR_ID_INTEL || vendor == VENDOR_ID_AMD);
-#if ANGLE_PLATFORM_APPLE
+#if defined(ANGLE_PLATFORM_APPLE)
workarounds->doWhileGLSLCausesGPUHang = true;
#endif
+
+ workarounds->finishDoesNotCauseQueriesToBeAvailable =
+ functions->standard == STANDARD_GL_DESKTOP && vendor == VENDOR_ID_NVIDIA;
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
index 7f293b5c875..284b603891f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -233,7 +233,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
// Request core profile
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
- std::vector<int> contextCreationAttibutes;
+ std::vector<int> contextCreationAttributes;
// Don't request a specific version unless the user wants one. WGL will return the highest version
// that the driver supports if no version is requested.
@@ -242,32 +242,32 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
EGLint requestedMinorVersion = displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
{
- contextCreationAttibutes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
- contextCreationAttibutes.push_back(requestedMajorVersion);
+ contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMajorVersion);
- contextCreationAttibutes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
- contextCreationAttibutes.push_back(requestedMinorVersion);
+ contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMinorVersion);
}
// Set the flag attributes
if (flags != 0)
{
- contextCreationAttibutes.push_back(WGL_CONTEXT_FLAGS_ARB);
- contextCreationAttibutes.push_back(flags);
+ contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ contextCreationAttributes.push_back(flags);
}
// Set the mask attribute
if (mask != 0)
{
- contextCreationAttibutes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
- contextCreationAttibutes.push_back(mask);
+ contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+ contextCreationAttributes.push_back(mask);
}
// Signal the end of the attributes
- contextCreationAttibutes.push_back(0);
- contextCreationAttibutes.push_back(0);
+ contextCreationAttributes.push_back(0);
+ contextCreationAttributes.push_back(0);
- mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttibutes[0]);
+ mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttributes[0]);
}
// If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
index 6532dfaef97..2cfe6e9eb95 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
@@ -8,6 +8,10 @@
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include <algorithm>
+
+#include "common/string_utils.h"
+
namespace rx
{
@@ -30,12 +34,15 @@ static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProc
}
template <typename T>
-static void GetWGLExtensionProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
- const std::string &extensions, const std::string &extensionName,
- const std::string &procName, T *outProcAddress)
+static void GetWGLExtensionProcAddress(HMODULE glModule,
+ PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+ const std::vector<std::string> &extensions,
+ const std::string &extensionName,
+ const std::string &procName,
+ T *outProcAddress)
{
T proc = nullptr;
- if (extensions.find(extensionName) != std::string::npos)
+ if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end())
{
GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc);
}
@@ -78,7 +85,15 @@ FunctionsWGL::FunctionsWGL()
queryPbufferARB(nullptr),
bindTexImageARB(nullptr),
releaseTexImageARB(nullptr),
- setPbufferAttribARB(nullptr)
+ setPbufferAttribARB(nullptr),
+ dxSetResourceShareHandleNV(nullptr),
+ dxOpenDeviceNV(nullptr),
+ dxCloseDeviceNV(nullptr),
+ dxRegisterObjectNV(nullptr),
+ dxUnregisterObjectNV(nullptr),
+ dxObjectAccessNV(nullptr),
+ dxLockObjectsNV(nullptr),
+ dxUnlockObjectsNV(nullptr)
{
}
@@ -112,15 +127,16 @@ void FunctionsWGL::initialize(HMODULE glModule, HDC context)
GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT);
GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB);
- std::string extensions = "";
+ std::string extensionString = "";
if (getExtensionStringEXT)
{
- extensions = getExtensionStringEXT();
+ extensionString = getExtensionStringEXT();
}
else if (getExtensionStringARB && context)
{
- extensions = getExtensionStringARB(context);
+ extensionString = getExtensionStringARB(context);
}
+ angle::SplitStringAlongWhitespace(extensionString, &extensions);
// Load the wgl extension functions by checking if the context supports the extension first
@@ -146,6 +162,20 @@ void FunctionsWGL::initialize(HMODULE glModule, HDC context)
GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB);
GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB);
GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB);
+
+ // WGL_NV_DX_interop
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV);
}
+bool FunctionsWGL::hasExtension(const std::string &ext) const
+{
+ return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
index 2f9409a47ac..30cf9ebc0b0 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
@@ -6,6 +6,9 @@
// FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+
#include "common/angleutils.h"
#include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h"
@@ -20,6 +23,10 @@ class FunctionsWGL : angle::NonCopyable
// Loads all available wgl functions, may be called multiple times
void initialize(HMODULE glModule, HDC context);
+ // Extension information
+ std::vector<std::string> extensions;
+ bool hasExtension(const std::string &ext) const;
+
// Base WGL functions
PFNWGLCOPYCONTEXTPROC copyContext;
PFNWGLCREATECONTEXTPROC createContext;
@@ -70,6 +77,18 @@ class FunctionsWGL : angle::NonCopyable
PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB;
PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB;
PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB;
+
+ // WGL_NV_DX_interop
+ PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV;
+ PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV;
+ PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV;
+ PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV;
+ PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV;
+ PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV;
+ PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV;
+ PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV;
};
}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
index 0615c879a0c..440b9934c47 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
@@ -146,7 +146,7 @@ static int GetWGLBufferBindTarget(EGLint buffer)
}
}
-egl::Error PbufferSurfaceWGL::bindTexImage(EGLint buffer)
+egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
{
if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
index 3deab4b5cdb..64e4de16c6d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
@@ -39,7 +39,7 @@ class PbufferSurfaceWGL : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
index 9c898a70d77..4c7e073d6a2 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
@@ -119,7 +119,7 @@ egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **v
return egl::Error(EGL_SUCCESS);
}
-egl::Error WindowSurfaceWGL::bindTexImage(EGLint buffer)
+egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
{
UNIMPLEMENTED();
return egl::Error(EGL_SUCCESS);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
index 568db3d5421..5112554cea6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
@@ -34,7 +34,7 @@ class WindowSurfaceWGL : public SurfaceGL
egl::Error swap() override;
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
- egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
index 1fae5a04ed0..641c3fbc429 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
@@ -8,7 +8,7 @@
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
-#include "libANGLE/renderer/gl/wgl/functionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
namespace rx
{