1 //
2 // Copyright 2019 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 // entry_points_wgl.cpp: Implements the exported WGL functions.
7
8 #include "entry_points_wgl.h"
9
10 #include "common/angle_version.h"
11 #include "common/debug.h"
12 #include "common/event_tracer.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/EGLSync.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/Texture.h"
19 #include "libANGLE/Thread.h"
20 #include "libANGLE/entry_points_utils.h"
21 #include "libANGLE/queryutils.h"
22 #include "libANGLE/validationEGL.h"
23 #include "libGL/proc_table_wgl.h"
24 #include "libGLESv2/global_state.h"
25
26 using namespace wgl;
27 using namespace egl;
28
29 namespace
30 {
31
CompareProc(const ProcEntry & a,const char * b)32 bool CompareProc(const ProcEntry &a, const char *b)
33 {
34 return strcmp(a.first, b) < 0;
35 }
36
ClipConfigs(const std::vector<const Config * > & filteredConfigs,EGLConfig * output_configs,EGLint config_size,EGLint * num_config)37 void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
38 EGLConfig *output_configs,
39 EGLint config_size,
40 EGLint *num_config)
41 {
42 EGLint result_size = static_cast<EGLint>(filteredConfigs.size());
43 if (output_configs)
44 {
45 result_size = std::max(std::min(result_size, config_size), 0);
46 for (EGLint i = 0; i < result_size; i++)
47 {
48 output_configs[i] = const_cast<Config *>(filteredConfigs[i]);
49 }
50 }
51 *num_config = result_size;
52 }
53 } // anonymous namespace
54
55 #define WGL_EVENT(EP, FMT, ...) EVENT(nullptr, WGL##EP, FMT, __VA_ARGS__)
56
57 extern "C" {
58
59 // WGL 1.0
wglChoosePixelFormat(HDC hDc,const PIXELFORMATDESCRIPTOR * pPfd)60 int GL_APIENTRY wglChoosePixelFormat(HDC hDc, const PIXELFORMATDESCRIPTOR *pPfd)
61 {
62 UNIMPLEMENTED();
63 return 1;
64 }
65
wglDescribePixelFormat(HDC hdc,int ipfd,UINT cjpfd,PIXELFORMATDESCRIPTOR * ppfd)66 int GL_APIENTRY wglDescribePixelFormat(HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd)
67 {
68 UNIMPLEMENTED();
69 if (ppfd)
70 {
71 ppfd->dwFlags = ppfd->dwFlags | PFD_DRAW_TO_WINDOW;
72 ppfd->dwFlags = ppfd->dwFlags | PFD_SUPPORT_OPENGL;
73 ppfd->dwFlags = ppfd->dwFlags | PFD_GENERIC_ACCELERATED;
74 ppfd->dwFlags = ppfd->dwFlags | PFD_DOUBLEBUFFER;
75 ppfd->iPixelType = PFD_TYPE_RGBA;
76 ppfd->cColorBits = 24;
77 ppfd->cRedBits = 8;
78 ppfd->cGreenBits = 8;
79 ppfd->cBlueBits = 8;
80 ppfd->cAlphaBits = 8;
81 ppfd->cDepthBits = 24;
82 ppfd->cStencilBits = 8;
83 ppfd->nVersion = 1;
84 }
85 return 1;
86 }
87
wglGetEnhMetaFilePixelFormat(HENHMETAFILE hemf,UINT cbBuffer,PIXELFORMATDESCRIPTOR * ppfd)88 UINT GL_APIENTRY wglGetEnhMetaFilePixelFormat(HENHMETAFILE hemf,
89 UINT cbBuffer,
90 PIXELFORMATDESCRIPTOR *ppfd)
91 {
92 UNIMPLEMENTED();
93 return 1u;
94 }
95
wglGetPixelFormat(HDC hdc)96 int GL_APIENTRY wglGetPixelFormat(HDC hdc)
97 {
98 UNIMPLEMENTED();
99 return 1;
100 }
101
wglSetPixelFormat(HDC hdc,int ipfd,const PIXELFORMATDESCRIPTOR * ppfd)102 BOOL GL_APIENTRY wglSetPixelFormat(HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *ppfd)
103 {
104 UNIMPLEMENTED();
105 return TRUE;
106 }
107
wglSwapBuffers(HDC hdc)108 BOOL GL_APIENTRY wglSwapBuffers(HDC hdc)
109 {
110 Thread *thread = egl::GetCurrentThread();
111 egl::Display *display = egl::Display::GetExistingDisplayFromNativeDisplay(hdc);
112
113 ANGLE_EGL_TRY_RETURN(thread, display->getWGLSurface()->swap(thread->getContext()),
114 "wglSwapBuffers", display->getWGLSurface(), FALSE);
115 return TRUE;
116 }
117
wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)118 BOOL GL_APIENTRY wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
119 {
120 UNIMPLEMENTED();
121 return TRUE;
122 }
123
wglCreateContext(HDC hDc)124 HGLRC GL_APIENTRY wglCreateContext(HDC hDc)
125 {
126 Thread *thread = egl::GetCurrentThread();
127
128 std::vector<EGLAttrib> displayAttributes;
129 displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
130 GLenum platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
131 displayAttributes.push_back(platformType);
132 displayAttributes.push_back(EGL_NONE);
133
134 const auto &attribMapDisplay = AttributeMap::CreateFromAttribArray(displayAttributes.data());
135
136 egl::Display *display = egl::Display::GetDisplayFromNativeDisplay(hDc, attribMapDisplay);
137
138 ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "wglCreateContext", display, nullptr);
139
140 thread->setAPI(EGL_OPENGL_API);
141
142 // Default config
143 const EGLint configAttributes[] = {EGL_NONE};
144
145 // Choose config
146 EGLint configCount;
147 EGLConfig config;
148 AttributeMap attribMapConfig = AttributeMap::CreateFromIntArray(configAttributes);
149 ClipConfigs(display->chooseConfig(attribMapConfig), &config, 1, &configCount);
150
151 Config *configuration = static_cast<Config *>(config);
152
153 // Initialize surface
154 std::vector<EGLint> surfaceAttributes;
155 surfaceAttributes.push_back(EGL_NONE);
156 surfaceAttributes.push_back(EGL_NONE);
157 AttributeMap surfAttributes = AttributeMap::CreateFromIntArray(&surfaceAttributes[0]);
158
159 // Create first window surface
160 egl::Surface *surface = nullptr;
161 ANGLE_EGL_TRY_RETURN(
162 thread,
163 display->createWindowSurface(configuration, WindowFromDC(hDc), surfAttributes, &surface),
164 "wglCreateContext", display, nullptr);
165
166 // Initialize context
167 EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, 4, EGL_CONTEXT_MINOR_VERSION, 6,
168 EGL_NONE};
169
170 gl::Context *sharedGLContext = static_cast<gl::Context *>(nullptr);
171 AttributeMap ctxAttributes = AttributeMap::CreateFromIntArray(contextAttibutes);
172
173 gl::Context *context = nullptr;
174
175 ANGLE_EGL_TRY_RETURN(thread,
176 display->createContext(configuration, sharedGLContext, EGL_OPENGL_API,
177 ctxAttributes, &context),
178 "wglCreateContext", display, nullptr);
179
180 return reinterpret_cast<HGLRC>(context);
181 }
182
wglCreateLayerContext(HDC hDc,int level)183 HGLRC GL_APIENTRY wglCreateLayerContext(HDC hDc, int level)
184 {
185 UNIMPLEMENTED();
186 return nullptr;
187 }
188
wglDeleteContext(HGLRC oldContext)189 BOOL GL_APIENTRY wglDeleteContext(HGLRC oldContext)
190 {
191 UNIMPLEMENTED();
192 return FALSE;
193 }
194
wglDescribeLayerPlane(HDC hDc,int pixelFormat,int layerPlane,UINT nBytes,LAYERPLANEDESCRIPTOR * plpd)195 BOOL GL_APIENTRY wglDescribeLayerPlane(HDC hDc,
196 int pixelFormat,
197 int layerPlane,
198 UINT nBytes,
199 LAYERPLANEDESCRIPTOR *plpd)
200 {
201 UNIMPLEMENTED();
202 return FALSE;
203 }
204
wglGetCurrentContext()205 HGLRC GL_APIENTRY wglGetCurrentContext()
206 {
207 UNIMPLEMENTED();
208 return nullptr;
209 }
210
wglGetCurrentDC()211 HDC GL_APIENTRY wglGetCurrentDC()
212 {
213 UNIMPLEMENTED();
214 return nullptr;
215 }
216
217 int GL_APIENTRY
wglGetLayerPaletteEntries(HDC hdc,int iLayerPlane,int iStart,int cEntries,COLORREF * pcr)218 wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr)
219 {
220 UNIMPLEMENTED();
221 return 0;
222 }
223
wglGetProcAddress(LPCSTR lpszProc)224 PROC GL_APIENTRY wglGetProcAddress(LPCSTR lpszProc)
225 {
226 ANGLE_SCOPED_GLOBAL_LOCK();
227 WGL_EVENT(GetProcAddress, "const char *procname = \"%s\"", lpszProc);
228 egl::Thread *thread = egl::GetCurrentThread();
229
230 const ProcEntry *entry =
231 std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], lpszProc, CompareProc);
232
233 thread->setSuccess();
234
235 if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, lpszProc) != 0)
236 {
237 return nullptr;
238 }
239
240 return entry->second;
241 }
242
wglMakeCurrent(HDC hDc,HGLRC newContext)243 BOOL GL_APIENTRY wglMakeCurrent(HDC hDc, HGLRC newContext)
244 {
245 Thread *thread = egl::GetCurrentThread();
246 egl::Display *display = egl::Display::GetExistingDisplayFromNativeDisplay(hDc);
247 const gl::Context *context =
248 GetContextIfValid(display, reinterpret_cast<gl::Context *>(newContext));
249
250 ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
251
252 // If display or context are invalid, make thread's current rendering context not current
253 if (!context)
254 {
255 gl::Context *oldContext = thread->getContext();
256 if (oldContext)
257 {
258 ANGLE_EGL_TRY_RETURN(thread, oldContext->unMakeCurrent(display), "wglMakeCurrent",
259 GetContextIfValid(display, oldContext), EGL_FALSE);
260 thread->setCurrent(nullptr);
261 }
262 return TRUE;
263 }
264
265 egl::Surface *surface = display->getWGLSurface();
266 Surface *previousDraw = thread->getCurrentDrawSurface();
267 Surface *previousRead = thread->getCurrentReadSurface();
268 gl::Context *previousContext = thread->getContext();
269
270 if (previousDraw != surface || previousRead != surface || previousContext != context)
271 {
272 ANGLE_EGL_TRY_RETURN(thread,
273 display->makeCurrent(thread, previousContext, surface, surface,
274 const_cast<gl::Context *>(context)),
275 "wglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
276 }
277
278 return TRUE;
279 }
280
wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)281 BOOL GL_APIENTRY wglRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize)
282 {
283 UNIMPLEMENTED();
284 return FALSE;
285 }
286
287 int GL_APIENTRY
wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane,int iStart,int cEntries,const COLORREF * pcr)288 wglSetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, const COLORREF *pcr)
289 {
290 UNIMPLEMENTED();
291 return 0;
292 }
293
wglShareLists(HGLRC hrcSrvShare,HGLRC hrcSrvSource)294 BOOL GL_APIENTRY wglShareLists(HGLRC hrcSrvShare, HGLRC hrcSrvSource)
295 {
296 UNIMPLEMENTED();
297 return FALSE;
298 }
299
wglSwapLayerBuffers(HDC hdc,UINT fuFlags)300 BOOL GL_APIENTRY wglSwapLayerBuffers(HDC hdc, UINT fuFlags)
301 {
302 UNIMPLEMENTED();
303 return FALSE;
304 }
305
wglUseFontBitmapsA(HDC hDC,DWORD first,DWORD count,DWORD listBase)306 BOOL GL_APIENTRY wglUseFontBitmapsA(HDC hDC, DWORD first, DWORD count, DWORD listBase)
307 {
308 UNIMPLEMENTED();
309 return FALSE;
310 }
311
wglUseFontBitmapsW(HDC hDC,DWORD first,DWORD count,DWORD listBase)312 BOOL GL_APIENTRY wglUseFontBitmapsW(HDC hDC, DWORD first, DWORD count, DWORD listBase)
313 {
314 UNIMPLEMENTED();
315 return FALSE;
316 }
317
wglUseFontOutlinesA(HDC hDC,DWORD first,DWORD count,DWORD listBase,FLOAT deviation,FLOAT extrusion,int format,LPGLYPHMETRICSFLOAT lpgmf)318 BOOL GL_APIENTRY wglUseFontOutlinesA(HDC hDC,
319 DWORD first,
320 DWORD count,
321 DWORD listBase,
322 FLOAT deviation,
323 FLOAT extrusion,
324 int format,
325 LPGLYPHMETRICSFLOAT lpgmf)
326 {
327 UNIMPLEMENTED();
328 return FALSE;
329 }
330
wglUseFontOutlinesW(HDC hDC,DWORD first,DWORD count,DWORD listBase,FLOAT deviation,FLOAT extrusion,int format,LPGLYPHMETRICSFLOAT lpgmf)331 BOOL GL_APIENTRY wglUseFontOutlinesW(HDC hDC,
332 DWORD first,
333 DWORD count,
334 DWORD listBase,
335 FLOAT deviation,
336 FLOAT extrusion,
337 int format,
338 LPGLYPHMETRICSFLOAT lpgmf)
339 {
340 UNIMPLEMENTED();
341 return FALSE;
342 }
343
344 } // extern "C"
345