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