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