1 //
2 // Copyright 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 mFeaturesInitialized(false),
41 mDisjoint(false),
42 mDeviceLost(false)
43 {}
44
~RendererD3D()45 RendererD3D::~RendererD3D() {}
46
skipDraw(const gl::State & glState,gl::PrimitiveMode drawMode)47 bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode)
48 {
49 if (drawMode == gl::PrimitiveMode::Points)
50 {
51 bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
52
53 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
54 // which affects varying interpolation. Since the value of gl_PointSize is
55 // undefined when not written, just skip drawing to avoid unexpected results.
56 if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
57 {
58 // Notify developers of risking undefined behavior.
59 WARN() << "Point rendering without writing to gl_PointSize.";
60 return true;
61 }
62 }
63 else if (gl::IsTriangleMode(drawMode))
64 {
65 if (glState.getRasterizerState().cullFace &&
66 glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
67 {
68 return true;
69 }
70 }
71
72 return false;
73 }
74
getResetStatus()75 gl::GraphicsResetStatus RendererD3D::getResetStatus()
76 {
77 if (!mDeviceLost)
78 {
79 if (testDeviceLost())
80 {
81 mDeviceLost = true;
82 notifyDeviceLost();
83 return gl::GraphicsResetStatus::UnknownContextReset;
84 }
85 return gl::GraphicsResetStatus::NoError;
86 }
87
88 if (testDeviceResettable())
89 {
90 return gl::GraphicsResetStatus::NoError;
91 }
92
93 return gl::GraphicsResetStatus::UnknownContextReset;
94 }
95
notifyDeviceLost()96 void RendererD3D::notifyDeviceLost()
97 {
98 mDisplay->notifyDeviceLost();
99 }
100
getVendorString() const101 std::string RendererD3D::getVendorString() const
102 {
103 LUID adapterLuid = {};
104
105 if (getLUID(&adapterLuid))
106 {
107 char adapterLuidString[64];
108 sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)",
109 adapterLuid.HighPart, adapterLuid.LowPart);
110 return std::string(adapterLuidString);
111 }
112
113 return std::string("");
114 }
115
setGPUDisjoint()116 void RendererD3D::setGPUDisjoint()
117 {
118 mDisjoint = true;
119 }
120
getGPUDisjoint()121 GLint RendererD3D::getGPUDisjoint()
122 {
123 bool disjoint = mDisjoint;
124
125 // Disjoint flag is cleared when read
126 mDisjoint = false;
127
128 return disjoint;
129 }
130
getTimestamp()131 GLint64 RendererD3D::getTimestamp()
132 {
133 // D3D has no way to get an actual timestamp reliably so 0 is returned
134 return 0;
135 }
136
ensureCapsInitialized() const137 void RendererD3D::ensureCapsInitialized() const
138 {
139 if (!mCapsInitialized)
140 {
141 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
142 mCapsInitialized = true;
143 }
144 }
145
getNativeCaps() const146 const gl::Caps &RendererD3D::getNativeCaps() const
147 {
148 ensureCapsInitialized();
149 return mNativeCaps;
150 }
151
getNativeTextureCaps() const152 const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
153 {
154 ensureCapsInitialized();
155 return mNativeTextureCaps;
156 }
157
getNativeExtensions() const158 const gl::Extensions &RendererD3D::getNativeExtensions() const
159 {
160 ensureCapsInitialized();
161 return mNativeExtensions;
162 }
163
getNativeLimitations() const164 const gl::Limitations &RendererD3D::getNativeLimitations() const
165 {
166 ensureCapsInitialized();
167 return mNativeLimitations;
168 }
169
generateSerial()170 Serial RendererD3D::generateSerial()
171 {
172 return mSerialFactory.generate();
173 }
174
InstancedPointSpritesActive(ProgramD3D * programD3D,gl::PrimitiveMode mode)175 bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode)
176 {
177 return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() &&
178 mode == gl::PrimitiveMode::Points;
179 }
180
initRenderTarget(const gl::Context * context,RenderTargetD3D * renderTarget)181 angle::Result RendererD3D::initRenderTarget(const gl::Context *context,
182 RenderTargetD3D *renderTarget)
183 {
184 return clearRenderTarget(context, renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0);
185 }
186
getFeatures() const187 const angle::FeaturesD3D &RendererD3D::getFeatures() const
188 {
189 if (!mFeaturesInitialized)
190 {
191 initializeFeatures(&mFeatures);
192 mFeaturesInitialized = true;
193 }
194
195 return mFeatures;
196 }
197
GetBlendSampleMask(const gl::State & glState,int samples)198 unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
199 {
200 unsigned int mask = 0;
201 if (glState.isSampleCoverageEnabled())
202 {
203 GLfloat coverageValue = glState.getSampleCoverageValue();
204 if (coverageValue != 0)
205 {
206 float threshold = 0.5f;
207
208 for (int i = 0; i < samples; ++i)
209 {
210 mask <<= 1;
211
212 if ((i + 1) * coverageValue >= threshold)
213 {
214 threshold += 1.0f;
215 mask |= 1;
216 }
217 }
218 }
219
220 bool coverageInvert = glState.getSampleCoverageInvert();
221 if (coverageInvert)
222 {
223 mask = ~mask;
224 }
225 }
226 else
227 {
228 mask = 0xFFFFFFFF;
229 }
230
231 if (glState.isSampleMaskEnabled())
232 {
233 mask &= glState.getSampleMaskWord(0);
234 }
235
236 return mask;
237 }
238
DefaultGLErrorCode(HRESULT hr)239 GLenum DefaultGLErrorCode(HRESULT hr)
240 {
241 switch (hr)
242 {
243 #ifdef ANGLE_ENABLE_D3D9
244 case D3DERR_OUTOFVIDEOMEMORY:
245 #endif
246 case E_OUTOFMEMORY:
247 return GL_OUT_OF_MEMORY;
248 default:
249 return GL_INVALID_OPERATION;
250 }
251 }
252 } // namespace rx
253