tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Renderer9.cpp (123792B)


      1 //
      2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
      8 
      9 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
     10 
     11 #include <EGL/eglext.h>
     12 #include <sstream>
     13 
     14 #include "common/utilities.h"
     15 #include "libANGLE/Buffer.h"
     16 #include "libANGLE/Context.h"
     17 #include "libANGLE/Display.h"
     18 #include "libANGLE/Framebuffer.h"
     19 #include "libANGLE/FramebufferAttachment.h"
     20 #include "libANGLE/Program.h"
     21 #include "libANGLE/Renderbuffer.h"
     22 #include "libANGLE/State.h"
     23 #include "libANGLE/Surface.h"
     24 #include "libANGLE/Texture.h"
     25 #include "libANGLE/angletypes.h"
     26 #include "libANGLE/features.h"
     27 #include "libANGLE/formatutils.h"
     28 #include "libANGLE/renderer/d3d/CompilerD3D.h"
     29 #include "libANGLE/renderer/d3d/DeviceD3D.h"
     30 #include "libANGLE/renderer/d3d/DisplayD3D.h"
     31 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
     32 #include "libANGLE/renderer/d3d/IndexDataManager.h"
     33 #include "libANGLE/renderer/d3d/ProgramD3D.h"
     34 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
     35 #include "libANGLE/renderer/d3d/ShaderD3D.h"
     36 #include "libANGLE/renderer/d3d/SurfaceD3D.h"
     37 #include "libANGLE/renderer/d3d/TextureD3D.h"
     38 #include "libANGLE/renderer/d3d/d3d9/Blit9.h"
     39 #include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
     40 #include "libANGLE/renderer/d3d/d3d9/Context9.h"
     41 #include "libANGLE/renderer/d3d/d3d9/Fence9.h"
     42 #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
     43 #include "libANGLE/renderer/d3d/d3d9/Image9.h"
     44 #include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
     45 #include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
     46 #include "libANGLE/renderer/d3d/d3d9/Query9.h"
     47 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
     48 #include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
     49 #include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
     50 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
     51 #include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
     52 #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
     53 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
     54 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
     55 #include "libANGLE/renderer/d3d/driver_utils_d3d.h"
     56 #include "libANGLE/renderer/driver_utils.h"
     57 #include "libANGLE/trace.h"
     58 
     59 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
     60 #    define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
     61 #endif
     62 
     63 // Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2.
     64 // Such a device would not be conformant.
     65 #ifndef ANGLE_SUPPORT_SHADER_MODEL_2
     66 #    define ANGLE_SUPPORT_SHADER_MODEL_2 0
     67 #endif
     68 
     69 namespace rx
     70 {
     71 
     72 namespace
     73 {
     74 enum
     75 {
     76    MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
     77    MAX_PIXEL_CONSTANT_VECTORS_SM2   = 32,
     78    MAX_PIXEL_CONSTANT_VECTORS_SM3   = 224,
     79    MAX_VARYING_VECTORS_SM2          = 8,
     80    MAX_VARYING_VECTORS_SM3          = 10,
     81 
     82    MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
     83 };
     84 
     85 template <typename T>
     86 static void DrawPoints(IDirect3DDevice9 *device, GLsizei count, const void *indices, int minIndex)
     87 {
     88    for (int i = 0; i < count; i++)
     89    {
     90        unsigned int indexValue =
     91            static_cast<unsigned int>(static_cast<const T *>(indices)[i]) - minIndex;
     92        device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
     93    }
     94 }
     95 
     96 // A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
     97 // close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
     98 // for almost any demanding application.
     99 constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
    100 }  // anonymous namespace
    101 
    102 Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
    103 {
    104    mD3d9Module = nullptr;
    105 
    106    mD3d9         = nullptr;
    107    mD3d9Ex       = nullptr;
    108    mDevice       = nullptr;
    109    mDeviceEx     = nullptr;
    110    mDeviceWindow = nullptr;
    111    mBlit         = nullptr;
    112 
    113    mAdapter = D3DADAPTER_DEFAULT;
    114 
    115    const egl::AttributeMap &attributes = display->getAttributeMap();
    116    EGLint requestedDeviceType          = static_cast<EGLint>(attributes.get(
    117                 EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
    118    switch (requestedDeviceType)
    119    {
    120        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
    121            mDeviceType = D3DDEVTYPE_HAL;
    122            break;
    123 
    124        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
    125            mDeviceType = D3DDEVTYPE_REF;
    126            break;
    127 
    128        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
    129            mDeviceType = D3DDEVTYPE_NULLREF;
    130            break;
    131 
    132        default:
    133            UNREACHABLE();
    134    }
    135 
    136    mMaskedClearSavedState = nullptr;
    137 
    138    mVertexDataManager = nullptr;
    139    mIndexDataManager  = nullptr;
    140    mLineLoopIB        = nullptr;
    141    mCountingIB        = nullptr;
    142 
    143    mMaxNullColorbufferLRU = 0;
    144    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
    145    {
    146        mNullRenderTargetCache[i].lruCount     = 0;
    147        mNullRenderTargetCache[i].width        = 0;
    148        mNullRenderTargetCache[i].height       = 0;
    149        mNullRenderTargetCache[i].renderTarget = nullptr;
    150    }
    151 
    152    mAppliedVertexShader  = nullptr;
    153    mAppliedPixelShader   = nullptr;
    154    mAppliedProgramSerial = 0;
    155 
    156    gl::InitializeDebugAnnotations(&mAnnotator);
    157 }
    158 
    159 void Renderer9::setGlobalDebugAnnotator()
    160 {
    161    gl::InitializeDebugAnnotations(&mAnnotator);
    162 }
    163 
    164 Renderer9::~Renderer9()
    165 {
    166    if (mDevice)
    167    {
    168        // If the device is lost, reset it first to prevent leaving the driver in an unstable state
    169        if (testDeviceLost())
    170        {
    171            resetDevice();
    172        }
    173    }
    174 
    175    release();
    176 }
    177 
    178 void Renderer9::release()
    179 {
    180    gl::UninitializeDebugAnnotations();
    181 
    182    mTranslatedAttribCache.clear();
    183 
    184    releaseDeviceResources();
    185 
    186    SafeRelease(mDevice);
    187    SafeRelease(mDeviceEx);
    188    SafeRelease(mD3d9);
    189    SafeRelease(mD3d9Ex);
    190 
    191    mCompiler.release();
    192 
    193    if (mDeviceWindow)
    194    {
    195        DestroyWindow(mDeviceWindow);
    196        mDeviceWindow = nullptr;
    197    }
    198 
    199    mD3d9Module = nullptr;
    200 }
    201 
    202 egl::Error Renderer9::initialize()
    203 {
    204    ANGLE_TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
    205    mD3d9Module = ::LoadLibrary(TEXT("d3d9.dll"));
    206 
    207    if (mD3d9Module == nullptr)
    208    {
    209        return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "No D3D9 module found.";
    210    }
    211 
    212    typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
    213    Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
    214        reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
    215 
    216    // Use Direct3D9Ex if available. Among other things, this version is less
    217    // inclined to report a lost context, for example when the user switches
    218    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are
    219    // available.
    220    if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr &&
    221        SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
    222    {
    223        ANGLE_TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
    224        ASSERT(mD3d9Ex);
    225        mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9));
    226        ASSERT(mD3d9);
    227    }
    228    else
    229    {
    230        ANGLE_TRACE_EVENT0("gpu.angle", "Direct3DCreate9");
    231        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    232    }
    233 
    234    if (!mD3d9)
    235    {
    236        return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "Could not create D3D9 device.";
    237    }
    238 
    239    if (mDisplay->getNativeDisplayId() != nullptr)
    240    {
    241        //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context
    242        //  corresponds to
    243    }
    244 
    245    HRESULT result;
    246 
    247    // Give up on getting device caps after about one second.
    248    {
    249        ANGLE_TRACE_EVENT0("gpu.angle", "GetDeviceCaps");
    250        for (int i = 0; i < 10; ++i)
    251        {
    252            result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
    253            if (SUCCEEDED(result))
    254            {
    255                break;
    256            }
    257            else if (result == D3DERR_NOTAVAILABLE)
    258            {
    259                Sleep(100);  // Give the driver some time to initialize/recover
    260            }
    261            else if (FAILED(result))  // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY,
    262                                      // D3DERR_INVALIDDEVICE, or another error we can't recover
    263                                      // from
    264            {
    265                return egl::EglNotInitialized(D3D9_INIT_OTHER_ERROR)
    266                       << "Failed to get device caps, " << gl::FmtHR(result);
    267            }
    268        }
    269    }
    270 
    271 #if ANGLE_SUPPORT_SHADER_MODEL_2
    272    size_t minShaderModel = 2;
    273 #else
    274    size_t minShaderModel = 3;
    275 #endif
    276 
    277    if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
    278    {
    279        return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_VERSION)
    280               << "Renderer does not support PS " << minShaderModel << ".0, aborting!";
    281    }
    282 
    283    // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture
    284    // to a render target texture is not supported. This is required by
    285    // Texture2D::ensureRenderTarget.
    286    if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
    287    {
    288        return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_STRETCHRECT)
    289               << "Renderer does not support StretctRect from textures.";
    290    }
    291 
    292    {
    293        ANGLE_TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier");
    294        mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
    295    }
    296 
    297    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
    298    static const TCHAR className[]  = TEXT("STATIC");
    299 
    300    {
    301        ANGLE_TRACE_EVENT0("gpu.angle", "CreateWindowEx");
    302        mDeviceWindow =
    303            CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1,
    304                           1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr);
    305    }
    306 
    307    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
    308    DWORD behaviorFlags =
    309        D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
    310 
    311    {
    312        ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
    313        result = mD3d9->CreateDevice(
    314            mAdapter, mDeviceType, mDeviceWindow,
    315            behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
    316            &presentParameters, &mDevice);
    317 
    318        if (FAILED(result))
    319        {
    320            ERR() << "CreateDevice1 failed: (" << gl::FmtHR(result) << ")";
    321        }
    322    }
    323    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
    324    {
    325        return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
    326               << "CreateDevice failed: device lost or out of memory (" << gl::FmtHR(result) << ")";
    327    }
    328 
    329    if (FAILED(result))
    330    {
    331        ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2");
    332        result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow,
    333                                     behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
    334                                     &presentParameters, &mDevice);
    335 
    336        if (FAILED(result))
    337        {
    338            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
    339                   result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
    340            return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
    341                   << "CreateDevice2 failed: device lost, not available, or of out of memory ("
    342                   << gl::FmtHR(result) << ")";
    343        }
    344    }
    345 
    346    if (mD3d9Ex)
    347    {
    348        ANGLE_TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
    349        result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx);
    350        ASSERT(SUCCEEDED(result));
    351    }
    352 
    353    {
    354        ANGLE_TRACE_EVENT0("gpu.angle", "ShaderCache initialize");
    355        mVertexShaderCache.initialize(mDevice);
    356        mPixelShaderCache.initialize(mDevice);
    357    }
    358 
    359    D3DDISPLAYMODE currentDisplayMode;
    360    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
    361 
    362    // Check vertex texture support
    363    // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
    364    // We test this using D3D9 by checking support for the R16F format.
    365    mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
    366                            SUCCEEDED(mD3d9->CheckDeviceFormat(
    367                                mAdapter, mDeviceType, currentDisplayMode.Format,
    368                                D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
    369 
    370    ANGLE_TRY(initializeDevice());
    371 
    372    return egl::NoError();
    373 }
    374 
    375 // do any one-time device initialization
    376 // NOTE: this is also needed after a device lost/reset
    377 // to reset the scene status and ensure the default states are reset.
    378 egl::Error Renderer9::initializeDevice()
    379 {
    380    // Permanent non-default states
    381    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
    382    mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
    383 
    384    if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
    385    {
    386        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize);
    387    }
    388    else
    389    {
    390        mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);  // 1.0f
    391    }
    392 
    393    const gl::Caps &rendererCaps = getNativeCaps();
    394 
    395    mCurVertexSamplerStates.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
    396    mCurPixelSamplerStates.resize(
    397        rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
    398 
    399    mCurVertexTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
    400    mCurPixelTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
    401 
    402    markAllStateDirty();
    403 
    404    mSceneStarted = false;
    405 
    406    ASSERT(!mBlit);
    407    mBlit = new Blit9(this);
    408 
    409    ASSERT(!mVertexDataManager && !mIndexDataManager);
    410    mIndexDataManager = new IndexDataManager(this);
    411 
    412    mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
    413 
    414    mStateManager.initialize();
    415 
    416    return egl::NoError();
    417 }
    418 
    419 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
    420 {
    421    D3DPRESENT_PARAMETERS presentParameters = {};
    422 
    423    // The default swap chain is never actually used. Surface will create a new swap chain with the
    424    // proper parameters.
    425    presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
    426    presentParameters.BackBufferCount        = 1;
    427    presentParameters.BackBufferFormat       = D3DFMT_UNKNOWN;
    428    presentParameters.BackBufferWidth        = 1;
    429    presentParameters.BackBufferHeight       = 1;
    430    presentParameters.EnableAutoDepthStencil = FALSE;
    431    presentParameters.Flags                  = 0;
    432    presentParameters.hDeviceWindow          = mDeviceWindow;
    433    presentParameters.MultiSampleQuality     = 0;
    434    presentParameters.MultiSampleType        = D3DMULTISAMPLE_NONE;
    435    presentParameters.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
    436    presentParameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
    437    presentParameters.Windowed               = TRUE;
    438 
    439    return presentParameters;
    440 }
    441 
    442 egl::ConfigSet Renderer9::generateConfigs()
    443 {
    444    static const GLenum colorBufferFormats[] = {
    445        GL_BGR5_A1_ANGLEX,
    446        GL_BGRA8_EXT,
    447        GL_RGB565,
    448 
    449    };
    450 
    451    static const GLenum depthStencilBufferFormats[] = {
    452        GL_NONE,
    453        GL_DEPTH_COMPONENT32_OES,
    454        GL_DEPTH24_STENCIL8_OES,
    455        GL_DEPTH_COMPONENT24_OES,
    456        GL_DEPTH_COMPONENT16,
    457    };
    458 
    459    const gl::Caps &rendererCaps                  = getNativeCaps();
    460    const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
    461 
    462    D3DDISPLAYMODE currentDisplayMode;
    463    mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
    464 
    465    // Determine the min and max swap intervals
    466    int minSwapInterval = 4;
    467    int maxSwapInterval = 0;
    468 
    469    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
    470    {
    471        minSwapInterval = std::min(minSwapInterval, 0);
    472        maxSwapInterval = std::max(maxSwapInterval, 0);
    473    }
    474    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
    475    {
    476        minSwapInterval = std::min(minSwapInterval, 1);
    477        maxSwapInterval = std::max(maxSwapInterval, 1);
    478    }
    479    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
    480    {
    481        minSwapInterval = std::min(minSwapInterval, 2);
    482        maxSwapInterval = std::max(maxSwapInterval, 2);
    483    }
    484    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
    485    {
    486        minSwapInterval = std::min(minSwapInterval, 3);
    487        maxSwapInterval = std::max(maxSwapInterval, 3);
    488    }
    489    if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
    490    {
    491        minSwapInterval = std::min(minSwapInterval, 4);
    492        maxSwapInterval = std::max(maxSwapInterval, 4);
    493    }
    494 
    495    egl::ConfigSet configs;
    496    for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
    497    {
    498        GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
    499        const gl::TextureCaps &colorBufferFormatCaps =
    500            rendererTextureCaps.get(colorBufferInternalFormat);
    501        if (colorBufferFormatCaps.renderbuffer)
    502        {
    503            ASSERT(colorBufferFormatCaps.textureAttachment);
    504            for (size_t depthStencilIndex = 0;
    505                 depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
    506            {
    507                GLenum depthStencilBufferInternalFormat =
    508                    depthStencilBufferFormats[depthStencilIndex];
    509                const gl::TextureCaps &depthStencilBufferFormatCaps =
    510                    rendererTextureCaps.get(depthStencilBufferInternalFormat);
    511                if (depthStencilBufferFormatCaps.renderbuffer ||
    512                    depthStencilBufferInternalFormat == GL_NONE)
    513                {
    514                    ASSERT(depthStencilBufferFormatCaps.textureAttachment ||
    515                           depthStencilBufferInternalFormat == GL_NONE);
    516                    const gl::InternalFormat &colorBufferFormatInfo =
    517                        gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
    518                    const gl::InternalFormat &depthStencilBufferFormatInfo =
    519                        gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
    520                    const d3d9::TextureFormat &d3d9ColorBufferFormatInfo =
    521                        d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
    522 
    523                    egl::Config config;
    524                    config.renderTargetFormat = colorBufferInternalFormat;
    525                    config.depthStencilFormat = depthStencilBufferInternalFormat;
    526                    config.bufferSize         = colorBufferFormatInfo.pixelBytes * 8;
    527                    config.redSize            = colorBufferFormatInfo.redBits;
    528                    config.greenSize          = colorBufferFormatInfo.greenBits;
    529                    config.blueSize           = colorBufferFormatInfo.blueBits;
    530                    config.luminanceSize      = colorBufferFormatInfo.luminanceBits;
    531                    config.alphaSize          = colorBufferFormatInfo.alphaBits;
    532                    config.alphaMaskSize      = 0;
    533                    config.bindToTextureRGB   = (colorBufferFormatInfo.format == GL_RGB);
    534                    config.bindToTextureRGBA  = (colorBufferFormatInfo.format == GL_RGBA ||
    535                                                colorBufferFormatInfo.format == GL_BGRA_EXT);
    536                    config.colorBufferType    = EGL_RGB_BUFFER;
    537                    // Mark as slow if blits to the back-buffer won't be straight forward
    538                    config.configCaveat =
    539                        (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat)
    540                            ? EGL_NONE
    541                            : EGL_SLOW_CONFIG;
    542                    config.configID          = static_cast<EGLint>(configs.size() + 1);
    543                    config.conformant        = EGL_OPENGL_ES2_BIT;
    544                    config.depthSize         = depthStencilBufferFormatInfo.depthBits;
    545                    config.level             = 0;
    546                    config.matchNativePixmap = EGL_NONE;
    547                    config.maxPBufferWidth   = rendererCaps.max2DTextureSize;
    548                    config.maxPBufferHeight  = rendererCaps.max2DTextureSize;
    549                    config.maxPBufferPixels =
    550                        rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
    551                    config.maxSwapInterval  = maxSwapInterval;
    552                    config.minSwapInterval  = minSwapInterval;
    553                    config.nativeRenderable = EGL_FALSE;
    554                    config.nativeVisualID   = 0;
    555                    config.nativeVisualType = EGL_NONE;
    556                    config.renderableType   = EGL_OPENGL_ES2_BIT;
    557                    config.sampleBuffers    = 0;  // FIXME: enumerate multi-sampling
    558                    config.samples          = 0;
    559                    config.stencilSize      = depthStencilBufferFormatInfo.stencilBits;
    560                    config.surfaceType =
    561                        EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    562                    config.transparentType       = EGL_NONE;
    563                    config.transparentRedValue   = 0;
    564                    config.transparentGreenValue = 0;
    565                    config.transparentBlueValue  = 0;
    566                    config.colorComponentType    = gl_egl::GLComponentTypeToEGLColorComponentType(
    567                           colorBufferFormatInfo.componentType);
    568 
    569                    configs.add(config);
    570                }
    571            }
    572        }
    573    }
    574 
    575    ASSERT(configs.size() > 0);
    576    return configs;
    577 }
    578 
    579 void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
    580 {
    581    outExtensions->createContextRobustness = true;
    582 
    583    if (getShareHandleSupport())
    584    {
    585        outExtensions->d3dShareHandleClientBuffer     = true;
    586        outExtensions->surfaceD3DTexture2DShareHandle = true;
    587    }
    588    outExtensions->d3dTextureClientBuffer = true;
    589 
    590    outExtensions->querySurfacePointer = true;
    591    outExtensions->windowFixedSize     = true;
    592    outExtensions->postSubBuffer       = true;
    593 
    594    outExtensions->image               = true;
    595    outExtensions->imageBase           = true;
    596    outExtensions->glTexture2DImage    = true;
    597    outExtensions->glRenderbufferImage = true;
    598 
    599    outExtensions->noConfigContext = true;
    600 
    601    // Contexts are virtualized so textures and semaphores can be shared globally
    602    outExtensions->displayTextureShareGroup   = true;
    603    outExtensions->displaySemaphoreShareGroup = true;
    604 
    605    // D3D9 can be used without an output surface
    606    outExtensions->surfacelessContext = true;
    607 
    608    outExtensions->robustResourceInitializationANGLE = true;
    609 }
    610 
    611 void Renderer9::startScene()
    612 {
    613    if (!mSceneStarted)
    614    {
    615        long result = mDevice->BeginScene();
    616        if (SUCCEEDED(result))
    617        {
    618            // This is defensive checking against the device being
    619            // lost at unexpected times.
    620            mSceneStarted = true;
    621        }
    622    }
    623 }
    624 
    625 void Renderer9::endScene()
    626 {
    627    if (mSceneStarted)
    628    {
    629        // EndScene can fail if the device was lost, for example due
    630        // to a TDR during a draw call.
    631        mDevice->EndScene();
    632        mSceneStarted = false;
    633    }
    634 }
    635 
    636 angle::Result Renderer9::flush(const gl::Context *context)
    637 {
    638    IDirect3DQuery9 *query = nullptr;
    639    ANGLE_TRY(allocateEventQuery(context, &query));
    640 
    641    Context9 *context9 = GetImplAs<Context9>(context);
    642 
    643    HRESULT result = query->Issue(D3DISSUE_END);
    644    ANGLE_TRY_HR(context9, result, "Failed to issue event query");
    645 
    646    // Grab the query data once
    647    result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
    648    freeEventQuery(query);
    649    ANGLE_TRY_HR(context9, result, "Failed to get event query data");
    650 
    651    return angle::Result::Continue;
    652 }
    653 
    654 angle::Result Renderer9::finish(const gl::Context *context)
    655 {
    656    IDirect3DQuery9 *query = nullptr;
    657    ANGLE_TRY(allocateEventQuery(context, &query));
    658 
    659    Context9 *context9 = GetImplAs<Context9>(context);
    660 
    661    HRESULT result = query->Issue(D3DISSUE_END);
    662    ANGLE_TRY_HR(context9, result, "Failed to issue event query");
    663 
    664    // Grab the query data once
    665    result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
    666    if (FAILED(result))
    667    {
    668        freeEventQuery(query);
    669    }
    670    ANGLE_TRY_HR(context9, result, "Failed to get event query data");
    671 
    672    // Loop until the query completes
    673    unsigned int attempt = 0;
    674    while (result == S_FALSE)
    675    {
    676        // Keep polling, but allow other threads to do something useful first
    677        ScheduleYield();
    678 
    679        result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
    680        attempt++;
    681 
    682        if (result == S_FALSE)
    683        {
    684            // explicitly check for device loss
    685            // some drivers seem to return S_FALSE even if the device is lost
    686            // instead of D3DERR_DEVICELOST like they should
    687            bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0;
    688            if (checkDeviceLost && testDeviceLost())
    689            {
    690                result = D3DERR_DEVICELOST;
    691            }
    692        }
    693 
    694        if (FAILED(result))
    695        {
    696            freeEventQuery(query);
    697        }
    698        ANGLE_TRY_HR(context9, result, "Failed to get event query data");
    699    }
    700 
    701    freeEventQuery(query);
    702 
    703    return angle::Result::Continue;
    704 }
    705 
    706 bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const
    707 {
    708    return NativeWindow9::IsValidNativeWindow(window);
    709 }
    710 
    711 NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
    712                                               const egl::Config *,
    713                                               const egl::AttributeMap &) const
    714 {
    715    return new NativeWindow9(window);
    716 }
    717 
    718 SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
    719                                         HANDLE shareHandle,
    720                                         IUnknown *d3dTexture,
    721                                         GLenum backBufferFormat,
    722                                         GLenum depthBufferFormat,
    723                                         EGLint orientation,
    724                                         EGLint samples)
    725 {
    726    return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
    727                          backBufferFormat, depthBufferFormat, orientation);
    728 }
    729 
    730 egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
    731                                        IUnknown *d3dTexture,
    732                                        const egl::AttributeMap &attribs,
    733                                        EGLint *width,
    734                                        EGLint *height,
    735                                        GLsizei *samples,
    736                                        gl::Format *glFormat,
    737                                        const angle::Format **angleFormat,
    738                                        UINT *arraySlice) const
    739 {
    740    IDirect3DTexture9 *texture = nullptr;
    741    if (FAILED(d3dTexture->QueryInterface(&texture)))
    742    {
    743        return egl::EglBadParameter() << "Client buffer is not a IDirect3DTexture9";
    744    }
    745 
    746    IDirect3DDevice9 *textureDevice = nullptr;
    747    texture->GetDevice(&textureDevice);
    748    if (textureDevice != mDevice)
    749    {
    750        SafeRelease(texture);
    751        return egl::EglBadParameter() << "Texture's device does not match.";
    752    }
    753    SafeRelease(textureDevice);
    754 
    755    D3DSURFACE_DESC desc;
    756    texture->GetLevelDesc(0, &desc);
    757    SafeRelease(texture);
    758 
    759    if (width)
    760    {
    761        *width = static_cast<EGLint>(desc.Width);
    762    }
    763    if (height)
    764    {
    765        *height = static_cast<EGLint>(desc.Height);
    766    }
    767 
    768    // GetSamplesCount() returns 0 when multisampling isn't used.
    769    GLsizei sampleCount = d3d9_gl::GetSamplesCount(desc.MultiSampleType);
    770    if ((configuration && configuration->samples > 1) || sampleCount != 0)
    771    {
    772        return egl::EglBadParameter() << "Multisampling not supported for client buffer texture";
    773    }
    774    if (samples)
    775    {
    776        *samples = static_cast<EGLint>(sampleCount);
    777    }
    778 
    779    // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
    780    switch (desc.Format)
    781    {
    782        case D3DFMT_R8G8B8:
    783        case D3DFMT_A8R8G8B8:
    784        case D3DFMT_A16B16G16R16F:
    785        case D3DFMT_A32B32G32R32F:
    786            break;
    787 
    788        default:
    789            return egl::EglBadParameter()
    790                   << "Unknown client buffer texture format: " << desc.Format;
    791    }
    792 
    793    const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
    794    ASSERT(d3dFormatInfo.info().id != angle::FormatID::NONE);
    795 
    796    if (glFormat)
    797    {
    798        *glFormat = gl::Format(d3dFormatInfo.info().glInternalFormat);
    799    }
    800 
    801    if (angleFormat)
    802    {
    803 
    804        *angleFormat = &d3dFormatInfo.info();
    805    }
    806 
    807    if (arraySlice)
    808    {
    809        *arraySlice = 0;
    810    }
    811 
    812    return egl::NoError();
    813 }
    814 
    815 egl::Error Renderer9::validateShareHandle(const egl::Config *config,
    816                                          HANDLE shareHandle,
    817                                          const egl::AttributeMap &attribs) const
    818 {
    819    if (shareHandle == nullptr)
    820    {
    821        return egl::EglBadParameter() << "NULL share handle.";
    822    }
    823 
    824    EGLint width  = attribs.getAsInt(EGL_WIDTH, 0);
    825    EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
    826    ASSERT(width != 0 && height != 0);
    827 
    828    const d3d9::TextureFormat &backBufferd3dFormatInfo =
    829        d3d9::GetTextureFormatInfo(config->renderTargetFormat);
    830 
    831    IDirect3DTexture9 *texture = nullptr;
    832    HRESULT result             = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
    833                                                        backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
    834                                                        &texture, &shareHandle);
    835    if (FAILED(result))
    836    {
    837        return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
    838    }
    839 
    840    DWORD levelCount = texture->GetLevelCount();
    841 
    842    D3DSURFACE_DESC desc;
    843    texture->GetLevelDesc(0, &desc);
    844    SafeRelease(texture);
    845 
    846    if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
    847        desc.Height != static_cast<UINT>(height) ||
    848        desc.Format != backBufferd3dFormatInfo.texFormat)
    849    {
    850        return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
    851    }
    852 
    853    return egl::NoError();
    854 }
    855 
    856 ContextImpl *Renderer9::createContext(const gl::State &state, gl::ErrorSet *errorSet)
    857 {
    858    return new Context9(state, errorSet, this);
    859 }
    860 
    861 void *Renderer9::getD3DDevice()
    862 {
    863    return mDevice;
    864 }
    865 
    866 angle::Result Renderer9::allocateEventQuery(const gl::Context *context, IDirect3DQuery9 **outQuery)
    867 {
    868    if (mEventQueryPool.empty())
    869    {
    870        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
    871        ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to allocate event query");
    872    }
    873    else
    874    {
    875        *outQuery = mEventQueryPool.back();
    876        mEventQueryPool.pop_back();
    877    }
    878 
    879    return angle::Result::Continue;
    880 }
    881 
    882 void Renderer9::freeEventQuery(IDirect3DQuery9 *query)
    883 {
    884    if (mEventQueryPool.size() > 1000)
    885    {
    886        SafeRelease(query);
    887    }
    888    else
    889    {
    890        mEventQueryPool.push_back(query);
    891    }
    892 }
    893 
    894 angle::Result Renderer9::createVertexShader(d3d::Context *context,
    895                                            const DWORD *function,
    896                                            size_t length,
    897                                            IDirect3DVertexShader9 **outShader)
    898 {
    899    return mVertexShaderCache.create(context, function, length, outShader);
    900 }
    901 
    902 angle::Result Renderer9::createPixelShader(d3d::Context *context,
    903                                           const DWORD *function,
    904                                           size_t length,
    905                                           IDirect3DPixelShader9 **outShader)
    906 {
    907    return mPixelShaderCache.create(context, function, length, outShader);
    908 }
    909 
    910 HRESULT Renderer9::createVertexBuffer(UINT Length,
    911                                      DWORD Usage,
    912                                      IDirect3DVertexBuffer9 **ppVertexBuffer)
    913 {
    914    // Force buffers to be limited to a fixed max size.
    915    if (Length > kMaximumBufferSizeHardLimit)
    916    {
    917        return E_OUTOFMEMORY;
    918    }
    919 
    920    D3DPOOL Pool = getBufferPool(Usage);
    921    return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
    922 }
    923 
    924 VertexBuffer *Renderer9::createVertexBuffer()
    925 {
    926    return new VertexBuffer9(this);
    927 }
    928 
    929 HRESULT Renderer9::createIndexBuffer(UINT Length,
    930                                     DWORD Usage,
    931                                     D3DFORMAT Format,
    932                                     IDirect3DIndexBuffer9 **ppIndexBuffer)
    933 {
    934    // Force buffers to be limited to a fixed max size.
    935    if (Length > kMaximumBufferSizeHardLimit)
    936    {
    937        return E_OUTOFMEMORY;
    938    }
    939 
    940    D3DPOOL Pool = getBufferPool(Usage);
    941    return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
    942 }
    943 
    944 IndexBuffer *Renderer9::createIndexBuffer()
    945 {
    946    return new IndexBuffer9(this);
    947 }
    948 
    949 StreamProducerImpl *Renderer9::createStreamProducerD3DTexture(
    950    egl::Stream::ConsumerType consumerType,
    951    const egl::AttributeMap &attribs)
    952 {
    953    // Streams are not supported under D3D9
    954    UNREACHABLE();
    955    return nullptr;
    956 }
    957 
    958 bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
    959 {
    960    // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
    961    return false;
    962 }
    963 
    964 angle::Result Renderer9::fastCopyBufferToTexture(const gl::Context *context,
    965                                                 const gl::PixelUnpackState &unpack,
    966                                                 gl::Buffer *unpackBuffer,
    967                                                 unsigned int offset,
    968                                                 RenderTargetD3D *destRenderTarget,
    969                                                 GLenum destinationFormat,
    970                                                 GLenum sourcePixelsType,
    971                                                 const gl::Box &destArea)
    972 {
    973    // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
    974    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    975    return angle::Result::Stop;
    976 }
    977 
    978 angle::Result Renderer9::setSamplerState(const gl::Context *context,
    979                                         gl::ShaderType type,
    980                                         int index,
    981                                         gl::Texture *texture,
    982                                         const gl::SamplerState &samplerState)
    983 {
    984    CurSamplerState &appliedSampler = (type == gl::ShaderType::Fragment)
    985                                          ? mCurPixelSamplerStates[index]
    986                                          : mCurVertexSamplerStates[index];
    987 
    988    // Make sure to add the level offset for our tiny compressed texture workaround
    989    TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
    990 
    991    TextureStorage *storage = nullptr;
    992    ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
    993 
    994    // Storage should exist, texture should be complete
    995    ASSERT(storage);
    996 
    997    DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel();
    998 
    999    if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel ||
   1000        memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0)
   1001    {
   1002        int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   1003        int d3dSampler       = index + d3dSamplerOffset;
   1004 
   1005        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU,
   1006                                 gl_d3d9::ConvertTextureWrap(samplerState.getWrapS()));
   1007        mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV,
   1008                                 gl_d3d9::ConvertTextureWrap(samplerState.getWrapT()));
   1009 
   1010        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER,
   1011                                 gl_d3d9::ConvertMagFilter(samplerState.getMagFilter(),
   1012                                                           samplerState.getMaxAnisotropy()));
   1013 
   1014        D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
   1015        float lodBias;
   1016        gl_d3d9::ConvertMinFilter(samplerState.getMinFilter(), &d3dMinFilter, &d3dMipFilter,
   1017                                  &lodBias, samplerState.getMaxAnisotropy(), baseLevel);
   1018        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
   1019        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
   1020        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
   1021        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias));
   1022        if (getNativeExtensions().textureFilterAnisotropicEXT)
   1023        {
   1024            DWORD maxAnisotropy = std::min(mDeviceCaps.MaxAnisotropy,
   1025                                           static_cast<DWORD>(samplerState.getMaxAnisotropy()));
   1026            mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
   1027        }
   1028 
   1029        const bool isSrgb = gl::GetSizedInternalFormatInfo(textureD3D->getBaseLevelInternalFormat())
   1030                                .colorEncoding == GL_SRGB;
   1031        mDevice->SetSamplerState(d3dSampler, D3DSAMP_SRGBTEXTURE, isSrgb);
   1032 
   1033        ASSERT(texture->getBorderColor().type == angle::ColorGeneric::Type::Float);
   1034        mDevice->SetSamplerState(d3dSampler, D3DSAMP_BORDERCOLOR,
   1035                                 gl_d3d9::ConvertColor(texture->getBorderColor().colorF));
   1036    }
   1037 
   1038    appliedSampler.forceSet     = false;
   1039    appliedSampler.samplerState = samplerState;
   1040    appliedSampler.baseLevel    = baseLevel;
   1041 
   1042    return angle::Result::Continue;
   1043 }
   1044 
   1045 angle::Result Renderer9::setTexture(const gl::Context *context,
   1046                                    gl::ShaderType type,
   1047                                    int index,
   1048                                    gl::Texture *texture)
   1049 {
   1050    int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   1051    int d3dSampler       = index + d3dSamplerOffset;
   1052    IDirect3DBaseTexture9 *d3dTexture = nullptr;
   1053    bool forceSetTexture              = false;
   1054 
   1055    std::vector<uintptr_t> &appliedTextures =
   1056        (type == gl::ShaderType::Fragment) ? mCurPixelTextures : mCurVertexTextures;
   1057 
   1058    if (texture)
   1059    {
   1060        TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
   1061 
   1062        TextureStorage *texStorage = nullptr;
   1063        ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
   1064 
   1065        // Texture should be complete and have a storage
   1066        ASSERT(texStorage);
   1067 
   1068        TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
   1069        ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture));
   1070 
   1071        // If we get NULL back from getBaseTexture here, something went wrong
   1072        // in the texture class and we're unexpectedly missing the d3d texture
   1073        ASSERT(d3dTexture != nullptr);
   1074 
   1075        forceSetTexture = textureImpl->hasDirtyImages();
   1076        textureImpl->resetDirty();
   1077    }
   1078 
   1079    if (forceSetTexture || appliedTextures[index] != reinterpret_cast<uintptr_t>(d3dTexture))
   1080    {
   1081        mDevice->SetTexture(d3dSampler, d3dTexture);
   1082    }
   1083 
   1084    appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture);
   1085 
   1086    return angle::Result::Continue;
   1087 }
   1088 
   1089 angle::Result Renderer9::updateState(const gl::Context *context, gl::PrimitiveMode drawMode)
   1090 {
   1091    const auto &glState = context->getState();
   1092 
   1093    // Applies the render target surface, depth stencil surface, viewport rectangle and
   1094    // scissor rectangle to the renderer
   1095    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
   1096    ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit());
   1097 
   1098    Framebuffer9 *framebuffer9 = GetImplAs<Framebuffer9>(framebuffer);
   1099 
   1100    ANGLE_TRY(applyRenderTarget(context, framebuffer9->getCachedColorRenderTargets()[0],
   1101                                framebuffer9->getCachedDepthStencilRenderTarget()));
   1102 
   1103    // Setting viewport state
   1104    setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
   1105                glState.getRasterizerState().frontFace, false);
   1106 
   1107    // Setting scissors state
   1108    setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
   1109 
   1110    // Setting blend, depth stencil, and rasterizer states
   1111    // Since framebuffer->getSamples will return the original samples which may be different with
   1112    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
   1113    // get the actual samples.
   1114    GLsizei samples                                       = 0;
   1115    const gl::FramebufferAttachment *firstColorAttachment = framebuffer->getFirstColorAttachment();
   1116    if (firstColorAttachment)
   1117    {
   1118        ASSERT(firstColorAttachment->isAttached());
   1119        RenderTarget9 *renderTarget = nullptr;
   1120        ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
   1121                                                        &renderTarget));
   1122        samples = renderTarget->getSamples();
   1123 
   1124        mDevice->SetRenderState(D3DRS_SRGBWRITEENABLE,
   1125                                renderTarget->getInternalFormat() == GL_SRGB8_ALPHA8);
   1126    }
   1127    gl::RasterizerState rasterizer = glState.getRasterizerState();
   1128    rasterizer.pointDrawMode       = (drawMode == gl::PrimitiveMode::Points);
   1129    rasterizer.multiSample         = (samples != 0);
   1130 
   1131    ANGLE_TRY(setBlendDepthRasterStates(context, drawMode));
   1132 
   1133    mStateManager.resetDirtyBits();
   1134 
   1135    return angle::Result::Continue;
   1136 }
   1137 
   1138 void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
   1139 {
   1140    mStateManager.setScissorState(scissor, enabled);
   1141 }
   1142 
   1143 angle::Result Renderer9::setBlendDepthRasterStates(const gl::Context *context,
   1144                                                   gl::PrimitiveMode drawMode)
   1145 {
   1146    const auto &glState              = context->getState();
   1147    gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
   1148    ASSERT(!drawFramebuffer->hasAnyDirtyBit());
   1149    // Since framebuffer->getSamples will return the original samples which may be different with
   1150    // the sample counts that we set in render target view, here we use renderTarget->getSamples to
   1151    // get the actual samples.
   1152    GLsizei samples = 0;
   1153    const gl::FramebufferAttachment *firstColorAttachment =
   1154        drawFramebuffer->getFirstColorAttachment();
   1155    if (firstColorAttachment)
   1156    {
   1157        ASSERT(firstColorAttachment->isAttached());
   1158        RenderTarget9 *renderTarget = nullptr;
   1159        ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
   1160                                                        &renderTarget));
   1161        samples = renderTarget->getSamples();
   1162    }
   1163    gl::RasterizerState rasterizer = glState.getRasterizerState();
   1164    rasterizer.pointDrawMode       = (drawMode == gl::PrimitiveMode::Points);
   1165    rasterizer.multiSample         = (samples != 0);
   1166 
   1167    unsigned int mask = GetBlendSampleMask(glState, samples);
   1168    mStateManager.setBlendDepthRasterStates(glState, mask);
   1169    return angle::Result::Continue;
   1170 }
   1171 
   1172 void Renderer9::setViewport(const gl::Rectangle &viewport,
   1173                            float zNear,
   1174                            float zFar,
   1175                            gl::PrimitiveMode drawMode,
   1176                            GLenum frontFace,
   1177                            bool ignoreViewport)
   1178 {
   1179    mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
   1180 }
   1181 
   1182 bool Renderer9::applyPrimitiveType(gl::PrimitiveMode mode, GLsizei count, bool usesPointSize)
   1183 {
   1184    switch (mode)
   1185    {
   1186        case gl::PrimitiveMode::Points:
   1187            mPrimitiveType  = D3DPT_POINTLIST;
   1188            mPrimitiveCount = count;
   1189            break;
   1190        case gl::PrimitiveMode::Lines:
   1191            mPrimitiveType  = D3DPT_LINELIST;
   1192            mPrimitiveCount = count / 2;
   1193            break;
   1194        case gl::PrimitiveMode::LineLoop:
   1195            mPrimitiveType = D3DPT_LINESTRIP;
   1196            mPrimitiveCount =
   1197                count - 1;  // D3D doesn't support line loops, so we draw the last line separately
   1198            break;
   1199        case gl::PrimitiveMode::LineStrip:
   1200            mPrimitiveType  = D3DPT_LINESTRIP;
   1201            mPrimitiveCount = count - 1;
   1202            break;
   1203        case gl::PrimitiveMode::Triangles:
   1204            mPrimitiveType  = D3DPT_TRIANGLELIST;
   1205            mPrimitiveCount = count / 3;
   1206            break;
   1207        case gl::PrimitiveMode::TriangleStrip:
   1208            mPrimitiveType  = D3DPT_TRIANGLESTRIP;
   1209            mPrimitiveCount = count - 2;
   1210            break;
   1211        case gl::PrimitiveMode::TriangleFan:
   1212            mPrimitiveType  = D3DPT_TRIANGLEFAN;
   1213            mPrimitiveCount = count - 2;
   1214            break;
   1215        default:
   1216            UNREACHABLE();
   1217            return false;
   1218    }
   1219 
   1220    return mPrimitiveCount > 0;
   1221 }
   1222 
   1223 angle::Result Renderer9::getNullColorRenderTarget(const gl::Context *context,
   1224                                                  const RenderTarget9 *depthRenderTarget,
   1225                                                  const RenderTarget9 **outColorRenderTarget)
   1226 {
   1227    ASSERT(depthRenderTarget);
   1228 
   1229    const gl::Extents &size = depthRenderTarget->getExtents();
   1230 
   1231    // search cached nullcolorbuffers
   1232    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
   1233    {
   1234        if (mNullRenderTargetCache[i].renderTarget != nullptr &&
   1235            mNullRenderTargetCache[i].width == size.width &&
   1236            mNullRenderTargetCache[i].height == size.height)
   1237        {
   1238            mNullRenderTargetCache[i].lruCount = ++mMaxNullColorbufferLRU;
   1239            *outColorRenderTarget              = mNullRenderTargetCache[i].renderTarget;
   1240            return angle::Result::Continue;
   1241        }
   1242    }
   1243 
   1244    RenderTargetD3D *nullRenderTarget = nullptr;
   1245    ANGLE_TRY(createRenderTarget(context, size.width, size.height, GL_NONE, 0, &nullRenderTarget));
   1246 
   1247    // add nullbuffer to the cache
   1248    NullRenderTargetCacheEntry *oldest = &mNullRenderTargetCache[0];
   1249    for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
   1250    {
   1251        if (mNullRenderTargetCache[i].lruCount < oldest->lruCount)
   1252        {
   1253            oldest = &mNullRenderTargetCache[i];
   1254        }
   1255    }
   1256 
   1257    SafeDelete(oldest->renderTarget);
   1258    oldest->renderTarget = GetAs<RenderTarget9>(nullRenderTarget);
   1259    oldest->lruCount     = ++mMaxNullColorbufferLRU;
   1260    oldest->width        = size.width;
   1261    oldest->height       = size.height;
   1262 
   1263    *outColorRenderTarget = oldest->renderTarget;
   1264    return angle::Result::Continue;
   1265 }
   1266 
   1267 angle::Result Renderer9::applyRenderTarget(const gl::Context *context,
   1268                                           const RenderTarget9 *colorRenderTargetIn,
   1269                                           const RenderTarget9 *depthStencilRenderTarget)
   1270 {
   1271    // if there is no color attachment we must synthesize a NULL colorattachment
   1272    // to keep the D3D runtime happy.  This should only be possible if depth texturing.
   1273    const RenderTarget9 *colorRenderTarget = colorRenderTargetIn;
   1274    if (colorRenderTarget == nullptr)
   1275    {
   1276        ANGLE_TRY(getNullColorRenderTarget(context, depthStencilRenderTarget, &colorRenderTarget));
   1277    }
   1278    ASSERT(colorRenderTarget != nullptr);
   1279 
   1280    size_t renderTargetWidth  = 0;
   1281    size_t renderTargetHeight = 0;
   1282 
   1283    bool renderTargetChanged        = false;
   1284    unsigned int renderTargetSerial = colorRenderTarget->getSerial();
   1285    if (renderTargetSerial != mAppliedRenderTargetSerial)
   1286    {
   1287        // Apply the render target on the device
   1288        IDirect3DSurface9 *renderTargetSurface = colorRenderTarget->getSurface();
   1289        ASSERT(renderTargetSurface);
   1290 
   1291        mDevice->SetRenderTarget(0, renderTargetSurface);
   1292        SafeRelease(renderTargetSurface);
   1293 
   1294        renderTargetWidth  = colorRenderTarget->getWidth();
   1295        renderTargetHeight = colorRenderTarget->getHeight();
   1296 
   1297        mAppliedRenderTargetSerial = renderTargetSerial;
   1298        renderTargetChanged        = true;
   1299    }
   1300 
   1301    unsigned int depthStencilSerial = 0;
   1302    if (depthStencilRenderTarget != nullptr)
   1303    {
   1304        depthStencilSerial = depthStencilRenderTarget->getSerial();
   1305    }
   1306 
   1307    if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
   1308    {
   1309        unsigned int depthSize   = 0;
   1310        unsigned int stencilSize = 0;
   1311 
   1312        // Apply the depth stencil on the device
   1313        if (depthStencilRenderTarget)
   1314        {
   1315            IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface();
   1316            ASSERT(depthStencilSurface);
   1317 
   1318            mDevice->SetDepthStencilSurface(depthStencilSurface);
   1319            SafeRelease(depthStencilSurface);
   1320 
   1321            const gl::InternalFormat &format =
   1322                gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
   1323 
   1324            depthSize   = format.depthBits;
   1325            stencilSize = format.stencilBits;
   1326        }
   1327        else
   1328        {
   1329            mDevice->SetDepthStencilSurface(nullptr);
   1330        }
   1331 
   1332        mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
   1333        mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
   1334 
   1335        mAppliedDepthStencilSerial = depthStencilSerial;
   1336        mDepthStencilInitialized   = true;
   1337    }
   1338 
   1339    if (renderTargetChanged || !mRenderTargetDescInitialized)
   1340    {
   1341        mStateManager.forceSetBlendState();
   1342        mStateManager.forceSetScissorState();
   1343        mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight);
   1344        mRenderTargetDescInitialized = true;
   1345    }
   1346 
   1347    return angle::Result::Continue;
   1348 }
   1349 
   1350 angle::Result Renderer9::applyVertexBuffer(const gl::Context *context,
   1351                                           gl::PrimitiveMode mode,
   1352                                           GLint first,
   1353                                           GLsizei count,
   1354                                           GLsizei instances,
   1355                                           TranslatedIndexData * /*indexInfo*/)
   1356 {
   1357    const gl::State &state = context->getState();
   1358    ANGLE_TRY(mVertexDataManager->prepareVertexData(context, first, count, &mTranslatedAttribCache,
   1359                                                    instances));
   1360 
   1361    return mVertexDeclarationCache.applyDeclaration(context, mDevice, mTranslatedAttribCache,
   1362                                                    state.getProgram(), first, instances,
   1363                                                    &mRepeatDraw);
   1364 }
   1365 
   1366 // Applies the indices and element array bindings to the Direct3D 9 device
   1367 angle::Result Renderer9::applyIndexBuffer(const gl::Context *context,
   1368                                          const void *indices,
   1369                                          GLsizei count,
   1370                                          gl::PrimitiveMode mode,
   1371                                          gl::DrawElementsType type,
   1372                                          TranslatedIndexData *indexInfo)
   1373 {
   1374    gl::VertexArray *vao           = context->getState().getVertexArray();
   1375    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
   1376 
   1377    gl::DrawElementsType dstType = gl::DrawElementsType::InvalidEnum;
   1378    ANGLE_TRY(GetIndexTranslationDestType(context, count, type, indices, false, &dstType));
   1379 
   1380    ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer,
   1381                                                  indices, indexInfo));
   1382 
   1383    // Directly binding the storage buffer is not supported for d3d9
   1384    ASSERT(indexInfo->storage == nullptr);
   1385 
   1386    if (indexInfo->serial != mAppliedIBSerial)
   1387    {
   1388        IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
   1389 
   1390        mDevice->SetIndices(indexBuffer->getBuffer());
   1391        mAppliedIBSerial = indexInfo->serial;
   1392    }
   1393 
   1394    return angle::Result::Continue;
   1395 }
   1396 
   1397 angle::Result Renderer9::drawArraysImpl(const gl::Context *context,
   1398                                        gl::PrimitiveMode mode,
   1399                                        GLint startVertex,
   1400                                        GLsizei count,
   1401                                        GLsizei instances)
   1402 {
   1403    ASSERT(!context->getState().isTransformFeedbackActiveUnpaused());
   1404 
   1405    startScene();
   1406 
   1407    if (mode == gl::PrimitiveMode::LineLoop)
   1408    {
   1409        return drawLineLoop(context, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr);
   1410    }
   1411 
   1412    if (instances > 0)
   1413    {
   1414        StaticIndexBufferInterface *countingIB = nullptr;
   1415        ANGLE_TRY(getCountingIB(context, count, &countingIB));
   1416 
   1417        if (mAppliedIBSerial != countingIB->getSerial())
   1418        {
   1419            IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(countingIB->getIndexBuffer());
   1420 
   1421            mDevice->SetIndices(indexBuffer->getBuffer());
   1422            mAppliedIBSerial = countingIB->getSerial();
   1423        }
   1424 
   1425        for (int i = 0; i < mRepeatDraw; i++)
   1426        {
   1427            mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
   1428        }
   1429 
   1430        return angle::Result::Continue;
   1431    }
   1432 
   1433    // Regular case
   1434    mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
   1435    return angle::Result::Continue;
   1436 }
   1437 
   1438 angle::Result Renderer9::drawElementsImpl(const gl::Context *context,
   1439                                          gl::PrimitiveMode mode,
   1440                                          GLsizei count,
   1441                                          gl::DrawElementsType type,
   1442                                          const void *indices,
   1443                                          GLsizei instances)
   1444 {
   1445    TranslatedIndexData indexInfo;
   1446 
   1447    ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo));
   1448 
   1449    gl::IndexRange indexRange;
   1450    ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices,
   1451                                                                  &indexRange));
   1452 
   1453    size_t vertexCount = indexRange.vertexCount();
   1454    ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start),
   1455                                static_cast<GLsizei>(vertexCount), instances, &indexInfo));
   1456 
   1457    startScene();
   1458 
   1459    int minIndex = static_cast<int>(indexRange.start);
   1460 
   1461    gl::VertexArray *vao           = context->getState().getVertexArray();
   1462    gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
   1463 
   1464    if (mode == gl::PrimitiveMode::Points)
   1465    {
   1466        return drawIndexedPoints(context, count, type, indices, minIndex, elementArrayBuffer);
   1467    }
   1468 
   1469    if (mode == gl::PrimitiveMode::LineLoop)
   1470    {
   1471        return drawLineLoop(context, count, type, indices, minIndex, elementArrayBuffer);
   1472    }
   1473 
   1474    for (int i = 0; i < mRepeatDraw; i++)
   1475    {
   1476        mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
   1477                                      static_cast<UINT>(vertexCount), indexInfo.startIndex,
   1478                                      mPrimitiveCount);
   1479    }
   1480    return angle::Result::Continue;
   1481 }
   1482 
   1483 angle::Result Renderer9::drawLineLoop(const gl::Context *context,
   1484                                      GLsizei count,
   1485                                      gl::DrawElementsType type,
   1486                                      const void *indices,
   1487                                      int minIndex,
   1488                                      gl::Buffer *elementArrayBuffer)
   1489 {
   1490    // Get the raw indices for an indexed draw
   1491    if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
   1492    {
   1493        BufferD3D *storage        = GetImplAs<BufferD3D>(elementArrayBuffer);
   1494        intptr_t offset           = reinterpret_cast<intptr_t>(indices);
   1495        const uint8_t *bufferData = nullptr;
   1496        ANGLE_TRY(storage->getData(context, &bufferData));
   1497        indices = bufferData + offset;
   1498    }
   1499 
   1500    unsigned int startIndex = 0;
   1501    Context9 *context9      = GetImplAs<Context9>(context);
   1502 
   1503    if (getNativeExtensions().elementIndexUintOES)
   1504    {
   1505        if (!mLineLoopIB)
   1506        {
   1507            mLineLoopIB = new StreamingIndexBufferInterface(this);
   1508            ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
   1509                                                      gl::DrawElementsType::UnsignedInt));
   1510        }
   1511 
   1512        // Checked by Renderer9::applyPrimitiveType
   1513        ASSERT(count >= 0);
   1514 
   1515        ANGLE_CHECK(context9,
   1516                    static_cast<unsigned int>(count) + 1 <=
   1517                        (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)),
   1518                    "Failed to create a 32-bit looping index buffer for "
   1519                    "GL_LINE_LOOP, too many indices required.",
   1520                    GL_OUT_OF_MEMORY);
   1521 
   1522        const unsigned int spaceNeeded =
   1523            (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
   1524        ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
   1525                                                  gl::DrawElementsType::UnsignedInt));
   1526 
   1527        void *mappedMemory  = nullptr;
   1528        unsigned int offset = 0;
   1529        ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
   1530 
   1531        startIndex         = static_cast<unsigned int>(offset) / 4;
   1532        unsigned int *data = static_cast<unsigned int *>(mappedMemory);
   1533 
   1534        switch (type)
   1535        {
   1536            case gl::DrawElementsType::InvalidEnum:  // Non-indexed draw
   1537                for (int i = 0; i < count; i++)
   1538                {
   1539                    data[i] = i;
   1540                }
   1541                data[count] = 0;
   1542                break;
   1543            case gl::DrawElementsType::UnsignedByte:
   1544                for (int i = 0; i < count; i++)
   1545                {
   1546                    data[i] = static_cast<const GLubyte *>(indices)[i];
   1547                }
   1548                data[count] = static_cast<const GLubyte *>(indices)[0];
   1549                break;
   1550            case gl::DrawElementsType::UnsignedShort:
   1551                for (int i = 0; i < count; i++)
   1552                {
   1553                    data[i] = static_cast<const GLushort *>(indices)[i];
   1554                }
   1555                data[count] = static_cast<const GLushort *>(indices)[0];
   1556                break;
   1557            case gl::DrawElementsType::UnsignedInt:
   1558                for (int i = 0; i < count; i++)
   1559                {
   1560                    data[i] = static_cast<const GLuint *>(indices)[i];
   1561                }
   1562                data[count] = static_cast<const GLuint *>(indices)[0];
   1563                break;
   1564            default:
   1565                UNREACHABLE();
   1566        }
   1567 
   1568        ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
   1569    }
   1570    else
   1571    {
   1572        if (!mLineLoopIB)
   1573        {
   1574            mLineLoopIB = new StreamingIndexBufferInterface(this);
   1575            ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
   1576                                                      gl::DrawElementsType::UnsignedShort));
   1577        }
   1578 
   1579        // Checked by Renderer9::applyPrimitiveType
   1580        ASSERT(count >= 0);
   1581 
   1582        ANGLE_CHECK(context9,
   1583                    static_cast<unsigned int>(count) + 1 <=
   1584                        (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)),
   1585                    "Failed to create a 16-bit looping index buffer for "
   1586                    "GL_LINE_LOOP, too many indices required.",
   1587                    GL_OUT_OF_MEMORY);
   1588 
   1589        const unsigned int spaceNeeded =
   1590            (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
   1591        ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
   1592                                                  gl::DrawElementsType::UnsignedShort));
   1593 
   1594        void *mappedMemory = nullptr;
   1595        unsigned int offset;
   1596        ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
   1597 
   1598        startIndex           = static_cast<unsigned int>(offset) / 2;
   1599        unsigned short *data = static_cast<unsigned short *>(mappedMemory);
   1600 
   1601        switch (type)
   1602        {
   1603            case gl::DrawElementsType::InvalidEnum:  // Non-indexed draw
   1604                for (int i = 0; i < count; i++)
   1605                {
   1606                    data[i] = static_cast<unsigned short>(i);
   1607                }
   1608                data[count] = 0;
   1609                break;
   1610            case gl::DrawElementsType::UnsignedByte:
   1611                for (int i = 0; i < count; i++)
   1612                {
   1613                    data[i] = static_cast<const GLubyte *>(indices)[i];
   1614                }
   1615                data[count] = static_cast<const GLubyte *>(indices)[0];
   1616                break;
   1617            case gl::DrawElementsType::UnsignedShort:
   1618                for (int i = 0; i < count; i++)
   1619                {
   1620                    data[i] = static_cast<const GLushort *>(indices)[i];
   1621                }
   1622                data[count] = static_cast<const GLushort *>(indices)[0];
   1623                break;
   1624            case gl::DrawElementsType::UnsignedInt:
   1625                for (int i = 0; i < count; i++)
   1626                {
   1627                    data[i] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[i]);
   1628                }
   1629                data[count] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[0]);
   1630                break;
   1631            default:
   1632                UNREACHABLE();
   1633        }
   1634 
   1635        ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
   1636    }
   1637 
   1638    if (mAppliedIBSerial != mLineLoopIB->getSerial())
   1639    {
   1640        IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(mLineLoopIB->getIndexBuffer());
   1641 
   1642        mDevice->SetIndices(indexBuffer->getBuffer());
   1643        mAppliedIBSerial = mLineLoopIB->getSerial();
   1644    }
   1645 
   1646    mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
   1647 
   1648    return angle::Result::Continue;
   1649 }
   1650 
   1651 angle::Result Renderer9::drawIndexedPoints(const gl::Context *context,
   1652                                           GLsizei count,
   1653                                           gl::DrawElementsType type,
   1654                                           const void *indices,
   1655                                           int minIndex,
   1656                                           gl::Buffer *elementArrayBuffer)
   1657 {
   1658    // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
   1659    // for each individual point. This call is not expected to happen often.
   1660 
   1661    if (elementArrayBuffer)
   1662    {
   1663        BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
   1664        intptr_t offset    = reinterpret_cast<intptr_t>(indices);
   1665 
   1666        const uint8_t *bufferData = nullptr;
   1667        ANGLE_TRY(storage->getData(context, &bufferData));
   1668        indices = bufferData + offset;
   1669    }
   1670 
   1671    switch (type)
   1672    {
   1673        case gl::DrawElementsType::UnsignedByte:
   1674            DrawPoints<GLubyte>(mDevice, count, indices, minIndex);
   1675            return angle::Result::Continue;
   1676        case gl::DrawElementsType::UnsignedShort:
   1677            DrawPoints<GLushort>(mDevice, count, indices, minIndex);
   1678            return angle::Result::Continue;
   1679        case gl::DrawElementsType::UnsignedInt:
   1680            DrawPoints<GLuint>(mDevice, count, indices, minIndex);
   1681            return angle::Result::Continue;
   1682        default:
   1683            ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
   1684    }
   1685 }
   1686 
   1687 angle::Result Renderer9::getCountingIB(const gl::Context *context,
   1688                                       size_t count,
   1689                                       StaticIndexBufferInterface **outIB)
   1690 {
   1691    // Update the counting index buffer if it is not large enough or has not been created yet.
   1692    if (count <= 65536)  // 16-bit indices
   1693    {
   1694        const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short);
   1695 
   1696        if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
   1697        {
   1698            SafeDelete(mCountingIB);
   1699            mCountingIB = new StaticIndexBufferInterface(this);
   1700            ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
   1701                                                      gl::DrawElementsType::UnsignedShort));
   1702 
   1703            void *mappedMemory = nullptr;
   1704            ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
   1705 
   1706            unsigned short *data = static_cast<unsigned short *>(mappedMemory);
   1707            for (size_t i = 0; i < count; i++)
   1708            {
   1709                data[i] = static_cast<unsigned short>(i);
   1710            }
   1711 
   1712            ANGLE_TRY(mCountingIB->unmapBuffer(context));
   1713        }
   1714    }
   1715    else if (getNativeExtensions().elementIndexUintOES)
   1716    {
   1717        const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
   1718 
   1719        if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
   1720        {
   1721            SafeDelete(mCountingIB);
   1722            mCountingIB = new StaticIndexBufferInterface(this);
   1723            ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
   1724                                                      gl::DrawElementsType::UnsignedInt));
   1725 
   1726            void *mappedMemory = nullptr;
   1727            ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
   1728 
   1729            unsigned int *data = static_cast<unsigned int *>(mappedMemory);
   1730            for (unsigned int i = 0; i < count; i++)
   1731            {
   1732                data[i] = i;
   1733            }
   1734 
   1735            ANGLE_TRY(mCountingIB->unmapBuffer(context));
   1736        }
   1737    }
   1738    else
   1739    {
   1740        ANGLE_TRY_HR(GetImplAs<Context9>(context), E_OUTOFMEMORY,
   1741                     "Could not create a counting index buffer for glDrawArraysInstanced.");
   1742    }
   1743 
   1744    *outIB = mCountingIB;
   1745    return angle::Result::Continue;
   1746 }
   1747 
   1748 angle::Result Renderer9::applyShaders(const gl::Context *context, gl::PrimitiveMode drawMode)
   1749 {
   1750    const gl::State &state   = context->getState();
   1751    d3d::Context *contextD3D = GetImplAs<ContextD3D>(context);
   1752 
   1753    // This method is called single-threaded.
   1754    ANGLE_TRY(ensureHLSLCompilerInitialized(contextD3D));
   1755 
   1756    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(state.getProgram());
   1757    VertexArray9 *vao      = GetImplAs<VertexArray9>(state.getVertexArray());
   1758    programD3D->updateCachedInputLayout(vao->getCurrentStateSerial(), state);
   1759 
   1760    ShaderExecutableD3D *vertexExe = nullptr;
   1761    ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(contextD3D, &vertexExe, nullptr));
   1762 
   1763    const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
   1764    programD3D->updateCachedOutputLayout(context, drawFramebuffer);
   1765 
   1766    ShaderExecutableD3D *pixelExe = nullptr;
   1767    ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(contextD3D, &pixelExe, nullptr));
   1768 
   1769    IDirect3DVertexShader9 *vertexShader =
   1770        (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
   1771    IDirect3DPixelShader9 *pixelShader =
   1772        (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
   1773 
   1774    if (vertexShader != mAppliedVertexShader)
   1775    {
   1776        mDevice->SetVertexShader(vertexShader);
   1777        mAppliedVertexShader = vertexShader;
   1778    }
   1779 
   1780    if (pixelShader != mAppliedPixelShader)
   1781    {
   1782        mDevice->SetPixelShader(pixelShader);
   1783        mAppliedPixelShader = pixelShader;
   1784    }
   1785 
   1786    // D3D9 has a quirk where creating multiple shaders with the same content
   1787    // can return the same shader pointer. Because GL programs store different data
   1788    // per-program, checking the program serial guarantees we upload fresh
   1789    // uniform data even if our shader pointers are the same.
   1790    // https://code.google.com/p/angleproject/issues/detail?id=661
   1791    unsigned int programSerial = programD3D->getSerial();
   1792    if (programSerial != mAppliedProgramSerial)
   1793    {
   1794        programD3D->dirtyAllUniforms();
   1795        mStateManager.forceSetDXUniformsState();
   1796        mAppliedProgramSerial = programSerial;
   1797    }
   1798 
   1799    applyUniforms(programD3D);
   1800 
   1801    // Driver uniforms
   1802    mStateManager.setShaderConstants();
   1803 
   1804    return angle::Result::Continue;
   1805 }
   1806 
   1807 void Renderer9::applyUniforms(ProgramD3D *programD3D)
   1808 {
   1809    // Skip updates if we're not dirty. Note that D3D9 cannot have compute or geometry.
   1810    if (!programD3D->anyShaderUniformsDirty())
   1811    {
   1812        return;
   1813    }
   1814 
   1815    const auto &uniformArray = programD3D->getD3DUniforms();
   1816 
   1817    for (const D3DUniform *targetUniform : uniformArray)
   1818    {
   1819        // Built-in uniforms must be skipped.
   1820        if (!targetUniform->isReferencedByShader(gl::ShaderType::Vertex) &&
   1821            !targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
   1822            continue;
   1823 
   1824        const GLfloat *f = reinterpret_cast<const GLfloat *>(targetUniform->firstNonNullData());
   1825        const GLint *i   = reinterpret_cast<const GLint *>(targetUniform->firstNonNullData());
   1826 
   1827        switch (targetUniform->typeInfo.type)
   1828        {
   1829            case GL_SAMPLER_2D:
   1830            case GL_SAMPLER_CUBE:
   1831            case GL_SAMPLER_EXTERNAL_OES:
   1832            case GL_SAMPLER_VIDEO_IMAGE_WEBGL:
   1833                break;
   1834            case GL_BOOL:
   1835            case GL_BOOL_VEC2:
   1836            case GL_BOOL_VEC3:
   1837            case GL_BOOL_VEC4:
   1838                applyUniformnbv(targetUniform, i);
   1839                break;
   1840            case GL_FLOAT:
   1841            case GL_FLOAT_VEC2:
   1842            case GL_FLOAT_VEC3:
   1843            case GL_FLOAT_VEC4:
   1844            case GL_FLOAT_MAT2:
   1845            case GL_FLOAT_MAT3:
   1846            case GL_FLOAT_MAT4:
   1847                applyUniformnfv(targetUniform, f);
   1848                break;
   1849            case GL_INT:
   1850            case GL_INT_VEC2:
   1851            case GL_INT_VEC3:
   1852            case GL_INT_VEC4:
   1853                applyUniformniv(targetUniform, i);
   1854                break;
   1855            default:
   1856                UNREACHABLE();
   1857        }
   1858    }
   1859 
   1860    programD3D->markUniformsClean();
   1861 }
   1862 
   1863 void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
   1864 {
   1865    if (targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
   1866    {
   1867        mDevice->SetPixelShaderConstantF(
   1868            targetUniform->mShaderRegisterIndexes[gl::ShaderType::Fragment], v,
   1869            targetUniform->registerCount);
   1870    }
   1871 
   1872    if (targetUniform->isReferencedByShader(gl::ShaderType::Vertex))
   1873    {
   1874        mDevice->SetVertexShaderConstantF(
   1875            targetUniform->mShaderRegisterIndexes[gl::ShaderType::Vertex], v,
   1876            targetUniform->registerCount);
   1877    }
   1878 }
   1879 
   1880 void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
   1881 {
   1882    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
   1883    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
   1884 
   1885    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
   1886    {
   1887        vector[i][0] = (GLfloat)v[4 * i + 0];
   1888        vector[i][1] = (GLfloat)v[4 * i + 1];
   1889        vector[i][2] = (GLfloat)v[4 * i + 2];
   1890        vector[i][3] = (GLfloat)v[4 * i + 3];
   1891    }
   1892 
   1893    applyUniformnfv(targetUniform, (GLfloat *)vector);
   1894 }
   1895 
   1896 void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
   1897 {
   1898    ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
   1899    GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
   1900 
   1901    for (unsigned int i = 0; i < targetUniform->registerCount; i++)
   1902    {
   1903        vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
   1904        vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
   1905        vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
   1906        vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
   1907    }
   1908 
   1909    applyUniformnfv(targetUniform, (GLfloat *)vector);
   1910 }
   1911 
   1912 void Renderer9::clear(const ClearParameters &clearParams,
   1913                      const RenderTarget9 *colorRenderTarget,
   1914                      const RenderTarget9 *depthStencilRenderTarget)
   1915 {
   1916    // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
   1917    ASSERT(clearParams.colorType == GL_FLOAT);
   1918 
   1919    // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0
   1920    bool clearColor = clearParams.clearColor[0];
   1921    for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
   1922    {
   1923        ASSERT(clearParams.clearColor[i] == clearColor);
   1924    }
   1925 
   1926    float depth   = gl::clamp01(clearParams.depthValue);
   1927    DWORD stencil = clearParams.stencilValue & 0x000000FF;
   1928 
   1929    unsigned int stencilUnmasked = 0x0;
   1930    if (clearParams.clearStencil && depthStencilRenderTarget)
   1931    {
   1932        const gl::InternalFormat &depthStencilFormat =
   1933            gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
   1934        if (depthStencilFormat.stencilBits > 0)
   1935        {
   1936            const d3d9::D3DFormat &d3dFormatInfo =
   1937                d3d9::GetD3DFormatInfo(depthStencilRenderTarget->getD3DFormat());
   1938            stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
   1939        }
   1940    }
   1941 
   1942    const bool needMaskedStencilClear =
   1943        clearParams.clearStencil &&
   1944        (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
   1945 
   1946    bool needMaskedColorClear = false;
   1947    D3DCOLOR color            = D3DCOLOR_ARGB(255, 0, 0, 0);
   1948    if (clearColor)
   1949    {
   1950        ASSERT(colorRenderTarget != nullptr);
   1951 
   1952        const gl::InternalFormat &formatInfo =
   1953            gl::GetSizedInternalFormatInfo(colorRenderTarget->getInternalFormat());
   1954        const d3d9::D3DFormat &d3dFormatInfo =
   1955            d3d9::GetD3DFormatInfo(colorRenderTarget->getD3DFormat());
   1956 
   1957        color =
   1958            D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
   1959                                           ? 1.0f
   1960                                           : clearParams.colorF.alpha),
   1961                          gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
   1962                                           ? 0.0f
   1963                                           : clearParams.colorF.red),
   1964                          gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
   1965                                           ? 0.0f
   1966                                           : clearParams.colorF.green),
   1967                          gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
   1968                                           ? 0.0f
   1969                                           : clearParams.colorF.blue));
   1970 
   1971        const uint8_t colorMask =
   1972            gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(0, clearParams.colorMask);
   1973        bool r, g, b, a;
   1974        gl::BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
   1975        if ((formatInfo.redBits > 0 && !r) || (formatInfo.greenBits > 0 && !g) ||
   1976            (formatInfo.blueBits > 0 && !b) || (formatInfo.alphaBits > 0 && !a))
   1977        {
   1978            needMaskedColorClear = true;
   1979        }
   1980    }
   1981 
   1982    if (needMaskedColorClear || needMaskedStencilClear)
   1983    {
   1984        // State which is altered in all paths from this point to the clear call is saved.
   1985        // State which is altered in only some paths will be flagged dirty in the case that
   1986        //  that path is taken.
   1987        HRESULT hr;
   1988        if (mMaskedClearSavedState == nullptr)
   1989        {
   1990            hr = mDevice->BeginStateBlock();
   1991            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
   1992 
   1993            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
   1994            mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
   1995            mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
   1996            mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   1997            mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   1998            mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
   1999            mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   2000            mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
   2001            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
   2002            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
   2003            mDevice->SetPixelShader(nullptr);
   2004            mDevice->SetVertexShader(nullptr);
   2005            mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
   2006            mDevice->SetStreamSource(0, nullptr, 0, 0);
   2007            mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   2008            mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
   2009            mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
   2010            mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
   2011            mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
   2012            mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
   2013            mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
   2014 
   2015            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
   2016            {
   2017                mDevice->SetStreamSourceFreq(i, 1);
   2018            }
   2019 
   2020            hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
   2021            ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
   2022        }
   2023 
   2024        ASSERT(mMaskedClearSavedState != nullptr);
   2025 
   2026        if (mMaskedClearSavedState != nullptr)
   2027        {
   2028            hr = mMaskedClearSavedState->Capture();
   2029            ASSERT(SUCCEEDED(hr));
   2030        }
   2031 
   2032        mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
   2033        mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
   2034        mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
   2035        mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   2036        mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   2037        mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
   2038        mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   2039        mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
   2040 
   2041        if (clearColor)
   2042        {
   2043            // clearParams.colorMask follows the same packing scheme as
   2044            // D3DCOLORWRITEENABLE_RED/GREEN/BLUE/ALPHA
   2045            mDevice->SetRenderState(
   2046                D3DRS_COLORWRITEENABLE,
   2047                gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(0, clearParams.colorMask));
   2048        }
   2049        else
   2050        {
   2051            mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
   2052        }
   2053 
   2054        if (stencilUnmasked != 0x0 && clearParams.clearStencil)
   2055        {
   2056            mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
   2057            mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
   2058            mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
   2059            mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
   2060            mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
   2061            mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
   2062            mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
   2063            mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
   2064        }
   2065        else
   2066        {
   2067            mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
   2068        }
   2069 
   2070        mDevice->SetPixelShader(nullptr);
   2071        mDevice->SetVertexShader(nullptr);
   2072        mDevice->SetFVF(D3DFVF_XYZRHW);
   2073        mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   2074        mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
   2075        mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
   2076        mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
   2077        mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
   2078        mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
   2079        mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
   2080 
   2081        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
   2082        {
   2083            mDevice->SetStreamSourceFreq(i, 1);
   2084        }
   2085 
   2086        int renderTargetWidth  = mStateManager.getRenderTargetWidth();
   2087        int renderTargetHeight = mStateManager.getRenderTargetHeight();
   2088 
   2089        float quad[4][4];  // A quadrilateral covering the target, aligned to match the edges
   2090        quad[0][0] = -0.5f;
   2091        quad[0][1] = renderTargetHeight - 0.5f;
   2092        quad[0][2] = 0.0f;
   2093        quad[0][3] = 1.0f;
   2094 
   2095        quad[1][0] = renderTargetWidth - 0.5f;
   2096        quad[1][1] = renderTargetHeight - 0.5f;
   2097        quad[1][2] = 0.0f;
   2098        quad[1][3] = 1.0f;
   2099 
   2100        quad[2][0] = -0.5f;
   2101        quad[2][1] = -0.5f;
   2102        quad[2][2] = 0.0f;
   2103        quad[2][3] = 1.0f;
   2104 
   2105        quad[3][0] = renderTargetWidth - 0.5f;
   2106        quad[3][1] = -0.5f;
   2107        quad[3][2] = 0.0f;
   2108        quad[3][3] = 1.0f;
   2109 
   2110        startScene();
   2111        mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
   2112 
   2113        if (clearParams.clearDepth)
   2114        {
   2115            mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
   2116            mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
   2117            mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil);
   2118        }
   2119 
   2120        if (mMaskedClearSavedState != nullptr)
   2121        {
   2122            mMaskedClearSavedState->Apply();
   2123        }
   2124    }
   2125    else if (clearColor || clearParams.clearDepth || clearParams.clearStencil)
   2126    {
   2127        DWORD dxClearFlags = 0;
   2128        if (clearColor)
   2129        {
   2130            dxClearFlags |= D3DCLEAR_TARGET;
   2131        }
   2132        if (clearParams.clearDepth)
   2133        {
   2134            dxClearFlags |= D3DCLEAR_ZBUFFER;
   2135        }
   2136        if (clearParams.clearStencil)
   2137        {
   2138            dxClearFlags |= D3DCLEAR_STENCIL;
   2139        }
   2140 
   2141        mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
   2142    }
   2143 }
   2144 
   2145 void Renderer9::markAllStateDirty()
   2146 {
   2147    mAppliedRenderTargetSerial   = 0;
   2148    mAppliedDepthStencilSerial   = 0;
   2149    mDepthStencilInitialized     = false;
   2150    mRenderTargetDescInitialized = false;
   2151 
   2152    mStateManager.forceSetRasterState();
   2153    mStateManager.forceSetDepthStencilState();
   2154    mStateManager.forceSetBlendState();
   2155    mStateManager.forceSetScissorState();
   2156    mStateManager.forceSetViewportState();
   2157 
   2158    ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size());
   2159    for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
   2160    {
   2161        mCurVertexSamplerStates[i].forceSet = true;
   2162        mCurVertexTextures[i]               = angle::DirtyPointer;
   2163    }
   2164 
   2165    ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size());
   2166    for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++)
   2167    {
   2168        mCurPixelSamplerStates[i].forceSet = true;
   2169        mCurPixelTextures[i]               = angle::DirtyPointer;
   2170    }
   2171 
   2172    mAppliedIBSerial      = 0;
   2173    mAppliedVertexShader  = nullptr;
   2174    mAppliedPixelShader   = nullptr;
   2175    mAppliedProgramSerial = 0;
   2176    mStateManager.forceSetDXUniformsState();
   2177 
   2178    mVertexDeclarationCache.markStateDirty();
   2179 }
   2180 
   2181 void Renderer9::releaseDeviceResources()
   2182 {
   2183    for (size_t i = 0; i < mEventQueryPool.size(); i++)
   2184    {
   2185        SafeRelease(mEventQueryPool[i]);
   2186    }
   2187    mEventQueryPool.clear();
   2188 
   2189    SafeRelease(mMaskedClearSavedState);
   2190 
   2191    mVertexShaderCache.clear();
   2192    mPixelShaderCache.clear();
   2193 
   2194    SafeDelete(mBlit);
   2195    SafeDelete(mVertexDataManager);
   2196    SafeDelete(mIndexDataManager);
   2197    SafeDelete(mLineLoopIB);
   2198    SafeDelete(mCountingIB);
   2199 
   2200    for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
   2201    {
   2202        SafeDelete(mNullRenderTargetCache[i].renderTarget);
   2203    }
   2204 }
   2205 
   2206 // set notify to true to broadcast a message to all contexts of the device loss
   2207 bool Renderer9::testDeviceLost()
   2208 {
   2209    HRESULT status = getDeviceStatusCode();
   2210    return FAILED(status);
   2211 }
   2212 
   2213 HRESULT Renderer9::getDeviceStatusCode()
   2214 {
   2215    HRESULT status = D3D_OK;
   2216 
   2217    if (mDeviceEx)
   2218    {
   2219        status = mDeviceEx->CheckDeviceState(nullptr);
   2220    }
   2221    else if (mDevice)
   2222    {
   2223        status = mDevice->TestCooperativeLevel();
   2224    }
   2225 
   2226    return status;
   2227 }
   2228 
   2229 bool Renderer9::testDeviceResettable()
   2230 {
   2231    // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
   2232    // DEVICEREMOVED indicates the device has been stopped and must be recreated
   2233    switch (getDeviceStatusCode())
   2234    {
   2235        case D3DERR_DEVICENOTRESET:
   2236        case D3DERR_DEVICEHUNG:
   2237            return true;
   2238        case D3DERR_DEVICELOST:
   2239            return (mDeviceEx != nullptr);
   2240        case D3DERR_DEVICEREMOVED:
   2241            ASSERT(mDeviceEx != nullptr);
   2242            return isRemovedDeviceResettable();
   2243        default:
   2244            return false;
   2245    }
   2246 }
   2247 
   2248 bool Renderer9::resetDevice()
   2249 {
   2250    releaseDeviceResources();
   2251 
   2252    D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
   2253 
   2254    HRESULT result     = D3D_OK;
   2255    bool lost          = testDeviceLost();
   2256    bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
   2257 
   2258    // Device Removed is a feature which is only present with D3D9Ex
   2259    ASSERT(mDeviceEx != nullptr || !removedDevice);
   2260 
   2261    for (int attempts = 3; lost && attempts > 0; attempts--)
   2262    {
   2263        if (removedDevice)
   2264        {
   2265            // Device removed, which may trigger on driver reinstallation,
   2266            // may cause a longer wait other reset attempts before the
   2267            // system is ready to handle creating a new device.
   2268            Sleep(800);
   2269            lost = !resetRemovedDevice();
   2270        }
   2271        else if (mDeviceEx)
   2272        {
   2273            Sleep(500);  // Give the graphics driver some CPU time
   2274            result = mDeviceEx->ResetEx(&presentParameters, nullptr);
   2275            lost   = testDeviceLost();
   2276        }
   2277        else
   2278        {
   2279            result = mDevice->TestCooperativeLevel();
   2280            while (result == D3DERR_DEVICELOST)
   2281            {
   2282                Sleep(100);  // Give the graphics driver some CPU time
   2283                result = mDevice->TestCooperativeLevel();
   2284            }
   2285 
   2286            if (result == D3DERR_DEVICENOTRESET)
   2287            {
   2288                result = mDevice->Reset(&presentParameters);
   2289            }
   2290            lost = testDeviceLost();
   2291        }
   2292    }
   2293 
   2294    if (FAILED(result))
   2295    {
   2296        ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result);
   2297        return false;
   2298    }
   2299 
   2300    if (removedDevice && lost)
   2301    {
   2302        ERR() << "Device lost reset failed multiple times";
   2303        return false;
   2304    }
   2305 
   2306    // If the device was removed, we already finished re-initialization in resetRemovedDevice
   2307    if (!removedDevice)
   2308    {
   2309        // reset device defaults
   2310        if (initializeDevice().isError())
   2311        {
   2312            return false;
   2313        }
   2314    }
   2315 
   2316    return true;
   2317 }
   2318 
   2319 bool Renderer9::isRemovedDeviceResettable() const
   2320 {
   2321    bool success = false;
   2322 
   2323 #if ANGLE_D3D9EX == ANGLE_ENABLED
   2324    IDirect3D9Ex *d3d9Ex = nullptr;
   2325    typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
   2326    Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
   2327        reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
   2328 
   2329    if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
   2330    {
   2331        D3DCAPS9 deviceCaps;
   2332        HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
   2333        success        = SUCCEEDED(result);
   2334    }
   2335 
   2336    SafeRelease(d3d9Ex);
   2337 #else
   2338    UNREACHABLE();
   2339 #endif
   2340 
   2341    return success;
   2342 }
   2343 
   2344 bool Renderer9::resetRemovedDevice()
   2345 {
   2346    // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
   2347    // The hardware adapter has been removed. Application must destroy the device, do enumeration of
   2348    // adapters and create another Direct3D device. If application continues rendering without
   2349    // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
   2350    release();
   2351    return !initialize().isError();
   2352 }
   2353 
   2354 VendorID Renderer9::getVendorId() const
   2355 {
   2356    return static_cast<VendorID>(mAdapterIdentifier.VendorId);
   2357 }
   2358 
   2359 std::string Renderer9::getRendererDescription() const
   2360 {
   2361    std::ostringstream rendererString;
   2362 
   2363    rendererString << mAdapterIdentifier.Description;
   2364    if (getShareHandleSupport())
   2365    {
   2366        rendererString << " Direct3D9Ex";
   2367    }
   2368    else
   2369    {
   2370        rendererString << " Direct3D9";
   2371    }
   2372 
   2373    rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_"
   2374                   << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
   2375    rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_"
   2376                   << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
   2377 
   2378    return rendererString.str();
   2379 }
   2380 
   2381 DeviceIdentifier Renderer9::getAdapterIdentifier() const
   2382 {
   2383    DeviceIdentifier deviceIdentifier = {};
   2384    deviceIdentifier.VendorId         = static_cast<UINT>(mAdapterIdentifier.VendorId);
   2385    deviceIdentifier.DeviceId         = static_cast<UINT>(mAdapterIdentifier.DeviceId);
   2386    deviceIdentifier.SubSysId         = static_cast<UINT>(mAdapterIdentifier.SubSysId);
   2387    deviceIdentifier.Revision         = static_cast<UINT>(mAdapterIdentifier.Revision);
   2388    deviceIdentifier.FeatureLevel     = 0;
   2389 
   2390    return deviceIdentifier;
   2391 }
   2392 
   2393 unsigned int Renderer9::getReservedVertexUniformVectors() const
   2394 {
   2395    return d3d9_gl::GetReservedVertexUniformVectors();
   2396 }
   2397 
   2398 unsigned int Renderer9::getReservedFragmentUniformVectors() const
   2399 {
   2400    return d3d9_gl::GetReservedFragmentUniformVectors();
   2401 }
   2402 
   2403 bool Renderer9::getShareHandleSupport() const
   2404 {
   2405    // PIX doesn't seem to support using share handles, so disable them.
   2406    return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive(/*context=*/nullptr);
   2407 }
   2408 
   2409 int Renderer9::getMajorShaderModel() const
   2410 {
   2411    return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
   2412 }
   2413 
   2414 int Renderer9::getMinorShaderModel() const
   2415 {
   2416    return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
   2417 }
   2418 
   2419 std::string Renderer9::getShaderModelSuffix() const
   2420 {
   2421    return "";
   2422 }
   2423 
   2424 DWORD Renderer9::getCapsDeclTypes() const
   2425 {
   2426    return mDeviceCaps.DeclTypes;
   2427 }
   2428 
   2429 D3DPOOL Renderer9::getBufferPool(DWORD usage) const
   2430 {
   2431    if (mD3d9Ex != nullptr)
   2432    {
   2433        return D3DPOOL_DEFAULT;
   2434    }
   2435    else
   2436    {
   2437        if (!(usage & D3DUSAGE_DYNAMIC))
   2438        {
   2439            return D3DPOOL_MANAGED;
   2440        }
   2441    }
   2442 
   2443    return D3DPOOL_DEFAULT;
   2444 }
   2445 
   2446 angle::Result Renderer9::copyImage2D(const gl::Context *context,
   2447                                     const gl::Framebuffer *framebuffer,
   2448                                     const gl::Rectangle &sourceRect,
   2449                                     GLenum destFormat,
   2450                                     const gl::Offset &destOffset,
   2451                                     TextureStorage *storage,
   2452                                     GLint level)
   2453 {
   2454    RECT rect;
   2455    rect.left   = sourceRect.x;
   2456    rect.top    = sourceRect.y;
   2457    rect.right  = sourceRect.x + sourceRect.width;
   2458    rect.bottom = sourceRect.y + sourceRect.height;
   2459 
   2460    return mBlit->copy2D(context, framebuffer, rect, destFormat, destOffset, storage, level);
   2461 }
   2462 
   2463 angle::Result Renderer9::copyImageCube(const gl::Context *context,
   2464                                       const gl::Framebuffer *framebuffer,
   2465                                       const gl::Rectangle &sourceRect,
   2466                                       GLenum destFormat,
   2467                                       const gl::Offset &destOffset,
   2468                                       TextureStorage *storage,
   2469                                       gl::TextureTarget target,
   2470                                       GLint level)
   2471 {
   2472    RECT rect;
   2473    rect.left   = sourceRect.x;
   2474    rect.top    = sourceRect.y;
   2475    rect.right  = sourceRect.x + sourceRect.width;
   2476    rect.bottom = sourceRect.y + sourceRect.height;
   2477 
   2478    return mBlit->copyCube(context, framebuffer, rect, destFormat, destOffset, storage, target,
   2479                           level);
   2480 }
   2481 
   2482 angle::Result Renderer9::copyImage3D(const gl::Context *context,
   2483                                     const gl::Framebuffer *framebuffer,
   2484                                     const gl::Rectangle &sourceRect,
   2485                                     GLenum destFormat,
   2486                                     const gl::Offset &destOffset,
   2487                                     TextureStorage *storage,
   2488                                     GLint level)
   2489 {
   2490    // 3D textures are not available in the D3D9 backend.
   2491    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
   2492    return angle::Result::Stop;
   2493 }
   2494 
   2495 angle::Result Renderer9::copyImage2DArray(const gl::Context *context,
   2496                                          const gl::Framebuffer *framebuffer,
   2497                                          const gl::Rectangle &sourceRect,
   2498                                          GLenum destFormat,
   2499                                          const gl::Offset &destOffset,
   2500                                          TextureStorage *storage,
   2501                                          GLint level)
   2502 {
   2503    // 2D array textures are not available in the D3D9 backend.
   2504    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
   2505    return angle::Result::Stop;
   2506 }
   2507 
   2508 angle::Result Renderer9::copyTexture(const gl::Context *context,
   2509                                     const gl::Texture *source,
   2510                                     GLint sourceLevel,
   2511                                     gl::TextureTarget srcTarget,
   2512                                     const gl::Box &sourceBox,
   2513                                     GLenum destFormat,
   2514                                     GLenum destType,
   2515                                     const gl::Offset &destOffset,
   2516                                     TextureStorage *storage,
   2517                                     gl::TextureTarget destTarget,
   2518                                     GLint destLevel,
   2519                                     bool unpackFlipY,
   2520                                     bool unpackPremultiplyAlpha,
   2521                                     bool unpackUnmultiplyAlpha)
   2522 {
   2523    RECT rect;
   2524    rect.left   = sourceBox.x;
   2525    rect.top    = sourceBox.y;
   2526    rect.right  = sourceBox.x + sourceBox.width;
   2527    rect.bottom = sourceBox.y + sourceBox.height;
   2528 
   2529    return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage,
   2530                              destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha,
   2531                              unpackUnmultiplyAlpha);
   2532 }
   2533 
   2534 angle::Result Renderer9::copyCompressedTexture(const gl::Context *context,
   2535                                               const gl::Texture *source,
   2536                                               GLint sourceLevel,
   2537                                               TextureStorage *storage,
   2538                                               GLint destLevel)
   2539 {
   2540    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
   2541    return angle::Result::Stop;
   2542 }
   2543 
   2544 angle::Result Renderer9::createRenderTarget(const gl::Context *context,
   2545                                            int width,
   2546                                            int height,
   2547                                            GLenum format,
   2548                                            GLsizei samples,
   2549                                            RenderTargetD3D **outRT)
   2550 {
   2551    const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
   2552 
   2553    const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
   2554    GLuint supportedSamples            = textureCaps.getNearestSamples(samples);
   2555 
   2556    IDirect3DTexture9 *texture      = nullptr;
   2557    IDirect3DSurface9 *renderTarget = nullptr;
   2558    if (width > 0 && height > 0)
   2559    {
   2560        bool requiresInitialization = false;
   2561        HRESULT result              = D3DERR_INVALIDCALL;
   2562 
   2563        const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
   2564        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
   2565        {
   2566            result = mDevice->CreateDepthStencilSurface(
   2567                width, height, d3d9FormatInfo.renderFormat,
   2568                gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr);
   2569        }
   2570        else
   2571        {
   2572            requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr);
   2573            if (supportedSamples > 0)
   2574            {
   2575                result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
   2576                                                     gl_d3d9::GetMultisampleType(supportedSamples),
   2577                                                     0, FALSE, &renderTarget, nullptr);
   2578            }
   2579            else
   2580            {
   2581                result = mDevice->CreateTexture(
   2582                    width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat,
   2583                    getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr);
   2584                if (!FAILED(result))
   2585                {
   2586                    result = texture->GetSurfaceLevel(0, &renderTarget);
   2587                }
   2588            }
   2589        }
   2590 
   2591        ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create render target");
   2592 
   2593        if (requiresInitialization)
   2594        {
   2595            // This format requires that the data be initialized before the render target can be
   2596            // used Unfortunately this requires a Get call on the d3d device but it is far better
   2597            // than having to mark the render target as lockable and copy data to the gpu.
   2598            IDirect3DSurface9 *prevRenderTarget = nullptr;
   2599            mDevice->GetRenderTarget(0, &prevRenderTarget);
   2600            mDevice->SetRenderTarget(0, renderTarget);
   2601            mDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
   2602            mDevice->SetRenderTarget(0, prevRenderTarget);
   2603        }
   2604    }
   2605 
   2606    *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1,
   2607                                      supportedSamples);
   2608    return angle::Result::Continue;
   2609 }
   2610 
   2611 angle::Result Renderer9::createRenderTargetCopy(const gl::Context *context,
   2612                                                RenderTargetD3D *source,
   2613                                                RenderTargetD3D **outRT)
   2614 {
   2615    ASSERT(source != nullptr);
   2616 
   2617    RenderTargetD3D *newRT = nullptr;
   2618    ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(),
   2619                                 source->getInternalFormat(), source->getSamples(), &newRT));
   2620 
   2621    RenderTarget9 *source9 = GetAs<RenderTarget9>(source);
   2622    RenderTarget9 *dest9   = GetAs<RenderTarget9>(newRT);
   2623 
   2624    HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(),
   2625                                          nullptr, D3DTEXF_NONE);
   2626    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to copy render target");
   2627 
   2628    *outRT = newRT;
   2629    return angle::Result::Continue;
   2630 }
   2631 
   2632 angle::Result Renderer9::loadExecutable(d3d::Context *context,
   2633                                        const uint8_t *function,
   2634                                        size_t length,
   2635                                        gl::ShaderType type,
   2636                                        const std::vector<D3DVarying> &streamOutVaryings,
   2637                                        bool separatedOutputBuffers,
   2638                                        ShaderExecutableD3D **outExecutable)
   2639 {
   2640    // Transform feedback is not supported in ES2 or D3D9
   2641    ASSERT(streamOutVaryings.empty());
   2642 
   2643    switch (type)
   2644    {
   2645        case gl::ShaderType::Vertex:
   2646        {
   2647            IDirect3DVertexShader9 *vshader = nullptr;
   2648            ANGLE_TRY(createVertexShader(context, (DWORD *)function, length, &vshader));
   2649            *outExecutable = new ShaderExecutable9(function, length, vshader);
   2650        }
   2651        break;
   2652        case gl::ShaderType::Fragment:
   2653        {
   2654            IDirect3DPixelShader9 *pshader = nullptr;
   2655            ANGLE_TRY(createPixelShader(context, (DWORD *)function, length, &pshader));
   2656            *outExecutable = new ShaderExecutable9(function, length, pshader);
   2657        }
   2658        break;
   2659        default:
   2660            ANGLE_HR_UNREACHABLE(context);
   2661    }
   2662 
   2663    return angle::Result::Continue;
   2664 }
   2665 
   2666 angle::Result Renderer9::compileToExecutable(d3d::Context *context,
   2667                                             gl::InfoLog &infoLog,
   2668                                             const std::string &shaderHLSL,
   2669                                             gl::ShaderType type,
   2670                                             const std::vector<D3DVarying> &streamOutVaryings,
   2671                                             bool separatedOutputBuffers,
   2672                                             const CompilerWorkaroundsD3D &workarounds,
   2673                                             ShaderExecutableD3D **outExectuable)
   2674 {
   2675    // Transform feedback is not supported in ES2 or D3D9
   2676    ASSERT(streamOutVaryings.empty());
   2677 
   2678    std::stringstream profileStream;
   2679 
   2680    switch (type)
   2681    {
   2682        case gl::ShaderType::Vertex:
   2683            profileStream << "vs";
   2684            break;
   2685        case gl::ShaderType::Fragment:
   2686            profileStream << "ps";
   2687            break;
   2688        default:
   2689            ANGLE_HR_UNREACHABLE(context);
   2690    }
   2691 
   2692    profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2);
   2693    profileStream << "_"
   2694                  << "0";
   2695 
   2696    std::string profile = profileStream.str();
   2697 
   2698    UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
   2699 
   2700    if (workarounds.skipOptimization)
   2701    {
   2702        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
   2703    }
   2704    else if (workarounds.useMaxOptimization)
   2705    {
   2706        flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
   2707    }
   2708 
   2709    if (gl::DebugAnnotationsActive(/*context=*/nullptr))
   2710    {
   2711 #ifndef NDEBUG
   2712        flags = D3DCOMPILE_SKIP_OPTIMIZATION;
   2713 #endif
   2714 
   2715        flags |= D3DCOMPILE_DEBUG;
   2716    }
   2717 
   2718    // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
   2719    // when it would otherwise pass with alternative options. Try the default flags first and if
   2720    // compilation fails, try some alternatives.
   2721    std::vector<CompileConfig> configs;
   2722    configs.push_back(CompileConfig(flags, "default"));
   2723    configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
   2724    configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
   2725 
   2726    ID3DBlob *binary = nullptr;
   2727    std::string debugInfo;
   2728    angle::Result error = mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs,
   2729                                                    nullptr, &binary, &debugInfo);
   2730    ANGLE_TRY(error);
   2731 
   2732    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the
   2733    // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
   2734    // internal state is still OK.
   2735    if (!binary)
   2736    {
   2737        *outExectuable = nullptr;
   2738        return angle::Result::Continue;
   2739    }
   2740 
   2741    error = loadExecutable(context, reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
   2742                           binary->GetBufferSize(), type, streamOutVaryings, separatedOutputBuffers,
   2743                           outExectuable);
   2744 
   2745    SafeRelease(binary);
   2746    ANGLE_TRY(error);
   2747 
   2748    if (!debugInfo.empty())
   2749    {
   2750        (*outExectuable)->appendDebugInfo(debugInfo);
   2751    }
   2752 
   2753    return angle::Result::Continue;
   2754 }
   2755 
   2756 angle::Result Renderer9::ensureHLSLCompilerInitialized(d3d::Context *context)
   2757 {
   2758    return mCompiler.ensureInitialized(context);
   2759 }
   2760 
   2761 UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
   2762 {
   2763    return new UniformStorageD3D(storageSize);
   2764 }
   2765 
   2766 angle::Result Renderer9::boxFilter(Context9 *context9,
   2767                                   IDirect3DSurface9 *source,
   2768                                   IDirect3DSurface9 *dest)
   2769 {
   2770    return mBlit->boxFilter(context9, source, dest);
   2771 }
   2772 
   2773 D3DPOOL Renderer9::getTexturePool(DWORD usage) const
   2774 {
   2775    if (mD3d9Ex != nullptr)
   2776    {
   2777        return D3DPOOL_DEFAULT;
   2778    }
   2779    else
   2780    {
   2781        if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
   2782        {
   2783            return D3DPOOL_MANAGED;
   2784        }
   2785    }
   2786 
   2787    return D3DPOOL_DEFAULT;
   2788 }
   2789 
   2790 angle::Result Renderer9::copyToRenderTarget(const gl::Context *context,
   2791                                            IDirect3DSurface9 *dest,
   2792                                            IDirect3DSurface9 *source,
   2793                                            bool fromManaged)
   2794 {
   2795    ASSERT(source && dest);
   2796 
   2797    Context9 *context9 = GetImplAs<Context9>(context);
   2798 
   2799    HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
   2800 
   2801    if (fromManaged)
   2802    {
   2803        D3DSURFACE_DESC desc;
   2804        source->GetDesc(&desc);
   2805 
   2806        IDirect3DSurface9 *surf = 0;
   2807        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
   2808                                                      D3DPOOL_SYSTEMMEM, &surf, nullptr);
   2809 
   2810        if (SUCCEEDED(result))
   2811        {
   2812            ANGLE_TRY(Image9::CopyLockableSurfaces(context9, surf, source));
   2813            result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr);
   2814            SafeRelease(surf);
   2815        }
   2816    }
   2817    else
   2818    {
   2819        endScene();
   2820        result = mDevice->StretchRect(source, nullptr, dest, nullptr, D3DTEXF_NONE);
   2821    }
   2822 
   2823    ANGLE_TRY_HR(context9, result, "Failed to blit internal texture");
   2824    return angle::Result::Continue;
   2825 }
   2826 
   2827 RendererClass Renderer9::getRendererClass() const
   2828 {
   2829    return RENDERER_D3D9;
   2830 }
   2831 
   2832 ImageD3D *Renderer9::createImage()
   2833 {
   2834    return new Image9(this);
   2835 }
   2836 
   2837 ExternalImageSiblingImpl *Renderer9::createExternalImageSibling(const gl::Context *context,
   2838                                                                EGLenum target,
   2839                                                                EGLClientBuffer buffer,
   2840                                                                const egl::AttributeMap &attribs)
   2841 {
   2842    UNREACHABLE();
   2843    return nullptr;
   2844 }
   2845 
   2846 angle::Result Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
   2847 {
   2848    Image9 *src9 = GetAs<Image9>(src);
   2849    Image9 *dst9 = GetAs<Image9>(dest);
   2850    return Image9::GenerateMipmap(GetImplAs<Context9>(context), dst9, src9);
   2851 }
   2852 
   2853 angle::Result Renderer9::generateMipmapUsingD3D(const gl::Context *context,
   2854                                                TextureStorage *storage,
   2855                                                const gl::TextureState &textureState)
   2856 {
   2857    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
   2858    return angle::Result::Stop;
   2859 }
   2860 
   2861 angle::Result Renderer9::copyImage(const gl::Context *context,
   2862                                   ImageD3D *dest,
   2863                                   ImageD3D *source,
   2864                                   const gl::Box &sourceBox,
   2865                                   const gl::Offset &destOffset,
   2866                                   bool unpackFlipY,
   2867                                   bool unpackPremultiplyAlpha,
   2868                                   bool unpackUnmultiplyAlpha)
   2869 {
   2870    Image9 *dest9 = GetAs<Image9>(dest);
   2871    Image9 *src9  = GetAs<Image9>(source);
   2872    return Image9::CopyImage(context, dest9, src9, sourceBox.toRect(), destOffset, unpackFlipY,
   2873                             unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
   2874 }
   2875 
   2876 TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain, const std::string &label)
   2877 {
   2878    SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
   2879    return new TextureStorage9_2D(this, swapChain9, label);
   2880 }
   2881 
   2882 TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
   2883                                                        RenderTargetD3D *renderTargetD3D,
   2884                                                        const std::string &label)
   2885 {
   2886    return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D),
   2887                                        label);
   2888 }
   2889 
   2890 TextureStorage *Renderer9::createTextureStorageBuffer(
   2891    const gl::OffsetBindingPointer<gl::Buffer> &buffer,
   2892    GLenum internalFormat,
   2893    const std::string &label)
   2894 {
   2895    UNREACHABLE();
   2896    return nullptr;
   2897 }
   2898 
   2899 TextureStorage *Renderer9::createTextureStorageExternal(
   2900    egl::Stream *stream,
   2901    const egl::Stream::GLTextureDescription &desc,
   2902    const std::string &label)
   2903 {
   2904    UNIMPLEMENTED();
   2905    return nullptr;
   2906 }
   2907 
   2908 TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat,
   2909                                                  BindFlags bindFlags,
   2910                                                  GLsizei width,
   2911                                                  GLsizei height,
   2912                                                  int levels,
   2913                                                  const std::string &label,
   2914                                                  bool hintLevelZeroOnly)
   2915 {
   2916    return new TextureStorage9_2D(this, internalformat, bindFlags.renderTarget, width, height,
   2917                                  levels, label);
   2918 }
   2919 
   2920 TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat,
   2921                                                    BindFlags bindFlags,
   2922                                                    int size,
   2923                                                    int levels,
   2924                                                    bool hintLevelZeroOnly,
   2925                                                    const std::string &label)
   2926 {
   2927    return new TextureStorage9_Cube(this, internalformat, bindFlags.renderTarget, size, levels,
   2928                                    hintLevelZeroOnly, label);
   2929 }
   2930 
   2931 TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat,
   2932                                                  BindFlags bindFlags,
   2933                                                  GLsizei width,
   2934                                                  GLsizei height,
   2935                                                  GLsizei depth,
   2936                                                  int levels,
   2937                                                  const std::string &label)
   2938 {
   2939    // 3D textures are not supported by the D3D9 backend.
   2940    UNREACHABLE();
   2941 
   2942    return nullptr;
   2943 }
   2944 
   2945 TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat,
   2946                                                       BindFlags bindFlags,
   2947                                                       GLsizei width,
   2948                                                       GLsizei height,
   2949                                                       GLsizei depth,
   2950                                                       int levels,
   2951                                                       const std::string &label)
   2952 {
   2953    // 2D array textures are not supported by the D3D9 backend.
   2954    UNREACHABLE();
   2955 
   2956    return nullptr;
   2957 }
   2958 
   2959 TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalformat,
   2960                                                             GLsizei width,
   2961                                                             GLsizei height,
   2962                                                             int levels,
   2963                                                             int samples,
   2964                                                             bool fixedSampleLocations,
   2965                                                             const std::string &label)
   2966 {
   2967    // 2D multisampled textures are not supported by the D3D9 backend.
   2968    UNREACHABLE();
   2969 
   2970    return nullptr;
   2971 }
   2972 
   2973 TextureStorage *Renderer9::createTextureStorage2DMultisampleArray(GLenum internalformat,
   2974                                                                  GLsizei width,
   2975                                                                  GLsizei height,
   2976                                                                  GLsizei depth,
   2977                                                                  int levels,
   2978                                                                  int samples,
   2979                                                                  bool fixedSampleLocations,
   2980                                                                  const std::string &label)
   2981 {
   2982    // 2D multisampled textures are not supported by the D3D9 backend.
   2983    UNREACHABLE();
   2984 
   2985    return nullptr;
   2986 }
   2987 
   2988 bool Renderer9::getLUID(LUID *adapterLuid) const
   2989 {
   2990    adapterLuid->HighPart = 0;
   2991    adapterLuid->LowPart  = 0;
   2992 
   2993    if (mD3d9Ex)
   2994    {
   2995        mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
   2996        return true;
   2997    }
   2998 
   2999    return false;
   3000 }
   3001 
   3002 VertexConversionType Renderer9::getVertexConversionType(angle::FormatID vertexFormatID) const
   3003 {
   3004    return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).conversionType;
   3005 }
   3006 
   3007 GLenum Renderer9::getVertexComponentType(angle::FormatID vertexFormatID) const
   3008 {
   3009    return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).componentType;
   3010 }
   3011 
   3012 angle::Result Renderer9::getVertexSpaceRequired(const gl::Context *context,
   3013                                                const gl::VertexAttribute &attrib,
   3014                                                const gl::VertexBinding &binding,
   3015                                                size_t count,
   3016                                                GLsizei instances,
   3017                                                GLuint baseInstance,
   3018                                                unsigned int *bytesRequiredOut) const
   3019 {
   3020    if (!attrib.enabled)
   3021    {
   3022        *bytesRequiredOut = 16u;
   3023        return angle::Result::Continue;
   3024    }
   3025 
   3026    angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, gl::VertexAttribType::Float);
   3027    const d3d9::VertexFormat &d3d9VertexInfo =
   3028        d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID);
   3029 
   3030    unsigned int elementCount  = 0;
   3031    const unsigned int divisor = binding.getDivisor();
   3032    if (instances == 0 || divisor == 0)
   3033    {
   3034        elementCount = static_cast<unsigned int>(count);
   3035    }
   3036    else
   3037    {
   3038        // Round up to divisor, if possible
   3039        elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
   3040    }
   3041 
   3042    bool check = (d3d9VertexInfo.outputElementSize >
   3043                  std::numeric_limits<unsigned int>::max() / elementCount);
   3044    ANGLE_CHECK(GetImplAs<Context9>(context), !check,
   3045                "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
   3046 
   3047    *bytesRequiredOut = static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
   3048    return angle::Result::Continue;
   3049 }
   3050 
   3051 void Renderer9::generateCaps(gl::Caps *outCaps,
   3052                             gl::TextureCapsMap *outTextureCaps,
   3053                             gl::Extensions *outExtensions,
   3054                             gl::Limitations *outLimitations) const
   3055 {
   3056    d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps,
   3057                          outExtensions, outLimitations);
   3058 }
   3059 
   3060 void Renderer9::initializeFeatures(angle::FeaturesD3D *features) const
   3061 {
   3062    if (!mDisplay->getState().featuresAllDisabled)
   3063    {
   3064        d3d9::InitializeFeatures(features);
   3065    }
   3066    ApplyFeatureOverrides(features, mDisplay->getState());
   3067 }
   3068 
   3069 void Renderer9::initializeFrontendFeatures(angle::FrontendFeatures *features) const {}
   3070 
   3071 DeviceImpl *Renderer9::createEGLDevice()
   3072 {
   3073    return new DeviceD3D(EGL_D3D9_DEVICE_ANGLE, mDevice);
   3074 }
   3075 
   3076 Renderer9::CurSamplerState::CurSamplerState()
   3077    : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState()
   3078 {}
   3079 
   3080 angle::Result Renderer9::genericDrawElements(const gl::Context *context,
   3081                                             gl::PrimitiveMode mode,
   3082                                             GLsizei count,
   3083                                             gl::DrawElementsType type,
   3084                                             const void *indices,
   3085                                             GLsizei instances)
   3086 {
   3087    const gl::State &state = context->getState();
   3088    gl::Program *program   = context->getState().getProgram();
   3089    ASSERT(program != nullptr);
   3090    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
   3091    bool usesPointSize     = programD3D->usesPointSize();
   3092 
   3093    programD3D->updateSamplerMapping();
   3094 
   3095    if (!applyPrimitiveType(mode, count, usesPointSize))
   3096    {
   3097        return angle::Result::Continue;
   3098    }
   3099 
   3100    ANGLE_TRY(updateState(context, mode));
   3101    ANGLE_TRY(applyTextures(context));
   3102    ANGLE_TRY(applyShaders(context, mode));
   3103 
   3104    if (!skipDraw(state, mode))
   3105    {
   3106        ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
   3107    }
   3108 
   3109    return angle::Result::Continue;
   3110 }
   3111 
   3112 angle::Result Renderer9::genericDrawArrays(const gl::Context *context,
   3113                                           gl::PrimitiveMode mode,
   3114                                           GLint first,
   3115                                           GLsizei count,
   3116                                           GLsizei instances)
   3117 {
   3118    gl::Program *program = context->getState().getProgram();
   3119    ASSERT(program != nullptr);
   3120    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
   3121    bool usesPointSize     = programD3D->usesPointSize();
   3122 
   3123    programD3D->updateSamplerMapping();
   3124 
   3125    if (!applyPrimitiveType(mode, count, usesPointSize))
   3126    {
   3127        return angle::Result::Continue;
   3128    }
   3129 
   3130    ANGLE_TRY(updateState(context, mode));
   3131    ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
   3132    ANGLE_TRY(applyTextures(context));
   3133    ANGLE_TRY(applyShaders(context, mode));
   3134 
   3135    if (!skipDraw(context->getState(), mode))
   3136    {
   3137        ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances));
   3138    }
   3139 
   3140    return angle::Result::Continue;
   3141 }
   3142 
   3143 FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
   3144 {
   3145    return new Framebuffer9(state, this);
   3146 }
   3147 
   3148 gl::Version Renderer9::getMaxSupportedESVersion() const
   3149 {
   3150    return gl::Version(2, 0);
   3151 }
   3152 
   3153 gl::Version Renderer9::getMaxConformantESVersion() const
   3154 {
   3155    return gl::Version(2, 0);
   3156 }
   3157 
   3158 angle::Result Renderer9::clearRenderTarget(const gl::Context *context,
   3159                                           RenderTargetD3D *renderTarget,
   3160                                           const gl::ColorF &clearColorValue,
   3161                                           const float clearDepthValue,
   3162                                           const unsigned int clearStencilValue)
   3163 {
   3164    D3DCOLOR color =
   3165        D3DCOLOR_ARGB(gl::unorm<8>(clearColorValue.alpha), gl::unorm<8>(clearColorValue.red),
   3166                      gl::unorm<8>(clearColorValue.green), gl::unorm<8>(clearColorValue.blue));
   3167    float depth   = clearDepthValue;
   3168    DWORD stencil = clearStencilValue & 0x000000FF;
   3169 
   3170    unsigned int renderTargetSerial        = renderTarget->getSerial();
   3171    RenderTarget9 *renderTarget9           = GetAs<RenderTarget9>(renderTarget);
   3172    IDirect3DSurface9 *renderTargetSurface = renderTarget9->getSurface();
   3173    ASSERT(renderTargetSurface);
   3174 
   3175    DWORD dxClearFlags = 0;
   3176 
   3177    const gl::InternalFormat &internalFormatInfo =
   3178        gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
   3179    if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
   3180    {
   3181        dxClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
   3182        if (mAppliedDepthStencilSerial != renderTargetSerial)
   3183        {
   3184            mDevice->SetDepthStencilSurface(renderTargetSurface);
   3185        }
   3186    }
   3187    else
   3188    {
   3189        dxClearFlags = D3DCLEAR_TARGET;
   3190        if (mAppliedRenderTargetSerial != renderTargetSerial)
   3191        {
   3192            mDevice->SetRenderTarget(0, renderTargetSurface);
   3193        }
   3194    }
   3195    SafeRelease(renderTargetSurface);
   3196 
   3197    D3DVIEWPORT9 viewport;
   3198    viewport.X      = 0;
   3199    viewport.Y      = 0;
   3200    viewport.Width  = renderTarget->getWidth();
   3201    viewport.Height = renderTarget->getHeight();
   3202    mDevice->SetViewport(&viewport);
   3203 
   3204    mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
   3205 
   3206    mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
   3207 
   3208    markAllStateDirty();
   3209 
   3210    return angle::Result::Continue;
   3211 }
   3212 
   3213 bool Renderer9::canSelectViewInVertexShader() const
   3214 {
   3215    return false;
   3216 }
   3217 
   3218 // For each Direct3D sampler of either the pixel or vertex stage,
   3219 // looks up the corresponding OpenGL texture image unit and texture type,
   3220 // and sets the texture and its addressing/filtering state (or NULL when inactive).
   3221 // Sampler mapping needs to be up-to-date on the program object before this is called.
   3222 angle::Result Renderer9::applyTextures(const gl::Context *context, gl::ShaderType shaderType)
   3223 {
   3224    const auto &glState    = context->getState();
   3225    const auto &caps       = context->getCaps();
   3226    ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
   3227 
   3228    ASSERT(!programD3D->isSamplerMappingDirty());
   3229 
   3230    // TODO(jmadill): Use the Program's sampler bindings.
   3231    const gl::ActiveTexturesCache &activeTextures = glState.getActiveTexturesCache();
   3232 
   3233    const gl::RangeUI samplerRange = programD3D->getUsedSamplerRange(shaderType);
   3234    for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
   3235         samplerIndex++)
   3236    {
   3237        GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
   3238        ASSERT(textureUnit != -1);
   3239        gl::Texture *texture = activeTextures[textureUnit];
   3240 
   3241        // A nullptr texture indicates incomplete.
   3242        if (texture)
   3243        {
   3244            gl::Sampler *samplerObject = glState.getSampler(textureUnit);
   3245 
   3246            const gl::SamplerState &samplerState =
   3247                samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
   3248 
   3249            ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
   3250            ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
   3251        }
   3252        else
   3253        {
   3254            gl::TextureType textureType =
   3255                programD3D->getSamplerTextureType(shaderType, samplerIndex);
   3256 
   3257            // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
   3258            // incomplete texture.
   3259            gl::Texture *incompleteTexture = nullptr;
   3260            ANGLE_TRY(getIncompleteTexture(context, textureType, &incompleteTexture));
   3261            ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
   3262                                      incompleteTexture->getSamplerState()));
   3263            ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
   3264        }
   3265    }
   3266 
   3267    // Set all the remaining textures to NULL
   3268    int samplerCount = (shaderType == gl::ShaderType::Fragment)
   3269                           ? caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]
   3270                           : caps.maxShaderTextureImageUnits[gl::ShaderType::Vertex];
   3271 
   3272    // TODO(jmadill): faster way?
   3273    for (int samplerIndex = samplerRange.high(); samplerIndex < samplerCount; samplerIndex++)
   3274    {
   3275        ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
   3276    }
   3277 
   3278    return angle::Result::Continue;
   3279 }
   3280 
   3281 angle::Result Renderer9::applyTextures(const gl::Context *context)
   3282 {
   3283    ANGLE_TRY(applyTextures(context, gl::ShaderType::Vertex));
   3284    ANGLE_TRY(applyTextures(context, gl::ShaderType::Fragment));
   3285    return angle::Result::Continue;
   3286 }
   3287 
   3288 angle::Result Renderer9::getIncompleteTexture(const gl::Context *context,
   3289                                              gl::TextureType type,
   3290                                              gl::Texture **textureOut)
   3291 {
   3292    return GetImplAs<Context9>(context)->getIncompleteTexture(context, type, textureOut);
   3293 }
   3294 
   3295 angle::Result Renderer9::ensureVertexDataManagerInitialized(const gl::Context *context)
   3296 {
   3297    if (!mVertexDataManager)
   3298    {
   3299        mVertexDataManager = new VertexDataManager(this);
   3300        ANGLE_TRY(mVertexDataManager->initialize(context));
   3301    }
   3302 
   3303    return angle::Result::Continue;
   3304 }
   3305 
   3306 std::string Renderer9::getVendorString() const
   3307 {
   3308    return GetVendorString(getVendorId());
   3309 }
   3310 
   3311 std::string Renderer9::getVersionString(bool includeFullVersion) const
   3312 {
   3313    std::ostringstream versionString;
   3314    std::string driverName(mAdapterIdentifier.Driver);
   3315    if (!driverName.empty())
   3316    {
   3317        versionString << mAdapterIdentifier.Driver;
   3318    }
   3319    else
   3320    {
   3321        versionString << "D3D9";
   3322    }
   3323 
   3324    if (includeFullVersion)
   3325    {
   3326        versionString << " -";
   3327        versionString << GetDriverVersionString(mAdapterIdentifier.DriverVersion);
   3328    }
   3329 
   3330    return versionString.str();
   3331 }
   3332 
   3333 RendererD3D *CreateRenderer9(egl::Display *display)
   3334 {
   3335    return new Renderer9(display);
   3336 }
   3337 
   3338 }  // namespace rx