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/DisplayD3D.h"
27 #include "libANGLE/renderer/d3d/IndexDataManager.h"
28 #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h"
29 #include "libANGLE/renderer/d3d/SamplerD3D.h"
30 #include "libANGLE/renderer/d3d/TextureD3D.h"
31
32 namespace rx
33 {
34
RendererD3D(egl::Display * display)35 RendererD3D::RendererD3D(egl::Display *display)
36 : mDisplay(display),
37 mPresentPathFastEnabled(false),
38 mCapsInitialized(false),
39 mFeaturesInitialized(false),
40 mDeviceLost(false)
41 {}
42
~RendererD3D()43 RendererD3D::~RendererD3D() {}
44
skipDraw(const gl::State & glState,gl::PrimitiveMode drawMode)45 bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode)
46 {
47 if (drawMode == gl::PrimitiveMode::Points)
48 {
49 bool usesPointSize =
50 GetImplAs<ProgramExecutableD3D>(glState.getProgramExecutable())->usesPointSize();
51
52 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
53 // which affects varying interpolation. Since the value of gl_PointSize is
54 // undefined when not written, just skip drawing to avoid unexpected results.
55 if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
56 {
57 // Notify developers of risking undefined behavior.
58 WARN() << "Point rendering without writing to gl_PointSize.";
59 return true;
60 }
61 }
62 else if (gl::IsTriangleMode(drawMode))
63 {
64 if (glState.getRasterizerState().cullFace &&
65 glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
66 {
67 return true;
68 }
69 }
70
71 return false;
72 }
73
getResetStatus()74 gl::GraphicsResetStatus RendererD3D::getResetStatus()
75 {
76 if (!mDeviceLost)
77 {
78 if (testDeviceLost())
79 {
80 mDeviceLost = true;
81 notifyDeviceLost();
82 return gl::GraphicsResetStatus::UnknownContextReset;
83 }
84 return gl::GraphicsResetStatus::NoError;
85 }
86
87 if (testDeviceResettable())
88 {
89 return gl::GraphicsResetStatus::NoError;
90 }
91
92 return gl::GraphicsResetStatus::UnknownContextReset;
93 }
94
notifyDeviceLost()95 void RendererD3D::notifyDeviceLost()
96 {
97 mDisplay->notifyDeviceLost();
98 }
99
getTimestamp()100 GLint64 RendererD3D::getTimestamp()
101 {
102 // D3D has no way to get an actual timestamp reliably so 0 is returned
103 return 0;
104 }
105
ensureCapsInitialized() const106 void RendererD3D::ensureCapsInitialized() const
107 {
108 if (!mCapsInitialized)
109 {
110 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations,
111 &mNativePLSOptions);
112 mCapsInitialized = true;
113 }
114 }
115
getNativeCaps() const116 const gl::Caps &RendererD3D::getNativeCaps() const
117 {
118 ensureCapsInitialized();
119 return mNativeCaps;
120 }
121
getNativeTextureCaps() const122 const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
123 {
124 ensureCapsInitialized();
125 return mNativeTextureCaps;
126 }
127
getNativeExtensions() const128 const gl::Extensions &RendererD3D::getNativeExtensions() const
129 {
130 ensureCapsInitialized();
131 return mNativeExtensions;
132 }
133
getNativeLimitations() const134 const gl::Limitations &RendererD3D::getNativeLimitations() const
135 {
136 ensureCapsInitialized();
137 return mNativeLimitations;
138 }
139
getNativePixelLocalStorageOptions() const140 const ShPixelLocalStorageOptions &RendererD3D::getNativePixelLocalStorageOptions() const
141 {
142 return mNativePLSOptions;
143 }
144
generateSerial()145 UniqueSerial RendererD3D::generateSerial()
146 {
147 return mSerialFactory.generate();
148 }
149
initRenderTarget(const gl::Context * context,RenderTargetD3D * renderTarget)150 angle::Result RendererD3D::initRenderTarget(const gl::Context *context,
151 RenderTargetD3D *renderTarget)
152 {
153 return clearRenderTarget(context, renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0);
154 }
155
getFeatures() const156 const angle::FeaturesD3D &RendererD3D::getFeatures() const
157 {
158 if (!mFeaturesInitialized)
159 {
160 initializeFeatures(&mFeatures);
161 mFeaturesInitialized = true;
162 }
163
164 return mFeatures;
165 }
166
GetBlendSampleMask(const gl::State & glState,int samples)167 unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
168 {
169 unsigned int mask = 0;
170 if (glState.isSampleCoverageEnabled())
171 {
172 GLfloat coverageValue = glState.getSampleCoverageValue();
173 if (coverageValue != 0)
174 {
175 float threshold = 0.5f;
176
177 for (int i = 0; i < samples; ++i)
178 {
179 mask <<= 1;
180
181 if ((i + 1) * coverageValue >= threshold)
182 {
183 threshold += 1.0f;
184 mask |= 1;
185 }
186 }
187 }
188
189 bool coverageInvert = glState.getSampleCoverageInvert();
190 if (coverageInvert)
191 {
192 mask = ~mask;
193 }
194 }
195 else
196 {
197 mask = 0xFFFFFFFF;
198 }
199
200 if (glState.isSampleMaskEnabled())
201 {
202 mask &= glState.getSampleMaskWord(0);
203 }
204
205 return mask;
206 }
207
DefaultGLErrorCode(HRESULT hr)208 GLenum DefaultGLErrorCode(HRESULT hr)
209 {
210 switch (hr)
211 {
212 #ifdef ANGLE_ENABLE_D3D9
213 case D3DERR_OUTOFVIDEOMEMORY:
214 #endif
215 case E_OUTOFMEMORY:
216 return GL_OUT_OF_MEMORY;
217 default:
218 return GL_INVALID_OPERATION;
219 }
220 }
221 } // namespace rx
222