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