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 // SurfaceWGL.cpp: WGL implementation of egl::Surface
8 
9 #include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
10 
11 #include "common/debug.h"
12 #include "libANGLE/renderer/gl/RendererGL.h"
13 #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
14 #include "libANGLE/renderer/gl/wgl/wgl_utils.h"
15 
16 namespace rx
17 {
18 
PbufferSurfaceWGL(const egl::SurfaceState & state,EGLint width,EGLint height,EGLenum textureFormat,EGLenum textureTarget,bool largest,int pixelFormat,HDC deviceContext,const FunctionsWGL * functions)19 PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state,
20                                      EGLint width,
21                                      EGLint height,
22                                      EGLenum textureFormat,
23                                      EGLenum textureTarget,
24                                      bool largest,
25                                      int pixelFormat,
26                                      HDC deviceContext,
27                                      const FunctionsWGL *functions)
28     : SurfaceWGL(state),
29       mWidth(width),
30       mHeight(height),
31       mLargest(largest),
32       mTextureFormat(textureFormat),
33       mTextureTarget(textureTarget),
34       mPixelFormat(pixelFormat),
35       mParentDeviceContext(deviceContext),
36       mPbuffer(nullptr),
37       mPbufferDeviceContext(nullptr),
38       mFunctionsWGL(functions)
39 {}
40 
~PbufferSurfaceWGL()41 PbufferSurfaceWGL::~PbufferSurfaceWGL()
42 {
43     mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext);
44     mPbufferDeviceContext = nullptr;
45 
46     mFunctionsWGL->destroyPbufferARB(mPbuffer);
47     mPbuffer = nullptr;
48 }
49 
GetWGLTextureType(EGLenum eglTextureType)50 static int GetWGLTextureType(EGLenum eglTextureType)
51 {
52     switch (eglTextureType)
53     {
54         case EGL_NO_TEXTURE:
55             return WGL_NO_TEXTURE_ARB;
56         case EGL_TEXTURE_RGB:
57             return WGL_TEXTURE_RGB_ARB;
58         case EGL_TEXTURE_RGBA:
59             return WGL_TEXTURE_RGBA_ARB;
60         default:
61             UNREACHABLE();
62             return 0;
63     }
64 }
65 
GetWGLTextureTarget(EGLenum eglTextureTarget)66 static int GetWGLTextureTarget(EGLenum eglTextureTarget)
67 {
68     switch (eglTextureTarget)
69     {
70         case EGL_NO_TEXTURE:
71             return WGL_NO_TEXTURE_ARB;
72         case EGL_TEXTURE_2D:
73             return WGL_TEXTURE_2D_ARB;
74         default:
75             UNREACHABLE();
76             return 0;
77     }
78 }
79 
initialize(const egl::Display * display)80 egl::Error PbufferSurfaceWGL::initialize(const egl::Display *display)
81 {
82     const int pbufferCreationAttributes[] = {
83         WGL_PBUFFER_LARGEST_ARB,
84         mLargest ? 1 : 0,
85         WGL_TEXTURE_FORMAT_ARB,
86         GetWGLTextureType(mTextureFormat),
87         WGL_TEXTURE_TARGET_ARB,
88         GetWGLTextureTarget(mTextureTarget),
89         0,
90         0,
91     };
92 
93     mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight,
94                                                pbufferCreationAttributes);
95     if (mPbuffer == nullptr)
96     {
97         DWORD error = GetLastError();
98         return egl::EglBadAlloc() << "Failed to create a native WGL pbuffer, "
99                                   << gl::FmtErr(HRESULT_CODE(error));
100     }
101 
102     // The returned pbuffer may not be as large as requested, update the size members.
103     if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE ||
104         mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE)
105     {
106         DWORD error = GetLastError();
107         return egl::EglBadAlloc() << "Failed to query the WGL pbuffer's dimensions, "
108                                   << gl::FmtErr(HRESULT_CODE(error));
109     }
110 
111     mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer);
112     if (mPbufferDeviceContext == nullptr)
113     {
114         mFunctionsWGL->destroyPbufferARB(mPbuffer);
115         mPbuffer = nullptr;
116 
117         DWORD error = GetLastError();
118         return egl::EglBadAlloc() << "Failed to get the WGL pbuffer handle, "
119                                   << gl::FmtErr(HRESULT_CODE(error));
120     }
121 
122     return egl::NoError();
123 }
124 
makeCurrent(const gl::Context * context)125 egl::Error PbufferSurfaceWGL::makeCurrent(const gl::Context *context)
126 {
127     return egl::NoError();
128 }
129 
swap(const gl::Context * context)130 egl::Error PbufferSurfaceWGL::swap(const gl::Context *context)
131 {
132     return egl::NoError();
133 }
134 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)135 egl::Error PbufferSurfaceWGL::postSubBuffer(const gl::Context *context,
136                                             EGLint x,
137                                             EGLint y,
138                                             EGLint width,
139                                             EGLint height)
140 {
141     return egl::NoError();
142 }
143 
querySurfacePointerANGLE(EGLint attribute,void ** value)144 egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
145 {
146     *value = nullptr;
147     return egl::NoError();
148 }
149 
GetWGLBufferBindTarget(EGLint buffer)150 static int GetWGLBufferBindTarget(EGLint buffer)
151 {
152     switch (buffer)
153     {
154         case EGL_BACK_BUFFER:
155             return WGL_BACK_LEFT_ARB;
156         default:
157             UNREACHABLE();
158             return 0;
159     }
160 }
161 
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)162 egl::Error PbufferSurfaceWGL::bindTexImage(const gl::Context *context,
163                                            gl::Texture *texture,
164                                            EGLint buffer)
165 {
166     if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
167     {
168         DWORD error = GetLastError();
169         return egl::EglBadSurface()
170                << "Failed to bind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error));
171     }
172 
173     return egl::NoError();
174 }
175 
releaseTexImage(const gl::Context * context,EGLint buffer)176 egl::Error PbufferSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer)
177 {
178     if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
179     {
180         DWORD error = GetLastError();
181         return egl::EglBadSurface()
182                << "Failed to unbind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error));
183     }
184 
185     return egl::NoError();
186 }
187 
setSwapInterval(EGLint interval)188 void PbufferSurfaceWGL::setSwapInterval(EGLint interval) {}
189 
getWidth() const190 EGLint PbufferSurfaceWGL::getWidth() const
191 {
192     return mWidth;
193 }
194 
getHeight() const195 EGLint PbufferSurfaceWGL::getHeight() const
196 {
197     return mHeight;
198 }
199 
isPostSubBufferSupported() const200 EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const
201 {
202     return EGL_FALSE;
203 }
204 
getSwapBehavior() const205 EGLint PbufferSurfaceWGL::getSwapBehavior() const
206 {
207     return EGL_BUFFER_PRESERVED;
208 }
209 
getDC() const210 HDC PbufferSurfaceWGL::getDC() const
211 {
212     return mPbufferDeviceContext;
213 }
214 }  // namespace rx
215