1 
2 /*
3  * Copyright 2015 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "WindowContextFactory_win.h"
10 #include <GL/gl.h>
11 
12  // windows stuff
13 #include "win/SkWGL.h"
14 
15 #include "../GLWindowContext.h"
16 
17 using sk_app::GLWindowContext;
18 using sk_app::DisplayParams;
19 
20 namespace {
21 
22 class GLWindowContext_win : public GLWindowContext {
23 public:
24     GLWindowContext_win(HWND, const DisplayParams&);
25     ~GLWindowContext_win() override;
26 
27 protected:
28     void onSwapBuffers() override;
29 
30     void onInitializeContext() override;
31     void onDestroyContext() override;
32 
33 private:
34     HWND              fHWND;
35     HGLRC             fHGLRC;
36 };
37 
GLWindowContext_win(HWND wnd,const DisplayParams & params)38 GLWindowContext_win::GLWindowContext_win(HWND wnd, const DisplayParams& params)
39     : GLWindowContext(params)
40     , fHWND(wnd)
41     , fHGLRC(NULL) {
42 
43     // any config code here (particularly for msaa)?
44 
45     this->initializeContext();
46 }
47 
~GLWindowContext_win()48 GLWindowContext_win::~GLWindowContext_win() {
49     this->destroyContext();
50 }
51 
onInitializeContext()52 void GLWindowContext_win::onInitializeContext() {
53     HDC dc = GetDC(fHWND);
54 
55     fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
56                                 kGLPreferCompatibilityProfile_SkWGLContextRequest);
57     if (NULL == fHGLRC) {
58         return;
59     }
60 
61     // Look to see if RenderDoc is attached. If so, re-create the context with a core profile
62     if (wglMakeCurrent(dc, fHGLRC)) {
63         const GrGLInterface* glInterface = GrGLCreateNativeInterface();
64         bool renderDocAttached = glInterface->hasExtension("GL_EXT_debug_tool");
65         SkSafeUnref(glInterface);
66         if (renderDocAttached) {
67             wglDeleteContext(fHGLRC);
68             fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, false /* deepColor */,
69                                         kGLPreferCoreProfile_SkWGLContextRequest);
70             if (NULL == fHGLRC) {
71                 return;
72             }
73         }
74     }
75 
76     if (wglMakeCurrent(dc, fHGLRC)) {
77         glClearStencil(0);
78         glClearColor(0, 0, 0, 0);
79         glStencilMask(0xffffffff);
80         glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
81 
82         // use DescribePixelFormat to get the stencil and color bit depth.
83         int pixelFormat = GetPixelFormat(dc);
84         PIXELFORMATDESCRIPTOR pfd;
85         DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
86         fStencilBits = pfd.cStencilBits;
87 
88         // Get sample count if the MSAA WGL extension is present
89         SkWGLExtensions extensions;
90         if (extensions.hasExtension(dc, "WGL_ARB_multisample")) {
91             static const int kSampleCountAttr = SK_WGL_SAMPLES;
92             extensions.getPixelFormatAttribiv(dc,
93                                               pixelFormat,
94                                               0,
95                                               1,
96                                               &kSampleCountAttr,
97                                               &fSampleCount);
98         } else {
99             fSampleCount = 0;
100         }
101 
102         RECT rect;
103         GetClientRect(fHWND, &rect);
104         fWidth = rect.right - rect.left;
105         fHeight = rect.bottom - rect.top;
106         glViewport(0, 0, fWidth, fHeight);
107     }
108 }
109 
110 
onDestroyContext()111 void GLWindowContext_win::onDestroyContext() {
112     wglDeleteContext(fHGLRC);
113     fHGLRC = NULL;
114 }
115 
116 
onSwapBuffers()117 void GLWindowContext_win::onSwapBuffers() {
118     HDC dc = GetDC((HWND)fHWND);
119     SwapBuffers(dc);
120     ReleaseDC((HWND)fHWND, dc);
121 }
122 
123 
124 }  // anonymous namespace
125 
126 namespace sk_app {
127 namespace window_context_factory {
128 
NewGLForWin(HWND wnd,const DisplayParams & params)129 WindowContext* NewGLForWin(HWND wnd, const DisplayParams& params) {
130     GLWindowContext_win* ctx = new GLWindowContext_win(wnd, params);
131     if (!ctx->isValid()) {
132         delete ctx;
133         return nullptr;
134     }
135     return ctx;
136 }
137 
138 }  // namespace window_context_factory
139 }  // namespace sk_app
140