• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "precompiled.h"
2 //
3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7 
8 // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
9 
10 #include "libGLESv2/main.h"
11 #include "libGLESv2/Buffer.h"
12 #include "libGLESv2/Texture.h"
13 #include "libGLESv2/Framebuffer.h"
14 #include "libGLESv2/Renderbuffer.h"
15 #include "libGLESv2/ProgramBinary.h"
16 #include "libGLESv2/renderer/IndexDataManager.h"
17 #include "libGLESv2/renderer/Renderer9.h"
18 #include "libGLESv2/renderer/renderer9_utils.h"
19 #include "libGLESv2/renderer/ShaderExecutable9.h"
20 #include "libGLESv2/renderer/SwapChain9.h"
21 #include "libGLESv2/renderer/TextureStorage9.h"
22 #include "libGLESv2/renderer/Image9.h"
23 #include "libGLESv2/renderer/Blit.h"
24 #include "libGLESv2/renderer/RenderTarget9.h"
25 #include "libGLESv2/renderer/VertexBuffer9.h"
26 #include "libGLESv2/renderer/IndexBuffer9.h"
27 #include "libGLESv2/renderer/BufferStorage9.h"
28 #include "libGLESv2/renderer/Query9.h"
29 #include "libGLESv2/renderer/Fence9.h"
30 
31 #include "libEGL/Display.h"
32 
33 #include "third_party/trace_event/trace_event.h"
34 
35 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
36 #define REF_RAST 0
37 
38 // The "Debug This Pixel..." feature in PIX often fails when using the
39 // D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
40 // machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
41 #if !defined(ANGLE_ENABLE_D3D9EX)
42 // Enables use of the IDirect3D9Ex interface, when available
43 #define ANGLE_ENABLE_D3D9EX 1
44 #endif // !defined(ANGLE_ENABLE_D3D9EX)
45 
46 namespace rx
47 {
48 static const D3DFORMAT RenderTargetFormats[] =
49     {
50         D3DFMT_A1R5G5B5,
51     //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
52         D3DFMT_A8R8G8B8,
53         D3DFMT_R5G6B5,
54     //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
55         D3DFMT_X8R8G8B8
56     };
57 
58 static const D3DFORMAT DepthStencilFormats[] =
59     {
60         D3DFMT_UNKNOWN,
61     //  D3DFMT_D16_LOCKABLE,
62         D3DFMT_D32,
63     //  D3DFMT_D15S1,
64         D3DFMT_D24S8,
65         D3DFMT_D24X8,
66     //  D3DFMT_D24X4S4,
67         D3DFMT_D16,
68     //  D3DFMT_D32F_LOCKABLE,
69     //  D3DFMT_D24FS8
70     };
71 
72 enum
73 {
74     MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
75     MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
76     MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
77     MAX_VARYING_VECTORS_SM2 = 8,
78     MAX_VARYING_VECTORS_SM3 = 10,
79 
80     MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
81 };
82 
Renderer9(egl::Display * display,HDC hDc,bool softwareDevice)83 Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
84 {
85     mD3d9Module = NULL;
86 
87     mD3d9 = NULL;
88     mD3d9Ex = NULL;
89     mDevice = NULL;
90     mDeviceEx = NULL;
91     mDeviceWindow = NULL;
92     mBlit = NULL;
93 
94     mAdapter = D3DADAPTER_DEFAULT;
95 
96     #if REF_RAST == 1 || defined(FORCE_REF_RAST)
97         mDeviceType = D3DDEVTYPE_REF;
98     #else
99         mDeviceType = D3DDEVTYPE_HAL;
100     #endif
101 
102     mDeviceLost = false;
103 
104     mMaxSupportedSamples = 0;
105 
106     mMaskedClearSavedState = NULL;
107 
108     mVertexDataManager = NULL;
109     mIndexDataManager = NULL;
110     mLineLoopIB = NULL;
111 
112     mMaxNullColorbufferLRU = 0;
113     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
114     {
115         mNullColorbufferCache[i].lruCount = 0;
116         mNullColorbufferCache[i].width = 0;
117         mNullColorbufferCache[i].height = 0;
118         mNullColorbufferCache[i].buffer = NULL;
119     }
120 }
121 
~Renderer9()122 Renderer9::~Renderer9()
123 {
124     if (mDevice)
125     {
126         // If the device is lost, reset it first to prevent leaving the driver in an unstable state
127         if (testDeviceLost(false))
128         {
129             resetDevice();
130         }
131     }
132 
133     deinitialize();
134 }
135 
deinitialize()136 void Renderer9::deinitialize()
137 {
138     releaseDeviceResources();
139 
140     SafeRelease(mDevice);
141     SafeRelease(mDeviceEx);
142     SafeRelease(mD3d9);
143     SafeRelease(mD3d9Ex);
144 
145     if (mDeviceWindow)
146     {
147         DestroyWindow(mDeviceWindow);
148         mDeviceWindow = NULL;
149     }
150 
151     if (mD3d9Module)
152     {
153         mD3d9Module = NULL;
154     }
155 
156     while (!mMultiSampleSupport.empty())
157     {
158         delete [] mMultiSampleSupport.begin()->second;
159         mMultiSampleSupport.erase(mMultiSampleSupport.begin());
160     }
161 }
162 
makeRenderer9(Renderer * renderer)163 Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
164 {
165     ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
166     return static_cast<rx::Renderer9*>(renderer);
167 }
168 
initialize()169 EGLint Renderer9::initialize()
170 {
171     if (!initializeCompiler())
172     {
173         return EGL_NOT_INITIALIZED;
174     }
175 
176     if (mSoftwareDevice)
177     {
178         TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader");
179         mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
180     }
181     else
182     {
183         TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
184         mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
185     }
186 
187     if (mD3d9Module == NULL)
188     {
189         ERR("No D3D9 module found - aborting!\n");
190         return EGL_NOT_INITIALIZED;
191     }
192 
193     typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
194     Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
195 
196     // Use Direct3D9Ex if available. Among other things, this version is less
197     // inclined to report a lost context, for example when the user switches
198     // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
199     if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
200     {
201         TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
202         ASSERT(mD3d9Ex);
203         mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
204         ASSERT(mD3d9);
205     }
206     else
207     {
208         TRACE_EVENT0("gpu", "Direct3DCreate9");
209         mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
210     }
211 
212     if (!mD3d9)
213     {
214         ERR("Could not create D3D9 device - aborting!\n");
215         return EGL_NOT_INITIALIZED;
216     }
217 
218     if (mDc != NULL)
219     {
220     //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
221     }
222 
223     HRESULT result;
224 
225     // Give up on getting device caps after about one second.
226     {
227         TRACE_EVENT0("gpu", "GetDeviceCaps");
228         for (int i = 0; i < 10; ++i)
229         {
230             result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
231             if (SUCCEEDED(result))
232             {
233                 break;
234             }
235             else if (result == D3DERR_NOTAVAILABLE)
236             {
237                 Sleep(100);   // Give the driver some time to initialize/recover
238             }
239             else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
240             {
241                 ERR("failed to get device caps (0x%x)\n", result);
242                 return EGL_NOT_INITIALIZED;
243             }
244         }
245     }
246 
247     if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
248     {
249         ERR("Renderer does not support PS 2.0. aborting!\n");
250         return EGL_NOT_INITIALIZED;
251     }
252 
253     // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
254     // This is required by Texture2D::convertToRenderTarget.
255     if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
256     {
257         ERR("Renderer does not support stretctrect from textures!\n");
258         return EGL_NOT_INITIALIZED;
259     }
260 
261     {
262         TRACE_EVENT0("gpu", "GetAdapterIdentifier");
263         mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
264     }
265 
266     // ATI cards on XP have problems with non-power-of-two textures.
267     mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
268         !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
269         !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
270         !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
271 
272     // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
273     mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
274 
275     mMinSwapInterval = 4;
276     mMaxSwapInterval = 0;
277 
278     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
279     {
280         mMinSwapInterval = std::min(mMinSwapInterval, 0);
281         mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
282     }
283     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
284     {
285         mMinSwapInterval = std::min(mMinSwapInterval, 1);
286         mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
287     }
288     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
289     {
290         mMinSwapInterval = std::min(mMinSwapInterval, 2);
291         mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
292     }
293     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
294     {
295         mMinSwapInterval = std::min(mMinSwapInterval, 3);
296         mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
297     }
298     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
299     {
300         mMinSwapInterval = std::min(mMinSwapInterval, 4);
301         mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
302     }
303 
304     int max = 0;
305     {
306         TRACE_EVENT0("gpu", "getMultiSampleSupport");
307         for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
308         {
309             bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
310             getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
311             mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
312 
313             for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
314             {
315                 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
316                 {
317                     max = j;
318                 }
319             }
320         }
321     }
322 
323     {
324         TRACE_EVENT0("gpu", "getMultiSampleSupport2");
325         for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
326         {
327             if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
328                 continue;
329 
330             bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
331             getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
332             mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
333 
334             for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
335             {
336                 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
337                 {
338                     max = j;
339                 }
340             }
341         }
342     }
343 
344     mMaxSupportedSamples = max;
345 
346     static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
347     static const TCHAR className[] = TEXT("STATIC");
348 
349     {
350         TRACE_EVENT0("gpu", "CreateWindowEx");
351         mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
352     }
353 
354     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
355     DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
356 
357     {
358         TRACE_EVENT0("gpu", "D3d9_CreateDevice");
359         result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
360     }
361     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
362     {
363         return EGL_BAD_ALLOC;
364     }
365 
366     if (FAILED(result))
367     {
368         TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
369         result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
370 
371         if (FAILED(result))
372         {
373             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
374             return EGL_BAD_ALLOC;
375         }
376     }
377 
378     if (mD3d9Ex)
379     {
380         TRACE_EVENT0("gpu", "mDevice_QueryInterface");
381         result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
382         ASSERT(SUCCEEDED(result));
383     }
384 
385     {
386         TRACE_EVENT0("gpu", "ShaderCache initialize");
387         mVertexShaderCache.initialize(mDevice);
388         mPixelShaderCache.initialize(mDevice);
389     }
390 
391     // Check occlusion query support
392     IDirect3DQuery9 *occlusionQuery = NULL;
393     {
394         TRACE_EVENT0("gpu", "device_CreateQuery");
395         if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
396         {
397             occlusionQuery->Release();
398             mOcclusionQuerySupport = true;
399         }
400         else
401         {
402             mOcclusionQuerySupport = false;
403         }
404     }
405 
406     // Check event query support
407     IDirect3DQuery9 *eventQuery = NULL;
408     {
409         TRACE_EVENT0("gpu", "device_CreateQuery2");
410         if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
411         {
412             eventQuery->Release();
413             mEventQuerySupport = true;
414         }
415         else
416         {
417             mEventQuerySupport = false;
418         }
419     }
420 
421     D3DDISPLAYMODE currentDisplayMode;
422     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
423 
424     // Check vertex texture support
425     // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
426     // We test this using D3D9 by checking support for the R16F format.
427     mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
428                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
429                                                                D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
430 
431     // Check depth texture support
432     // we use INTZ for depth textures in Direct3D9
433     // we also want NULL texture support to ensure the we can make depth-only FBOs
434     // see http://aras-p.info/texts/D3D9GPUHacks.html
435     mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
436                                                               D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
437                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
438                                                               D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
439 
440     // Check 32 bit floating point texture support
441     mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
442                                                                D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
443                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
444                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
445 
446     mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
447                                                                D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
448                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
449                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
450 
451     if (!mFloat32FilterSupport && !mFloat32RenderSupport)
452     {
453         mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
454                                                                     D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
455                                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
456                                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
457     }
458     else
459     {
460         mFloat32TextureSupport = true;
461     }
462 
463     // Check 16 bit floating point texture support
464     mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
465                                                                D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
466                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
467                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
468 
469     mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
470                                                                D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
471                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
472                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
473 
474     if (!mFloat16FilterSupport && !mFloat16RenderSupport)
475     {
476         mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
477                                                                     D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
478                                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
479                                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
480     }
481     else
482     {
483         mFloat16TextureSupport = true;
484     }
485 
486     // Check DXT texture support
487     mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
488     mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
489     mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
490 
491     // Check luminance[alpha] texture support
492     mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
493     mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
494 
495     initializeDevice();
496 
497     return EGL_SUCCESS;
498 }
499 
500 // do any one-time device initialization
501 // NOTE: this is also needed after a device lost/reset
502 // to reset the scene status and ensure the default states are reset.
initializeDevice()503 void Renderer9::initializeDevice()
504 {
505     // Permanent non-default states
506     mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
507     mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
508 
509     if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
510     {
511         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
512     }
513     else
514     {
515         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);   // 1.0f
516     }
517 
518     markAllStateDirty();
519 
520     mSceneStarted = false;
521 
522     ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
523     mBlit = new Blit(this);
524     mVertexDataManager = new rx::VertexDataManager(this);
525     mIndexDataManager = new rx::IndexDataManager(this);
526 }
527 
getDefaultPresentParameters()528 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
529 {
530     D3DPRESENT_PARAMETERS presentParameters = {0};
531 
532     // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
533     presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
534     presentParameters.BackBufferCount = 1;
535     presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
536     presentParameters.BackBufferWidth = 1;
537     presentParameters.BackBufferHeight = 1;
538     presentParameters.EnableAutoDepthStencil = FALSE;
539     presentParameters.Flags = 0;
540     presentParameters.hDeviceWindow = mDeviceWindow;
541     presentParameters.MultiSampleQuality = 0;
542     presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
543     presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
544     presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
545     presentParameters.Windowed = TRUE;
546 
547     return presentParameters;
548 }
549 
generateConfigs(ConfigDesc ** configDescList)550 int Renderer9::generateConfigs(ConfigDesc **configDescList)
551 {
552     D3DDISPLAYMODE currentDisplayMode;
553     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
554 
555     unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
556     unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
557     (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
558     int numConfigs = 0;
559 
560     for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
561     {
562         D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
563 
564         HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
565 
566         if (SUCCEEDED(result))
567         {
568             for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
569             {
570                 D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
571                 HRESULT result = D3D_OK;
572 
573                 if(depthStencilFormat != D3DFMT_UNKNOWN)
574                 {
575                     result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
576                 }
577 
578                 if (SUCCEEDED(result))
579                 {
580                     if(depthStencilFormat != D3DFMT_UNKNOWN)
581                     {
582                         result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
583                     }
584 
585                     if (SUCCEEDED(result))
586                     {
587                         ConfigDesc newConfig;
588                         newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
589                         newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
590                         newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
591                         newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
592 
593                         (*configDescList)[numConfigs++] = newConfig;
594                     }
595                 }
596             }
597         }
598     }
599 
600     return numConfigs;
601 }
602 
deleteConfigs(ConfigDesc * configDescList)603 void Renderer9::deleteConfigs(ConfigDesc *configDescList)
604 {
605     delete [] (configDescList);
606 }
607 
startScene()608 void Renderer9::startScene()
609 {
610     if (!mSceneStarted)
611     {
612         long result = mDevice->BeginScene();
613         if (SUCCEEDED(result)) {
614             // This is defensive checking against the device being
615             // lost at unexpected times.
616             mSceneStarted = true;
617         }
618     }
619 }
620 
endScene()621 void Renderer9::endScene()
622 {
623     if (mSceneStarted)
624     {
625         // EndScene can fail if the device was lost, for example due
626         // to a TDR during a draw call.
627         mDevice->EndScene();
628         mSceneStarted = false;
629     }
630 }
631 
sync(bool block)632 void Renderer9::sync(bool block)
633 {
634     HRESULT result;
635 
636     IDirect3DQuery9* query = allocateEventQuery();
637     if (!query)
638     {
639         return;
640     }
641 
642     result = query->Issue(D3DISSUE_END);
643     ASSERT(SUCCEEDED(result));
644 
645     do
646     {
647         result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
648 
649         if(block && result == S_FALSE)
650         {
651             // Keep polling, but allow other threads to do something useful first
652             Sleep(0);
653             // explicitly check for device loss
654             // some drivers seem to return S_FALSE even if the device is lost
655             // instead of D3DERR_DEVICELOST like they should
656             if (testDeviceLost(false))
657             {
658                 result = D3DERR_DEVICELOST;
659             }
660         }
661     }
662     while(block && result == S_FALSE);
663 
664     freeEventQuery(query);
665 
666     if (d3d9::isDeviceLostError(result))
667     {
668         notifyDeviceLost();
669     }
670 }
671 
createSwapChain(HWND window,HANDLE shareHandle,GLenum backBufferFormat,GLenum depthBufferFormat)672 SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
673 {
674     return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
675 }
676 
allocateEventQuery()677 IDirect3DQuery9* Renderer9::allocateEventQuery()
678 {
679     IDirect3DQuery9 *query = NULL;
680 
681     if (mEventQueryPool.empty())
682     {
683         HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
684         ASSERT(SUCCEEDED(result));
685     }
686     else
687     {
688         query = mEventQueryPool.back();
689         mEventQueryPool.pop_back();
690     }
691 
692     return query;
693 }
694 
freeEventQuery(IDirect3DQuery9 * query)695 void Renderer9::freeEventQuery(IDirect3DQuery9* query)
696 {
697     if (mEventQueryPool.size() > 1000)
698     {
699         query->Release();
700     }
701     else
702     {
703         mEventQueryPool.push_back(query);
704     }
705 }
706 
createVertexShader(const DWORD * function,size_t length)707 IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
708 {
709     return mVertexShaderCache.create(function, length);
710 }
711 
createPixelShader(const DWORD * function,size_t length)712 IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
713 {
714     return mPixelShaderCache.create(function, length);
715 }
716 
createVertexBuffer(UINT Length,DWORD Usage,IDirect3DVertexBuffer9 ** ppVertexBuffer)717 HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
718 {
719     D3DPOOL Pool = getBufferPool(Usage);
720     return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
721 }
722 
createVertexBuffer()723 VertexBuffer *Renderer9::createVertexBuffer()
724 {
725     return new VertexBuffer9(this);
726 }
727 
createIndexBuffer(UINT Length,DWORD Usage,D3DFORMAT Format,IDirect3DIndexBuffer9 ** ppIndexBuffer)728 HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
729 {
730     D3DPOOL Pool = getBufferPool(Usage);
731     return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
732 }
733 
createIndexBuffer()734 IndexBuffer *Renderer9::createIndexBuffer()
735 {
736     return new IndexBuffer9(this);
737 }
738 
createBufferStorage()739 BufferStorage *Renderer9::createBufferStorage()
740 {
741     return new BufferStorage9();
742 }
743 
createQuery(GLenum type)744 QueryImpl *Renderer9::createQuery(GLenum type)
745 {
746     return new Query9(this, type);
747 }
748 
createFence()749 FenceImpl *Renderer9::createFence()
750 {
751     return new Fence9(this);
752 }
753 
setSamplerState(gl::SamplerType type,int index,const gl::SamplerState & samplerState)754 void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
755 {
756     bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
757     gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
758 
759     if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
760     {
761         int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
762         int d3dSampler = index + d3dSamplerOffset;
763 
764         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
765         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
766 
767         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
768         D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
769         gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
770         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
771         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
772         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
773         if (mSupportsTextureFilterAnisotropy)
774         {
775             mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
776         }
777     }
778 
779     forceSetSamplers[index] = false;
780     appliedSamplers[index] = samplerState;
781 }
782 
setTexture(gl::SamplerType type,int index,gl::Texture * texture)783 void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
784 {
785     int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
786     int d3dSampler = index + d3dSamplerOffset;
787     IDirect3DBaseTexture9 *d3dTexture = NULL;
788     unsigned int serial = 0;
789     bool forceSetTexture = false;
790 
791     unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
792 
793     if (texture)
794     {
795         TextureStorageInterface *texStorage = texture->getNativeTexture();
796         if (texStorage)
797         {
798             TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
799             d3dTexture = storage9->getBaseTexture();
800         }
801         // If we get NULL back from getBaseTexture here, something went wrong
802         // in the texture class and we're unexpectedly missing the d3d texture
803         ASSERT(d3dTexture != NULL);
804 
805         serial = texture->getTextureSerial();
806         forceSetTexture = texture->hasDirtyImages();
807     }
808 
809     if (forceSetTexture || appliedSerials[index] != serial)
810     {
811         mDevice->SetTexture(d3dSampler, d3dTexture);
812     }
813 
814     appliedSerials[index] = serial;
815 }
816 
setRasterizerState(const gl::RasterizerState & rasterState)817 void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
818 {
819     bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
820 
821     if (rasterStateChanged)
822     {
823         // Set the cull mode
824         if (rasterState.cullFace)
825         {
826             mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
827         }
828         else
829         {
830             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
831         }
832 
833         if (rasterState.polygonOffsetFill)
834         {
835             if (mCurDepthSize > 0)
836             {
837                 mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
838 
839                 float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
840                 mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
841             }
842         }
843         else
844         {
845             mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
846             mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
847         }
848 
849         mCurRasterState = rasterState;
850     }
851 
852     mForceSetRasterState = false;
853 }
854 
setBlendState(const gl::BlendState & blendState,const gl::Color & blendColor,unsigned int sampleMask)855 void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
856 {
857     bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
858     bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
859     bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
860 
861     if (blendStateChanged || blendColorChanged)
862     {
863         if (blendState.blend)
864         {
865             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
866 
867             if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
868                 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
869             {
870                 mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
871             }
872             else
873             {
874                 mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
875                                                                          gl::unorm<8>(blendColor.alpha),
876                                                                          gl::unorm<8>(blendColor.alpha),
877                                                                          gl::unorm<8>(blendColor.alpha)));
878             }
879 
880             mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
881             mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
882             mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
883 
884             if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
885                 blendState.destBlendRGB != blendState.destBlendAlpha ||
886                 blendState.blendEquationRGB != blendState.blendEquationAlpha)
887             {
888                 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
889 
890                 mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
891                 mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
892                 mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
893             }
894             else
895             {
896                 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
897             }
898         }
899         else
900         {
901             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
902         }
903 
904         if (blendState.sampleAlphaToCoverage)
905         {
906             FIXME("Sample alpha to coverage is unimplemented.");
907         }
908 
909         // Set the color mask
910         bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
911         // Apparently some ATI cards have a bug where a draw with a zero color
912         // write mask can cause later draws to have incorrect results. Instead,
913         // set a nonzero color write mask but modify the blend state so that no
914         // drawing is done.
915         // http://code.google.com/p/angleproject/issues/detail?id=169
916 
917         DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
918                                                     blendState.colorMaskBlue, blendState.colorMaskAlpha);
919         if (colorMask == 0 && !zeroColorMaskAllowed)
920         {
921             // Enable green channel, but set blending so nothing will be drawn.
922             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
923             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
924 
925             mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
926             mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
927             mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
928         }
929         else
930         {
931             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
932         }
933 
934         mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
935 
936         mCurBlendState = blendState;
937         mCurBlendColor = blendColor;
938     }
939 
940     if (sampleMaskChanged)
941     {
942         // Set the multisample mask
943         mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
944         mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
945 
946         mCurSampleMask = sampleMask;
947     }
948 
949     mForceSetBlendState = false;
950 }
951 
setDepthStencilState(const gl::DepthStencilState & depthStencilState,int stencilRef,int stencilBackRef,bool frontFaceCCW)952 void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
953                                      int stencilBackRef, bool frontFaceCCW)
954 {
955     bool depthStencilStateChanged = mForceSetDepthStencilState ||
956                                     memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
957     bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
958                              stencilBackRef != mCurStencilBackRef;
959     bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
960 
961     if (depthStencilStateChanged)
962     {
963         if (depthStencilState.depthTest)
964         {
965             mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
966             mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
967         }
968         else
969         {
970             mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
971         }
972 
973         mCurDepthStencilState = depthStencilState;
974     }
975 
976     if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
977     {
978         if (depthStencilState.stencilTest && mCurStencilSize > 0)
979         {
980             mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
981             mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
982 
983             // FIXME: Unsupported by D3D9
984             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
985             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
986             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
987             if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
988                 stencilRef != stencilBackRef ||
989                 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
990             {
991                 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
992                 return gl::error(GL_INVALID_OPERATION);
993             }
994 
995             // get the maximum size of the stencil ref
996             unsigned int maxStencil = (1 << mCurStencilSize) - 1;
997 
998             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
999                                     depthStencilState.stencilWritemask);
1000             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1001                                     gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
1002 
1003             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
1004                                     (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
1005             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
1006                                     depthStencilState.stencilMask);
1007 
1008             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1009                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
1010             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1011                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
1012             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1013                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
1014 
1015             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
1016                                     depthStencilState.stencilBackWritemask);
1017             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1018                                     gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
1019 
1020             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
1021                                     (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
1022             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
1023                                     depthStencilState.stencilBackMask);
1024 
1025             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1026                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
1027             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1028                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
1029             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1030                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
1031         }
1032         else
1033         {
1034             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1035         }
1036 
1037         mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
1038 
1039         mCurStencilRef = stencilRef;
1040         mCurStencilBackRef = stencilBackRef;
1041         mCurFrontFaceCCW = frontFaceCCW;
1042     }
1043 
1044     mForceSetDepthStencilState = false;
1045 }
1046 
setScissorRectangle(const gl::Rectangle & scissor,bool enabled)1047 void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
1048 {
1049     bool scissorChanged = mForceSetScissor ||
1050                           memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
1051                           enabled != mScissorEnabled;
1052 
1053     if (scissorChanged)
1054     {
1055         if (enabled)
1056         {
1057             RECT rect;
1058             rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
1059             rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
1060             rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
1061             rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
1062             mDevice->SetScissorRect(&rect);
1063         }
1064 
1065         mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
1066 
1067         mScissorEnabled = enabled;
1068         mCurScissor = scissor;
1069     }
1070 
1071     mForceSetScissor = false;
1072 }
1073 
setViewport(const gl::Rectangle & viewport,float zNear,float zFar,GLenum drawMode,GLenum frontFace,bool ignoreViewport)1074 bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
1075                             bool ignoreViewport)
1076 {
1077     gl::Rectangle actualViewport = viewport;
1078     float actualZNear = gl::clamp01(zNear);
1079     float actualZFar = gl::clamp01(zFar);
1080     if (ignoreViewport)
1081     {
1082         actualViewport.x = 0;
1083         actualViewport.y = 0;
1084         actualViewport.width = mRenderTargetDesc.width;
1085         actualViewport.height = mRenderTargetDesc.height;
1086         actualZNear = 0.0f;
1087         actualZFar = 1.0f;
1088     }
1089 
1090     D3DVIEWPORT9 dxViewport;
1091     dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
1092     dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
1093     dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
1094     dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
1095     dxViewport.MinZ = actualZNear;
1096     dxViewport.MaxZ = actualZFar;
1097 
1098     if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
1099     {
1100         return false;   // Nothing to render
1101     }
1102 
1103     float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
1104 
1105     bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
1106                            actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront;
1107     if (viewportChanged)
1108     {
1109         mDevice->SetViewport(&dxViewport);
1110 
1111         mCurViewport = actualViewport;
1112         mCurNear = actualZNear;
1113         mCurFar = actualZFar;
1114         mCurDepthFront = depthFront;
1115 
1116         dx_VertexConstants vc = {0};
1117         dx_PixelConstants pc = {0};
1118 
1119         vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
1120         vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
1121         vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
1122         vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
1123 
1124         pc.viewCoords[0] = actualViewport.width  * 0.5f;
1125         pc.viewCoords[1] = actualViewport.height * 0.5f;
1126         pc.viewCoords[2] = actualViewport.x + (actualViewport.width  * 0.5f);
1127         pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
1128 
1129         pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
1130         pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
1131         pc.depthFront[2] = depthFront;
1132 
1133         vc.depthRange[0] = actualZNear;
1134         vc.depthRange[1] = actualZFar;
1135         vc.depthRange[2] = actualZFar - actualZNear;
1136 
1137         pc.depthRange[0] = actualZNear;
1138         pc.depthRange[1] = actualZFar;
1139         pc.depthRange[2] = actualZFar - actualZNear;
1140 
1141         if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
1142         {
1143             mVertexConstants = vc;
1144             mDxUniformsDirty = true;
1145         }
1146 
1147         if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
1148         {
1149             mPixelConstants = pc;
1150             mDxUniformsDirty = true;
1151         }
1152     }
1153 
1154     mForceSetViewport = false;
1155     return true;
1156 }
1157 
applyPrimitiveType(GLenum mode,GLsizei count)1158 bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
1159 {
1160     switch (mode)
1161     {
1162       case GL_POINTS:
1163         mPrimitiveType = D3DPT_POINTLIST;
1164         mPrimitiveCount = count;
1165         break;
1166       case GL_LINES:
1167         mPrimitiveType = D3DPT_LINELIST;
1168         mPrimitiveCount = count / 2;
1169         break;
1170       case GL_LINE_LOOP:
1171         mPrimitiveType = D3DPT_LINESTRIP;
1172         mPrimitiveCount = count - 1;   // D3D doesn't support line loops, so we draw the last line separately
1173         break;
1174       case GL_LINE_STRIP:
1175         mPrimitiveType = D3DPT_LINESTRIP;
1176         mPrimitiveCount = count - 1;
1177         break;
1178       case GL_TRIANGLES:
1179         mPrimitiveType = D3DPT_TRIANGLELIST;
1180         mPrimitiveCount = count / 3;
1181         break;
1182       case GL_TRIANGLE_STRIP:
1183         mPrimitiveType = D3DPT_TRIANGLESTRIP;
1184         mPrimitiveCount = count - 2;
1185         break;
1186       case GL_TRIANGLE_FAN:
1187         mPrimitiveType = D3DPT_TRIANGLEFAN;
1188         mPrimitiveCount = count - 2;
1189         break;
1190       default:
1191         return gl::error(GL_INVALID_ENUM, false);
1192     }
1193 
1194     return mPrimitiveCount > 0;
1195 }
1196 
1197 
getNullColorbuffer(gl::Renderbuffer * depthbuffer)1198 gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
1199 {
1200     if (!depthbuffer)
1201     {
1202         ERR("Unexpected null depthbuffer for depth-only FBO.");
1203         return NULL;
1204     }
1205 
1206     GLsizei width  = depthbuffer->getWidth();
1207     GLsizei height = depthbuffer->getHeight();
1208 
1209     // search cached nullcolorbuffers
1210     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
1211     {
1212         if (mNullColorbufferCache[i].buffer != NULL &&
1213             mNullColorbufferCache[i].width == width &&
1214             mNullColorbufferCache[i].height == height)
1215         {
1216             mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
1217             return mNullColorbufferCache[i].buffer;
1218         }
1219     }
1220 
1221     gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
1222 
1223     // add nullbuffer to the cache
1224     NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
1225     for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
1226     {
1227         if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
1228         {
1229             oldest = &mNullColorbufferCache[i];
1230         }
1231     }
1232 
1233     delete oldest->buffer;
1234     oldest->buffer = nullbuffer;
1235     oldest->lruCount = ++mMaxNullColorbufferLRU;
1236     oldest->width = width;
1237     oldest->height = height;
1238 
1239     return nullbuffer;
1240 }
1241 
applyRenderTarget(gl::Framebuffer * framebuffer)1242 bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
1243 {
1244     // if there is no color attachment we must synthesize a NULL colorattachment
1245     // to keep the D3D runtime happy.  This should only be possible if depth texturing.
1246     gl::Renderbuffer *renderbufferObject = NULL;
1247     if (framebuffer->getColorbufferType(0) != GL_NONE)
1248     {
1249         renderbufferObject = framebuffer->getColorbuffer(0);
1250     }
1251     else
1252     {
1253         renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
1254     }
1255     if (!renderbufferObject)
1256     {
1257         ERR("unable to locate renderbuffer for FBO.");
1258         return false;
1259     }
1260 
1261     bool renderTargetChanged = false;
1262     unsigned int renderTargetSerial = renderbufferObject->getSerial();
1263     if (renderTargetSerial != mAppliedRenderTargetSerial)
1264     {
1265         // Apply the render target on the device
1266         IDirect3DSurface9 *renderTargetSurface = NULL;
1267 
1268         RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
1269         if (renderTarget)
1270         {
1271             renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
1272         }
1273 
1274         if (!renderTargetSurface)
1275         {
1276             ERR("render target pointer unexpectedly null.");
1277             return false;   // Context must be lost
1278         }
1279 
1280         mDevice->SetRenderTarget(0, renderTargetSurface);
1281         renderTargetSurface->Release();
1282 
1283         mAppliedRenderTargetSerial = renderTargetSerial;
1284         renderTargetChanged = true;
1285     }
1286 
1287     gl::Renderbuffer *depthStencil = NULL;
1288     unsigned int depthbufferSerial = 0;
1289     unsigned int stencilbufferSerial = 0;
1290     if (framebuffer->getDepthbufferType() != GL_NONE)
1291     {
1292         depthStencil = framebuffer->getDepthbuffer();
1293         if (!depthStencil)
1294         {
1295             ERR("Depth stencil pointer unexpectedly null.");
1296             return false;
1297         }
1298 
1299         depthbufferSerial = depthStencil->getSerial();
1300     }
1301     else if (framebuffer->getStencilbufferType() != GL_NONE)
1302     {
1303         depthStencil = framebuffer->getStencilbuffer();
1304         if (!depthStencil)
1305         {
1306             ERR("Depth stencil pointer unexpectedly null.");
1307             return false;
1308         }
1309 
1310         stencilbufferSerial = depthStencil->getSerial();
1311     }
1312 
1313     if (depthbufferSerial != mAppliedDepthbufferSerial ||
1314         stencilbufferSerial != mAppliedStencilbufferSerial ||
1315         !mDepthStencilInitialized)
1316     {
1317         unsigned int depthSize = 0;
1318         unsigned int stencilSize = 0;
1319 
1320         // Apply the depth stencil on the device
1321         if (depthStencil)
1322         {
1323             IDirect3DSurface9 *depthStencilSurface = NULL;
1324             RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
1325 
1326             if (depthStencilRenderTarget)
1327             {
1328                 depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
1329             }
1330 
1331             if (!depthStencilSurface)
1332             {
1333                 ERR("depth stencil pointer unexpectedly null.");
1334                 return false;   // Context must be lost
1335             }
1336 
1337             mDevice->SetDepthStencilSurface(depthStencilSurface);
1338             depthStencilSurface->Release();
1339 
1340             depthSize = depthStencil->getDepthSize();
1341             stencilSize = depthStencil->getStencilSize();
1342         }
1343         else
1344         {
1345             mDevice->SetDepthStencilSurface(NULL);
1346         }
1347 
1348         if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
1349         {
1350             mCurDepthSize = depthSize;
1351             mForceSetRasterState = true;
1352         }
1353 
1354         if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
1355         {
1356             mCurStencilSize = stencilSize;
1357             mForceSetDepthStencilState = true;
1358         }
1359 
1360         mAppliedDepthbufferSerial = depthbufferSerial;
1361         mAppliedStencilbufferSerial = stencilbufferSerial;
1362         mDepthStencilInitialized = true;
1363     }
1364 
1365     if (renderTargetChanged || !mRenderTargetDescInitialized)
1366     {
1367         mForceSetScissor = true;
1368         mForceSetViewport = true;
1369 
1370         mRenderTargetDesc.width = renderbufferObject->getWidth();
1371         mRenderTargetDesc.height = renderbufferObject->getHeight();
1372         mRenderTargetDesc.format = renderbufferObject->getActualFormat();
1373         mRenderTargetDescInitialized = true;
1374     }
1375 
1376     return true;
1377 }
1378 
applyVertexBuffer(gl::ProgramBinary * programBinary,gl::VertexAttribute vertexAttributes[],GLint first,GLsizei count,GLsizei instances)1379 GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
1380 {
1381     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
1382     GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
1383     if (err != GL_NO_ERROR)
1384     {
1385         return err;
1386     }
1387 
1388     return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
1389 }
1390 
1391 // Applies the indices and element array bindings to the Direct3D 9 device
applyIndexBuffer(const GLvoid * indices,gl::Buffer * elementArrayBuffer,GLsizei count,GLenum mode,GLenum type,TranslatedIndexData * indexInfo)1392 GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
1393 {
1394     GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
1395 
1396     if (err == GL_NO_ERROR)
1397     {
1398         // Directly binding the storage buffer is not supported for d3d9
1399         ASSERT(indexInfo->storage == NULL);
1400 
1401         if (indexInfo->serial != mAppliedIBSerial)
1402         {
1403             IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
1404 
1405             mDevice->SetIndices(indexBuffer->getBuffer());
1406             mAppliedIBSerial = indexInfo->serial;
1407         }
1408     }
1409 
1410     return err;
1411 }
1412 
drawArrays(GLenum mode,GLsizei count,GLsizei instances)1413 void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
1414 {
1415     startScene();
1416 
1417     if (mode == GL_LINE_LOOP)
1418     {
1419         drawLineLoop(count, GL_NONE, NULL, 0, NULL);
1420     }
1421     else if (instances > 0)
1422     {
1423         StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
1424         if (countingIB)
1425         {
1426             if (mAppliedIBSerial != countingIB->getSerial())
1427             {
1428                 IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
1429 
1430                 mDevice->SetIndices(indexBuffer->getBuffer());
1431                 mAppliedIBSerial = countingIB->getSerial();
1432             }
1433 
1434             for (int i = 0; i < mRepeatDraw; i++)
1435             {
1436                 mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
1437             }
1438         }
1439         else
1440         {
1441             ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
1442             return gl::error(GL_OUT_OF_MEMORY);
1443         }
1444     }
1445     else   // Regular case
1446     {
1447         mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
1448     }
1449 }
1450 
drawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,gl::Buffer * elementArrayBuffer,const TranslatedIndexData & indexInfo,GLsizei)1451 void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
1452 {
1453     startScene();
1454 
1455     if (mode == GL_POINTS)
1456     {
1457         drawIndexedPoints(count, type, indices, elementArrayBuffer);
1458     }
1459     else if (mode == GL_LINE_LOOP)
1460     {
1461         drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
1462     }
1463     else
1464     {
1465         for (int i = 0; i < mRepeatDraw; i++)
1466         {
1467             GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
1468             mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
1469         }
1470     }
1471 }
1472 
drawLineLoop(GLsizei count,GLenum type,const GLvoid * indices,int minIndex,gl::Buffer * elementArrayBuffer)1473 void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
1474 {
1475     // Get the raw indices for an indexed draw
1476     if (type != GL_NONE && elementArrayBuffer)
1477     {
1478         gl::Buffer *indexBuffer = elementArrayBuffer;
1479         BufferStorage *storage = indexBuffer->getStorage();
1480         intptr_t offset = reinterpret_cast<intptr_t>(indices);
1481         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1482     }
1483 
1484     unsigned int startIndex = 0;
1485 
1486     if (get32BitIndexSupport())
1487     {
1488         if (!mLineLoopIB)
1489         {
1490             mLineLoopIB = new StreamingIndexBufferInterface(this);
1491             if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
1492             {
1493                 delete mLineLoopIB;
1494                 mLineLoopIB = NULL;
1495 
1496                 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
1497                 return gl::error(GL_OUT_OF_MEMORY);
1498             }
1499         }
1500 
1501         if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
1502         {
1503             ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
1504             return gl::error(GL_OUT_OF_MEMORY);
1505         }
1506 
1507         // Checked by Renderer9::applyPrimitiveType
1508         ASSERT(count >= 0);
1509 
1510         const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
1511         if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
1512         {
1513             ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
1514             return gl::error(GL_OUT_OF_MEMORY);
1515         }
1516 
1517         void* mappedMemory = NULL;
1518         unsigned int offset = 0;
1519         if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1520         {
1521             ERR("Could not map index buffer for GL_LINE_LOOP.");
1522             return gl::error(GL_OUT_OF_MEMORY);
1523         }
1524 
1525         startIndex = static_cast<unsigned int>(offset) / 4;
1526         unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
1527 
1528         switch (type)
1529         {
1530           case GL_NONE:   // Non-indexed draw
1531             for (int i = 0; i < count; i++)
1532             {
1533                 data[i] = i;
1534             }
1535             data[count] = 0;
1536             break;
1537           case GL_UNSIGNED_BYTE:
1538             for (int i = 0; i < count; i++)
1539             {
1540                 data[i] = static_cast<const GLubyte*>(indices)[i];
1541             }
1542             data[count] = static_cast<const GLubyte*>(indices)[0];
1543             break;
1544           case GL_UNSIGNED_SHORT:
1545             for (int i = 0; i < count; i++)
1546             {
1547                 data[i] = static_cast<const GLushort*>(indices)[i];
1548             }
1549             data[count] = static_cast<const GLushort*>(indices)[0];
1550             break;
1551           case GL_UNSIGNED_INT:
1552             for (int i = 0; i < count; i++)
1553             {
1554                 data[i] = static_cast<const GLuint*>(indices)[i];
1555             }
1556             data[count] = static_cast<const GLuint*>(indices)[0];
1557             break;
1558           default: UNREACHABLE();
1559         }
1560 
1561         if (!mLineLoopIB->unmapBuffer())
1562         {
1563             ERR("Could not unmap index buffer for GL_LINE_LOOP.");
1564             return gl::error(GL_OUT_OF_MEMORY);
1565         }
1566     }
1567     else
1568     {
1569         if (!mLineLoopIB)
1570         {
1571             mLineLoopIB = new StreamingIndexBufferInterface(this);
1572             if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
1573             {
1574                 delete mLineLoopIB;
1575                 mLineLoopIB = NULL;
1576 
1577                 ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
1578                 return gl::error(GL_OUT_OF_MEMORY);
1579             }
1580         }
1581 
1582         // Checked by Renderer9::applyPrimitiveType
1583         ASSERT(count >= 0);
1584 
1585         if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
1586         {
1587             ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
1588             return gl::error(GL_OUT_OF_MEMORY);
1589         }
1590 
1591         const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
1592         if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
1593         {
1594             ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
1595             return gl::error(GL_OUT_OF_MEMORY);
1596         }
1597 
1598         void* mappedMemory = NULL;
1599         unsigned int offset;
1600         if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
1601         {
1602             ERR("Could not map index buffer for GL_LINE_LOOP.");
1603             return gl::error(GL_OUT_OF_MEMORY);
1604         }
1605 
1606         startIndex = static_cast<unsigned int>(offset) / 2;
1607         unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
1608 
1609         switch (type)
1610         {
1611           case GL_NONE:   // Non-indexed draw
1612             for (int i = 0; i < count; i++)
1613             {
1614                 data[i] = i;
1615             }
1616             data[count] = 0;
1617             break;
1618           case GL_UNSIGNED_BYTE:
1619             for (int i = 0; i < count; i++)
1620             {
1621                 data[i] = static_cast<const GLubyte*>(indices)[i];
1622             }
1623             data[count] = static_cast<const GLubyte*>(indices)[0];
1624             break;
1625           case GL_UNSIGNED_SHORT:
1626             for (int i = 0; i < count; i++)
1627             {
1628                 data[i] = static_cast<const GLushort*>(indices)[i];
1629             }
1630             data[count] = static_cast<const GLushort*>(indices)[0];
1631             break;
1632           case GL_UNSIGNED_INT:
1633             for (int i = 0; i < count; i++)
1634             {
1635                 data[i] = static_cast<const GLuint*>(indices)[i];
1636             }
1637             data[count] = static_cast<const GLuint*>(indices)[0];
1638             break;
1639           default: UNREACHABLE();
1640         }
1641 
1642         if (!mLineLoopIB->unmapBuffer())
1643         {
1644             ERR("Could not unmap index buffer for GL_LINE_LOOP.");
1645             return gl::error(GL_OUT_OF_MEMORY);
1646         }
1647     }
1648 
1649     if (mAppliedIBSerial != mLineLoopIB->getSerial())
1650     {
1651         IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
1652 
1653         mDevice->SetIndices(indexBuffer->getBuffer());
1654         mAppliedIBSerial = mLineLoopIB->getSerial();
1655     }
1656 
1657     mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
1658 }
1659 
1660 template <typename T>
drawPoints(IDirect3DDevice9 * device,GLsizei count,const GLvoid * indices)1661 static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices)
1662 {
1663     for (int i = 0; i < count; i++)
1664     {
1665         unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]);
1666         device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
1667     }
1668 }
1669 
drawIndexedPoints(GLsizei count,GLenum type,const GLvoid * indices,gl::Buffer * elementArrayBuffer)1670 void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
1671 {
1672     // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
1673     // for each individual point. This call is not expected to happen often.
1674 
1675     if (elementArrayBuffer)
1676     {
1677         BufferStorage *storage = elementArrayBuffer->getStorage();
1678         intptr_t offset = reinterpret_cast<intptr_t>(indices);
1679         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
1680     }
1681 
1682     switch (type)
1683     {
1684         case GL_UNSIGNED_BYTE:  drawPoints<GLubyte>(mDevice, count, indices);  break;
1685         case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices); break;
1686         case GL_UNSIGNED_INT:   drawPoints<GLuint>(mDevice, count, indices);   break;
1687         default: UNREACHABLE();
1688     }
1689 }
1690 
applyShaders(gl::ProgramBinary * programBinary)1691 void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
1692 {
1693     unsigned int programBinarySerial = programBinary->getSerial();
1694     if (programBinarySerial != mAppliedProgramBinarySerial)
1695     {
1696         ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
1697         ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
1698 
1699         IDirect3DVertexShader9 *vertexShader = NULL;
1700         if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
1701 
1702         IDirect3DPixelShader9 *pixelShader = NULL;
1703         if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
1704 
1705         mDevice->SetPixelShader(pixelShader);
1706         mDevice->SetVertexShader(vertexShader);
1707         programBinary->dirtyAllUniforms();
1708         mDxUniformsDirty = true;
1709 
1710         mAppliedProgramBinarySerial = programBinarySerial;
1711     }
1712 }
1713 
applyUniforms(gl::ProgramBinary * programBinary,gl::UniformArray * uniformArray)1714 void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
1715 {
1716     for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
1717     {
1718         gl::Uniform *targetUniform = *ub;
1719 
1720         if (targetUniform->dirty)
1721         {
1722             GLfloat *f = (GLfloat*)targetUniform->data;
1723             GLint *i = (GLint*)targetUniform->data;
1724 
1725             switch (targetUniform->type)
1726             {
1727               case GL_SAMPLER_2D:
1728               case GL_SAMPLER_CUBE:
1729                 break;
1730               case GL_BOOL:
1731               case GL_BOOL_VEC2:
1732               case GL_BOOL_VEC3:
1733               case GL_BOOL_VEC4:
1734                 applyUniformnbv(targetUniform, i);
1735                 break;
1736               case GL_FLOAT:
1737               case GL_FLOAT_VEC2:
1738               case GL_FLOAT_VEC3:
1739               case GL_FLOAT_VEC4:
1740               case GL_FLOAT_MAT2:
1741               case GL_FLOAT_MAT3:
1742               case GL_FLOAT_MAT4:
1743                 applyUniformnfv(targetUniform, f);
1744                 break;
1745               case GL_INT:
1746               case GL_INT_VEC2:
1747               case GL_INT_VEC3:
1748               case GL_INT_VEC4:
1749                 applyUniformniv(targetUniform, i);
1750                 break;
1751               default:
1752                 UNREACHABLE();
1753             }
1754 
1755             targetUniform->dirty = false;
1756         }
1757     }
1758 
1759     // Driver uniforms
1760     if (mDxUniformsDirty)
1761     {
1762         mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
1763         mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
1764         mDxUniformsDirty = false;
1765     }
1766 }
1767 
applyUniformnfv(gl::Uniform * targetUniform,const GLfloat * v)1768 void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
1769 {
1770     if (targetUniform->psRegisterIndex >= 0)
1771     {
1772         mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
1773     }
1774 
1775     if (targetUniform->vsRegisterIndex >= 0)
1776     {
1777         mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
1778     }
1779 }
1780 
applyUniformniv(gl::Uniform * targetUniform,const GLint * v)1781 void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
1782 {
1783     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
1784     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
1785 
1786     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
1787     {
1788         vector[i][0] = (GLfloat)v[4 * i + 0];
1789         vector[i][1] = (GLfloat)v[4 * i + 1];
1790         vector[i][2] = (GLfloat)v[4 * i + 2];
1791         vector[i][3] = (GLfloat)v[4 * i + 3];
1792     }
1793 
1794     applyUniformnfv(targetUniform, (GLfloat*)vector);
1795 }
1796 
applyUniformnbv(gl::Uniform * targetUniform,const GLint * v)1797 void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
1798 {
1799     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
1800     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
1801 
1802     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
1803     {
1804         vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
1805         vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
1806         vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
1807         vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
1808     }
1809 
1810     applyUniformnfv(targetUniform, (GLfloat*)vector);
1811 }
1812 
clear(const gl::ClearParameters & clearParams,gl::Framebuffer * frameBuffer)1813 void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
1814 {
1815     D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
1816                                    gl::unorm<8>(clearParams.colorClearValue.red),
1817                                    gl::unorm<8>(clearParams.colorClearValue.green),
1818                                    gl::unorm<8>(clearParams.colorClearValue.blue));
1819     float depth = gl::clamp01(clearParams.depthClearValue);
1820     int stencil = clearParams.stencilClearValue & 0x000000FF;
1821 
1822     unsigned int stencilUnmasked = 0x0;
1823     if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
1824     {
1825         unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
1826         stencilUnmasked = (0x1 << stencilSize) - 1;
1827     }
1828 
1829     bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
1830 
1831     const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
1832                                         (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
1833     const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
1834                                       !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
1835                                         clearParams.colorMaskBlue && alphaUnmasked);
1836 
1837     if (needMaskedColorClear || needMaskedStencilClear)
1838     {
1839         // State which is altered in all paths from this point to the clear call is saved.
1840         // State which is altered in only some paths will be flagged dirty in the case that
1841         //  that path is taken.
1842         HRESULT hr;
1843         if (mMaskedClearSavedState == NULL)
1844         {
1845             hr = mDevice->BeginStateBlock();
1846             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
1847 
1848             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1849             mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1850             mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
1851             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1852             mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1853             mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1854             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1855             mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1856             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1857             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1858             mDevice->SetPixelShader(NULL);
1859             mDevice->SetVertexShader(NULL);
1860             mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1861             mDevice->SetStreamSource(0, NULL, 0, 0);
1862             mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1863             mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1864             mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
1865             mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
1866             mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
1867             mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
1868             mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
1869 
1870             for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1871             {
1872                 mDevice->SetStreamSourceFreq(i, 1);
1873             }
1874 
1875             hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
1876             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
1877         }
1878 
1879         ASSERT(mMaskedClearSavedState != NULL);
1880 
1881         if (mMaskedClearSavedState != NULL)
1882         {
1883             hr = mMaskedClearSavedState->Capture();
1884             ASSERT(SUCCEEDED(hr));
1885         }
1886 
1887         mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
1888         mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1889         mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
1890         mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1891         mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
1892         mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
1893         mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
1894         mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
1895 
1896         if (clearParams.mask & GL_COLOR_BUFFER_BIT)
1897         {
1898             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
1899                                     gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
1900                                                               clearParams.colorMaskGreen,
1901                                                               clearParams.colorMaskBlue,
1902                                                               clearParams.colorMaskAlpha));
1903         }
1904         else
1905         {
1906             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1907         }
1908 
1909         if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
1910         {
1911             mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1912             mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
1913             mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
1914             mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
1915             mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
1916             mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
1917             mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
1918             mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
1919         }
1920         else
1921         {
1922             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1923         }
1924 
1925         mDevice->SetPixelShader(NULL);
1926         mDevice->SetVertexShader(NULL);
1927         mDevice->SetFVF(D3DFVF_XYZRHW);
1928         mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1929         mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1930         mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
1931         mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
1932         mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
1933         mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
1934         mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
1935 
1936         for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1937         {
1938             mDevice->SetStreamSourceFreq(i, 1);
1939         }
1940 
1941         float quad[4][4];   // A quadrilateral covering the target, aligned to match the edges
1942         quad[0][0] = -0.5f;
1943         quad[0][1] = mRenderTargetDesc.height - 0.5f;
1944         quad[0][2] = 0.0f;
1945         quad[0][3] = 1.0f;
1946 
1947         quad[1][0] = mRenderTargetDesc.width - 0.5f;
1948         quad[1][1] = mRenderTargetDesc.height - 0.5f;
1949         quad[1][2] = 0.0f;
1950         quad[1][3] = 1.0f;
1951 
1952         quad[2][0] = -0.5f;
1953         quad[2][1] = -0.5f;
1954         quad[2][2] = 0.0f;
1955         quad[2][3] = 1.0f;
1956 
1957         quad[3][0] = mRenderTargetDesc.width - 0.5f;
1958         quad[3][1] = -0.5f;
1959         quad[3][2] = 0.0f;
1960         quad[3][3] = 1.0f;
1961 
1962         startScene();
1963         mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
1964 
1965         if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
1966         {
1967             mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
1968             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1969             mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
1970         }
1971 
1972         if (mMaskedClearSavedState != NULL)
1973         {
1974             mMaskedClearSavedState->Apply();
1975         }
1976     }
1977     else if (clearParams.mask)
1978     {
1979         DWORD dxClearFlags = 0;
1980         if (clearParams.mask & GL_COLOR_BUFFER_BIT)
1981         {
1982             dxClearFlags |= D3DCLEAR_TARGET;
1983         }
1984         if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
1985         {
1986             dxClearFlags |= D3DCLEAR_ZBUFFER;
1987         }
1988         if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
1989         {
1990             dxClearFlags |= D3DCLEAR_STENCIL;
1991         }
1992 
1993         mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
1994     }
1995 }
1996 
markAllStateDirty()1997 void Renderer9::markAllStateDirty()
1998 {
1999     mAppliedRenderTargetSerial = 0;
2000     mAppliedDepthbufferSerial = 0;
2001     mAppliedStencilbufferSerial = 0;
2002     mDepthStencilInitialized = false;
2003     mRenderTargetDescInitialized = false;
2004 
2005     mForceSetDepthStencilState = true;
2006     mForceSetRasterState = true;
2007     mForceSetScissor = true;
2008     mForceSetViewport = true;
2009     mForceSetBlendState = true;
2010 
2011     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
2012     {
2013         mForceSetVertexSamplerStates[i] = true;
2014         mCurVertexTextureSerials[i] = 0;
2015     }
2016     for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
2017     {
2018         mForceSetPixelSamplerStates[i] = true;
2019         mCurPixelTextureSerials[i] = 0;
2020     }
2021 
2022     mAppliedIBSerial = 0;
2023     mAppliedProgramBinarySerial = 0;
2024     mDxUniformsDirty = true;
2025 
2026     mVertexDeclarationCache.markStateDirty();
2027 }
2028 
releaseDeviceResources()2029 void Renderer9::releaseDeviceResources()
2030 {
2031     while (!mEventQueryPool.empty())
2032     {
2033         mEventQueryPool.back()->Release();
2034         mEventQueryPool.pop_back();
2035     }
2036 
2037     SafeRelease(mMaskedClearSavedState);
2038 
2039     mVertexShaderCache.clear();
2040     mPixelShaderCache.clear();
2041 
2042     SafeDelete(mBlit);
2043     SafeDelete(mVertexDataManager);
2044     SafeDelete(mIndexDataManager);
2045     SafeDelete(mLineLoopIB);
2046 
2047     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
2048     {
2049         SafeDelete(mNullColorbufferCache[i].buffer);
2050     }
2051 
2052 }
2053 
2054 
notifyDeviceLost()2055 void Renderer9::notifyDeviceLost()
2056 {
2057     mDeviceLost = true;
2058     mDisplay->notifyDeviceLost();
2059 }
2060 
isDeviceLost()2061 bool Renderer9::isDeviceLost()
2062 {
2063     return mDeviceLost;
2064 }
2065 
2066 // set notify to true to broadcast a message to all contexts of the device loss
testDeviceLost(bool notify)2067 bool Renderer9::testDeviceLost(bool notify)
2068 {
2069     HRESULT status = getDeviceStatusCode();
2070     bool isLost = (FAILED(status) || d3d9::isDeviceLostError(status));
2071 
2072     if (isLost)
2073     {
2074         // ensure we note the device loss --
2075         // we'll probably get this done again by notifyDeviceLost
2076         // but best to remember it!
2077         // Note that we don't want to clear the device loss status here
2078         // -- this needs to be done by resetDevice
2079         mDeviceLost = true;
2080         if (notify)
2081         {
2082             notifyDeviceLost();
2083         }
2084     }
2085 
2086     return isLost;
2087 }
2088 
getDeviceStatusCode()2089 HRESULT Renderer9::getDeviceStatusCode()
2090 {
2091     HRESULT status = D3D_OK;
2092 
2093     if (mDeviceEx)
2094     {
2095         status = mDeviceEx->CheckDeviceState(NULL);
2096     }
2097     else if (mDevice)
2098     {
2099         status = mDevice->TestCooperativeLevel();
2100     }
2101 
2102     return status;
2103 }
2104 
testDeviceResettable()2105 bool Renderer9::testDeviceResettable()
2106 {
2107     // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
2108     // DEVICEREMOVED indicates the device has been stopped and must be recreated
2109     switch (getDeviceStatusCode())
2110     {
2111       case D3DERR_DEVICENOTRESET:
2112       case D3DERR_DEVICEHUNG:
2113         return true;
2114       case D3DERR_DEVICELOST:
2115         return (mDeviceEx != NULL);
2116       case D3DERR_DEVICEREMOVED:
2117         ASSERT(mDeviceEx != NULL);
2118         return isRemovedDeviceResettable();
2119       default:
2120         return false;
2121     }
2122 }
2123 
resetDevice()2124 bool Renderer9::resetDevice()
2125 {
2126     releaseDeviceResources();
2127 
2128     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
2129 
2130     HRESULT result = D3D_OK;
2131     bool lost = testDeviceLost(false);
2132     bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
2133 
2134     // Device Removed is a feature which is only present with D3D9Ex
2135     ASSERT(mDeviceEx != NULL || !removedDevice);
2136 
2137     for (int attempts = 3; lost && attempts > 0; attempts--)
2138     {
2139         if (removedDevice)
2140         {
2141             // Device removed, which may trigger on driver reinstallation,
2142             // may cause a longer wait other reset attempts before the
2143             // system is ready to handle creating a new device.
2144             Sleep(800);
2145             lost = !resetRemovedDevice();
2146         }
2147         else if (mDeviceEx)
2148         {
2149             Sleep(500);   // Give the graphics driver some CPU time
2150             result = mDeviceEx->ResetEx(&presentParameters, NULL);
2151             lost = testDeviceLost(false);
2152         }
2153         else
2154         {
2155             result = mDevice->TestCooperativeLevel();
2156             while (result == D3DERR_DEVICELOST)
2157             {
2158                 Sleep(100);   // Give the graphics driver some CPU time
2159                 result = mDevice->TestCooperativeLevel();
2160             }
2161 
2162             if (result == D3DERR_DEVICENOTRESET)
2163             {
2164                 result = mDevice->Reset(&presentParameters);
2165             }
2166             lost = testDeviceLost(false);
2167         }
2168     }
2169 
2170     if (FAILED(result))
2171     {
2172         ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
2173         return false;
2174     }
2175 
2176     if (removedDevice && lost)
2177     {
2178         ERR("Device lost reset failed multiple times");
2179         return false;
2180     }
2181 
2182     // If the device was removed, we already finished re-initialization in resetRemovedDevice
2183     if (!removedDevice)
2184     {
2185         // reset device defaults
2186         initializeDevice();
2187     }
2188 
2189     mDeviceLost = false;
2190 
2191     return true;
2192 }
2193 
isRemovedDeviceResettable() const2194 bool Renderer9::isRemovedDeviceResettable() const
2195 {
2196     bool success = false;
2197 
2198 #ifdef ANGLE_ENABLE_D3D9EX
2199     IDirect3D9Ex *d3d9Ex = NULL;
2200     typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
2201     Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
2202 
2203     if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
2204     {
2205         D3DCAPS9 deviceCaps;
2206         HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
2207         success = SUCCEEDED(result);
2208     }
2209 
2210     SafeRelease(d3d9Ex);
2211 #else
2212     ASSERT(UNREACHABLE());
2213 #endif
2214 
2215     return success;
2216 }
2217 
resetRemovedDevice()2218 bool Renderer9::resetRemovedDevice()
2219 {
2220     // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
2221     // The hardware adapter has been removed. Application must destroy the device, do enumeration of
2222     // adapters and create another Direct3D device. If application continues rendering without
2223     // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
2224     deinitialize();
2225     return (initialize() == EGL_SUCCESS);
2226 }
2227 
getAdapterVendor() const2228 DWORD Renderer9::getAdapterVendor() const
2229 {
2230     return mAdapterIdentifier.VendorId;
2231 }
2232 
getRendererDescription() const2233 std::string Renderer9::getRendererDescription() const
2234 {
2235     std::ostringstream rendererString;
2236 
2237     rendererString << mAdapterIdentifier.Description;
2238     if (getShareHandleSupport())
2239     {
2240         rendererString << " Direct3D9Ex";
2241     }
2242     else
2243     {
2244         rendererString << " Direct3D9";
2245     }
2246 
2247     rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
2248     rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
2249 
2250     return rendererString.str();
2251 }
2252 
getAdapterIdentifier() const2253 GUID Renderer9::getAdapterIdentifier() const
2254 {
2255     return mAdapterIdentifier.DeviceIdentifier;
2256 }
2257 
getMultiSampleSupport(D3DFORMAT format,bool * multiSampleArray)2258 void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
2259 {
2260     for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
2261     {
2262         HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
2263                                                            TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
2264 
2265         multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
2266     }
2267 }
2268 
getBGRATextureSupport() const2269 bool Renderer9::getBGRATextureSupport() const
2270 {
2271     // DirectX 9 always supports BGRA
2272     return true;
2273 }
2274 
getDXT1TextureSupport()2275 bool Renderer9::getDXT1TextureSupport()
2276 {
2277     return mDXT1TextureSupport;
2278 }
2279 
getDXT3TextureSupport()2280 bool Renderer9::getDXT3TextureSupport()
2281 {
2282     return mDXT3TextureSupport;
2283 }
2284 
getDXT5TextureSupport()2285 bool Renderer9::getDXT5TextureSupport()
2286 {
2287     return mDXT5TextureSupport;
2288 }
2289 
getDepthTextureSupport() const2290 bool Renderer9::getDepthTextureSupport() const
2291 {
2292     return mDepthTextureSupport;
2293 }
2294 
getFloat32TextureSupport(bool * filtering,bool * renderable)2295 bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
2296 {
2297     *filtering = mFloat32FilterSupport;
2298     *renderable = mFloat32RenderSupport;
2299     return mFloat32TextureSupport;
2300 }
2301 
getFloat16TextureSupport(bool * filtering,bool * renderable)2302 bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
2303 {
2304     *filtering = mFloat16FilterSupport;
2305     *renderable = mFloat16RenderSupport;
2306     return mFloat16TextureSupport;
2307 }
2308 
getLuminanceTextureSupport()2309 bool Renderer9::getLuminanceTextureSupport()
2310 {
2311     return mLuminanceTextureSupport;
2312 }
2313 
getLuminanceAlphaTextureSupport()2314 bool Renderer9::getLuminanceAlphaTextureSupport()
2315 {
2316     return mLuminanceAlphaTextureSupport;
2317 }
2318 
getTextureFilterAnisotropySupport() const2319 bool Renderer9::getTextureFilterAnisotropySupport() const
2320 {
2321     return mSupportsTextureFilterAnisotropy;
2322 }
2323 
getTextureMaxAnisotropy() const2324 float Renderer9::getTextureMaxAnisotropy() const
2325 {
2326     if (mSupportsTextureFilterAnisotropy)
2327     {
2328         return static_cast<float>(mDeviceCaps.MaxAnisotropy);
2329     }
2330     return 1.0f;
2331 }
2332 
getEventQuerySupport()2333 bool Renderer9::getEventQuerySupport()
2334 {
2335     return mEventQuerySupport;
2336 }
2337 
getMaxVertexTextureImageUnits() const2338 unsigned int Renderer9::getMaxVertexTextureImageUnits() const
2339 {
2340     META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
2341     return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
2342 }
2343 
getMaxCombinedTextureImageUnits() const2344 unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
2345 {
2346     return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
2347 }
2348 
getReservedVertexUniformVectors() const2349 unsigned int Renderer9::getReservedVertexUniformVectors() const
2350 {
2351     return 2;   // dx_ViewAdjust and dx_DepthRange.
2352 }
2353 
getReservedFragmentUniformVectors() const2354 unsigned int Renderer9::getReservedFragmentUniformVectors() const
2355 {
2356     return 3;   // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
2357 }
2358 
getMaxVertexUniformVectors() const2359 unsigned int Renderer9::getMaxVertexUniformVectors() const
2360 {
2361     return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
2362 }
2363 
getMaxFragmentUniformVectors() const2364 unsigned int Renderer9::getMaxFragmentUniformVectors() const
2365 {
2366     const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
2367 
2368     return maxPixelConstantVectors - getReservedFragmentUniformVectors();
2369 }
2370 
getMaxVaryingVectors() const2371 unsigned int Renderer9::getMaxVaryingVectors() const
2372 {
2373     return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
2374 }
2375 
getNonPower2TextureSupport() const2376 bool Renderer9::getNonPower2TextureSupport() const
2377 {
2378     return mSupportsNonPower2Textures;
2379 }
2380 
getOcclusionQuerySupport() const2381 bool Renderer9::getOcclusionQuerySupport() const
2382 {
2383     return mOcclusionQuerySupport;
2384 }
2385 
getInstancingSupport() const2386 bool Renderer9::getInstancingSupport() const
2387 {
2388     return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
2389 }
2390 
getShareHandleSupport() const2391 bool Renderer9::getShareHandleSupport() const
2392 {
2393     // PIX doesn't seem to support using share handles, so disable them.
2394     return (mD3d9Ex != NULL) && !gl::perfActive();
2395 }
2396 
getDerivativeInstructionSupport() const2397 bool Renderer9::getDerivativeInstructionSupport() const
2398 {
2399     return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
2400 }
2401 
getPostSubBufferSupport() const2402 bool Renderer9::getPostSubBufferSupport() const
2403 {
2404     return true;
2405 }
2406 
getMajorShaderModel() const2407 int Renderer9::getMajorShaderModel() const
2408 {
2409     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
2410 }
2411 
getMaxPointSize() const2412 float Renderer9::getMaxPointSize() const
2413 {
2414     // Point size clamped at 1.0f for SM2
2415     return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
2416 }
2417 
getMaxViewportDimension() const2418 int Renderer9::getMaxViewportDimension() const
2419 {
2420     int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
2421                                        (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
2422     return maxTextureDimension;
2423 }
2424 
getMaxTextureWidth() const2425 int Renderer9::getMaxTextureWidth() const
2426 {
2427     return (int)mDeviceCaps.MaxTextureWidth;
2428 }
2429 
getMaxTextureHeight() const2430 int Renderer9::getMaxTextureHeight() const
2431 {
2432     return (int)mDeviceCaps.MaxTextureHeight;
2433 }
2434 
get32BitIndexSupport() const2435 bool Renderer9::get32BitIndexSupport() const
2436 {
2437     return mDeviceCaps.MaxVertexIndex >= (1 << 16);
2438 }
2439 
getCapsDeclTypes() const2440 DWORD Renderer9::getCapsDeclTypes() const
2441 {
2442     return mDeviceCaps.DeclTypes;
2443 }
2444 
getMinSwapInterval() const2445 int Renderer9::getMinSwapInterval() const
2446 {
2447     return mMinSwapInterval;
2448 }
2449 
getMaxSwapInterval() const2450 int Renderer9::getMaxSwapInterval() const
2451 {
2452     return mMaxSwapInterval;
2453 }
2454 
getMaxSupportedSamples() const2455 int Renderer9::getMaxSupportedSamples() const
2456 {
2457     return mMaxSupportedSamples;
2458 }
2459 
getNearestSupportedSamples(D3DFORMAT format,int requested) const2460 int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
2461 {
2462     if (requested == 0)
2463     {
2464         return requested;
2465     }
2466 
2467     std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
2468     if (itr == mMultiSampleSupport.end())
2469     {
2470         if (format == D3DFMT_UNKNOWN)
2471             return 0;
2472         return -1;
2473     }
2474 
2475     for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
2476     {
2477         if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
2478         {
2479             return i;
2480         }
2481     }
2482 
2483     return -1;
2484 }
2485 
getMaxRenderTargets() const2486 unsigned int Renderer9::getMaxRenderTargets() const
2487 {
2488     // we do not support MRT in d3d9
2489     return 1;
2490 }
2491 
ConvertTextureInternalFormat(GLint internalformat)2492 D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
2493 {
2494     switch (internalformat)
2495     {
2496       case GL_DEPTH_COMPONENT16:
2497       case GL_DEPTH_COMPONENT32_OES:
2498       case GL_DEPTH24_STENCIL8_OES:
2499         return D3DFMT_INTZ;
2500       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2501       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2502         return D3DFMT_DXT1;
2503       case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
2504         return D3DFMT_DXT3;
2505       case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
2506         return D3DFMT_DXT5;
2507       case GL_RGBA32F_EXT:
2508       case GL_RGB32F_EXT:
2509       case GL_ALPHA32F_EXT:
2510       case GL_LUMINANCE32F_EXT:
2511       case GL_LUMINANCE_ALPHA32F_EXT:
2512         return D3DFMT_A32B32G32R32F;
2513       case GL_RGBA16F_EXT:
2514       case GL_RGB16F_EXT:
2515       case GL_ALPHA16F_EXT:
2516       case GL_LUMINANCE16F_EXT:
2517       case GL_LUMINANCE_ALPHA16F_EXT:
2518         return D3DFMT_A16B16G16R16F;
2519       case GL_LUMINANCE8_EXT:
2520         if (getLuminanceTextureSupport())
2521         {
2522             return D3DFMT_L8;
2523         }
2524         break;
2525       case GL_LUMINANCE8_ALPHA8_EXT:
2526         if (getLuminanceAlphaTextureSupport())
2527         {
2528             return D3DFMT_A8L8;
2529         }
2530         break;
2531       case GL_RGB8_OES:
2532       case GL_RGB565:
2533         return D3DFMT_X8R8G8B8;
2534     }
2535 
2536     return D3DFMT_A8R8G8B8;
2537 }
2538 
copyToRenderTarget(TextureStorageInterface2D * dest,TextureStorageInterface2D * source)2539 bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
2540 {
2541     bool result = false;
2542 
2543     if (source && dest)
2544     {
2545         TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
2546         TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
2547 
2548         int levels = source9->levelCount();
2549         for (int i = 0; i < levels; ++i)
2550         {
2551             IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
2552             IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
2553 
2554             result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
2555 
2556             if (srcSurf) srcSurf->Release();
2557             if (dstSurf) dstSurf->Release();
2558 
2559             if (!result)
2560                 return false;
2561         }
2562     }
2563 
2564     return result;
2565 }
2566 
copyToRenderTarget(TextureStorageInterfaceCube * dest,TextureStorageInterfaceCube * source)2567 bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
2568 {
2569     bool result = false;
2570 
2571     if (source && dest)
2572     {
2573         TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
2574         TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
2575         int levels = source9->levelCount();
2576         for (int f = 0; f < 6; f++)
2577         {
2578             for (int i = 0; i < levels; i++)
2579             {
2580                 IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
2581                 IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
2582 
2583                 result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
2584 
2585                 if (srcSurf) srcSurf->Release();
2586                 if (dstSurf) dstSurf->Release();
2587 
2588                 if (!result)
2589                     return false;
2590             }
2591         }
2592     }
2593 
2594     return result;
2595 }
2596 
getBufferPool(DWORD usage) const2597 D3DPOOL Renderer9::getBufferPool(DWORD usage) const
2598 {
2599     if (mD3d9Ex != NULL)
2600     {
2601         return D3DPOOL_DEFAULT;
2602     }
2603     else
2604     {
2605         if (!(usage & D3DUSAGE_DYNAMIC))
2606         {
2607             return D3DPOOL_MANAGED;
2608         }
2609     }
2610 
2611     return D3DPOOL_DEFAULT;
2612 }
2613 
copyImage(gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,GLint xoffset,GLint yoffset,TextureStorageInterface2D * storage,GLint level)2614 bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2615                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
2616 {
2617     RECT rect;
2618     rect.left = sourceRect.x;
2619     rect.top = sourceRect.y;
2620     rect.right = sourceRect.x + sourceRect.width;
2621     rect.bottom = sourceRect.y + sourceRect.height;
2622 
2623     return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
2624 }
2625 
copyImage(gl::Framebuffer * framebuffer,const gl::Rectangle & sourceRect,GLenum destFormat,GLint xoffset,GLint yoffset,TextureStorageInterfaceCube * storage,GLenum target,GLint level)2626 bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
2627                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
2628 {
2629     RECT rect;
2630     rect.left = sourceRect.x;
2631     rect.top = sourceRect.y;
2632     rect.right = sourceRect.x + sourceRect.width;
2633     rect.bottom = sourceRect.y + sourceRect.height;
2634 
2635     return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
2636 }
2637 
blitRect(gl::Framebuffer * readFramebuffer,const gl::Rectangle & readRect,gl::Framebuffer * drawFramebuffer,const gl::Rectangle & drawRect,bool blitRenderTarget,bool blitDepthStencil)2638 bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
2639                          bool blitRenderTarget, bool blitDepthStencil)
2640 {
2641     endScene();
2642 
2643     if (blitRenderTarget)
2644     {
2645         gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
2646         gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
2647         RenderTarget9 *readRenderTarget = NULL;
2648         RenderTarget9 *drawRenderTarget = NULL;
2649         IDirect3DSurface9* readSurface = NULL;
2650         IDirect3DSurface9* drawSurface = NULL;
2651 
2652         if (readBuffer)
2653         {
2654             readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
2655         }
2656         if (drawBuffer)
2657         {
2658             drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
2659         }
2660 
2661         if (readRenderTarget)
2662         {
2663             readSurface = readRenderTarget->getSurface();
2664         }
2665         if (drawRenderTarget)
2666         {
2667             drawSurface = drawRenderTarget->getSurface();
2668         }
2669 
2670         if (!readSurface || !drawSurface)
2671         {
2672             ERR("Failed to retrieve the render target.");
2673             return gl::error(GL_OUT_OF_MEMORY, false);
2674         }
2675 
2676         RECT srcRect;
2677         srcRect.left = readRect.x;
2678         srcRect.right = readRect.x + readRect.width;
2679         srcRect.top = readRect.y;
2680         srcRect.bottom = readRect.y + readRect.height;
2681 
2682         RECT dstRect;
2683         dstRect.left = drawRect.x;
2684         dstRect.right = drawRect.x + drawRect.width;
2685         dstRect.top = drawRect.y;
2686         dstRect.bottom = drawRect.y + drawRect.height;
2687 
2688         HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
2689 
2690         readSurface->Release();
2691         drawSurface->Release();
2692 
2693         if (FAILED(result))
2694         {
2695             ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
2696             return false;
2697         }
2698     }
2699 
2700     if (blitDepthStencil)
2701     {
2702         gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
2703         gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
2704         RenderTarget9 *readDepthStencil = NULL;
2705         RenderTarget9 *drawDepthStencil = NULL;
2706         IDirect3DSurface9* readSurface = NULL;
2707         IDirect3DSurface9* drawSurface = NULL;
2708 
2709         if (readBuffer)
2710         {
2711             readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
2712         }
2713         if (drawBuffer)
2714         {
2715             drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
2716         }
2717 
2718         if (readDepthStencil)
2719         {
2720             readSurface = readDepthStencil->getSurface();
2721         }
2722         if (drawDepthStencil)
2723         {
2724             drawSurface = drawDepthStencil->getSurface();
2725         }
2726 
2727         if (!readSurface || !drawSurface)
2728         {
2729             ERR("Failed to retrieve the render target.");
2730             return gl::error(GL_OUT_OF_MEMORY, false);
2731         }
2732 
2733         HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
2734 
2735         readSurface->Release();
2736         drawSurface->Release();
2737 
2738         if (FAILED(result))
2739         {
2740             ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
2741             return false;
2742         }
2743     }
2744 
2745     return true;
2746 }
2747 
readPixels(gl::Framebuffer * framebuffer,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei outputPitch,bool packReverseRowOrder,GLint packAlignment,void * pixels)2748 void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
2749                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
2750 {
2751     RenderTarget9 *renderTarget = NULL;
2752     IDirect3DSurface9 *surface = NULL;
2753     gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
2754 
2755     if (colorbuffer)
2756     {
2757         renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
2758     }
2759 
2760     if (renderTarget)
2761     {
2762         surface = renderTarget->getSurface();
2763     }
2764 
2765     if (!surface)
2766     {
2767         // context must be lost
2768         return;
2769     }
2770 
2771     D3DSURFACE_DESC desc;
2772     surface->GetDesc(&desc);
2773 
2774     if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2775     {
2776         UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
2777         surface->Release();
2778         return gl::error(GL_OUT_OF_MEMORY);
2779     }
2780 
2781     HRESULT result;
2782     IDirect3DSurface9 *systemSurface = NULL;
2783     bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
2784                           x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
2785                           desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
2786     if (directToPixels)
2787     {
2788         // Use the pixels ptr as a shared handle to write directly into client's memory
2789         result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
2790                                                       D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
2791         if (FAILED(result))
2792         {
2793             // Try again without the shared handle
2794             directToPixels = false;
2795         }
2796     }
2797 
2798     if (!directToPixels)
2799     {
2800         result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
2801                                                       D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2802         if (FAILED(result))
2803         {
2804             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2805             surface->Release();
2806             return gl::error(GL_OUT_OF_MEMORY);
2807         }
2808     }
2809 
2810     result = mDevice->GetRenderTargetData(surface, systemSurface);
2811     surface->Release();
2812     surface = NULL;
2813 
2814     if (FAILED(result))
2815     {
2816         systemSurface->Release();
2817 
2818         // It turns out that D3D will sometimes produce more error
2819         // codes than those documented.
2820         if (d3d9::isDeviceLostError(result))
2821         {
2822             notifyDeviceLost();
2823             return gl::error(GL_OUT_OF_MEMORY);
2824         }
2825         else
2826         {
2827             UNREACHABLE();
2828             return;
2829         }
2830 
2831     }
2832 
2833     if (directToPixels)
2834     {
2835         systemSurface->Release();
2836         return;
2837     }
2838 
2839     RECT rect;
2840     rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
2841     rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
2842     rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
2843     rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
2844 
2845     D3DLOCKED_RECT lock;
2846     result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2847 
2848     if (FAILED(result))
2849     {
2850         UNREACHABLE();
2851         systemSurface->Release();
2852 
2853         return;   // No sensible error to generate
2854     }
2855 
2856     unsigned char *dest = (unsigned char*)pixels;
2857     unsigned short *dest16 = (unsigned short*)pixels;
2858 
2859     unsigned char *source;
2860     int inputPitch;
2861     if (packReverseRowOrder)
2862     {
2863         source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
2864         inputPitch = -lock.Pitch;
2865     }
2866     else
2867     {
2868         source = (unsigned char*)lock.pBits;
2869         inputPitch = lock.Pitch;
2870     }
2871 
2872     unsigned int fastPixelSize = 0;
2873 
2874     if (desc.Format == D3DFMT_A8R8G8B8 &&
2875         format == GL_BGRA_EXT &&
2876         type == GL_UNSIGNED_BYTE)
2877     {
2878         fastPixelSize = 4;
2879     }
2880     else if ((desc.Format == D3DFMT_A4R4G4B4 &&
2881              format == GL_BGRA_EXT &&
2882              type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
2883              (desc.Format == D3DFMT_A1R5G5B5 &&
2884              format == GL_BGRA_EXT &&
2885              type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
2886     {
2887         fastPixelSize = 2;
2888     }
2889     else if (desc.Format == D3DFMT_A16B16G16R16F &&
2890              format == GL_RGBA &&
2891              type == GL_HALF_FLOAT_OES)
2892     {
2893         fastPixelSize = 8;
2894     }
2895     else if (desc.Format == D3DFMT_A32B32G32R32F &&
2896              format == GL_RGBA &&
2897              type == GL_FLOAT)
2898     {
2899         fastPixelSize = 16;
2900     }
2901 
2902     for (int j = 0; j < rect.bottom - rect.top; j++)
2903     {
2904         if (fastPixelSize != 0)
2905         {
2906             // Fast path for formats which require no translation:
2907             // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
2908             // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
2909             // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
2910             // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
2911             // D3DFMT_A32B32G32R32F to RGBA/FLOAT
2912             //
2913             // Note that buffers with no alpha go through the slow path below.
2914             memcpy(dest + j * outputPitch,
2915                    source + j * inputPitch,
2916                    (rect.right - rect.left) * fastPixelSize);
2917             continue;
2918         }
2919         else if (desc.Format == D3DFMT_A8R8G8B8 &&
2920                  format == GL_RGBA &&
2921                  type == GL_UNSIGNED_BYTE)
2922         {
2923             // Fast path for swapping red with blue
2924             for (int i = 0; i < rect.right - rect.left; i++)
2925             {
2926                 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2927                 *(unsigned int*)(dest + 4 * i + j * outputPitch) =
2928                     (argb & 0xFF00FF00) |       // Keep alpha and green
2929                     (argb & 0x00FF0000) >> 16 | // Move red to blue
2930                     (argb & 0x000000FF) << 16;  // Move blue to red
2931             }
2932             continue;
2933         }
2934 
2935         for (int i = 0; i < rect.right - rect.left; i++)
2936         {
2937             float r;
2938             float g;
2939             float b;
2940             float a;
2941 
2942             switch (desc.Format)
2943             {
2944               case D3DFMT_R5G6B5:
2945                 {
2946                     unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
2947 
2948                     a = 1.0f;
2949                     b = (rgb & 0x001F) * (1.0f / 0x001F);
2950                     g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2951                     r = (rgb & 0xF800) * (1.0f / 0xF800);
2952                 }
2953                 break;
2954               case D3DFMT_A1R5G5B5:
2955                 {
2956                     unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
2957 
2958                     a = (argb & 0x8000) ? 1.0f : 0.0f;
2959                     b = (argb & 0x001F) * (1.0f / 0x001F);
2960                     g = (argb & 0x03E0) * (1.0f / 0x03E0);
2961                     r = (argb & 0x7C00) * (1.0f / 0x7C00);
2962                 }
2963                 break;
2964               case D3DFMT_A8R8G8B8:
2965                 {
2966                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2967 
2968                     a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2969                     b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2970                     g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2971                     r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2972                 }
2973                 break;
2974               case D3DFMT_X8R8G8B8:
2975                 {
2976                     unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2977 
2978                     a = 1.0f;
2979                     b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2980                     g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2981                     r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2982                 }
2983                 break;
2984               case D3DFMT_A2R10G10B10:
2985                 {
2986                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
2987 
2988                     a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2989                     b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2990                     g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2991                     r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2992                 }
2993                 break;
2994               case D3DFMT_A32B32G32R32F:
2995                 {
2996                     // float formats in D3D are stored rgba, rather than the other way round
2997                     r = *((float*)(source + 16 * i + j * inputPitch) + 0);
2998                     g = *((float*)(source + 16 * i + j * inputPitch) + 1);
2999                     b = *((float*)(source + 16 * i + j * inputPitch) + 2);
3000                     a = *((float*)(source + 16 * i + j * inputPitch) + 3);
3001                 }
3002                 break;
3003               case D3DFMT_A16B16G16R16F:
3004                 {
3005                     // float formats in D3D are stored rgba, rather than the other way round
3006                     r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
3007                     g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
3008                     b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
3009                     a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
3010                 }
3011                 break;
3012               default:
3013                 UNIMPLEMENTED();   // FIXME
3014                 UNREACHABLE();
3015                 return;
3016             }
3017 
3018             switch (format)
3019             {
3020               case GL_RGBA:
3021                 switch (type)
3022                 {
3023                   case GL_UNSIGNED_BYTE:
3024                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
3025                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
3026                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
3027                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
3028                     break;
3029                   default: UNREACHABLE();
3030                 }
3031                 break;
3032               case GL_BGRA_EXT:
3033                 switch (type)
3034                 {
3035                   case GL_UNSIGNED_BYTE:
3036                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
3037                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
3038                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
3039                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
3040                     break;
3041                   case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
3042                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3043                     // this type is packed as follows:
3044                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
3045                     //  --------------------------------------------------------------------------------
3046                     // |       4th         |        3rd         |        2nd        |   1st component   |
3047                     //  --------------------------------------------------------------------------------
3048                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3049                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
3050                         ((unsigned short)(15 * a + 0.5f) << 12)|
3051                         ((unsigned short)(15 * r + 0.5f) << 8) |
3052                         ((unsigned short)(15 * g + 0.5f) << 4) |
3053                         ((unsigned short)(15 * b + 0.5f) << 0);
3054                     break;
3055                   case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
3056                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
3057                     // this type is packed as follows:
3058                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
3059                     //  --------------------------------------------------------------------------------
3060                     // | 4th |          3rd           |           2nd          |      1st component     |
3061                     //  --------------------------------------------------------------------------------
3062                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
3063                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
3064                         ((unsigned short)(     a + 0.5f) << 15) |
3065                         ((unsigned short)(31 * r + 0.5f) << 10) |
3066                         ((unsigned short)(31 * g + 0.5f) << 5) |
3067                         ((unsigned short)(31 * b + 0.5f) << 0);
3068                     break;
3069                   default: UNREACHABLE();
3070                 }
3071                 break;
3072               case GL_RGB:
3073                 switch (type)
3074                 {
3075                   case GL_UNSIGNED_SHORT_5_6_5:
3076                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
3077                         ((unsigned short)(31 * b + 0.5f) << 0) |
3078                         ((unsigned short)(63 * g + 0.5f) << 5) |
3079                         ((unsigned short)(31 * r + 0.5f) << 11);
3080                     break;
3081                   case GL_UNSIGNED_BYTE:
3082                     dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
3083                     dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
3084                     dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
3085                     break;
3086                   default: UNREACHABLE();
3087                 }
3088                 break;
3089               default: UNREACHABLE();
3090             }
3091         }
3092     }
3093 
3094     systemSurface->UnlockRect();
3095 
3096     systemSurface->Release();
3097 }
3098 
createRenderTarget(SwapChain * swapChain,bool depth)3099 RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
3100 {
3101     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
3102     IDirect3DSurface9 *surface = NULL;
3103     if (depth)
3104     {
3105         surface = swapChain9->getDepthStencil();
3106     }
3107     else
3108     {
3109         surface = swapChain9->getRenderTarget();
3110     }
3111 
3112     RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
3113 
3114     return renderTarget;
3115 }
3116 
createRenderTarget(int width,int height,GLenum format,GLsizei samples,bool depth)3117 RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
3118 {
3119     RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
3120     return renderTarget;
3121 }
3122 
loadExecutable(const void * function,size_t length,rx::ShaderType type)3123 ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
3124 {
3125     ShaderExecutable9 *executable = NULL;
3126 
3127     switch (type)
3128     {
3129       case rx::SHADER_VERTEX:
3130         {
3131             IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
3132             if (vshader)
3133             {
3134                 executable = new ShaderExecutable9(function, length, vshader);
3135             }
3136         }
3137         break;
3138       case rx::SHADER_PIXEL:
3139         {
3140             IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
3141             if (pshader)
3142             {
3143                 executable = new ShaderExecutable9(function, length, pshader);
3144             }
3145         }
3146         break;
3147       default:
3148         UNREACHABLE();
3149         break;
3150     }
3151 
3152     return executable;
3153 }
3154 
compileToExecutable(gl::InfoLog & infoLog,const char * shaderHLSL,rx::ShaderType type,D3DWorkaroundType workaround)3155 ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
3156 {
3157     const char *profile = NULL;
3158 
3159     switch (type)
3160     {
3161       case rx::SHADER_VERTEX:
3162         profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
3163         break;
3164       case rx::SHADER_PIXEL:
3165         profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
3166         break;
3167       default:
3168         UNREACHABLE();
3169         return NULL;
3170     }
3171 
3172     // ANGLE issue 486:
3173     // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
3174     UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL);
3175 
3176     ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true);
3177     if (!binary)
3178         return NULL;
3179 
3180     ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
3181     binary->Release();
3182 
3183     return executable;
3184 }
3185 
boxFilter(IDirect3DSurface9 * source,IDirect3DSurface9 * dest)3186 bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
3187 {
3188     return mBlit->boxFilter(source, dest);
3189 }
3190 
getTexturePool(DWORD usage) const3191 D3DPOOL Renderer9::getTexturePool(DWORD usage) const
3192 {
3193     if (mD3d9Ex != NULL)
3194     {
3195         return D3DPOOL_DEFAULT;
3196     }
3197     else
3198     {
3199         if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
3200         {
3201             return D3DPOOL_MANAGED;
3202         }
3203     }
3204 
3205     return D3DPOOL_DEFAULT;
3206 }
3207 
copyToRenderTarget(IDirect3DSurface9 * dest,IDirect3DSurface9 * source,bool fromManaged)3208 bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
3209 {
3210     if (source && dest)
3211     {
3212         HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
3213 
3214         if (fromManaged)
3215         {
3216             D3DSURFACE_DESC desc;
3217             source->GetDesc(&desc);
3218 
3219             IDirect3DSurface9 *surf = 0;
3220             result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
3221 
3222             if (SUCCEEDED(result))
3223             {
3224                 Image9::copyLockableSurfaces(surf, source);
3225                 result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
3226                 surf->Release();
3227             }
3228         }
3229         else
3230         {
3231             endScene();
3232             result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
3233         }
3234 
3235         if (FAILED(result))
3236         {
3237             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
3238             return false;
3239         }
3240     }
3241 
3242     return true;
3243 }
3244 
createImage()3245 Image *Renderer9::createImage()
3246 {
3247     return new Image9();
3248 }
3249 
generateMipmap(Image * dest,Image * src)3250 void Renderer9::generateMipmap(Image *dest, Image *src)
3251 {
3252     Image9 *src9 = Image9::makeImage9(src);
3253     Image9 *dst9 = Image9::makeImage9(dest);
3254     Image9::generateMipmap(dst9, src9);
3255 }
3256 
createTextureStorage2D(SwapChain * swapChain)3257 TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
3258 {
3259     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
3260     return new TextureStorage9_2D(this, swapChain9);
3261 }
3262 
createTextureStorage2D(int levels,GLenum internalformat,GLenum usage,bool forceRenderable,GLsizei width,GLsizei height)3263 TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
3264 {
3265     return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
3266 }
3267 
createTextureStorageCube(int levels,GLenum internalformat,GLenum usage,bool forceRenderable,int size)3268 TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
3269 {
3270     return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
3271 }
3272 
getLUID(LUID * adapterLuid) const3273 bool Renderer9::getLUID(LUID *adapterLuid) const
3274 {
3275     adapterLuid->HighPart = 0;
3276     adapterLuid->LowPart = 0;
3277 
3278     if (mD3d9Ex)
3279     {
3280         mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
3281         return true;
3282     }
3283 
3284     return false;
3285 }
3286 
3287 }
3288