1
2/*
3 * Copyright 2011 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 "gl/GLTestContext.h"
10
11#include <windows.h>
12#include <GL/GL.h>
13#include "win/SkWGL.h"
14
15#include <windows.h>
16
17namespace {
18
19class WinGLTestContext : public sk_gpu_test::GLTestContext {
20public:
21    WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
22    ~WinGLTestContext() override;
23
24private:
25    void destroyGLContext();
26
27    void onPlatformMakeCurrent() const override;
28    void onPlatformSwapBuffers() const override;
29    GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
30
31    HWND fWindow;
32    HDC fDeviceContext;
33    HGLRC fGlRenderContext;
34    static ATOM gWC;
35    SkWGLPbufferContext* fPbufferContext;
36};
37
38ATOM WinGLTestContext::gWC = 0;
39
40WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext)
41    : fWindow(nullptr)
42    , fDeviceContext(nullptr)
43    , fGlRenderContext(0)
44    , fPbufferContext(nullptr) {
45    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr);
46
47    if (!gWC) {
48        WNDCLASS wc;
49        wc.cbClsExtra = 0;
50        wc.cbWndExtra = 0;
51        wc.hbrBackground = nullptr;
52        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
53        wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
54        wc.hInstance = hInstance;
55        wc.lpfnWndProc = (WNDPROC) DefWindowProc;
56        wc.lpszClassName = TEXT("Griffin");
57        wc.lpszMenuName = nullptr;
58        wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
59
60        gWC = RegisterClass(&wc);
61        if (!gWC) {
62            SkDebugf("Could not register window class.\n");
63            return;
64        }
65    }
66
67    if (!(fWindow = CreateWindow(TEXT("Griffin"),
68                                 TEXT("The Invisible Man"),
69                                 WS_OVERLAPPEDWINDOW,
70                                 0, 0, 1, 1,
71                                 nullptr, nullptr,
72                                 hInstance, nullptr))) {
73        SkDebugf("Could not create window.\n");
74        return;
75    }
76
77    if (!(fDeviceContext = GetDC(fWindow))) {
78        SkDebugf("Could not get device context.\n");
79        this->destroyGLContext();
80        return;
81    }
82    // Requesting a Core profile would bar us from using NVPR. So we request
83    // compatibility profile or GL ES.
84    SkWGLContextRequest contextType =
85        kGLES_GrGLStandard == forcedGpuAPI ?
86        kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest;
87
88    HGLRC winShareContext = nullptr;
89    if (shareContext) {
90        winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC()
91                                                        : shareContext->fGlRenderContext;
92    }
93    fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType, winShareContext);
94
95    HDC dc;
96    HGLRC glrc;
97    if (nullptr == fPbufferContext) {
98        if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType,
99                                                    winShareContext))) {
100            SkDebugf("Could not create rendering context.\n");
101            this->destroyGLContext();
102            return;
103        }
104        dc = fDeviceContext;
105        glrc = fGlRenderContext;
106    } else {
107        ReleaseDC(fWindow, fDeviceContext);
108        fDeviceContext = 0;
109        DestroyWindow(fWindow);
110        fWindow = 0;
111
112        dc = fPbufferContext->getDC();
113        glrc = fPbufferContext->getGLRC();
114    }
115
116    if (!(wglMakeCurrent(dc, glrc))) {
117        SkDebugf("Could not set the context.\n");
118        this->destroyGLContext();
119        return;
120    }
121
122    sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
123    if (nullptr == gl.get()) {
124        SkDebugf("Could not create GL interface.\n");
125        this->destroyGLContext();
126        return;
127    }
128    if (!gl->validate()) {
129        SkDebugf("Could not validate GL interface.\n");
130        this->destroyGLContext();
131        return;
132    }
133
134    this->init(gl.release());
135}
136
137WinGLTestContext::~WinGLTestContext() {
138    this->teardown();
139    this->destroyGLContext();
140}
141
142void WinGLTestContext::destroyGLContext() {
143    SkSafeSetNull(fPbufferContext);
144    if (fGlRenderContext) {
145        wglDeleteContext(fGlRenderContext);
146        fGlRenderContext = 0;
147    }
148    if (fWindow && fDeviceContext) {
149        ReleaseDC(fWindow, fDeviceContext);
150        fDeviceContext = 0;
151    }
152    if (fWindow) {
153        DestroyWindow(fWindow);
154        fWindow = 0;
155    }
156}
157
158void WinGLTestContext::onPlatformMakeCurrent() const {
159    HDC dc;
160    HGLRC glrc;
161
162    if (nullptr == fPbufferContext) {
163        dc = fDeviceContext;
164        glrc = fGlRenderContext;
165    } else {
166        dc = fPbufferContext->getDC();
167        glrc = fPbufferContext->getGLRC();
168    }
169
170    if (!wglMakeCurrent(dc, glrc)) {
171        SkDebugf("Could not create rendering context.\n");
172    }
173}
174
175void WinGLTestContext::onPlatformSwapBuffers() const {
176    HDC dc;
177
178    if (nullptr == fPbufferContext) {
179        dc = fDeviceContext;
180    } else {
181        dc = fPbufferContext->getDC();
182    }
183    if (!SwapBuffers(dc)) {
184        SkDebugf("Could not complete SwapBuffers.\n");
185    }
186}
187
188GrGLFuncPtr WinGLTestContext::onPlatformGetProcAddress(const char* name) const {
189    return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
190}
191
192} // anonymous namespace
193
194namespace sk_gpu_test {
195GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
196                                           GLTestContext *shareContext) {
197    WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext);
198    WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext);
199    if (!ctx->isValid()) {
200        delete ctx;
201        return nullptr;
202    }
203    return ctx;
204}
205}  // namespace sk_gpu_test
206
207