Home | History | Annotate | Download | only in win
      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 <EGL/egl.h>
     10 #include <EGL/eglext.h>
     11 #include "../GLWindowContext.h"
     12 #include "WindowContextFactory_win.h"
     13 #include "gl/GrGLAssembleInterface.h"
     14 #include "gl/GrGLDefines.h"
     15 
     16 using sk_app::GLWindowContext;
     17 using sk_app::DisplayParams;
     18 
     19 namespace {
     20 
     21 EGLDisplay get_angle_egl_display(HDC hdc) {
     22     PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
     23     eglGetPlatformDisplayEXT =
     24             (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
     25 
     26     // We expect ANGLE to support this extension
     27     if (!eglGetPlatformDisplayEXT) {
     28         return EGL_NO_DISPLAY;
     29     }
     30 
     31     // We currently only support D3D11 ANGLE.
     32     static constexpr EGLint kType = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
     33     static constexpr EGLint attribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, kType, EGL_NONE};
     34     return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, hdc, attribs);
     35 }
     36 
     37 class ANGLEGLWindowContext_win : public GLWindowContext {
     38 public:
     39     ANGLEGLWindowContext_win(HWND, const DisplayParams&);
     40     ~ANGLEGLWindowContext_win() override;
     41 
     42 protected:
     43     void onSwapBuffers() override;
     44 
     45     sk_sp<const GrGLInterface> onInitializeContext() override;
     46     void onDestroyContext() override;
     47 
     48 private:
     49     HWND fHWND;
     50     EGLDisplay fDisplay = EGL_NO_DISPLAY;
     51     EGLContext fEGLContext = EGL_NO_CONTEXT;
     52     EGLSurface fEGLSurface = EGL_NO_SURFACE;
     53 
     54     typedef GLWindowContext INHERITED;
     55 };
     56 
     57 ANGLEGLWindowContext_win::ANGLEGLWindowContext_win(HWND wnd, const DisplayParams& params)
     58         : INHERITED(params), fHWND(wnd) {
     59     this->initializeContext();
     60 }
     61 
     62 ANGLEGLWindowContext_win::~ANGLEGLWindowContext_win() { this->destroyContext(); }
     63 
     64 sk_sp<const GrGLInterface> ANGLEGLWindowContext_win::onInitializeContext() {
     65     HDC dc = GetDC(fHWND);
     66     fDisplay = get_angle_egl_display(dc);
     67     if (EGL_NO_DISPLAY == fDisplay) {
     68         return nullptr;
     69     }
     70 
     71     EGLint majorVersion;
     72     EGLint minorVersion;
     73     if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
     74         SkDebugf("Could not initialize display!\n");
     75         return nullptr;
     76     }
     77     EGLint numConfigs;
     78     fSampleCount = this->getDisplayParams().fMSAASampleCount;
     79     const int sampleBuffers = fSampleCount > 1 ? 1 : 0;
     80     const int eglSampleCnt = fSampleCount > 1 ? fSampleCount : 0;
     81     const EGLint configAttribs[] = {EGL_RENDERABLE_TYPE,
     82                                     // We currently only support ES3.
     83                                     EGL_OPENGL_ES3_BIT,
     84                                     EGL_RED_SIZE,
     85                                     8,
     86                                     EGL_GREEN_SIZE,
     87                                     8,
     88                                     EGL_BLUE_SIZE,
     89                                     8,
     90                                     EGL_ALPHA_SIZE,
     91                                     8,
     92                                     EGL_SAMPLE_BUFFERS,
     93                                     sampleBuffers,
     94                                     EGL_SAMPLES,
     95                                     eglSampleCnt,
     96                                     EGL_NONE};
     97 
     98     EGLConfig surfaceConfig;
     99     if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
    100         SkDebugf("Could not create choose config!\n");
    101         return nullptr;
    102     }
    103     // We currently only support ES3.
    104     const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
    105     fEGLContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
    106     if (EGL_NO_CONTEXT == fEGLContext) {
    107         SkDebugf("Could not create context!\n");
    108         return nullptr;
    109     }
    110     fEGLSurface = eglCreateWindowSurface(fDisplay, surfaceConfig, fHWND, nullptr);
    111     if (EGL_NO_SURFACE == fEGLSurface) {
    112         SkDebugf("Could not create surface!\n");
    113         return nullptr;
    114     }
    115     if (!eglMakeCurrent(fDisplay, fEGLSurface, fEGLSurface, fEGLContext)) {
    116         SkDebugf("Could not make contxt current!\n");
    117         return nullptr;
    118     }
    119 
    120     sk_sp<const GrGLInterface> interface(GrGLMakeAssembledInterface(
    121             nullptr,
    122             [](void* ctx, const char name[]) -> GrGLFuncPtr { return eglGetProcAddress(name); }));
    123     if (interface) {
    124         interface->fFunctions.fClearStencil(0);
    125         interface->fFunctions.fClearColor(0, 0, 0, 0);
    126         interface->fFunctions.fStencilMask(0xffffffff);
    127         interface->fFunctions.fClear(GR_GL_STENCIL_BUFFER_BIT | GR_GL_COLOR_BUFFER_BIT);
    128 
    129         // use DescribePixelFormat to get the stencil depth.
    130         int pixelFormat = GetPixelFormat(dc);
    131         PIXELFORMATDESCRIPTOR pfd;
    132         DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
    133         fStencilBits = pfd.cStencilBits;
    134 
    135         RECT rect;
    136         GetClientRect(fHWND, &rect);
    137         fWidth = rect.right - rect.left;
    138         fHeight = rect.bottom - rect.top;
    139         interface->fFunctions.fViewport(0, 0, fWidth, fHeight);
    140     }
    141     return interface;
    142 }
    143 
    144 void ANGLEGLWindowContext_win::onDestroyContext() {
    145     eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    146     if (EGL_NO_CONTEXT != fEGLContext) {
    147         eglDestroyContext(fDisplay, fEGLContext);
    148     }
    149     if (EGL_NO_SURFACE != fEGLSurface) {
    150         eglDestroySurface(fDisplay, fEGLSurface);
    151     }
    152     if (EGL_NO_DISPLAY != fDisplay) {
    153         eglTerminate(fDisplay);
    154     }
    155 }
    156 
    157 void ANGLEGLWindowContext_win::onSwapBuffers() {
    158     if (!eglSwapBuffers(fDisplay, fEGLSurface)) {
    159         SkDebugf("Could not complete eglSwapBuffers.\n");
    160     }
    161 }
    162 
    163 }  // anonymous namespace
    164 
    165 namespace sk_app {
    166 namespace window_context_factory {
    167 
    168 WindowContext* NewANGLEForWin(HWND wnd, const DisplayParams& params) {
    169     ANGLEGLWindowContext_win* ctx = new ANGLEGLWindowContext_win(wnd, params);
    170     if (!ctx->isValid()) {
    171         delete ctx;
    172         return nullptr;
    173     }
    174     return ctx;
    175 }
    176 
    177 }  // namespace window_context_factory
    178 }  // namespace sk_app
    179