gfx/angle/src/libGLESv2/renderer/Renderer9.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/Renderer9.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3222 @@
     1.4 +#include "precompiled.h"
     1.5 +//
     1.6 +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
     1.7 +// Use of this source code is governed by a BSD-style license that can be
     1.8 +// found in the LICENSE file.
     1.9 +//
    1.10 +
    1.11 +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
    1.12 +
    1.13 +#include "libGLESv2/main.h"
    1.14 +#include "libGLESv2/Buffer.h"
    1.15 +#include "libGLESv2/Texture.h"
    1.16 +#include "libGLESv2/Framebuffer.h"
    1.17 +#include "libGLESv2/Renderbuffer.h"
    1.18 +#include "libGLESv2/ProgramBinary.h"
    1.19 +#include "libGLESv2/renderer/IndexDataManager.h"
    1.20 +#include "libGLESv2/renderer/Renderer9.h"
    1.21 +#include "libGLESv2/renderer/renderer9_utils.h"
    1.22 +#include "libGLESv2/renderer/ShaderExecutable9.h"
    1.23 +#include "libGLESv2/renderer/SwapChain9.h"
    1.24 +#include "libGLESv2/renderer/TextureStorage9.h"
    1.25 +#include "libGLESv2/renderer/Image9.h"
    1.26 +#include "libGLESv2/renderer/Blit.h"
    1.27 +#include "libGLESv2/renderer/RenderTarget9.h"
    1.28 +#include "libGLESv2/renderer/VertexBuffer9.h"
    1.29 +#include "libGLESv2/renderer/IndexBuffer9.h"
    1.30 +#include "libGLESv2/renderer/BufferStorage9.h"
    1.31 +#include "libGLESv2/renderer/Query9.h"
    1.32 +#include "libGLESv2/renderer/Fence9.h"
    1.33 +
    1.34 +#include "libEGL/Display.h"
    1.35 +
    1.36 +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
    1.37 +#define REF_RAST 0
    1.38 +
    1.39 +// The "Debug This Pixel..." feature in PIX often fails when using the
    1.40 +// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
    1.41 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
    1.42 +#if !defined(ANGLE_ENABLE_D3D9EX)
    1.43 +// Enables use of the IDirect3D9Ex interface, when available
    1.44 +#define ANGLE_ENABLE_D3D9EX 1
    1.45 +#endif // !defined(ANGLE_ENABLE_D3D9EX)
    1.46 +
    1.47 +namespace rx
    1.48 +{
    1.49 +static const D3DFORMAT RenderTargetFormats[] =
    1.50 +    {
    1.51 +        D3DFMT_A1R5G5B5,
    1.52 +    //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
    1.53 +        D3DFMT_A8R8G8B8,
    1.54 +        D3DFMT_R5G6B5,
    1.55 +    //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
    1.56 +        D3DFMT_X8R8G8B8
    1.57 +    };
    1.58 +
    1.59 +static const D3DFORMAT DepthStencilFormats[] =
    1.60 +    {
    1.61 +        D3DFMT_UNKNOWN,
    1.62 +    //  D3DFMT_D16_LOCKABLE,
    1.63 +        D3DFMT_D32,
    1.64 +    //  D3DFMT_D15S1,
    1.65 +        D3DFMT_D24S8,
    1.66 +        D3DFMT_D24X8,
    1.67 +    //  D3DFMT_D24X4S4,
    1.68 +        D3DFMT_D16,
    1.69 +    //  D3DFMT_D32F_LOCKABLE,
    1.70 +    //  D3DFMT_D24FS8
    1.71 +    };
    1.72 +
    1.73 +enum
    1.74 +{
    1.75 +    MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
    1.76 +    MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
    1.77 +    MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
    1.78 +    MAX_VARYING_VECTORS_SM2 = 8,
    1.79 +    MAX_VARYING_VECTORS_SM3 = 10,
    1.80 +
    1.81 +    MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
    1.82 +};
    1.83 +
    1.84 +Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
    1.85 +{
    1.86 +    mD3d9Module = NULL;
    1.87 +
    1.88 +    mD3d9 = NULL;
    1.89 +    mD3d9Ex = NULL;
    1.90 +    mDevice = NULL;
    1.91 +    mDeviceEx = NULL;
    1.92 +    mDeviceWindow = NULL;
    1.93 +    mBlit = NULL;
    1.94 +
    1.95 +    mAdapter = D3DADAPTER_DEFAULT;
    1.96 +
    1.97 +    #if REF_RAST == 1 || defined(FORCE_REF_RAST)
    1.98 +        mDeviceType = D3DDEVTYPE_REF;
    1.99 +    #else
   1.100 +        mDeviceType = D3DDEVTYPE_HAL;
   1.101 +    #endif
   1.102 +
   1.103 +    mDeviceLost = false;
   1.104 +
   1.105 +    mMaxSupportedSamples = 0;
   1.106 +
   1.107 +    mMaskedClearSavedState = NULL;
   1.108 +
   1.109 +    mVertexDataManager = NULL;
   1.110 +    mIndexDataManager = NULL;
   1.111 +    mLineLoopIB = NULL;
   1.112 +
   1.113 +    mMaxNullColorbufferLRU = 0;
   1.114 +    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
   1.115 +    {
   1.116 +        mNullColorbufferCache[i].lruCount = 0;
   1.117 +        mNullColorbufferCache[i].width = 0;
   1.118 +        mNullColorbufferCache[i].height = 0;
   1.119 +        mNullColorbufferCache[i].buffer = NULL;
   1.120 +    }
   1.121 +}
   1.122 +
   1.123 +Renderer9::~Renderer9()
   1.124 +{
   1.125 +    releaseDeviceResources();
   1.126 +
   1.127 +    if (mDevice)
   1.128 +    {
   1.129 +        // If the device is lost, reset it first to prevent leaving the driver in an unstable state
   1.130 +        if (testDeviceLost(false))
   1.131 +        {
   1.132 +            resetDevice();
   1.133 +        }
   1.134 +
   1.135 +        mDevice->Release();
   1.136 +        mDevice = NULL;
   1.137 +    }
   1.138 +
   1.139 +    if (mDeviceEx)
   1.140 +    {
   1.141 +        mDeviceEx->Release();
   1.142 +        mDeviceEx = NULL;
   1.143 +    }
   1.144 +
   1.145 +    if (mD3d9)
   1.146 +    {
   1.147 +        mD3d9->Release();
   1.148 +        mD3d9 = NULL;
   1.149 +    }
   1.150 +
   1.151 +    if (mDeviceWindow)
   1.152 +    {
   1.153 +        DestroyWindow(mDeviceWindow);
   1.154 +        mDeviceWindow = NULL;
   1.155 +    }
   1.156 +
   1.157 +    if (mD3d9Ex)
   1.158 +    {
   1.159 +        mD3d9Ex->Release();
   1.160 +        mD3d9Ex = NULL;
   1.161 +    }
   1.162 +
   1.163 +    if (mD3d9Module)
   1.164 +    {
   1.165 +        mD3d9Module = NULL;
   1.166 +    }
   1.167 +
   1.168 +    while (!mMultiSampleSupport.empty())
   1.169 +    {
   1.170 +        delete [] mMultiSampleSupport.begin()->second;
   1.171 +        mMultiSampleSupport.erase(mMultiSampleSupport.begin());
   1.172 +    }
   1.173 +}
   1.174 +
   1.175 +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
   1.176 +{
   1.177 +    ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
   1.178 +    return static_cast<rx::Renderer9*>(renderer);
   1.179 +}
   1.180 +
   1.181 +EGLint Renderer9::initialize()
   1.182 +{
   1.183 +    if (!initializeCompiler())
   1.184 +    {
   1.185 +        return EGL_NOT_INITIALIZED;
   1.186 +    }
   1.187 +
   1.188 +    if (mSoftwareDevice)
   1.189 +    {
   1.190 +        mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
   1.191 +    }
   1.192 +    else
   1.193 +    {
   1.194 +        mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
   1.195 +    }
   1.196 +
   1.197 +    if (mD3d9Module == NULL)
   1.198 +    {
   1.199 +        ERR("No D3D9 module found - aborting!\n");
   1.200 +        return EGL_NOT_INITIALIZED;
   1.201 +    }
   1.202 +
   1.203 +    typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
   1.204 +    Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
   1.205 +
   1.206 +    // Use Direct3D9Ex if available. Among other things, this version is less
   1.207 +    // inclined to report a lost context, for example when the user switches
   1.208 +    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
   1.209 +    if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
   1.210 +    {
   1.211 +        ASSERT(mD3d9Ex);
   1.212 +        mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
   1.213 +        ASSERT(mD3d9);
   1.214 +    }
   1.215 +    else
   1.216 +    {
   1.217 +        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
   1.218 +    }
   1.219 +
   1.220 +    if (!mD3d9)
   1.221 +    {
   1.222 +        ERR("Could not create D3D9 device - aborting!\n");
   1.223 +        return EGL_NOT_INITIALIZED;
   1.224 +    }
   1.225 +
   1.226 +    if (mDc != NULL)
   1.227 +    {
   1.228 +    //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
   1.229 +    }
   1.230 +
   1.231 +    HRESULT result;
   1.232 +
   1.233 +    // Give up on getting device caps after about one second.
   1.234 +    for (int i = 0; i < 10; ++i)
   1.235 +    {
   1.236 +        result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
   1.237 +        if (SUCCEEDED(result))
   1.238 +        {
   1.239 +            break;
   1.240 +        }
   1.241 +        else if (result == D3DERR_NOTAVAILABLE)
   1.242 +        {
   1.243 +            Sleep(100);   // Give the driver some time to initialize/recover
   1.244 +        }
   1.245 +        else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
   1.246 +        {
   1.247 +            ERR("failed to get device caps (0x%x)\n", result);
   1.248 +            return EGL_NOT_INITIALIZED;
   1.249 +        }
   1.250 +    }
   1.251 +
   1.252 +    if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
   1.253 +    {
   1.254 +        ERR("Renderer does not support PS 2.0. aborting!\n");
   1.255 +        return EGL_NOT_INITIALIZED;
   1.256 +    }
   1.257 +
   1.258 +    // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
   1.259 +    // This is required by Texture2D::convertToRenderTarget.
   1.260 +    if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
   1.261 +    {
   1.262 +        ERR("Renderer does not support stretctrect from textures!\n");
   1.263 +        return EGL_NOT_INITIALIZED;
   1.264 +    }
   1.265 +
   1.266 +    mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
   1.267 +
   1.268 +    // ATI cards on XP have problems with non-power-of-two textures.
   1.269 +    mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
   1.270 +        !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
   1.271 +        !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
   1.272 +        !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
   1.273 +
   1.274 +    // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
   1.275 +    mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
   1.276 +
   1.277 +    mMinSwapInterval = 4;
   1.278 +    mMaxSwapInterval = 0;
   1.279 +
   1.280 +    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
   1.281 +    {
   1.282 +        mMinSwapInterval = std::min(mMinSwapInterval, 0);
   1.283 +        mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
   1.284 +    }
   1.285 +    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
   1.286 +    {
   1.287 +        mMinSwapInterval = std::min(mMinSwapInterval, 1);
   1.288 +        mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
   1.289 +    }
   1.290 +    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
   1.291 +    {
   1.292 +        mMinSwapInterval = std::min(mMinSwapInterval, 2);
   1.293 +        mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
   1.294 +    }
   1.295 +    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
   1.296 +    {
   1.297 +        mMinSwapInterval = std::min(mMinSwapInterval, 3);
   1.298 +        mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
   1.299 +    }
   1.300 +    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
   1.301 +    {
   1.302 +        mMinSwapInterval = std::min(mMinSwapInterval, 4);
   1.303 +        mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
   1.304 +    }
   1.305 +
   1.306 +    int max = 0;
   1.307 +    for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
   1.308 +    {
   1.309 +        bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
   1.310 +        getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
   1.311 +        mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
   1.312 +
   1.313 +        for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
   1.314 +        {
   1.315 +            if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
   1.316 +            {
   1.317 +                max = j;
   1.318 +            }
   1.319 +        }
   1.320 +    }
   1.321 +
   1.322 +    for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
   1.323 +    {
   1.324 +        if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
   1.325 +            continue;
   1.326 +
   1.327 +        bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
   1.328 +        getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
   1.329 +        mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
   1.330 +
   1.331 +        for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
   1.332 +        {
   1.333 +            if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
   1.334 +            {
   1.335 +                max = j;
   1.336 +            }
   1.337 +        }
   1.338 +    }
   1.339 +
   1.340 +    mMaxSupportedSamples = max;
   1.341 +
   1.342 +    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
   1.343 +    static const TCHAR className[] = TEXT("STATIC");
   1.344 +
   1.345 +    mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
   1.346 +
   1.347 +    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
   1.348 +    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
   1.349 +
   1.350 +    result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
   1.351 +    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
   1.352 +    {
   1.353 +        return EGL_BAD_ALLOC;
   1.354 +    }
   1.355 +
   1.356 +    if (FAILED(result))
   1.357 +    {
   1.358 +        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
   1.359 +
   1.360 +        if (FAILED(result))
   1.361 +        {
   1.362 +            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
   1.363 +            return EGL_BAD_ALLOC;
   1.364 +        }
   1.365 +    }
   1.366 +
   1.367 +    if (mD3d9Ex)
   1.368 +    {
   1.369 +        result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
   1.370 +        ASSERT(SUCCEEDED(result));
   1.371 +    }
   1.372 +
   1.373 +    mVertexShaderCache.initialize(mDevice);
   1.374 +    mPixelShaderCache.initialize(mDevice);
   1.375 +
   1.376 +    // Check occlusion query support
   1.377 +    IDirect3DQuery9 *occlusionQuery = NULL;
   1.378 +    if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
   1.379 +    {
   1.380 +        occlusionQuery->Release();
   1.381 +        mOcclusionQuerySupport = true;
   1.382 +    }
   1.383 +    else
   1.384 +    {
   1.385 +        mOcclusionQuerySupport = false;
   1.386 +    }
   1.387 +
   1.388 +    // Check event query support
   1.389 +    IDirect3DQuery9 *eventQuery = NULL;
   1.390 +    if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
   1.391 +    {
   1.392 +        eventQuery->Release();
   1.393 +        mEventQuerySupport = true;
   1.394 +    }
   1.395 +    else
   1.396 +    {
   1.397 +        mEventQuerySupport = false;
   1.398 +    }
   1.399 +
   1.400 +    D3DDISPLAYMODE currentDisplayMode;
   1.401 +    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
   1.402 +
   1.403 +    // Check vertex texture support
   1.404 +    // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
   1.405 +    // We test this using D3D9 by checking support for the R16F format.
   1.406 +    mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
   1.407 +                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   1.408 +                                                               D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
   1.409 +
   1.410 +    // Check depth texture support
   1.411 +    // we use INTZ for depth textures in Direct3D9
   1.412 +    // we also want NULL texture support to ensure the we can make depth-only FBOs
   1.413 +    // see http://aras-p.info/texts/D3D9GPUHacks.html
   1.414 +    mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   1.415 +                                                              D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
   1.416 +                           SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   1.417 +                                                              D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
   1.418 +
   1.419 +    // Check 32 bit floating point texture support
   1.420 +    mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   1.421 +                                                               D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   1.422 +                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   1.423 +                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   1.424 +
   1.425 +    mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   1.426 +                                                               D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   1.427 +                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   1.428 +                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   1.429 +
   1.430 +    if (!mFloat32FilterSupport && !mFloat32RenderSupport)
   1.431 +    {
   1.432 +        mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   1.433 +                                                                    D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   1.434 +                                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   1.435 +                                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   1.436 +    }
   1.437 +    else
   1.438 +    {
   1.439 +        mFloat32TextureSupport = true;
   1.440 +    }
   1.441 +
   1.442 +    // Check 16 bit floating point texture support
   1.443 +    mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   1.444 +                                                               D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   1.445 +                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   1.446 +                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   1.447 +
   1.448 +    mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   1.449 +                                                               D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   1.450 +                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   1.451 +                                                               D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   1.452 +
   1.453 +    if (!mFloat16FilterSupport && !mFloat16RenderSupport)
   1.454 +    {
   1.455 +        mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   1.456 +                                                                    D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   1.457 +                                 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   1.458 +                                                                    D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   1.459 +    }
   1.460 +    else
   1.461 +    {
   1.462 +        mFloat16TextureSupport = true;
   1.463 +    }
   1.464 +
   1.465 +    // Check DXT texture support
   1.466 +    mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
   1.467 +    mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
   1.468 +    mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
   1.469 +
   1.470 +    // Check luminance[alpha] texture support
   1.471 +    mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
   1.472 +    mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
   1.473 +
   1.474 +    initializeDevice();
   1.475 +
   1.476 +    return EGL_SUCCESS;
   1.477 +}
   1.478 +
   1.479 +// do any one-time device initialization
   1.480 +// NOTE: this is also needed after a device lost/reset
   1.481 +// to reset the scene status and ensure the default states are reset.
   1.482 +void Renderer9::initializeDevice()
   1.483 +{
   1.484 +    // Permanent non-default states
   1.485 +    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
   1.486 +    mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
   1.487 +
   1.488 +    if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
   1.489 +    {
   1.490 +        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
   1.491 +    }
   1.492 +    else
   1.493 +    {
   1.494 +        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);   // 1.0f
   1.495 +    }
   1.496 +
   1.497 +    markAllStateDirty();
   1.498 +
   1.499 +    mSceneStarted = false;
   1.500 +
   1.501 +    ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
   1.502 +    mBlit = new Blit(this);
   1.503 +    mVertexDataManager = new rx::VertexDataManager(this);
   1.504 +    mIndexDataManager = new rx::IndexDataManager(this);
   1.505 +}
   1.506 +
   1.507 +D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
   1.508 +{
   1.509 +    D3DPRESENT_PARAMETERS presentParameters = {0};
   1.510 +
   1.511 +    // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
   1.512 +    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
   1.513 +    presentParameters.BackBufferCount = 1;
   1.514 +    presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
   1.515 +    presentParameters.BackBufferWidth = 1;
   1.516 +    presentParameters.BackBufferHeight = 1;
   1.517 +    presentParameters.EnableAutoDepthStencil = FALSE;
   1.518 +    presentParameters.Flags = 0;
   1.519 +    presentParameters.hDeviceWindow = mDeviceWindow;
   1.520 +    presentParameters.MultiSampleQuality = 0;
   1.521 +    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
   1.522 +    presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
   1.523 +    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
   1.524 +    presentParameters.Windowed = TRUE;
   1.525 +
   1.526 +    return presentParameters;
   1.527 +}
   1.528 +
   1.529 +int Renderer9::generateConfigs(ConfigDesc **configDescList)
   1.530 +{
   1.531 +    D3DDISPLAYMODE currentDisplayMode;
   1.532 +    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
   1.533 +
   1.534 +    unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
   1.535 +    unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
   1.536 +    (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
   1.537 +    int numConfigs = 0;
   1.538 +
   1.539 +    for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
   1.540 +    {
   1.541 +        D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
   1.542 +
   1.543 +        HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
   1.544 +
   1.545 +        if (SUCCEEDED(result))
   1.546 +        {
   1.547 +            for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
   1.548 +            {
   1.549 +                D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
   1.550 +                HRESULT result = D3D_OK;
   1.551 +
   1.552 +                if(depthStencilFormat != D3DFMT_UNKNOWN)
   1.553 +                {
   1.554 +                    result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
   1.555 +                }
   1.556 +
   1.557 +                if (SUCCEEDED(result))
   1.558 +                {
   1.559 +                    if(depthStencilFormat != D3DFMT_UNKNOWN)
   1.560 +                    {
   1.561 +                        result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
   1.562 +                    }
   1.563 +
   1.564 +                    if (SUCCEEDED(result))
   1.565 +                    {
   1.566 +                        ConfigDesc newConfig;
   1.567 +                        newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
   1.568 +                        newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
   1.569 +                        newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
   1.570 +                        newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
   1.571 +
   1.572 +                        (*configDescList)[numConfigs++] = newConfig;
   1.573 +                    }
   1.574 +                }
   1.575 +            }
   1.576 +        }
   1.577 +    }
   1.578 +
   1.579 +    return numConfigs;
   1.580 +}
   1.581 +
   1.582 +void Renderer9::deleteConfigs(ConfigDesc *configDescList)
   1.583 +{
   1.584 +    delete [] (configDescList);
   1.585 +}
   1.586 +
   1.587 +void Renderer9::startScene()
   1.588 +{
   1.589 +    if (!mSceneStarted)
   1.590 +    {
   1.591 +        long result = mDevice->BeginScene();
   1.592 +        if (SUCCEEDED(result)) {
   1.593 +            // This is defensive checking against the device being
   1.594 +            // lost at unexpected times.
   1.595 +            mSceneStarted = true;
   1.596 +        }
   1.597 +    }
   1.598 +}
   1.599 +
   1.600 +void Renderer9::endScene()
   1.601 +{
   1.602 +    if (mSceneStarted)
   1.603 +    {
   1.604 +        // EndScene can fail if the device was lost, for example due
   1.605 +        // to a TDR during a draw call.
   1.606 +        mDevice->EndScene();
   1.607 +        mSceneStarted = false;
   1.608 +    }
   1.609 +}
   1.610 +
   1.611 +void Renderer9::sync(bool block)
   1.612 +{
   1.613 +    HRESULT result;
   1.614 +
   1.615 +    IDirect3DQuery9* query = allocateEventQuery();
   1.616 +    if (!query)
   1.617 +    {
   1.618 +        return;
   1.619 +    }
   1.620 +
   1.621 +    result = query->Issue(D3DISSUE_END);
   1.622 +    ASSERT(SUCCEEDED(result));
   1.623 +
   1.624 +    do
   1.625 +    {
   1.626 +        result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
   1.627 +
   1.628 +        if(block && result == S_FALSE)
   1.629 +        {
   1.630 +            // Keep polling, but allow other threads to do something useful first
   1.631 +            Sleep(0);
   1.632 +            // explicitly check for device loss
   1.633 +            // some drivers seem to return S_FALSE even if the device is lost
   1.634 +            // instead of D3DERR_DEVICELOST like they should
   1.635 +            if (testDeviceLost(false))
   1.636 +            {
   1.637 +                result = D3DERR_DEVICELOST;
   1.638 +            }
   1.639 +        }
   1.640 +    }
   1.641 +    while(block && result == S_FALSE);
   1.642 +
   1.643 +    freeEventQuery(query);
   1.644 +
   1.645 +    if (d3d9::isDeviceLostError(result))
   1.646 +    {
   1.647 +        notifyDeviceLost();
   1.648 +    }
   1.649 +}
   1.650 +
   1.651 +SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
   1.652 +{
   1.653 +    return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
   1.654 +}
   1.655 +
   1.656 +IDirect3DQuery9* Renderer9::allocateEventQuery()
   1.657 +{
   1.658 +    IDirect3DQuery9 *query = NULL;
   1.659 +
   1.660 +    if (mEventQueryPool.empty())
   1.661 +    {
   1.662 +        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
   1.663 +        ASSERT(SUCCEEDED(result));
   1.664 +    }
   1.665 +    else
   1.666 +    {
   1.667 +        query = mEventQueryPool.back();
   1.668 +        mEventQueryPool.pop_back();
   1.669 +    }
   1.670 +
   1.671 +    return query;
   1.672 +}
   1.673 +
   1.674 +void Renderer9::freeEventQuery(IDirect3DQuery9* query)
   1.675 +{
   1.676 +    if (mEventQueryPool.size() > 1000)
   1.677 +    {
   1.678 +        query->Release();
   1.679 +    }
   1.680 +    else
   1.681 +    {
   1.682 +        mEventQueryPool.push_back(query);
   1.683 +    }
   1.684 +}
   1.685 +
   1.686 +IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
   1.687 +{
   1.688 +    return mVertexShaderCache.create(function, length);
   1.689 +}
   1.690 +
   1.691 +IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
   1.692 +{
   1.693 +    return mPixelShaderCache.create(function, length);
   1.694 +}
   1.695 +
   1.696 +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
   1.697 +{
   1.698 +    D3DPOOL Pool = getBufferPool(Usage);
   1.699 +    return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
   1.700 +}
   1.701 +
   1.702 +VertexBuffer *Renderer9::createVertexBuffer()
   1.703 +{
   1.704 +    return new VertexBuffer9(this);
   1.705 +}
   1.706 +
   1.707 +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
   1.708 +{
   1.709 +    D3DPOOL Pool = getBufferPool(Usage);
   1.710 +    return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
   1.711 +}
   1.712 +
   1.713 +IndexBuffer *Renderer9::createIndexBuffer()
   1.714 +{
   1.715 +    return new IndexBuffer9(this);
   1.716 +}
   1.717 +
   1.718 +BufferStorage *Renderer9::createBufferStorage()
   1.719 +{
   1.720 +    return new BufferStorage9();
   1.721 +}
   1.722 +
   1.723 +QueryImpl *Renderer9::createQuery(GLenum type)
   1.724 +{
   1.725 +    return new Query9(this, type);
   1.726 +}
   1.727 +
   1.728 +FenceImpl *Renderer9::createFence()
   1.729 +{
   1.730 +    return new Fence9(this);
   1.731 +}
   1.732 +
   1.733 +void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
   1.734 +{
   1.735 +    bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
   1.736 +    gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
   1.737 +
   1.738 +    if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
   1.739 +    {
   1.740 +        int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   1.741 +        int d3dSampler = index + d3dSamplerOffset;
   1.742 +
   1.743 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
   1.744 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
   1.745 +
   1.746 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
   1.747 +        D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
   1.748 +        gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
   1.749 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
   1.750 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
   1.751 +        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
   1.752 +        if (mSupportsTextureFilterAnisotropy)
   1.753 +        {
   1.754 +            mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
   1.755 +        }
   1.756 +    }
   1.757 +
   1.758 +    forceSetSamplers[index] = false;
   1.759 +    appliedSamplers[index] = samplerState;
   1.760 +}
   1.761 +
   1.762 +void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
   1.763 +{
   1.764 +    int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   1.765 +    int d3dSampler = index + d3dSamplerOffset;
   1.766 +    IDirect3DBaseTexture9 *d3dTexture = NULL;
   1.767 +    unsigned int serial = 0;
   1.768 +    bool forceSetTexture = false;
   1.769 +
   1.770 +    unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
   1.771 +
   1.772 +    if (texture)
   1.773 +    {
   1.774 +        TextureStorageInterface *texStorage = texture->getNativeTexture();
   1.775 +        if (texStorage)
   1.776 +        {
   1.777 +            TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
   1.778 +            d3dTexture = storage9->getBaseTexture();
   1.779 +        }
   1.780 +        // If we get NULL back from getBaseTexture here, something went wrong
   1.781 +        // in the texture class and we're unexpectedly missing the d3d texture
   1.782 +        ASSERT(d3dTexture != NULL);
   1.783 +
   1.784 +        serial = texture->getTextureSerial();
   1.785 +        forceSetTexture = texture->hasDirtyImages();
   1.786 +    }
   1.787 +
   1.788 +    if (forceSetTexture || appliedSerials[index] != serial)
   1.789 +    {
   1.790 +        mDevice->SetTexture(d3dSampler, d3dTexture);
   1.791 +    }
   1.792 +
   1.793 +    appliedSerials[index] = serial;
   1.794 +}
   1.795 +
   1.796 +void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
   1.797 +{
   1.798 +    bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
   1.799 +
   1.800 +    if (rasterStateChanged)
   1.801 +    {
   1.802 +        // Set the cull mode
   1.803 +        if (rasterState.cullFace)
   1.804 +        {
   1.805 +            mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
   1.806 +        }
   1.807 +        else
   1.808 +        {
   1.809 +            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   1.810 +        }
   1.811 +
   1.812 +        if (rasterState.polygonOffsetFill)
   1.813 +        {
   1.814 +            if (mCurDepthSize > 0)
   1.815 +            {
   1.816 +                mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
   1.817 +
   1.818 +                float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
   1.819 +                mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
   1.820 +            }
   1.821 +        }
   1.822 +        else
   1.823 +        {
   1.824 +            mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
   1.825 +            mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
   1.826 +        }
   1.827 +
   1.828 +        mCurRasterState = rasterState;
   1.829 +    }
   1.830 +
   1.831 +    mForceSetRasterState = false;
   1.832 +}
   1.833 +
   1.834 +void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
   1.835 +{
   1.836 +    bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
   1.837 +    bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
   1.838 +    bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
   1.839 +
   1.840 +    if (blendStateChanged || blendColorChanged)
   1.841 +    {
   1.842 +        if (blendState.blend)
   1.843 +        {
   1.844 +            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   1.845 +
   1.846 +            if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
   1.847 +                blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
   1.848 +            {
   1.849 +                mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
   1.850 +            }
   1.851 +            else
   1.852 +            {
   1.853 +                mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
   1.854 +                                                                         gl::unorm<8>(blendColor.alpha),
   1.855 +                                                                         gl::unorm<8>(blendColor.alpha),
   1.856 +                                                                         gl::unorm<8>(blendColor.alpha)));
   1.857 +            }
   1.858 +
   1.859 +            mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
   1.860 +            mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
   1.861 +            mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
   1.862 +
   1.863 +            if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
   1.864 +                blendState.destBlendRGB != blendState.destBlendAlpha ||
   1.865 +                blendState.blendEquationRGB != blendState.blendEquationAlpha)
   1.866 +            {
   1.867 +                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   1.868 +
   1.869 +                mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
   1.870 +                mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
   1.871 +                mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
   1.872 +            }
   1.873 +            else
   1.874 +            {
   1.875 +                mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
   1.876 +            }
   1.877 +        }
   1.878 +        else
   1.879 +        {
   1.880 +            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   1.881 +        }
   1.882 +
   1.883 +        if (blendState.sampleAlphaToCoverage)
   1.884 +        {
   1.885 +            FIXME("Sample alpha to coverage is unimplemented.");
   1.886 +        }
   1.887 +
   1.888 +        // Set the color mask
   1.889 +        bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
   1.890 +        // Apparently some ATI cards have a bug where a draw with a zero color
   1.891 +        // write mask can cause later draws to have incorrect results. Instead,
   1.892 +        // set a nonzero color write mask but modify the blend state so that no
   1.893 +        // drawing is done.
   1.894 +        // http://code.google.com/p/angleproject/issues/detail?id=169
   1.895 +
   1.896 +        DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
   1.897 +                                                    blendState.colorMaskBlue, blendState.colorMaskAlpha);
   1.898 +        if (colorMask == 0 && !zeroColorMaskAllowed)
   1.899 +        {
   1.900 +            // Enable green channel, but set blending so nothing will be drawn.
   1.901 +            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
   1.902 +            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   1.903 +
   1.904 +            mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
   1.905 +            mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
   1.906 +            mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
   1.907 +        }
   1.908 +        else
   1.909 +        {
   1.910 +            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
   1.911 +        }
   1.912 +
   1.913 +        mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
   1.914 +
   1.915 +        mCurBlendState = blendState;
   1.916 +        mCurBlendColor = blendColor;
   1.917 +    }
   1.918 +
   1.919 +    if (sampleMaskChanged)
   1.920 +    {
   1.921 +        // Set the multisample mask
   1.922 +        mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
   1.923 +        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
   1.924 +
   1.925 +        mCurSampleMask = sampleMask;
   1.926 +    }
   1.927 +
   1.928 +    mForceSetBlendState = false;
   1.929 +}
   1.930 +
   1.931 +void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
   1.932 +                                     int stencilBackRef, bool frontFaceCCW)
   1.933 +{
   1.934 +    bool depthStencilStateChanged = mForceSetDepthStencilState ||
   1.935 +                                    memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
   1.936 +    bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
   1.937 +                             stencilBackRef != mCurStencilBackRef;
   1.938 +    bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
   1.939 +
   1.940 +    if (depthStencilStateChanged)
   1.941 +    {
   1.942 +        if (depthStencilState.depthTest)
   1.943 +        {
   1.944 +            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
   1.945 +            mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
   1.946 +        }
   1.947 +        else
   1.948 +        {
   1.949 +            mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
   1.950 +        }
   1.951 +
   1.952 +        mCurDepthStencilState = depthStencilState;
   1.953 +    }
   1.954 +
   1.955 +    if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
   1.956 +    {
   1.957 +        if (depthStencilState.stencilTest && mCurStencilSize > 0)
   1.958 +        {
   1.959 +            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
   1.960 +            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
   1.961 +
   1.962 +            // FIXME: Unsupported by D3D9
   1.963 +            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
   1.964 +            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
   1.965 +            const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
   1.966 +            if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
   1.967 +                stencilRef != stencilBackRef ||
   1.968 +                depthStencilState.stencilMask != depthStencilState.stencilBackMask)
   1.969 +            {
   1.970 +                ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
   1.971 +                return gl::error(GL_INVALID_OPERATION);
   1.972 +            }
   1.973 +
   1.974 +            // get the maximum size of the stencil ref
   1.975 +            unsigned int maxStencil = (1 << mCurStencilSize) - 1;
   1.976 +
   1.977 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
   1.978 +                                    depthStencilState.stencilWritemask);
   1.979 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   1.980 +                                    gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
   1.981 +
   1.982 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
   1.983 +                                    (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
   1.984 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
   1.985 +                                    depthStencilState.stencilMask);
   1.986 +
   1.987 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
   1.988 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
   1.989 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
   1.990 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
   1.991 +            mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
   1.992 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
   1.993 +
   1.994 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
   1.995 +                                    depthStencilState.stencilBackWritemask);
   1.996 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   1.997 +                                    gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
   1.998 +
   1.999 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
  1.1000 +                                    (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
  1.1001 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
  1.1002 +                                    depthStencilState.stencilBackMask);
  1.1003 +
  1.1004 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
  1.1005 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
  1.1006 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
  1.1007 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
  1.1008 +            mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
  1.1009 +                                    gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
  1.1010 +        }
  1.1011 +        else
  1.1012 +        {
  1.1013 +            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1.1014 +        }
  1.1015 +
  1.1016 +        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
  1.1017 +
  1.1018 +        mCurStencilRef = stencilRef;
  1.1019 +        mCurStencilBackRef = stencilBackRef;
  1.1020 +        mCurFrontFaceCCW = frontFaceCCW;
  1.1021 +    }
  1.1022 +
  1.1023 +    mForceSetDepthStencilState = false;
  1.1024 +}
  1.1025 +
  1.1026 +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
  1.1027 +{
  1.1028 +    bool scissorChanged = mForceSetScissor ||
  1.1029 +                          memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
  1.1030 +                          enabled != mScissorEnabled;
  1.1031 +
  1.1032 +    if (scissorChanged)
  1.1033 +    {
  1.1034 +        if (enabled)
  1.1035 +        {
  1.1036 +            RECT rect;
  1.1037 +            rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
  1.1038 +            rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
  1.1039 +            rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
  1.1040 +            rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
  1.1041 +            mDevice->SetScissorRect(&rect);
  1.1042 +        }
  1.1043 +
  1.1044 +        mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
  1.1045 +
  1.1046 +        mScissorEnabled = enabled;
  1.1047 +        mCurScissor = scissor;
  1.1048 +    }
  1.1049 +
  1.1050 +    mForceSetScissor = false;
  1.1051 +}
  1.1052 +
  1.1053 +bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
  1.1054 +                            bool ignoreViewport)
  1.1055 +{
  1.1056 +    gl::Rectangle actualViewport = viewport;
  1.1057 +    float actualZNear = gl::clamp01(zNear);
  1.1058 +    float actualZFar = gl::clamp01(zFar);
  1.1059 +    if (ignoreViewport)
  1.1060 +    {
  1.1061 +        actualViewport.x = 0;
  1.1062 +        actualViewport.y = 0;
  1.1063 +        actualViewport.width = mRenderTargetDesc.width;
  1.1064 +        actualViewport.height = mRenderTargetDesc.height;
  1.1065 +        actualZNear = 0.0f;
  1.1066 +        actualZFar = 1.0f;
  1.1067 +    }
  1.1068 +
  1.1069 +    D3DVIEWPORT9 dxViewport;
  1.1070 +    dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
  1.1071 +    dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
  1.1072 +    dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
  1.1073 +    dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
  1.1074 +    dxViewport.MinZ = actualZNear;
  1.1075 +    dxViewport.MaxZ = actualZFar;
  1.1076 +
  1.1077 +    if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
  1.1078 +    {
  1.1079 +        return false;   // Nothing to render
  1.1080 +    }
  1.1081 +
  1.1082 +    bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
  1.1083 +                           actualZNear != mCurNear || actualZFar != mCurFar;
  1.1084 +    if (viewportChanged)
  1.1085 +    {
  1.1086 +        mDevice->SetViewport(&dxViewport);
  1.1087 +
  1.1088 +        mCurViewport = actualViewport;
  1.1089 +        mCurNear = actualZNear;
  1.1090 +        mCurFar = actualZFar;
  1.1091 +
  1.1092 +        dx_VertexConstants vc = {0};
  1.1093 +        dx_PixelConstants pc = {0};
  1.1094 +
  1.1095 +        vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
  1.1096 +        vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
  1.1097 +        vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
  1.1098 +        vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
  1.1099 +
  1.1100 +        pc.viewCoords[0] = actualViewport.width  * 0.5f;
  1.1101 +        pc.viewCoords[1] = actualViewport.height * 0.5f;
  1.1102 +        pc.viewCoords[2] = actualViewport.x + (actualViewport.width  * 0.5f);
  1.1103 +        pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
  1.1104 +
  1.1105 +        pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
  1.1106 +        pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
  1.1107 +        pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);;
  1.1108 +
  1.1109 +        vc.depthRange[0] = actualZNear;
  1.1110 +        vc.depthRange[1] = actualZFar;
  1.1111 +        vc.depthRange[2] = actualZFar - actualZNear;
  1.1112 +
  1.1113 +        pc.depthRange[0] = actualZNear;
  1.1114 +        pc.depthRange[1] = actualZFar;
  1.1115 +        pc.depthRange[2] = actualZFar - actualZNear;
  1.1116 +
  1.1117 +        if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
  1.1118 +        {
  1.1119 +            mVertexConstants = vc;
  1.1120 +            mDxUniformsDirty = true;
  1.1121 +        }
  1.1122 +
  1.1123 +        if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
  1.1124 +        {
  1.1125 +            mPixelConstants = pc;
  1.1126 +            mDxUniformsDirty = true;
  1.1127 +        }
  1.1128 +    }
  1.1129 +
  1.1130 +    mForceSetViewport = false;
  1.1131 +    return true;
  1.1132 +}
  1.1133 +
  1.1134 +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
  1.1135 +{
  1.1136 +    switch (mode)
  1.1137 +    {
  1.1138 +      case GL_POINTS:
  1.1139 +        mPrimitiveType = D3DPT_POINTLIST;
  1.1140 +        mPrimitiveCount = count;
  1.1141 +        break;
  1.1142 +      case GL_LINES:
  1.1143 +        mPrimitiveType = D3DPT_LINELIST;
  1.1144 +        mPrimitiveCount = count / 2;
  1.1145 +        break;
  1.1146 +      case GL_LINE_LOOP:
  1.1147 +        mPrimitiveType = D3DPT_LINESTRIP;
  1.1148 +        mPrimitiveCount = count - 1;   // D3D doesn't support line loops, so we draw the last line separately
  1.1149 +        break;
  1.1150 +      case GL_LINE_STRIP:
  1.1151 +        mPrimitiveType = D3DPT_LINESTRIP;
  1.1152 +        mPrimitiveCount = count - 1;
  1.1153 +        break;
  1.1154 +      case GL_TRIANGLES:
  1.1155 +        mPrimitiveType = D3DPT_TRIANGLELIST;
  1.1156 +        mPrimitiveCount = count / 3;
  1.1157 +        break;
  1.1158 +      case GL_TRIANGLE_STRIP:
  1.1159 +        mPrimitiveType = D3DPT_TRIANGLESTRIP;
  1.1160 +        mPrimitiveCount = count - 2;
  1.1161 +        break;
  1.1162 +      case GL_TRIANGLE_FAN:
  1.1163 +        mPrimitiveType = D3DPT_TRIANGLEFAN;
  1.1164 +        mPrimitiveCount = count - 2;
  1.1165 +        break;
  1.1166 +      default:
  1.1167 +        return gl::error(GL_INVALID_ENUM, false);
  1.1168 +    }
  1.1169 +
  1.1170 +    return mPrimitiveCount > 0;
  1.1171 +}
  1.1172 +
  1.1173 +
  1.1174 +gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
  1.1175 +{
  1.1176 +    if (!depthbuffer)
  1.1177 +    {
  1.1178 +        ERR("Unexpected null depthbuffer for depth-only FBO.");
  1.1179 +        return NULL;
  1.1180 +    }
  1.1181 +
  1.1182 +    GLsizei width  = depthbuffer->getWidth();
  1.1183 +    GLsizei height = depthbuffer->getHeight();
  1.1184 +
  1.1185 +    // search cached nullcolorbuffers
  1.1186 +    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  1.1187 +    {
  1.1188 +        if (mNullColorbufferCache[i].buffer != NULL &&
  1.1189 +            mNullColorbufferCache[i].width == width &&
  1.1190 +            mNullColorbufferCache[i].height == height)
  1.1191 +        {
  1.1192 +            mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
  1.1193 +            return mNullColorbufferCache[i].buffer;
  1.1194 +        }
  1.1195 +    }
  1.1196 +
  1.1197 +    gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
  1.1198 +
  1.1199 +    // add nullbuffer to the cache
  1.1200 +    NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
  1.1201 +    for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  1.1202 +    {
  1.1203 +        if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
  1.1204 +        {
  1.1205 +            oldest = &mNullColorbufferCache[i];
  1.1206 +        }
  1.1207 +    }
  1.1208 +
  1.1209 +    delete oldest->buffer;
  1.1210 +    oldest->buffer = nullbuffer;
  1.1211 +    oldest->lruCount = ++mMaxNullColorbufferLRU;
  1.1212 +    oldest->width = width;
  1.1213 +    oldest->height = height;
  1.1214 +
  1.1215 +    return nullbuffer;
  1.1216 +}
  1.1217 +
  1.1218 +bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
  1.1219 +{
  1.1220 +    // if there is no color attachment we must synthesize a NULL colorattachment
  1.1221 +    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
  1.1222 +    gl::Renderbuffer *renderbufferObject = NULL;
  1.1223 +    if (framebuffer->getColorbufferType(0) != GL_NONE)
  1.1224 +    {
  1.1225 +        renderbufferObject = framebuffer->getColorbuffer(0);
  1.1226 +    }
  1.1227 +    else
  1.1228 +    {
  1.1229 +        renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
  1.1230 +    }
  1.1231 +    if (!renderbufferObject)
  1.1232 +    {
  1.1233 +        ERR("unable to locate renderbuffer for FBO.");
  1.1234 +        return false;
  1.1235 +    }
  1.1236 +
  1.1237 +    bool renderTargetChanged = false;
  1.1238 +    unsigned int renderTargetSerial = renderbufferObject->getSerial();
  1.1239 +    if (renderTargetSerial != mAppliedRenderTargetSerial)
  1.1240 +    {
  1.1241 +        // Apply the render target on the device
  1.1242 +        IDirect3DSurface9 *renderTargetSurface = NULL;
  1.1243 +
  1.1244 +        RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
  1.1245 +        if (renderTarget)
  1.1246 +        {
  1.1247 +            renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
  1.1248 +        }
  1.1249 +
  1.1250 +        if (!renderTargetSurface)
  1.1251 +        {
  1.1252 +            ERR("render target pointer unexpectedly null.");
  1.1253 +            return false;   // Context must be lost
  1.1254 +        }
  1.1255 +
  1.1256 +        mDevice->SetRenderTarget(0, renderTargetSurface);
  1.1257 +        renderTargetSurface->Release();
  1.1258 +
  1.1259 +        mAppliedRenderTargetSerial = renderTargetSerial;
  1.1260 +        renderTargetChanged = true;
  1.1261 +    }
  1.1262 +
  1.1263 +    gl::Renderbuffer *depthStencil = NULL;
  1.1264 +    unsigned int depthbufferSerial = 0;
  1.1265 +    unsigned int stencilbufferSerial = 0;
  1.1266 +    if (framebuffer->getDepthbufferType() != GL_NONE)
  1.1267 +    {
  1.1268 +        depthStencil = framebuffer->getDepthbuffer();
  1.1269 +        if (!depthStencil)
  1.1270 +        {
  1.1271 +            ERR("Depth stencil pointer unexpectedly null.");
  1.1272 +            return false;
  1.1273 +        }
  1.1274 +
  1.1275 +        depthbufferSerial = depthStencil->getSerial();
  1.1276 +    }
  1.1277 +    else if (framebuffer->getStencilbufferType() != GL_NONE)
  1.1278 +    {
  1.1279 +        depthStencil = framebuffer->getStencilbuffer();
  1.1280 +        if (!depthStencil)
  1.1281 +        {
  1.1282 +            ERR("Depth stencil pointer unexpectedly null.");
  1.1283 +            return false;
  1.1284 +        }
  1.1285 +
  1.1286 +        stencilbufferSerial = depthStencil->getSerial();
  1.1287 +    }
  1.1288 +
  1.1289 +    if (depthbufferSerial != mAppliedDepthbufferSerial ||
  1.1290 +        stencilbufferSerial != mAppliedStencilbufferSerial ||
  1.1291 +        !mDepthStencilInitialized)
  1.1292 +    {
  1.1293 +        unsigned int depthSize = 0;
  1.1294 +        unsigned int stencilSize = 0;
  1.1295 +
  1.1296 +        // Apply the depth stencil on the device
  1.1297 +        if (depthStencil)
  1.1298 +        {
  1.1299 +            IDirect3DSurface9 *depthStencilSurface = NULL;
  1.1300 +            RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
  1.1301 +
  1.1302 +            if (depthStencilRenderTarget)
  1.1303 +            {
  1.1304 +                depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
  1.1305 +            }
  1.1306 +
  1.1307 +            if (!depthStencilSurface)
  1.1308 +            {
  1.1309 +                ERR("depth stencil pointer unexpectedly null.");
  1.1310 +                return false;   // Context must be lost
  1.1311 +            }
  1.1312 +
  1.1313 +            mDevice->SetDepthStencilSurface(depthStencilSurface);
  1.1314 +            depthStencilSurface->Release();
  1.1315 +
  1.1316 +            depthSize = depthStencil->getDepthSize();
  1.1317 +            stencilSize = depthStencil->getStencilSize();
  1.1318 +        }
  1.1319 +        else
  1.1320 +        {
  1.1321 +            mDevice->SetDepthStencilSurface(NULL);
  1.1322 +        }
  1.1323 +
  1.1324 +        if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
  1.1325 +        {
  1.1326 +            mCurDepthSize = depthSize;
  1.1327 +            mForceSetRasterState = true;
  1.1328 +        }
  1.1329 +
  1.1330 +        if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
  1.1331 +        {
  1.1332 +            mCurStencilSize = stencilSize;
  1.1333 +            mForceSetDepthStencilState = true;
  1.1334 +        }
  1.1335 +
  1.1336 +        mAppliedDepthbufferSerial = depthbufferSerial;
  1.1337 +        mAppliedStencilbufferSerial = stencilbufferSerial;
  1.1338 +        mDepthStencilInitialized = true;
  1.1339 +    }
  1.1340 +
  1.1341 +    if (renderTargetChanged || !mRenderTargetDescInitialized)
  1.1342 +    {
  1.1343 +        mForceSetScissor = true;
  1.1344 +        mForceSetViewport = true;
  1.1345 +
  1.1346 +        mRenderTargetDesc.width = renderbufferObject->getWidth();
  1.1347 +        mRenderTargetDesc.height = renderbufferObject->getHeight();
  1.1348 +        mRenderTargetDesc.format = renderbufferObject->getActualFormat();
  1.1349 +        mRenderTargetDescInitialized = true;
  1.1350 +    }
  1.1351 +
  1.1352 +    return true;
  1.1353 +}
  1.1354 +
  1.1355 +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
  1.1356 +{
  1.1357 +    TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
  1.1358 +    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
  1.1359 +    if (err != GL_NO_ERROR)
  1.1360 +    {
  1.1361 +        return err;
  1.1362 +    }
  1.1363 +    
  1.1364 +    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
  1.1365 +}
  1.1366 +
  1.1367 +// Applies the indices and element array bindings to the Direct3D 9 device
  1.1368 +GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
  1.1369 +{
  1.1370 +    GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
  1.1371 +
  1.1372 +    if (err == GL_NO_ERROR)
  1.1373 +    {
  1.1374 +        // Directly binding the storage buffer is not supported for d3d9
  1.1375 +        ASSERT(indexInfo->storage == NULL);
  1.1376 +
  1.1377 +        if (indexInfo->serial != mAppliedIBSerial)
  1.1378 +        {
  1.1379 +            IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
  1.1380 +
  1.1381 +            mDevice->SetIndices(indexBuffer->getBuffer());
  1.1382 +            mAppliedIBSerial = indexInfo->serial;
  1.1383 +        }
  1.1384 +    }
  1.1385 +
  1.1386 +    return err;
  1.1387 +}
  1.1388 +
  1.1389 +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
  1.1390 +{
  1.1391 +    startScene();
  1.1392 +        
  1.1393 +    if (mode == GL_LINE_LOOP)
  1.1394 +    {
  1.1395 +        drawLineLoop(count, GL_NONE, NULL, 0, NULL);
  1.1396 +    }
  1.1397 +    else if (instances > 0)
  1.1398 +    {
  1.1399 +        StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
  1.1400 +        if (countingIB)
  1.1401 +        {
  1.1402 +            if (mAppliedIBSerial != countingIB->getSerial())
  1.1403 +            {
  1.1404 +                IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
  1.1405 +
  1.1406 +                mDevice->SetIndices(indexBuffer->getBuffer());
  1.1407 +                mAppliedIBSerial = countingIB->getSerial();
  1.1408 +            }
  1.1409 +
  1.1410 +            for (int i = 0; i < mRepeatDraw; i++)
  1.1411 +            {
  1.1412 +                mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
  1.1413 +            }
  1.1414 +        }
  1.1415 +        else
  1.1416 +        {
  1.1417 +            ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
  1.1418 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1419 +        }
  1.1420 +    }
  1.1421 +    else   // Regular case
  1.1422 +    {
  1.1423 +        mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
  1.1424 +    }
  1.1425 +}
  1.1426 +
  1.1427 +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
  1.1428 +{
  1.1429 +    startScene();
  1.1430 +
  1.1431 +    if (mode == GL_POINTS)
  1.1432 +    {
  1.1433 +        drawIndexedPoints(count, type, indices, elementArrayBuffer);
  1.1434 +    }
  1.1435 +    else if (mode == GL_LINE_LOOP)
  1.1436 +    {
  1.1437 +        drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
  1.1438 +    }
  1.1439 +    else
  1.1440 +    {
  1.1441 +        for (int i = 0; i < mRepeatDraw; i++)
  1.1442 +        {
  1.1443 +            GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
  1.1444 +            mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
  1.1445 +        }
  1.1446 +    }
  1.1447 +}
  1.1448 +
  1.1449 +void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
  1.1450 +{
  1.1451 +    // Get the raw indices for an indexed draw
  1.1452 +    if (type != GL_NONE && elementArrayBuffer)
  1.1453 +    {
  1.1454 +        gl::Buffer *indexBuffer = elementArrayBuffer;
  1.1455 +        BufferStorage *storage = indexBuffer->getStorage();
  1.1456 +        intptr_t offset = reinterpret_cast<intptr_t>(indices);
  1.1457 +        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
  1.1458 +    }
  1.1459 +
  1.1460 +    unsigned int startIndex = 0;
  1.1461 +
  1.1462 +    if (get32BitIndexSupport())
  1.1463 +    {
  1.1464 +        if (!mLineLoopIB)
  1.1465 +        {
  1.1466 +            mLineLoopIB = new StreamingIndexBufferInterface(this);
  1.1467 +            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
  1.1468 +            {
  1.1469 +                delete mLineLoopIB;
  1.1470 +                mLineLoopIB = NULL;
  1.1471 +
  1.1472 +                ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
  1.1473 +                return gl::error(GL_OUT_OF_MEMORY);
  1.1474 +            }
  1.1475 +        }
  1.1476 +
  1.1477 +        if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
  1.1478 +        {
  1.1479 +            ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
  1.1480 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1481 +        }
  1.1482 +
  1.1483 +        // Checked by Renderer9::applyPrimitiveType
  1.1484 +        ASSERT(count >= 0);
  1.1485 +
  1.1486 +        const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
  1.1487 +        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
  1.1488 +        {
  1.1489 +            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
  1.1490 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1491 +        }
  1.1492 +
  1.1493 +        void* mappedMemory = NULL;
  1.1494 +        unsigned int offset = 0;
  1.1495 +        if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
  1.1496 +        {
  1.1497 +            ERR("Could not map index buffer for GL_LINE_LOOP.");
  1.1498 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1499 +        }
  1.1500 +
  1.1501 +        startIndex = static_cast<unsigned int>(offset) / 4;
  1.1502 +        unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
  1.1503 +
  1.1504 +        switch (type)
  1.1505 +        {
  1.1506 +          case GL_NONE:   // Non-indexed draw
  1.1507 +            for (int i = 0; i < count; i++)
  1.1508 +            {
  1.1509 +                data[i] = i;
  1.1510 +            }
  1.1511 +            data[count] = 0;
  1.1512 +            break;
  1.1513 +          case GL_UNSIGNED_BYTE:
  1.1514 +            for (int i = 0; i < count; i++)
  1.1515 +            {
  1.1516 +                data[i] = static_cast<const GLubyte*>(indices)[i];
  1.1517 +            }
  1.1518 +            data[count] = static_cast<const GLubyte*>(indices)[0];
  1.1519 +            break;
  1.1520 +          case GL_UNSIGNED_SHORT:
  1.1521 +            for (int i = 0; i < count; i++)
  1.1522 +            {
  1.1523 +                data[i] = static_cast<const GLushort*>(indices)[i];
  1.1524 +            }
  1.1525 +            data[count] = static_cast<const GLushort*>(indices)[0];
  1.1526 +            break;
  1.1527 +          case GL_UNSIGNED_INT:
  1.1528 +            for (int i = 0; i < count; i++)
  1.1529 +            {
  1.1530 +                data[i] = static_cast<const GLuint*>(indices)[i];
  1.1531 +            }
  1.1532 +            data[count] = static_cast<const GLuint*>(indices)[0];
  1.1533 +            break;
  1.1534 +          default: UNREACHABLE();
  1.1535 +        }
  1.1536 +
  1.1537 +        if (!mLineLoopIB->unmapBuffer())
  1.1538 +        {
  1.1539 +            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
  1.1540 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1541 +        }
  1.1542 +    }
  1.1543 +    else
  1.1544 +    {
  1.1545 +        if (!mLineLoopIB)
  1.1546 +        {
  1.1547 +            mLineLoopIB = new StreamingIndexBufferInterface(this);
  1.1548 +            if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
  1.1549 +            {
  1.1550 +                delete mLineLoopIB;
  1.1551 +                mLineLoopIB = NULL;
  1.1552 +
  1.1553 +                ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
  1.1554 +                return gl::error(GL_OUT_OF_MEMORY);
  1.1555 +            }
  1.1556 +        }
  1.1557 +
  1.1558 +        // Checked by Renderer9::applyPrimitiveType
  1.1559 +        ASSERT(count >= 0);
  1.1560 +
  1.1561 +        if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
  1.1562 +        {
  1.1563 +            ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
  1.1564 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1565 +        }
  1.1566 +
  1.1567 +        const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
  1.1568 +        if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
  1.1569 +        {
  1.1570 +            ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
  1.1571 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1572 +        }
  1.1573 +
  1.1574 +        void* mappedMemory = NULL;
  1.1575 +        unsigned int offset;
  1.1576 +        if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
  1.1577 +        {
  1.1578 +            ERR("Could not map index buffer for GL_LINE_LOOP.");
  1.1579 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1580 +        }
  1.1581 +
  1.1582 +        startIndex = static_cast<unsigned int>(offset) / 2;
  1.1583 +        unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
  1.1584 +
  1.1585 +        switch (type)
  1.1586 +        {
  1.1587 +          case GL_NONE:   // Non-indexed draw
  1.1588 +            for (int i = 0; i < count; i++)
  1.1589 +            {
  1.1590 +                data[i] = i;
  1.1591 +            }
  1.1592 +            data[count] = 0;
  1.1593 +            break;
  1.1594 +          case GL_UNSIGNED_BYTE:
  1.1595 +            for (int i = 0; i < count; i++)
  1.1596 +            {
  1.1597 +                data[i] = static_cast<const GLubyte*>(indices)[i];
  1.1598 +            }
  1.1599 +            data[count] = static_cast<const GLubyte*>(indices)[0];
  1.1600 +            break;
  1.1601 +          case GL_UNSIGNED_SHORT:
  1.1602 +            for (int i = 0; i < count; i++)
  1.1603 +            {
  1.1604 +                data[i] = static_cast<const GLushort*>(indices)[i];
  1.1605 +            }
  1.1606 +            data[count] = static_cast<const GLushort*>(indices)[0];
  1.1607 +            break;
  1.1608 +          case GL_UNSIGNED_INT:
  1.1609 +            for (int i = 0; i < count; i++)
  1.1610 +            {
  1.1611 +                data[i] = static_cast<const GLuint*>(indices)[i];
  1.1612 +            }
  1.1613 +            data[count] = static_cast<const GLuint*>(indices)[0];
  1.1614 +            break;
  1.1615 +          default: UNREACHABLE();
  1.1616 +        }
  1.1617 +
  1.1618 +        if (!mLineLoopIB->unmapBuffer())
  1.1619 +        {
  1.1620 +            ERR("Could not unmap index buffer for GL_LINE_LOOP.");
  1.1621 +            return gl::error(GL_OUT_OF_MEMORY);
  1.1622 +        }
  1.1623 +    }
  1.1624 +
  1.1625 +    if (mAppliedIBSerial != mLineLoopIB->getSerial())
  1.1626 +    {
  1.1627 +        IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
  1.1628 +
  1.1629 +        mDevice->SetIndices(indexBuffer->getBuffer());
  1.1630 +        mAppliedIBSerial = mLineLoopIB->getSerial();
  1.1631 +    }
  1.1632 +
  1.1633 +    mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
  1.1634 +}
  1.1635 +
  1.1636 +template <typename T>
  1.1637 +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices)
  1.1638 +{
  1.1639 +    for (int i = 0; i < count; i++)
  1.1640 +    {
  1.1641 +        unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]);
  1.1642 +        device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
  1.1643 +    }
  1.1644 +}
  1.1645 +
  1.1646 +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
  1.1647 +{
  1.1648 +    // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
  1.1649 +    // for each individual point. This call is not expected to happen often.
  1.1650 +
  1.1651 +    if (elementArrayBuffer)
  1.1652 +    {
  1.1653 +        BufferStorage *storage = elementArrayBuffer->getStorage();
  1.1654 +        intptr_t offset = reinterpret_cast<intptr_t>(indices);
  1.1655 +        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
  1.1656 +    }
  1.1657 +
  1.1658 +    switch (type)
  1.1659 +    {
  1.1660 +        case GL_UNSIGNED_BYTE:  drawPoints<GLubyte>(mDevice, count, indices);  break;
  1.1661 +        case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices); break;
  1.1662 +        case GL_UNSIGNED_INT:   drawPoints<GLuint>(mDevice, count, indices);   break;
  1.1663 +        default: UNREACHABLE();
  1.1664 +    }
  1.1665 +}
  1.1666 +
  1.1667 +void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
  1.1668 +{
  1.1669 +    unsigned int programBinarySerial = programBinary->getSerial();
  1.1670 +    if (programBinarySerial != mAppliedProgramBinarySerial)
  1.1671 +    {
  1.1672 +        ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
  1.1673 +        ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
  1.1674 +
  1.1675 +        IDirect3DVertexShader9 *vertexShader = NULL;
  1.1676 +        if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
  1.1677 +
  1.1678 +        IDirect3DPixelShader9 *pixelShader = NULL;
  1.1679 +        if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
  1.1680 +
  1.1681 +        mDevice->SetPixelShader(pixelShader);
  1.1682 +        mDevice->SetVertexShader(vertexShader);
  1.1683 +        programBinary->dirtyAllUniforms();
  1.1684 +        mDxUniformsDirty = true;
  1.1685 +
  1.1686 +        mAppliedProgramBinarySerial = programBinarySerial;
  1.1687 +    }
  1.1688 +}
  1.1689 +
  1.1690 +void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
  1.1691 +{
  1.1692 +    for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
  1.1693 +    {
  1.1694 +        gl::Uniform *targetUniform = *ub;
  1.1695 +
  1.1696 +        if (targetUniform->dirty)
  1.1697 +        {
  1.1698 +            GLfloat *f = (GLfloat*)targetUniform->data;
  1.1699 +            GLint *i = (GLint*)targetUniform->data;
  1.1700 +
  1.1701 +            switch (targetUniform->type)
  1.1702 +            {
  1.1703 +              case GL_SAMPLER_2D:
  1.1704 +              case GL_SAMPLER_CUBE:
  1.1705 +                break;
  1.1706 +              case GL_BOOL:
  1.1707 +              case GL_BOOL_VEC2:
  1.1708 +              case GL_BOOL_VEC3:
  1.1709 +              case GL_BOOL_VEC4:
  1.1710 +                applyUniformnbv(targetUniform, i);
  1.1711 +                break;
  1.1712 +              case GL_FLOAT:
  1.1713 +              case GL_FLOAT_VEC2:
  1.1714 +              case GL_FLOAT_VEC3:
  1.1715 +              case GL_FLOAT_VEC4:
  1.1716 +              case GL_FLOAT_MAT2:
  1.1717 +              case GL_FLOAT_MAT3:
  1.1718 +              case GL_FLOAT_MAT4:
  1.1719 +                applyUniformnfv(targetUniform, f);
  1.1720 +                break;
  1.1721 +              case GL_INT:
  1.1722 +              case GL_INT_VEC2:
  1.1723 +              case GL_INT_VEC3:
  1.1724 +              case GL_INT_VEC4:
  1.1725 +                applyUniformniv(targetUniform, i);
  1.1726 +                break;
  1.1727 +              default:
  1.1728 +                UNREACHABLE();
  1.1729 +            }
  1.1730 +
  1.1731 +            targetUniform->dirty = false;
  1.1732 +        }
  1.1733 +    }
  1.1734 +
  1.1735 +    // Driver uniforms
  1.1736 +    if (mDxUniformsDirty)
  1.1737 +    {
  1.1738 +        mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
  1.1739 +        mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
  1.1740 +        mDxUniformsDirty = false;
  1.1741 +    }
  1.1742 +}
  1.1743 +
  1.1744 +void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
  1.1745 +{
  1.1746 +    if (targetUniform->psRegisterIndex >= 0)
  1.1747 +    {
  1.1748 +        mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
  1.1749 +    }
  1.1750 +
  1.1751 +    if (targetUniform->vsRegisterIndex >= 0)
  1.1752 +    {
  1.1753 +        mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
  1.1754 +    }
  1.1755 +}
  1.1756 +
  1.1757 +void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
  1.1758 +{
  1.1759 +    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
  1.1760 +    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
  1.1761 +
  1.1762 +    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
  1.1763 +    {
  1.1764 +        vector[i][0] = (GLfloat)v[4 * i + 0];
  1.1765 +        vector[i][1] = (GLfloat)v[4 * i + 1];
  1.1766 +        vector[i][2] = (GLfloat)v[4 * i + 2];
  1.1767 +        vector[i][3] = (GLfloat)v[4 * i + 3];
  1.1768 +    }
  1.1769 +
  1.1770 +    applyUniformnfv(targetUniform, (GLfloat*)vector);
  1.1771 +}
  1.1772 +
  1.1773 +void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
  1.1774 +{
  1.1775 +    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
  1.1776 +    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
  1.1777 +
  1.1778 +    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
  1.1779 +    {
  1.1780 +        vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
  1.1781 +        vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
  1.1782 +        vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
  1.1783 +        vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
  1.1784 +    }
  1.1785 +
  1.1786 +    applyUniformnfv(targetUniform, (GLfloat*)vector);
  1.1787 +}
  1.1788 +
  1.1789 +void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
  1.1790 +{
  1.1791 +    D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
  1.1792 +                                   gl::unorm<8>(clearParams.colorClearValue.red),
  1.1793 +                                   gl::unorm<8>(clearParams.colorClearValue.green),
  1.1794 +                                   gl::unorm<8>(clearParams.colorClearValue.blue));
  1.1795 +    float depth = gl::clamp01(clearParams.depthClearValue);
  1.1796 +    int stencil = clearParams.stencilClearValue & 0x000000FF;
  1.1797 +
  1.1798 +    unsigned int stencilUnmasked = 0x0;
  1.1799 +    if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
  1.1800 +    {
  1.1801 +        unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
  1.1802 +        stencilUnmasked = (0x1 << stencilSize) - 1;
  1.1803 +    }
  1.1804 +
  1.1805 +    bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
  1.1806 +
  1.1807 +    const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
  1.1808 +                                        (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
  1.1809 +    const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
  1.1810 +                                      !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
  1.1811 +                                        clearParams.colorMaskBlue && alphaUnmasked);
  1.1812 +
  1.1813 +    if (needMaskedColorClear || needMaskedStencilClear)
  1.1814 +    {
  1.1815 +        // State which is altered in all paths from this point to the clear call is saved.
  1.1816 +        // State which is altered in only some paths will be flagged dirty in the case that
  1.1817 +        //  that path is taken.
  1.1818 +        HRESULT hr;
  1.1819 +        if (mMaskedClearSavedState == NULL)
  1.1820 +        {
  1.1821 +            hr = mDevice->BeginStateBlock();
  1.1822 +            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
  1.1823 +
  1.1824 +            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  1.1825 +            mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  1.1826 +            mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  1.1827 +            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1.1828 +            mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  1.1829 +            mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  1.1830 +            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1.1831 +            mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
  1.1832 +            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
  1.1833 +            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1.1834 +            mDevice->SetPixelShader(NULL);
  1.1835 +            mDevice->SetVertexShader(NULL);
  1.1836 +            mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
  1.1837 +            mDevice->SetStreamSource(0, NULL, 0, 0);
  1.1838 +            mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
  1.1839 +            mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1.1840 +            mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  1.1841 +            mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1.1842 +            mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  1.1843 +            mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
  1.1844 +            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
  1.1845 +
  1.1846 +            for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
  1.1847 +            {
  1.1848 +                mDevice->SetStreamSourceFreq(i, 1);
  1.1849 +            }
  1.1850 +
  1.1851 +            hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
  1.1852 +            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
  1.1853 +        }
  1.1854 +
  1.1855 +        ASSERT(mMaskedClearSavedState != NULL);
  1.1856 +
  1.1857 +        if (mMaskedClearSavedState != NULL)
  1.1858 +        {
  1.1859 +            hr = mMaskedClearSavedState->Capture();
  1.1860 +            ASSERT(SUCCEEDED(hr));
  1.1861 +        }
  1.1862 +
  1.1863 +        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  1.1864 +        mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  1.1865 +        mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  1.1866 +        mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1.1867 +        mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  1.1868 +        mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  1.1869 +        mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1.1870 +        mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
  1.1871 +
  1.1872 +        if (clearParams.mask & GL_COLOR_BUFFER_BIT)
  1.1873 +        {
  1.1874 +            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
  1.1875 +                                    gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
  1.1876 +                                                              clearParams.colorMaskGreen,
  1.1877 +                                                              clearParams.colorMaskBlue,
  1.1878 +                                                              clearParams.colorMaskAlpha));
  1.1879 +        }
  1.1880 +        else
  1.1881 +        {
  1.1882 +            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
  1.1883 +        }
  1.1884 +
  1.1885 +        if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
  1.1886 +        {
  1.1887 +            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
  1.1888 +            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
  1.1889 +            mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
  1.1890 +            mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
  1.1891 +            mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
  1.1892 +            mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
  1.1893 +            mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
  1.1894 +            mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
  1.1895 +        }
  1.1896 +        else
  1.1897 +        {
  1.1898 +            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1.1899 +        }
  1.1900 +
  1.1901 +        mDevice->SetPixelShader(NULL);
  1.1902 +        mDevice->SetVertexShader(NULL);
  1.1903 +        mDevice->SetFVF(D3DFVF_XYZRHW);
  1.1904 +        mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
  1.1905 +        mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1.1906 +        mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  1.1907 +        mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1.1908 +        mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  1.1909 +        mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
  1.1910 +        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
  1.1911 +
  1.1912 +        for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
  1.1913 +        {
  1.1914 +            mDevice->SetStreamSourceFreq(i, 1);
  1.1915 +        }
  1.1916 +
  1.1917 +        float quad[4][4];   // A quadrilateral covering the target, aligned to match the edges
  1.1918 +        quad[0][0] = -0.5f;
  1.1919 +        quad[0][1] = mRenderTargetDesc.height - 0.5f;
  1.1920 +        quad[0][2] = 0.0f;
  1.1921 +        quad[0][3] = 1.0f;
  1.1922 +
  1.1923 +        quad[1][0] = mRenderTargetDesc.width - 0.5f;
  1.1924 +        quad[1][1] = mRenderTargetDesc.height - 0.5f;
  1.1925 +        quad[1][2] = 0.0f;
  1.1926 +        quad[1][3] = 1.0f;
  1.1927 +
  1.1928 +        quad[2][0] = -0.5f;
  1.1929 +        quad[2][1] = -0.5f;
  1.1930 +        quad[2][2] = 0.0f;
  1.1931 +        quad[2][3] = 1.0f;
  1.1932 +
  1.1933 +        quad[3][0] = mRenderTargetDesc.width - 0.5f;
  1.1934 +        quad[3][1] = -0.5f;
  1.1935 +        quad[3][2] = 0.0f;
  1.1936 +        quad[3][3] = 1.0f;
  1.1937 +
  1.1938 +        startScene();
  1.1939 +        mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
  1.1940 +
  1.1941 +        if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
  1.1942 +        {
  1.1943 +            mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  1.1944 +            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  1.1945 +            mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
  1.1946 +        }
  1.1947 +
  1.1948 +        if (mMaskedClearSavedState != NULL)
  1.1949 +        {
  1.1950 +            mMaskedClearSavedState->Apply();
  1.1951 +        }
  1.1952 +    }
  1.1953 +    else if (clearParams.mask)
  1.1954 +    {
  1.1955 +        DWORD dxClearFlags = 0;
  1.1956 +        if (clearParams.mask & GL_COLOR_BUFFER_BIT)
  1.1957 +        {
  1.1958 +            dxClearFlags |= D3DCLEAR_TARGET;
  1.1959 +        }
  1.1960 +        if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
  1.1961 +        {
  1.1962 +            dxClearFlags |= D3DCLEAR_ZBUFFER;
  1.1963 +        }
  1.1964 +        if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
  1.1965 +        {
  1.1966 +            dxClearFlags |= D3DCLEAR_STENCIL;
  1.1967 +        }
  1.1968 +
  1.1969 +        mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
  1.1970 +    }
  1.1971 +}
  1.1972 +
  1.1973 +void Renderer9::markAllStateDirty()
  1.1974 +{
  1.1975 +    mAppliedRenderTargetSerial = 0;
  1.1976 +    mAppliedDepthbufferSerial = 0;
  1.1977 +    mAppliedStencilbufferSerial = 0;
  1.1978 +    mDepthStencilInitialized = false;
  1.1979 +    mRenderTargetDescInitialized = false;
  1.1980 +
  1.1981 +    mForceSetDepthStencilState = true;
  1.1982 +    mForceSetRasterState = true;
  1.1983 +    mForceSetScissor = true;
  1.1984 +    mForceSetViewport = true;
  1.1985 +    mForceSetBlendState = true;
  1.1986 +
  1.1987 +    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
  1.1988 +    {
  1.1989 +        mForceSetVertexSamplerStates[i] = true;
  1.1990 +        mCurVertexTextureSerials[i] = 0;
  1.1991 +    }
  1.1992 +    for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
  1.1993 +    {
  1.1994 +        mForceSetPixelSamplerStates[i] = true;
  1.1995 +        mCurPixelTextureSerials[i] = 0;
  1.1996 +    }
  1.1997 +
  1.1998 +    mAppliedIBSerial = 0;
  1.1999 +    mAppliedProgramBinarySerial = 0;
  1.2000 +    mDxUniformsDirty = true;
  1.2001 +
  1.2002 +    mVertexDeclarationCache.markStateDirty();
  1.2003 +}
  1.2004 +
  1.2005 +void Renderer9::releaseDeviceResources()
  1.2006 +{
  1.2007 +    while (!mEventQueryPool.empty())
  1.2008 +    {
  1.2009 +        mEventQueryPool.back()->Release();
  1.2010 +        mEventQueryPool.pop_back();
  1.2011 +    }
  1.2012 +
  1.2013 +    if (mMaskedClearSavedState)
  1.2014 +    {
  1.2015 +        mMaskedClearSavedState->Release();
  1.2016 +        mMaskedClearSavedState = NULL;
  1.2017 +    }
  1.2018 +
  1.2019 +    mVertexShaderCache.clear();
  1.2020 +    mPixelShaderCache.clear();
  1.2021 +
  1.2022 +    delete mBlit;
  1.2023 +    mBlit = NULL;
  1.2024 +
  1.2025 +    delete mVertexDataManager;
  1.2026 +    mVertexDataManager = NULL;
  1.2027 +
  1.2028 +    delete mIndexDataManager;
  1.2029 +    mIndexDataManager = NULL;
  1.2030 +
  1.2031 +    delete mLineLoopIB;
  1.2032 +    mLineLoopIB = NULL;
  1.2033 +
  1.2034 +    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  1.2035 +    {
  1.2036 +        delete mNullColorbufferCache[i].buffer;
  1.2037 +        mNullColorbufferCache[i].buffer = NULL;
  1.2038 +    }
  1.2039 +
  1.2040 +}
  1.2041 +
  1.2042 +
  1.2043 +void Renderer9::notifyDeviceLost()
  1.2044 +{
  1.2045 +    mDeviceLost = true;
  1.2046 +    mDisplay->notifyDeviceLost();
  1.2047 +}
  1.2048 +
  1.2049 +bool Renderer9::isDeviceLost()
  1.2050 +{
  1.2051 +    return mDeviceLost;
  1.2052 +}
  1.2053 +
  1.2054 +// set notify to true to broadcast a message to all contexts of the device loss
  1.2055 +bool Renderer9::testDeviceLost(bool notify)
  1.2056 +{
  1.2057 +    HRESULT status = S_OK;
  1.2058 +
  1.2059 +    if (mDeviceEx)
  1.2060 +    {
  1.2061 +        status = mDeviceEx->CheckDeviceState(NULL);
  1.2062 +    }
  1.2063 +    else if (mDevice)
  1.2064 +    {
  1.2065 +        status = mDevice->TestCooperativeLevel();
  1.2066 +    }
  1.2067 +    else
  1.2068 +    {
  1.2069 +        // No device yet, so no reset required
  1.2070 +    }
  1.2071 +
  1.2072 +    bool isLost = FAILED(status) || d3d9::isDeviceLostError(status);
  1.2073 +
  1.2074 +    if (isLost)
  1.2075 +    {
  1.2076 +        // ensure we note the device loss --
  1.2077 +        // we'll probably get this done again by notifyDeviceLost
  1.2078 +        // but best to remember it!
  1.2079 +        // Note that we don't want to clear the device loss status here
  1.2080 +        // -- this needs to be done by resetDevice
  1.2081 +        mDeviceLost = true;
  1.2082 +        if (notify)
  1.2083 +        {
  1.2084 +            notifyDeviceLost();
  1.2085 +        }
  1.2086 +    }
  1.2087 +
  1.2088 +    return isLost;
  1.2089 +}
  1.2090 +
  1.2091 +bool Renderer9::testDeviceResettable()
  1.2092 +{
  1.2093 +    HRESULT status = D3D_OK;
  1.2094 +
  1.2095 +    if (mDeviceEx)
  1.2096 +    {
  1.2097 +        status = mDeviceEx->CheckDeviceState(NULL);
  1.2098 +    }
  1.2099 +    else if (mDevice)
  1.2100 +    {
  1.2101 +        status = mDevice->TestCooperativeLevel();
  1.2102 +    }
  1.2103 +
  1.2104 +    // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
  1.2105 +    // DEVICEREMOVED indicates the device has been stopped and must be recreated
  1.2106 +    switch (status)
  1.2107 +    {
  1.2108 +      case D3DERR_DEVICENOTRESET:
  1.2109 +      case D3DERR_DEVICEHUNG:
  1.2110 +        return true;
  1.2111 +      case D3DERR_DEVICELOST:
  1.2112 +        return (mDeviceEx != NULL);
  1.2113 +      case D3DERR_DEVICEREMOVED:
  1.2114 +        UNIMPLEMENTED();
  1.2115 +        return false;
  1.2116 +      default:
  1.2117 +        return false;
  1.2118 +    }
  1.2119 +}
  1.2120 +
  1.2121 +bool Renderer9::resetDevice()
  1.2122 +{
  1.2123 +    releaseDeviceResources();
  1.2124 +
  1.2125 +    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
  1.2126 +
  1.2127 +    HRESULT result = D3D_OK;
  1.2128 +    bool lost = testDeviceLost(false);
  1.2129 +    int attempts = 3;
  1.2130 +
  1.2131 +    while (lost && attempts > 0)
  1.2132 +    {
  1.2133 +        if (mDeviceEx)
  1.2134 +        {
  1.2135 +            Sleep(500);   // Give the graphics driver some CPU time
  1.2136 +            result = mDeviceEx->ResetEx(&presentParameters, NULL);
  1.2137 +        }
  1.2138 +        else
  1.2139 +        {
  1.2140 +            result = mDevice->TestCooperativeLevel();
  1.2141 +            while (result == D3DERR_DEVICELOST)
  1.2142 +            {
  1.2143 +                Sleep(100);   // Give the graphics driver some CPU time
  1.2144 +                result = mDevice->TestCooperativeLevel();
  1.2145 +            }
  1.2146 +
  1.2147 +            if (result == D3DERR_DEVICENOTRESET)
  1.2148 +            {
  1.2149 +                result = mDevice->Reset(&presentParameters);
  1.2150 +            }
  1.2151 +        }
  1.2152 +
  1.2153 +        lost = testDeviceLost(false);
  1.2154 +        attempts --;
  1.2155 +    }
  1.2156 +
  1.2157 +    if (FAILED(result))
  1.2158 +    {
  1.2159 +        ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
  1.2160 +        return false;
  1.2161 +    }
  1.2162 +
  1.2163 +    // reset device defaults
  1.2164 +    initializeDevice();
  1.2165 +    mDeviceLost = false;
  1.2166 +
  1.2167 +    return true;
  1.2168 +}
  1.2169 +
  1.2170 +DWORD Renderer9::getAdapterVendor() const
  1.2171 +{
  1.2172 +    return mAdapterIdentifier.VendorId;
  1.2173 +}
  1.2174 +
  1.2175 +std::string Renderer9::getRendererDescription() const
  1.2176 +{
  1.2177 +    std::ostringstream rendererString;
  1.2178 +
  1.2179 +    rendererString << mAdapterIdentifier.Description;
  1.2180 +    if (getShareHandleSupport())
  1.2181 +    {
  1.2182 +        rendererString << " Direct3D9Ex";
  1.2183 +    }
  1.2184 +    else
  1.2185 +    {
  1.2186 +        rendererString << " Direct3D9";
  1.2187 +    }
  1.2188 +
  1.2189 +    rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
  1.2190 +    rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
  1.2191 +
  1.2192 +    return rendererString.str();
  1.2193 +}
  1.2194 +
  1.2195 +GUID Renderer9::getAdapterIdentifier() const
  1.2196 +{
  1.2197 +    return mAdapterIdentifier.DeviceIdentifier;
  1.2198 +}
  1.2199 +
  1.2200 +void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
  1.2201 +{
  1.2202 +    for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
  1.2203 +    {
  1.2204 +        HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
  1.2205 +                                                           TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
  1.2206 +
  1.2207 +        multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
  1.2208 +    }
  1.2209 +}
  1.2210 +
  1.2211 +bool Renderer9::getBGRATextureSupport() const
  1.2212 +{
  1.2213 +    // DirectX 9 always supports BGRA
  1.2214 +    return true;
  1.2215 +}
  1.2216 +
  1.2217 +bool Renderer9::getDXT1TextureSupport()
  1.2218 +{
  1.2219 +    return mDXT1TextureSupport;
  1.2220 +}
  1.2221 +
  1.2222 +bool Renderer9::getDXT3TextureSupport()
  1.2223 +{
  1.2224 +    return mDXT3TextureSupport;
  1.2225 +}
  1.2226 +
  1.2227 +bool Renderer9::getDXT5TextureSupport()
  1.2228 +{
  1.2229 +    return mDXT5TextureSupport;
  1.2230 +}
  1.2231 +
  1.2232 +bool Renderer9::getDepthTextureSupport() const
  1.2233 +{
  1.2234 +    return mDepthTextureSupport;
  1.2235 +}
  1.2236 +
  1.2237 +bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
  1.2238 +{
  1.2239 +    *filtering = mFloat32FilterSupport;
  1.2240 +    *renderable = mFloat32RenderSupport;
  1.2241 +    return mFloat32TextureSupport;
  1.2242 +}
  1.2243 +
  1.2244 +bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
  1.2245 +{
  1.2246 +    *filtering = mFloat16FilterSupport;
  1.2247 +    *renderable = mFloat16RenderSupport;
  1.2248 +    return mFloat16TextureSupport;
  1.2249 +}
  1.2250 +
  1.2251 +bool Renderer9::getLuminanceTextureSupport()
  1.2252 +{
  1.2253 +    return mLuminanceTextureSupport;
  1.2254 +}
  1.2255 +
  1.2256 +bool Renderer9::getLuminanceAlphaTextureSupport()
  1.2257 +{
  1.2258 +    return mLuminanceAlphaTextureSupport;
  1.2259 +}
  1.2260 +
  1.2261 +bool Renderer9::getTextureFilterAnisotropySupport() const
  1.2262 +{
  1.2263 +    return mSupportsTextureFilterAnisotropy;
  1.2264 +}
  1.2265 +
  1.2266 +float Renderer9::getTextureMaxAnisotropy() const
  1.2267 +{
  1.2268 +    if (mSupportsTextureFilterAnisotropy)
  1.2269 +    {
  1.2270 +        return static_cast<float>(mDeviceCaps.MaxAnisotropy);
  1.2271 +    }
  1.2272 +    return 1.0f;
  1.2273 +}
  1.2274 +
  1.2275 +bool Renderer9::getEventQuerySupport()
  1.2276 +{
  1.2277 +    return mEventQuerySupport;
  1.2278 +}
  1.2279 +
  1.2280 +unsigned int Renderer9::getMaxVertexTextureImageUnits() const
  1.2281 +{
  1.2282 +    META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
  1.2283 +    return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
  1.2284 +}
  1.2285 +
  1.2286 +unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
  1.2287 +{
  1.2288 +    return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
  1.2289 +}
  1.2290 +
  1.2291 +unsigned int Renderer9::getReservedVertexUniformVectors() const
  1.2292 +{
  1.2293 +    return 2;   // dx_ViewAdjust and dx_DepthRange.
  1.2294 +}
  1.2295 +
  1.2296 +unsigned int Renderer9::getReservedFragmentUniformVectors() const
  1.2297 +{
  1.2298 +    return 3;   // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
  1.2299 +}
  1.2300 +
  1.2301 +unsigned int Renderer9::getMaxVertexUniformVectors() const
  1.2302 +{
  1.2303 +    return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
  1.2304 +}
  1.2305 +
  1.2306 +unsigned int Renderer9::getMaxFragmentUniformVectors() const
  1.2307 +{
  1.2308 +    const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
  1.2309 +
  1.2310 +    return maxPixelConstantVectors - getReservedFragmentUniformVectors();
  1.2311 +}
  1.2312 +
  1.2313 +unsigned int Renderer9::getMaxVaryingVectors() const
  1.2314 +{
  1.2315 +    return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
  1.2316 +}
  1.2317 +
  1.2318 +bool Renderer9::getNonPower2TextureSupport() const
  1.2319 +{
  1.2320 +    return mSupportsNonPower2Textures;
  1.2321 +}
  1.2322 +
  1.2323 +bool Renderer9::getOcclusionQuerySupport() const
  1.2324 +{
  1.2325 +    return mOcclusionQuerySupport;
  1.2326 +}
  1.2327 +
  1.2328 +bool Renderer9::getInstancingSupport() const
  1.2329 +{
  1.2330 +    return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
  1.2331 +}
  1.2332 +
  1.2333 +bool Renderer9::getShareHandleSupport() const
  1.2334 +{
  1.2335 +    // PIX doesn't seem to support using share handles, so disable them.
  1.2336 +    return (mD3d9Ex != NULL) && !gl::perfActive();
  1.2337 +}
  1.2338 +
  1.2339 +bool Renderer9::getDerivativeInstructionSupport() const
  1.2340 +{
  1.2341 +    return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
  1.2342 +}
  1.2343 +
  1.2344 +bool Renderer9::getPostSubBufferSupport() const
  1.2345 +{
  1.2346 +    return true;
  1.2347 +}
  1.2348 +
  1.2349 +int Renderer9::getMajorShaderModel() const
  1.2350 +{
  1.2351 +    return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
  1.2352 +}
  1.2353 +
  1.2354 +float Renderer9::getMaxPointSize() const
  1.2355 +{
  1.2356 +    // Point size clamped at 1.0f for SM2
  1.2357 +    return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
  1.2358 +}
  1.2359 +
  1.2360 +int Renderer9::getMaxViewportDimension() const
  1.2361 +{
  1.2362 +    int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
  1.2363 +                                       (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
  1.2364 +    return maxTextureDimension;
  1.2365 +}
  1.2366 +
  1.2367 +int Renderer9::getMaxTextureWidth() const
  1.2368 +{
  1.2369 +    return (int)mDeviceCaps.MaxTextureWidth;
  1.2370 +}
  1.2371 +
  1.2372 +int Renderer9::getMaxTextureHeight() const
  1.2373 +{
  1.2374 +    return (int)mDeviceCaps.MaxTextureHeight;
  1.2375 +}
  1.2376 +
  1.2377 +bool Renderer9::get32BitIndexSupport() const
  1.2378 +{
  1.2379 +    return mDeviceCaps.MaxVertexIndex >= (1 << 16);
  1.2380 +}
  1.2381 +
  1.2382 +DWORD Renderer9::getCapsDeclTypes() const
  1.2383 +{
  1.2384 +    return mDeviceCaps.DeclTypes;
  1.2385 +}
  1.2386 +
  1.2387 +int Renderer9::getMinSwapInterval() const
  1.2388 +{
  1.2389 +    return mMinSwapInterval;
  1.2390 +}
  1.2391 +
  1.2392 +int Renderer9::getMaxSwapInterval() const
  1.2393 +{
  1.2394 +    return mMaxSwapInterval;
  1.2395 +}
  1.2396 +
  1.2397 +int Renderer9::getMaxSupportedSamples() const
  1.2398 +{
  1.2399 +    return mMaxSupportedSamples;
  1.2400 +}
  1.2401 +
  1.2402 +int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
  1.2403 +{
  1.2404 +    if (requested == 0)
  1.2405 +    {
  1.2406 +        return requested;
  1.2407 +    }
  1.2408 +
  1.2409 +    std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
  1.2410 +    if (itr == mMultiSampleSupport.end())
  1.2411 +    {
  1.2412 +        if (format == D3DFMT_UNKNOWN)
  1.2413 +            return 0;
  1.2414 +        return -1;
  1.2415 +    }
  1.2416 +
  1.2417 +    for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
  1.2418 +    {
  1.2419 +        if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
  1.2420 +        {
  1.2421 +            return i;
  1.2422 +        }
  1.2423 +    }
  1.2424 +
  1.2425 +    return -1;
  1.2426 +}
  1.2427 +
  1.2428 +unsigned int Renderer9::getMaxRenderTargets() const
  1.2429 +{
  1.2430 +    // we do not support MRT in d3d9
  1.2431 +    return 1;
  1.2432 +}
  1.2433 +
  1.2434 +D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
  1.2435 +{
  1.2436 +    switch (internalformat)
  1.2437 +    {
  1.2438 +      case GL_DEPTH_COMPONENT16:
  1.2439 +      case GL_DEPTH_COMPONENT32_OES:
  1.2440 +      case GL_DEPTH24_STENCIL8_OES:
  1.2441 +        return D3DFMT_INTZ;
  1.2442 +      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  1.2443 +      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  1.2444 +        return D3DFMT_DXT1;
  1.2445 +      case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
  1.2446 +        return D3DFMT_DXT3;
  1.2447 +      case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
  1.2448 +        return D3DFMT_DXT5;
  1.2449 +      case GL_RGBA32F_EXT:
  1.2450 +      case GL_RGB32F_EXT:
  1.2451 +      case GL_ALPHA32F_EXT:
  1.2452 +      case GL_LUMINANCE32F_EXT:
  1.2453 +      case GL_LUMINANCE_ALPHA32F_EXT:
  1.2454 +        return D3DFMT_A32B32G32R32F;
  1.2455 +      case GL_RGBA16F_EXT:
  1.2456 +      case GL_RGB16F_EXT:
  1.2457 +      case GL_ALPHA16F_EXT:
  1.2458 +      case GL_LUMINANCE16F_EXT:
  1.2459 +      case GL_LUMINANCE_ALPHA16F_EXT:
  1.2460 +        return D3DFMT_A16B16G16R16F;
  1.2461 +      case GL_LUMINANCE8_EXT:
  1.2462 +        if (getLuminanceTextureSupport())
  1.2463 +        {
  1.2464 +            return D3DFMT_L8;
  1.2465 +        }
  1.2466 +        break;
  1.2467 +      case GL_LUMINANCE8_ALPHA8_EXT:
  1.2468 +        if (getLuminanceAlphaTextureSupport())
  1.2469 +        {
  1.2470 +            return D3DFMT_A8L8;
  1.2471 +        }
  1.2472 +        break;
  1.2473 +      case GL_RGB8_OES:
  1.2474 +      case GL_RGB565:
  1.2475 +        return D3DFMT_X8R8G8B8;
  1.2476 +    }
  1.2477 +
  1.2478 +    return D3DFMT_A8R8G8B8;
  1.2479 +}
  1.2480 +
  1.2481 +bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
  1.2482 +{
  1.2483 +    bool result = false;
  1.2484 +
  1.2485 +    if (source && dest)
  1.2486 +    {
  1.2487 +        TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
  1.2488 +        TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
  1.2489 +
  1.2490 +        int levels = source9->levelCount();
  1.2491 +        for (int i = 0; i < levels; ++i)
  1.2492 +        {
  1.2493 +            IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
  1.2494 +            IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
  1.2495 +            
  1.2496 +            result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
  1.2497 +
  1.2498 +            if (srcSurf) srcSurf->Release();
  1.2499 +            if (dstSurf) dstSurf->Release();
  1.2500 +
  1.2501 +            if (!result)
  1.2502 +                return false;
  1.2503 +        }
  1.2504 +    }
  1.2505 +
  1.2506 +    return result;
  1.2507 +}
  1.2508 +
  1.2509 +bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
  1.2510 +{
  1.2511 +    bool result = false;
  1.2512 +
  1.2513 +    if (source && dest)
  1.2514 +    {
  1.2515 +        TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
  1.2516 +        TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
  1.2517 +        int levels = source9->levelCount();
  1.2518 +        for (int f = 0; f < 6; f++)
  1.2519 +        {
  1.2520 +            for (int i = 0; i < levels; i++)
  1.2521 +            {
  1.2522 +                IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
  1.2523 +                IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
  1.2524 +
  1.2525 +                result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
  1.2526 +
  1.2527 +                if (srcSurf) srcSurf->Release();
  1.2528 +                if (dstSurf) dstSurf->Release();
  1.2529 +
  1.2530 +                if (!result)
  1.2531 +                    return false;
  1.2532 +            }
  1.2533 +        }
  1.2534 +    }
  1.2535 +
  1.2536 +    return result;
  1.2537 +}
  1.2538 +
  1.2539 +D3DPOOL Renderer9::getBufferPool(DWORD usage) const
  1.2540 +{
  1.2541 +    if (mD3d9Ex != NULL)
  1.2542 +    {
  1.2543 +        return D3DPOOL_DEFAULT;
  1.2544 +    }
  1.2545 +    else
  1.2546 +    {
  1.2547 +        if (!(usage & D3DUSAGE_DYNAMIC))
  1.2548 +        {
  1.2549 +            return D3DPOOL_MANAGED;
  1.2550 +        }
  1.2551 +    }
  1.2552 +
  1.2553 +    return D3DPOOL_DEFAULT;
  1.2554 +}
  1.2555 +
  1.2556 +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
  1.2557 +                          GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
  1.2558 +{
  1.2559 +    RECT rect;
  1.2560 +    rect.left = sourceRect.x;
  1.2561 +    rect.top = sourceRect.y;
  1.2562 +    rect.right = sourceRect.x + sourceRect.width;
  1.2563 +    rect.bottom = sourceRect.y + sourceRect.height;
  1.2564 +
  1.2565 +    return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
  1.2566 +}
  1.2567 +
  1.2568 +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
  1.2569 +                          GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
  1.2570 +{
  1.2571 +    RECT rect;
  1.2572 +    rect.left = sourceRect.x;
  1.2573 +    rect.top = sourceRect.y;
  1.2574 +    rect.right = sourceRect.x + sourceRect.width;
  1.2575 +    rect.bottom = sourceRect.y + sourceRect.height;
  1.2576 +
  1.2577 +    return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
  1.2578 +}
  1.2579 +
  1.2580 +bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
  1.2581 +                         bool blitRenderTarget, bool blitDepthStencil)
  1.2582 +{
  1.2583 +    endScene();
  1.2584 +
  1.2585 +    if (blitRenderTarget)
  1.2586 +    {
  1.2587 +        gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
  1.2588 +        gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
  1.2589 +        RenderTarget9 *readRenderTarget = NULL;
  1.2590 +        RenderTarget9 *drawRenderTarget = NULL;
  1.2591 +        IDirect3DSurface9* readSurface = NULL;
  1.2592 +        IDirect3DSurface9* drawSurface = NULL;
  1.2593 +
  1.2594 +        if (readBuffer)
  1.2595 +        {
  1.2596 +            readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
  1.2597 +        }
  1.2598 +        if (drawBuffer)
  1.2599 +        {
  1.2600 +            drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
  1.2601 +        }
  1.2602 +
  1.2603 +        if (readRenderTarget)
  1.2604 +        {
  1.2605 +            readSurface = readRenderTarget->getSurface();
  1.2606 +        }
  1.2607 +        if (drawRenderTarget)
  1.2608 +        {
  1.2609 +            drawSurface = drawRenderTarget->getSurface();
  1.2610 +        }
  1.2611 +
  1.2612 +        if (!readSurface || !drawSurface)
  1.2613 +        {
  1.2614 +            ERR("Failed to retrieve the render target.");
  1.2615 +            return gl::error(GL_OUT_OF_MEMORY, false);
  1.2616 +        }
  1.2617 +
  1.2618 +        RECT srcRect;
  1.2619 +        srcRect.left = readRect.x;
  1.2620 +        srcRect.right = readRect.x + readRect.width;
  1.2621 +        srcRect.top = readRect.y;
  1.2622 +        srcRect.bottom = readRect.y + readRect.height;
  1.2623 +
  1.2624 +        RECT dstRect;
  1.2625 +        dstRect.left = drawRect.x;
  1.2626 +        dstRect.right = drawRect.x + drawRect.width;
  1.2627 +        dstRect.top = drawRect.y;
  1.2628 +        dstRect.bottom = drawRect.y + drawRect.height;
  1.2629 +
  1.2630 +        HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
  1.2631 +
  1.2632 +        readSurface->Release();
  1.2633 +        drawSurface->Release();
  1.2634 +
  1.2635 +        if (FAILED(result))
  1.2636 +        {
  1.2637 +            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
  1.2638 +            return false;
  1.2639 +        }
  1.2640 +    }
  1.2641 +
  1.2642 +    if (blitDepthStencil)
  1.2643 +    {
  1.2644 +        gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
  1.2645 +        gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
  1.2646 +        RenderTarget9 *readDepthStencil = NULL;
  1.2647 +        RenderTarget9 *drawDepthStencil = NULL;
  1.2648 +        IDirect3DSurface9* readSurface = NULL;
  1.2649 +        IDirect3DSurface9* drawSurface = NULL;
  1.2650 +
  1.2651 +        if (readBuffer)
  1.2652 +        {
  1.2653 +            readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
  1.2654 +        }
  1.2655 +        if (drawBuffer)
  1.2656 +        {
  1.2657 +            drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
  1.2658 +        }
  1.2659 +
  1.2660 +        if (readDepthStencil)
  1.2661 +        {
  1.2662 +            readSurface = readDepthStencil->getSurface();
  1.2663 +        }
  1.2664 +        if (drawDepthStencil)
  1.2665 +        {
  1.2666 +            drawSurface = drawDepthStencil->getSurface();
  1.2667 +        }
  1.2668 +
  1.2669 +        if (!readSurface || !drawSurface)
  1.2670 +        {
  1.2671 +            ERR("Failed to retrieve the render target.");
  1.2672 +            return gl::error(GL_OUT_OF_MEMORY, false);
  1.2673 +        }
  1.2674 +
  1.2675 +        HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
  1.2676 +
  1.2677 +        readSurface->Release();
  1.2678 +        drawSurface->Release();
  1.2679 +
  1.2680 +        if (FAILED(result))
  1.2681 +        {
  1.2682 +            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
  1.2683 +            return false;
  1.2684 +        }
  1.2685 +    }
  1.2686 +
  1.2687 +    return true;
  1.2688 +}
  1.2689 +
  1.2690 +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 
  1.2691 +                           GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
  1.2692 +{
  1.2693 +    RenderTarget9 *renderTarget = NULL;
  1.2694 +    IDirect3DSurface9 *surface = NULL;
  1.2695 +    gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
  1.2696 +
  1.2697 +    if (colorbuffer)
  1.2698 +    {
  1.2699 +        renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
  1.2700 +    }
  1.2701 +    
  1.2702 +    if (renderTarget)
  1.2703 +    {
  1.2704 +        surface = renderTarget->getSurface();
  1.2705 +    }
  1.2706 +
  1.2707 +    if (!surface)
  1.2708 +    {
  1.2709 +        // context must be lost
  1.2710 +        return;
  1.2711 +    }
  1.2712 +
  1.2713 +    D3DSURFACE_DESC desc;
  1.2714 +    surface->GetDesc(&desc);
  1.2715 +
  1.2716 +    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
  1.2717 +    {
  1.2718 +        UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
  1.2719 +        surface->Release();
  1.2720 +        return gl::error(GL_OUT_OF_MEMORY);
  1.2721 +    }
  1.2722 +
  1.2723 +    HRESULT result;
  1.2724 +    IDirect3DSurface9 *systemSurface = NULL;
  1.2725 +    bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
  1.2726 +                          x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
  1.2727 +                          desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
  1.2728 +    if (directToPixels)
  1.2729 +    {
  1.2730 +        // Use the pixels ptr as a shared handle to write directly into client's memory
  1.2731 +        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  1.2732 +                                                      D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
  1.2733 +        if (FAILED(result))
  1.2734 +        {
  1.2735 +            // Try again without the shared handle
  1.2736 +            directToPixels = false;
  1.2737 +        }
  1.2738 +    }
  1.2739 +
  1.2740 +    if (!directToPixels)
  1.2741 +    {
  1.2742 +        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  1.2743 +                                                      D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
  1.2744 +        if (FAILED(result))
  1.2745 +        {
  1.2746 +            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
  1.2747 +            surface->Release();
  1.2748 +            return gl::error(GL_OUT_OF_MEMORY);
  1.2749 +        }
  1.2750 +    }
  1.2751 +
  1.2752 +    result = mDevice->GetRenderTargetData(surface, systemSurface);
  1.2753 +    surface->Release();
  1.2754 +    surface = NULL;
  1.2755 +
  1.2756 +    if (FAILED(result))
  1.2757 +    {
  1.2758 +        systemSurface->Release();
  1.2759 +
  1.2760 +        // It turns out that D3D will sometimes produce more error
  1.2761 +        // codes than those documented.
  1.2762 +        if (d3d9::isDeviceLostError(result))
  1.2763 +        {
  1.2764 +            notifyDeviceLost();
  1.2765 +            return gl::error(GL_OUT_OF_MEMORY);
  1.2766 +        }
  1.2767 +        else
  1.2768 +        {
  1.2769 +            UNREACHABLE();
  1.2770 +            return;
  1.2771 +        }
  1.2772 +
  1.2773 +    }
  1.2774 +
  1.2775 +    if (directToPixels)
  1.2776 +    {
  1.2777 +        systemSurface->Release();
  1.2778 +        return;
  1.2779 +    }
  1.2780 +
  1.2781 +    RECT rect;
  1.2782 +    rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
  1.2783 +    rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
  1.2784 +    rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
  1.2785 +    rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
  1.2786 +
  1.2787 +    D3DLOCKED_RECT lock;
  1.2788 +    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
  1.2789 +
  1.2790 +    if (FAILED(result))
  1.2791 +    {
  1.2792 +        UNREACHABLE();
  1.2793 +        systemSurface->Release();
  1.2794 +
  1.2795 +        return;   // No sensible error to generate
  1.2796 +    }
  1.2797 +
  1.2798 +    unsigned char *dest = (unsigned char*)pixels;
  1.2799 +    unsigned short *dest16 = (unsigned short*)pixels;
  1.2800 +
  1.2801 +    unsigned char *source;
  1.2802 +    int inputPitch;
  1.2803 +    if (packReverseRowOrder)
  1.2804 +    {
  1.2805 +        source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
  1.2806 +        inputPitch = -lock.Pitch;
  1.2807 +    }
  1.2808 +    else
  1.2809 +    {
  1.2810 +        source = (unsigned char*)lock.pBits;
  1.2811 +        inputPitch = lock.Pitch;
  1.2812 +    }
  1.2813 +
  1.2814 +    unsigned int fastPixelSize = 0;
  1.2815 +
  1.2816 +    if (desc.Format == D3DFMT_A8R8G8B8 &&
  1.2817 +        format == GL_BGRA_EXT &&
  1.2818 +        type == GL_UNSIGNED_BYTE)
  1.2819 +    {
  1.2820 +        fastPixelSize = 4;
  1.2821 +    }
  1.2822 +    else if ((desc.Format == D3DFMT_A4R4G4B4 &&
  1.2823 +             format == GL_BGRA_EXT &&
  1.2824 +             type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
  1.2825 +             (desc.Format == D3DFMT_A1R5G5B5 &&
  1.2826 +             format == GL_BGRA_EXT &&
  1.2827 +             type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
  1.2828 +    {
  1.2829 +        fastPixelSize = 2;
  1.2830 +    }
  1.2831 +    else if (desc.Format == D3DFMT_A16B16G16R16F &&
  1.2832 +             format == GL_RGBA &&
  1.2833 +             type == GL_HALF_FLOAT_OES)
  1.2834 +    {
  1.2835 +        fastPixelSize = 8;
  1.2836 +    }
  1.2837 +    else if (desc.Format == D3DFMT_A32B32G32R32F &&
  1.2838 +             format == GL_RGBA &&
  1.2839 +             type == GL_FLOAT)
  1.2840 +    {
  1.2841 +        fastPixelSize = 16;
  1.2842 +    }
  1.2843 +
  1.2844 +    for (int j = 0; j < rect.bottom - rect.top; j++)
  1.2845 +    {
  1.2846 +        if (fastPixelSize != 0)
  1.2847 +        {
  1.2848 +            // Fast path for formats which require no translation:
  1.2849 +            // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
  1.2850 +            // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
  1.2851 +            // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
  1.2852 +            // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
  1.2853 +            // D3DFMT_A32B32G32R32F to RGBA/FLOAT
  1.2854 +            // 
  1.2855 +            // Note that buffers with no alpha go through the slow path below.
  1.2856 +            memcpy(dest + j * outputPitch,
  1.2857 +                   source + j * inputPitch,
  1.2858 +                   (rect.right - rect.left) * fastPixelSize);
  1.2859 +            continue;
  1.2860 +        }
  1.2861 +        else if (desc.Format == D3DFMT_A8R8G8B8 &&
  1.2862 +                 format == GL_RGBA &&
  1.2863 +                 type == GL_UNSIGNED_BYTE)
  1.2864 +        {
  1.2865 +            // Fast path for swapping red with blue
  1.2866 +            for (int i = 0; i < rect.right - rect.left; i++)
  1.2867 +            {
  1.2868 +                unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  1.2869 +                *(unsigned int*)(dest + 4 * i + j * outputPitch) =
  1.2870 +                    (argb & 0xFF00FF00) |       // Keep alpha and green
  1.2871 +                    (argb & 0x00FF0000) >> 16 | // Move red to blue
  1.2872 +                    (argb & 0x000000FF) << 16;  // Move blue to red
  1.2873 +            }
  1.2874 +            continue;
  1.2875 +        }
  1.2876 +
  1.2877 +        for (int i = 0; i < rect.right - rect.left; i++)
  1.2878 +        {
  1.2879 +            float r;
  1.2880 +            float g;
  1.2881 +            float b;
  1.2882 +            float a;
  1.2883 +
  1.2884 +            switch (desc.Format)
  1.2885 +            {
  1.2886 +              case D3DFMT_R5G6B5:
  1.2887 +                {
  1.2888 +                    unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
  1.2889 +
  1.2890 +                    a = 1.0f;
  1.2891 +                    b = (rgb & 0x001F) * (1.0f / 0x001F);
  1.2892 +                    g = (rgb & 0x07E0) * (1.0f / 0x07E0);
  1.2893 +                    r = (rgb & 0xF800) * (1.0f / 0xF800);
  1.2894 +                }
  1.2895 +                break;
  1.2896 +              case D3DFMT_A1R5G5B5:
  1.2897 +                {
  1.2898 +                    unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
  1.2899 +
  1.2900 +                    a = (argb & 0x8000) ? 1.0f : 0.0f;
  1.2901 +                    b = (argb & 0x001F) * (1.0f / 0x001F);
  1.2902 +                    g = (argb & 0x03E0) * (1.0f / 0x03E0);
  1.2903 +                    r = (argb & 0x7C00) * (1.0f / 0x7C00);
  1.2904 +                }
  1.2905 +                break;
  1.2906 +              case D3DFMT_A8R8G8B8:
  1.2907 +                {
  1.2908 +                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  1.2909 +
  1.2910 +                    a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
  1.2911 +                    b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
  1.2912 +                    g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
  1.2913 +                    r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
  1.2914 +                }
  1.2915 +                break;
  1.2916 +              case D3DFMT_X8R8G8B8:
  1.2917 +                {
  1.2918 +                    unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  1.2919 +
  1.2920 +                    a = 1.0f;
  1.2921 +                    b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
  1.2922 +                    g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
  1.2923 +                    r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
  1.2924 +                }
  1.2925 +                break;
  1.2926 +              case D3DFMT_A2R10G10B10:
  1.2927 +                {
  1.2928 +                    unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  1.2929 +
  1.2930 +                    a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
  1.2931 +                    b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
  1.2932 +                    g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
  1.2933 +                    r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
  1.2934 +                }
  1.2935 +                break;
  1.2936 +              case D3DFMT_A32B32G32R32F:
  1.2937 +                {
  1.2938 +                    // float formats in D3D are stored rgba, rather than the other way round
  1.2939 +                    r = *((float*)(source + 16 * i + j * inputPitch) + 0);
  1.2940 +                    g = *((float*)(source + 16 * i + j * inputPitch) + 1);
  1.2941 +                    b = *((float*)(source + 16 * i + j * inputPitch) + 2);
  1.2942 +                    a = *((float*)(source + 16 * i + j * inputPitch) + 3);
  1.2943 +                }
  1.2944 +                break;
  1.2945 +              case D3DFMT_A16B16G16R16F:
  1.2946 +                {
  1.2947 +                    // float formats in D3D are stored rgba, rather than the other way round
  1.2948 +                    r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
  1.2949 +                    g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
  1.2950 +                    b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
  1.2951 +                    a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
  1.2952 +                }
  1.2953 +                break;
  1.2954 +              default:
  1.2955 +                UNIMPLEMENTED();   // FIXME
  1.2956 +                UNREACHABLE();
  1.2957 +                return;
  1.2958 +            }
  1.2959 +
  1.2960 +            switch (format)
  1.2961 +            {
  1.2962 +              case GL_RGBA:
  1.2963 +                switch (type)
  1.2964 +                {
  1.2965 +                  case GL_UNSIGNED_BYTE:
  1.2966 +                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
  1.2967 +                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  1.2968 +                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
  1.2969 +                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
  1.2970 +                    break;
  1.2971 +                  default: UNREACHABLE();
  1.2972 +                }
  1.2973 +                break;
  1.2974 +              case GL_BGRA_EXT:
  1.2975 +                switch (type)
  1.2976 +                {
  1.2977 +                  case GL_UNSIGNED_BYTE:
  1.2978 +                    dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
  1.2979 +                    dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  1.2980 +                    dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
  1.2981 +                    dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
  1.2982 +                    break;
  1.2983 +                  case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
  1.2984 +                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
  1.2985 +                    // this type is packed as follows:
  1.2986 +                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
  1.2987 +                    //  --------------------------------------------------------------------------------
  1.2988 +                    // |       4th         |        3rd         |        2nd        |   1st component   |
  1.2989 +                    //  --------------------------------------------------------------------------------
  1.2990 +                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
  1.2991 +                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
  1.2992 +                        ((unsigned short)(15 * a + 0.5f) << 12)|
  1.2993 +                        ((unsigned short)(15 * r + 0.5f) << 8) |
  1.2994 +                        ((unsigned short)(15 * g + 0.5f) << 4) |
  1.2995 +                        ((unsigned short)(15 * b + 0.5f) << 0);
  1.2996 +                    break;
  1.2997 +                  case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
  1.2998 +                    // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
  1.2999 +                    // this type is packed as follows:
  1.3000 +                    //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
  1.3001 +                    //  --------------------------------------------------------------------------------
  1.3002 +                    // | 4th |          3rd           |           2nd          |      1st component     |
  1.3003 +                    //  --------------------------------------------------------------------------------
  1.3004 +                    // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
  1.3005 +                    dest16[i + j * outputPitch / sizeof(unsigned short)] =
  1.3006 +                        ((unsigned short)(     a + 0.5f) << 15) |
  1.3007 +                        ((unsigned short)(31 * r + 0.5f) << 10) |
  1.3008 +                        ((unsigned short)(31 * g + 0.5f) << 5) |
  1.3009 +                        ((unsigned short)(31 * b + 0.5f) << 0);
  1.3010 +                    break;
  1.3011 +                  default: UNREACHABLE();
  1.3012 +                }
  1.3013 +                break;
  1.3014 +              case GL_RGB:
  1.3015 +                switch (type)
  1.3016 +                {
  1.3017 +                  case GL_UNSIGNED_SHORT_5_6_5:
  1.3018 +                    dest16[i + j * outputPitch / sizeof(unsigned short)] = 
  1.3019 +                        ((unsigned short)(31 * b + 0.5f) << 0) |
  1.3020 +                        ((unsigned short)(63 * g + 0.5f) << 5) |
  1.3021 +                        ((unsigned short)(31 * r + 0.5f) << 11);
  1.3022 +                    break;
  1.3023 +                  case GL_UNSIGNED_BYTE:
  1.3024 +                    dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
  1.3025 +                    dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  1.3026 +                    dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
  1.3027 +                    break;
  1.3028 +                  default: UNREACHABLE();
  1.3029 +                }
  1.3030 +                break;
  1.3031 +              default: UNREACHABLE();
  1.3032 +            }
  1.3033 +        }
  1.3034 +    }
  1.3035 +
  1.3036 +    systemSurface->UnlockRect();
  1.3037 +
  1.3038 +    systemSurface->Release();
  1.3039 +}
  1.3040 +
  1.3041 +RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
  1.3042 +{
  1.3043 +    SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
  1.3044 +    IDirect3DSurface9 *surface = NULL;
  1.3045 +    if (depth)
  1.3046 +    {
  1.3047 +        surface = swapChain9->getDepthStencil();
  1.3048 +    }
  1.3049 +    else
  1.3050 +    {
  1.3051 +        surface = swapChain9->getRenderTarget();
  1.3052 +    }
  1.3053 +
  1.3054 +    RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
  1.3055 +
  1.3056 +    return renderTarget;
  1.3057 +}
  1.3058 +
  1.3059 +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
  1.3060 +{
  1.3061 +    RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
  1.3062 +    return renderTarget;
  1.3063 +}
  1.3064 +
  1.3065 +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
  1.3066 +{
  1.3067 +    ShaderExecutable9 *executable = NULL;
  1.3068 +
  1.3069 +    switch (type)
  1.3070 +    {
  1.3071 +      case rx::SHADER_VERTEX:
  1.3072 +        {
  1.3073 +            IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
  1.3074 +            if (vshader)
  1.3075 +            {
  1.3076 +                executable = new ShaderExecutable9(function, length, vshader);
  1.3077 +            }
  1.3078 +        }
  1.3079 +        break;
  1.3080 +      case rx::SHADER_PIXEL:
  1.3081 +        {
  1.3082 +            IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
  1.3083 +            if (pshader)
  1.3084 +            {
  1.3085 +                executable = new ShaderExecutable9(function, length, pshader);
  1.3086 +            }
  1.3087 +        }
  1.3088 +        break;
  1.3089 +      default:
  1.3090 +        UNREACHABLE();
  1.3091 +        break;
  1.3092 +    }
  1.3093 +
  1.3094 +    return executable;
  1.3095 +}
  1.3096 +
  1.3097 +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
  1.3098 +{
  1.3099 +    const char *profile = NULL;
  1.3100 +
  1.3101 +    switch (type)
  1.3102 +    {
  1.3103 +      case rx::SHADER_VERTEX:
  1.3104 +        profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
  1.3105 +        break;
  1.3106 +      case rx::SHADER_PIXEL:
  1.3107 +        profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
  1.3108 +        break;
  1.3109 +      default:
  1.3110 +        UNREACHABLE();
  1.3111 +        return NULL;
  1.3112 +    }
  1.3113 +
  1.3114 +    ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true);
  1.3115 +    if (!binary)
  1.3116 +        return NULL;
  1.3117 +
  1.3118 +    ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
  1.3119 +    binary->Release();
  1.3120 +
  1.3121 +    return executable;
  1.3122 +}
  1.3123 +
  1.3124 +bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
  1.3125 +{
  1.3126 +    return mBlit->boxFilter(source, dest);
  1.3127 +}
  1.3128 +
  1.3129 +D3DPOOL Renderer9::getTexturePool(DWORD usage) const
  1.3130 +{
  1.3131 +    if (mD3d9Ex != NULL)
  1.3132 +    {
  1.3133 +        return D3DPOOL_DEFAULT;
  1.3134 +    }
  1.3135 +    else
  1.3136 +    {
  1.3137 +        if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
  1.3138 +        {
  1.3139 +            return D3DPOOL_DEFAULT;
  1.3140 +        }
  1.3141 +    }
  1.3142 +
  1.3143 +    return D3DPOOL_DEFAULT;
  1.3144 +}
  1.3145 +
  1.3146 +bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
  1.3147 +{
  1.3148 +    if (source && dest)
  1.3149 +    {
  1.3150 +        HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
  1.3151 +
  1.3152 +        if (fromManaged)
  1.3153 +        {
  1.3154 +            D3DSURFACE_DESC desc;
  1.3155 +            source->GetDesc(&desc);
  1.3156 +
  1.3157 +            IDirect3DSurface9 *surf = 0;
  1.3158 +            result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
  1.3159 +
  1.3160 +            if (SUCCEEDED(result))
  1.3161 +            {
  1.3162 +                Image9::copyLockableSurfaces(surf, source);
  1.3163 +                result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
  1.3164 +                surf->Release();
  1.3165 +            }
  1.3166 +        }
  1.3167 +        else
  1.3168 +        {
  1.3169 +            endScene();
  1.3170 +            result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
  1.3171 +        }
  1.3172 +
  1.3173 +        if (FAILED(result))
  1.3174 +        {
  1.3175 +            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
  1.3176 +            return false;
  1.3177 +        }
  1.3178 +    }
  1.3179 +
  1.3180 +    return true;
  1.3181 +}
  1.3182 +
  1.3183 +Image *Renderer9::createImage()
  1.3184 +{
  1.3185 +    return new Image9();
  1.3186 +}
  1.3187 +
  1.3188 +void Renderer9::generateMipmap(Image *dest, Image *src)
  1.3189 +{
  1.3190 +    Image9 *src9 = Image9::makeImage9(src);
  1.3191 +    Image9 *dst9 = Image9::makeImage9(dest);
  1.3192 +    Image9::generateMipmap(dst9, src9);
  1.3193 +}
  1.3194 +
  1.3195 +TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
  1.3196 +{
  1.3197 +    SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
  1.3198 +    return new TextureStorage9_2D(this, swapChain9);
  1.3199 +}
  1.3200 +
  1.3201 +TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
  1.3202 +{
  1.3203 +    return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
  1.3204 +}
  1.3205 +
  1.3206 +TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
  1.3207 +{
  1.3208 +    return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
  1.3209 +}
  1.3210 +
  1.3211 +bool Renderer9::getLUID(LUID *adapterLuid) const
  1.3212 +{
  1.3213 +    adapterLuid->HighPart = 0;
  1.3214 +    adapterLuid->LowPart = 0;
  1.3215 +
  1.3216 +    if (mD3d9Ex)
  1.3217 +    {
  1.3218 +        mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
  1.3219 +        return true;
  1.3220 +    }
  1.3221 +
  1.3222 +    return false;
  1.3223 +}
  1.3224 +
  1.3225 +}

mercurial