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
17namespace rx
18{
19
20SwapChain11::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
44SwapChain11::~SwapChain11()
45{
46    release();
47}
48
49void 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
135void 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
168EGLint 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
279                if (FAILED(result))
280                {
281                    mShareHandle = NULL;
282                    ERR("Could not get offscreen texture shared handle: %08lX", result);
283                }
284            }
285        }
286    }
287
288    HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
289
290    ASSERT(SUCCEEDED(result));
291    d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
292
293    result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
294    ASSERT(SUCCEEDED(result));
295    d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
296
297    if (mDepthBufferFormat != GL_NONE)
298    {
299        D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
300        depthStencilDesc.Width = backbufferWidth;
301        depthStencilDesc.Height = backbufferHeight;
302        depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
303        depthStencilDesc.MipLevels = 1;
304        depthStencilDesc.ArraySize = 1;
305        depthStencilDesc.SampleDesc.Count = 1;
306        depthStencilDesc.SampleDesc.Quality = 0;
307        depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
308        depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
309        depthStencilDesc.CPUAccessFlags = 0;
310        depthStencilDesc.MiscFlags = 0;
311
312        result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
313        if (FAILED(result))
314        {
315            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
316            release();
317
318            if (d3d11::isDeviceLostError(result))
319            {
320                return EGL_CONTEXT_LOST;
321            }
322            else
323            {
324                return EGL_BAD_ALLOC;
325            }
326        }
327        d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
328
329        result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
330        ASSERT(SUCCEEDED(result));
331        d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
332    }
333
334    mWidth = backbufferWidth;
335    mHeight = backbufferHeight;
336
337    if (previousOffscreenTexture != NULL)
338    {
339        D3D11_BOX sourceBox = {0};
340        sourceBox.left = 0;
341        sourceBox.right = std::min(previousWidth, mWidth);
342        sourceBox.top = std::max(previousHeight - mHeight, 0);
343        sourceBox.bottom = previousHeight;
344        sourceBox.front = 0;
345        sourceBox.back = 1;
346
347        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
348        const int yoffset = std::max(mHeight - previousHeight, 0);
349        deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
350
351        previousOffscreenTexture->Release();
352
353        if (mSwapChain)
354        {
355            swapRect(0, 0, mWidth, mHeight);
356        }
357    }
358
359    return EGL_SUCCESS;
360}
361
362EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
363{
364    ID3D11Device *device = mRenderer->getDevice();
365
366    if (device == NULL)
367    {
368        return EGL_BAD_ACCESS;
369    }
370
371    // Can only call resize if we have already created our swap buffer and resources
372    ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
373
374    if (mBackBufferTexture)
375    {
376        mBackBufferTexture->Release();
377        mBackBufferTexture = NULL;
378    }
379
380    if (mBackBufferRTView)
381    {
382        mBackBufferRTView->Release();
383        mBackBufferRTView = NULL;
384    }
385
386    // Resize swap chain
387    DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
388    HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
389
390    if (FAILED(result))
391    {
392        ERR("Error resizing swap chain buffers: 0x%08X", result);
393        release();
394
395        if (d3d11::isDeviceLostError(result))
396        {
397            return EGL_CONTEXT_LOST;
398        }
399        else
400        {
401            return EGL_BAD_ALLOC;
402        }
403    }
404
405    result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
406    ASSERT(SUCCEEDED(result));
407    if (SUCCEEDED(result))
408    {
409        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
410    }
411
412    result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
413    ASSERT(SUCCEEDED(result));
414    if (SUCCEEDED(result))
415    {
416        d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
417    }
418
419    return resetOffscreenTexture(backbufferWidth, backbufferHeight);
420}
421
422EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
423{
424    ID3D11Device *device = mRenderer->getDevice();
425
426    if (device == NULL)
427    {
428        return EGL_BAD_ACCESS;
429    }
430
431    // Release specific resources to free up memory for the new render target, while the
432    // old render target still exists for the purpose of preserving its contents.
433    if (mSwapChain)
434    {
435        mSwapChain->Release();
436        mSwapChain = NULL;
437    }
438
439    if (mBackBufferTexture)
440    {
441        mBackBufferTexture->Release();
442        mBackBufferTexture = NULL;
443    }
444
445    if (mBackBufferRTView)
446    {
447        mBackBufferRTView->Release();
448        mBackBufferRTView = NULL;
449    }
450
451    mSwapInterval = static_cast<unsigned int>(swapInterval);
452    if (mSwapInterval > 4)
453    {
454        // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
455        return EGL_BAD_PARAMETER;
456    }
457
458    // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
459    if (backbufferWidth < 1 || backbufferHeight < 1)
460    {
461        releaseOffscreenTexture();
462        return EGL_SUCCESS;
463    }
464
465    if (mWindow)
466    {
467        // We cannot create a swap chain for an HWND that is owned by a different process
468        DWORD currentProcessId = GetCurrentProcessId();
469        DWORD wndProcessId;
470        GetWindowThreadProcessId(mWindow, &wndProcessId);
471
472        if (currentProcessId != wndProcessId)
473        {
474            ERR("Could not create swap chain, window owned by different process");
475            release();
476            return EGL_BAD_NATIVE_WINDOW;
477        }
478
479        IDXGIFactory *factory = mRenderer->getDxgiFactory();
480
481        DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
482        swapChainDesc.BufferCount = 2;
483        swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
484        swapChainDesc.BufferDesc.Width = backbufferWidth;
485        swapChainDesc.BufferDesc.Height = backbufferHeight;
486        swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
487        swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
488        swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
489        swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
490        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
491        swapChainDesc.Flags = 0;
492        swapChainDesc.OutputWindow = mWindow;
493        swapChainDesc.SampleDesc.Count = 1;
494        swapChainDesc.SampleDesc.Quality = 0;
495        swapChainDesc.Windowed = TRUE;
496
497        HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
498
499        if (FAILED(result))
500        {
501            ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
502            release();
503
504            if (d3d11::isDeviceLostError(result))
505            {
506                return EGL_CONTEXT_LOST;
507            }
508            else
509            {
510                return EGL_BAD_ALLOC;
511            }
512        }
513
514        result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
515        ASSERT(SUCCEEDED(result));
516        d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
517
518        result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
519        ASSERT(SUCCEEDED(result));
520        d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
521    }
522
523    // If we are resizing the swap chain, we don't wish to recreate all the static resources
524    if (!mPassThroughResourcesInit)
525    {
526        mPassThroughResourcesInit = true;
527        initPassThroughResources();
528    }
529
530    return resetOffscreenTexture(backbufferWidth, backbufferHeight);
531}
532
533void SwapChain11::initPassThroughResources()
534{
535    ID3D11Device *device = mRenderer->getDevice();
536
537    ASSERT(device != NULL);
538
539    // Make sure our resources are all not allocated, when we create
540    ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
541    ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
542
543    D3D11_BUFFER_DESC vbDesc;
544    vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
545    vbDesc.Usage = D3D11_USAGE_DYNAMIC;
546    vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
547    vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
548    vbDesc.MiscFlags = 0;
549    vbDesc.StructureByteStride = 0;
550
551    HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
552    ASSERT(SUCCEEDED(result));
553    d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
554
555    D3D11_SAMPLER_DESC samplerDesc;
556    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
557    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
558    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
559    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
560    samplerDesc.MipLODBias = 0.0f;
561    samplerDesc.MaxAnisotropy = 0;
562    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
563    samplerDesc.BorderColor[0] = 0.0f;
564    samplerDesc.BorderColor[1] = 0.0f;
565    samplerDesc.BorderColor[2] = 0.0f;
566    samplerDesc.BorderColor[3] = 0.0f;
567    samplerDesc.MinLOD = 0;
568    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
569
570    result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
571    ASSERT(SUCCEEDED(result));
572    d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
573
574    D3D11_INPUT_ELEMENT_DESC quadLayout[] =
575    {
576        { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
577        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
578    };
579
580    result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
581    ASSERT(SUCCEEDED(result));
582    d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
583
584    result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
585    ASSERT(SUCCEEDED(result));
586    d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
587
588    result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
589    ASSERT(SUCCEEDED(result));
590    d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
591}
592
593// parameters should be validated/clamped by caller
594EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
595{
596    if (!mSwapChain)
597    {
598        return EGL_SUCCESS;
599    }
600
601    ID3D11Device *device = mRenderer->getDevice();
602    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
603
604    // Set vertices
605    D3D11_MAPPED_SUBRESOURCE mappedResource;
606    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
607    if (FAILED(result))
608    {
609        return EGL_BAD_ACCESS;
610    }
611
612    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
613
614    // Create a quad in homogeneous coordinates
615    float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
616    float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
617    float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
618    float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
619
620    float u1 = x / float(mWidth);
621    float v1 = y / float(mHeight);
622    float u2 = (x + width) / float(mWidth);
623    float v2 = (y + height) / float(mHeight);
624
625    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
626    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
627    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
628    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
629
630    deviceContext->Unmap(mQuadVB, 0);
631
632    static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
633    static UINT startIdx = 0;
634    deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
635
636    // Apply state
637    deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
638
639    static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
640    deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
641
642    deviceContext->RSSetState(NULL);
643
644    // Apply shaders
645    deviceContext->IASetInputLayout(mPassThroughIL);
646    deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
647    deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
648    deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
649    deviceContext->GSSetShader(NULL, NULL, 0);
650
651    // Apply render targets
652    mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
653
654    // Set the viewport
655    D3D11_VIEWPORT viewport;
656    viewport.TopLeftX = 0;
657    viewport.TopLeftY = 0;
658    viewport.Width = mWidth;
659    viewport.Height = mHeight;
660    viewport.MinDepth = 0.0f;
661    viewport.MaxDepth = 1.0f;
662    deviceContext->RSSetViewports(1, &viewport);
663
664    // Apply textures
665    deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
666    deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
667
668    // Draw
669    deviceContext->Draw(4, 0);
670    result = mSwapChain->Present(mSwapInterval, 0);
671
672    if (result == DXGI_ERROR_DEVICE_REMOVED)
673    {
674        HRESULT removedReason = device->GetDeviceRemovedReason();
675        ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
676        return EGL_CONTEXT_LOST;
677    }
678    else if (result == DXGI_ERROR_DEVICE_RESET)
679    {
680        ERR("Present failed: the D3D11 device was reset from a bad command.");
681        return EGL_CONTEXT_LOST;
682    }
683    else if (FAILED(result))
684    {
685        ERR("Present failed with error code 0x%08X", result);
686    }
687
688    // Unbind
689    static ID3D11ShaderResourceView *const nullSRV = NULL;
690    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
691
692    mRenderer->unapplyRenderTargets();
693    mRenderer->markAllStateDirty();
694
695    return EGL_SUCCESS;
696}
697
698// Increments refcount on texture.
699// caller must Release() the returned texture
700ID3D11Texture2D *SwapChain11::getOffscreenTexture()
701{
702    if (mOffscreenTexture)
703    {
704        mOffscreenTexture->AddRef();
705    }
706
707    return mOffscreenTexture;
708}
709
710// Increments refcount on view.
711// caller must Release() the returned view
712ID3D11RenderTargetView *SwapChain11::getRenderTarget()
713{
714    if (mOffscreenRTView)
715    {
716        mOffscreenRTView->AddRef();
717    }
718
719    return mOffscreenRTView;
720}
721
722// Increments refcount on view.
723// caller must Release() the returned view
724ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
725{
726    if (mOffscreenSRView)
727    {
728        mOffscreenSRView->AddRef();
729    }
730
731    return mOffscreenSRView;
732}
733
734// Increments refcount on view.
735// caller must Release() the returned view
736ID3D11DepthStencilView *SwapChain11::getDepthStencil()
737{
738    if (mDepthStencilDSView)
739    {
740        mDepthStencilDSView->AddRef();
741    }
742
743    return mDepthStencilDSView;
744}
745
746ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
747{
748    if (mDepthStencilTexture)
749    {
750        mDepthStencilTexture->AddRef();
751    }
752
753    return mDepthStencilTexture;
754}
755
756SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
757{
758    ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
759    return static_cast<rx::SwapChain11*>(swapChain);
760}
761
762void SwapChain11::recreate()
763{
764    // possibly should use this method instead of reset
765}
766
767}
768