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