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