xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // SurfaceD3D.cpp: D3D implementation of an EGL surface
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/SurfaceD3D.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/Format.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/DisplayD3D.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/RendererD3D.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/SwapChainD3D.h"
19*8975f5c5SAndroid Build Coastguard Worker 
20*8975f5c5SAndroid Build Coastguard Worker #include <EGL/eglext.h>
21*8975f5c5SAndroid Build Coastguard Worker #include <tchar.h>
22*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
23*8975f5c5SAndroid Build Coastguard Worker 
24*8975f5c5SAndroid Build Coastguard Worker namespace rx
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker 
SurfaceD3D(const egl::SurfaceState & state,RendererD3D * renderer,egl::Display * display,EGLNativeWindowType window,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)27*8975f5c5SAndroid Build Coastguard Worker SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
28*8975f5c5SAndroid Build Coastguard Worker                        RendererD3D *renderer,
29*8975f5c5SAndroid Build Coastguard Worker                        egl::Display *display,
30*8975f5c5SAndroid Build Coastguard Worker                        EGLNativeWindowType window,
31*8975f5c5SAndroid Build Coastguard Worker                        EGLenum buftype,
32*8975f5c5SAndroid Build Coastguard Worker                        EGLClientBuffer clientBuffer,
33*8975f5c5SAndroid Build Coastguard Worker                        const egl::AttributeMap &attribs)
34*8975f5c5SAndroid Build Coastguard Worker     : SurfaceImpl(state),
35*8975f5c5SAndroid Build Coastguard Worker       mRenderer(renderer),
36*8975f5c5SAndroid Build Coastguard Worker       mDisplay(display),
37*8975f5c5SAndroid Build Coastguard Worker       mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
38*8975f5c5SAndroid Build Coastguard Worker       mFixedWidth(0),
39*8975f5c5SAndroid Build Coastguard Worker       mFixedHeight(0),
40*8975f5c5SAndroid Build Coastguard Worker       mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
41*8975f5c5SAndroid Build Coastguard Worker       mRenderTargetFormat(state.config->renderTargetFormat),
42*8975f5c5SAndroid Build Coastguard Worker       mDepthStencilFormat(state.config->depthStencilFormat),
43*8975f5c5SAndroid Build Coastguard Worker       mColorFormat(nullptr),
44*8975f5c5SAndroid Build Coastguard Worker       mSwapChain(nullptr),
45*8975f5c5SAndroid Build Coastguard Worker       mSwapIntervalDirty(true),
46*8975f5c5SAndroid Build Coastguard Worker       mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
47*8975f5c5SAndroid Build Coastguard Worker       mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
48*8975f5c5SAndroid Build Coastguard Worker       mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
49*8975f5c5SAndroid Build Coastguard Worker       mSwapInterval(1),
50*8975f5c5SAndroid Build Coastguard Worker       mShareHandle(0),
51*8975f5c5SAndroid Build Coastguard Worker       mD3DTexture(nullptr),
52*8975f5c5SAndroid Build Coastguard Worker       mBuftype(buftype)
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker     if (window != nullptr && !mFixedSize)
55*8975f5c5SAndroid Build Coastguard Worker     {
56*8975f5c5SAndroid Build Coastguard Worker         mWidth  = -1;
57*8975f5c5SAndroid Build Coastguard Worker         mHeight = -1;
58*8975f5c5SAndroid Build Coastguard Worker     }
59*8975f5c5SAndroid Build Coastguard Worker 
60*8975f5c5SAndroid Build Coastguard Worker     if (mFixedSize)
61*8975f5c5SAndroid Build Coastguard Worker     {
62*8975f5c5SAndroid Build Coastguard Worker         mFixedWidth  = mWidth;
63*8975f5c5SAndroid Build Coastguard Worker         mFixedHeight = mHeight;
64*8975f5c5SAndroid Build Coastguard Worker     }
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker     switch (buftype)
67*8975f5c5SAndroid Build Coastguard Worker     {
68*8975f5c5SAndroid Build Coastguard Worker         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
69*8975f5c5SAndroid Build Coastguard Worker             mShareHandle = static_cast<HANDLE>(clientBuffer);
70*8975f5c5SAndroid Build Coastguard Worker             break;
71*8975f5c5SAndroid Build Coastguard Worker 
72*8975f5c5SAndroid Build Coastguard Worker         case EGL_D3D_TEXTURE_ANGLE:
73*8975f5c5SAndroid Build Coastguard Worker             mD3DTexture = static_cast<IUnknown *>(clientBuffer);
74*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mD3DTexture != nullptr);
75*8975f5c5SAndroid Build Coastguard Worker             mD3DTexture->AddRef();
76*8975f5c5SAndroid Build Coastguard Worker             break;
77*8975f5c5SAndroid Build Coastguard Worker 
78*8975f5c5SAndroid Build Coastguard Worker         default:
79*8975f5c5SAndroid Build Coastguard Worker             break;
80*8975f5c5SAndroid Build Coastguard Worker     }
81*8975f5c5SAndroid Build Coastguard Worker }
82*8975f5c5SAndroid Build Coastguard Worker 
~SurfaceD3D()83*8975f5c5SAndroid Build Coastguard Worker SurfaceD3D::~SurfaceD3D()
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker     releaseSwapChain();
86*8975f5c5SAndroid Build Coastguard Worker     SafeDelete(mNativeWindow);
87*8975f5c5SAndroid Build Coastguard Worker     SafeRelease(mD3DTexture);
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker 
releaseSwapChain()90*8975f5c5SAndroid Build Coastguard Worker void SurfaceD3D::releaseSwapChain()
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker     SafeDelete(mSwapChain);
93*8975f5c5SAndroid Build Coastguard Worker }
94*8975f5c5SAndroid Build Coastguard Worker 
initialize(const egl::Display * display)95*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::initialize(const egl::Display *display)
96*8975f5c5SAndroid Build Coastguard Worker {
97*8975f5c5SAndroid Build Coastguard Worker     if (mNativeWindow->getNativeWindow())
98*8975f5c5SAndroid Build Coastguard Worker     {
99*8975f5c5SAndroid Build Coastguard Worker         if (!mNativeWindow->initialize())
100*8975f5c5SAndroid Build Coastguard Worker         {
101*8975f5c5SAndroid Build Coastguard Worker             return egl::EglBadSurface();
102*8975f5c5SAndroid Build Coastguard Worker         }
103*8975f5c5SAndroid Build Coastguard Worker     }
104*8975f5c5SAndroid Build Coastguard Worker 
105*8975f5c5SAndroid Build Coastguard Worker     if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
106*8975f5c5SAndroid Build Coastguard Worker     {
107*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, mState.attributes,
108*8975f5c5SAndroid Build Coastguard Worker                                                &mFixedWidth, &mFixedHeight, nullptr, nullptr,
109*8975f5c5SAndroid Build Coastguard Worker                                                &mColorFormat, nullptr));
110*8975f5c5SAndroid Build Coastguard Worker         if (mState.attributes.contains(EGL_GL_COLORSPACE))
111*8975f5c5SAndroid Build Coastguard Worker         {
112*8975f5c5SAndroid Build Coastguard Worker             if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
113*8975f5c5SAndroid Build Coastguard Worker                 mColorFormat->id != angle::FormatID::B8G8R8A8_TYPELESS)
114*8975f5c5SAndroid Build Coastguard Worker             {
115*8975f5c5SAndroid Build Coastguard Worker                 return egl::EglBadMatch()
116*8975f5c5SAndroid Build Coastguard Worker                        << "EGL_GL_COLORSPACE may only be specified for TYPELESS textures";
117*8975f5c5SAndroid Build Coastguard Worker             }
118*8975f5c5SAndroid Build Coastguard Worker         }
119*8975f5c5SAndroid Build Coastguard Worker         if (mColorFormat->id == angle::FormatID::R8G8B8A8_TYPELESS)
120*8975f5c5SAndroid Build Coastguard Worker         {
121*8975f5c5SAndroid Build Coastguard Worker             EGLAttrib colorspace =
122*8975f5c5SAndroid Build Coastguard Worker                 mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
123*8975f5c5SAndroid Build Coastguard Worker             if (colorspace == EGL_GL_COLORSPACE_SRGB)
124*8975f5c5SAndroid Build Coastguard Worker             {
125*8975f5c5SAndroid Build Coastguard Worker                 mColorFormat = &angle::Format::Get(angle::FormatID::R8G8B8A8_TYPELESS_SRGB);
126*8975f5c5SAndroid Build Coastguard Worker             }
127*8975f5c5SAndroid Build Coastguard Worker         }
128*8975f5c5SAndroid Build Coastguard Worker         if (mColorFormat->id == angle::FormatID::B8G8R8A8_TYPELESS)
129*8975f5c5SAndroid Build Coastguard Worker         {
130*8975f5c5SAndroid Build Coastguard Worker             EGLAttrib colorspace =
131*8975f5c5SAndroid Build Coastguard Worker                 mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
132*8975f5c5SAndroid Build Coastguard Worker             if (colorspace == EGL_GL_COLORSPACE_SRGB)
133*8975f5c5SAndroid Build Coastguard Worker             {
134*8975f5c5SAndroid Build Coastguard Worker                 mColorFormat = &angle::Format::Get(angle::FormatID::B8G8R8A8_TYPELESS_SRGB);
135*8975f5c5SAndroid Build Coastguard Worker             }
136*8975f5c5SAndroid Build Coastguard Worker         }
137*8975f5c5SAndroid Build Coastguard Worker         mRenderTargetFormat = mColorFormat->fboImplementationInternalFormat;
138*8975f5c5SAndroid Build Coastguard Worker     }
139*8975f5c5SAndroid Build Coastguard Worker 
140*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(resetSwapChain(display));
141*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
142*8975f5c5SAndroid Build Coastguard Worker }
143*8975f5c5SAndroid Build Coastguard Worker 
bindTexImage(const gl::Context *,gl::Texture *,EGLint)144*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::bindTexImage(const gl::Context *, gl::Texture *, EGLint)
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
147*8975f5c5SAndroid Build Coastguard Worker }
148*8975f5c5SAndroid Build Coastguard Worker 
releaseTexImage(const gl::Context *,EGLint)149*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::releaseTexImage(const gl::Context *, EGLint)
150*8975f5c5SAndroid Build Coastguard Worker {
151*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker 
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)154*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker     if (!mState.directComposition)
157*8975f5c5SAndroid Build Coastguard Worker     {
158*8975f5c5SAndroid Build Coastguard Worker         return egl::EglBadSurface()
159*8975f5c5SAndroid Build Coastguard Worker                << "getSyncValues: surface requires Direct Composition to be enabled";
160*8975f5c5SAndroid Build Coastguard Worker     }
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     return mSwapChain->getSyncValues(ust, msc, sbc);
163*8975f5c5SAndroid Build Coastguard Worker }
164*8975f5c5SAndroid Build Coastguard Worker 
getMscRate(EGLint * numerator,EGLint * denominator)165*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::getMscRate(EGLint *numerator, EGLint *denominator)
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker     UNIMPLEMENTED();
168*8975f5c5SAndroid Build Coastguard Worker     return egl::EglBadAccess();
169*8975f5c5SAndroid Build Coastguard Worker }
170*8975f5c5SAndroid Build Coastguard Worker 
resetSwapChain(const egl::Display * display)171*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
172*8975f5c5SAndroid Build Coastguard Worker {
173*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mSwapChain);
174*8975f5c5SAndroid Build Coastguard Worker 
175*8975f5c5SAndroid Build Coastguard Worker     int width;
176*8975f5c5SAndroid Build Coastguard Worker     int height;
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     if (!mFixedSize)
179*8975f5c5SAndroid Build Coastguard Worker     {
180*8975f5c5SAndroid Build Coastguard Worker         RECT windowRect;
181*8975f5c5SAndroid Build Coastguard Worker         if (!mNativeWindow->getClientRect(&windowRect))
182*8975f5c5SAndroid Build Coastguard Worker         {
183*8975f5c5SAndroid Build Coastguard Worker             ASSERT(false);
184*8975f5c5SAndroid Build Coastguard Worker 
185*8975f5c5SAndroid Build Coastguard Worker             return egl::EglBadSurface() << "Could not retrieve the window dimensions";
186*8975f5c5SAndroid Build Coastguard Worker         }
187*8975f5c5SAndroid Build Coastguard Worker 
188*8975f5c5SAndroid Build Coastguard Worker         width  = windowRect.right - windowRect.left;
189*8975f5c5SAndroid Build Coastguard Worker         height = windowRect.bottom - windowRect.top;
190*8975f5c5SAndroid Build Coastguard Worker     }
191*8975f5c5SAndroid Build Coastguard Worker     else
192*8975f5c5SAndroid Build Coastguard Worker     {
193*8975f5c5SAndroid Build Coastguard Worker         // non-window surface - size is determined at creation
194*8975f5c5SAndroid Build Coastguard Worker         width  = mFixedWidth;
195*8975f5c5SAndroid Build Coastguard Worker         height = mFixedHeight;
196*8975f5c5SAndroid Build Coastguard Worker     }
197*8975f5c5SAndroid Build Coastguard Worker 
198*8975f5c5SAndroid Build Coastguard Worker     mSwapChain =
199*8975f5c5SAndroid Build Coastguard Worker         mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat,
200*8975f5c5SAndroid Build Coastguard Worker                                    mDepthStencilFormat, mOrientation, mState.config->samples);
201*8975f5c5SAndroid Build Coastguard Worker     if (!mSwapChain)
202*8975f5c5SAndroid Build Coastguard Worker     {
203*8975f5c5SAndroid Build Coastguard Worker         return egl::EglBadAlloc();
204*8975f5c5SAndroid Build Coastguard Worker     }
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     // This is a bit risky to pass the proxy context here, but it can happen at almost any time.
207*8975f5c5SAndroid Build Coastguard Worker     DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(display);
208*8975f5c5SAndroid Build Coastguard Worker     egl::Error error       = resetSwapChain(displayD3D, width, height);
209*8975f5c5SAndroid Build Coastguard Worker     if (error.isError())
210*8975f5c5SAndroid Build Coastguard Worker     {
211*8975f5c5SAndroid Build Coastguard Worker         SafeDelete(mSwapChain);
212*8975f5c5SAndroid Build Coastguard Worker         return error;
213*8975f5c5SAndroid Build Coastguard Worker     }
214*8975f5c5SAndroid Build Coastguard Worker 
215*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker 
resizeSwapChain(DisplayD3D * displayD3D,int backbufferWidth,int backbufferHeight)218*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::resizeSwapChain(DisplayD3D *displayD3D,
219*8975f5c5SAndroid Build Coastguard Worker                                        int backbufferWidth,
220*8975f5c5SAndroid Build Coastguard Worker                                        int backbufferHeight)
221*8975f5c5SAndroid Build Coastguard Worker {
222*8975f5c5SAndroid Build Coastguard Worker     ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
223*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mSwapChain);
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker     EGLint status =
226*8975f5c5SAndroid Build Coastguard Worker         mSwapChain->resize(displayD3D, std::max(1, backbufferWidth), std::max(1, backbufferHeight));
227*8975f5c5SAndroid Build Coastguard Worker 
228*8975f5c5SAndroid Build Coastguard Worker     if (status == EGL_CONTEXT_LOST)
229*8975f5c5SAndroid Build Coastguard Worker     {
230*8975f5c5SAndroid Build Coastguard Worker         mDisplay->notifyDeviceLost();
231*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(status);
232*8975f5c5SAndroid Build Coastguard Worker     }
233*8975f5c5SAndroid Build Coastguard Worker     else if (status != EGL_SUCCESS)
234*8975f5c5SAndroid Build Coastguard Worker     {
235*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(status);
236*8975f5c5SAndroid Build Coastguard Worker     }
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker     mWidth  = backbufferWidth;
239*8975f5c5SAndroid Build Coastguard Worker     mHeight = backbufferHeight;
240*8975f5c5SAndroid Build Coastguard Worker 
241*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
242*8975f5c5SAndroid Build Coastguard Worker }
243*8975f5c5SAndroid Build Coastguard Worker 
resetSwapChain(DisplayD3D * displayD3D,int backbufferWidth,int backbufferHeight)244*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::resetSwapChain(DisplayD3D *displayD3D,
245*8975f5c5SAndroid Build Coastguard Worker                                       int backbufferWidth,
246*8975f5c5SAndroid Build Coastguard Worker                                       int backbufferHeight)
247*8975f5c5SAndroid Build Coastguard Worker {
248*8975f5c5SAndroid Build Coastguard Worker     ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
249*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mSwapChain);
250*8975f5c5SAndroid Build Coastguard Worker 
251*8975f5c5SAndroid Build Coastguard Worker     EGLint status = mSwapChain->reset(displayD3D, std::max(1, backbufferWidth),
252*8975f5c5SAndroid Build Coastguard Worker                                       std::max(1, backbufferHeight), mSwapInterval);
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker     if (status == EGL_CONTEXT_LOST)
255*8975f5c5SAndroid Build Coastguard Worker     {
256*8975f5c5SAndroid Build Coastguard Worker         mRenderer->notifyDeviceLost();
257*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(status);
258*8975f5c5SAndroid Build Coastguard Worker     }
259*8975f5c5SAndroid Build Coastguard Worker     else if (status != EGL_SUCCESS)
260*8975f5c5SAndroid Build Coastguard Worker     {
261*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(status);
262*8975f5c5SAndroid Build Coastguard Worker     }
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     mWidth             = backbufferWidth;
265*8975f5c5SAndroid Build Coastguard Worker     mHeight            = backbufferHeight;
266*8975f5c5SAndroid Build Coastguard Worker     mSwapIntervalDirty = false;
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
269*8975f5c5SAndroid Build Coastguard Worker }
270*8975f5c5SAndroid Build Coastguard Worker 
swapRect(DisplayD3D * displayD3D,EGLint x,EGLint y,EGLint width,EGLint height)271*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::swapRect(DisplayD3D *displayD3D,
272*8975f5c5SAndroid Build Coastguard Worker                                 EGLint x,
273*8975f5c5SAndroid Build Coastguard Worker                                 EGLint y,
274*8975f5c5SAndroid Build Coastguard Worker                                 EGLint width,
275*8975f5c5SAndroid Build Coastguard Worker                                 EGLint height)
276*8975f5c5SAndroid Build Coastguard Worker {
277*8975f5c5SAndroid Build Coastguard Worker     if (!mSwapChain)
278*8975f5c5SAndroid Build Coastguard Worker     {
279*8975f5c5SAndroid Build Coastguard Worker         return egl::NoError();
280*8975f5c5SAndroid Build Coastguard Worker     }
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker     if (x + width > mWidth)
283*8975f5c5SAndroid Build Coastguard Worker     {
284*8975f5c5SAndroid Build Coastguard Worker         width = mWidth - x;
285*8975f5c5SAndroid Build Coastguard Worker     }
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker     if (y + height > mHeight)
288*8975f5c5SAndroid Build Coastguard Worker     {
289*8975f5c5SAndroid Build Coastguard Worker         height = mHeight - y;
290*8975f5c5SAndroid Build Coastguard Worker     }
291*8975f5c5SAndroid Build Coastguard Worker 
292*8975f5c5SAndroid Build Coastguard Worker     if (width != 0 && height != 0)
293*8975f5c5SAndroid Build Coastguard Worker     {
294*8975f5c5SAndroid Build Coastguard Worker         EGLint status = mSwapChain->swapRect(displayD3D, x, y, width, height);
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker         if (status == EGL_CONTEXT_LOST)
297*8975f5c5SAndroid Build Coastguard Worker         {
298*8975f5c5SAndroid Build Coastguard Worker             mRenderer->notifyDeviceLost();
299*8975f5c5SAndroid Build Coastguard Worker             return egl::Error(status);
300*8975f5c5SAndroid Build Coastguard Worker         }
301*8975f5c5SAndroid Build Coastguard Worker         else if (status != EGL_SUCCESS)
302*8975f5c5SAndroid Build Coastguard Worker         {
303*8975f5c5SAndroid Build Coastguard Worker             return egl::Error(status);
304*8975f5c5SAndroid Build Coastguard Worker         }
305*8975f5c5SAndroid Build Coastguard Worker     }
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(checkForOutOfDateSwapChain(displayD3D));
308*8975f5c5SAndroid Build Coastguard Worker 
309*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
310*8975f5c5SAndroid Build Coastguard Worker }
311*8975f5c5SAndroid Build Coastguard Worker 
checkForOutOfDateSwapChain(DisplayD3D * displayD3D)312*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D)
313*8975f5c5SAndroid Build Coastguard Worker {
314*8975f5c5SAndroid Build Coastguard Worker     RECT client;
315*8975f5c5SAndroid Build Coastguard Worker     int clientWidth  = getWidth();
316*8975f5c5SAndroid Build Coastguard Worker     int clientHeight = getHeight();
317*8975f5c5SAndroid Build Coastguard Worker     bool sizeDirty   = false;
318*8975f5c5SAndroid Build Coastguard Worker     if (!mFixedSize && !mNativeWindow->isIconic())
319*8975f5c5SAndroid Build Coastguard Worker     {
320*8975f5c5SAndroid Build Coastguard Worker         // The window is automatically resized to 150x22 when it's minimized, but the swapchain
321*8975f5c5SAndroid Build Coastguard Worker         // shouldn't be resized because that's not a useful size to render to.
322*8975f5c5SAndroid Build Coastguard Worker         if (!mNativeWindow->getClientRect(&client))
323*8975f5c5SAndroid Build Coastguard Worker         {
324*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
325*8975f5c5SAndroid Build Coastguard Worker             return egl::NoError();
326*8975f5c5SAndroid Build Coastguard Worker         }
327*8975f5c5SAndroid Build Coastguard Worker 
328*8975f5c5SAndroid Build Coastguard Worker         // Grow the buffer now, if the window has grown. We need to grow now to avoid losing
329*8975f5c5SAndroid Build Coastguard Worker         // information.
330*8975f5c5SAndroid Build Coastguard Worker         clientWidth  = client.right - client.left;
331*8975f5c5SAndroid Build Coastguard Worker         clientHeight = client.bottom - client.top;
332*8975f5c5SAndroid Build Coastguard Worker         sizeDirty    = clientWidth != getWidth() || clientHeight != getHeight();
333*8975f5c5SAndroid Build Coastguard Worker     }
334*8975f5c5SAndroid Build Coastguard Worker     else if (mFixedSize)
335*8975f5c5SAndroid Build Coastguard Worker     {
336*8975f5c5SAndroid Build Coastguard Worker         clientWidth  = mFixedWidth;
337*8975f5c5SAndroid Build Coastguard Worker         clientHeight = mFixedHeight;
338*8975f5c5SAndroid Build Coastguard Worker         sizeDirty    = mFixedWidth != getWidth() || mFixedHeight != getHeight();
339*8975f5c5SAndroid Build Coastguard Worker     }
340*8975f5c5SAndroid Build Coastguard Worker 
341*8975f5c5SAndroid Build Coastguard Worker     if (mSwapIntervalDirty)
342*8975f5c5SAndroid Build Coastguard Worker     {
343*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(resetSwapChain(displayD3D, clientWidth, clientHeight));
344*8975f5c5SAndroid Build Coastguard Worker     }
345*8975f5c5SAndroid Build Coastguard Worker     else if (sizeDirty)
346*8975f5c5SAndroid Build Coastguard Worker     {
347*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(resizeSwapChain(displayD3D, clientWidth, clientHeight));
348*8975f5c5SAndroid Build Coastguard Worker     }
349*8975f5c5SAndroid Build Coastguard Worker 
350*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
351*8975f5c5SAndroid Build Coastguard Worker }
352*8975f5c5SAndroid Build Coastguard Worker 
swap(const gl::Context * context)353*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::swap(const gl::Context *context)
354*8975f5c5SAndroid Build Coastguard Worker {
355*8975f5c5SAndroid Build Coastguard Worker     DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
356*8975f5c5SAndroid Build Coastguard Worker     return swapRect(displayD3D, 0, 0, mWidth, mHeight);
357*8975f5c5SAndroid Build Coastguard Worker }
358*8975f5c5SAndroid Build Coastguard Worker 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)359*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::postSubBuffer(const gl::Context *context,
360*8975f5c5SAndroid Build Coastguard Worker                                      EGLint x,
361*8975f5c5SAndroid Build Coastguard Worker                                      EGLint y,
362*8975f5c5SAndroid Build Coastguard Worker                                      EGLint width,
363*8975f5c5SAndroid Build Coastguard Worker                                      EGLint height)
364*8975f5c5SAndroid Build Coastguard Worker {
365*8975f5c5SAndroid Build Coastguard Worker     DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
366*8975f5c5SAndroid Build Coastguard Worker     return swapRect(displayD3D, x, y, width, height);
367*8975f5c5SAndroid Build Coastguard Worker }
368*8975f5c5SAndroid Build Coastguard Worker 
getSwapChain() const369*8975f5c5SAndroid Build Coastguard Worker rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
370*8975f5c5SAndroid Build Coastguard Worker {
371*8975f5c5SAndroid Build Coastguard Worker     return mSwapChain;
372*8975f5c5SAndroid Build Coastguard Worker }
373*8975f5c5SAndroid Build Coastguard Worker 
setSwapInterval(const egl::Display * display,EGLint interval)374*8975f5c5SAndroid Build Coastguard Worker void SurfaceD3D::setSwapInterval(const egl::Display *display, EGLint interval)
375*8975f5c5SAndroid Build Coastguard Worker {
376*8975f5c5SAndroid Build Coastguard Worker     if (mSwapInterval == interval)
377*8975f5c5SAndroid Build Coastguard Worker     {
378*8975f5c5SAndroid Build Coastguard Worker         return;
379*8975f5c5SAndroid Build Coastguard Worker     }
380*8975f5c5SAndroid Build Coastguard Worker 
381*8975f5c5SAndroid Build Coastguard Worker     mSwapInterval      = interval;
382*8975f5c5SAndroid Build Coastguard Worker     mSwapIntervalDirty = true;
383*8975f5c5SAndroid Build Coastguard Worker }
384*8975f5c5SAndroid Build Coastguard Worker 
setFixedWidth(EGLint width)385*8975f5c5SAndroid Build Coastguard Worker void SurfaceD3D::setFixedWidth(EGLint width)
386*8975f5c5SAndroid Build Coastguard Worker {
387*8975f5c5SAndroid Build Coastguard Worker     mFixedWidth = width;
388*8975f5c5SAndroid Build Coastguard Worker }
389*8975f5c5SAndroid Build Coastguard Worker 
setFixedHeight(EGLint height)390*8975f5c5SAndroid Build Coastguard Worker void SurfaceD3D::setFixedHeight(EGLint height)
391*8975f5c5SAndroid Build Coastguard Worker {
392*8975f5c5SAndroid Build Coastguard Worker     mFixedHeight = height;
393*8975f5c5SAndroid Build Coastguard Worker }
394*8975f5c5SAndroid Build Coastguard Worker 
getWidth() const395*8975f5c5SAndroid Build Coastguard Worker EGLint SurfaceD3D::getWidth() const
396*8975f5c5SAndroid Build Coastguard Worker {
397*8975f5c5SAndroid Build Coastguard Worker     return mWidth;
398*8975f5c5SAndroid Build Coastguard Worker }
399*8975f5c5SAndroid Build Coastguard Worker 
getHeight() const400*8975f5c5SAndroid Build Coastguard Worker EGLint SurfaceD3D::getHeight() const
401*8975f5c5SAndroid Build Coastguard Worker {
402*8975f5c5SAndroid Build Coastguard Worker     return mHeight;
403*8975f5c5SAndroid Build Coastguard Worker }
404*8975f5c5SAndroid Build Coastguard Worker 
isPostSubBufferSupported() const405*8975f5c5SAndroid Build Coastguard Worker EGLint SurfaceD3D::isPostSubBufferSupported() const
406*8975f5c5SAndroid Build Coastguard Worker {
407*8975f5c5SAndroid Build Coastguard Worker     // post sub buffer is always possible on D3D surfaces
408*8975f5c5SAndroid Build Coastguard Worker     return EGL_TRUE;
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker 
getSwapBehavior() const411*8975f5c5SAndroid Build Coastguard Worker EGLint SurfaceD3D::getSwapBehavior() const
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker     return EGL_BUFFER_PRESERVED;
414*8975f5c5SAndroid Build Coastguard Worker }
415*8975f5c5SAndroid Build Coastguard Worker 
querySurfacePointerANGLE(EGLint attribute,void ** value)416*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
417*8975f5c5SAndroid Build Coastguard Worker {
418*8975f5c5SAndroid Build Coastguard Worker     if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
419*8975f5c5SAndroid Build Coastguard Worker     {
420*8975f5c5SAndroid Build Coastguard Worker         *value = mSwapChain->getShareHandle();
421*8975f5c5SAndroid Build Coastguard Worker     }
422*8975f5c5SAndroid Build Coastguard Worker     else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE)
423*8975f5c5SAndroid Build Coastguard Worker     {
424*8975f5c5SAndroid Build Coastguard Worker         *value = mSwapChain->getKeyedMutex();
425*8975f5c5SAndroid Build Coastguard Worker     }
426*8975f5c5SAndroid Build Coastguard Worker     else
427*8975f5c5SAndroid Build Coastguard Worker         UNREACHABLE();
428*8975f5c5SAndroid Build Coastguard Worker 
429*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
430*8975f5c5SAndroid Build Coastguard Worker }
431*8975f5c5SAndroid Build Coastguard Worker 
getD3DTextureColorFormat() const432*8975f5c5SAndroid Build Coastguard Worker const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const
433*8975f5c5SAndroid Build Coastguard Worker {
434*8975f5c5SAndroid Build Coastguard Worker     return mColorFormat;
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker 
attachToFramebuffer(const gl::Context * context,gl::Framebuffer * framebuffer)437*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::attachToFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer)
438*8975f5c5SAndroid Build Coastguard Worker {
439*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
440*8975f5c5SAndroid Build Coastguard Worker }
441*8975f5c5SAndroid Build Coastguard Worker 
detachFromFramebuffer(const gl::Context * context,gl::Framebuffer * framebuffer)442*8975f5c5SAndroid Build Coastguard Worker egl::Error SurfaceD3D::detachFromFramebuffer(const gl::Context *context,
443*8975f5c5SAndroid Build Coastguard Worker                                              gl::Framebuffer *framebuffer)
444*8975f5c5SAndroid Build Coastguard Worker {
445*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)448*8975f5c5SAndroid Build Coastguard Worker angle::Result SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
449*8975f5c5SAndroid Build Coastguard Worker                                                     GLenum binding,
450*8975f5c5SAndroid Build Coastguard Worker                                                     const gl::ImageIndex &imageIndex,
451*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei samples,
452*8975f5c5SAndroid Build Coastguard Worker                                                     FramebufferAttachmentRenderTarget **rtOut)
453*8975f5c5SAndroid Build Coastguard Worker {
454*8975f5c5SAndroid Build Coastguard Worker     if (binding == GL_BACK)
455*8975f5c5SAndroid Build Coastguard Worker     {
456*8975f5c5SAndroid Build Coastguard Worker         *rtOut = mSwapChain->getColorRenderTarget();
457*8975f5c5SAndroid Build Coastguard Worker     }
458*8975f5c5SAndroid Build Coastguard Worker     else
459*8975f5c5SAndroid Build Coastguard Worker     {
460*8975f5c5SAndroid Build Coastguard Worker         *rtOut = mSwapChain->getDepthStencilRenderTarget();
461*8975f5c5SAndroid Build Coastguard Worker     }
462*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker 
initializeContents(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)465*8975f5c5SAndroid Build Coastguard Worker angle::Result SurfaceD3D::initializeContents(const gl::Context *context,
466*8975f5c5SAndroid Build Coastguard Worker                                              GLenum binding,
467*8975f5c5SAndroid Build Coastguard Worker                                              const gl::ImageIndex &imageIndex)
468*8975f5c5SAndroid Build Coastguard Worker {
469*8975f5c5SAndroid Build Coastguard Worker     switch (binding)
470*8975f5c5SAndroid Build Coastguard Worker     {
471*8975f5c5SAndroid Build Coastguard Worker         case GL_BACK:
472*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.config->renderTargetFormat != GL_NONE);
473*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mRenderer->initRenderTarget(context, mSwapChain->getColorRenderTarget()));
474*8975f5c5SAndroid Build Coastguard Worker             break;
475*8975f5c5SAndroid Build Coastguard Worker 
476*8975f5c5SAndroid Build Coastguard Worker         case GL_DEPTH:
477*8975f5c5SAndroid Build Coastguard Worker         case GL_STENCIL:
478*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.config->depthStencilFormat != GL_NONE);
479*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(
480*8975f5c5SAndroid Build Coastguard Worker                 mRenderer->initRenderTarget(context, mSwapChain->getDepthStencilRenderTarget()));
481*8975f5c5SAndroid Build Coastguard Worker             break;
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker         default:
484*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
485*8975f5c5SAndroid Build Coastguard Worker             break;
486*8975f5c5SAndroid Build Coastguard Worker     }
487*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
488*8975f5c5SAndroid Build Coastguard Worker }
489*8975f5c5SAndroid Build Coastguard Worker 
WindowSurfaceD3D(const egl::SurfaceState & state,RendererD3D * renderer,egl::Display * display,EGLNativeWindowType window,const egl::AttributeMap & attribs)490*8975f5c5SAndroid Build Coastguard Worker WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
491*8975f5c5SAndroid Build Coastguard Worker                                    RendererD3D *renderer,
492*8975f5c5SAndroid Build Coastguard Worker                                    egl::Display *display,
493*8975f5c5SAndroid Build Coastguard Worker                                    EGLNativeWindowType window,
494*8975f5c5SAndroid Build Coastguard Worker                                    const egl::AttributeMap &attribs)
495*8975f5c5SAndroid Build Coastguard Worker     : SurfaceD3D(state, renderer, display, window, 0, static_cast<EGLClientBuffer>(0), attribs)
496*8975f5c5SAndroid Build Coastguard Worker {}
497*8975f5c5SAndroid Build Coastguard Worker 
~WindowSurfaceD3D()498*8975f5c5SAndroid Build Coastguard Worker WindowSurfaceD3D::~WindowSurfaceD3D() {}
499*8975f5c5SAndroid Build Coastguard Worker 
PbufferSurfaceD3D(const egl::SurfaceState & state,RendererD3D * renderer,egl::Display * display,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)500*8975f5c5SAndroid Build Coastguard Worker PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
501*8975f5c5SAndroid Build Coastguard Worker                                      RendererD3D *renderer,
502*8975f5c5SAndroid Build Coastguard Worker                                      egl::Display *display,
503*8975f5c5SAndroid Build Coastguard Worker                                      EGLenum buftype,
504*8975f5c5SAndroid Build Coastguard Worker                                      EGLClientBuffer clientBuffer,
505*8975f5c5SAndroid Build Coastguard Worker                                      const egl::AttributeMap &attribs)
506*8975f5c5SAndroid Build Coastguard Worker     : SurfaceD3D(state,
507*8975f5c5SAndroid Build Coastguard Worker                  renderer,
508*8975f5c5SAndroid Build Coastguard Worker                  display,
509*8975f5c5SAndroid Build Coastguard Worker                  static_cast<EGLNativeWindowType>(0),
510*8975f5c5SAndroid Build Coastguard Worker                  buftype,
511*8975f5c5SAndroid Build Coastguard Worker                  clientBuffer,
512*8975f5c5SAndroid Build Coastguard Worker                  attribs)
513*8975f5c5SAndroid Build Coastguard Worker {}
514*8975f5c5SAndroid Build Coastguard Worker 
~PbufferSurfaceD3D()515*8975f5c5SAndroid Build Coastguard Worker PbufferSurfaceD3D::~PbufferSurfaceD3D() {}
516*8975f5c5SAndroid Build Coastguard Worker 
517*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
518