Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
      9 
     10 #include "libGLESv2/renderer/SwapChain11.h"
     11 
     12 #include "libGLESv2/renderer/renderer11_utils.h"
     13 #include "libGLESv2/renderer/Renderer11.h"
     14 #include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
     15 #include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
     16 
     17 namespace rx
     18 {
     19 
     20 SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
     21                          GLenum backBufferFormat, GLenum depthBufferFormat)
     22     : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
     23 {
     24     mSwapChain = NULL;
     25     mBackBufferTexture = NULL;
     26     mBackBufferRTView = NULL;
     27     mOffscreenTexture = NULL;
     28     mOffscreenRTView = NULL;
     29     mOffscreenSRView = NULL;
     30     mDepthStencilTexture = NULL;
     31     mDepthStencilDSView = NULL;
     32     mQuadVB = NULL;
     33     mPassThroughSampler = NULL;
     34     mPassThroughIL = NULL;
     35     mPassThroughVS = NULL;
     36     mPassThroughPS = NULL;
     37     mWidth = -1;
     38     mHeight = -1;
     39     mSwapInterval = 0;
     40     mAppCreatedShareHandle = mShareHandle != NULL;
     41     mPassThroughResourcesInit = false;
     42 }
     43 
     44 SwapChain11::~SwapChain11()
     45 {
     46     release();
     47 }
     48 
     49 void SwapChain11::release()
     50 {
     51     if (mSwapChain)
     52     {
     53         mSwapChain->Release();
     54         mSwapChain = NULL;
     55     }
     56 
     57     if (mBackBufferTexture)
     58     {
     59         mBackBufferTexture->Release();
     60         mBackBufferTexture = NULL;
     61     }
     62 
     63     if (mBackBufferRTView)
     64     {
     65         mBackBufferRTView->Release();
     66         mBackBufferRTView = NULL;
     67     }
     68 
     69     if (mOffscreenTexture)
     70     {
     71         mOffscreenTexture->Release();
     72         mOffscreenTexture = NULL;
     73     }
     74 
     75     if (mOffscreenRTView)
     76     {
     77         mOffscreenRTView->Release();
     78         mOffscreenRTView = NULL;
     79     }
     80 
     81     if (mOffscreenSRView)
     82     {
     83         mOffscreenSRView->Release();
     84         mOffscreenSRView = NULL;
     85     }
     86 
     87     if (mDepthStencilTexture)
     88     {
     89         mDepthStencilTexture->Release();
     90         mDepthStencilTexture = NULL;
     91     }
     92 
     93     if (mDepthStencilDSView)
     94     {
     95         mDepthStencilDSView->Release();
     96         mDepthStencilDSView = NULL;
     97     }
     98 
     99     if (mQuadVB)
    100     {
    101         mQuadVB->Release();
    102         mQuadVB = NULL;
    103     }
    104 
    105     if (mPassThroughSampler)
    106     {
    107         mPassThroughSampler->Release();
    108         mPassThroughSampler = NULL;
    109     }
    110 
    111     if (mPassThroughIL)
    112     {
    113         mPassThroughIL->Release();
    114         mPassThroughIL = NULL;
    115     }
    116 
    117     if (mPassThroughVS)
    118     {
    119         mPassThroughVS->Release();
    120         mPassThroughVS = NULL;
    121     }
    122 
    123     if (mPassThroughPS)
    124     {
    125         mPassThroughPS->Release();
    126         mPassThroughPS = NULL;
    127     }
    128 
    129     if (!mAppCreatedShareHandle)
    130     {
    131         mShareHandle = NULL;
    132     }
    133 }
    134 
    135 void SwapChain11::releaseOffscreenTexture()
    136 {
    137     if (mOffscreenTexture)
    138     {
    139         mOffscreenTexture->Release();
    140         mOffscreenTexture = NULL;
    141     }
    142 
    143     if (mOffscreenRTView)
    144     {
    145         mOffscreenRTView->Release();
    146         mOffscreenRTView = NULL;
    147     }
    148 
    149     if (mOffscreenSRView)
    150     {
    151         mOffscreenSRView->Release();
    152         mOffscreenSRView = NULL;
    153     }
    154 
    155     if (mDepthStencilTexture)
    156     {
    157         mDepthStencilTexture->Release();
    158         mDepthStencilTexture = NULL;
    159     }
    160 
    161     if (mDepthStencilDSView)
    162     {
    163         mDepthStencilDSView->Release();
    164         mDepthStencilDSView = NULL;
    165     }
    166 }
    167 
    168 EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
    169 {
    170     ID3D11Device *device = mRenderer->getDevice();
    171 
    172     ASSERT(device != NULL);
    173 
    174     // D3D11 does not allow zero size textures
    175     ASSERT(backbufferWidth >= 1);
    176     ASSERT(backbufferHeight >= 1);
    177 
    178     // Preserve the render target content
    179     ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
    180     if (previousOffscreenTexture)
    181     {
    182         previousOffscreenTexture->AddRef();
    183     }
    184     const int previousWidth = mWidth;
    185     const int previousHeight = mHeight;
    186 
    187     releaseOffscreenTexture();
    188 
    189     // If the app passed in a share handle, open the resource
    190     // See EGL_ANGLE_d3d_share_handle_client_buffer
    191     if (mAppCreatedShareHandle)
    192     {
    193         ID3D11Resource *tempResource11;
    194         HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
    195 
    196         if (FAILED(result))
    197         {
    198             ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
    199             release();
    200             return EGL_BAD_PARAMETER;
    201         }
    202 
    203         result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
    204         tempResource11->Release();
    205 
    206         if (FAILED(result))
    207         {
    208             ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
    209             release();
    210             return EGL_BAD_PARAMETER;
    211         }
    212 
    213         // Validate offscreen texture parameters
    214         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
    215         mOffscreenTexture->GetDesc(&offscreenTextureDesc);
    216 
    217         if (offscreenTextureDesc.Width != (UINT)backbufferWidth
    218             || offscreenTextureDesc.Height != (UINT)backbufferHeight
    219             || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
    220             || offscreenTextureDesc.MipLevels != 1
    221             || offscreenTextureDesc.ArraySize != 1)
    222         {
    223             ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
    224             release();
    225             return EGL_BAD_PARAMETER;
    226         }
    227     }
    228     else
    229     {
    230         const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
    231 
    232         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
    233         offscreenTextureDesc.Width = backbufferWidth;
    234         offscreenTextureDesc.Height = backbufferHeight;
    235         offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
    236         offscreenTextureDesc.MipLevels = 1;
    237         offscreenTextureDesc.ArraySize = 1;
    238         offscreenTextureDesc.SampleDesc.Count = 1;
    239         offscreenTextureDesc.SampleDesc.Quality = 0;
    240         offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
    241         offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
    242         offscreenTextureDesc.CPUAccessFlags = 0;
    243         offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
    244 
    245         HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
    246 
    247         if (FAILED(result))
    248         {
    249             ERR("Could not create offscreen texture: %08lX", result);
    250             release();
    251 
    252             if (d3d11::isDeviceLostError(result))
    253             {
    254                 return EGL_CONTEXT_LOST;
    255             }
    256             else
    257             {
    258                 return EGL_BAD_ALLOC;
    259             }
    260         }
    261 
    262         d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
    263 
    264         // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
    265         if (useSharedResource)
    266         {
    267             IDXGIResource *offscreenTextureResource = NULL;
    268             result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
    269 
    270             // Fall back to no share handle on failure
    271             if (FAILED(result))
    272             {
    273                 ERR("Could not query offscreen texture resource: %08lX", result);
    274             }
    275             else
    276             {
    277                 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
    278                 offscreenTextureResource->Release();
    279 
    280                 if (FAILED(result))
    281                 {
    282                     mShareHandle = NULL;
    283                     ERR("Could not get offscreen texture shared handle: %08lX", result);
    284                 }
    285             }
    286         }
    287     }
    288 
    289     HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
    290 
    291     ASSERT(SUCCEEDED(result));
    292     d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
    293 
    294     result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
    295     ASSERT(SUCCEEDED(result));
    296     d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
    297 
    298     if (mDepthBufferFormat != GL_NONE)
    299     {
    300         D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
    301         depthStencilDesc.Width = backbufferWidth;
    302         depthStencilDesc.Height = backbufferHeight;
    303         depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
    304         depthStencilDesc.MipLevels = 1;
    305         depthStencilDesc.ArraySize = 1;
    306         depthStencilDesc.SampleDesc.Count = 1;
    307         depthStencilDesc.SampleDesc.Quality = 0;
    308         depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
    309         depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    310         depthStencilDesc.CPUAccessFlags = 0;
    311         depthStencilDesc.MiscFlags = 0;
    312 
    313         result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
    314         if (FAILED(result))
    315         {
    316             ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
    317             release();
    318 
    319             if (d3d11::isDeviceLostError(result))
    320             {
    321                 return EGL_CONTEXT_LOST;
    322             }
    323             else
    324             {
    325                 return EGL_BAD_ALLOC;
    326             }
    327         }
    328         d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
    329 
    330         result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
    331         ASSERT(SUCCEEDED(result));
    332         d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
    333     }
    334 
    335     mWidth = backbufferWidth;
    336     mHeight = backbufferHeight;
    337 
    338     if (previousOffscreenTexture != NULL)
    339     {
    340         D3D11_BOX sourceBox = {0};
    341         sourceBox.left = 0;
    342         sourceBox.right = std::min(previousWidth, mWidth);
    343         sourceBox.top = std::max(previousHeight - mHeight, 0);
    344         sourceBox.bottom = previousHeight;
    345         sourceBox.front = 0;
    346         sourceBox.back = 1;
    347 
    348         ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    349         const int yoffset = std::max(mHeight - previousHeight, 0);
    350         deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
    351 
    352         previousOffscreenTexture->Release();
    353 
    354         if (mSwapChain)
    355         {
    356             swapRect(0, 0, mWidth, mHeight);
    357         }
    358     }
    359 
    360     return EGL_SUCCESS;
    361 }
    362 
    363 EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
    364 {
    365     ID3D11Device *device = mRenderer->getDevice();
    366 
    367     if (device == NULL)
    368     {
    369         return EGL_BAD_ACCESS;
    370     }
    371 
    372     // Can only call resize if we have already created our swap buffer and resources
    373     ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
    374 
    375     if (mBackBufferTexture)
    376     {
    377         mBackBufferTexture->Release();
    378         mBackBufferTexture = NULL;
    379     }
    380 
    381     if (mBackBufferRTView)
    382     {
    383         mBackBufferRTView->Release();
    384         mBackBufferRTView = NULL;
    385     }
    386 
    387     // Resize swap chain
    388     DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
    389     HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
    390 
    391     if (FAILED(result))
    392     {
    393         ERR("Error resizing swap chain buffers: 0x%08X", result);
    394         release();
    395 
    396         if (d3d11::isDeviceLostError(result))
    397         {
    398             return EGL_CONTEXT_LOST;
    399         }
    400         else
    401         {
    402             return EGL_BAD_ALLOC;
    403         }
    404     }
    405 
    406     result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
    407     ASSERT(SUCCEEDED(result));
    408     if (SUCCEEDED(result))
    409     {
    410         d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
    411     }
    412 
    413     result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
    414     ASSERT(SUCCEEDED(result));
    415     if (SUCCEEDED(result))
    416     {
    417         d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
    418     }
    419 
    420     return resetOffscreenTexture(backbufferWidth, backbufferHeight);
    421 }
    422 
    423 EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
    424 {
    425     ID3D11Device *device = mRenderer->getDevice();
    426 
    427     if (device == NULL)
    428     {
    429         return EGL_BAD_ACCESS;
    430     }
    431 
    432     // Release specific resources to free up memory for the new render target, while the
    433     // old render target still exists for the purpose of preserving its contents.
    434     if (mSwapChain)
    435     {
    436         mSwapChain->Release();
    437         mSwapChain = NULL;
    438     }
    439 
    440     if (mBackBufferTexture)
    441     {
    442         mBackBufferTexture->Release();
    443         mBackBufferTexture = NULL;
    444     }
    445 
    446     if (mBackBufferRTView)
    447     {
    448         mBackBufferRTView->Release();
    449         mBackBufferRTView = NULL;
    450     }
    451 
    452     mSwapInterval = static_cast<unsigned int>(swapInterval);
    453     if (mSwapInterval > 4)
    454     {
    455         // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
    456         return EGL_BAD_PARAMETER;
    457     }
    458 
    459     // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
    460     if (backbufferWidth < 1 || backbufferHeight < 1)
    461     {
    462         releaseOffscreenTexture();
    463         return EGL_SUCCESS;
    464     }
    465 
    466     if (mWindow)
    467     {
    468         IDXGIFactory *factory = mRenderer->getDxgiFactory();
    469 
    470         DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
    471         swapChainDesc.BufferCount = 2;
    472         swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
    473         swapChainDesc.BufferDesc.Width = backbufferWidth;
    474         swapChainDesc.BufferDesc.Height = backbufferHeight;
    475         swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    476         swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    477         swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
    478         swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    479         swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    480         swapChainDesc.Flags = 0;
    481         swapChainDesc.OutputWindow = mWindow;
    482         swapChainDesc.SampleDesc.Count = 1;
    483         swapChainDesc.SampleDesc.Quality = 0;
    484         swapChainDesc.Windowed = TRUE;
    485 
    486         HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
    487 
    488         if (FAILED(result))
    489         {
    490             ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
    491             release();
    492 
    493             if (d3d11::isDeviceLostError(result))
    494             {
    495                 return EGL_CONTEXT_LOST;
    496             }
    497             else
    498             {
    499                 // We cannot create a swap chain for an HWND that is owned by a different process on some versions of
    500                 // windows
    501                 DWORD currentProcessId = GetCurrentProcessId();
    502                 DWORD wndProcessId;
    503                 GetWindowThreadProcessId(mWindow, &wndProcessId);
    504 
    505                 if (currentProcessId != wndProcessId)
    506                 {
    507                     ERR("Could not create swap chain, window owned by different process");
    508                     return EGL_BAD_NATIVE_WINDOW;
    509                 }
    510                 else
    511                 {
    512                     return EGL_BAD_ALLOC;
    513                 }
    514             }
    515         }
    516 
    517         result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
    518         ASSERT(SUCCEEDED(result));
    519         d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
    520 
    521         result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
    522         ASSERT(SUCCEEDED(result));
    523         d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
    524     }
    525 
    526     // If we are resizing the swap chain, we don't wish to recreate all the static resources
    527     if (!mPassThroughResourcesInit)
    528     {
    529         mPassThroughResourcesInit = true;
    530         initPassThroughResources();
    531     }
    532 
    533     return resetOffscreenTexture(backbufferWidth, backbufferHeight);
    534 }
    535 
    536 void SwapChain11::initPassThroughResources()
    537 {
    538     ID3D11Device *device = mRenderer->getDevice();
    539 
    540     ASSERT(device != NULL);
    541 
    542     // Make sure our resources are all not allocated, when we create
    543     ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
    544     ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
    545 
    546     D3D11_BUFFER_DESC vbDesc;
    547     vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
    548     vbDesc.Usage = D3D11_USAGE_DYNAMIC;
    549     vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    550     vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    551     vbDesc.MiscFlags = 0;
    552     vbDesc.StructureByteStride = 0;
    553 
    554     HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
    555     ASSERT(SUCCEEDED(result));
    556     d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
    557 
    558     D3D11_SAMPLER_DESC samplerDesc;
    559     samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
    560     samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    561     samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    562     samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    563     samplerDesc.MipLODBias = 0.0f;
    564     samplerDesc.MaxAnisotropy = 0;
    565     samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    566     samplerDesc.BorderColor[0] = 0.0f;
    567     samplerDesc.BorderColor[1] = 0.0f;
    568     samplerDesc.BorderColor[2] = 0.0f;
    569     samplerDesc.BorderColor[3] = 0.0f;
    570     samplerDesc.MinLOD = 0;
    571     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
    572 
    573     result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
    574     ASSERT(SUCCEEDED(result));
    575     d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
    576 
    577     D3D11_INPUT_ELEMENT_DESC quadLayout[] =
    578     {
    579         { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    580         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    581     };
    582 
    583     result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
    584     ASSERT(SUCCEEDED(result));
    585     d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
    586 
    587     result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
    588     ASSERT(SUCCEEDED(result));
    589     d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
    590 
    591     result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
    592     ASSERT(SUCCEEDED(result));
    593     d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
    594 }
    595 
    596 // parameters should be validated/clamped by caller
    597 EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
    598 {
    599     if (!mSwapChain)
    600     {
    601         return EGL_SUCCESS;
    602     }
    603 
    604     ID3D11Device *device = mRenderer->getDevice();
    605     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    606 
    607     // Set vertices
    608     D3D11_MAPPED_SUBRESOURCE mappedResource;
    609     HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    610     if (FAILED(result))
    611     {
    612         return EGL_BAD_ACCESS;
    613     }
    614 
    615     d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
    616 
    617     // Create a quad in homogeneous coordinates
    618     float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
    619     float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
    620     float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
    621     float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
    622 
    623     float u1 = x / float(mWidth);
    624     float v1 = y / float(mHeight);
    625     float u2 = (x + width) / float(mWidth);
    626     float v2 = (y + height) / float(mHeight);
    627 
    628     d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
    629     d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
    630     d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
    631     d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
    632 
    633     deviceContext->Unmap(mQuadVB, 0);
    634 
    635     static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
    636     static UINT startIdx = 0;
    637     deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
    638 
    639     // Apply state
    640     deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
    641 
    642     static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
    643     deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
    644 
    645     deviceContext->RSSetState(NULL);
    646 
    647     // Apply shaders
    648     deviceContext->IASetInputLayout(mPassThroughIL);
    649     deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    650     deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
    651     deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
    652     deviceContext->GSSetShader(NULL, NULL, 0);
    653 
    654     // Apply render targets
    655     mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
    656 
    657     // Set the viewport
    658     D3D11_VIEWPORT viewport;
    659     viewport.TopLeftX = 0;
    660     viewport.TopLeftY = 0;
    661     viewport.Width = mWidth;
    662     viewport.Height = mHeight;
    663     viewport.MinDepth = 0.0f;
    664     viewport.MaxDepth = 1.0f;
    665     deviceContext->RSSetViewports(1, &viewport);
    666 
    667     // Apply textures
    668     deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
    669     deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
    670 
    671     // Draw
    672     deviceContext->Draw(4, 0);
    673 
    674 #if ANGLE_FORCE_VSYNC_OFF
    675     result = mSwapChain->Present(0, 0);
    676 #else
    677     result = mSwapChain->Present(mSwapInterval, 0);
    678 #endif
    679 
    680     if (result == DXGI_ERROR_DEVICE_REMOVED)
    681     {
    682         HRESULT removedReason = device->GetDeviceRemovedReason();
    683         ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
    684         return EGL_CONTEXT_LOST;
    685     }
    686     else if (result == DXGI_ERROR_DEVICE_RESET)
    687     {
    688         ERR("Present failed: the D3D11 device was reset from a bad command.");
    689         return EGL_CONTEXT_LOST;
    690     }
    691     else if (FAILED(result))
    692     {
    693         ERR("Present failed with error code 0x%08X", result);
    694     }
    695 
    696     // Unbind
    697     static ID3D11ShaderResourceView *const nullSRV = NULL;
    698     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    699 
    700     mRenderer->unapplyRenderTargets();
    701     mRenderer->markAllStateDirty();
    702 
    703     return EGL_SUCCESS;
    704 }
    705 
    706 // Increments refcount on texture.
    707 // caller must Release() the returned texture
    708 ID3D11Texture2D *SwapChain11::getOffscreenTexture()
    709 {
    710     if (mOffscreenTexture)
    711     {
    712         mOffscreenTexture->AddRef();
    713     }
    714 
    715     return mOffscreenTexture;
    716 }
    717 
    718 // Increments refcount on view.
    719 // caller must Release() the returned view
    720 ID3D11RenderTargetView *SwapChain11::getRenderTarget()
    721 {
    722     if (mOffscreenRTView)
    723     {
    724         mOffscreenRTView->AddRef();
    725     }
    726 
    727     return mOffscreenRTView;
    728 }
    729 
    730 // Increments refcount on view.
    731 // caller must Release() the returned view
    732 ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
    733 {
    734     if (mOffscreenSRView)
    735     {
    736         mOffscreenSRView->AddRef();
    737     }
    738 
    739     return mOffscreenSRView;
    740 }
    741 
    742 // Increments refcount on view.
    743 // caller must Release() the returned view
    744 ID3D11DepthStencilView *SwapChain11::getDepthStencil()
    745 {
    746     if (mDepthStencilDSView)
    747     {
    748         mDepthStencilDSView->AddRef();
    749     }
    750 
    751     return mDepthStencilDSView;
    752 }
    753 
    754 ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
    755 {
    756     if (mDepthStencilTexture)
    757     {
    758         mDepthStencilTexture->AddRef();
    759     }
    760 
    761     return mDepthStencilTexture;
    762 }
    763 
    764 SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
    765 {
    766     ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
    767     return static_cast<rx::SwapChain11*>(swapChain);
    768 }
    769 
    770 void SwapChain11::recreate()
    771 {
    772     // possibly should use this method instead of reset
    773 }
    774 
    775 }
    776