• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // WGLWindow:
7 //   Implements initializing a WGL rendering context.
8 //
9 
10 #include "util/windows/WGLWindow.h"
11 
12 #include "common/string_utils.h"
13 #include "common/system_utils.h"
14 #include "util/OSWindow.h"
15 
16 #include <iostream>
17 
18 namespace
19 {
GetDefaultPixelFormatDescriptor()20 PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor()
21 {
22     PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {};
23     pixelFormatDescriptor.nSize                 = sizeof(pixelFormatDescriptor);
24     pixelFormatDescriptor.nVersion              = 1;
25     pixelFormatDescriptor.dwFlags =
26         PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
27     pixelFormatDescriptor.iPixelType   = PFD_TYPE_RGBA;
28     pixelFormatDescriptor.cColorBits   = 24;
29     pixelFormatDescriptor.cAlphaBits   = 8;
30     pixelFormatDescriptor.cDepthBits   = 24;
31     pixelFormatDescriptor.cStencilBits = 8;
32     pixelFormatDescriptor.iLayerType   = PFD_MAIN_PLANE;
33 
34     return pixelFormatDescriptor;
35 }
36 
37 PFNWGLGETPROCADDRESSPROC gCurrentWGLGetProcAddress = nullptr;
38 HMODULE gCurrentModule                             = nullptr;
39 
GetProcAddressWithFallback(const char * name)40 angle::GenericProc WINAPI GetProcAddressWithFallback(const char *name)
41 {
42     angle::GenericProc proc = reinterpret_cast<angle::GenericProc>(gCurrentWGLGetProcAddress(name));
43     if (proc)
44     {
45         return proc;
46     }
47 
48     return reinterpret_cast<angle::GenericProc>(GetProcAddress(gCurrentModule, name));
49 }
50 
HasExtension(const std::vector<std::string> & extensions,const char * ext)51 bool HasExtension(const std::vector<std::string> &extensions, const char *ext)
52 {
53     return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
54 }
55 
DumpLastWindowsError()56 void DumpLastWindowsError()
57 {
58     std::cerr << "Last Windows error code: 0x" << std::hex << GetLastError() << std::endl;
59 }
60 }  // namespace
61 
WGLWindow(int glesMajorVersion,int glesMinorVersion)62 WGLWindow::WGLWindow(int glesMajorVersion, int glesMinorVersion)
63     : GLWindowBase(glesMajorVersion, glesMinorVersion),
64       mDeviceContext(nullptr),
65       mWGLContext(nullptr),
66       mWindow(nullptr)
67 {}
68 
~WGLWindow()69 WGLWindow::~WGLWindow() {}
70 
71 // Internally initializes GL resources.
initializeGL(OSWindow * osWindow,angle::Library * glWindowingLibrary,angle::GLESDriverType driverType,const EGLPlatformParameters & platformParams,const ConfigParameters & configParams)72 bool WGLWindow::initializeGL(OSWindow *osWindow,
73                              angle::Library *glWindowingLibrary,
74                              angle::GLESDriverType driverType,
75                              const EGLPlatformParameters &platformParams,
76                              const ConfigParameters &configParams)
77 {
78     if (driverType != angle::GLESDriverType::SystemWGL)
79     {
80         return false;
81     }
82 
83     glWindowingLibrary->getAs("wglGetProcAddress", &gCurrentWGLGetProcAddress);
84 
85     if (!gCurrentWGLGetProcAddress)
86     {
87         std::cerr << "Error loading wglGetProcAddress." << std::endl;
88         return false;
89     }
90 
91     gCurrentModule = reinterpret_cast<HMODULE>(glWindowingLibrary->getNative());
92     angle::LoadWGL(GetProcAddressWithFallback);
93 
94     mWindow                                           = osWindow->getNativeWindow();
95     mDeviceContext                                    = GetDC(mWindow);
96     const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = GetDefaultPixelFormatDescriptor();
97 
98     int pixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
99     if (pixelFormat == 0)
100     {
101         std::cerr << "Could not find a compatible pixel format." << std::endl;
102         DumpLastWindowsError();
103         return false;
104     }
105 
106     // According to the Windows docs, it is an error to set a pixel format twice.
107     int currentPixelFormat = GetPixelFormat(mDeviceContext);
108     if (currentPixelFormat != pixelFormat)
109     {
110         if (SetPixelFormat(mDeviceContext, pixelFormat, &pixelFormatDescriptor) != TRUE)
111         {
112             std::cerr << "Failed to set the pixel format." << std::endl;
113             DumpLastWindowsError();
114             return false;
115         }
116     }
117 
118     mWGLContext = _wglCreateContext(mDeviceContext);
119     if (!mWGLContext)
120     {
121         std::cerr << "Failed to create a WGL context." << std::endl;
122         return false;
123     }
124 
125     if (!makeCurrent())
126     {
127         return false;
128     }
129 
130     // Reload entry points to capture extensions.
131     angle::LoadWGL(GetProcAddressWithFallback);
132 
133     if (!_wglGetExtensionsStringARB)
134     {
135         std::cerr << "Driver does not expose wglGetExtensionsStringARB." << std::endl;
136         return false;
137     }
138 
139     const char *extensionsString = _wglGetExtensionsStringARB(mDeviceContext);
140 
141     std::vector<std::string> extensions;
142     angle::SplitStringAlongWhitespace(extensionsString, &extensions);
143 
144     if (!HasExtension(extensions, "WGL_EXT_create_context_es2_profile"))
145     {
146         std::cerr << "Driver does not expose WGL_EXT_create_context_es2_profile." << std::endl;
147         return false;
148     }
149 
150     if (configParams.webGLCompatibility.valid() || configParams.robustResourceInit.valid())
151     {
152         std::cerr << "WGLWindow does not support the requested feature set." << std::endl;
153         return false;
154     }
155 
156     // Tear down the context and create another with ES2 compatibility.
157     _wglDeleteContext(mWGLContext);
158 
159     // This could be extended to cover ES1 compatiblity.
160     int kCreateAttribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB,
161                             mClientMajorVersion,
162                             WGL_CONTEXT_MINOR_VERSION_ARB,
163                             mClientMinorVersion,
164                             WGL_CONTEXT_PROFILE_MASK_ARB,
165                             WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
166                             0,
167                             0};
168 
169     mWGLContext = _wglCreateContextAttribsARB(mDeviceContext, nullptr, kCreateAttribs);
170     if (!mWGLContext)
171     {
172         std::cerr << "Failed to create an ES2 compatible WGL context." << std::endl;
173         return false;
174     }
175 
176     if (!makeCurrent())
177     {
178         return false;
179     }
180 
181     mPlatform     = platformParams;
182     mConfigParams = configParams;
183 
184     angle::LoadGLES(GetProcAddressWithFallback);
185     return true;
186 }
187 
destroyGL()188 void WGLWindow::destroyGL()
189 {
190     if (mWGLContext)
191     {
192         _wglDeleteContext(mWGLContext);
193         mWGLContext = nullptr;
194     }
195 
196     if (mDeviceContext)
197     {
198         ReleaseDC(mWindow, mDeviceContext);
199         mDeviceContext = nullptr;
200     }
201 }
202 
isGLInitialized() const203 bool WGLWindow::isGLInitialized() const
204 {
205     return mWGLContext != nullptr;
206 }
207 
makeCurrent()208 bool WGLWindow::makeCurrent()
209 {
210     if (_wglMakeCurrent(mDeviceContext, mWGLContext) == FALSE)
211     {
212         std::cerr << "Error during wglMakeCurrent.\n";
213         return false;
214     }
215 
216     return true;
217 }
218 
setSwapInterval(EGLint swapInterval)219 bool WGLWindow::setSwapInterval(EGLint swapInterval)
220 {
221     if (!_wglSwapIntervalEXT || _wglSwapIntervalEXT(swapInterval) == FALSE)
222     {
223         std::cerr << "Error during wglSwapIntervalEXT.\n";
224         return false;
225     }
226     return true;
227 }
228 
swap()229 void WGLWindow::swap()
230 {
231     if (SwapBuffers(mDeviceContext) == FALSE)
232     {
233         std::cerr << "Error during SwapBuffers.\n";
234     }
235 }
236 
hasError() const237 bool WGLWindow::hasError() const
238 {
239     return GetLastError() != S_OK;
240 }
241 
242 // static
New(int glesMajorVersion,int glesMinorVersion)243 WGLWindow *WGLWindow::New(int glesMajorVersion, int glesMinorVersion)
244 {
245     return new WGLWindow(glesMajorVersion, glesMinorVersion);
246 }
247 
248 // static
Delete(WGLWindow ** window)249 void WGLWindow::Delete(WGLWindow **window)
250 {
251     delete *window;
252     *window = nullptr;
253 }
254