Home | History | Annotate | Download | only in unix
      1 
      2 /*
      3  * Copyright 2016 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/gl.h>
     10 #include "../GLWindowContext.h"
     11 #include "WindowContextFactory_unix.h"
     12 #include "gl/GrGLInterface.h"
     13 
     14 using sk_app::window_context_factory::XlibWindowInfo;
     15 using sk_app::DisplayParams;
     16 using sk_app::GLWindowContext;
     17 
     18 namespace {
     19 
     20 class GLWindowContext_xlib : public GLWindowContext {
     21 public:
     22     GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
     23     ~GLWindowContext_xlib() override;
     24 
     25     void onSwapBuffers() override;
     26 
     27     void onDestroyContext() override;
     28 
     29 protected:
     30     sk_sp<const GrGLInterface> onInitializeContext() override;
     31 
     32 private:
     33     GLWindowContext_xlib(void*, const DisplayParams&);
     34 
     35     Display*     fDisplay;
     36     XWindow      fWindow;
     37     GLXFBConfig* fFBConfig;
     38     XVisualInfo* fVisualInfo;
     39     GLXContext   fGLContext;
     40 
     41     typedef GLWindowContext INHERITED;
     42 };
     43 
     44 GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
     45         : INHERITED(params)
     46         , fDisplay(winInfo.fDisplay)
     47         , fWindow(winInfo.fWindow)
     48         , fFBConfig(winInfo.fFBConfig)
     49         , fVisualInfo(winInfo.fVisualInfo)
     50         , fGLContext() {
     51     fWidth = winInfo.fWidth;
     52     fHeight = winInfo.fHeight;
     53     this->initializeContext();
     54 }
     55 
     56 using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
     57 
     58 sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
     59     SkASSERT(fDisplay);
     60     SkASSERT(!fGLContext);
     61     // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
     62     // created with this rather than glXCreateContext.
     63     CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB(
     64             (const GLubyte*)"glXCreateContextAttribsARB");
     65     if (createContextAttribs && fFBConfig) {
     66         // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features
     67         // have been removed).
     68         for (int minor = 2; minor >= 0 && !fGLContext; --minor) {
     69             // Ganesh prefers a compatibility profile for possible NVPR support. However, RenderDoc
     70             // requires a core profile. Edit this code to use RenderDoc.
     71             for (int profile : {GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
     72                                 GLX_CONTEXT_CORE_PROFILE_BIT_ARB}) {
     73                 int attribs[] = {
     74                         GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor,
     75                         GLX_CONTEXT_PROFILE_MASK_ARB, profile,
     76                         0
     77                 };
     78                 fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs);
     79                 if (fGLContext) {
     80                     break;
     81                 }
     82             }
     83         }
     84     }
     85     if (!fGLContext) {
     86         fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
     87     }
     88     if (!fGLContext) {
     89         return nullptr;
     90     }
     91 
     92     if (!glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
     93         return nullptr;
     94     }
     95     glClearStencil(0);
     96     glClearColor(0, 0, 0, 0);
     97     glStencilMask(0xffffffff);
     98     glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
     99 
    100     glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
    101     glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
    102     fSampleCount = SkTMax(fSampleCount, 1);
    103 
    104     XWindow root;
    105     int x, y;
    106     unsigned int border_width, depth;
    107     XGetGeometry(fDisplay, fWindow, &root, &x, &y, (unsigned int*)&fWidth, (unsigned int*)&fHeight,
    108                  &border_width, &depth);
    109     glViewport(0, 0, fWidth, fHeight);
    110 
    111     return GrGLMakeNativeInterface();
    112 }
    113 
    114 GLWindowContext_xlib::~GLWindowContext_xlib() {
    115     this->destroyContext();
    116 }
    117 
    118 void GLWindowContext_xlib::onDestroyContext() {
    119     if (!fDisplay || !fGLContext) {
    120         return;
    121     }
    122     glXMakeCurrent(fDisplay, None, nullptr);
    123     glXDestroyContext(fDisplay, fGLContext);
    124     fGLContext = nullptr;
    125 }
    126 
    127 void GLWindowContext_xlib::onSwapBuffers() {
    128     if (fDisplay && fGLContext) {
    129         glXSwapBuffers(fDisplay, fWindow);
    130     }
    131 }
    132 
    133 }  // anonymous namespace
    134 
    135 namespace sk_app {
    136 
    137 namespace window_context_factory {
    138 
    139 WindowContext* NewGLForXlib(const XlibWindowInfo& winInfo, const DisplayParams& params) {
    140     WindowContext* ctx = new GLWindowContext_xlib(winInfo, params);
    141     if (!ctx->isValid()) {
    142         delete ctx;
    143         return nullptr;
    144     }
    145     return ctx;
    146 }
    147 
    148 }  // namespace window_context_factory
    149 
    150 }  // namespace sk_app
    151