Home | History | Annotate | Download | only in renderer
      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 
     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 
    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 
    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 
    163 Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
    164 {
    165     ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
    166     return static_cast<rx::Renderer9*>(renderer);
    167 }
    168 
    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.
    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 
    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 
    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 
    603 void Renderer9::deleteConfigs(ConfigDesc *configDescList)
    604 {
    605     delete [] (configDescList);
    606 }
    607 
    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 
    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 
    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 
    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 
    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 
    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 
    707 IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
    708 {
    709     return mVertexShaderCache.create(function, length);
    710 }
    711 
    712 IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
    713 {
    714     return mPixelShaderCache.create(function, length);
    715 }
    716 
    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 
    723 VertexBuffer *Renderer9::createVertexBuffer()
    724 {
    725     return new VertexBuffer9(this);
    726 }
    727 
    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 
    734 IndexBuffer *Renderer9::createIndexBuffer()
    735 {
    736     return new IndexBuffer9(this);
    737 }
    738 
    739 BufferStorage *Renderer9::createBufferStorage()
    740 {
    741     return new BufferStorage9();
    742 }
    743 
    744 QueryImpl *Renderer9::createQuery(GLenum type)
    745 {
    746     return new Query9(this, type);
    747 }
    748 
    749 FenceImpl *Renderer9::createFence()
    750 {
    751     return new Fence9(this);
    752 }
    753 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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
   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 
   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 
   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 
   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>
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2055 void Renderer9::notifyDeviceLost()
   2056 {
   2057     mDeviceLost = true;
   2058     mDisplay->notifyDeviceLost();
   2059 }
   2060 
   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
   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 
   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 
   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 
   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 
   2194 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 
   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 
   2228 DWORD Renderer9::getAdapterVendor() const
   2229 {
   2230     return mAdapterIdentifier.VendorId;
   2231 }
   2232 
   2233 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 
   2253 GUID Renderer9::getAdapterIdentifier() const
   2254 {
   2255     return mAdapterIdentifier.DeviceIdentifier;
   2256 }
   2257 
   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 
   2269 bool Renderer9::getBGRATextureSupport() const
   2270 {
   2271     // DirectX 9 always supports BGRA
   2272     return true;
   2273 }
   2274 
   2275 bool Renderer9::getDXT1TextureSupport()
   2276 {
   2277     return mDXT1TextureSupport;
   2278 }
   2279 
   2280 bool Renderer9::getDXT3TextureSupport()
   2281 {
   2282     return mDXT3TextureSupport;
   2283 }
   2284 
   2285 bool Renderer9::getDXT5TextureSupport()
   2286 {
   2287     return mDXT5TextureSupport;
   2288 }
   2289 
   2290 bool Renderer9::getDepthTextureSupport() const
   2291 {
   2292     return mDepthTextureSupport;
   2293 }
   2294 
   2295 bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
   2296 {
   2297     *filtering = mFloat32FilterSupport;
   2298     *renderable = mFloat32RenderSupport;
   2299     return mFloat32TextureSupport;
   2300 }
   2301 
   2302 bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
   2303 {
   2304     *filtering = mFloat16FilterSupport;
   2305     *renderable = mFloat16RenderSupport;
   2306     return mFloat16TextureSupport;
   2307 }
   2308 
   2309 bool Renderer9::getLuminanceTextureSupport()
   2310 {
   2311     return mLuminanceTextureSupport;
   2312 }
   2313 
   2314 bool Renderer9::getLuminanceAlphaTextureSupport()
   2315 {
   2316     return mLuminanceAlphaTextureSupport;
   2317 }
   2318 
   2319 bool Renderer9::getTextureFilterAnisotropySupport() const
   2320 {
   2321     return mSupportsTextureFilterAnisotropy;
   2322 }
   2323 
   2324 float Renderer9::getTextureMaxAnisotropy() const
   2325 {
   2326     if (mSupportsTextureFilterAnisotropy)
   2327     {
   2328         return static_cast<float>(mDeviceCaps.MaxAnisotropy);
   2329     }
   2330     return 1.0f;
   2331 }
   2332 
   2333 bool Renderer9::getEventQuerySupport()
   2334 {
   2335     return mEventQuerySupport;
   2336 }
   2337 
   2338 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 
   2344 unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
   2345 {
   2346     return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
   2347 }
   2348 
   2349 unsigned int Renderer9::getReservedVertexUniformVectors() const
   2350 {
   2351     return 2;   // dx_ViewAdjust and dx_DepthRange.
   2352 }
   2353 
   2354 unsigned int Renderer9::getReservedFragmentUniformVectors() const
   2355 {
   2356     return 3;   // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
   2357 }
   2358 
   2359 unsigned int Renderer9::getMaxVertexUniformVectors() const
   2360 {
   2361     return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
   2362 }
   2363 
   2364 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 
   2371 unsigned int Renderer9::getMaxVaryingVectors() const
   2372 {
   2373     return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
   2374 }
   2375 
   2376 bool Renderer9::getNonPower2TextureSupport() const
   2377 {
   2378     return mSupportsNonPower2Textures;
   2379 }
   2380 
   2381 bool Renderer9::getOcclusionQuerySupport() const
   2382 {
   2383     return mOcclusionQuerySupport;
   2384 }
   2385 
   2386 bool Renderer9::getInstancingSupport() const
   2387 {
   2388     return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
   2389 }
   2390 
   2391 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 
   2397 bool Renderer9::getDerivativeInstructionSupport() const
   2398 {
   2399     return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
   2400 }
   2401 
   2402 bool Renderer9::getPostSubBufferSupport() const
   2403 {
   2404     return true;
   2405 }
   2406 
   2407 int Renderer9::getMajorShaderModel() const
   2408 {
   2409     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
   2410 }
   2411 
   2412 float Renderer9::getMaxPointSize() const
   2413 {
   2414     // Point size clamped at 1.0f for SM2
   2415     return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
   2416 }
   2417 
   2418 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 
   2425 int Renderer9::getMaxTextureWidth() const
   2426 {
   2427     return (int)mDeviceCaps.MaxTextureWidth;
   2428 }
   2429 
   2430 int Renderer9::getMaxTextureHeight() const
   2431 {
   2432     return (int)mDeviceCaps.MaxTextureHeight;
   2433 }
   2434 
   2435 bool Renderer9::get32BitIndexSupport() const
   2436 {
   2437     return mDeviceCaps.MaxVertexIndex >= (1 << 16);
   2438 }
   2439 
   2440 DWORD Renderer9::getCapsDeclTypes() const
   2441 {
   2442     return mDeviceCaps.DeclTypes;
   2443 }
   2444 
   2445 int Renderer9::getMinSwapInterval() const
   2446 {
   2447     return mMinSwapInterval;
   2448 }
   2449 
   2450 int Renderer9::getMaxSwapInterval() const
   2451 {
   2452     return mMaxSwapInterval;
   2453 }
   2454 
   2455 int Renderer9::getMaxSupportedSamples() const
   2456 {
   2457     return mMaxSupportedSamples;
   2458 }
   2459 
   2460 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 
   2486 unsigned int Renderer9::getMaxRenderTargets() const
   2487 {
   2488     // we do not support MRT in d3d9
   2489     return 1;
   2490 }
   2491 
   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 
   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 
   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 
   2597 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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   3186 bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
   3187 {
   3188     return mBlit->boxFilter(source, dest);
   3189 }
   3190 
   3191 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 
   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 
   3245 Image *Renderer9::createImage()
   3246 {
   3247     return new Image9();
   3248 }
   3249 
   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 
   3257 TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
   3258 {
   3259     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
   3260     return new TextureStorage9_2D(this, swapChain9);
   3261 }
   3262 
   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 
   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 
   3273 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