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