gfx/gl/GLContextProviderWGL.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:164646748d96
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "GLContextProvider.h"
7 #include "GLContextWGL.h"
8 #include "GLLibraryLoader.h"
9 #include "nsDebug.h"
10 #include "nsIWidget.h"
11 #include "gfxPlatform.h"
12 #include "gfxWindowsSurface.h"
13
14 #include "gfxCrashReporterUtils.h"
15
16 #include "prenv.h"
17
18 #include "mozilla/Preferences.h"
19
20 using namespace mozilla::gfx;
21
22 namespace mozilla {
23 namespace gl {
24
25 WGLLibrary sWGLLib;
26
27 HWND
28 WGLLibrary::CreateDummyWindow(HDC *aWindowDC)
29 {
30 WNDCLASSW wc;
31 if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) {
32 ZeroMemory(&wc, sizeof(WNDCLASSW));
33 wc.style = CS_OWNDC;
34 wc.hInstance = GetModuleHandle(nullptr);
35 wc.lpfnWndProc = DefWindowProc;
36 wc.lpszClassName = L"GLContextWGLClass";
37 if (!RegisterClassW(&wc)) {
38 NS_WARNING("Failed to register GLContextWGLClass?!");
39 // er. failed to register our class?
40 return nullptr;
41 }
42 }
43
44 HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0,
45 0, 0, 16, 16,
46 nullptr, nullptr, GetModuleHandle(nullptr),
47 nullptr);
48 NS_ENSURE_TRUE(win, nullptr);
49
50 HDC dc = GetDC(win);
51 NS_ENSURE_TRUE(dc, nullptr);
52
53 if (mWindowPixelFormat == 0) {
54 PIXELFORMATDESCRIPTOR pfd;
55 ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
56 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
57 pfd.nVersion = 1;
58 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
59 pfd.iPixelType = PFD_TYPE_RGBA;
60 pfd.cColorBits = 24;
61 pfd.cRedBits = 8;
62 pfd.cGreenBits = 8;
63 pfd.cBlueBits = 8;
64 pfd.cAlphaBits = 8;
65 pfd.cDepthBits = 0;
66 pfd.iLayerType = PFD_MAIN_PLANE;
67
68 mWindowPixelFormat = ChoosePixelFormat(dc, &pfd);
69 }
70
71 if (!mWindowPixelFormat ||
72 !SetPixelFormat(dc, mWindowPixelFormat, nullptr))
73 {
74 NS_WARNING("SetPixelFormat failed!");
75 DestroyWindow(win);
76 return nullptr;
77 }
78
79 if (aWindowDC) {
80 *aWindowDC = dc;
81 }
82
83 return win;
84 }
85
86 static inline bool
87 HasExtension(const char* aExtensions, const char* aRequiredExtension)
88 {
89 return GLContext::ListHasExtension(
90 reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
91 }
92
93 bool
94 WGLLibrary::EnsureInitialized()
95 {
96 if (mInitialized)
97 return true;
98
99 mozilla::ScopedGfxFeatureReporter reporter("WGL");
100
101 std::string libGLFilename = "Opengl32.dll";
102 // SU_SPIES_DIRECTORY is for AMD CodeXL/gDEBugger
103 if (PR_GetEnv("SU_SPIES_DIRECTORY")) {
104 libGLFilename = std::string(PR_GetEnv("SU_SPIES_DIRECTORY")) + "\\opengl32.dll";
105 }
106
107 if (!mOGLLibrary) {
108 mOGLLibrary = PR_LoadLibrary(&libGLFilename[0]);
109 if (!mOGLLibrary) {
110 NS_WARNING("Couldn't load OpenGL library.");
111 return false;
112 }
113 }
114
115 GLLibraryLoader::SymLoadStruct earlySymbols[] = {
116 { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", nullptr } },
117 { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", nullptr } },
118 { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", nullptr } },
119 { (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", nullptr } },
120 { (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", nullptr } },
121 { (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", nullptr } },
122 { (PRFuncPtr*) &fShareLists, { "wglShareLists", nullptr } },
123 { nullptr, { nullptr } }
124 };
125
126 if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) {
127 NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)");
128 return false;
129 }
130
131 // This is ridiculous -- we have to actually create a context to
132 // get the OpenGL ICD to load.
133 mWindow = CreateDummyWindow(&mWindowDC);
134 NS_ENSURE_TRUE(mWindow, false);
135
136 // create rendering context
137 mWindowGLContext = fCreateContext(mWindowDC);
138 NS_ENSURE_TRUE(mWindowGLContext, false);
139
140 HGLRC curCtx = fGetCurrentContext();
141 HDC curDC = fGetCurrentDC();
142
143 if (!fMakeCurrent((HDC)mWindowDC, (HGLRC)mWindowGLContext)) {
144 NS_WARNING("wglMakeCurrent failed");
145 return false;
146 }
147
148 // Now we can grab all the other symbols that we couldn't without having
149 // a context current.
150
151 GLLibraryLoader::SymLoadStruct pbufferSymbols[] = {
152 { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } },
153 { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } },
154 { (PRFuncPtr*) &fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", nullptr } },
155 { (PRFuncPtr*) &fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } },
156 { (PRFuncPtr*) &fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } },
157 { nullptr, { nullptr } }
158 };
159
160 GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = {
161 { (PRFuncPtr*) &fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", nullptr } },
162 { (PRFuncPtr*) &fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } },
163 { nullptr, { nullptr } }
164 };
165
166 if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0],
167 (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress))
168 {
169 // this isn't an error, just means that pbuffers aren't supported
170 fCreatePbuffer = nullptr;
171 }
172
173 if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0],
174 (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress))
175 {
176 // this isn't an error, just means that we don't have the pixel format extension
177 fChoosePixelFormat = nullptr;
178 }
179
180 GLLibraryLoader::SymLoadStruct extensionsSymbols[] = {
181 { (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", nullptr} },
182 { nullptr, { nullptr } }
183 };
184
185 GLLibraryLoader::SymLoadStruct robustnessSymbols[] = {
186 { (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", nullptr} },
187 { nullptr, { nullptr } }
188 };
189
190 if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0],
191 (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) {
192 const char *wglExts = fGetExtensionsString(mWindowDC);
193 if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) {
194 GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0],
195 (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress);
196 if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) {
197 mHasRobustness = true;
198 }
199 }
200 }
201
202 // reset back to the previous context, just in case
203 fMakeCurrent(curDC, curCtx);
204
205 if (mHasRobustness) {
206 fDeleteContext(mWindowGLContext);
207
208 int attribs[] = {
209 LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
210 LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
211 0
212 };
213
214 mWindowGLContext = fCreateContextAttribs(mWindowDC, nullptr, attribs);
215 if (!mWindowGLContext) {
216 mHasRobustness = false;
217 mWindowGLContext = fCreateContext(mWindowDC);
218 }
219 }
220
221 mInitialized = true;
222
223 // Call this to create the global GLContext instance,
224 // and to check for errors. Note that this must happen /after/
225 // setting mInitialized to TRUE, or an infinite loop results.
226 if (GLContextProviderWGL::GetGlobalContext() == nullptr) {
227 mInitialized = false;
228 return false;
229 }
230
231 reporter.SetSuccessful();
232 return true;
233 }
234
235 GLContextWGL::GLContextWGL(
236 const SurfaceCaps& caps,
237 GLContext* sharedContext,
238 bool isOffscreen,
239 HDC aDC,
240 HGLRC aContext,
241 HWND aWindow)
242 : GLContext(caps, sharedContext, isOffscreen),
243 mDC(aDC),
244 mContext(aContext),
245 mWnd(aWindow),
246 mPBuffer(nullptr),
247 mPixelFormat(0),
248 mIsDoubleBuffered(false)
249 {
250 // See 899855
251 SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
252 }
253
254 GLContextWGL::GLContextWGL(
255 const SurfaceCaps& caps,
256 GLContext* sharedContext,
257 bool isOffscreen,
258 HANDLE aPbuffer,
259 HDC aDC,
260 HGLRC aContext,
261 int aPixelFormat)
262 : GLContext(caps, sharedContext, isOffscreen),
263 mDC(aDC),
264 mContext(aContext),
265 mWnd(nullptr),
266 mPBuffer(aPbuffer),
267 mPixelFormat(aPixelFormat),
268 mIsDoubleBuffered(false)
269 {
270 // See 899855
271 SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
272 }
273
274 GLContextWGL::~GLContextWGL()
275 {
276 MarkDestroyed();
277
278 sWGLLib.fDeleteContext(mContext);
279
280 if (mPBuffer)
281 sWGLLib.fDestroyPbuffer(mPBuffer);
282 if (mWnd)
283 DestroyWindow(mWnd);
284 }
285
286 bool
287 GLContextWGL::Init()
288 {
289 if (!mDC || !mContext)
290 return false;
291
292 // see bug 929506 comment 29. wglGetProcAddress requires a current context.
293 if (!sWGLLib.fMakeCurrent(mDC, mContext))
294 return false;
295
296 SetupLookupFunction();
297 if (!InitWithPrefix("gl", true))
298 return false;
299
300 return true;
301 }
302
303 bool
304 GLContextWGL::MakeCurrentImpl(bool aForce)
305 {
306 BOOL succeeded = true;
307
308 // wglGetCurrentContext seems to just pull the HGLRC out
309 // of its TLS slot, so no need to do our own tls slot.
310 // You would think that wglMakeCurrent would avoid doing
311 // work if mContext was already current, but not so much..
312 if (aForce || sWGLLib.fGetCurrentContext() != mContext) {
313 succeeded = sWGLLib.fMakeCurrent(mDC, mContext);
314 NS_ASSERTION(succeeded, "Failed to make GL context current!");
315 }
316
317 return succeeded;
318 }
319
320 bool
321 GLContextWGL::IsCurrent()
322 {
323 return sWGLLib.fGetCurrentContext() == mContext;
324 }
325
326 void
327 GLContextWGL::SetIsDoubleBuffered(bool aIsDB)
328 {
329 mIsDoubleBuffered = aIsDB;
330 }
331
332 bool
333 GLContextWGL::IsDoubleBuffered() const
334 {
335 return mIsDoubleBuffered;
336 }
337
338 bool
339 GLContextWGL::SupportsRobustness() const
340 {
341 return sWGLLib.HasRobustness();
342 }
343
344 bool
345 GLContextWGL::SwapBuffers() {
346 if (!mIsDoubleBuffered)
347 return false;
348 return ::SwapBuffers(mDC);
349 }
350
351 bool
352 GLContextWGL::SetupLookupFunction()
353 {
354 // Make sure that we have a ref to the OGL library;
355 // when run under CodeXL, wglGetProcAddress won't return
356 // the right thing for some core functions.
357 MOZ_ASSERT(mLibrary == nullptr);
358
359 mLibrary = sWGLLib.GetOGLLibrary();
360 mLookupFunc = (PlatformLookupFunction)sWGLLib.fGetProcAddress;
361 return true;
362 }
363
364 static bool
365 GetMaxSize(HDC hDC, int format, gfxIntSize& size)
366 {
367 int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB};
368 int result[2];
369
370 // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues)
371 if (!sWGLLib.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result))
372 return false;
373
374 size.width = result[0];
375 size.height = result[1];
376 return true;
377 }
378
379 static bool
380 IsValidSizeForFormat(HDC hDC, int format,
381 const gfxIntSize& requested)
382 {
383 gfxIntSize max;
384 if (!GetMaxSize(hDC, format, max))
385 return true;
386
387 if (requested.width > max.width)
388 return false;
389 if (requested.height > max.height)
390 return false;
391
392 return true;
393 }
394
395 static GLContextWGL *
396 GetGlobalContextWGL()
397 {
398 return static_cast<GLContextWGL*>(GLContextProviderWGL::GetGlobalContext());
399 }
400
401 already_AddRefed<GLContext>
402 GLContextProviderWGL::CreateWrappingExisting(void*, void*)
403 {
404 return nullptr;
405 }
406
407 already_AddRefed<GLContext>
408 GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
409 {
410 if (!sWGLLib.EnsureInitialized()) {
411 return nullptr;
412 }
413
414 /**
415 * We need to make sure we call SetPixelFormat -after- calling
416 * EnsureInitialized, otherwise it can load/unload the dll and
417 * wglCreateContext will fail.
418 */
419
420 HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);
421
422 SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr);
423 HGLRC context;
424
425 GLContextWGL *shareContext = GetGlobalContextWGL();
426
427 if (sWGLLib.HasRobustness()) {
428 int attribs[] = {
429 LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
430 LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
431 0
432 };
433
434 context = sWGLLib.fCreateContextAttribs(dc,
435 shareContext ? shareContext->Context() : nullptr,
436 attribs);
437 } else {
438 context = sWGLLib.fCreateContext(dc);
439 if (context &&
440 shareContext &&
441 !sWGLLib.fShareLists(shareContext->Context(), context))
442 {
443 printf_stderr("WGL context creation failed for window: wglShareLists returned false!");
444 sWGLLib.fDeleteContext(context);
445 context = nullptr;
446 }
447 }
448
449 if (!context) {
450 return nullptr;
451 }
452
453 SurfaceCaps caps = SurfaceCaps::ForRGBA();
454 nsRefPtr<GLContextWGL> glContext = new GLContextWGL(caps,
455 shareContext,
456 false,
457 dc,
458 context);
459 if (!glContext->Init()) {
460 return nullptr;
461 }
462
463 glContext->SetIsDoubleBuffered(true);
464
465 return glContext.forget();
466 }
467
468 static already_AddRefed<GLContextWGL>
469 CreatePBufferOffscreenContext(const gfxIntSize& aSize,
470 GLContextWGL *aShareContext)
471 {
472 WGLLibrary& wgl = sWGLLib;
473
474 #define A1(_a,_x) do { _a.AppendElement(_x); } while(0)
475 #define A2(_a,_x,_y) do { _a.AppendElement(_x); _a.AppendElement(_y); } while(0)
476
477 nsTArray<int> attrs;
478
479 A2(attrs, LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE);
480 A2(attrs, LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE);
481 A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
482
483 A2(attrs, LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB);
484
485 A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE);
486 A2(attrs, LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE);
487
488 A1(attrs, 0);
489
490 nsTArray<int> pbattrs;
491 A1(pbattrs, 0);
492
493 #undef A1
494 #undef A2
495
496 // We only need one!
497 UINT numFormats = 1;
498 int formats[1];
499 HDC windowDC = wgl.GetWindowDC();
500 if (!wgl.fChoosePixelFormat(windowDC,
501 attrs.Elements(), nullptr,
502 numFormats, formats, &numFormats)
503 || numFormats == 0)
504 {
505 return nullptr;
506 }
507
508 // We don't care; just pick the first one.
509 int chosenFormat = formats[0];
510 if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize))
511 return nullptr;
512
513 HANDLE pbuffer = wgl.fCreatePbuffer(windowDC, chosenFormat,
514 aSize.width, aSize.height,
515 pbattrs.Elements());
516 if (!pbuffer) {
517 return nullptr;
518 }
519
520 HDC pbdc = wgl.fGetPbufferDC(pbuffer);
521 NS_ASSERTION(pbdc, "expected a dc");
522
523 HGLRC context;
524 if (wgl.HasRobustness()) {
525 int attribs[] = {
526 LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
527 LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
528 0
529 };
530
531 context = wgl.fCreateContextAttribs(pbdc, aShareContext->Context(), attribs);
532 } else {
533 context = wgl.fCreateContext(pbdc);
534 if (context && aShareContext) {
535 if (!wgl.fShareLists(aShareContext->Context(), context)) {
536 wgl.fDeleteContext(context);
537 context = nullptr;
538 printf_stderr("ERROR - creating pbuffer context failed because wglShareLists returned FALSE");
539 }
540 }
541 }
542
543 if (!context) {
544 wgl.fDestroyPbuffer(pbuffer);
545 return nullptr;
546 }
547
548 SurfaceCaps dummyCaps = SurfaceCaps::Any();
549 nsRefPtr<GLContextWGL> glContext = new GLContextWGL(dummyCaps,
550 aShareContext,
551 true,
552 pbuffer,
553 pbdc,
554 context,
555 chosenFormat);
556
557 return glContext.forget();
558 }
559
560 static already_AddRefed<GLContextWGL>
561 CreateWindowOffscreenContext()
562 {
563 // CreateWindowOffscreenContext must return a global-shared context
564 GLContextWGL *shareContext = GetGlobalContextWGL();
565 if (!shareContext) {
566 return nullptr;
567 }
568
569 HDC dc;
570 HWND win = sWGLLib.CreateDummyWindow(&dc);
571 if (!win) {
572 return nullptr;
573 }
574
575 HGLRC context = sWGLLib.fCreateContext(dc);
576 if (sWGLLib.HasRobustness()) {
577 int attribs[] = {
578 LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
579 LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
580 0
581 };
582
583 context = sWGLLib.fCreateContextAttribs(dc, shareContext->Context(), attribs);
584 } else {
585 context = sWGLLib.fCreateContext(dc);
586 if (context && shareContext &&
587 !sWGLLib.fShareLists(shareContext->Context(), context))
588 {
589 NS_WARNING("wglShareLists failed!");
590
591 sWGLLib.fDeleteContext(context);
592 DestroyWindow(win);
593 return nullptr;
594 }
595 }
596
597 if (!context) {
598 return nullptr;
599 }
600
601 SurfaceCaps caps = SurfaceCaps::ForRGBA();
602 nsRefPtr<GLContextWGL> glContext = new GLContextWGL(caps,
603 shareContext, true,
604 dc, context, win);
605
606 return glContext.forget();
607 }
608
609 already_AddRefed<GLContext>
610 GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
611 const SurfaceCaps& caps)
612 {
613 if (!sWGLLib.EnsureInitialized()) {
614 return nullptr;
615 }
616
617 nsRefPtr<GLContextWGL> glContext;
618
619 // Always try to create a pbuffer context first, because we
620 // want the context isolation.
621 if (sWGLLib.fCreatePbuffer &&
622 sWGLLib.fChoosePixelFormat)
623 {
624 gfxIntSize dummySize = gfxIntSize(16, 16);
625 glContext = CreatePBufferOffscreenContext(dummySize, GetGlobalContextWGL());
626 }
627
628 // If it failed, then create a window context and use a FBO.
629 if (!glContext) {
630 glContext = CreateWindowOffscreenContext();
631 }
632
633 if (!glContext ||
634 !glContext->Init())
635 {
636 return nullptr;
637 }
638
639 if (!glContext->InitOffscreen(ToIntSize(size), caps))
640 return nullptr;
641
642 return glContext.forget();
643 }
644
645 static nsRefPtr<GLContextWGL> gGlobalContext;
646
647 GLContext *
648 GLContextProviderWGL::GetGlobalContext()
649 {
650 if (!sWGLLib.EnsureInitialized()) {
651 return nullptr;
652 }
653
654 static bool triedToCreateContext = false;
655
656 if (!triedToCreateContext && !gGlobalContext) {
657 triedToCreateContext = true;
658
659 // conveniently, we already have what we need...
660 SurfaceCaps dummyCaps = SurfaceCaps::Any();
661 gGlobalContext = new GLContextWGL(dummyCaps,
662 nullptr, true,
663 sWGLLib.GetWindowDC(),
664 sWGLLib.GetWindowGLContext());
665 if (!gGlobalContext->Init()) {
666 NS_WARNING("Global context GLContext initialization failed?");
667 gGlobalContext = nullptr;
668 return nullptr;
669 }
670 }
671
672 return static_cast<GLContext*>(gGlobalContext);
673 }
674
675 void
676 GLContextProviderWGL::Shutdown()
677 {
678 gGlobalContext = nullptr;
679 }
680
681 } /* namespace gl */
682 } /* namespace mozilla */

mercurial