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 14using sk_app::window_context_factory::XlibWindowInfo; 15using sk_app::DisplayParams; 16using sk_app::GLWindowContext; 17 18namespace { 19 20class GLWindowContext_xlib : public GLWindowContext { 21public: 22 GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&); 23 ~GLWindowContext_xlib() override; 24 25 void onSwapBuffers() override; 26 27 void onDestroyContext() override; 28 29protected: 30 sk_sp<const GrGLInterface> onInitializeContext() override; 31 32private: 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 44GLWindowContext_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 56using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*); 57 58sk_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 114GLWindowContext_xlib::~GLWindowContext_xlib() { 115 this->destroyContext(); 116} 117 118void GLWindowContext_xlib::onDestroyContext() { 119 if (!fDisplay || !fGLContext) { 120 return; 121 } 122 glXMakeCurrent(fDisplay, None, nullptr); 123 glXDestroyContext(fDisplay, fGLContext); 124 fGLContext = nullptr; 125} 126 127void GLWindowContext_xlib::onSwapBuffers() { 128 if (fDisplay && fGLContext) { 129 glXSwapBuffers(fDisplay, fWindow); 130 } 131} 132 133} // anonymous namespace 134 135namespace sk_app { 136 137namespace window_context_factory { 138 139WindowContext* 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