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