blob: e3cd646181da08cf9e744c756d37ae0548f5f112 [file] [log] [blame]
daniel@transgaming.com32fdf822012-11-28 20:53:30 +00001//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
8
9#include "libGLESv2/renderer/SwapChain11.h"
10
11#include "common/debug.h"
12#include "libGLESv2/utilities.h"
13#include "libGLESv2/renderer/renderer11_utils.h"
14#include "libGLESv2/renderer/Renderer11.h"
15#include "libGLESv2/Context.h"
16#include "libGLESv2/main.h"
17
18namespace rx
19{
20
21SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
22 GLenum backBufferFormat, GLenum depthBufferFormat)
23 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
24{
25 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000026 mBackBufferTexture = NULL;
27 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000028 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000029 mOffscreenRTView = NULL;
30 mDepthStencilTexture = NULL;
31 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000032 mWidth = -1;
33 mHeight = -1;
34}
35
36SwapChain11::~SwapChain11()
37{
38 release();
39}
40
41void SwapChain11::release()
42{
43 if (mSwapChain)
44 {
45 mSwapChain->Release();
46 mSwapChain = NULL;
47 }
48
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000049 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000050 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000051 mBackBufferTexture->Release();
52 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000053 }
54
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000055 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000056 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000057 mBackBufferRTView->Release();
58 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000059 }
60
61 if (mOffscreenTexture)
62 {
63 mOffscreenTexture->Release();
64 mOffscreenTexture = NULL;
65 }
66
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000067 if (mOffscreenRTView)
68 {
69 mOffscreenRTView->Release();
70 mOffscreenRTView = NULL;
71 }
72
73 if (mDepthStencilTexture)
74 {
75 mDepthStencilTexture->Release();
76 mDepthStencilTexture = NULL;
77 }
78
79 if (mDepthStencilDSView)
80 {
81 mDepthStencilDSView->Release();
82 mDepthStencilDSView = NULL;
83 }
84
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000085 if (mWindow)
86 mShareHandle = NULL;
87}
88
89EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
90{
91 ID3D11Device *device = mRenderer->getDevice();
92
93 if (device == NULL)
94 {
95 return EGL_BAD_ACCESS;
96 }
97
98 // Release specific resources to free up memory for the new render target, while the
99 // old render target still exists for the purpose of preserving its contents.
100 if (mSwapChain)
101 {
102 mSwapChain->Release();
103 mSwapChain = NULL;
104 }
105
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000106 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000107 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000108 mBackBufferTexture->Release();
109 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000110 }
111
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000112 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000113 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000114 mBackBufferRTView->Release();
115 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000116 }
117
118 if (mOffscreenTexture)
119 {
120 mOffscreenTexture->Release();
121 mOffscreenTexture = NULL;
122 }
123
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000124 if (mOffscreenRTView) // TODO: Preserve the render target content
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000125 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000126 mOffscreenRTView->Release();
127 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000128 }
129
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000130 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000131 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000132 mDepthStencilTexture->Release();
133 mDepthStencilTexture = NULL;
134 }
135
136 if (mDepthStencilDSView)
137 {
138 mDepthStencilDSView->Release();
139 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000140 }
141
142 HANDLE *pShareHandle = NULL;
143 if (!mWindow && mRenderer->getShareHandleSupport())
144 {
145 pShareHandle = &mShareHandle;
146 }
147
148 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
149 offscreenTextureDesc.Width = backbufferWidth;
150 offscreenTextureDesc.Height = backbufferHeight;
151 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
152 offscreenTextureDesc.MipLevels = 1;
153 offscreenTextureDesc.ArraySize = 1;
154 offscreenTextureDesc.SampleDesc.Count = 1;
155 offscreenTextureDesc.SampleDesc.Quality = 0;
156 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
157 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
158 offscreenTextureDesc.CPUAccessFlags = 0;
159 offscreenTextureDesc.MiscFlags = 0; // D3D11_RESOURCE_MISC_SHARED
160
161 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
162
163 if (FAILED(result))
164 {
165 ERR("Could not create offscreen texture: %08lX", result);
166 release();
167
168 if (isDeviceLostError(result))
169 {
170 return EGL_CONTEXT_LOST;
171 }
172 else
173 {
174 return EGL_BAD_ALLOC;
175 }
176 }
177
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000178 result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000179 ASSERT(SUCCEEDED(result));
180
181 if (mWindow)
182 {
183 IDXGIFactory *factory = mRenderer->getDxgiFactory();
184
185 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
186 swapChainDesc.BufferCount = 2;
187 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
daniel@transgaming.com567b9cf2012-11-28 21:04:46 +0000188 swapChainDesc.BufferDesc.Width = backbufferWidth;
189 swapChainDesc.BufferDesc.Height = backbufferHeight;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000190 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
191 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
192 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
193 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
194 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
195 swapChainDesc.Flags = 0;
196 swapChainDesc.OutputWindow = mWindow;
197 swapChainDesc.SampleDesc.Count = 1;
198 swapChainDesc.SampleDesc.Quality = 0;
199 swapChainDesc.Windowed = TRUE;
200
201 result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
202
203 if (FAILED(result))
204 {
205 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
206 release();
207
208 if (isDeviceLostError(result))
209 {
210 return EGL_CONTEXT_LOST;
211 }
212 else
213 {
214 return EGL_BAD_ALLOC;
215 }
216 }
217
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000218 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000219 ASSERT(SUCCEEDED(result));
220
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000221 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000222 ASSERT(SUCCEEDED(result));
223 }
224
225 if (mDepthBufferFormat != GL_NONE)
226 {
227 D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
228 depthStencilDesc.Width = backbufferWidth;
229 depthStencilDesc.Height = backbufferHeight;
230 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
231 depthStencilDesc.MipLevels = 1;
232 depthStencilDesc.ArraySize = 1;
233 depthStencilDesc.SampleDesc.Count = 1;
234 depthStencilDesc.SampleDesc.Quality = 0;
235 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
236 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
237 depthStencilDesc.CPUAccessFlags = 0;
238 depthStencilDesc.MiscFlags = 0;
239
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000240 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000241
242 if (FAILED(result))
243 {
244 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
245 release();
246
247 if (isDeviceLostError(result))
248 {
249 return EGL_CONTEXT_LOST;
250 }
251 else
252 {
253 return EGL_BAD_ALLOC;
254 }
255 }
256
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000257 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000258 ASSERT(SUCCEEDED(result));
259 }
260
261 mWidth = backbufferWidth;
262 mHeight = backbufferHeight;
263
264 return EGL_SUCCESS;
265}
266
267// parameters should be validated/clamped by caller
268EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
269{
270 if (!mSwapChain)
271 {
272 return EGL_SUCCESS;
273 }
274
275 ID3D11Device *device = mRenderer->getDevice();
276
277 // TODO
278 UNIMPLEMENTED();
279
280 return EGL_SUCCESS;
281}
282
283// Increments refcount on view.
284// caller must Release() the returned view
285ID3D11RenderTargetView *SwapChain11::getRenderTarget()
286{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000287 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000288 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000289 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000290 }
291
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000292 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000293}
294
295// Increments refcount on view.
296// caller must Release() the returned view
297ID3D11DepthStencilView *SwapChain11::getDepthStencil()
298{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000299 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000300 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000301 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000302 }
303
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000304 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000305}
306
307// Increments refcount on texture.
308// caller must Release() the returned texture
309ID3D11Texture2D *SwapChain11::getOffscreenTexture()
310{
311 if (mOffscreenTexture)
312 {
313 mOffscreenTexture->AddRef();
314 }
315
316 return mOffscreenTexture;
317}
318
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000319SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
320{
321 ASSERT(dynamic_cast<rx::SwapChain11*>(swapChain) != NULL);
322 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000323}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000324
325}
326