1 //
2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // RendererD3D.cpp: Implementation of the base D3D Renderer.
8
9 #include "libANGLE/renderer/d3d/RendererD3D.h"
10
11 #include "common/MemoryBuffer.h"
12 #include "common/debug.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 #include "libANGLE/ImageIndex.h"
19 #include "libANGLE/ResourceManager.h"
20 #include "libANGLE/State.h"
21 #include "libANGLE/VertexArray.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/renderer/ContextImpl.h"
24 #include "libANGLE/renderer/TextureImpl.h"
25 #include "libANGLE/renderer/d3d/BufferD3D.h"
26 #include "libANGLE/renderer/d3d/DeviceD3D.h"
27 #include "libANGLE/renderer/d3d/DisplayD3D.h"
28 #include "libANGLE/renderer/d3d/IndexDataManager.h"
29 #include "libANGLE/renderer/d3d/ProgramD3D.h"
30 #include "libANGLE/renderer/d3d/SamplerD3D.h"
31 #include "libANGLE/renderer/d3d/TextureD3D.h"
32
33 namespace rx
34 {
35
RendererD3D(egl::Display * display)36 RendererD3D::RendererD3D(egl::Display *display)
37 : mDisplay(display),
38 mPresentPathFastEnabled(false),
39 mCapsInitialized(false),
40 mWorkaroundsInitialized(false),
41 mDisjoint(false),
42 mDeviceLost(false),
43 mWorkerThreadPool(4)
44 {
45 }
46
~RendererD3D()47 RendererD3D::~RendererD3D()
48 {
49 cleanup();
50 }
51
cleanup()52 void RendererD3D::cleanup()
53 {
54 mIncompleteTextures.onDestroy(mDisplay->getProxyContext());
55 }
56
skipDraw(const gl::State & glState,GLenum drawMode)57 bool RendererD3D::skipDraw(const gl::State &glState, GLenum drawMode)
58 {
59 if (drawMode == GL_POINTS)
60 {
61 bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
62
63 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
64 // which affects varying interpolation. Since the value of gl_PointSize is
65 // undefined when not written, just skip drawing to avoid unexpected results.
66 if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
67 {
68 // Notify developers of risking undefined behavior.
69 WARN() << "Point rendering without writing to gl_PointSize.";
70 return true;
71 }
72 }
73 else if (gl::IsTriangleMode(drawMode))
74 {
75 if (glState.getRasterizerState().cullFace &&
76 glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
77 {
78 return true;
79 }
80 }
81
82 return false;
83 }
84
getIncompleteTexture(const gl::Context * context,GLenum type,gl::Texture ** textureOut)85 gl::Error RendererD3D::getIncompleteTexture(const gl::Context *context,
86 GLenum type,
87 gl::Texture **textureOut)
88 {
89 return mIncompleteTextures.getIncompleteTexture(context, type, this, textureOut);
90 }
91
getResetStatus()92 GLenum RendererD3D::getResetStatus()
93 {
94 if (!mDeviceLost)
95 {
96 if (testDeviceLost())
97 {
98 mDeviceLost = true;
99 notifyDeviceLost();
100 return GL_UNKNOWN_CONTEXT_RESET_EXT;
101 }
102 return GL_NO_ERROR;
103 }
104
105 if (testDeviceResettable())
106 {
107 return GL_NO_ERROR;
108 }
109
110 return GL_UNKNOWN_CONTEXT_RESET_EXT;
111 }
112
notifyDeviceLost()113 void RendererD3D::notifyDeviceLost()
114 {
115 mDisplay->notifyDeviceLost();
116 }
117
getVendorString() const118 std::string RendererD3D::getVendorString() const
119 {
120 LUID adapterLuid = {0};
121
122 if (getLUID(&adapterLuid))
123 {
124 char adapterLuidString[64];
125 sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)",
126 adapterLuid.HighPart, adapterLuid.LowPart);
127 return std::string(adapterLuidString);
128 }
129
130 return std::string("");
131 }
132
setGPUDisjoint()133 void RendererD3D::setGPUDisjoint()
134 {
135 mDisjoint = true;
136 }
137
getGPUDisjoint()138 GLint RendererD3D::getGPUDisjoint()
139 {
140 bool disjoint = mDisjoint;
141
142 // Disjoint flag is cleared when read
143 mDisjoint = false;
144
145 return disjoint;
146 }
147
getTimestamp()148 GLint64 RendererD3D::getTimestamp()
149 {
150 // D3D has no way to get an actual timestamp reliably so 0 is returned
151 return 0;
152 }
153
ensureCapsInitialized() const154 void RendererD3D::ensureCapsInitialized() const
155 {
156 if (!mCapsInitialized)
157 {
158 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
159 mCapsInitialized = true;
160 }
161 }
162
getNativeCaps() const163 const gl::Caps &RendererD3D::getNativeCaps() const
164 {
165 ensureCapsInitialized();
166 return mNativeCaps;
167 }
168
getNativeTextureCaps() const169 const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
170 {
171 ensureCapsInitialized();
172 return mNativeTextureCaps;
173 }
174
getNativeExtensions() const175 const gl::Extensions &RendererD3D::getNativeExtensions() const
176 {
177 ensureCapsInitialized();
178 return mNativeExtensions;
179 }
180
getNativeLimitations() const181 const gl::Limitations &RendererD3D::getNativeLimitations() const
182 {
183 ensureCapsInitialized();
184 return mNativeLimitations;
185 }
186
getWorkerThreadPool()187 angle::WorkerThreadPool *RendererD3D::getWorkerThreadPool()
188 {
189 return &mWorkerThreadPool;
190 }
191
generateSerial()192 Serial RendererD3D::generateSerial()
193 {
194 return mSerialFactory.generate();
195 }
196
InstancedPointSpritesActive(ProgramD3D * programD3D,GLenum mode)197 bool InstancedPointSpritesActive(ProgramD3D *programD3D, GLenum mode)
198 {
199 return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() &&
200 mode == GL_POINTS;
201 }
202
initRenderTarget(RenderTargetD3D * renderTarget)203 gl::Error RendererD3D::initRenderTarget(RenderTargetD3D *renderTarget)
204 {
205 return clearRenderTarget(renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0);
206 }
207
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)208 gl::Error RendererD3D::initializeMultisampleTextureToBlack(const gl::Context *context,
209 gl::Texture *glTexture)
210 {
211 ASSERT(glTexture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE);
212 TextureD3D *textureD3D = GetImplAs<TextureD3D>(glTexture);
213 gl::ImageIndex index = gl::ImageIndex::Make2DMultisample();
214 RenderTargetD3D *renderTarget = nullptr;
215 ANGLE_TRY(textureD3D->getRenderTarget(context, index, &renderTarget));
216 return clearRenderTarget(renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0);
217 }
218
GetBlendSampleMask(const gl::State & glState,int samples)219 unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
220 {
221 unsigned int mask = 0;
222 if (glState.isSampleCoverageEnabled())
223 {
224 GLfloat coverageValue = glState.getSampleCoverageValue();
225 if (coverageValue != 0)
226 {
227 float threshold = 0.5f;
228
229 for (int i = 0; i < samples; ++i)
230 {
231 mask <<= 1;
232
233 if ((i + 1) * coverageValue >= threshold)
234 {
235 threshold += 1.0f;
236 mask |= 1;
237 }
238 }
239 }
240
241 bool coverageInvert = glState.getSampleCoverageInvert();
242 if (coverageInvert)
243 {
244 mask = ~mask;
245 }
246 }
247 else
248 {
249 mask = 0xFFFFFFFF;
250 }
251
252 if (glState.isSampleMaskEnabled())
253 {
254 mask &= glState.getSampleMaskWord(0);
255 }
256
257 return mask;
258 }
259
260 } // namespace rx
261