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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 #include "precompiled.h"
     2 //
     3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
     4 // Use of this source code is governed by a BSD-style license that can be
     5 // found in the LICENSE file.
     6 //
     8 // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
    10 #include "libGLESv2/main.h"
    11 #include "libGLESv2/Buffer.h"
    12 #include "libGLESv2/Texture.h"
    13 #include "libGLESv2/Framebuffer.h"
    14 #include "libGLESv2/Renderbuffer.h"
    15 #include "libGLESv2/ProgramBinary.h"
    16 #include "libGLESv2/renderer/IndexDataManager.h"
    17 #include "libGLESv2/renderer/Renderer9.h"
    18 #include "libGLESv2/renderer/renderer9_utils.h"
    19 #include "libGLESv2/renderer/ShaderExecutable9.h"
    20 #include "libGLESv2/renderer/SwapChain9.h"
    21 #include "libGLESv2/renderer/TextureStorage9.h"
    22 #include "libGLESv2/renderer/Image9.h"
    23 #include "libGLESv2/renderer/Blit.h"
    24 #include "libGLESv2/renderer/RenderTarget9.h"
    25 #include "libGLESv2/renderer/VertexBuffer9.h"
    26 #include "libGLESv2/renderer/IndexBuffer9.h"
    27 #include "libGLESv2/renderer/BufferStorage9.h"
    28 #include "libGLESv2/renderer/Query9.h"
    29 #include "libGLESv2/renderer/Fence9.h"
    31 #include "libEGL/Display.h"
    33 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
    34 #define REF_RAST 0
    36 // The "Debug This Pixel..." feature in PIX often fails when using the
    37 // D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
    38 // machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
    39 #if !defined(ANGLE_ENABLE_D3D9EX)
    40 // Enables use of the IDirect3D9Ex interface, when available
    41 #define ANGLE_ENABLE_D3D9EX 1
    42 #endif // !defined(ANGLE_ENABLE_D3D9EX)
    44 namespace rx
    45 {
    46 static const D3DFORMAT RenderTargetFormats[] =
    47     {
    48         D3DFMT_A1R5G5B5,
    49     //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
    50         D3DFMT_A8R8G8B8,
    51         D3DFMT_R5G6B5,
    52     //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
    53         D3DFMT_X8R8G8B8
    54     };
    56 static const D3DFORMAT DepthStencilFormats[] =
    57     {
    58         D3DFMT_UNKNOWN,
    59     //  D3DFMT_D16_LOCKABLE,
    60         D3DFMT_D32,
    61     //  D3DFMT_D15S1,
    62         D3DFMT_D24S8,
    63         D3DFMT_D24X8,
    64     //  D3DFMT_D24X4S4,
    65         D3DFMT_D16,
    66     //  D3DFMT_D32F_LOCKABLE,
    67     //  D3DFMT_D24FS8
    68     };
    70 enum
    71 {
    72     MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
    73     MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
    74     MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
    75     MAX_VARYING_VECTORS_SM2 = 8,
    76     MAX_VARYING_VECTORS_SM3 = 10,
    78     MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
    79 };
    81 Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
    82 {
    83     mD3d9Module = NULL;
    85     mD3d9 = NULL;
    86     mD3d9Ex = NULL;
    87     mDevice = NULL;
    88     mDeviceEx = NULL;
    89     mDeviceWindow = NULL;
    90     mBlit = NULL;
    92     mAdapter = D3DADAPTER_DEFAULT;
    94     #if REF_RAST == 1 || defined(FORCE_REF_RAST)
    95         mDeviceType = D3DDEVTYPE_REF;
    96     #else
    97         mDeviceType = D3DDEVTYPE_HAL;
    98     #endif
   100     mDeviceLost = false;
   102     mMaxSupportedSamples = 0;
   104     mMaskedClearSavedState = NULL;
   106     mVertexDataManager = NULL;
   107     mIndexDataManager = NULL;
   108     mLineLoopIB = NULL;
   110     mMaxNullColorbufferLRU = 0;
   111     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
   112     {
   113         mNullColorbufferCache[i].lruCount = 0;
   114         mNullColorbufferCache[i].width = 0;
   115         mNullColorbufferCache[i].height = 0;
   116         mNullColorbufferCache[i].buffer = NULL;
   117     }
   118 }
   120 Renderer9::~Renderer9()
   121 {
   122     releaseDeviceResources();
   124     if (mDevice)
   125     {
   126         // If the device is lost, reset it first to prevent leaving the driver in an unstable state
   127         if (testDeviceLost(false))
   128         {
   129             resetDevice();
   130         }
   132         mDevice->Release();
   133         mDevice = NULL;
   134     }
   136     if (mDeviceEx)
   137     {
   138         mDeviceEx->Release();
   139         mDeviceEx = NULL;
   140     }
   142     if (mD3d9)
   143     {
   144         mD3d9->Release();
   145         mD3d9 = NULL;
   146     }
   148     if (mDeviceWindow)
   149     {
   150         DestroyWindow(mDeviceWindow);
   151         mDeviceWindow = NULL;
   152     }
   154     if (mD3d9Ex)
   155     {
   156         mD3d9Ex->Release();
   157         mD3d9Ex = NULL;
   158     }
   160     if (mD3d9Module)
   161     {
   162         mD3d9Module = NULL;
   163     }
   165     while (!mMultiSampleSupport.empty())
   166     {
   167         delete [] mMultiSampleSupport.begin()->second;
   168         mMultiSampleSupport.erase(mMultiSampleSupport.begin());
   169     }
   170 }
   172 Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
   173 {
   174     ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
   175     return static_cast<rx::Renderer9*>(renderer);
   176 }
   178 EGLint Renderer9::initialize()
   179 {
   180     if (!initializeCompiler())
   181     {
   182         return EGL_NOT_INITIALIZED;
   183     }
   185     if (mSoftwareDevice)
   186     {
   187         mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
   188     }
   189     else
   190     {
   191         mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
   192     }
   194     if (mD3d9Module == NULL)
   195     {
   196         ERR("No D3D9 module found - aborting!\n");
   197         return EGL_NOT_INITIALIZED;
   198     }
   200     typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
   201     Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
   203     // Use Direct3D9Ex if available. Among other things, this version is less
   204     // inclined to report a lost context, for example when the user switches
   205     // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
   206     if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
   207     {
   208         ASSERT(mD3d9Ex);
   209         mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
   210         ASSERT(mD3d9);
   211     }
   212     else
   213     {
   214         mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
   215     }
   217     if (!mD3d9)
   218     {
   219         ERR("Could not create D3D9 device - aborting!\n");
   220         return EGL_NOT_INITIALIZED;
   221     }
   223     if (mDc != NULL)
   224     {
   225     //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
   226     }
   228     HRESULT result;
   230     // Give up on getting device caps after about one second.
   231     for (int i = 0; i < 10; ++i)
   232     {
   233         result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
   234         if (SUCCEEDED(result))
   235         {
   236             break;
   237         }
   238         else if (result == D3DERR_NOTAVAILABLE)
   239         {
   240             Sleep(100);   // Give the driver some time to initialize/recover
   241         }
   242         else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
   243         {
   244             ERR("failed to get device caps (0x%x)\n", result);
   245             return EGL_NOT_INITIALIZED;
   246         }
   247     }
   249     if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
   250     {
   251         ERR("Renderer does not support PS 2.0. aborting!\n");
   252         return EGL_NOT_INITIALIZED;
   253     }
   255     // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
   256     // This is required by Texture2D::convertToRenderTarget.
   257     if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
   258     {
   259         ERR("Renderer does not support stretctrect from textures!\n");
   260         return EGL_NOT_INITIALIZED;
   261     }
   263     mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
   265     // ATI cards on XP have problems with non-power-of-two textures.
   266     mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
   267         !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
   268         !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
   269         !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
   271     // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
   272     mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
   274     mMinSwapInterval = 4;
   275     mMaxSwapInterval = 0;
   277     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
   278     {
   279         mMinSwapInterval = std::min(mMinSwapInterval, 0);
   280         mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
   281     }
   282     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
   283     {
   284         mMinSwapInterval = std::min(mMinSwapInterval, 1);
   285         mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
   286     }
   287     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
   288     {
   289         mMinSwapInterval = std::min(mMinSwapInterval, 2);
   290         mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
   291     }
   292     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
   293     {
   294         mMinSwapInterval = std::min(mMinSwapInterval, 3);
   295         mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
   296     }
   297     if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
   298     {
   299         mMinSwapInterval = std::min(mMinSwapInterval, 4);
   300         mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
   301     }
   303     int max = 0;
   304     for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
   305     {
   306         bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
   307         getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
   308         mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
   310         for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
   311         {
   312             if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
   313             {
   314                 max = j;
   315             }
   316         }
   317     }
   319     for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
   320     {
   321         if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
   322             continue;
   324         bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
   325         getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
   326         mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
   328         for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
   329         {
   330             if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
   331             {
   332                 max = j;
   333             }
   334         }
   335     }
   337     mMaxSupportedSamples = max;
   339     static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
   340     static const TCHAR className[] = TEXT("STATIC");
   342     mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
   344     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
   345     DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
   347     result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
   348     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
   349     {
   350         return EGL_BAD_ALLOC;
   351     }
   353     if (FAILED(result))
   354     {
   355         result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
   357         if (FAILED(result))
   358         {
   359             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
   360             return EGL_BAD_ALLOC;
   361         }
   362     }
   364     if (mD3d9Ex)
   365     {
   366         result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
   367         ASSERT(SUCCEEDED(result));
   368     }
   370     mVertexShaderCache.initialize(mDevice);
   371     mPixelShaderCache.initialize(mDevice);
   373     // Check occlusion query support
   374     IDirect3DQuery9 *occlusionQuery = NULL;
   375     if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
   376     {
   377         occlusionQuery->Release();
   378         mOcclusionQuerySupport = true;
   379     }
   380     else
   381     {
   382         mOcclusionQuerySupport = false;
   383     }
   385     // Check event query support
   386     IDirect3DQuery9 *eventQuery = NULL;
   387     if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
   388     {
   389         eventQuery->Release();
   390         mEventQuerySupport = true;
   391     }
   392     else
   393     {
   394         mEventQuerySupport = false;
   395     }
   397     D3DDISPLAYMODE currentDisplayMode;
   398     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
   400     // Check vertex texture support
   401     // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
   402     // We test this using D3D9 by checking support for the R16F format.
   403     mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
   404                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   405                                                                D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
   407     // Check depth texture support
   408     // we use INTZ for depth textures in Direct3D9
   409     // we also want NULL texture support to ensure the we can make depth-only FBOs
   410     // see http://aras-p.info/texts/D3D9GPUHacks.html
   411     mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   412                                                               D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
   413                            SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
   414                                                               D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
   416     // Check 32 bit floating point texture support
   417     mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   418                                                                D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   419                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   420                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   422     mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   423                                                                D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   424                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   425                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   427     if (!mFloat32FilterSupport && !mFloat32RenderSupport)
   428     {
   429         mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   430                                                                     D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
   431                                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   432                                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
   433     }
   434     else
   435     {
   436         mFloat32TextureSupport = true;
   437     }
   439     // Check 16 bit floating point texture support
   440     mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   441                                                                D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   442                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
   443                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   445     mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   446                                                                D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   447                             SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
   448                                                                D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   450     if (!mFloat16FilterSupport && !mFloat16RenderSupport)
   451     {
   452         mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   453                                                                     D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
   454                                  SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
   455                                                                     D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
   456     }
   457     else
   458     {
   459         mFloat16TextureSupport = true;
   460     }
   462     // Check DXT texture support
   463     mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
   464     mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
   465     mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
   467     // Check luminance[alpha] texture support
   468     mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
   469     mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
   471     initializeDevice();
   473     return EGL_SUCCESS;
   474 }
   476 // do any one-time device initialization
   477 // NOTE: this is also needed after a device lost/reset
   478 // to reset the scene status and ensure the default states are reset.
   479 void Renderer9::initializeDevice()
   480 {
   481     // Permanent non-default states
   482     mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
   483     mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
   485     if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
   486     {
   487         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
   488     }
   489     else
   490     {
   491         mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000);   // 1.0f
   492     }
   494     markAllStateDirty();
   496     mSceneStarted = false;
   498     ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
   499     mBlit = new Blit(this);
   500     mVertexDataManager = new rx::VertexDataManager(this);
   501     mIndexDataManager = new rx::IndexDataManager(this);
   502 }
   504 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
   505 {
   506     D3DPRESENT_PARAMETERS presentParameters = {0};
   508     // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
   509     presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
   510     presentParameters.BackBufferCount = 1;
   511     presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
   512     presentParameters.BackBufferWidth = 1;
   513     presentParameters.BackBufferHeight = 1;
   514     presentParameters.EnableAutoDepthStencil = FALSE;
   515     presentParameters.Flags = 0;
   516     presentParameters.hDeviceWindow = mDeviceWindow;
   517     presentParameters.MultiSampleQuality = 0;
   518     presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
   519     presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
   520     presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
   521     presentParameters.Windowed = TRUE;
   523     return presentParameters;
   524 }
   526 int Renderer9::generateConfigs(ConfigDesc **configDescList)
   527 {
   528     D3DDISPLAYMODE currentDisplayMode;
   529     mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
   531     unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
   532     unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
   533     (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
   534     int numConfigs = 0;
   536     for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
   537     {
   538         D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
   540         HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
   542         if (SUCCEEDED(result))
   543         {
   544             for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
   545             {
   546                 D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
   547                 HRESULT result = D3D_OK;
   549                 if(depthStencilFormat != D3DFMT_UNKNOWN)
   550                 {
   551                     result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
   552                 }
   554                 if (SUCCEEDED(result))
   555                 {
   556                     if(depthStencilFormat != D3DFMT_UNKNOWN)
   557                     {
   558                         result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
   559                     }
   561                     if (SUCCEEDED(result))
   562                     {
   563                         ConfigDesc newConfig;
   564                         newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
   565                         newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
   566                         newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
   567                         newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
   569                         (*configDescList)[numConfigs++] = newConfig;
   570                     }
   571                 }
   572             }
   573         }
   574     }
   576     return numConfigs;
   577 }
   579 void Renderer9::deleteConfigs(ConfigDesc *configDescList)
   580 {
   581     delete [] (configDescList);
   582 }
   584 void Renderer9::startScene()
   585 {
   586     if (!mSceneStarted)
   587     {
   588         long result = mDevice->BeginScene();
   589         if (SUCCEEDED(result)) {
   590             // This is defensive checking against the device being
   591             // lost at unexpected times.
   592             mSceneStarted = true;
   593         }
   594     }
   595 }
   597 void Renderer9::endScene()
   598 {
   599     if (mSceneStarted)
   600     {
   601         // EndScene can fail if the device was lost, for example due
   602         // to a TDR during a draw call.
   603         mDevice->EndScene();
   604         mSceneStarted = false;
   605     }
   606 }
   608 void Renderer9::sync(bool block)
   609 {
   610     HRESULT result;
   612     IDirect3DQuery9* query = allocateEventQuery();
   613     if (!query)
   614     {
   615         return;
   616     }
   618     result = query->Issue(D3DISSUE_END);
   619     ASSERT(SUCCEEDED(result));
   621     do
   622     {
   623         result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
   625         if(block && result == S_FALSE)
   626         {
   627             // Keep polling, but allow other threads to do something useful first
   628             Sleep(0);
   629             // explicitly check for device loss
   630             // some drivers seem to return S_FALSE even if the device is lost
   631             // instead of D3DERR_DEVICELOST like they should
   632             if (testDeviceLost(false))
   633             {
   634                 result = D3DERR_DEVICELOST;
   635             }
   636         }
   637     }
   638     while(block && result == S_FALSE);
   640     freeEventQuery(query);
   642     if (d3d9::isDeviceLostError(result))
   643     {
   644         notifyDeviceLost();
   645     }
   646 }
   648 SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
   649 {
   650     return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
   651 }
   653 IDirect3DQuery9* Renderer9::allocateEventQuery()
   654 {
   655     IDirect3DQuery9 *query = NULL;
   657     if (mEventQueryPool.empty())
   658     {
   659         HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
   660         ASSERT(SUCCEEDED(result));
   661     }
   662     else
   663     {
   664         query = mEventQueryPool.back();
   665         mEventQueryPool.pop_back();
   666     }
   668     return query;
   669 }
   671 void Renderer9::freeEventQuery(IDirect3DQuery9* query)
   672 {
   673     if (mEventQueryPool.size() > 1000)
   674     {
   675         query->Release();
   676     }
   677     else
   678     {
   679         mEventQueryPool.push_back(query);
   680     }
   681 }
   683 IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
   684 {
   685     return mVertexShaderCache.create(function, length);
   686 }
   688 IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
   689 {
   690     return mPixelShaderCache.create(function, length);
   691 }
   693 HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
   694 {
   695     D3DPOOL Pool = getBufferPool(Usage);
   696     return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
   697 }
   699 VertexBuffer *Renderer9::createVertexBuffer()
   700 {
   701     return new VertexBuffer9(this);
   702 }
   704 HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
   705 {
   706     D3DPOOL Pool = getBufferPool(Usage);
   707     return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
   708 }
   710 IndexBuffer *Renderer9::createIndexBuffer()
   711 {
   712     return new IndexBuffer9(this);
   713 }
   715 BufferStorage *Renderer9::createBufferStorage()
   716 {
   717     return new BufferStorage9();
   718 }
   720 QueryImpl *Renderer9::createQuery(GLenum type)
   721 {
   722     return new Query9(this, type);
   723 }
   725 FenceImpl *Renderer9::createFence()
   726 {
   727     return new Fence9(this);
   728 }
   730 void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
   731 {
   732     bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
   733     gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
   735     if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
   736     {
   737         int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   738         int d3dSampler = index + d3dSamplerOffset;
   740         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
   741         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
   743         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
   744         D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
   745         gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
   746         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
   747         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
   748         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
   749         if (mSupportsTextureFilterAnisotropy)
   750         {
   751             mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
   752         }
   753     }
   755     forceSetSamplers[index] = false;
   756     appliedSamplers[index] = samplerState;
   757 }
   759 void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
   760 {
   761     int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
   762     int d3dSampler = index + d3dSamplerOffset;
   763     IDirect3DBaseTexture9 *d3dTexture = NULL;
   764     unsigned int serial = 0;
   765     bool forceSetTexture = false;
   767     unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
   769     if (texture)
   770     {
   771         TextureStorageInterface *texStorage = texture->getNativeTexture();
   772         if (texStorage)
   773         {
   774             TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
   775             d3dTexture = storage9->getBaseTexture();
   776         }
   777         // If we get NULL back from getBaseTexture here, something went wrong
   778         // in the texture class and we're unexpectedly missing the d3d texture
   779         ASSERT(d3dTexture != NULL);
   781         serial = texture->getTextureSerial();
   782         forceSetTexture = texture->hasDirtyImages();
   783     }
   785     if (forceSetTexture || appliedSerials[index] != serial)
   786     {
   787         mDevice->SetTexture(d3dSampler, d3dTexture);
   788     }
   790     appliedSerials[index] = serial;
   791 }
   793 void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
   794 {
   795     bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
   797     if (rasterStateChanged)
   798     {
   799         // Set the cull mode
   800         if (rasterState.cullFace)
   801         {
   802             mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
   803         }
   804         else
   805         {
   806             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   807         }
   809         if (rasterState.polygonOffsetFill)
   810         {
   811             if (mCurDepthSize > 0)
   812             {
   813                 mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
   815                 float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
   816                 mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
   817             }
   818         }
   819         else
   820         {
   821             mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
   822             mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
   823         }
   825         mCurRasterState = rasterState;
   826     }
   828     mForceSetRasterState = false;
   829 }
   831 void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
   832 {
   833     bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
   834     bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
   835     bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
   837     if (blendStateChanged || blendColorChanged)
   838     {
   839         if (blendState.blend)
   840         {
   841             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   843             if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
   844                 blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
   845             {
   846                 mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
   847             }
   848             else
   849             {
   850                 mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
   851                                                                          gl::unorm<8>(blendColor.alpha),
   852                                                                          gl::unorm<8>(blendColor.alpha),
   853                                                                          gl::unorm<8>(blendColor.alpha)));
   854             }
   856             mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
   857             mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
   858             mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
   860             if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
   861                 blendState.destBlendRGB != blendState.destBlendAlpha ||
   862                 blendState.blendEquationRGB != blendState.blendEquationAlpha)
   863             {
   864                 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   866                 mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
   867                 mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
   868                 mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
   869             }
   870             else
   871             {
   872                 mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
   873             }
   874         }
   875         else
   876         {
   877             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   878         }
   880         if (blendState.sampleAlphaToCoverage)
   881         {
   882             FIXME("Sample alpha to coverage is unimplemented.");
   883         }
   885         // Set the color mask
   886         bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
   887         // Apparently some ATI cards have a bug where a draw with a zero color
   888         // write mask can cause later draws to have incorrect results. Instead,
   889         // set a nonzero color write mask but modify the blend state so that no
   890         // drawing is done.
   891         // http://code.google.com/p/angleproject/issues/detail?id=169
   893         DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
   894                                                     blendState.colorMaskBlue, blendState.colorMaskAlpha);
   895         if (colorMask == 0 && !zeroColorMaskAllowed)
   896         {
   897             // Enable green channel, but set blending so nothing will be drawn.
   898             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
   899             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   901             mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
   902             mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
   903             mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
   904         }
   905         else
   906         {
   907             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
   908         }
   910         mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
   912         mCurBlendState = blendState;
   913         mCurBlendColor = blendColor;
   914     }
   916     if (sampleMaskChanged)
   917     {
   918         // Set the multisample mask
   919         mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
   920         mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
   922         mCurSampleMask = sampleMask;
   923     }
   925     mForceSetBlendState = false;
   926 }
   928 void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
   929                                      int stencilBackRef, bool frontFaceCCW)
   930 {
   931     bool depthStencilStateChanged = mForceSetDepthStencilState ||
   932                                     memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
   933     bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
   934                              stencilBackRef != mCurStencilBackRef;
   935     bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
   937     if (depthStencilStateChanged)
   938     {
   939         if (depthStencilState.depthTest)
   940         {
   941             mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
   942             mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
   943         }
   944         else
   945         {
   946             mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
   947         }
   949         mCurDepthStencilState = depthStencilState;
   950     }
   952     if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
   953     {
   954         if (depthStencilState.stencilTest && mCurStencilSize > 0)
   955         {
   956             mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
   957             mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
   959             // FIXME: Unsupported by D3D9
   960             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
   961             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
   962             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
   963             if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
   964                 stencilRef != stencilBackRef ||
   965                 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
   966             {
   967                 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
   968                 return gl::error(GL_INVALID_OPERATION);
   969             }
   971             // get the maximum size of the stencil ref
   972             unsigned int maxStencil = (1 << mCurStencilSize) - 1;
   974             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
   975                                     depthStencilState.stencilWritemask);
   976             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   977                                     gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
   979             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
   980                                     (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
   981             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
   982                                     depthStencilState.stencilMask);
   984             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
   985                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
   986             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
   987                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
   988             mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
   989                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
   991             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
   992                                     depthStencilState.stencilBackWritemask);
   993             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   994                                     gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
   996             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
   997                                     (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
   998             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
   999                                     depthStencilState.stencilBackMask);
  1001             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
  1002                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
  1003             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
  1004                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
  1005             mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
  1006                                     gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
  1008         else
  1010             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1013         mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
  1015         mCurStencilRef = stencilRef;
  1016         mCurStencilBackRef = stencilBackRef;
  1017         mCurFrontFaceCCW = frontFaceCCW;
  1020     mForceSetDepthStencilState = false;
  1023 void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
  1025     bool scissorChanged = mForceSetScissor ||
  1026                           memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
  1027                           enabled != mScissorEnabled;
  1029     if (scissorChanged)
  1031         if (enabled)
  1033             RECT rect;
  1034             rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
  1035             rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
  1036             rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
  1037             rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
  1038             mDevice->SetScissorRect(&rect);
  1041         mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
  1043         mScissorEnabled = enabled;
  1044         mCurScissor = scissor;
  1047     mForceSetScissor = false;
  1050 bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
  1051                             bool ignoreViewport)
  1053     gl::Rectangle actualViewport = viewport;
  1054     float actualZNear = gl::clamp01(zNear);
  1055     float actualZFar = gl::clamp01(zFar);
  1056     if (ignoreViewport)
  1058         actualViewport.x = 0;
  1059         actualViewport.y = 0;
  1060         actualViewport.width = mRenderTargetDesc.width;
  1061         actualViewport.height = mRenderTargetDesc.height;
  1062         actualZNear = 0.0f;
  1063         actualZFar = 1.0f;
  1066     D3DVIEWPORT9 dxViewport;
  1067     dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
  1068     dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
  1069     dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
  1070     dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
  1071     dxViewport.MinZ = actualZNear;
  1072     dxViewport.MaxZ = actualZFar;
  1074     if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
  1076         return false;   // Nothing to render
  1079     bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
  1080                            actualZNear != mCurNear || actualZFar != mCurFar;
  1081     if (viewportChanged)
  1083         mDevice->SetViewport(&dxViewport);
  1085         mCurViewport = actualViewport;
  1086         mCurNear = actualZNear;
  1087         mCurFar = actualZFar;
  1089         dx_VertexConstants vc = {0};
  1090         dx_PixelConstants pc = {0};
  1092         vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
  1093         vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
  1094         vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
  1095         vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
  1097         pc.viewCoords[0] = actualViewport.width  * 0.5f;
  1098         pc.viewCoords[1] = actualViewport.height * 0.5f;
  1099         pc.viewCoords[2] = actualViewport.x + (actualViewport.width  * 0.5f);
  1100         pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
  1102         pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
  1103         pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
  1104         pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);;
  1106         vc.depthRange[0] = actualZNear;
  1107         vc.depthRange[1] = actualZFar;
  1108         vc.depthRange[2] = actualZFar - actualZNear;
  1110         pc.depthRange[0] = actualZNear;
  1111         pc.depthRange[1] = actualZFar;
  1112         pc.depthRange[2] = actualZFar - actualZNear;
  1114         if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
  1116             mVertexConstants = vc;
  1117             mDxUniformsDirty = true;
  1120         if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
  1122             mPixelConstants = pc;
  1123             mDxUniformsDirty = true;
  1127     mForceSetViewport = false;
  1128     return true;
  1131 bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
  1133     switch (mode)
  1135       case GL_POINTS:
  1136         mPrimitiveType = D3DPT_POINTLIST;
  1137         mPrimitiveCount = count;
  1138         break;
  1139       case GL_LINES:
  1140         mPrimitiveType = D3DPT_LINELIST;
  1141         mPrimitiveCount = count / 2;
  1142         break;
  1143       case GL_LINE_LOOP:
  1144         mPrimitiveType = D3DPT_LINESTRIP;
  1145         mPrimitiveCount = count - 1;   // D3D doesn't support line loops, so we draw the last line separately
  1146         break;
  1147       case GL_LINE_STRIP:
  1148         mPrimitiveType = D3DPT_LINESTRIP;
  1149         mPrimitiveCount = count - 1;
  1150         break;
  1151       case GL_TRIANGLES:
  1152         mPrimitiveType = D3DPT_TRIANGLELIST;
  1153         mPrimitiveCount = count / 3;
  1154         break;
  1155       case GL_TRIANGLE_STRIP:
  1156         mPrimitiveType = D3DPT_TRIANGLESTRIP;
  1157         mPrimitiveCount = count - 2;
  1158         break;
  1159       case GL_TRIANGLE_FAN:
  1160         mPrimitiveType = D3DPT_TRIANGLEFAN;
  1161         mPrimitiveCount = count - 2;
  1162         break;
  1163       default:
  1164         return gl::error(GL_INVALID_ENUM, false);
  1167     return mPrimitiveCount > 0;
  1171 gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
  1173     if (!depthbuffer)
  1175         ERR("Unexpected null depthbuffer for depth-only FBO.");
  1176         return NULL;
  1179     GLsizei width  = depthbuffer->getWidth();
  1180     GLsizei height = depthbuffer->getHeight();
  1182     // search cached nullcolorbuffers
  1183     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  1185         if (mNullColorbufferCache[i].buffer != NULL &&
  1186             mNullColorbufferCache[i].width == width &&
  1187             mNullColorbufferCache[i].height == height)
  1189             mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
  1190             return mNullColorbufferCache[i].buffer;
  1194     gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
  1196     // add nullbuffer to the cache
  1197     NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
  1198     for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  1200         if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
  1202             oldest = &mNullColorbufferCache[i];
  1206     delete oldest->buffer;
  1207     oldest->buffer = nullbuffer;
  1208     oldest->lruCount = ++mMaxNullColorbufferLRU;
  1209     oldest->width = width;
  1210     oldest->height = height;
  1212     return nullbuffer;
  1215 bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
  1217     // if there is no color attachment we must synthesize a NULL colorattachment
  1218     // to keep the D3D runtime happy.  This should only be possible if depth texturing.
  1219     gl::Renderbuffer *renderbufferObject = NULL;
  1220     if (framebuffer->getColorbufferType(0) != GL_NONE)
  1222         renderbufferObject = framebuffer->getColorbuffer(0);
  1224     else
  1226         renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
  1228     if (!renderbufferObject)
  1230         ERR("unable to locate renderbuffer for FBO.");
  1231         return false;
  1234     bool renderTargetChanged = false;
  1235     unsigned int renderTargetSerial = renderbufferObject->getSerial();
  1236     if (renderTargetSerial != mAppliedRenderTargetSerial)
  1238         // Apply the render target on the device
  1239         IDirect3DSurface9 *renderTargetSurface = NULL;
  1241         RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
  1242         if (renderTarget)
  1244             renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
  1247         if (!renderTargetSurface)
  1249             ERR("render target pointer unexpectedly null.");
  1250             return false;   // Context must be lost
  1253         mDevice->SetRenderTarget(0, renderTargetSurface);
  1254         renderTargetSurface->Release();
  1256         mAppliedRenderTargetSerial = renderTargetSerial;
  1257         renderTargetChanged = true;
  1260     gl::Renderbuffer *depthStencil = NULL;
  1261     unsigned int depthbufferSerial = 0;
  1262     unsigned int stencilbufferSerial = 0;
  1263     if (framebuffer->getDepthbufferType() != GL_NONE)
  1265         depthStencil = framebuffer->getDepthbuffer();
  1266         if (!depthStencil)
  1268             ERR("Depth stencil pointer unexpectedly null.");
  1269             return false;
  1272         depthbufferSerial = depthStencil->getSerial();
  1274     else if (framebuffer->getStencilbufferType() != GL_NONE)
  1276         depthStencil = framebuffer->getStencilbuffer();
  1277         if (!depthStencil)
  1279             ERR("Depth stencil pointer unexpectedly null.");
  1280             return false;
  1283         stencilbufferSerial = depthStencil->getSerial();
  1286     if (depthbufferSerial != mAppliedDepthbufferSerial ||
  1287         stencilbufferSerial != mAppliedStencilbufferSerial ||
  1288         !mDepthStencilInitialized)
  1290         unsigned int depthSize = 0;
  1291         unsigned int stencilSize = 0;
  1293         // Apply the depth stencil on the device
  1294         if (depthStencil)
  1296             IDirect3DSurface9 *depthStencilSurface = NULL;
  1297             RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
  1299             if (depthStencilRenderTarget)
  1301                 depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
  1304             if (!depthStencilSurface)
  1306                 ERR("depth stencil pointer unexpectedly null.");
  1307                 return false;   // Context must be lost
  1310             mDevice->SetDepthStencilSurface(depthStencilSurface);
  1311             depthStencilSurface->Release();
  1313             depthSize = depthStencil->getDepthSize();
  1314             stencilSize = depthStencil->getStencilSize();
  1316         else
  1318             mDevice->SetDepthStencilSurface(NULL);
  1321         if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
  1323             mCurDepthSize = depthSize;
  1324             mForceSetRasterState = true;
  1327         if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
  1329             mCurStencilSize = stencilSize;
  1330             mForceSetDepthStencilState = true;
  1333         mAppliedDepthbufferSerial = depthbufferSerial;
  1334         mAppliedStencilbufferSerial = stencilbufferSerial;
  1335         mDepthStencilInitialized = true;
  1338     if (renderTargetChanged || !mRenderTargetDescInitialized)
  1340         mForceSetScissor = true;
  1341         mForceSetViewport = true;
  1343         mRenderTargetDesc.width = renderbufferObject->getWidth();
  1344         mRenderTargetDesc.height = renderbufferObject->getHeight();
  1345         mRenderTargetDesc.format = renderbufferObject->getActualFormat();
  1346         mRenderTargetDescInitialized = true;
  1349     return true;
  1352 GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
  1354     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
  1355     GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
  1356     if (err != GL_NO_ERROR)
  1358         return err;
  1361     return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
  1364 // Applies the indices and element array bindings to the Direct3D 9 device
  1365 GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
  1367     GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
  1369     if (err == GL_NO_ERROR)
  1371         // Directly binding the storage buffer is not supported for d3d9
  1372         ASSERT(indexInfo->storage == NULL);
  1374         if (indexInfo->serial != mAppliedIBSerial)
  1376             IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
  1378             mDevice->SetIndices(indexBuffer->getBuffer());
  1379             mAppliedIBSerial = indexInfo->serial;
  1383     return err;
  1386 void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
  1388     startScene();
  1390     if (mode == GL_LINE_LOOP)
  1392         drawLineLoop(count, GL_NONE, NULL, 0, NULL);
  1394     else if (instances > 0)
  1396         StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
  1397         if (countingIB)
  1399             if (mAppliedIBSerial != countingIB->getSerial())
  1401                 IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
  1403                 mDevice->SetIndices(indexBuffer->getBuffer());
  1404                 mAppliedIBSerial = countingIB->getSerial();
  1407             for (int i = 0; i < mRepeatDraw; i++)
  1409                 mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
  1412         else
  1414             ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
  1415             return gl::error(GL_OUT_OF_MEMORY);
  1418     else   // Regular case
  1420         mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
  1424 void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
  1426     startScene();
  1428     if (mode == GL_POINTS)
  1430         drawIndexedPoints(count, type, indices, elementArrayBuffer);
  1432     else if (mode == GL_LINE_LOOP)
  1434         drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
  1436     else
  1438         for (int i = 0; i < mRepeatDraw; i++)
  1440             GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
  1441             mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
  1446 void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
  1448     // Get the raw indices for an indexed draw
  1449     if (type != GL_NONE && elementArrayBuffer)
  1451         gl::Buffer *indexBuffer = elementArrayBuffer;
  1452         BufferStorage *storage = indexBuffer->getStorage();
  1453         intptr_t offset = reinterpret_cast<intptr_t>(indices);
  1454         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
  1457     unsigned int startIndex = 0;
  1459     if (get32BitIndexSupport())
  1461         if (!mLineLoopIB)
  1463             mLineLoopIB = new StreamingIndexBufferInterface(this);
  1464             if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
  1466                 delete mLineLoopIB;
  1467                 mLineLoopIB = NULL;
  1469                 ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
  1470                 return gl::error(GL_OUT_OF_MEMORY);
  1474         if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
  1476             ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
  1477             return gl::error(GL_OUT_OF_MEMORY);
  1480         // Checked by Renderer9::applyPrimitiveType
  1481         ASSERT(count >= 0);
  1483         const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
  1484         if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
  1486             ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
  1487             return gl::error(GL_OUT_OF_MEMORY);
  1490         void* mappedMemory = NULL;
  1491         unsigned int offset = 0;
  1492         if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
  1494             ERR("Could not map index buffer for GL_LINE_LOOP.");
  1495             return gl::error(GL_OUT_OF_MEMORY);
  1498         startIndex = static_cast<unsigned int>(offset) / 4;
  1499         unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
  1501         switch (type)
  1503           case GL_NONE:   // Non-indexed draw
  1504             for (int i = 0; i < count; i++)
  1506                 data[i] = i;
  1508             data[count] = 0;
  1509             break;
  1510           case GL_UNSIGNED_BYTE:
  1511             for (int i = 0; i < count; i++)
  1513                 data[i] = static_cast<const GLubyte*>(indices)[i];
  1515             data[count] = static_cast<const GLubyte*>(indices)[0];
  1516             break;
  1517           case GL_UNSIGNED_SHORT:
  1518             for (int i = 0; i < count; i++)
  1520                 data[i] = static_cast<const GLushort*>(indices)[i];
  1522             data[count] = static_cast<const GLushort*>(indices)[0];
  1523             break;
  1524           case GL_UNSIGNED_INT:
  1525             for (int i = 0; i < count; i++)
  1527                 data[i] = static_cast<const GLuint*>(indices)[i];
  1529             data[count] = static_cast<const GLuint*>(indices)[0];
  1530             break;
  1531           default: UNREACHABLE();
  1534         if (!mLineLoopIB->unmapBuffer())
  1536             ERR("Could not unmap index buffer for GL_LINE_LOOP.");
  1537             return gl::error(GL_OUT_OF_MEMORY);
  1540     else
  1542         if (!mLineLoopIB)
  1544             mLineLoopIB = new StreamingIndexBufferInterface(this);
  1545             if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
  1547                 delete mLineLoopIB;
  1548                 mLineLoopIB = NULL;
  1550                 ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
  1551                 return gl::error(GL_OUT_OF_MEMORY);
  1555         // Checked by Renderer9::applyPrimitiveType
  1556         ASSERT(count >= 0);
  1558         if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
  1560             ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
  1561             return gl::error(GL_OUT_OF_MEMORY);
  1564         const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
  1565         if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
  1567             ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
  1568             return gl::error(GL_OUT_OF_MEMORY);
  1571         void* mappedMemory = NULL;
  1572         unsigned int offset;
  1573         if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
  1575             ERR("Could not map index buffer for GL_LINE_LOOP.");
  1576             return gl::error(GL_OUT_OF_MEMORY);
  1579         startIndex = static_cast<unsigned int>(offset) / 2;
  1580         unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
  1582         switch (type)
  1584           case GL_NONE:   // Non-indexed draw
  1585             for (int i = 0; i < count; i++)
  1587                 data[i] = i;
  1589             data[count] = 0;
  1590             break;
  1591           case GL_UNSIGNED_BYTE:
  1592             for (int i = 0; i < count; i++)
  1594                 data[i] = static_cast<const GLubyte*>(indices)[i];
  1596             data[count] = static_cast<const GLubyte*>(indices)[0];
  1597             break;
  1598           case GL_UNSIGNED_SHORT:
  1599             for (int i = 0; i < count; i++)
  1601                 data[i] = static_cast<const GLushort*>(indices)[i];
  1603             data[count] = static_cast<const GLushort*>(indices)[0];
  1604             break;
  1605           case GL_UNSIGNED_INT:
  1606             for (int i = 0; i < count; i++)
  1608                 data[i] = static_cast<const GLuint*>(indices)[i];
  1610             data[count] = static_cast<const GLuint*>(indices)[0];
  1611             break;
  1612           default: UNREACHABLE();
  1615         if (!mLineLoopIB->unmapBuffer())
  1617             ERR("Could not unmap index buffer for GL_LINE_LOOP.");
  1618             return gl::error(GL_OUT_OF_MEMORY);
  1622     if (mAppliedIBSerial != mLineLoopIB->getSerial())
  1624         IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
  1626         mDevice->SetIndices(indexBuffer->getBuffer());
  1627         mAppliedIBSerial = mLineLoopIB->getSerial();
  1630     mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
  1633 template <typename T>
  1634 static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices)
  1636     for (int i = 0; i < count; i++)
  1638         unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]);
  1639         device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
  1643 void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer)
  1645     // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
  1646     // for each individual point. This call is not expected to happen often.
  1648     if (elementArrayBuffer)
  1650         BufferStorage *storage = elementArrayBuffer->getStorage();
  1651         intptr_t offset = reinterpret_cast<intptr_t>(indices);
  1652         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
  1655     switch (type)
  1657         case GL_UNSIGNED_BYTE:  drawPoints<GLubyte>(mDevice, count, indices);  break;
  1658         case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices); break;
  1659         case GL_UNSIGNED_INT:   drawPoints<GLuint>(mDevice, count, indices);   break;
  1660         default: UNREACHABLE();
  1664 void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
  1666     unsigned int programBinarySerial = programBinary->getSerial();
  1667     if (programBinarySerial != mAppliedProgramBinarySerial)
  1669         ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
  1670         ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
  1672         IDirect3DVertexShader9 *vertexShader = NULL;
  1673         if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
  1675         IDirect3DPixelShader9 *pixelShader = NULL;
  1676         if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
  1678         mDevice->SetPixelShader(pixelShader);
  1679         mDevice->SetVertexShader(vertexShader);
  1680         programBinary->dirtyAllUniforms();
  1681         mDxUniformsDirty = true;
  1683         mAppliedProgramBinarySerial = programBinarySerial;
  1687 void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
  1689     for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
  1691         gl::Uniform *targetUniform = *ub;
  1693         if (targetUniform->dirty)
  1695             GLfloat *f = (GLfloat*)targetUniform->data;
  1696             GLint *i = (GLint*)targetUniform->data;
  1698             switch (targetUniform->type)
  1700               case GL_SAMPLER_2D:
  1701               case GL_SAMPLER_CUBE:
  1702                 break;
  1703               case GL_BOOL:
  1704               case GL_BOOL_VEC2:
  1705               case GL_BOOL_VEC3:
  1706               case GL_BOOL_VEC4:
  1707                 applyUniformnbv(targetUniform, i);
  1708                 break;
  1709               case GL_FLOAT:
  1710               case GL_FLOAT_VEC2:
  1711               case GL_FLOAT_VEC3:
  1712               case GL_FLOAT_VEC4:
  1713               case GL_FLOAT_MAT2:
  1714               case GL_FLOAT_MAT3:
  1715               case GL_FLOAT_MAT4:
  1716                 applyUniformnfv(targetUniform, f);
  1717                 break;
  1718               case GL_INT:
  1719               case GL_INT_VEC2:
  1720               case GL_INT_VEC3:
  1721               case GL_INT_VEC4:
  1722                 applyUniformniv(targetUniform, i);
  1723                 break;
  1724               default:
  1725                 UNREACHABLE();
  1728             targetUniform->dirty = false;
  1732     // Driver uniforms
  1733     if (mDxUniformsDirty)
  1735         mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
  1736         mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
  1737         mDxUniformsDirty = false;
  1741 void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
  1743     if (targetUniform->psRegisterIndex >= 0)
  1745         mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
  1748     if (targetUniform->vsRegisterIndex >= 0)
  1750         mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
  1754 void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
  1756     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
  1757     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
  1759     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
  1761         vector[i][0] = (GLfloat)v[4 * i + 0];
  1762         vector[i][1] = (GLfloat)v[4 * i + 1];
  1763         vector[i][2] = (GLfloat)v[4 * i + 2];
  1764         vector[i][3] = (GLfloat)v[4 * i + 3];
  1767     applyUniformnfv(targetUniform, (GLfloat*)vector);
  1770 void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
  1772     ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
  1773     GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
  1775     for (unsigned int i = 0; i < targetUniform->registerCount; i++)
  1777         vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
  1778         vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
  1779         vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
  1780         vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
  1783     applyUniformnfv(targetUniform, (GLfloat*)vector);
  1786 void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
  1788     D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
  1789                                    gl::unorm<8>(clearParams.colorClearValue.red),
  1790                                    gl::unorm<8>(clearParams.colorClearValue.green),
  1791                                    gl::unorm<8>(clearParams.colorClearValue.blue));
  1792     float depth = gl::clamp01(clearParams.depthClearValue);
  1793     int stencil = clearParams.stencilClearValue & 0x000000FF;
  1795     unsigned int stencilUnmasked = 0x0;
  1796     if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
  1798         unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
  1799         stencilUnmasked = (0x1 << stencilSize) - 1;
  1802     bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
  1804     const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
  1805                                         (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
  1806     const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
  1807                                       !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
  1808                                         clearParams.colorMaskBlue && alphaUnmasked);
  1810     if (needMaskedColorClear || needMaskedStencilClear)
  1812         // State which is altered in all paths from this point to the clear call is saved.
  1813         // State which is altered in only some paths will be flagged dirty in the case that
  1814         //  that path is taken.
  1815         HRESULT hr;
  1816         if (mMaskedClearSavedState == NULL)
  1818             hr = mDevice->BeginStateBlock();
  1819             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
  1821             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  1822             mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  1823             mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  1824             mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1825             mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  1826             mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  1827             mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1828             mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
  1829             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
  1830             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1831             mDevice->SetPixelShader(NULL);
  1832             mDevice->SetVertexShader(NULL);
  1833             mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
  1834             mDevice->SetStreamSource(0, NULL, 0, 0);
  1835             mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
  1836             mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1837             mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  1838             mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1839             mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  1840             mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
  1841             mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
  1843             for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
  1845                 mDevice->SetStreamSourceFreq(i, 1);
  1848             hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
  1849             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
  1852         ASSERT(mMaskedClearSavedState != NULL);
  1854         if (mMaskedClearSavedState != NULL)
  1856             hr = mMaskedClearSavedState->Capture();
  1857             ASSERT(SUCCEEDED(hr));
  1860         mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
  1861         mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  1862         mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
  1863         mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1864         mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  1865         mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  1866         mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1867         mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
  1869         if (clearParams.mask & GL_COLOR_BUFFER_BIT)
  1871             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
  1872                                     gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
  1873                                                               clearParams.colorMaskGreen,
  1874                                                               clearParams.colorMaskBlue,
  1875                                                               clearParams.colorMaskAlpha));
  1877         else
  1879             mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
  1882         if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
  1884             mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
  1885             mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
  1886             mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
  1887             mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
  1888             mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
  1889             mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
  1890             mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
  1891             mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
  1893         else
  1895             mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1898         mDevice->SetPixelShader(NULL);
  1899         mDevice->SetVertexShader(NULL);
  1900         mDevice->SetFVF(D3DFVF_XYZRHW);
  1901         mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
  1902         mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  1903         mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
  1904         mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  1905         mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
  1906         mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
  1907         mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
  1909         for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
  1911             mDevice->SetStreamSourceFreq(i, 1);
  1914         float quad[4][4];   // A quadrilateral covering the target, aligned to match the edges
  1915         quad[0][0] = -0.5f;
  1916         quad[0][1] = mRenderTargetDesc.height - 0.5f;
  1917         quad[0][2] = 0.0f;
  1918         quad[0][3] = 1.0f;
  1920         quad[1][0] = mRenderTargetDesc.width - 0.5f;
  1921         quad[1][1] = mRenderTargetDesc.height - 0.5f;
  1922         quad[1][2] = 0.0f;
  1923         quad[1][3] = 1.0f;
  1925         quad[2][0] = -0.5f;
  1926         quad[2][1] = -0.5f;
  1927         quad[2][2] = 0.0f;
  1928         quad[2][3] = 1.0f;
  1930         quad[3][0] = mRenderTargetDesc.width - 0.5f;
  1931         quad[3][1] = -0.5f;
  1932         quad[3][2] = 0.0f;
  1933         quad[3][3] = 1.0f;
  1935         startScene();
  1936         mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
  1938         if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
  1940             mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  1941             mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  1942             mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
  1945         if (mMaskedClearSavedState != NULL)
  1947             mMaskedClearSavedState->Apply();
  1950     else if (clearParams.mask)
  1952         DWORD dxClearFlags = 0;
  1953         if (clearParams.mask & GL_COLOR_BUFFER_BIT)
  1955             dxClearFlags |= D3DCLEAR_TARGET;
  1957         if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
  1959             dxClearFlags |= D3DCLEAR_ZBUFFER;
  1961         if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
  1963             dxClearFlags |= D3DCLEAR_STENCIL;
  1966         mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
  1970 void Renderer9::markAllStateDirty()
  1972     mAppliedRenderTargetSerial = 0;
  1973     mAppliedDepthbufferSerial = 0;
  1974     mAppliedStencilbufferSerial = 0;
  1975     mDepthStencilInitialized = false;
  1976     mRenderTargetDescInitialized = false;
  1978     mForceSetDepthStencilState = true;
  1979     mForceSetRasterState = true;
  1980     mForceSetScissor = true;
  1981     mForceSetViewport = true;
  1982     mForceSetBlendState = true;
  1984     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
  1986         mForceSetVertexSamplerStates[i] = true;
  1987         mCurVertexTextureSerials[i] = 0;
  1989     for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
  1991         mForceSetPixelSamplerStates[i] = true;
  1992         mCurPixelTextureSerials[i] = 0;
  1995     mAppliedIBSerial = 0;
  1996     mAppliedProgramBinarySerial = 0;
  1997     mDxUniformsDirty = true;
  1999     mVertexDeclarationCache.markStateDirty();
  2002 void Renderer9::releaseDeviceResources()
  2004     while (!mEventQueryPool.empty())
  2006         mEventQueryPool.back()->Release();
  2007         mEventQueryPool.pop_back();
  2010     if (mMaskedClearSavedState)
  2012         mMaskedClearSavedState->Release();
  2013         mMaskedClearSavedState = NULL;
  2016     mVertexShaderCache.clear();
  2017     mPixelShaderCache.clear();
  2019     delete mBlit;
  2020     mBlit = NULL;
  2022     delete mVertexDataManager;
  2023     mVertexDataManager = NULL;
  2025     delete mIndexDataManager;
  2026     mIndexDataManager = NULL;
  2028     delete mLineLoopIB;
  2029     mLineLoopIB = NULL;
  2031     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
  2033         delete mNullColorbufferCache[i].buffer;
  2034         mNullColorbufferCache[i].buffer = NULL;
  2040 void Renderer9::notifyDeviceLost()
  2042     mDeviceLost = true;
  2043     mDisplay->notifyDeviceLost();
  2046 bool Renderer9::isDeviceLost()
  2048     return mDeviceLost;
  2051 // set notify to true to broadcast a message to all contexts of the device loss
  2052 bool Renderer9::testDeviceLost(bool notify)
  2054     HRESULT status = S_OK;
  2056     if (mDeviceEx)
  2058         status = mDeviceEx->CheckDeviceState(NULL);
  2060     else if (mDevice)
  2062         status = mDevice->TestCooperativeLevel();
  2064     else
  2066         // No device yet, so no reset required
  2069     bool isLost = FAILED(status) || d3d9::isDeviceLostError(status);
  2071     if (isLost)
  2073         // ensure we note the device loss --
  2074         // we'll probably get this done again by notifyDeviceLost
  2075         // but best to remember it!
  2076         // Note that we don't want to clear the device loss status here
  2077         // -- this needs to be done by resetDevice
  2078         mDeviceLost = true;
  2079         if (notify)
  2081             notifyDeviceLost();
  2085     return isLost;
  2088 bool Renderer9::testDeviceResettable()
  2090     HRESULT status = D3D_OK;
  2092     if (mDeviceEx)
  2094         status = mDeviceEx->CheckDeviceState(NULL);
  2096     else if (mDevice)
  2098         status = mDevice->TestCooperativeLevel();
  2101     // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
  2102     // DEVICEREMOVED indicates the device has been stopped and must be recreated
  2103     switch (status)
  2105       case D3DERR_DEVICENOTRESET:
  2106       case D3DERR_DEVICEHUNG:
  2107         return true;
  2108       case D3DERR_DEVICELOST:
  2109         return (mDeviceEx != NULL);
  2110       case D3DERR_DEVICEREMOVED:
  2111         UNIMPLEMENTED();
  2112         return false;
  2113       default:
  2114         return false;
  2118 bool Renderer9::resetDevice()
  2120     releaseDeviceResources();
  2122     D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
  2124     HRESULT result = D3D_OK;
  2125     bool lost = testDeviceLost(false);
  2126     int attempts = 3;
  2128     while (lost && attempts > 0)
  2130         if (mDeviceEx)
  2132             Sleep(500);   // Give the graphics driver some CPU time
  2133             result = mDeviceEx->ResetEx(&presentParameters, NULL);
  2135         else
  2137             result = mDevice->TestCooperativeLevel();
  2138             while (result == D3DERR_DEVICELOST)
  2140                 Sleep(100);   // Give the graphics driver some CPU time
  2141                 result = mDevice->TestCooperativeLevel();
  2144             if (result == D3DERR_DEVICENOTRESET)
  2146                 result = mDevice->Reset(&presentParameters);
  2150         lost = testDeviceLost(false);
  2151         attempts --;
  2154     if (FAILED(result))
  2156         ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
  2157         return false;
  2160     // reset device defaults
  2161     initializeDevice();
  2162     mDeviceLost = false;
  2164     return true;
  2167 DWORD Renderer9::getAdapterVendor() const
  2169     return mAdapterIdentifier.VendorId;
  2172 std::string Renderer9::getRendererDescription() const
  2174     std::ostringstream rendererString;
  2176     rendererString << mAdapterIdentifier.Description;
  2177     if (getShareHandleSupport())
  2179         rendererString << " Direct3D9Ex";
  2181     else
  2183         rendererString << " Direct3D9";
  2186     rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
  2187     rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
  2189     return rendererString.str();
  2192 GUID Renderer9::getAdapterIdentifier() const
  2194     return mAdapterIdentifier.DeviceIdentifier;
  2197 void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
  2199     for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
  2201         HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
  2202                                                            TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
  2204         multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
  2208 bool Renderer9::getBGRATextureSupport() const
  2210     // DirectX 9 always supports BGRA
  2211     return true;
  2214 bool Renderer9::getDXT1TextureSupport()
  2216     return mDXT1TextureSupport;
  2219 bool Renderer9::getDXT3TextureSupport()
  2221     return mDXT3TextureSupport;
  2224 bool Renderer9::getDXT5TextureSupport()
  2226     return mDXT5TextureSupport;
  2229 bool Renderer9::getDepthTextureSupport() const
  2231     return mDepthTextureSupport;
  2234 bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
  2236     *filtering = mFloat32FilterSupport;
  2237     *renderable = mFloat32RenderSupport;
  2238     return mFloat32TextureSupport;
  2241 bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
  2243     *filtering = mFloat16FilterSupport;
  2244     *renderable = mFloat16RenderSupport;
  2245     return mFloat16TextureSupport;
  2248 bool Renderer9::getLuminanceTextureSupport()
  2250     return mLuminanceTextureSupport;
  2253 bool Renderer9::getLuminanceAlphaTextureSupport()
  2255     return mLuminanceAlphaTextureSupport;
  2258 bool Renderer9::getTextureFilterAnisotropySupport() const
  2260     return mSupportsTextureFilterAnisotropy;
  2263 float Renderer9::getTextureMaxAnisotropy() const
  2265     if (mSupportsTextureFilterAnisotropy)
  2267         return static_cast<float>(mDeviceCaps.MaxAnisotropy);
  2269     return 1.0f;
  2272 bool Renderer9::getEventQuerySupport()
  2274     return mEventQuerySupport;
  2277 unsigned int Renderer9::getMaxVertexTextureImageUnits() const
  2279     META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
  2280     return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
  2283 unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
  2285     return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
  2288 unsigned int Renderer9::getReservedVertexUniformVectors() const
  2290     return 2;   // dx_ViewAdjust and dx_DepthRange.
  2293 unsigned int Renderer9::getReservedFragmentUniformVectors() const
  2295     return 3;   // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
  2298 unsigned int Renderer9::getMaxVertexUniformVectors() const
  2300     return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
  2303 unsigned int Renderer9::getMaxFragmentUniformVectors() const
  2305     const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
  2307     return maxPixelConstantVectors - getReservedFragmentUniformVectors();
  2310 unsigned int Renderer9::getMaxVaryingVectors() const
  2312     return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
  2315 bool Renderer9::getNonPower2TextureSupport() const
  2317     return mSupportsNonPower2Textures;
  2320 bool Renderer9::getOcclusionQuerySupport() const
  2322     return mOcclusionQuerySupport;
  2325 bool Renderer9::getInstancingSupport() const
  2327     return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
  2330 bool Renderer9::getShareHandleSupport() const
  2332     // PIX doesn't seem to support using share handles, so disable them.
  2333     return (mD3d9Ex != NULL) && !gl::perfActive();
  2336 bool Renderer9::getDerivativeInstructionSupport() const
  2338     return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
  2341 bool Renderer9::getPostSubBufferSupport() const
  2343     return true;
  2346 int Renderer9::getMajorShaderModel() const
  2348     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
  2351 float Renderer9::getMaxPointSize() const
  2353     // Point size clamped at 1.0f for SM2
  2354     return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
  2357 int Renderer9::getMaxViewportDimension() const
  2359     int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
  2360                                        (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
  2361     return maxTextureDimension;
  2364 int Renderer9::getMaxTextureWidth() const
  2366     return (int)mDeviceCaps.MaxTextureWidth;
  2369 int Renderer9::getMaxTextureHeight() const
  2371     return (int)mDeviceCaps.MaxTextureHeight;
  2374 bool Renderer9::get32BitIndexSupport() const
  2376     return mDeviceCaps.MaxVertexIndex >= (1 << 16);
  2379 DWORD Renderer9::getCapsDeclTypes() const
  2381     return mDeviceCaps.DeclTypes;
  2384 int Renderer9::getMinSwapInterval() const
  2386     return mMinSwapInterval;
  2389 int Renderer9::getMaxSwapInterval() const
  2391     return mMaxSwapInterval;
  2394 int Renderer9::getMaxSupportedSamples() const
  2396     return mMaxSupportedSamples;
  2399 int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
  2401     if (requested == 0)
  2403         return requested;
  2406     std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
  2407     if (itr == mMultiSampleSupport.end())
  2409         if (format == D3DFMT_UNKNOWN)
  2410             return 0;
  2411         return -1;
  2414     for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
  2416         if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
  2418             return i;
  2422     return -1;
  2425 unsigned int Renderer9::getMaxRenderTargets() const
  2427     // we do not support MRT in d3d9
  2428     return 1;
  2431 D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
  2433     switch (internalformat)
  2435       case GL_DEPTH_COMPONENT16:
  2436       case GL_DEPTH_COMPONENT32_OES:
  2437       case GL_DEPTH24_STENCIL8_OES:
  2438         return D3DFMT_INTZ;
  2439       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  2440       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  2441         return D3DFMT_DXT1;
  2442       case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
  2443         return D3DFMT_DXT3;
  2444       case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
  2445         return D3DFMT_DXT5;
  2446       case GL_RGBA32F_EXT:
  2447       case GL_RGB32F_EXT:
  2448       case GL_ALPHA32F_EXT:
  2449       case GL_LUMINANCE32F_EXT:
  2450       case GL_LUMINANCE_ALPHA32F_EXT:
  2451         return D3DFMT_A32B32G32R32F;
  2452       case GL_RGBA16F_EXT:
  2453       case GL_RGB16F_EXT:
  2454       case GL_ALPHA16F_EXT:
  2455       case GL_LUMINANCE16F_EXT:
  2456       case GL_LUMINANCE_ALPHA16F_EXT:
  2457         return D3DFMT_A16B16G16R16F;
  2458       case GL_LUMINANCE8_EXT:
  2459         if (getLuminanceTextureSupport())
  2461             return D3DFMT_L8;
  2463         break;
  2464       case GL_LUMINANCE8_ALPHA8_EXT:
  2465         if (getLuminanceAlphaTextureSupport())
  2467             return D3DFMT_A8L8;
  2469         break;
  2470       case GL_RGB8_OES:
  2471       case GL_RGB565:
  2472         return D3DFMT_X8R8G8B8;
  2475     return D3DFMT_A8R8G8B8;
  2478 bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
  2480     bool result = false;
  2482     if (source && dest)
  2484         TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
  2485         TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
  2487         int levels = source9->levelCount();
  2488         for (int i = 0; i < levels; ++i)
  2490             IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
  2491             IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
  2493             result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
  2495             if (srcSurf) srcSurf->Release();
  2496             if (dstSurf) dstSurf->Release();
  2498             if (!result)
  2499                 return false;
  2503     return result;
  2506 bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
  2508     bool result = false;
  2510     if (source && dest)
  2512         TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
  2513         TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
  2514         int levels = source9->levelCount();
  2515         for (int f = 0; f < 6; f++)
  2517             for (int i = 0; i < levels; i++)
  2519                 IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
  2520                 IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
  2522                 result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
  2524                 if (srcSurf) srcSurf->Release();
  2525                 if (dstSurf) dstSurf->Release();
  2527                 if (!result)
  2528                     return false;
  2533     return result;
  2536 D3DPOOL Renderer9::getBufferPool(DWORD usage) const
  2538     if (mD3d9Ex != NULL)
  2540         return D3DPOOL_DEFAULT;
  2542     else
  2544         if (!(usage & D3DUSAGE_DYNAMIC))
  2546             return D3DPOOL_MANAGED;
  2550     return D3DPOOL_DEFAULT;
  2553 bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
  2554                           GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
  2556     RECT rect;
  2557     rect.left = sourceRect.x;
  2558     rect.top = sourceRect.y;
  2559     rect.right = sourceRect.x + sourceRect.width;
  2560     rect.bottom = sourceRect.y + sourceRect.height;
  2562     return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
  2565 bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
  2566                           GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
  2568     RECT rect;
  2569     rect.left = sourceRect.x;
  2570     rect.top = sourceRect.y;
  2571     rect.right = sourceRect.x + sourceRect.width;
  2572     rect.bottom = sourceRect.y + sourceRect.height;
  2574     return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
  2577 bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
  2578                          bool blitRenderTarget, bool blitDepthStencil)
  2580     endScene();
  2582     if (blitRenderTarget)
  2584         gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
  2585         gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
  2586         RenderTarget9 *readRenderTarget = NULL;
  2587         RenderTarget9 *drawRenderTarget = NULL;
  2588         IDirect3DSurface9* readSurface = NULL;
  2589         IDirect3DSurface9* drawSurface = NULL;
  2591         if (readBuffer)
  2593             readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
  2595         if (drawBuffer)
  2597             drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
  2600         if (readRenderTarget)
  2602             readSurface = readRenderTarget->getSurface();
  2604         if (drawRenderTarget)
  2606             drawSurface = drawRenderTarget->getSurface();
  2609         if (!readSurface || !drawSurface)
  2611             ERR("Failed to retrieve the render target.");
  2612             return gl::error(GL_OUT_OF_MEMORY, false);
  2615         RECT srcRect;
  2616         srcRect.left = readRect.x;
  2617         srcRect.right = readRect.x + readRect.width;
  2618         srcRect.top = readRect.y;
  2619         srcRect.bottom = readRect.y + readRect.height;
  2621         RECT dstRect;
  2622         dstRect.left = drawRect.x;
  2623         dstRect.right = drawRect.x + drawRect.width;
  2624         dstRect.top = drawRect.y;
  2625         dstRect.bottom = drawRect.y + drawRect.height;
  2627         HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
  2629         readSurface->Release();
  2630         drawSurface->Release();
  2632         if (FAILED(result))
  2634             ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
  2635             return false;
  2639     if (blitDepthStencil)
  2641         gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
  2642         gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
  2643         RenderTarget9 *readDepthStencil = NULL;
  2644         RenderTarget9 *drawDepthStencil = NULL;
  2645         IDirect3DSurface9* readSurface = NULL;
  2646         IDirect3DSurface9* drawSurface = NULL;
  2648         if (readBuffer)
  2650             readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
  2652         if (drawBuffer)
  2654             drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
  2657         if (readDepthStencil)
  2659             readSurface = readDepthStencil->getSurface();
  2661         if (drawDepthStencil)
  2663             drawSurface = drawDepthStencil->getSurface();
  2666         if (!readSurface || !drawSurface)
  2668             ERR("Failed to retrieve the render target.");
  2669             return gl::error(GL_OUT_OF_MEMORY, false);
  2672         HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
  2674         readSurface->Release();
  2675         drawSurface->Release();
  2677         if (FAILED(result))
  2679             ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
  2680             return false;
  2684     return true;
  2687 void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, 
  2688                            GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
  2690     RenderTarget9 *renderTarget = NULL;
  2691     IDirect3DSurface9 *surface = NULL;
  2692     gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
  2694     if (colorbuffer)
  2696         renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
  2699     if (renderTarget)
  2701         surface = renderTarget->getSurface();
  2704     if (!surface)
  2706         // context must be lost
  2707         return;
  2710     D3DSURFACE_DESC desc;
  2711     surface->GetDesc(&desc);
  2713     if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
  2715         UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
  2716         surface->Release();
  2717         return gl::error(GL_OUT_OF_MEMORY);
  2720     HRESULT result;
  2721     IDirect3DSurface9 *systemSurface = NULL;
  2722     bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
  2723                           x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
  2724                           desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
  2725     if (directToPixels)
  2727         // Use the pixels ptr as a shared handle to write directly into client's memory
  2728         result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  2729                                                       D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
  2730         if (FAILED(result))
  2732             // Try again without the shared handle
  2733             directToPixels = false;
  2737     if (!directToPixels)
  2739         result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  2740                                                       D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
  2741         if (FAILED(result))
  2743             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
  2744             surface->Release();
  2745             return gl::error(GL_OUT_OF_MEMORY);
  2749     result = mDevice->GetRenderTargetData(surface, systemSurface);
  2750     surface->Release();
  2751     surface = NULL;
  2753     if (FAILED(result))
  2755         systemSurface->Release();
  2757         // It turns out that D3D will sometimes produce more error
  2758         // codes than those documented.
  2759         if (d3d9::isDeviceLostError(result))
  2761             notifyDeviceLost();
  2762             return gl::error(GL_OUT_OF_MEMORY);
  2764         else
  2766             UNREACHABLE();
  2767             return;
  2772     if (directToPixels)
  2774         systemSurface->Release();
  2775         return;
  2778     RECT rect;
  2779     rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
  2780     rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
  2781     rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
  2782     rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
  2784     D3DLOCKED_RECT lock;
  2785     result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
  2787     if (FAILED(result))
  2789         UNREACHABLE();
  2790         systemSurface->Release();
  2792         return;   // No sensible error to generate
  2795     unsigned char *dest = (unsigned char*)pixels;
  2796     unsigned short *dest16 = (unsigned short*)pixels;
  2798     unsigned char *source;
  2799     int inputPitch;
  2800     if (packReverseRowOrder)
  2802         source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
  2803         inputPitch = -lock.Pitch;
  2805     else
  2807         source = (unsigned char*)lock.pBits;
  2808         inputPitch = lock.Pitch;
  2811     unsigned int fastPixelSize = 0;
  2813     if (desc.Format == D3DFMT_A8R8G8B8 &&
  2814         format == GL_BGRA_EXT &&
  2815         type == GL_UNSIGNED_BYTE)
  2817         fastPixelSize = 4;
  2819     else if ((desc.Format == D3DFMT_A4R4G4B4 &&
  2820              format == GL_BGRA_EXT &&
  2821              type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
  2822              (desc.Format == D3DFMT_A1R5G5B5 &&
  2823              format == GL_BGRA_EXT &&
  2824              type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
  2826         fastPixelSize = 2;
  2828     else if (desc.Format == D3DFMT_A16B16G16R16F &&
  2829              format == GL_RGBA &&
  2830              type == GL_HALF_FLOAT_OES)
  2832         fastPixelSize = 8;
  2834     else if (desc.Format == D3DFMT_A32B32G32R32F &&
  2835              format == GL_RGBA &&
  2836              type == GL_FLOAT)
  2838         fastPixelSize = 16;
  2841     for (int j = 0; j < rect.bottom - rect.top; j++)
  2843         if (fastPixelSize != 0)
  2845             // Fast path for formats which require no translation:
  2846             // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
  2847             // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
  2848             // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
  2849             // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
  2850             // D3DFMT_A32B32G32R32F to RGBA/FLOAT
  2851             // 
  2852             // Note that buffers with no alpha go through the slow path below.
  2853             memcpy(dest + j * outputPitch,
  2854                    source + j * inputPitch,
  2855                    (rect.right - rect.left) * fastPixelSize);
  2856             continue;
  2858         else if (desc.Format == D3DFMT_A8R8G8B8 &&
  2859                  format == GL_RGBA &&
  2860                  type == GL_UNSIGNED_BYTE)
  2862             // Fast path for swapping red with blue
  2863             for (int i = 0; i < rect.right - rect.left; i++)
  2865                 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  2866                 *(unsigned int*)(dest + 4 * i + j * outputPitch) =
  2867                     (argb & 0xFF00FF00) |       // Keep alpha and green
  2868                     (argb & 0x00FF0000) >> 16 | // Move red to blue
  2869                     (argb & 0x000000FF) << 16;  // Move blue to red
  2871             continue;
  2874         for (int i = 0; i < rect.right - rect.left; i++)
  2876             float r;
  2877             float g;
  2878             float b;
  2879             float a;
  2881             switch (desc.Format)
  2883               case D3DFMT_R5G6B5:
  2885                     unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
  2887                     a = 1.0f;
  2888                     b = (rgb & 0x001F) * (1.0f / 0x001F);
  2889                     g = (rgb & 0x07E0) * (1.0f / 0x07E0);
  2890                     r = (rgb & 0xF800) * (1.0f / 0xF800);
  2892                 break;
  2893               case D3DFMT_A1R5G5B5:
  2895                     unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
  2897                     a = (argb & 0x8000) ? 1.0f : 0.0f;
  2898                     b = (argb & 0x001F) * (1.0f / 0x001F);
  2899                     g = (argb & 0x03E0) * (1.0f / 0x03E0);
  2900                     r = (argb & 0x7C00) * (1.0f / 0x7C00);
  2902                 break;
  2903               case D3DFMT_A8R8G8B8:
  2905                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  2907                     a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
  2908                     b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
  2909                     g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
  2910                     r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
  2912                 break;
  2913               case D3DFMT_X8R8G8B8:
  2915                     unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  2917                     a = 1.0f;
  2918                     b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
  2919                     g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
  2920                     r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
  2922                 break;
  2923               case D3DFMT_A2R10G10B10:
  2925                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
  2927                     a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
  2928                     b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
  2929                     g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
  2930                     r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
  2932                 break;
  2933               case D3DFMT_A32B32G32R32F:
  2935                     // float formats in D3D are stored rgba, rather than the other way round
  2936                     r = *((float*)(source + 16 * i + j * inputPitch) + 0);
  2937                     g = *((float*)(source + 16 * i + j * inputPitch) + 1);
  2938                     b = *((float*)(source + 16 * i + j * inputPitch) + 2);
  2939                     a = *((float*)(source + 16 * i + j * inputPitch) + 3);
  2941                 break;
  2942               case D3DFMT_A16B16G16R16F:
  2944                     // float formats in D3D are stored rgba, rather than the other way round
  2945                     r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
  2946                     g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
  2947                     b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
  2948                     a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
  2950                 break;
  2951               default:
  2952                 UNIMPLEMENTED();   // FIXME
  2953                 UNREACHABLE();
  2954                 return;
  2957             switch (format)
  2959               case GL_RGBA:
  2960                 switch (type)
  2962                   case GL_UNSIGNED_BYTE:
  2963                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
  2964                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  2965                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
  2966                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
  2967                     break;
  2968                   default: UNREACHABLE();
  2970                 break;
  2971               case GL_BGRA_EXT:
  2972                 switch (type)
  2974                   case GL_UNSIGNED_BYTE:
  2975                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
  2976                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  2977                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
  2978                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
  2979                     break;
  2980                   case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
  2981                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
  2982                     // this type is packed as follows:
  2983                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
  2984                     //  --------------------------------------------------------------------------------
  2985                     // |       4th         |        3rd         |        2nd        |   1st component   |
  2986                     //  --------------------------------------------------------------------------------
  2987                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
  2988                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
  2989                         ((unsigned short)(15 * a + 0.5f) << 12)|
  2990                         ((unsigned short)(15 * r + 0.5f) << 8) |
  2991                         ((unsigned short)(15 * g + 0.5f) << 4) |
  2992                         ((unsigned short)(15 * b + 0.5f) << 0);
  2993                     break;
  2994                   case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
  2995                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
  2996                     // this type is packed as follows:
  2997                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
  2998                     //  --------------------------------------------------------------------------------
  2999                     // | 4th |          3rd           |           2nd          |      1st component     |
  3000                     //  --------------------------------------------------------------------------------
  3001                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
  3002                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
  3003                         ((unsigned short)(     a + 0.5f) << 15) |
  3004                         ((unsigned short)(31 * r + 0.5f) << 10) |
  3005                         ((unsigned short)(31 * g + 0.5f) << 5) |
  3006                         ((unsigned short)(31 * b + 0.5f) << 0);
  3007                     break;
  3008                   default: UNREACHABLE();
  3010                 break;
  3011               case GL_RGB:
  3012                 switch (type)
  3014                   case GL_UNSIGNED_SHORT_5_6_5:
  3015                     dest16[i + j * outputPitch / sizeof(unsigned short)] = 
  3016                         ((unsigned short)(31 * b + 0.5f) << 0) |
  3017                         ((unsigned short)(63 * g + 0.5f) << 5) |
  3018                         ((unsigned short)(31 * r + 0.5f) << 11);
  3019                     break;
  3020                   case GL_UNSIGNED_BYTE:
  3021                     dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
  3022                     dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
  3023                     dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
  3024                     break;
  3025                   default: UNREACHABLE();
  3027                 break;
  3028               default: UNREACHABLE();
  3033     systemSurface->UnlockRect();
  3035     systemSurface->Release();
  3038 RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
  3040     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
  3041     IDirect3DSurface9 *surface = NULL;
  3042     if (depth)
  3044         surface = swapChain9->getDepthStencil();
  3046     else
  3048         surface = swapChain9->getRenderTarget();
  3051     RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
  3053     return renderTarget;
  3056 RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
  3058     RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
  3059     return renderTarget;
  3062 ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
  3064     ShaderExecutable9 *executable = NULL;
  3066     switch (type)
  3068       case rx::SHADER_VERTEX:
  3070             IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
  3071             if (vshader)
  3073                 executable = new ShaderExecutable9(function, length, vshader);
  3076         break;
  3077       case rx::SHADER_PIXEL:
  3079             IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
  3080             if (pshader)
  3082                 executable = new ShaderExecutable9(function, length, pshader);
  3085         break;
  3086       default:
  3087         UNREACHABLE();
  3088         break;
  3091     return executable;
  3094 ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type)
  3096     const char *profile = NULL;
  3098     switch (type)
  3100       case rx::SHADER_VERTEX:
  3101         profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
  3102         break;
  3103       case rx::SHADER_PIXEL:
  3104         profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
  3105         break;
  3106       default:
  3107         UNREACHABLE();
  3108         return NULL;
  3111     ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true);
  3112     if (!binary)
  3113         return NULL;
  3115     ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
  3116     binary->Release();
  3118     return executable;
  3121 bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
  3123     return mBlit->boxFilter(source, dest);
  3126 D3DPOOL Renderer9::getTexturePool(DWORD usage) const
  3128     if (mD3d9Ex != NULL)
  3130         return D3DPOOL_DEFAULT;
  3132     else
  3134         if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
  3136             return D3DPOOL_DEFAULT;
  3140     return D3DPOOL_DEFAULT;
  3143 bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
  3145     if (source && dest)
  3147         HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
  3149         if (fromManaged)
  3151             D3DSURFACE_DESC desc;
  3152             source->GetDesc(&desc);
  3154             IDirect3DSurface9 *surf = 0;
  3155             result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
  3157             if (SUCCEEDED(result))
  3159                 Image9::copyLockableSurfaces(surf, source);
  3160                 result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
  3161                 surf->Release();
  3164         else
  3166             endScene();
  3167             result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
  3170         if (FAILED(result))
  3172             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
  3173             return false;
  3177     return true;
  3180 Image *Renderer9::createImage()
  3182     return new Image9();
  3185 void Renderer9::generateMipmap(Image *dest, Image *src)
  3187     Image9 *src9 = Image9::makeImage9(src);
  3188     Image9 *dst9 = Image9::makeImage9(dest);
  3189     Image9::generateMipmap(dst9, src9);
  3192 TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
  3194     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
  3195     return new TextureStorage9_2D(this, swapChain9);
  3198 TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
  3200     return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
  3203 TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
  3205     return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
  3208 bool Renderer9::getLUID(LUID *adapterLuid) const
  3210     adapterLuid->HighPart = 0;
  3211     adapterLuid->LowPart = 0;
  3213     if (mD3d9Ex)
  3215         mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
  3216         return true;
  3219     return false;

mercurial