• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 // DXGISwapChainWindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows using a DXGI
8 // swapchain.
9 
10 #include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
11 
12 #include "libANGLE/formatutils.h"
13 #include "libANGLE/renderer/gl/FramebufferGL.h"
14 #include "libANGLE/renderer/gl/RendererGL.h"
15 #include "libANGLE/renderer/gl/StateManagerGL.h"
16 #include "libANGLE/renderer/gl/TextureGL.h"
17 #include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
18 #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
19 
20 #include <EGL/eglext.h>
21 
22 namespace rx
23 {
24 
DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState & state,StateManagerGL * stateManager,EGLNativeWindowType window,ID3D11Device * device,HANDLE deviceHandle,HDC deviceContext,const FunctionsGL * functionsGL,const FunctionsWGL * functionsWGL,EGLint orientation)25 DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
26                                                              StateManagerGL *stateManager,
27                                                              EGLNativeWindowType window,
28                                                              ID3D11Device *device,
29                                                              HANDLE deviceHandle,
30                                                              HDC deviceContext,
31                                                              const FunctionsGL *functionsGL,
32                                                              const FunctionsWGL *functionsWGL,
33                                                              EGLint orientation)
34     : SurfaceWGL(state),
35       mWindow(window),
36       mStateManager(stateManager),
37       mFunctionsGL(functionsGL),
38       mFunctionsWGL(functionsWGL),
39       mDevice(device),
40       mDeviceHandle(deviceHandle),
41       mWGLDevice(deviceContext),
42       mSwapChainFormat(DXGI_FORMAT_UNKNOWN),
43       mSwapChainFlags(0),
44       mDepthBufferFormat(GL_NONE),
45       mFirstSwap(true),
46       mSwapChain(nullptr),
47       mSwapChain1(nullptr),
48       mFramebufferID(0),
49       mColorRenderbufferID(0),
50       mRenderbufferBufferHandle(nullptr),
51       mDepthRenderbufferID(0),
52       mTextureID(0),
53       mTextureHandle(nullptr),
54       mWidth(0),
55       mHeight(0),
56       mSwapInterval(1),
57       mOrientation(orientation)
58 {}
59 
~DXGISwapChainWindowSurfaceWGL()60 DXGISwapChainWindowSurfaceWGL::~DXGISwapChainWindowSurfaceWGL()
61 {
62     if (mRenderbufferBufferHandle != nullptr)
63     {
64         mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mRenderbufferBufferHandle);
65         mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
66     }
67 
68     if (mFramebufferID != 0)
69     {
70         mStateManager->deleteFramebuffer(mFramebufferID);
71         mFramebufferID = 0;
72     }
73 
74     if (mColorRenderbufferID != 0)
75     {
76         mStateManager->deleteRenderbuffer(mColorRenderbufferID);
77         mColorRenderbufferID = 0;
78     }
79 
80     if (mDepthRenderbufferID != 0)
81     {
82         mStateManager->deleteRenderbuffer(mDepthRenderbufferID);
83         mDepthRenderbufferID = 0;
84     }
85 
86     SafeRelease(mSwapChain);
87     SafeRelease(mSwapChain1);
88 }
89 
initialize(const egl::Display * display)90 egl::Error DXGISwapChainWindowSurfaceWGL::initialize(const egl::Display *display)
91 {
92     if (mOrientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE)
93     {
94         // TODO(geofflang): Support the orientation extensions fully.  Currently only inverting Y is
95         // supported.  To support all orientations, an intermediate framebuffer will be needed with
96         // a blit before swap.
97         return egl::Error(EGL_BAD_ATTRIBUTE,
98                           "DXGISwapChainWindowSurfaceWGL requires an orientation of "
99                           "EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE.");
100     }
101 
102     RECT rect;
103     if (!GetClientRect(mWindow, &rect))
104     {
105         return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
106     }
107     mWidth  = rect.right - rect.left;
108     mHeight = rect.bottom - rect.top;
109 
110     mSwapChainFormat   = DXGI_FORMAT_R8G8B8A8_UNORM;
111     mSwapChainFlags    = 0;
112     mDepthBufferFormat = GL_DEPTH24_STENCIL8;
113 
114     mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
115     mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
116 
117     mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID);
118     mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
119 
120     return createSwapChain();
121 }
122 
makeCurrent(const gl::Context * context)123 egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent(const gl::Context *context)
124 {
125     return egl::NoError();
126 }
127 
swap(const gl::Context * context,SurfaceSwapFeedback * feedback)128 egl::Error DXGISwapChainWindowSurfaceWGL::swap(const gl::Context *context,
129                                                SurfaceSwapFeedback *feedback)
130 {
131     mFunctionsGL->flush();
132 
133     ANGLE_TRY(setObjectsLocked(false));
134 
135     HRESULT result = mSwapChain->Present(mSwapInterval, 0);
136     mFirstSwap     = false;
137 
138     ANGLE_TRY(setObjectsLocked(true));
139 
140     if (FAILED(result))
141     {
142         std::ostringstream err;
143         err << "Failed to present swap chain, " << gl::FmtHR(result);
144         return egl::Error(EGL_BAD_ALLOC, err.str());
145     }
146 
147     return checkForResize();
148 }
149 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)150 egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(const gl::Context *context,
151                                                         EGLint x,
152                                                         EGLint y,
153                                                         EGLint width,
154                                                         EGLint height)
155 {
156     ASSERT(width > 0 && height > 0);
157     ASSERT(mSwapChain1 != nullptr);
158 
159     mFunctionsGL->flush();
160 
161     ANGLE_TRY(setObjectsLocked(false));
162 
163     HRESULT result = S_OK;
164     if (mFirstSwap)
165     {
166         result     = mSwapChain1->Present(mSwapInterval, 0);
167         mFirstSwap = false;
168     }
169     else
170     {
171         RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
172                      static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
173         DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
174         result                         = mSwapChain1->Present1(mSwapInterval, 0, &params);
175     }
176 
177     ANGLE_TRY(setObjectsLocked(true));
178 
179     if (FAILED(result))
180     {
181         std::ostringstream err;
182         err << "Failed to present swap chain, " << gl::FmtHR(result);
183         return egl::Error(EGL_BAD_ALLOC, err.str());
184     }
185 
186     return checkForResize();
187 }
188 
querySurfacePointerANGLE(EGLint attribute,void ** value)189 egl::Error DXGISwapChainWindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
190 {
191     UNREACHABLE();
192     return egl::NoError();
193 }
194 
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)195 egl::Error DXGISwapChainWindowSurfaceWGL::bindTexImage(const gl::Context *context,
196                                                        gl::Texture *texture,
197                                                        EGLint buffer)
198 {
199     ASSERT(mTextureHandle == nullptr);
200 
201     const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
202     GLuint textureID           = textureGL->getTextureID();
203 
204     ID3D11Texture2D *colorBuffer = nullptr;
205     HRESULT result               = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
206                                                          reinterpret_cast<void **>(&colorBuffer));
207     if (FAILED(result))
208     {
209         std::ostringstream err;
210         err << "Failed to query texture from swap chain, " << gl::FmtHR(result);
211         return egl::Error(EGL_BAD_ALLOC, err.str());
212     }
213 
214     mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, textureID,
215                                                        GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
216     SafeRelease(colorBuffer);
217     if (mTextureHandle == nullptr)
218     {
219         std::ostringstream err;
220         err << "Failed to register D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
221         return egl::Error(EGL_BAD_ALLOC, err.str());
222     }
223 
224     if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
225     {
226         mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
227         mTextureHandle = nullptr;
228 
229         std::ostringstream err;
230         err << "Failed to lock D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
231         return egl::Error(EGL_BAD_ALLOC, err.str());
232     }
233 
234     mTextureID = textureID;
235 
236     return egl::NoError();
237 }
238 
releaseTexImage(const gl::Context * context,EGLint buffer)239 egl::Error DXGISwapChainWindowSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer)
240 {
241     ASSERT(mTextureHandle != nullptr);
242 
243     if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
244     {
245         std::ostringstream err;
246         err << "Failed to unlock D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
247         return egl::Error(EGL_BAD_ALLOC, err.str());
248     }
249 
250     if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle))
251     {
252         std::ostringstream err;
253         err << "Failed to unregister D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
254         return egl::Error(EGL_BAD_ALLOC, err.str());
255     }
256 
257     mTextureID     = 0;
258     mTextureHandle = nullptr;
259 
260     return egl::NoError();
261 }
262 
setSwapInterval(const egl::Display * display,EGLint interval)263 void DXGISwapChainWindowSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint interval)
264 {
265     mSwapInterval = interval;
266 }
267 
getWidth() const268 EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const
269 {
270     return static_cast<EGLint>(mWidth);
271 }
272 
getHeight() const273 EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const
274 {
275     return static_cast<EGLint>(mHeight);
276 }
277 
isPostSubBufferSupported() const278 EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const
279 {
280     return mSwapChain1 != nullptr;
281 }
282 
getSwapBehavior() const283 EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const
284 {
285     return EGL_BUFFER_DESTROYED;
286 }
287 
getDC() const288 HDC DXGISwapChainWindowSurfaceWGL::getDC() const
289 {
290     return mWGLDevice;
291 }
292 
attachToFramebuffer(const gl::Context * context,gl::Framebuffer * framebuffer)293 egl::Error DXGISwapChainWindowSurfaceWGL::attachToFramebuffer(const gl::Context *context,
294                                                               gl::Framebuffer *framebuffer)
295 {
296     FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
297     ASSERT(framebufferGL->getFramebufferID() == 0);
298 
299     if (mFramebufferID == 0)
300     {
301         GLuint framebufferID = 0;
302         mFunctionsGL->genFramebuffers(1, &framebufferID);
303         mStateManager->bindFramebuffer(GL_FRAMEBUFFER, framebufferID);
304         mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
305                                               mColorRenderbufferID);
306 
307         if (mDepthBufferFormat != GL_NONE)
308         {
309             const gl::InternalFormat &depthStencilFormatInfo =
310                 gl::GetSizedInternalFormatInfo(mDepthBufferFormat);
311             if (depthStencilFormatInfo.depthBits > 0)
312             {
313                 mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
314                                                       GL_RENDERBUFFER, mDepthRenderbufferID);
315             }
316             if (depthStencilFormatInfo.stencilBits > 0)
317             {
318                 mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
319                                                       GL_RENDERBUFFER, mDepthRenderbufferID);
320             }
321         }
322 
323         mFramebufferID = framebufferID;
324     }
325     framebufferGL->setFramebufferID(mFramebufferID);
326     return egl::NoError();
327 }
328 
detachFromFramebuffer(const gl::Context * context,gl::Framebuffer * framebuffer)329 egl::Error DXGISwapChainWindowSurfaceWGL::detachFromFramebuffer(const gl::Context *context,
330                                                                 gl::Framebuffer *framebuffer)
331 {
332     FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
333     ASSERT(framebufferGL->getFramebufferID() == mFramebufferID);
334     framebufferGL->setFramebufferID(0);
335     return egl::NoError();
336 }
337 
setObjectsLocked(bool locked)338 egl::Error DXGISwapChainWindowSurfaceWGL::setObjectsLocked(bool locked)
339 {
340     if (mRenderbufferBufferHandle == nullptr)
341     {
342         ASSERT(mTextureHandle == nullptr);
343         return egl::NoError();
344     }
345 
346     HANDLE resources[] = {
347         mRenderbufferBufferHandle,
348         mTextureHandle,
349     };
350     GLint count = (mTextureHandle != nullptr) ? 2 : 1;
351 
352     if (locked)
353     {
354         if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, count, resources))
355         {
356             std::ostringstream err;
357             err << "Failed to lock object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
358             return egl::Error(EGL_BAD_ALLOC, err.str());
359         }
360     }
361     else
362     {
363         if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, count, resources))
364         {
365             std::ostringstream err;
366             err << "Failed to lock object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
367             return egl::Error(EGL_BAD_ALLOC, err.str());
368         }
369     }
370 
371     return egl::NoError();
372 }
373 
checkForResize()374 egl::Error DXGISwapChainWindowSurfaceWGL::checkForResize()
375 {
376     RECT rect;
377     if (!GetClientRect(mWindow, &rect))
378     {
379         return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
380     }
381 
382     size_t newWidth  = rect.right - rect.left;
383     size_t newHeight = rect.bottom - rect.top;
384     if (newWidth != mWidth || newHeight != mHeight)
385     {
386         mWidth  = newWidth;
387         mHeight = newHeight;
388 
389         // TODO(geofflang): Handle resize by resizing the swap chain instead of re-creating it.
390         egl::Error error = createSwapChain();
391         if (error.isError())
392         {
393             return error;
394         }
395     }
396 
397     return egl::NoError();
398 }
399 
GetDXGIFactoryFromDevice(ID3D11Device * device)400 static IDXGIFactory *GetDXGIFactoryFromDevice(ID3D11Device *device)
401 {
402     IDXGIDevice *dxgiDevice = nullptr;
403     HRESULT result =
404         device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice));
405     if (FAILED(result))
406     {
407         return nullptr;
408     }
409 
410     IDXGIAdapter *dxgiAdapter = nullptr;
411     result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&dxgiAdapter));
412     SafeRelease(dxgiDevice);
413     if (FAILED(result))
414     {
415         return nullptr;
416     }
417 
418     IDXGIFactory *dxgiFactory = nullptr;
419     result =
420         dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory));
421     SafeRelease(dxgiAdapter);
422     if (FAILED(result))
423     {
424         return nullptr;
425     }
426 
427     return dxgiFactory;
428 }
429 
createSwapChain()430 egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
431 {
432     egl::Error error = setObjectsLocked(false);
433     if (error.isError())
434     {
435         return error;
436     }
437 
438     if (mRenderbufferBufferHandle)
439     {
440         mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
441         mRenderbufferBufferHandle = nullptr;
442     }
443 
444     // If this surface is bound to a texture, unregister it.
445     bool hadBoundSurface = (mTextureHandle != nullptr);
446     if (hadBoundSurface)
447     {
448         mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
449         mTextureHandle = nullptr;
450     }
451 
452     IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice);
453     if (dxgiFactory == nullptr)
454     {
455         return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory.");
456     }
457 
458     IDXGIFactory2 *dxgiFactory2 = nullptr;
459     HRESULT result              = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2),
460                                                               reinterpret_cast<void **>(&dxgiFactory2));
461     if (SUCCEEDED(result))
462     {
463         ASSERT(dxgiFactory2 != nullptr);
464 
465         DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
466         swapChainDesc.BufferCount           = 1;
467         swapChainDesc.Format                = mSwapChainFormat;
468         swapChainDesc.Width                 = static_cast<UINT>(mWidth);
469         swapChainDesc.Height                = static_cast<UINT>(mHeight);
470         swapChainDesc.Format                = mSwapChainFormat;
471         swapChainDesc.Stereo                = FALSE;
472         swapChainDesc.SampleDesc.Count      = 1;
473         swapChainDesc.SampleDesc.Quality    = 0;
474         swapChainDesc.BufferUsage =
475             DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
476         swapChainDesc.BufferCount = 1;
477         swapChainDesc.Scaling     = DXGI_SCALING_STRETCH;
478         swapChainDesc.SwapEffect  = DXGI_SWAP_EFFECT_SEQUENTIAL;
479         swapChainDesc.AlphaMode   = DXGI_ALPHA_MODE_UNSPECIFIED;
480         swapChainDesc.Flags       = mSwapChainFlags;
481 
482         result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr,
483                                                       nullptr, &mSwapChain1);
484         SafeRelease(dxgiFactory2);
485         SafeRelease(dxgiFactory);
486         if (FAILED(result))
487         {
488             std::ostringstream err;
489             err << "Failed to create swap chain for window, " << gl::FmtHR(result);
490             return egl::Error(EGL_BAD_ALLOC, err.str());
491         }
492 
493         mSwapChain = mSwapChain1;
494         mSwapChain->AddRef();
495     }
496     else
497     {
498         DXGI_SWAP_CHAIN_DESC swapChainDesc               = {};
499         swapChainDesc.BufferCount                        = 1;
500         swapChainDesc.BufferDesc.Format                  = mSwapChainFormat;
501         swapChainDesc.BufferDesc.Width                   = static_cast<UINT>(mWidth);
502         swapChainDesc.BufferDesc.Height                  = static_cast<UINT>(mHeight);
503         swapChainDesc.BufferDesc.Scaling                 = DXGI_MODE_SCALING_UNSPECIFIED;
504         swapChainDesc.BufferDesc.ScanlineOrdering        = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
505         swapChainDesc.BufferDesc.RefreshRate.Numerator   = 0;
506         swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
507         swapChainDesc.BufferUsage =
508             DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
509         swapChainDesc.Flags              = mSwapChainFlags;
510         swapChainDesc.OutputWindow       = mWindow;
511         swapChainDesc.SampleDesc.Count   = 1;
512         swapChainDesc.SampleDesc.Quality = 0;
513         swapChainDesc.Windowed           = TRUE;
514         swapChainDesc.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;
515 
516         result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
517         SafeRelease(dxgiFactory);
518         if (FAILED(result))
519         {
520             std::ostringstream err;
521             err << "Failed to create swap chain for window, " << gl::FmtHR(result);
522             return egl::Error(EGL_BAD_ALLOC, err.str());
523         }
524     }
525 
526     ID3D11Texture2D *colorBuffer = nullptr;
527     result                       = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
528                                                          reinterpret_cast<void **>(&colorBuffer));
529     if (FAILED(result))
530     {
531         std::ostringstream err;
532         err << "Failed to query texture from swap chain, " << gl::FmtHR(result);
533         return egl::Error(EGL_BAD_ALLOC, err.str());
534     }
535 
536     mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
537     mRenderbufferBufferHandle =
538         mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID,
539                                           GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
540     SafeRelease(colorBuffer);
541     if (mRenderbufferBufferHandle == nullptr)
542     {
543         std::ostringstream err;
544         err << "Failed to register D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
545         return egl::Error(EGL_BAD_ALLOC, err.str());
546     }
547 
548     // Rebind the surface to the texture if needed.
549     if (hadBoundSurface)
550     {
551         mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID,
552                                                            GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
553         if (mTextureHandle == nullptr)
554         {
555             std::ostringstream err;
556             err << "Failed to register D3D object, " << gl::FmtErr(HRESULT_CODE(GetLastError()));
557             return egl::Error(EGL_BAD_ALLOC, err.str());
558         }
559     }
560 
561     error = setObjectsLocked(true);
562     if (error.isError())
563     {
564         return error;
565     }
566 
567     if (mDepthBufferFormat != GL_NONE)
568     {
569         ASSERT(mDepthRenderbufferID != 0);
570         mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
571         mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat,
572                                           static_cast<GLsizei>(mWidth),
573                                           static_cast<GLsizei>(mHeight));
574     }
575 
576     mFirstSwap = true;
577 
578     return egl::NoError();
579 }
580 }  // namespace rx
581