• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 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 // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
8 
9 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
10 
11 #include <EGL/eglext.h>
12 #include <sstream>
13 
14 #include "common/utilities.h"
15 #include "libANGLE/Buffer.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Display.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/FramebufferAttachment.h"
20 #include "libANGLE/Program.h"
21 #include "libANGLE/Renderbuffer.h"
22 #include "libANGLE/State.h"
23 #include "libANGLE/Surface.h"
24 #include "libANGLE/Texture.h"
25 #include "libANGLE/angletypes.h"
26 #include "libANGLE/features.h"
27 #include "libANGLE/formatutils.h"
28 #include "libANGLE/renderer/d3d/CompilerD3D.h"
29 #include "libANGLE/renderer/d3d/DeviceD3D.h"
30 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
31 #include "libANGLE/renderer/d3d/IndexDataManager.h"
32 #include "libANGLE/renderer/d3d/ProgramD3D.h"
33 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
34 #include "libANGLE/renderer/d3d/ShaderD3D.h"
35 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
36 #include "libANGLE/renderer/d3d/TextureD3D.h"
37 #include "libANGLE/renderer/d3d/d3d9/Blit9.h"
38 #include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
39 #include "libANGLE/renderer/d3d/d3d9/Context9.h"
40 #include "libANGLE/renderer/d3d/d3d9/Fence9.h"
41 #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
42 #include "libANGLE/renderer/d3d/d3d9/Image9.h"
43 #include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
44 #include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
45 #include "libANGLE/renderer/d3d/d3d9/Query9.h"
46 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
47 #include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
48 #include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
49 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
50 #include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
51 #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
52 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
53 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
54 #include "libANGLE/trace.h"
55 
56 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
57 #    define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
58 #endif
59 
60 // Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2.
61 // Such a device would not be conformant.
62 #ifndef ANGLE_SUPPORT_SHADER_MODEL_2
63 #    define ANGLE_SUPPORT_SHADER_MODEL_2 0
64 #endif
65 
66 namespace rx
67 {
68 
69 namespace
70 {
71 enum
72 {
73     MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
74     MAX_PIXEL_CONSTANT_VECTORS_SM2   = 32,
75     MAX_PIXEL_CONSTANT_VECTORS_SM3   = 224,
76     MAX_VARYING_VECTORS_SM2          = 8,
77     MAX_VARYING_VECTORS_SM3          = 10,
78 
79     MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
80 };
81 
82 template <typename T>
DrawPoints(IDirect3DDevice9 * device,GLsizei count,const void * indices,int minIndex)83 static void DrawPoints(IDirect3DDevice9 *device, GLsizei count, const void *indices, int minIndex)
84 {
85     for (int i = 0; i < count; i++)
86     {
87         unsigned int indexValue =
88             static_cast<unsigned int>(static_cast<const T *>(indices)[i]) - minIndex;
89         device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
90     }
91 }
92 
93 // A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
94 // close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
95 // for almost any demanding application.
96 constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
97 }  // anonymous namespace
98 
Renderer9(egl::Display * display)99 Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
100 {
101     mD3d9Module = nullptr;
102 
103     mD3d9         = nullptr;
104     mD3d9Ex       = nullptr;
105     mDevice       = nullptr;
106     mDeviceEx     = nullptr;
107     mDeviceWindow = nullptr;
108     mBlit         = nullptr;
109 
110     mAdapter = D3DADAPTER_DEFAULT;
111 
112     const egl::AttributeMap &attributes = display->getAttributeMap();
113     EGLint requestedDeviceType          = static_cast<EGLint>(attributes.get(
114         EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
115     switch (requestedDeviceType)
116     {
117         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
118             mDeviceType = D3DDEVTYPE_HAL;
119             break;
120 
121         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
122             mDeviceType = D3DDEVTYPE_REF;
123             break;
124 
125         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
126             mDeviceType = D3DDEVTYPE_NULLREF;
127             break;
128 
129         default:
130             UNREACHABLE();
131     }
132 
133     mMaskedClearSavedState = nullptr;
134 
135     mVertexDataManager = nullptr;
136     mIndexDataManager  = nullptr;
137     mLineLoopIB        = nullptr;
138     mCountingIB        = nullptr;
139 
140     mMaxNullColorbufferLRU = 0;
141     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
142     {
143         mNullRenderTargetCache[i].lruCount     = 0;
144         mNullRenderTargetCache[i].width        = 0;
145         mNullRenderTargetCache[i].height       = 0;
146         mNullRenderTargetCache[i].renderTarget = nullptr;
147     }
148 
149     mAppliedVertexShader  = nullptr;
150     mAppliedPixelShader   = nullptr;
151     mAppliedProgramSerial = 0;
152 
153     gl::InitializeDebugAnnotations(&mAnnotator);
154 }
155 
~Renderer9()156 Renderer9::~Renderer9()
157 {
158     if (mDevice)
159     {
160         // If the device is lost, reset it first to prevent leaving the driver in an unstable state
161         if (testDeviceLost())
162         {
163             resetDevice();
164         }
165     }
166 
167     release();
168 }
169 
release()170 void Renderer9::release()
171 {
172     gl::UninitializeDebugAnnotations();
173 
174     mTranslatedAttribCache.clear();
175 
176     releaseDeviceResources();
177 
178     SafeRelease(mDevice);
179     SafeRelease(mDeviceEx);
180     SafeRelease(mD3d9);
181     SafeRelease(mD3d9Ex);
182 
183     mCompiler.release();
184 
185     if (mDeviceWindow)
186     {
187         DestroyWindow(mDeviceWindow);
188         mDeviceWindow = nullptr;
189     }
190 
191     mD3d9Module = nullptr;
192 }
193 
initialize()194 egl::Error Renderer9::initialize()
195 {
196     ANGLE_TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
197     mD3d9Module = ::LoadLibrary(TEXT("d3d9.dll"));
198 
199     if (mD3d9Module == nullptr)
200     {
201         return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "No D3D9 module found.";
202     }
203 
204     typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
205     Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
206         reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
207 
208     // Use Direct3D9Ex if available. Among other things, this version is less
209     // inclined to report a lost context, for example when the user switches
210     // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are
211     // available.
212     if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr &&
213         SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
214     {
215         ANGLE_TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
216         ASSERT(mD3d9Ex);
217         mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9));
218         ASSERT(mD3d9);
219     }
220     else
221     {
222         ANGLE_TRACE_EVENT0("gpu.angle", "Direct3DCreate9");
223         mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
224     }
225 
226     if (!mD3d9)
227     {
228         return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "Could not create D3D9 device.";
229     }
230 
231     if (mDisplay->getNativeDisplayId() != nullptr)
232     {
233         //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context
234         //  corresponds to
235     }
236 
237     HRESULT result;
238 
239     // Give up on getting device caps after about one second.
240     {
241         ANGLE_TRACE_EVENT0("gpu.angle", "GetDeviceCaps");
242         for (int i = 0; i < 10; ++i)
243         {
244             result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
245             if (SUCCEEDED(result))
246             {
247                 break;
248             }
249             else if (result == D3DERR_NOTAVAILABLE)
250             {
251                 Sleep(100);  // Give the driver some time to initialize/recover
252             }
253             else if (FAILED(result))  // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY,
254                                       // D3DERR_INVALIDDEVICE, or another error we can't recover
255                                       // from
256             {
257                 return egl::EglNotInitialized(D3D9_INIT_OTHER_ERROR)
258                        << "Failed to get device caps, " << gl::FmtHR(result);
259             }
260         }
261     }
262 
263 #if ANGLE_SUPPORT_SHADER_MODEL_2
264     size_t minShaderModel = 2;
265 #else
266     size_t minShaderModel = 3;
267 #endif
268 
269     if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
270     {
271         return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_VERSION)
272                << "Renderer does not support PS " << minShaderModel << ".0, aborting!";
273     }
274 
275     // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture
276     // to a render target texture is not supported. This is required by
277     // Texture2D::ensureRenderTarget.
278     if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
279     {
280         return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_STRETCHRECT)
281                << "Renderer does not support StretctRect from textures.";
282     }
283 
284     {
285         ANGLE_TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier");
286         mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
287     }
288 
289     static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
290     static const TCHAR className[]  = TEXT("STATIC");
291 
292     {
293         ANGLE_TRACE_EVENT0("gpu.angle", "CreateWindowEx");
294         mDeviceWindow =
295             CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1,
296                            1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr);
297     }
298 
299     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
300     DWORD behaviorFlags =
301         D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
302 
303     {
304         ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
305         result = mD3d9->CreateDevice(
306             mAdapter, mDeviceType, mDeviceWindow,
307             behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
308             &presentParameters, &mDevice);
309 
310         if (FAILED(result))
311         {
312             ERR() << "CreateDevice1 failed: (" << gl::FmtHR(result) << ")";
313         }
314     }
315     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
316     {
317         return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
318                << "CreateDevice failed: device lost or out of memory (" << gl::FmtHR(result) << ")";
319     }
320 
321     if (FAILED(result))
322     {
323         ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2");
324         result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow,
325                                      behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
326                                      &presentParameters, &mDevice);
327 
328         if (FAILED(result))
329         {
330             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
331                    result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
332             return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
333                    << "CreateDevice2 failed: device lost, not available, or of out of memory ("
334                    << gl::FmtHR(result) << ")";
335         }
336     }
337 
338     if (mD3d9Ex)
339     {
340         ANGLE_TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
341         result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx);
342         ASSERT(SUCCEEDED(result));
343     }
344 
345     {
346         ANGLE_TRACE_EVENT0("gpu.angle", "ShaderCache initialize");
347         mVertexShaderCache.initialize(mDevice);
348         mPixelShaderCache.initialize(mDevice);
349     }
350 
351     D3DDISPLAYMODE currentDisplayMode;
352     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
353 
354     // Check vertex texture support
355     // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
356     // We test this using D3D9 by checking support for the R16F format.
357     mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
358                             SUCCEEDED(mD3d9->CheckDeviceFormat(
359                                 mAdapter, mDeviceType, currentDisplayMode.Format,
360                                 D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
361 
362     ANGLE_TRY(initializeDevice());
363 
364     return egl::NoError();
365 }
366 
367 // do any one-time device initialization
368 // NOTE: this is also needed after a device lost/reset
369 // to reset the scene status and ensure the default states are reset.
initializeDevice()370 egl::Error Renderer9::initializeDevice()
371 {
372     // Permanent non-default states
373     mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
374     mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
375 
376     if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
377     {
378         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize);
379     }
380     else
381     {
382         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);  // 1.0f
383     }
384 
385     const gl::Caps &rendererCaps = getNativeCaps();
386 
387     mCurVertexSamplerStates.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
388     mCurPixelSamplerStates.resize(
389         rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
390 
391     mCurVertexTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
392     mCurPixelTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
393 
394     markAllStateDirty();
395 
396     mSceneStarted = false;
397 
398     ASSERT(!mBlit);
399     mBlit = new Blit9(this);
400 
401     ASSERT(!mVertexDataManager && !mIndexDataManager);
402     mIndexDataManager = new IndexDataManager(this);
403 
404     mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
405 
406     mStateManager.initialize();
407 
408     return egl::NoError();
409 }
410 
getDefaultPresentParameters()411 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
412 {
413     D3DPRESENT_PARAMETERS presentParameters = {};
414 
415     // The default swap chain is never actually used. Surface will create a new swap chain with the
416     // proper parameters.
417     presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
418     presentParameters.BackBufferCount        = 1;
419     presentParameters.BackBufferFormat       = D3DFMT_UNKNOWN;
420     presentParameters.BackBufferWidth        = 1;
421     presentParameters.BackBufferHeight       = 1;
422     presentParameters.EnableAutoDepthStencil = FALSE;
423     presentParameters.Flags                  = 0;
424     presentParameters.hDeviceWindow          = mDeviceWindow;
425     presentParameters.MultiSampleQuality     = 0;
426     presentParameters.MultiSampleType        = D3DMULTISAMPLE_NONE;
427     presentParameters.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
428     presentParameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
429     presentParameters.Windowed               = TRUE;
430 
431     return presentParameters;
432 }
433 
generateConfigs()434 egl::ConfigSet Renderer9::generateConfigs()
435 {
436     static const GLenum colorBufferFormats[] = {
437         GL_BGR5_A1_ANGLEX,
438         GL_BGRA8_EXT,
439         GL_RGB565,
440 
441     };
442 
443     static const GLenum depthStencilBufferFormats[] = {
444         GL_NONE,
445         GL_DEPTH_COMPONENT32_OES,
446         GL_DEPTH24_STENCIL8_OES,
447         GL_DEPTH_COMPONENT24_OES,
448         GL_DEPTH_COMPONENT16,
449     };
450 
451     const gl::Caps &rendererCaps                  = getNativeCaps();
452     const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
453 
454     D3DDISPLAYMODE currentDisplayMode;
455     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
456 
457     // Determine the min and max swap intervals
458     int minSwapInterval = 4;
459     int maxSwapInterval = 0;
460 
461     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
462     {
463         minSwapInterval = std::min(minSwapInterval, 0);
464         maxSwapInterval = std::max(maxSwapInterval, 0);
465     }
466     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
467     {
468         minSwapInterval = std::min(minSwapInterval, 1);
469         maxSwapInterval = std::max(maxSwapInterval, 1);
470     }
471     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
472     {
473         minSwapInterval = std::min(minSwapInterval, 2);
474         maxSwapInterval = std::max(maxSwapInterval, 2);
475     }
476     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
477     {
478         minSwapInterval = std::min(minSwapInterval, 3);
479         maxSwapInterval = std::max(maxSwapInterval, 3);
480     }
481     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
482     {
483         minSwapInterval = std::min(minSwapInterval, 4);
484         maxSwapInterval = std::max(maxSwapInterval, 4);
485     }
486 
487     egl::ConfigSet configs;
488     for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
489     {
490         GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
491         const gl::TextureCaps &colorBufferFormatCaps =
492             rendererTextureCaps.get(colorBufferInternalFormat);
493         if (colorBufferFormatCaps.renderbuffer)
494         {
495             ASSERT(colorBufferFormatCaps.textureAttachment);
496             for (size_t depthStencilIndex = 0;
497                  depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
498             {
499                 GLenum depthStencilBufferInternalFormat =
500                     depthStencilBufferFormats[depthStencilIndex];
501                 const gl::TextureCaps &depthStencilBufferFormatCaps =
502                     rendererTextureCaps.get(depthStencilBufferInternalFormat);
503                 if (depthStencilBufferFormatCaps.renderbuffer ||
504                     depthStencilBufferInternalFormat == GL_NONE)
505                 {
506                     ASSERT(depthStencilBufferFormatCaps.textureAttachment ||
507                            depthStencilBufferInternalFormat == GL_NONE);
508                     const gl::InternalFormat &colorBufferFormatInfo =
509                         gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
510                     const gl::InternalFormat &depthStencilBufferFormatInfo =
511                         gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
512                     const d3d9::TextureFormat &d3d9ColorBufferFormatInfo =
513                         d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
514 
515                     egl::Config config;
516                     config.renderTargetFormat = colorBufferInternalFormat;
517                     config.depthStencilFormat = depthStencilBufferInternalFormat;
518                     config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
519                     config.redSize            = colorBufferFormatInfo.redBits;
520                     config.greenSize          = colorBufferFormatInfo.greenBits;
521                     config.blueSize           = colorBufferFormatInfo.blueBits;
522                     config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
523                     config.alphaSize          = colorBufferFormatInfo.alphaBits;
524                     config.alphaMaskSize      = 0;
525                     config.bindToTextureRGB   = (colorBufferFormatInfo.format == GL_RGB);
526                     config.bindToTextureRGBA  = (colorBufferFormatInfo.format == GL_RGBA ||
527                                                 colorBufferFormatInfo.format == GL_BGRA_EXT);
528                     config.colorBufferType    = EGL_RGB_BUFFER;
529                     // Mark as slow if blits to the back-buffer won't be straight forward
530                     config.configCaveat =
531                         (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat)
532                             ? EGL_NONE
533                             : EGL_SLOW_CONFIG;
534                     config.configID          = static_cast<EGLint>(configs.size() + 1);
535                     config.conformant        = EGL_OPENGL_ES2_BIT;
536                     config.depthSize         = depthStencilBufferFormatInfo.depthBits;
537                     config.level             = 0;
538                     config.matchNativePixmap = EGL_NONE;
539                     config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
540                     config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
541                     config.maxPBufferPixels =
542                         rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
543                     config.maxSwapInterval  = maxSwapInterval;
544                     config.minSwapInterval  = minSwapInterval;
545                     config.nativeRenderable = EGL_FALSE;
546                     config.nativeVisualID   = 0;
547                     config.nativeVisualType = EGL_NONE;
548                     config.renderableType   = EGL_OPENGL_ES2_BIT;
549                     config.sampleBuffers    = 0;  // FIXME: enumerate multi-sampling
550                     config.samples          = 0;
551                     config.stencilSize      = depthStencilBufferFormatInfo.stencilBits;
552                     config.surfaceType =
553                         EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
554                     config.transparentType       = EGL_NONE;
555                     config.transparentRedValue   = 0;
556                     config.transparentGreenValue = 0;
557                     config.transparentBlueValue  = 0;
558                     config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
559                         colorBufferFormatInfo.componentType);
560 
561                     configs.add(config);
562                 }
563             }
564         }
565     }
566 
567     ASSERT(configs.size() > 0);
568     return configs;
569 }
570 
generateDisplayExtensions(egl::DisplayExtensions * outExtensions) const571 void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
572 {
573     outExtensions->createContextRobustness = true;
574 
575     if (getShareHandleSupport())
576     {
577         outExtensions->d3dShareHandleClientBuffer     = true;
578         outExtensions->surfaceD3DTexture2DShareHandle = true;
579     }
580     outExtensions->d3dTextureClientBuffer = true;
581 
582     outExtensions->querySurfacePointer = true;
583     outExtensions->windowFixedSize     = true;
584     outExtensions->postSubBuffer       = true;
585     outExtensions->deviceQuery         = true;
586 
587     outExtensions->image               = true;
588     outExtensions->imageBase           = true;
589     outExtensions->glTexture2DImage    = true;
590     outExtensions->glRenderbufferImage = true;
591 
592     outExtensions->flexibleSurfaceCompatibility = true;
593 
594     // Contexts are virtualized so textures can be shared globally
595     outExtensions->displayTextureShareGroup = true;
596 
597     // D3D9 can be used without an output surface
598     outExtensions->surfacelessContext = true;
599 
600     outExtensions->robustResourceInitialization = true;
601 }
602 
startScene()603 void Renderer9::startScene()
604 {
605     if (!mSceneStarted)
606     {
607         long result = mDevice->BeginScene();
608         if (SUCCEEDED(result))
609         {
610             // This is defensive checking against the device being
611             // lost at unexpected times.
612             mSceneStarted = true;
613         }
614     }
615 }
616 
endScene()617 void Renderer9::endScene()
618 {
619     if (mSceneStarted)
620     {
621         // EndScene can fail if the device was lost, for example due
622         // to a TDR during a draw call.
623         mDevice->EndScene();
624         mSceneStarted = false;
625     }
626 }
627 
flush(const gl::Context * context)628 angle::Result Renderer9::flush(const gl::Context *context)
629 {
630     IDirect3DQuery9 *query = nullptr;
631     ANGLE_TRY(allocateEventQuery(context, &query));
632 
633     Context9 *context9 = GetImplAs<Context9>(context);
634 
635     HRESULT result = query->Issue(D3DISSUE_END);
636     ANGLE_TRY_HR(context9, result, "Failed to issue event query");
637 
638     // Grab the query data once
639     result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
640     freeEventQuery(query);
641     ANGLE_TRY_HR(context9, result, "Failed to get event query data");
642 
643     return angle::Result::Continue;
644 }
645 
finish(const gl::Context * context)646 angle::Result Renderer9::finish(const gl::Context *context)
647 {
648     IDirect3DQuery9 *query = nullptr;
649     ANGLE_TRY(allocateEventQuery(context, &query));
650 
651     Context9 *context9 = GetImplAs<Context9>(context);
652 
653     HRESULT result = query->Issue(D3DISSUE_END);
654     ANGLE_TRY_HR(context9, result, "Failed to issue event query");
655 
656     // Grab the query data once
657     result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
658     if (FAILED(result))
659     {
660         freeEventQuery(query);
661     }
662     ANGLE_TRY_HR(context9, result, "Failed to get event query data");
663 
664     // Loop until the query completes
665     unsigned int attempt = 0;
666     while (result == S_FALSE)
667     {
668         // Keep polling, but allow other threads to do something useful first
669         ScheduleYield();
670 
671         result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
672         attempt++;
673 
674         if (result == S_FALSE)
675         {
676             // explicitly check for device loss
677             // some drivers seem to return S_FALSE even if the device is lost
678             // instead of D3DERR_DEVICELOST like they should
679             bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0;
680             if (checkDeviceLost && testDeviceLost())
681             {
682                 result = D3DERR_DEVICELOST;
683             }
684         }
685 
686         if (FAILED(result))
687         {
688             freeEventQuery(query);
689         }
690         ANGLE_TRY_HR(context9, result, "Failed to get event query data");
691     }
692 
693     freeEventQuery(query);
694 
695     return angle::Result::Continue;
696 }
697 
isValidNativeWindow(EGLNativeWindowType window) const698 bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const
699 {
700     return NativeWindow9::IsValidNativeWindow(window);
701 }
702 
createNativeWindow(EGLNativeWindowType window,const egl::Config *,const egl::AttributeMap &) const703 NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
704                                                const egl::Config *,
705                                                const egl::AttributeMap &) const
706 {
707     return new NativeWindow9(window);
708 }
709 
createSwapChain(NativeWindowD3D * nativeWindow,HANDLE shareHandle,IUnknown * d3dTexture,GLenum backBufferFormat,GLenum depthBufferFormat,EGLint orientation,EGLint samples)710 SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
711                                          HANDLE shareHandle,
712                                          IUnknown *d3dTexture,
713                                          GLenum backBufferFormat,
714                                          GLenum depthBufferFormat,
715                                          EGLint orientation,
716                                          EGLint samples)
717 {
718     return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
719                           backBufferFormat, depthBufferFormat, orientation);
720 }
721 
getD3DTextureInfo(const egl::Config * configuration,IUnknown * d3dTexture,const egl::AttributeMap & attribs,EGLint * width,EGLint * height,GLsizei * samples,gl::Format * glFormat,const angle::Format ** angleFormat) const722 egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
723                                         IUnknown *d3dTexture,
724                                         const egl::AttributeMap &attribs,
725                                         EGLint *width,
726                                         EGLint *height,
727                                         GLsizei *samples,
728                                         gl::Format *glFormat,
729                                         const angle::Format **angleFormat) const
730 {
731     IDirect3DTexture9 *texture = nullptr;
732     if (FAILED(d3dTexture->QueryInterface(&texture)))
733     {
734         return egl::EglBadParameter() << "Client buffer is not a IDirect3DTexture9";
735     }
736 
737     IDirect3DDevice9 *textureDevice = nullptr;
738     texture->GetDevice(&textureDevice);
739     if (textureDevice != mDevice)
740     {
741         SafeRelease(texture);
742         return egl::EglBadParameter() << "Texture's device does not match.";
743     }
744     SafeRelease(textureDevice);
745 
746     D3DSURFACE_DESC desc;
747     texture->GetLevelDesc(0, &desc);
748     SafeRelease(texture);
749 
750     if (width)
751     {
752         *width = static_cast<EGLint>(desc.Width);
753     }
754     if (height)
755     {
756         *height = static_cast<EGLint>(desc.Height);
757     }
758 
759     // GetSamplesCount() returns 0 when multisampling isn't used.
760     GLsizei sampleCount = d3d9_gl::GetSamplesCount(desc.MultiSampleType);
761     if ((configuration && configuration->samples > 1) || sampleCount != 0)
762     {
763         return egl::EglBadParameter() << "Multisampling not supported for client buffer texture";
764     }
765     if (samples)
766     {
767         *samples = static_cast<EGLint>(sampleCount);
768     }
769 
770     // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
771     switch (desc.Format)
772     {
773         case D3DFMT_R8G8B8:
774         case D3DFMT_A8R8G8B8:
775         case D3DFMT_A16B16G16R16F:
776         case D3DFMT_A32B32G32R32F:
777             break;
778 
779         default:
780             return egl::EglBadParameter()
781                    << "Unknown client buffer texture format: " << desc.Format;
782     }
783 
784     const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
785     ASSERT(d3dFormatInfo.info().id != angle::FormatID::NONE);
786 
787     if (glFormat)
788     {
789         *glFormat = gl::Format(d3dFormatInfo.info().glInternalFormat);
790     }
791 
792     if (angleFormat)
793     {
794 
795         *angleFormat = &d3dFormatInfo.info();
796     }
797 
798     return egl::NoError();
799 }
800 
validateShareHandle(const egl::Config * config,HANDLE shareHandle,const egl::AttributeMap & attribs) const801 egl::Error Renderer9::validateShareHandle(const egl::Config *config,
802                                           HANDLE shareHandle,
803                                           const egl::AttributeMap &attribs) const
804 {
805     if (shareHandle == nullptr)
806     {
807         return egl::EglBadParameter() << "NULL share handle.";
808     }
809 
810     EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
811     EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
812     ASSERT(width != 0 && height != 0);
813 
814     const d3d9::TextureFormat &backBufferd3dFormatInfo =
815         d3d9::GetTextureFormatInfo(config->renderTargetFormat);
816 
817     IDirect3DTexture9 *texture = nullptr;
818     HRESULT result             = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
819                                             backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
820                                             &texture, &shareHandle);
821     if (FAILED(result))
822     {
823         return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
824     }
825 
826     DWORD levelCount = texture->GetLevelCount();
827 
828     D3DSURFACE_DESC desc;
829     texture->GetLevelDesc(0, &desc);
830     SafeRelease(texture);
831 
832     if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
833         desc.Height != static_cast<UINT>(height) ||
834         desc.Format != backBufferd3dFormatInfo.texFormat)
835     {
836         return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
837     }
838 
839     return egl::NoError();
840 }
841 
createContext(const gl::State & state,gl::ErrorSet * errorSet)842 ContextImpl *Renderer9::createContext(const gl::State &state, gl::ErrorSet *errorSet)
843 {
844     return new Context9(state, errorSet, this);
845 }
846 
getD3DDevice()847 void *Renderer9::getD3DDevice()
848 {
849     return mDevice;
850 }
851 
allocateEventQuery(const gl::Context * context,IDirect3DQuery9 ** outQuery)852 angle::Result Renderer9::allocateEventQuery(const gl::Context *context, IDirect3DQuery9 **outQuery)
853 {
854     if (mEventQueryPool.empty())
855     {
856         HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
857         ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to allocate event query");
858     }
859     else
860     {
861         *outQuery = mEventQueryPool.back();
862         mEventQueryPool.pop_back();
863     }
864 
865     return angle::Result::Continue;
866 }
867 
freeEventQuery(IDirect3DQuery9 * query)868 void Renderer9::freeEventQuery(IDirect3DQuery9 *query)
869 {
870     if (mEventQueryPool.size() > 1000)
871     {
872         SafeRelease(query);
873     }
874     else
875     {
876         mEventQueryPool.push_back(query);
877     }
878 }
879 
createVertexShader(d3d::Context * context,const DWORD * function,size_t length,IDirect3DVertexShader9 ** outShader)880 angle::Result Renderer9::createVertexShader(d3d::Context *context,
881                                             const DWORD *function,
882                                             size_t length,
883                                             IDirect3DVertexShader9 **outShader)
884 {
885     return mVertexShaderCache.create(context, function, length, outShader);
886 }
887 
createPixelShader(d3d::Context * context,const DWORD * function,size_t length,IDirect3DPixelShader9 ** outShader)888 angle::Result Renderer9::createPixelShader(d3d::Context *context,
889                                            const DWORD *function,
890                                            size_t length,
891                                            IDirect3DPixelShader9 **outShader)
892 {
893     return mPixelShaderCache.create(context, function, length, outShader);
894 }
895 
createVertexBuffer(UINT Length,DWORD Usage,IDirect3DVertexBuffer9 ** ppVertexBuffer)896 HRESULT Renderer9::createVertexBuffer(UINT Length,
897                                       DWORD Usage,
898                                       IDirect3DVertexBuffer9 **ppVertexBuffer)
899 {
900     // Force buffers to be limited to a fixed max size.
901     if (Length > kMaximumBufferSizeHardLimit)
902     {
903         return E_OUTOFMEMORY;
904     }
905 
906     D3DPOOL Pool = getBufferPool(Usage);
907     return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
908 }
909 
createVertexBuffer()910 VertexBuffer *Renderer9::createVertexBuffer()
911 {
912     return new VertexBuffer9(this);
913 }
914 
createIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,IDirect3DIndexBuffer9 ** ppIndexBuffer)915 HRESULT Renderer9::createIndexBuffer(UINT Length,
916                                      DWORD Usage,
917                                      D3DFORMAT Format,
918                                      IDirect3DIndexBuffer9 **ppIndexBuffer)
919 {
920     // Force buffers to be limited to a fixed max size.
921     if (Length > kMaximumBufferSizeHardLimit)
922     {
923         return E_OUTOFMEMORY;
924     }
925 
926     D3DPOOL Pool = getBufferPool(Usage);
927     return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
928 }
929 
createIndexBuffer()930 IndexBuffer *Renderer9::createIndexBuffer()
931 {
932     return new IndexBuffer9(this);
933 }
934 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)935 StreamProducerImpl *Renderer9::createStreamProducerD3DTexture(
936     egl::Stream::ConsumerType consumerType,
937     const egl::AttributeMap &attribs)
938 {
939     // Streams are not supported under D3D9
940     UNREACHABLE();
941     return nullptr;
942 }
943 
supportsFastCopyBufferToTexture(GLenum internalFormat) const944 bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
945 {
946     // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
947     return false;
948 }
949 
fastCopyBufferToTexture(const gl::Context * context,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,unsigned int offset,RenderTargetD3D * destRenderTarget,GLenum destinationFormat,GLenum sourcePixelsType,const gl::Box & destArea)950 angle::Result Renderer9::fastCopyBufferToTexture(const gl::Context *context,
951                                                  const gl::PixelUnpackState &unpack,
952                                                  gl::Buffer *unpackBuffer,
953                                                  unsigned int offset,
954                                                  RenderTargetD3D *destRenderTarget,
955                                                  GLenum destinationFormat,
956                                                  GLenum sourcePixelsType,
957                                                  const gl::Box &destArea)
958 {
959     // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
960     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
961     return angle::Result::Stop;
962 }
963 
setSamplerState(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture,const gl::SamplerState & samplerState)964 angle::Result Renderer9::setSamplerState(const gl::Context *context,
965                                          gl::ShaderType type,
966                                          int index,
967                                          gl::Texture *texture,
968                                          const gl::SamplerState &samplerState)
969 {
970     CurSamplerState &appliedSampler = (type == gl::ShaderType::Fragment)
971                                           ? mCurPixelSamplerStates[index]
972                                           : mCurVertexSamplerStates[index];
973 
974     // Make sure to add the level offset for our tiny compressed texture workaround
975     TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
976 
977     TextureStorage *storage = nullptr;
978     ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
979 
980     // Storage should exist, texture should be complete
981     ASSERT(storage);
982 
983     DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel();
984 
985     if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel ||
986         memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0)
987     {
988         int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
989         int d3dSampler       = index + d3dSamplerOffset;
990 
991         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU,
992                                  gl_d3d9::ConvertTextureWrap(samplerState.getWrapS()));
993         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV,
994                                  gl_d3d9::ConvertTextureWrap(samplerState.getWrapT()));
995 
996         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER,
997                                  gl_d3d9::ConvertMagFilter(samplerState.getMagFilter(),
998                                                            samplerState.getMaxAnisotropy()));
999 
1000         D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1001         float lodBias;
1002         gl_d3d9::ConvertMinFilter(samplerState.getMinFilter(), &d3dMinFilter, &d3dMipFilter,
1003                                   &lodBias, samplerState.getMaxAnisotropy(), baseLevel);
1004         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
1005         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
1006         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
1007         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias));
1008         if (getNativeExtensions().textureFilterAnisotropic)
1009         {
1010             DWORD maxAnisotropy = std::min(mDeviceCaps.MaxAnisotropy,
1011                                            static_cast<DWORD>(samplerState.getMaxAnisotropy()));
1012             mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
1013         }
1014 
1015         ASSERT(texture->getBorderColor().type == angle::ColorGeneric::Type::Float);
1016         mDevice->SetSamplerState(d3dSampler, D3DSAMP_BORDERCOLOR,
1017                                  gl_d3d9::ConvertColor(texture->getBorderColor().colorF));
1018     }
1019 
1020     appliedSampler.forceSet     = false;
1021     appliedSampler.samplerState = samplerState;
1022     appliedSampler.baseLevel    = baseLevel;
1023 
1024     return angle::Result::Continue;
1025 }
1026 
setTexture(const gl::Context * context,gl::ShaderType type,int index,gl::Texture * texture)1027 angle::Result Renderer9::setTexture(const gl::Context *context,
1028                                     gl::ShaderType type,
1029                                     int index,
1030                                     gl::Texture *texture)
1031 {
1032     int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
1033     int d3dSampler       = index + d3dSamplerOffset;
1034     IDirect3DBaseTexture9 *d3dTexture = nullptr;
1035     bool forceSetTexture              = false;
1036 
1037     std::vector<uintptr_t> &appliedTextures =
1038         (type == gl::ShaderType::Fragment) ? mCurPixelTextures : mCurVertexTextures;
1039 
1040     if (texture)
1041     {
1042         TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
1043 
1044         TextureStorage *texStorage = nullptr;
1045         ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
1046 
1047         // Texture should be complete and have a storage
1048         ASSERT(texStorage);
1049 
1050         TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
1051         ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture));
1052 
1053         // If we get NULL back from getBaseTexture here, something went wrong
1054         // in the texture class and we're unexpectedly missing the d3d texture
1055         ASSERT(d3dTexture != nullptr);
1056 
1057         forceSetTexture = textureImpl->hasDirtyImages();
1058         textureImpl->resetDirty();
1059     }
1060 
1061     if (forceSetTexture || appliedTextures[index] != reinterpret_cast<uintptr_t>(d3dTexture))
1062     {
1063         mDevice->SetTexture(d3dSampler, d3dTexture);
1064     }
1065 
1066     appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture);
1067 
1068     return angle::Result::Continue;
1069 }
1070 
updateState(const gl::Context * context,gl::PrimitiveMode drawMode)1071 angle::Result Renderer9::updateState(const gl::Context *context, gl::PrimitiveMode drawMode)
1072 {
1073     const auto &glState = context->getState();
1074 
1075     // Applies the render target surface, depth stencil surface, viewport rectangle and
1076     // scissor rectangle to the renderer
1077     gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
1078     ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit());
1079 
1080     Framebuffer9 *framebuffer9 = GetImplAs<Framebuffer9>(framebuffer);
1081 
1082     ANGLE_TRY(applyRenderTarget(context, framebuffer9->getCachedColorRenderTargets()[0],
1083                                 framebuffer9->getCachedDepthStencilRenderTarget()));
1084 
1085     // Setting viewport state
1086     setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
1087                 glState.getRasterizerState().frontFace, false);
1088 
1089     // Setting scissors state
1090     setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
1091 
1092     // Setting blend, depth stencil, and rasterizer states
1093     // Since framebuffer->getSamples will return the original samples which may be different with
1094     // the sample counts that we set in render target view, here we use renderTarget->getSamples to
1095     // get the actual samples.
1096     GLsizei samples                                       = 0;
1097     const gl::FramebufferAttachment *firstColorAttachment = framebuffer->getFirstColorAttachment();
1098     if (firstColorAttachment)
1099     {
1100         ASSERT(firstColorAttachment->isAttached());
1101         RenderTarget9 *renderTarget = nullptr;
1102         ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
1103                                                         &renderTarget));
1104         samples = renderTarget->getSamples();
1105     }
1106     gl::RasterizerState rasterizer = glState.getRasterizerState();
1107     rasterizer.pointDrawMode       = (drawMode == gl::PrimitiveMode::Points);
1108     rasterizer.multiSample         = (samples != 0);
1109 
1110     ANGLE_TRY(setBlendDepthRasterStates(context, drawMode));
1111 
1112     mStateManager.resetDirtyBits();
1113 
1114     return angle::Result::Continue;
1115 }
1116 
setScissorRectangle(const gl::Rectangle & scissor,bool enabled)1117 void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
1118 {
1119     mStateManager.setScissorState(scissor, enabled);
1120 }
1121 
setBlendDepthRasterStates(const gl::Context * context,gl::PrimitiveMode drawMode)1122 angle::Result Renderer9::setBlendDepthRasterStates(const gl::Context *context,
1123                                                    gl::PrimitiveMode drawMode)
1124 {
1125     const auto &glState              = context->getState();
1126     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1127     ASSERT(!drawFramebuffer->hasAnyDirtyBit());
1128     // Since framebuffer->getSamples will return the original samples which may be different with
1129     // the sample counts that we set in render target view, here we use renderTarget->getSamples to
1130     // get the actual samples.
1131     GLsizei samples = 0;
1132     const gl::FramebufferAttachment *firstColorAttachment =
1133         drawFramebuffer->getFirstColorAttachment();
1134     if (firstColorAttachment)
1135     {
1136         ASSERT(firstColorAttachment->isAttached());
1137         RenderTarget9 *renderTarget = nullptr;
1138         ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
1139                                                         &renderTarget));
1140         samples = renderTarget->getSamples();
1141     }
1142     gl::RasterizerState rasterizer = glState.getRasterizerState();
1143     rasterizer.pointDrawMode       = (drawMode == gl::PrimitiveMode::Points);
1144     rasterizer.multiSample         = (samples != 0);
1145 
1146     unsigned int mask = GetBlendSampleMask(glState, samples);
1147     mStateManager.setBlendDepthRasterStates(glState, mask);
1148     return angle::Result::Continue;
1149 }
1150 
setViewport(const gl::Rectangle & viewport,float zNear,float zFar,gl::PrimitiveMode drawMode,GLenum frontFace,bool ignoreViewport)1151 void Renderer9::setViewport(const gl::Rectangle &viewport,
1152                             float zNear,
1153                             float zFar,
1154                             gl::PrimitiveMode drawMode,
1155                             GLenum frontFace,
1156                             bool ignoreViewport)
1157 {
1158     mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
1159 }
1160 
applyPrimitiveType(gl::PrimitiveMode mode,GLsizei count,bool usesPointSize)1161 bool Renderer9::applyPrimitiveType(gl::PrimitiveMode mode, GLsizei count, bool usesPointSize)
1162 {
1163     switch (mode)
1164     {
1165         case gl::PrimitiveMode::Points:
1166             mPrimitiveType  = D3DPT_POINTLIST;
1167             mPrimitiveCount = count;
1168             break;
1169         case gl::PrimitiveMode::Lines:
1170             mPrimitiveType  = D3DPT_LINELIST;
1171             mPrimitiveCount = count / 2;
1172             break;
1173         case gl::PrimitiveMode::LineLoop:
1174             mPrimitiveType = D3DPT_LINESTRIP;
1175             mPrimitiveCount =
1176                 count - 1;  // D3D doesn't support line loops, so we draw the last line separately
1177             break;
1178         case gl::PrimitiveMode::LineStrip:
1179             mPrimitiveType  = D3DPT_LINESTRIP;
1180             mPrimitiveCount = count - 1;
1181             break;
1182         case gl::PrimitiveMode::Triangles:
1183             mPrimitiveType  = D3DPT_TRIANGLELIST;
1184             mPrimitiveCount = count / 3;
1185             break;
1186         case gl::PrimitiveMode::TriangleStrip:
1187             mPrimitiveType  = D3DPT_TRIANGLESTRIP;
1188             mPrimitiveCount = count - 2;
1189             break;
1190         case gl::PrimitiveMode::TriangleFan:
1191             mPrimitiveType  = D3DPT_TRIANGLEFAN;
1192             mPrimitiveCount = count - 2;
1193             break;
1194         default:
1195             UNREACHABLE();
1196             return false;
1197     }
1198 
1199     return mPrimitiveCount > 0;
1200 }
1201 
getNullColorRenderTarget(const gl::Context * context,const RenderTarget9 * depthRenderTarget,const RenderTarget9 ** outColorRenderTarget)1202 angle::Result Renderer9::getNullColorRenderTarget(const gl::Context *context,
1203                                                   const RenderTarget9 *depthRenderTarget,
1204                                                   const RenderTarget9 **outColorRenderTarget)
1205 {
1206     ASSERT(depthRenderTarget);
1207 
1208     const gl::Extents &size = depthRenderTarget->getExtents();
1209 
1210     // search cached nullcolorbuffers
1211     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
1212     {
1213         if (mNullRenderTargetCache[i].renderTarget != nullptr &&
1214             mNullRenderTargetCache[i].width == size.width &&
1215             mNullRenderTargetCache[i].height == size.height)
1216         {
1217             mNullRenderTargetCache[i].lruCount = ++mMaxNullColorbufferLRU;
1218             *outColorRenderTarget              = mNullRenderTargetCache[i].renderTarget;
1219             return angle::Result::Continue;
1220         }
1221     }
1222 
1223     RenderTargetD3D *nullRenderTarget = nullptr;
1224     ANGLE_TRY(createRenderTarget(context, size.width, size.height, GL_NONE, 0, &nullRenderTarget));
1225 
1226     // add nullbuffer to the cache
1227     NullRenderTargetCacheEntry *oldest = &mNullRenderTargetCache[0];
1228     for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
1229     {
1230         if (mNullRenderTargetCache[i].lruCount < oldest->lruCount)
1231         {
1232             oldest = &mNullRenderTargetCache[i];
1233         }
1234     }
1235 
1236     SafeDelete(oldest->renderTarget);
1237     oldest->renderTarget = GetAs<RenderTarget9>(nullRenderTarget);
1238     oldest->lruCount     = ++mMaxNullColorbufferLRU;
1239     oldest->width        = size.width;
1240     oldest->height       = size.height;
1241 
1242     *outColorRenderTarget = oldest->renderTarget;
1243     return angle::Result::Continue;
1244 }
1245 
applyRenderTarget(const gl::Context * context,const RenderTarget9 * colorRenderTargetIn,const RenderTarget9 * depthStencilRenderTarget)1246 angle::Result Renderer9::applyRenderTarget(const gl::Context *context,
1247                                            const RenderTarget9 *colorRenderTargetIn,
1248                                            const RenderTarget9 *depthStencilRenderTarget)
1249 {
1250     // if there is no color attachment we must synthesize a NULL colorattachment
1251     // to keep the D3D runtime happy.  This should only be possible if depth texturing.
1252     const RenderTarget9 *colorRenderTarget = colorRenderTargetIn;
1253     if (colorRenderTarget == nullptr)
1254     {
1255         ANGLE_TRY(getNullColorRenderTarget(context, depthStencilRenderTarget, &colorRenderTarget));
1256     }
1257     ASSERT(colorRenderTarget != nullptr);
1258 
1259     size_t renderTargetWidth     = 0;
1260     size_t renderTargetHeight    = 0;
1261     D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
1262 
1263     bool renderTargetChanged        = false;
1264     unsigned int renderTargetSerial = colorRenderTarget->getSerial();
1265     if (renderTargetSerial != mAppliedRenderTargetSerial)
1266     {
1267         // Apply the render target on the device
1268         IDirect3DSurface9 *renderTargetSurface = colorRenderTarget->getSurface();
1269         ASSERT(renderTargetSurface);
1270 
1271         mDevice->SetRenderTarget(0, renderTargetSurface);
1272         SafeRelease(renderTargetSurface);
1273 
1274         renderTargetWidth  = colorRenderTarget->getWidth();
1275         renderTargetHeight = colorRenderTarget->getHeight();
1276         renderTargetFormat = colorRenderTarget->getD3DFormat();
1277 
1278         mAppliedRenderTargetSerial = renderTargetSerial;
1279         renderTargetChanged        = true;
1280     }
1281 
1282     unsigned int depthStencilSerial = 0;
1283     if (depthStencilRenderTarget != nullptr)
1284     {
1285         depthStencilSerial = depthStencilRenderTarget->getSerial();
1286     }
1287 
1288     if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
1289     {
1290         unsigned int depthSize   = 0;
1291         unsigned int stencilSize = 0;
1292 
1293         // Apply the depth stencil on the device
1294         if (depthStencilRenderTarget)
1295         {
1296             IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface();
1297             ASSERT(depthStencilSurface);
1298 
1299             mDevice->SetDepthStencilSurface(depthStencilSurface);
1300             SafeRelease(depthStencilSurface);
1301 
1302             const gl::InternalFormat &format =
1303                 gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
1304 
1305             depthSize   = format.depthBits;
1306             stencilSize = format.stencilBits;
1307         }
1308         else
1309         {
1310             mDevice->SetDepthStencilSurface(nullptr);
1311         }
1312 
1313         mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
1314         mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
1315 
1316         mAppliedDepthStencilSerial = depthStencilSerial;
1317         mDepthStencilInitialized   = true;
1318     }
1319 
1320     if (renderTargetChanged || !mRenderTargetDescInitialized)
1321     {
1322         mStateManager.forceSetBlendState();
1323         mStateManager.forceSetScissorState();
1324         mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight);
1325         mRenderTargetDescInitialized = true;
1326     }
1327 
1328     return angle::Result::Continue;
1329 }
1330 
applyVertexBuffer(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances,TranslatedIndexData *)1331 angle::Result Renderer9::applyVertexBuffer(const gl::Context *context,
1332                                            gl::PrimitiveMode mode,
1333                                            GLint first,
1334                                            GLsizei count,
1335                                            GLsizei instances,
1336                                            TranslatedIndexData * /*indexInfo*/)
1337 {
1338     const gl::State &state = context->getState();
1339     ANGLE_TRY(mVertexDataManager->prepareVertexData(context, first, count, &mTranslatedAttribCache,
1340                                                     instances));
1341 
1342     return mVertexDeclarationCache.applyDeclaration(context, mDevice, mTranslatedAttribCache,
1343                                                     state.getProgram(), first, instances,
1344                                                     &mRepeatDraw);
1345 }
1346 
1347 // Applies the indices and element array bindings to the Direct3D 9 device
applyIndexBuffer(const gl::Context * context,const void * indices,GLsizei count,gl::PrimitiveMode mode,gl::DrawElementsType type,TranslatedIndexData * indexInfo)1348 angle::Result Renderer9::applyIndexBuffer(const gl::Context *context,
1349                                           const void *indices,
1350                                           GLsizei count,
1351                                           gl::PrimitiveMode mode,
1352                                           gl::DrawElementsType type,
1353                                           TranslatedIndexData *indexInfo)
1354 {
1355     gl::VertexArray *vao           = context->getState().getVertexArray();
1356     gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1357 
1358     gl::DrawElementsType dstType = gl::DrawElementsType::InvalidEnum;
1359     ANGLE_TRY(GetIndexTranslationDestType(context, count, type, indices, false, &dstType));
1360 
1361     ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer,
1362                                                   indices, indexInfo));
1363 
1364     // Directly binding the storage buffer is not supported for d3d9
1365     ASSERT(indexInfo->storage == nullptr);
1366 
1367     if (indexInfo->serial != mAppliedIBSerial)
1368     {
1369         IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
1370 
1371         mDevice->SetIndices(indexBuffer->getBuffer());
1372         mAppliedIBSerial = indexInfo->serial;
1373     }
1374 
1375     return angle::Result::Continue;
1376 }
1377 
drawArraysImpl(const gl::Context * context,gl::PrimitiveMode mode,GLint startVertex,GLsizei count,GLsizei instances)1378 angle::Result Renderer9::drawArraysImpl(const gl::Context *context,
1379                                         gl::PrimitiveMode mode,
1380                                         GLint startVertex,
1381                                         GLsizei count,
1382                                         GLsizei instances)
1383 {
1384     ASSERT(!context->getState().isTransformFeedbackActiveUnpaused());
1385 
1386     startScene();
1387 
1388     if (mode == gl::PrimitiveMode::LineLoop)
1389     {
1390         return drawLineLoop(context, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr);
1391     }
1392 
1393     if (instances > 0)
1394     {
1395         StaticIndexBufferInterface *countingIB = nullptr;
1396         ANGLE_TRY(getCountingIB(context, count, &countingIB));
1397 
1398         if (mAppliedIBSerial != countingIB->getSerial())
1399         {
1400             IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(countingIB->getIndexBuffer());
1401 
1402             mDevice->SetIndices(indexBuffer->getBuffer());
1403             mAppliedIBSerial = countingIB->getSerial();
1404         }
1405 
1406         for (int i = 0; i < mRepeatDraw; i++)
1407         {
1408             mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
1409         }
1410 
1411         return angle::Result::Continue;
1412     }
1413 
1414     // Regular case
1415     mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
1416     return angle::Result::Continue;
1417 }
1418 
drawElementsImpl(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)1419 angle::Result Renderer9::drawElementsImpl(const gl::Context *context,
1420                                           gl::PrimitiveMode mode,
1421                                           GLsizei count,
1422                                           gl::DrawElementsType type,
1423                                           const void *indices,
1424                                           GLsizei instances)
1425 {
1426     TranslatedIndexData indexInfo;
1427 
1428     ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo));
1429 
1430     gl::IndexRange indexRange;
1431     ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices,
1432                                                                   &indexRange));
1433 
1434     size_t vertexCount = indexRange.vertexCount();
1435     ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start),
1436                                 static_cast<GLsizei>(vertexCount), instances, &indexInfo));
1437 
1438     startScene();
1439 
1440     int minIndex = static_cast<int>(indexRange.start);
1441 
1442     gl::VertexArray *vao           = context->getState().getVertexArray();
1443     gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1444 
1445     if (mode == gl::PrimitiveMode::Points)
1446     {
1447         return drawIndexedPoints(context, count, type, indices, minIndex, elementArrayBuffer);
1448     }
1449 
1450     if (mode == gl::PrimitiveMode::LineLoop)
1451     {
1452         return drawLineLoop(context, count, type, indices, minIndex, elementArrayBuffer);
1453     }
1454 
1455     for (int i = 0; i < mRepeatDraw; i++)
1456     {
1457         mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
1458                                       static_cast<UINT>(vertexCount), indexInfo.startIndex,
1459                                       mPrimitiveCount);
1460     }
1461     return angle::Result::Continue;
1462 }
1463 
drawLineLoop(const gl::Context * context,GLsizei count,gl::DrawElementsType type,const void * indices,int minIndex,gl::Buffer * elementArrayBuffer)1464 angle::Result Renderer9::drawLineLoop(const gl::Context *context,
1465                                       GLsizei count,
1466                                       gl::DrawElementsType type,
1467                                       const void *indices,
1468                                       int minIndex,
1469                                       gl::Buffer *elementArrayBuffer)
1470 {
1471     // Get the raw indices for an indexed draw
1472     if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
1473     {
1474         BufferD3D *storage        = GetImplAs<BufferD3D>(elementArrayBuffer);
1475         intptr_t offset           = reinterpret_cast<intptr_t>(indices);
1476         const uint8_t *bufferData = nullptr;
1477         ANGLE_TRY(storage->getData(context, &bufferData));
1478         indices = bufferData + offset;
1479     }
1480 
1481     unsigned int startIndex = 0;
1482     Context9 *context9      = GetImplAs<Context9>(context);
1483 
1484     if (getNativeExtensions().elementIndexUintOES)
1485     {
1486         if (!mLineLoopIB)
1487         {
1488             mLineLoopIB = new StreamingIndexBufferInterface(this);
1489             ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
1490                                                       gl::DrawElementsType::UnsignedInt));
1491         }
1492 
1493         // Checked by Renderer9::applyPrimitiveType
1494         ASSERT(count >= 0);
1495 
1496         ANGLE_CHECK(context9,
1497                     static_cast<unsigned int>(count) + 1 <=
1498                         (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)),
1499                     "Failed to create a 32-bit looping index buffer for "
1500                     "GL_LINE_LOOP, too many indices required.",
1501                     GL_OUT_OF_MEMORY);
1502 
1503         const unsigned int spaceNeeded =
1504             (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
1505         ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
1506                                                   gl::DrawElementsType::UnsignedInt));
1507 
1508         void *mappedMemory  = nullptr;
1509         unsigned int offset = 0;
1510         ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
1511 
1512         startIndex         = static_cast<unsigned int>(offset) / 4;
1513         unsigned int *data = static_cast<unsigned int *>(mappedMemory);
1514 
1515         switch (type)
1516         {
1517             case gl::DrawElementsType::InvalidEnum:  // Non-indexed draw
1518                 for (int i = 0; i < count; i++)
1519                 {
1520                     data[i] = i;
1521                 }
1522                 data[count] = 0;
1523                 break;
1524             case gl::DrawElementsType::UnsignedByte:
1525                 for (int i = 0; i < count; i++)
1526                 {
1527                     data[i] = static_cast<const GLubyte *>(indices)[i];
1528                 }
1529                 data[count] = static_cast<const GLubyte *>(indices)[0];
1530                 break;
1531             case gl::DrawElementsType::UnsignedShort:
1532                 for (int i = 0; i < count; i++)
1533                 {
1534                     data[i] = static_cast<const GLushort *>(indices)[i];
1535                 }
1536                 data[count] = static_cast<const GLushort *>(indices)[0];
1537                 break;
1538             case gl::DrawElementsType::UnsignedInt:
1539                 for (int i = 0; i < count; i++)
1540                 {
1541                     data[i] = static_cast<const GLuint *>(indices)[i];
1542                 }
1543                 data[count] = static_cast<const GLuint *>(indices)[0];
1544                 break;
1545             default:
1546                 UNREACHABLE();
1547         }
1548 
1549         ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
1550     }
1551     else
1552     {
1553         if (!mLineLoopIB)
1554         {
1555             mLineLoopIB = new StreamingIndexBufferInterface(this);
1556             ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
1557                                                       gl::DrawElementsType::UnsignedShort));
1558         }
1559 
1560         // Checked by Renderer9::applyPrimitiveType
1561         ASSERT(count >= 0);
1562 
1563         ANGLE_CHECK(context9,
1564                     static_cast<unsigned int>(count) + 1 <=
1565                         (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)),
1566                     "Failed to create a 16-bit looping index buffer for "
1567                     "GL_LINE_LOOP, too many indices required.",
1568                     GL_OUT_OF_MEMORY);
1569 
1570         const unsigned int spaceNeeded =
1571             (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
1572         ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
1573                                                   gl::DrawElementsType::UnsignedShort));
1574 
1575         void *mappedMemory = nullptr;
1576         unsigned int offset;
1577         ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
1578 
1579         startIndex           = static_cast<unsigned int>(offset) / 2;
1580         unsigned short *data = static_cast<unsigned short *>(mappedMemory);
1581 
1582         switch (type)
1583         {
1584             case gl::DrawElementsType::InvalidEnum:  // Non-indexed draw
1585                 for (int i = 0; i < count; i++)
1586                 {
1587                     data[i] = static_cast<unsigned short>(i);
1588                 }
1589                 data[count] = 0;
1590                 break;
1591             case gl::DrawElementsType::UnsignedByte:
1592                 for (int i = 0; i < count; i++)
1593                 {
1594                     data[i] = static_cast<const GLubyte *>(indices)[i];
1595                 }
1596                 data[count] = static_cast<const GLubyte *>(indices)[0];
1597                 break;
1598             case gl::DrawElementsType::UnsignedShort:
1599                 for (int i = 0; i < count; i++)
1600                 {
1601                     data[i] = static_cast<const GLushort *>(indices)[i];
1602                 }
1603                 data[count] = static_cast<const GLushort *>(indices)[0];
1604                 break;
1605             case gl::DrawElementsType::UnsignedInt:
1606                 for (int i = 0; i < count; i++)
1607                 {
1608                     data[i] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[i]);
1609                 }
1610                 data[count] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[0]);
1611                 break;
1612             default:
1613                 UNREACHABLE();
1614         }
1615 
1616         ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
1617     }
1618 
1619     if (mAppliedIBSerial != mLineLoopIB->getSerial())
1620     {
1621         IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(mLineLoopIB->getIndexBuffer());
1622 
1623         mDevice->SetIndices(indexBuffer->getBuffer());
1624         mAppliedIBSerial = mLineLoopIB->getSerial();
1625     }
1626 
1627     mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
1628 
1629     return angle::Result::Continue;
1630 }
1631 
drawIndexedPoints(const gl::Context * context,GLsizei count,gl::DrawElementsType type,const void * indices,int minIndex,gl::Buffer * elementArrayBuffer)1632 angle::Result Renderer9::drawIndexedPoints(const gl::Context *context,
1633                                            GLsizei count,
1634                                            gl::DrawElementsType type,
1635                                            const void *indices,
1636                                            int minIndex,
1637                                            gl::Buffer *elementArrayBuffer)
1638 {
1639     // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
1640     // for each individual point. This call is not expected to happen often.
1641 
1642     if (elementArrayBuffer)
1643     {
1644         BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
1645         intptr_t offset    = reinterpret_cast<intptr_t>(indices);
1646 
1647         const uint8_t *bufferData = nullptr;
1648         ANGLE_TRY(storage->getData(context, &bufferData));
1649         indices = bufferData + offset;
1650     }
1651 
1652     switch (type)
1653     {
1654         case gl::DrawElementsType::UnsignedByte:
1655             DrawPoints<GLubyte>(mDevice, count, indices, minIndex);
1656             return angle::Result::Continue;
1657         case gl::DrawElementsType::UnsignedShort:
1658             DrawPoints<GLushort>(mDevice, count, indices, minIndex);
1659             return angle::Result::Continue;
1660         case gl::DrawElementsType::UnsignedInt:
1661             DrawPoints<GLuint>(mDevice, count, indices, minIndex);
1662             return angle::Result::Continue;
1663         default:
1664             ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
1665     }
1666 }
1667 
getCountingIB(const gl::Context * context,size_t count,StaticIndexBufferInterface ** outIB)1668 angle::Result Renderer9::getCountingIB(const gl::Context *context,
1669                                        size_t count,
1670                                        StaticIndexBufferInterface **outIB)
1671 {
1672     // Update the counting index buffer if it is not large enough or has not been created yet.
1673     if (count <= 65536)  // 16-bit indices
1674     {
1675         const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short);
1676 
1677         if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
1678         {
1679             SafeDelete(mCountingIB);
1680             mCountingIB = new StaticIndexBufferInterface(this);
1681             ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
1682                                                       gl::DrawElementsType::UnsignedShort));
1683 
1684             void *mappedMemory = nullptr;
1685             ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
1686 
1687             unsigned short *data = static_cast<unsigned short *>(mappedMemory);
1688             for (size_t i = 0; i < count; i++)
1689             {
1690                 data[i] = static_cast<unsigned short>(i);
1691             }
1692 
1693             ANGLE_TRY(mCountingIB->unmapBuffer(context));
1694         }
1695     }
1696     else if (getNativeExtensions().elementIndexUintOES)
1697     {
1698         const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
1699 
1700         if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
1701         {
1702             SafeDelete(mCountingIB);
1703             mCountingIB = new StaticIndexBufferInterface(this);
1704             ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
1705                                                       gl::DrawElementsType::UnsignedInt));
1706 
1707             void *mappedMemory = nullptr;
1708             ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
1709 
1710             unsigned int *data = static_cast<unsigned int *>(mappedMemory);
1711             for (unsigned int i = 0; i < count; i++)
1712             {
1713                 data[i] = i;
1714             }
1715 
1716             ANGLE_TRY(mCountingIB->unmapBuffer(context));
1717         }
1718     }
1719     else
1720     {
1721         ANGLE_TRY_HR(GetImplAs<Context9>(context), E_OUTOFMEMORY,
1722                      "Could not create a counting index buffer for glDrawArraysInstanced.");
1723     }
1724 
1725     *outIB = mCountingIB;
1726     return angle::Result::Continue;
1727 }
1728 
applyShaders(const gl::Context * context,gl::PrimitiveMode drawMode)1729 angle::Result Renderer9::applyShaders(const gl::Context *context, gl::PrimitiveMode drawMode)
1730 {
1731     const gl::State &state   = context->getState();
1732     d3d::Context *contextD3D = GetImplAs<ContextD3D>(context);
1733 
1734     // This method is called single-threaded.
1735     ANGLE_TRY(ensureHLSLCompilerInitialized(contextD3D));
1736 
1737     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(state.getProgram());
1738     VertexArray9 *vao      = GetImplAs<VertexArray9>(state.getVertexArray());
1739     programD3D->updateCachedInputLayout(vao->getCurrentStateSerial(), state);
1740 
1741     ShaderExecutableD3D *vertexExe = nullptr;
1742     ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(contextD3D, &vertexExe, nullptr));
1743 
1744     const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
1745     programD3D->updateCachedOutputLayout(context, drawFramebuffer);
1746 
1747     ShaderExecutableD3D *pixelExe = nullptr;
1748     ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(contextD3D, &pixelExe, nullptr));
1749 
1750     IDirect3DVertexShader9 *vertexShader =
1751         (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
1752     IDirect3DPixelShader9 *pixelShader =
1753         (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
1754 
1755     if (vertexShader != mAppliedVertexShader)
1756     {
1757         mDevice->SetVertexShader(vertexShader);
1758         mAppliedVertexShader = vertexShader;
1759     }
1760 
1761     if (pixelShader != mAppliedPixelShader)
1762     {
1763         mDevice->SetPixelShader(pixelShader);
1764         mAppliedPixelShader = pixelShader;
1765     }
1766 
1767     // D3D9 has a quirk where creating multiple shaders with the same content
1768     // can return the same shader pointer. Because GL programs store different data
1769     // per-program, checking the program serial guarantees we upload fresh
1770     // uniform data even if our shader pointers are the same.
1771     // https://code.google.com/p/angleproject/issues/detail?id=661
1772     unsigned int programSerial = programD3D->getSerial();
1773     if (programSerial != mAppliedProgramSerial)
1774     {
1775         programD3D->dirtyAllUniforms();
1776         mStateManager.forceSetDXUniformsState();
1777         mAppliedProgramSerial = programSerial;
1778     }
1779 
1780     applyUniforms(programD3D);
1781 
1782     // Driver uniforms
1783     mStateManager.setShaderConstants();
1784 
1785     return angle::Result::Continue;
1786 }
1787 
applyUniforms(ProgramD3D * programD3D)1788 void Renderer9::applyUniforms(ProgramD3D *programD3D)
1789 {
1790     // Skip updates if we're not dirty. Note that D3D9 cannot have compute or geometry.
1791     if (!programD3D->anyShaderUniformsDirty())
1792     {
1793         return;
1794     }
1795 
1796     const auto &uniformArray = programD3D->getD3DUniforms();
1797 
1798     for (const D3DUniform *targetUniform : uniformArray)
1799     {
1800         // Built-in uniforms must be skipped.
1801         if (!targetUniform->isReferencedByShader(gl::ShaderType::Vertex) &&
1802             !targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
1803             continue;
1804 
1805         const GLfloat *f = reinterpret_cast<const GLfloat *>(targetUniform->firstNonNullData());
1806         const GLint *i   = reinterpret_cast<const GLint *>(targetUniform->firstNonNullData());
1807 
1808         switch (targetUniform->typeInfo.type)
1809         {
1810             case GL_SAMPLER_2D:
1811             case GL_SAMPLER_CUBE:
1812             case GL_SAMPLER_EXTERNAL_OES:
1813             case GL_SAMPLER_VIDEO_IMAGE_WEBGL:
1814                 break;
1815             case GL_BOOL:
1816             case GL_BOOL_VEC2:
1817             case GL_BOOL_VEC3:
1818             case GL_BOOL_VEC4:
1819                 applyUniformnbv(targetUniform, i);
1820                 break;
1821             case GL_FLOAT:
1822             case GL_FLOAT_VEC2:
1823             case GL_FLOAT_VEC3:
1824             case GL_FLOAT_VEC4:
1825             case GL_FLOAT_MAT2:
1826             case GL_FLOAT_MAT3:
1827             case GL_FLOAT_MAT4:
1828                 applyUniformnfv(targetUniform, f);
1829                 break;
1830             case GL_INT:
1831             case GL_INT_VEC2:
1832             case GL_INT_VEC3:
1833             case GL_INT_VEC4:
1834                 applyUniformniv(targetUniform, i);
1835                 break;
1836             default:
1837                 UNREACHABLE();
1838         }
1839     }
1840 
1841     programD3D->markUniformsClean();
1842 }
1843 
applyUniformnfv(const D3DUniform * targetUniform,const GLfloat * v)1844 void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
1845 {
1846     if (targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
1847     {
1848         mDevice->SetPixelShaderConstantF(
1849             targetUniform->mShaderRegisterIndexes[gl::ShaderType::Fragment], v,
1850             targetUniform->registerCount);
1851     }
1852 
1853     if (targetUniform->isReferencedByShader(gl::ShaderType::Vertex))
1854     {
1855         mDevice->SetVertexShaderConstantF(
1856             targetUniform->mShaderRegisterIndexes[gl::ShaderType::Vertex], v,
1857             targetUniform->registerCount);
1858     }
1859 }
1860 
applyUniformniv(const D3DUniform * targetUniform,const GLint * v)1861 void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
1862 {
1863     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
1864     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
1865 
1866     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
1867     {
1868         vector[i][0] = (GLfloat)v[4 * i + 0];
1869         vector[i][1] = (GLfloat)v[4 * i + 1];
1870         vector[i][2] = (GLfloat)v[4 * i + 2];
1871         vector[i][3] = (GLfloat)v[4 * i + 3];
1872     }
1873 
1874     applyUniformnfv(targetUniform, (GLfloat *)vector);
1875 }
1876 
applyUniformnbv(const D3DUniform * targetUniform,const GLint * v)1877 void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
1878 {
1879     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
1880     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
1881 
1882     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
1883     {
1884         vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
1885         vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
1886         vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
1887         vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
1888     }
1889 
1890     applyUniformnfv(targetUniform, (GLfloat *)vector);
1891 }
1892 
clear(const ClearParameters & clearParams,const RenderTarget9 * colorRenderTarget,const RenderTarget9 * depthStencilRenderTarget)1893 void Renderer9::clear(const ClearParameters &clearParams,
1894                       const RenderTarget9 *colorRenderTarget,
1895                       const RenderTarget9 *depthStencilRenderTarget)
1896 {
1897     // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
1898     ASSERT(clearParams.colorType == GL_FLOAT);
1899 
1900     // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0
1901     bool clearColor = clearParams.clearColor[0];
1902     for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
1903     {
1904         ASSERT(clearParams.clearColor[i] == clearColor);
1905     }
1906 
1907     float depth   = gl::clamp01(clearParams.depthValue);
1908     DWORD stencil = clearParams.stencilValue & 0x000000FF;
1909 
1910     unsigned int stencilUnmasked = 0x0;
1911     if (clearParams.clearStencil && depthStencilRenderTarget)
1912     {
1913         const gl::InternalFormat &depthStencilFormat =
1914             gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
1915         if (depthStencilFormat.stencilBits > 0)
1916         {
1917             const d3d9::D3DFormat &d3dFormatInfo =
1918                 d3d9::GetD3DFormatInfo(depthStencilRenderTarget->getD3DFormat());
1919             stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
1920         }
1921     }
1922 
1923     const bool needMaskedStencilClear =
1924         clearParams.clearStencil &&
1925         (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
1926 
1927     bool needMaskedColorClear = false;
1928     D3DCOLOR color            = D3DCOLOR_ARGB(255, 0, 0, 0);
1929     if (clearColor)
1930     {
1931         ASSERT(colorRenderTarget != nullptr);
1932 
1933         const gl::InternalFormat &formatInfo =
1934             gl::GetSizedInternalFormatInfo(colorRenderTarget->getInternalFormat());
1935         const d3d9::D3DFormat &d3dFormatInfo =
1936             d3d9::GetD3DFormatInfo(colorRenderTarget->getD3DFormat());
1937 
1938         color =
1939             D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
1940                                            ? 1.0f
1941                                            : clearParams.colorF.alpha),
1942                           gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
1943                                            ? 0.0f
1944                                            : clearParams.colorF.red),
1945                           gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
1946                                            ? 0.0f
1947                                            : clearParams.colorF.green),
1948                           gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
1949                                            ? 0.0f
1950                                            : clearParams.colorF.blue));
1951 
1952         if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed[0]) ||
1953             (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen[0]) ||
1954             (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue[0]) ||
1955             (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha[0]))
1956         {
1957             needMaskedColorClear = true;
1958         }
1959     }
1960 
1961     if (needMaskedColorClear || needMaskedStencilClear)
1962     {
1963         // State which is altered in all paths from this point to the clear call is saved.
1964         // State which is altered in only some paths will be flagged dirty in the case that
1965         //  that path is taken.
1966         HRESULT hr;
1967         if (mMaskedClearSavedState == nullptr)
1968         {
1969             hr = mDevice->BeginStateBlock();
1970             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
1971 
1972             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1973             mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1974             mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
1975             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1976             mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1977             mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1978             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1979             mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1980             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1981             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1982             mDevice->SetPixelShader(nullptr);
1983             mDevice->SetVertexShader(nullptr);
1984             mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1985             mDevice->SetStreamSource(0, nullptr, 0, 0);
1986             mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1987             mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1988             mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
1989             mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
1990             mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
1991             mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
1992             mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
1993 
1994             for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1995             {
1996                 mDevice->SetStreamSourceFreq(i, 1);
1997             }
1998 
1999             hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
2000             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2001         }
2002 
2003         ASSERT(mMaskedClearSavedState != nullptr);
2004 
2005         if (mMaskedClearSavedState != nullptr)
2006         {
2007             hr = mMaskedClearSavedState->Capture();
2008             ASSERT(SUCCEEDED(hr));
2009         }
2010 
2011         mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2012         mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2013         mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
2014         mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2015         mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2016         mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2017         mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2018         mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2019 
2020         if (clearColor)
2021         {
2022             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
2023                                     gl_d3d9::ConvertColorMask(clearParams.colorMaskRed[0],
2024                                                               clearParams.colorMaskGreen[0],
2025                                                               clearParams.colorMaskBlue[0],
2026                                                               clearParams.colorMaskAlpha[0]));
2027         }
2028         else
2029         {
2030             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2031         }
2032 
2033         if (stencilUnmasked != 0x0 && clearParams.clearStencil)
2034         {
2035             mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2036             mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2037             mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2038             mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
2039             mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
2040             mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
2041             mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2042             mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2043         }
2044         else
2045         {
2046             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2047         }
2048 
2049         mDevice->SetPixelShader(nullptr);
2050         mDevice->SetVertexShader(nullptr);
2051         mDevice->SetFVF(D3DFVF_XYZRHW);
2052         mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
2053         mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
2054         mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
2055         mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
2056         mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
2057         mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
2058         mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
2059 
2060         for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
2061         {
2062             mDevice->SetStreamSourceFreq(i, 1);
2063         }
2064 
2065         int renderTargetWidth  = mStateManager.getRenderTargetWidth();
2066         int renderTargetHeight = mStateManager.getRenderTargetHeight();
2067 
2068         float quad[4][4];  // A quadrilateral covering the target, aligned to match the edges
2069         quad[0][0] = -0.5f;
2070         quad[0][1] = renderTargetHeight - 0.5f;
2071         quad[0][2] = 0.0f;
2072         quad[0][3] = 1.0f;
2073 
2074         quad[1][0] = renderTargetWidth - 0.5f;
2075         quad[1][1] = renderTargetHeight - 0.5f;
2076         quad[1][2] = 0.0f;
2077         quad[1][3] = 1.0f;
2078 
2079         quad[2][0] = -0.5f;
2080         quad[2][1] = -0.5f;
2081         quad[2][2] = 0.0f;
2082         quad[2][3] = 1.0f;
2083 
2084         quad[3][0] = renderTargetWidth - 0.5f;
2085         quad[3][1] = -0.5f;
2086         quad[3][2] = 0.0f;
2087         quad[3][3] = 1.0f;
2088 
2089         startScene();
2090         mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
2091 
2092         if (clearParams.clearDepth)
2093         {
2094             mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
2095             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2096             mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil);
2097         }
2098 
2099         if (mMaskedClearSavedState != nullptr)
2100         {
2101             mMaskedClearSavedState->Apply();
2102         }
2103     }
2104     else if (clearColor || clearParams.clearDepth || clearParams.clearStencil)
2105     {
2106         DWORD dxClearFlags = 0;
2107         if (clearColor)
2108         {
2109             dxClearFlags |= D3DCLEAR_TARGET;
2110         }
2111         if (clearParams.clearDepth)
2112         {
2113             dxClearFlags |= D3DCLEAR_ZBUFFER;
2114         }
2115         if (clearParams.clearStencil)
2116         {
2117             dxClearFlags |= D3DCLEAR_STENCIL;
2118         }
2119 
2120         mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
2121     }
2122 }
2123 
markAllStateDirty()2124 void Renderer9::markAllStateDirty()
2125 {
2126     mAppliedRenderTargetSerial   = 0;
2127     mAppliedDepthStencilSerial   = 0;
2128     mDepthStencilInitialized     = false;
2129     mRenderTargetDescInitialized = false;
2130 
2131     mStateManager.forceSetRasterState();
2132     mStateManager.forceSetDepthStencilState();
2133     mStateManager.forceSetBlendState();
2134     mStateManager.forceSetScissorState();
2135     mStateManager.forceSetViewportState();
2136 
2137     ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size());
2138     for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
2139     {
2140         mCurVertexSamplerStates[i].forceSet = true;
2141         mCurVertexTextures[i]               = angle::DirtyPointer;
2142     }
2143 
2144     ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size());
2145     for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++)
2146     {
2147         mCurPixelSamplerStates[i].forceSet = true;
2148         mCurPixelTextures[i]               = angle::DirtyPointer;
2149     }
2150 
2151     mAppliedIBSerial      = 0;
2152     mAppliedVertexShader  = nullptr;
2153     mAppliedPixelShader   = nullptr;
2154     mAppliedProgramSerial = 0;
2155     mStateManager.forceSetDXUniformsState();
2156 
2157     mVertexDeclarationCache.markStateDirty();
2158 }
2159 
releaseDeviceResources()2160 void Renderer9::releaseDeviceResources()
2161 {
2162     for (size_t i = 0; i < mEventQueryPool.size(); i++)
2163     {
2164         SafeRelease(mEventQueryPool[i]);
2165     }
2166     mEventQueryPool.clear();
2167 
2168     SafeRelease(mMaskedClearSavedState);
2169 
2170     mVertexShaderCache.clear();
2171     mPixelShaderCache.clear();
2172 
2173     SafeDelete(mBlit);
2174     SafeDelete(mVertexDataManager);
2175     SafeDelete(mIndexDataManager);
2176     SafeDelete(mLineLoopIB);
2177     SafeDelete(mCountingIB);
2178 
2179     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
2180     {
2181         SafeDelete(mNullRenderTargetCache[i].renderTarget);
2182     }
2183 }
2184 
2185 // set notify to true to broadcast a message to all contexts of the device loss
testDeviceLost()2186 bool Renderer9::testDeviceLost()
2187 {
2188     HRESULT status = getDeviceStatusCode();
2189     return FAILED(status);
2190 }
2191 
getDeviceStatusCode()2192 HRESULT Renderer9::getDeviceStatusCode()
2193 {
2194     HRESULT status = D3D_OK;
2195 
2196     if (mDeviceEx)
2197     {
2198         status = mDeviceEx->CheckDeviceState(nullptr);
2199     }
2200     else if (mDevice)
2201     {
2202         status = mDevice->TestCooperativeLevel();
2203     }
2204 
2205     return status;
2206 }
2207 
testDeviceResettable()2208 bool Renderer9::testDeviceResettable()
2209 {
2210     // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
2211     // DEVICEREMOVED indicates the device has been stopped and must be recreated
2212     switch (getDeviceStatusCode())
2213     {
2214         case D3DERR_DEVICENOTRESET:
2215         case D3DERR_DEVICEHUNG:
2216             return true;
2217         case D3DERR_DEVICELOST:
2218             return (mDeviceEx != nullptr);
2219         case D3DERR_DEVICEREMOVED:
2220             ASSERT(mDeviceEx != nullptr);
2221             return isRemovedDeviceResettable();
2222         default:
2223             return false;
2224     }
2225 }
2226 
resetDevice()2227 bool Renderer9::resetDevice()
2228 {
2229     releaseDeviceResources();
2230 
2231     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
2232 
2233     HRESULT result     = D3D_OK;
2234     bool lost          = testDeviceLost();
2235     bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
2236 
2237     // Device Removed is a feature which is only present with D3D9Ex
2238     ASSERT(mDeviceEx != nullptr || !removedDevice);
2239 
2240     for (int attempts = 3; lost && attempts > 0; attempts--)
2241     {
2242         if (removedDevice)
2243         {
2244             // Device removed, which may trigger on driver reinstallation,
2245             // may cause a longer wait other reset attempts before the
2246             // system is ready to handle creating a new device.
2247             Sleep(800);
2248             lost = !resetRemovedDevice();
2249         }
2250         else if (mDeviceEx)
2251         {
2252             Sleep(500);  // Give the graphics driver some CPU time
2253             result = mDeviceEx->ResetEx(&presentParameters, nullptr);
2254             lost   = testDeviceLost();
2255         }
2256         else
2257         {
2258             result = mDevice->TestCooperativeLevel();
2259             while (result == D3DERR_DEVICELOST)
2260             {
2261                 Sleep(100);  // Give the graphics driver some CPU time
2262                 result = mDevice->TestCooperativeLevel();
2263             }
2264 
2265             if (result == D3DERR_DEVICENOTRESET)
2266             {
2267                 result = mDevice->Reset(&presentParameters);
2268             }
2269             lost = testDeviceLost();
2270         }
2271     }
2272 
2273     if (FAILED(result))
2274     {
2275         ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result);
2276         return false;
2277     }
2278 
2279     if (removedDevice && lost)
2280     {
2281         ERR() << "Device lost reset failed multiple times";
2282         return false;
2283     }
2284 
2285     // If the device was removed, we already finished re-initialization in resetRemovedDevice
2286     if (!removedDevice)
2287     {
2288         // reset device defaults
2289         if (initializeDevice().isError())
2290         {
2291             return false;
2292         }
2293     }
2294 
2295     return true;
2296 }
2297 
isRemovedDeviceResettable() const2298 bool Renderer9::isRemovedDeviceResettable() const
2299 {
2300     bool success = false;
2301 
2302 #if ANGLE_D3D9EX == ANGLE_ENABLED
2303     IDirect3D9Ex *d3d9Ex = nullptr;
2304     typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
2305     Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
2306         reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
2307 
2308     if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
2309     {
2310         D3DCAPS9 deviceCaps;
2311         HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
2312         success        = SUCCEEDED(result);
2313     }
2314 
2315     SafeRelease(d3d9Ex);
2316 #else
2317     UNREACHABLE();
2318 #endif
2319 
2320     return success;
2321 }
2322 
resetRemovedDevice()2323 bool Renderer9::resetRemovedDevice()
2324 {
2325     // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
2326     // The hardware adapter has been removed. Application must destroy the device, do enumeration of
2327     // adapters and create another Direct3D device. If application continues rendering without
2328     // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
2329     release();
2330     return !initialize().isError();
2331 }
2332 
getVendorId() const2333 VendorID Renderer9::getVendorId() const
2334 {
2335     return static_cast<VendorID>(mAdapterIdentifier.VendorId);
2336 }
2337 
getRendererDescription() const2338 std::string Renderer9::getRendererDescription() const
2339 {
2340     std::ostringstream rendererString;
2341 
2342     rendererString << mAdapterIdentifier.Description;
2343     if (getShareHandleSupport())
2344     {
2345         rendererString << " Direct3D9Ex";
2346     }
2347     else
2348     {
2349         rendererString << " Direct3D9";
2350     }
2351 
2352     rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_"
2353                    << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
2354     rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_"
2355                    << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
2356 
2357     return rendererString.str();
2358 }
2359 
getAdapterIdentifier() const2360 DeviceIdentifier Renderer9::getAdapterIdentifier() const
2361 {
2362     DeviceIdentifier deviceIdentifier = {};
2363     deviceIdentifier.VendorId         = static_cast<UINT>(mAdapterIdentifier.VendorId);
2364     deviceIdentifier.DeviceId         = static_cast<UINT>(mAdapterIdentifier.DeviceId);
2365     deviceIdentifier.SubSysId         = static_cast<UINT>(mAdapterIdentifier.SubSysId);
2366     deviceIdentifier.Revision         = static_cast<UINT>(mAdapterIdentifier.Revision);
2367     deviceIdentifier.FeatureLevel     = 0;
2368 
2369     return deviceIdentifier;
2370 }
2371 
getReservedVertexUniformVectors() const2372 unsigned int Renderer9::getReservedVertexUniformVectors() const
2373 {
2374     return d3d9_gl::GetReservedVertexUniformVectors();
2375 }
2376 
getReservedFragmentUniformVectors() const2377 unsigned int Renderer9::getReservedFragmentUniformVectors() const
2378 {
2379     return d3d9_gl::GetReservedFragmentUniformVectors();
2380 }
2381 
getShareHandleSupport() const2382 bool Renderer9::getShareHandleSupport() const
2383 {
2384     // PIX doesn't seem to support using share handles, so disable them.
2385     return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive();
2386 }
2387 
getMajorShaderModel() const2388 int Renderer9::getMajorShaderModel() const
2389 {
2390     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
2391 }
2392 
getMinorShaderModel() const2393 int Renderer9::getMinorShaderModel() const
2394 {
2395     return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
2396 }
2397 
getShaderModelSuffix() const2398 std::string Renderer9::getShaderModelSuffix() const
2399 {
2400     return "";
2401 }
2402 
getCapsDeclTypes() const2403 DWORD Renderer9::getCapsDeclTypes() const
2404 {
2405     return mDeviceCaps.DeclTypes;
2406 }
2407 
getBufferPool(DWORD usage) const2408 D3DPOOL Renderer9::getBufferPool(DWORD usage) const
2409 {
2410     if (mD3d9Ex != nullptr)
2411     {
2412         return D3DPOOL_DEFAULT;
2413     }
2414     else
2415     {
2416         if (!(usage & D3DUSAGE_DYNAMIC))
2417         {
2418             return D3DPOOL_MANAGED;
2419         }
2420     }
2421 
2422     return D3DPOOL_DEFAULT;
2423 }
2424 
copyImage2D(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2425 angle::Result Renderer9::copyImage2D(const gl::Context *context,
2426                                      const gl::Framebuffer *framebuffer,
2427                                      const gl::Rectangle &sourceRect,
2428                                      GLenum destFormat,
2429                                      const gl::Offset &destOffset,
2430                                      TextureStorage *storage,
2431                                      GLint level)
2432 {
2433     RECT rect;
2434     rect.left   = sourceRect.x;
2435     rect.top    = sourceRect.y;
2436     rect.right  = sourceRect.x + sourceRect.width;
2437     rect.bottom = sourceRect.y + sourceRect.height;
2438 
2439     return mBlit->copy2D(context, framebuffer, rect, destFormat, destOffset, storage, level);
2440 }
2441 
copyImageCube(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,gl::TextureTarget target,GLint level)2442 angle::Result Renderer9::copyImageCube(const gl::Context *context,
2443                                        const gl::Framebuffer *framebuffer,
2444                                        const gl::Rectangle &sourceRect,
2445                                        GLenum destFormat,
2446                                        const gl::Offset &destOffset,
2447                                        TextureStorage *storage,
2448                                        gl::TextureTarget target,
2449                                        GLint level)
2450 {
2451     RECT rect;
2452     rect.left   = sourceRect.x;
2453     rect.top    = sourceRect.y;
2454     rect.right  = sourceRect.x + sourceRect.width;
2455     rect.bottom = sourceRect.y + sourceRect.height;
2456 
2457     return mBlit->copyCube(context, framebuffer, rect, destFormat, destOffset, storage, target,
2458                            level);
2459 }
2460 
copyImage3D(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2461 angle::Result Renderer9::copyImage3D(const gl::Context *context,
2462                                      const gl::Framebuffer *framebuffer,
2463                                      const gl::Rectangle &sourceRect,
2464                                      GLenum destFormat,
2465                                      const gl::Offset &destOffset,
2466                                      TextureStorage *storage,
2467                                      GLint level)
2468 {
2469     // 3D textures are not available in the D3D9 backend.
2470     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
2471     return angle::Result::Stop;
2472 }
2473 
copyImage2DArray(const gl::Context * context,const gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,const gl::Offset & destOffset,TextureStorage * storage,GLint level)2474 angle::Result Renderer9::copyImage2DArray(const gl::Context *context,
2475                                           const gl::Framebuffer *framebuffer,
2476                                           const gl::Rectangle &sourceRect,
2477                                           GLenum destFormat,
2478                                           const gl::Offset &destOffset,
2479                                           TextureStorage *storage,
2480                                           GLint level)
2481 {
2482     // 2D array textures are not available in the D3D9 backend.
2483     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
2484     return angle::Result::Stop;
2485 }
2486 
copyTexture(const gl::Context * context,const gl::Texture * source,GLint sourceLevel,gl::TextureTarget srcTarget,const gl::Box & sourceBox,GLenum destFormat,GLenum destType,const gl::Offset & destOffset,TextureStorage * storage,gl::TextureTarget destTarget,GLint destLevel,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)2487 angle::Result Renderer9::copyTexture(const gl::Context *context,
2488                                      const gl::Texture *source,
2489                                      GLint sourceLevel,
2490                                      gl::TextureTarget srcTarget,
2491                                      const gl::Box &sourceBox,
2492                                      GLenum destFormat,
2493                                      GLenum destType,
2494                                      const gl::Offset &destOffset,
2495                                      TextureStorage *storage,
2496                                      gl::TextureTarget destTarget,
2497                                      GLint destLevel,
2498                                      bool unpackFlipY,
2499                                      bool unpackPremultiplyAlpha,
2500                                      bool unpackUnmultiplyAlpha)
2501 {
2502     RECT rect;
2503     rect.left   = sourceBox.x;
2504     rect.top    = sourceBox.y;
2505     rect.right  = sourceBox.x + sourceBox.width;
2506     rect.bottom = sourceBox.y + sourceBox.height;
2507 
2508     return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage,
2509                               destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha,
2510                               unpackUnmultiplyAlpha);
2511 }
2512 
copyCompressedTexture(const gl::Context * context,const gl::Texture * source,GLint sourceLevel,TextureStorage * storage,GLint destLevel)2513 angle::Result Renderer9::copyCompressedTexture(const gl::Context *context,
2514                                                const gl::Texture *source,
2515                                                GLint sourceLevel,
2516                                                TextureStorage *storage,
2517                                                GLint destLevel)
2518 {
2519     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
2520     return angle::Result::Stop;
2521 }
2522 
createRenderTarget(const gl::Context * context,int width,int height,GLenum format,GLsizei samples,RenderTargetD3D ** outRT)2523 angle::Result Renderer9::createRenderTarget(const gl::Context *context,
2524                                             int width,
2525                                             int height,
2526                                             GLenum format,
2527                                             GLsizei samples,
2528                                             RenderTargetD3D **outRT)
2529 {
2530     const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
2531 
2532     const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
2533     GLuint supportedSamples            = textureCaps.getNearestSamples(samples);
2534 
2535     IDirect3DTexture9 *texture      = nullptr;
2536     IDirect3DSurface9 *renderTarget = nullptr;
2537     if (width > 0 && height > 0)
2538     {
2539         bool requiresInitialization = false;
2540         HRESULT result              = D3DERR_INVALIDCALL;
2541 
2542         const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
2543         if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
2544         {
2545             result = mDevice->CreateDepthStencilSurface(
2546                 width, height, d3d9FormatInfo.renderFormat,
2547                 gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr);
2548         }
2549         else
2550         {
2551             requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr);
2552             if (supportedSamples > 0)
2553             {
2554                 result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
2555                                                      gl_d3d9::GetMultisampleType(supportedSamples),
2556                                                      0, FALSE, &renderTarget, nullptr);
2557             }
2558             else
2559             {
2560                 result = mDevice->CreateTexture(
2561                     width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat,
2562                     getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr);
2563                 if (!FAILED(result))
2564                 {
2565                     result = texture->GetSurfaceLevel(0, &renderTarget);
2566                 }
2567             }
2568         }
2569 
2570         ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create render target");
2571 
2572         if (requiresInitialization)
2573         {
2574             // This format requires that the data be initialized before the render target can be
2575             // used Unfortunately this requires a Get call on the d3d device but it is far better
2576             // than having to mark the render target as lockable and copy data to the gpu.
2577             IDirect3DSurface9 *prevRenderTarget = nullptr;
2578             mDevice->GetRenderTarget(0, &prevRenderTarget);
2579             mDevice->SetRenderTarget(0, renderTarget);
2580             mDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
2581             mDevice->SetRenderTarget(0, prevRenderTarget);
2582         }
2583     }
2584 
2585     *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1,
2586                                       supportedSamples);
2587     return angle::Result::Continue;
2588 }
2589 
createRenderTargetCopy(const gl::Context * context,RenderTargetD3D * source,RenderTargetD3D ** outRT)2590 angle::Result Renderer9::createRenderTargetCopy(const gl::Context *context,
2591                                                 RenderTargetD3D *source,
2592                                                 RenderTargetD3D **outRT)
2593 {
2594     ASSERT(source != nullptr);
2595 
2596     RenderTargetD3D *newRT = nullptr;
2597     ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(),
2598                                  source->getInternalFormat(), source->getSamples(), &newRT));
2599 
2600     RenderTarget9 *source9 = GetAs<RenderTarget9>(source);
2601     RenderTarget9 *dest9   = GetAs<RenderTarget9>(newRT);
2602 
2603     HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(),
2604                                           nullptr, D3DTEXF_NONE);
2605     ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to copy render target");
2606 
2607     *outRT = newRT;
2608     return angle::Result::Continue;
2609 }
2610 
loadExecutable(d3d::Context * context,const uint8_t * function,size_t length,gl::ShaderType type,const std::vector<D3DVarying> & streamOutVaryings,bool separatedOutputBuffers,ShaderExecutableD3D ** outExecutable)2611 angle::Result Renderer9::loadExecutable(d3d::Context *context,
2612                                         const uint8_t *function,
2613                                         size_t length,
2614                                         gl::ShaderType type,
2615                                         const std::vector<D3DVarying> &streamOutVaryings,
2616                                         bool separatedOutputBuffers,
2617                                         ShaderExecutableD3D **outExecutable)
2618 {
2619     // Transform feedback is not supported in ES2 or D3D9
2620     ASSERT(streamOutVaryings.empty());
2621 
2622     switch (type)
2623     {
2624         case gl::ShaderType::Vertex:
2625         {
2626             IDirect3DVertexShader9 *vshader = nullptr;
2627             ANGLE_TRY(createVertexShader(context, (DWORD *)function, length, &vshader));
2628             *outExecutable = new ShaderExecutable9(function, length, vshader);
2629         }
2630         break;
2631         case gl::ShaderType::Fragment:
2632         {
2633             IDirect3DPixelShader9 *pshader = nullptr;
2634             ANGLE_TRY(createPixelShader(context, (DWORD *)function, length, &pshader));
2635             *outExecutable = new ShaderExecutable9(function, length, pshader);
2636         }
2637         break;
2638         default:
2639             ANGLE_HR_UNREACHABLE(context);
2640     }
2641 
2642     return angle::Result::Continue;
2643 }
2644 
compileToExecutable(d3d::Context * context,gl::InfoLog & infoLog,const std::string & shaderHLSL,gl::ShaderType type,const std::vector<D3DVarying> & streamOutVaryings,bool separatedOutputBuffers,const angle::CompilerWorkaroundsD3D & workarounds,ShaderExecutableD3D ** outExectuable)2645 angle::Result Renderer9::compileToExecutable(d3d::Context *context,
2646                                              gl::InfoLog &infoLog,
2647                                              const std::string &shaderHLSL,
2648                                              gl::ShaderType type,
2649                                              const std::vector<D3DVarying> &streamOutVaryings,
2650                                              bool separatedOutputBuffers,
2651                                              const angle::CompilerWorkaroundsD3D &workarounds,
2652                                              ShaderExecutableD3D **outExectuable)
2653 {
2654     // Transform feedback is not supported in ES2 or D3D9
2655     ASSERT(streamOutVaryings.empty());
2656 
2657     std::stringstream profileStream;
2658 
2659     switch (type)
2660     {
2661         case gl::ShaderType::Vertex:
2662             profileStream << "vs";
2663             break;
2664         case gl::ShaderType::Fragment:
2665             profileStream << "ps";
2666             break;
2667         default:
2668             ANGLE_HR_UNREACHABLE(context);
2669     }
2670 
2671     profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2);
2672     profileStream << "_"
2673                   << "0";
2674 
2675     std::string profile = profileStream.str();
2676 
2677     UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
2678 
2679     if (workarounds.skipOptimization)
2680     {
2681         flags = D3DCOMPILE_SKIP_OPTIMIZATION;
2682     }
2683     else if (workarounds.useMaxOptimization)
2684     {
2685         flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
2686     }
2687 
2688     if (gl::DebugAnnotationsActive())
2689     {
2690 #ifndef NDEBUG
2691         flags = D3DCOMPILE_SKIP_OPTIMIZATION;
2692 #endif
2693 
2694         flags |= D3DCOMPILE_DEBUG;
2695     }
2696 
2697     // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
2698     // when it would otherwise pass with alternative options. Try the default flags first and if
2699     // compilation fails, try some alternatives.
2700     std::vector<CompileConfig> configs;
2701     configs.push_back(CompileConfig(flags, "default"));
2702     configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
2703     configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
2704 
2705     ID3DBlob *binary = nullptr;
2706     std::string debugInfo;
2707     angle::Result error = mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs,
2708                                                     nullptr, &binary, &debugInfo);
2709     ANGLE_TRY(error);
2710 
2711     // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
2712     // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
2713     // internal state is still OK.
2714     if (!binary)
2715     {
2716         *outExectuable = nullptr;
2717         return angle::Result::Continue;
2718     }
2719 
2720     error = loadExecutable(context, reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
2721                            binary->GetBufferSize(), type, streamOutVaryings, separatedOutputBuffers,
2722                            outExectuable);
2723 
2724     SafeRelease(binary);
2725     ANGLE_TRY(error);
2726 
2727     if (!debugInfo.empty())
2728     {
2729         (*outExectuable)->appendDebugInfo(debugInfo);
2730     }
2731 
2732     return angle::Result::Continue;
2733 }
2734 
ensureHLSLCompilerInitialized(d3d::Context * context)2735 angle::Result Renderer9::ensureHLSLCompilerInitialized(d3d::Context *context)
2736 {
2737     return mCompiler.ensureInitialized(context);
2738 }
2739 
createUniformStorage(size_t storageSize)2740 UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
2741 {
2742     return new UniformStorageD3D(storageSize);
2743 }
2744 
boxFilter(Context9 * context9,IDirect3DSurface9 * source,IDirect3DSurface9 * dest)2745 angle::Result Renderer9::boxFilter(Context9 *context9,
2746                                    IDirect3DSurface9 *source,
2747                                    IDirect3DSurface9 *dest)
2748 {
2749     return mBlit->boxFilter(context9, source, dest);
2750 }
2751 
getTexturePool(DWORD usage) const2752 D3DPOOL Renderer9::getTexturePool(DWORD usage) const
2753 {
2754     if (mD3d9Ex != nullptr)
2755     {
2756         return D3DPOOL_DEFAULT;
2757     }
2758     else
2759     {
2760         if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
2761         {
2762             return D3DPOOL_MANAGED;
2763         }
2764     }
2765 
2766     return D3DPOOL_DEFAULT;
2767 }
2768 
copyToRenderTarget(const gl::Context * context,IDirect3DSurface9 * dest,IDirect3DSurface9 * source,bool fromManaged)2769 angle::Result Renderer9::copyToRenderTarget(const gl::Context *context,
2770                                             IDirect3DSurface9 *dest,
2771                                             IDirect3DSurface9 *source,
2772                                             bool fromManaged)
2773 {
2774     ASSERT(source && dest);
2775 
2776     Context9 *context9 = GetImplAs<Context9>(context);
2777 
2778     HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
2779 
2780     if (fromManaged)
2781     {
2782         D3DSURFACE_DESC desc;
2783         source->GetDesc(&desc);
2784 
2785         IDirect3DSurface9 *surf = 0;
2786         result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
2787                                                       D3DPOOL_SYSTEMMEM, &surf, nullptr);
2788 
2789         if (SUCCEEDED(result))
2790         {
2791             ANGLE_TRY(Image9::CopyLockableSurfaces(context9, surf, source));
2792             result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr);
2793             SafeRelease(surf);
2794         }
2795     }
2796     else
2797     {
2798         endScene();
2799         result = mDevice->StretchRect(source, nullptr, dest, nullptr, D3DTEXF_NONE);
2800     }
2801 
2802     ANGLE_TRY_HR(context9, result, "Failed to blit internal texture");
2803     return angle::Result::Continue;
2804 }
2805 
getRendererClass() const2806 RendererClass Renderer9::getRendererClass() const
2807 {
2808     return RENDERER_D3D9;
2809 }
2810 
createImage()2811 ImageD3D *Renderer9::createImage()
2812 {
2813     return new Image9(this);
2814 }
2815 
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)2816 ExternalImageSiblingImpl *Renderer9::createExternalImageSibling(const gl::Context *context,
2817                                                                 EGLenum target,
2818                                                                 EGLClientBuffer buffer,
2819                                                                 const egl::AttributeMap &attribs)
2820 {
2821     UNREACHABLE();
2822     return nullptr;
2823 }
2824 
generateMipmap(const gl::Context * context,ImageD3D * dest,ImageD3D * src)2825 angle::Result Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
2826 {
2827     Image9 *src9 = GetAs<Image9>(src);
2828     Image9 *dst9 = GetAs<Image9>(dest);
2829     return Image9::GenerateMipmap(GetImplAs<Context9>(context), dst9, src9);
2830 }
2831 
generateMipmapUsingD3D(const gl::Context * context,TextureStorage * storage,const gl::TextureState & textureState)2832 angle::Result Renderer9::generateMipmapUsingD3D(const gl::Context *context,
2833                                                 TextureStorage *storage,
2834                                                 const gl::TextureState &textureState)
2835 {
2836     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
2837     return angle::Result::Stop;
2838 }
2839 
copyImage(const gl::Context * context,ImageD3D * dest,ImageD3D * source,const gl::Box & sourceBox,const gl::Offset & destOffset,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)2840 angle::Result Renderer9::copyImage(const gl::Context *context,
2841                                    ImageD3D *dest,
2842                                    ImageD3D *source,
2843                                    const gl::Box &sourceBox,
2844                                    const gl::Offset &destOffset,
2845                                    bool unpackFlipY,
2846                                    bool unpackPremultiplyAlpha,
2847                                    bool unpackUnmultiplyAlpha)
2848 {
2849     Image9 *dest9 = GetAs<Image9>(dest);
2850     Image9 *src9  = GetAs<Image9>(source);
2851     return Image9::CopyImage(context, dest9, src9, sourceBox.toRect(), destOffset, unpackFlipY,
2852                              unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
2853 }
2854 
createTextureStorage2D(SwapChainD3D * swapChain)2855 TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
2856 {
2857     SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
2858     return new TextureStorage9_2D(this, swapChain9);
2859 }
2860 
createTextureStorageEGLImage(EGLImageD3D * eglImage,RenderTargetD3D * renderTargetD3D)2861 TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
2862                                                         RenderTargetD3D *renderTargetD3D)
2863 {
2864     return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D));
2865 }
2866 
createTextureStorageExternal(egl::Stream * stream,const egl::Stream::GLTextureDescription & desc)2867 TextureStorage *Renderer9::createTextureStorageExternal(
2868     egl::Stream *stream,
2869     const egl::Stream::GLTextureDescription &desc)
2870 {
2871     UNIMPLEMENTED();
2872     return nullptr;
2873 }
2874 
createTextureStorage2D(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,int levels,bool hintLevelZeroOnly)2875 TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat,
2876                                                   bool renderTarget,
2877                                                   GLsizei width,
2878                                                   GLsizei height,
2879                                                   int levels,
2880                                                   bool hintLevelZeroOnly)
2881 {
2882     return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
2883 }
2884 
createTextureStorageCube(GLenum internalformat,bool renderTarget,int size,int levels,bool hintLevelZeroOnly)2885 TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat,
2886                                                     bool renderTarget,
2887                                                     int size,
2888                                                     int levels,
2889                                                     bool hintLevelZeroOnly)
2890 {
2891     return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels,
2892                                     hintLevelZeroOnly);
2893 }
2894 
createTextureStorage3D(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)2895 TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat,
2896                                                   bool renderTarget,
2897                                                   GLsizei width,
2898                                                   GLsizei height,
2899                                                   GLsizei depth,
2900                                                   int levels)
2901 {
2902     // 3D textures are not supported by the D3D9 backend.
2903     UNREACHABLE();
2904 
2905     return nullptr;
2906 }
2907 
createTextureStorage2DArray(GLenum internalformat,bool renderTarget,GLsizei width,GLsizei height,GLsizei depth,int levels)2908 TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat,
2909                                                        bool renderTarget,
2910                                                        GLsizei width,
2911                                                        GLsizei height,
2912                                                        GLsizei depth,
2913                                                        int levels)
2914 {
2915     // 2D array textures are not supported by the D3D9 backend.
2916     UNREACHABLE();
2917 
2918     return nullptr;
2919 }
2920 
createTextureStorage2DMultisample(GLenum internalformat,GLsizei width,GLsizei height,int levels,int samples,bool fixedSampleLocations)2921 TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalformat,
2922                                                              GLsizei width,
2923                                                              GLsizei height,
2924                                                              int levels,
2925                                                              int samples,
2926                                                              bool fixedSampleLocations)
2927 {
2928     // 2D multisampled textures are not supported by the D3D9 backend.
2929     UNREACHABLE();
2930 
2931     return nullptr;
2932 }
2933 
createTextureStorage2DMultisampleArray(GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,int levels,int samples,bool fixedSampleLocations)2934 TextureStorage *Renderer9::createTextureStorage2DMultisampleArray(GLenum internalformat,
2935                                                                   GLsizei width,
2936                                                                   GLsizei height,
2937                                                                   GLsizei depth,
2938                                                                   int levels,
2939                                                                   int samples,
2940                                                                   bool fixedSampleLocations)
2941 {
2942     // 2D multisampled textures are not supported by the D3D9 backend.
2943     UNREACHABLE();
2944 
2945     return nullptr;
2946 }
2947 
getLUID(LUID * adapterLuid) const2948 bool Renderer9::getLUID(LUID *adapterLuid) const
2949 {
2950     adapterLuid->HighPart = 0;
2951     adapterLuid->LowPart  = 0;
2952 
2953     if (mD3d9Ex)
2954     {
2955         mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
2956         return true;
2957     }
2958 
2959     return false;
2960 }
2961 
getVertexConversionType(angle::FormatID vertexFormatID) const2962 VertexConversionType Renderer9::getVertexConversionType(angle::FormatID vertexFormatID) const
2963 {
2964     return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).conversionType;
2965 }
2966 
getVertexComponentType(angle::FormatID vertexFormatID) const2967 GLenum Renderer9::getVertexComponentType(angle::FormatID vertexFormatID) const
2968 {
2969     return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).componentType;
2970 }
2971 
getVertexSpaceRequired(const gl::Context * context,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,size_t count,GLsizei instances,unsigned int * bytesRequiredOut) const2972 angle::Result Renderer9::getVertexSpaceRequired(const gl::Context *context,
2973                                                 const gl::VertexAttribute &attrib,
2974                                                 const gl::VertexBinding &binding,
2975                                                 size_t count,
2976                                                 GLsizei instances,
2977                                                 unsigned int *bytesRequiredOut) const
2978 {
2979     if (!attrib.enabled)
2980     {
2981         *bytesRequiredOut = 16u;
2982         return angle::Result::Continue;
2983     }
2984 
2985     angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, gl::VertexAttribType::Float);
2986     const d3d9::VertexFormat &d3d9VertexInfo =
2987         d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID);
2988 
2989     unsigned int elementCount  = 0;
2990     const unsigned int divisor = binding.getDivisor();
2991     if (instances == 0 || divisor == 0)
2992     {
2993         elementCount = static_cast<unsigned int>(count);
2994     }
2995     else
2996     {
2997         // Round up to divisor, if possible
2998         elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
2999     }
3000 
3001     bool check = (d3d9VertexInfo.outputElementSize >
3002                   std::numeric_limits<unsigned int>::max() / elementCount);
3003     ANGLE_CHECK(GetImplAs<Context9>(context), !check,
3004                 "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
3005 
3006     *bytesRequiredOut = static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
3007     return angle::Result::Continue;
3008 }
3009 
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations * outLimitations) const3010 void Renderer9::generateCaps(gl::Caps *outCaps,
3011                              gl::TextureCapsMap *outTextureCaps,
3012                              gl::Extensions *outExtensions,
3013                              gl::Limitations *outLimitations) const
3014 {
3015     d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps,
3016                           outExtensions, outLimitations);
3017 }
3018 
initializeFeatures(angle::FeaturesD3D * features) const3019 void Renderer9::initializeFeatures(angle::FeaturesD3D *features) const
3020 {
3021     if (!mDisplay->getState().featuresAllDisabled)
3022     {
3023         d3d9::InitializeFeatures(features);
3024     }
3025     ApplyFeatureOverrides(features, mDisplay->getState());
3026 }
3027 
createEGLDevice()3028 DeviceImpl *Renderer9::createEGLDevice()
3029 {
3030     return new DeviceD3D(EGL_D3D9_DEVICE_ANGLE, mDevice);
3031 }
3032 
CurSamplerState()3033 Renderer9::CurSamplerState::CurSamplerState()
3034     : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState()
3035 {}
3036 
genericDrawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)3037 angle::Result Renderer9::genericDrawElements(const gl::Context *context,
3038                                              gl::PrimitiveMode mode,
3039                                              GLsizei count,
3040                                              gl::DrawElementsType type,
3041                                              const void *indices,
3042                                              GLsizei instances)
3043 {
3044     const gl::State &state = context->getState();
3045     gl::Program *program   = context->getState().getProgram();
3046     ASSERT(program != nullptr);
3047     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
3048     bool usesPointSize     = programD3D->usesPointSize();
3049 
3050     programD3D->updateSamplerMapping();
3051 
3052     if (!applyPrimitiveType(mode, count, usesPointSize))
3053     {
3054         return angle::Result::Continue;
3055     }
3056 
3057     ANGLE_TRY(updateState(context, mode));
3058     ANGLE_TRY(applyTextures(context));
3059     ANGLE_TRY(applyShaders(context, mode));
3060 
3061     if (!skipDraw(state, mode))
3062     {
3063         ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
3064     }
3065 
3066     return angle::Result::Continue;
3067 }
3068 
genericDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances)3069 angle::Result Renderer9::genericDrawArrays(const gl::Context *context,
3070                                            gl::PrimitiveMode mode,
3071                                            GLint first,
3072                                            GLsizei count,
3073                                            GLsizei instances)
3074 {
3075     gl::Program *program = context->getState().getProgram();
3076     ASSERT(program != nullptr);
3077     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
3078     bool usesPointSize     = programD3D->usesPointSize();
3079 
3080     programD3D->updateSamplerMapping();
3081 
3082     if (!applyPrimitiveType(mode, count, usesPointSize))
3083     {
3084         return angle::Result::Continue;
3085     }
3086 
3087     ANGLE_TRY(updateState(context, mode));
3088     ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
3089     ANGLE_TRY(applyTextures(context));
3090     ANGLE_TRY(applyShaders(context, mode));
3091 
3092     if (!skipDraw(context->getState(), mode))
3093     {
3094         ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances));
3095     }
3096 
3097     return angle::Result::Continue;
3098 }
3099 
createDefaultFramebuffer(const gl::FramebufferState & state)3100 FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
3101 {
3102     return new Framebuffer9(state, this);
3103 }
3104 
getMaxSupportedESVersion() const3105 gl::Version Renderer9::getMaxSupportedESVersion() const
3106 {
3107     return gl::Version(2, 0);
3108 }
3109 
getMaxConformantESVersion() const3110 gl::Version Renderer9::getMaxConformantESVersion() const
3111 {
3112     return gl::Version(2, 0);
3113 }
3114 
clearRenderTarget(const gl::Context * context,RenderTargetD3D * renderTarget,const gl::ColorF & clearColorValue,const float clearDepthValue,const unsigned int clearStencilValue)3115 angle::Result Renderer9::clearRenderTarget(const gl::Context *context,
3116                                            RenderTargetD3D *renderTarget,
3117                                            const gl::ColorF &clearColorValue,
3118                                            const float clearDepthValue,
3119                                            const unsigned int clearStencilValue)
3120 {
3121     D3DCOLOR color =
3122         D3DCOLOR_ARGB(gl::unorm<8>(clearColorValue.alpha), gl::unorm<8>(clearColorValue.red),
3123                       gl::unorm<8>(clearColorValue.green), gl::unorm<8>(clearColorValue.blue));
3124     float depth   = clearDepthValue;
3125     DWORD stencil = clearStencilValue & 0x000000FF;
3126 
3127     unsigned int renderTargetSerial        = renderTarget->getSerial();
3128     RenderTarget9 *renderTarget9           = GetAs<RenderTarget9>(renderTarget);
3129     IDirect3DSurface9 *renderTargetSurface = renderTarget9->getSurface();
3130     ASSERT(renderTargetSurface);
3131 
3132     DWORD dxClearFlags = 0;
3133 
3134     const gl::InternalFormat &internalFormatInfo =
3135         gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
3136     if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
3137     {
3138         dxClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
3139         if (mAppliedDepthStencilSerial != renderTargetSerial)
3140         {
3141             mDevice->SetDepthStencilSurface(renderTargetSurface);
3142         }
3143     }
3144     else
3145     {
3146         dxClearFlags = D3DCLEAR_TARGET;
3147         if (mAppliedRenderTargetSerial != renderTargetSerial)
3148         {
3149             mDevice->SetRenderTarget(0, renderTargetSurface);
3150         }
3151     }
3152     SafeRelease(renderTargetSurface);
3153 
3154     D3DVIEWPORT9 viewport;
3155     viewport.X      = 0;
3156     viewport.Y      = 0;
3157     viewport.Width  = renderTarget->getWidth();
3158     viewport.Height = renderTarget->getHeight();
3159     mDevice->SetViewport(&viewport);
3160 
3161     mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
3162 
3163     mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
3164 
3165     markAllStateDirty();
3166 
3167     return angle::Result::Continue;
3168 }
3169 
canSelectViewInVertexShader() const3170 bool Renderer9::canSelectViewInVertexShader() const
3171 {
3172     return false;
3173 }
3174 
3175 // For each Direct3D sampler of either the pixel or vertex stage,
3176 // looks up the corresponding OpenGL texture image unit and texture type,
3177 // and sets the texture and its addressing/filtering state (or NULL when inactive).
3178 // Sampler mapping needs to be up-to-date on the program object before this is called.
applyTextures(const gl::Context * context,gl::ShaderType shaderType)3179 angle::Result Renderer9::applyTextures(const gl::Context *context, gl::ShaderType shaderType)
3180 {
3181     const auto &glState    = context->getState();
3182     const auto &caps       = context->getCaps();
3183     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
3184 
3185     ASSERT(!programD3D->isSamplerMappingDirty());
3186 
3187     // TODO(jmadill): Use the Program's sampler bindings.
3188     const gl::ActiveTexturesCache &activeTextures = glState.getActiveTexturesCache();
3189 
3190     const gl::RangeUI samplerRange = programD3D->getUsedSamplerRange(shaderType);
3191     for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
3192          samplerIndex++)
3193     {
3194         GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
3195         ASSERT(textureUnit != -1);
3196         gl::Texture *texture = activeTextures[textureUnit];
3197 
3198         // A nullptr texture indicates incomplete.
3199         if (texture)
3200         {
3201             gl::Sampler *samplerObject = glState.getSampler(textureUnit);
3202 
3203             const gl::SamplerState &samplerState =
3204                 samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
3205 
3206             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
3207             ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
3208         }
3209         else
3210         {
3211             gl::TextureType textureType =
3212                 programD3D->getSamplerTextureType(shaderType, samplerIndex);
3213 
3214             // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
3215             // incomplete texture.
3216             gl::Texture *incompleteTexture = nullptr;
3217             ANGLE_TRY(getIncompleteTexture(context, textureType, &incompleteTexture));
3218             ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
3219                                       incompleteTexture->getSamplerState()));
3220             ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
3221         }
3222     }
3223 
3224     // Set all the remaining textures to NULL
3225     int samplerCount = (shaderType == gl::ShaderType::Fragment)
3226                            ? caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]
3227                            : caps.maxShaderTextureImageUnits[gl::ShaderType::Vertex];
3228 
3229     // TODO(jmadill): faster way?
3230     for (int samplerIndex = samplerRange.high(); samplerIndex < samplerCount; samplerIndex++)
3231     {
3232         ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
3233     }
3234 
3235     return angle::Result::Continue;
3236 }
3237 
applyTextures(const gl::Context * context)3238 angle::Result Renderer9::applyTextures(const gl::Context *context)
3239 {
3240     ANGLE_TRY(applyTextures(context, gl::ShaderType::Vertex));
3241     ANGLE_TRY(applyTextures(context, gl::ShaderType::Fragment));
3242     return angle::Result::Continue;
3243 }
3244 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::Texture ** textureOut)3245 angle::Result Renderer9::getIncompleteTexture(const gl::Context *context,
3246                                               gl::TextureType type,
3247                                               gl::Texture **textureOut)
3248 {
3249     return GetImplAs<Context9>(context)->getIncompleteTexture(context, type, textureOut);
3250 }
3251 
ensureVertexDataManagerInitialized(const gl::Context * context)3252 angle::Result Renderer9::ensureVertexDataManagerInitialized(const gl::Context *context)
3253 {
3254     if (!mVertexDataManager)
3255     {
3256         mVertexDataManager = new VertexDataManager(this);
3257         ANGLE_TRY(mVertexDataManager->initialize(context));
3258     }
3259 
3260     return angle::Result::Continue;
3261 }
3262 }  // namespace rx
3263