199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 299eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth/* 399eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth * Copyright 2016 Google Inc. 499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth * 599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth * Use of this source code is governed by a BSD-style license that can be 699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth * found in the LICENSE file. 799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth */ 899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 9d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon#include "../GLWindowContext.h" 10d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon#include "WindowContextFactory_unix.h" 1199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 1299eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth#include <GL/gl.h> 1399eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 14d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonusing sk_app::window_context_factory::XlibWindowInfo; 15d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonusing sk_app::DisplayParams; 16d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonusing sk_app::GLWindowContext; 1799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 18d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonnamespace { 1999eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 20d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonclass GLWindowContext_xlib : public GLWindowContext { 21d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonpublic: 22d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&); 23d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon ~GLWindowContext_xlib() override; 2499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 25d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon void onSwapBuffers() override; 2699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 27d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon void onDestroyContext() override; 2899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 29d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonprotected: 30d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon void onInitializeContext() override; 3199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 32d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonprivate: 33d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon GLWindowContext_xlib(void*, const DisplayParams&); 3499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 35d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon Display* fDisplay; 36d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon XWindow fWindow; 37837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon GLXFBConfig* fFBConfig; 38d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon XVisualInfo* fVisualInfo; 39d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon GLXContext fGLContext; 40fbdc080d3cae3695544ffbc05c6ff6f5b4514c02Jim Van Verth 41fbdc080d3cae3695544ffbc05c6ff6f5b4514c02Jim Van Verth typedef GLWindowContext INHERITED; 42d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon}; 4399eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 44d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonGLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params) 45fbdc080d3cae3695544ffbc05c6ff6f5b4514c02Jim Van Verth : INHERITED(params) 46d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon , fDisplay(winInfo.fDisplay) 47d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon , fWindow(winInfo.fWindow) 48837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon , fFBConfig(winInfo.fFBConfig) 49d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon , fVisualInfo(winInfo.fVisualInfo) 50d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon , fGLContext() { 51443ec1b794ec5ec8a155a9cdc641e95a95914533Christopher Dalton fWidth = winInfo.fWidth; 52443ec1b794ec5ec8a155a9cdc641e95a95914533Christopher Dalton fHeight = winInfo.fHeight; 53d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon this->initializeContext(); 54d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} 5599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 56837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomonusing CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*); 57837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon 58d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonvoid GLWindowContext_xlib::onInitializeContext() { 59d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon SkASSERT(fDisplay); 60837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon SkASSERT(!fGLContext); 61837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be 62837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // created with this rather than glXCreateContext. 63837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB( 64837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon (const GLubyte*)"glXCreateContextAttribsARB"); 65837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon if (createContextAttribs && fFBConfig) { 66837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features 67837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // have been removed). 68837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon for (int minor = 2; minor >= 0 && !fGLContext; --minor) { 69837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // Ganesh prefers a compatibility profile for possible NVPR support. However, RenderDoc 70837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon // requires a core profile. Edit this code to use RenderDoc. 71837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon for (int profile : {GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 72837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon GLX_CONTEXT_CORE_PROFILE_BIT_ARB}) { 73837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon int attribs[] = { 74837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor, 75837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon GLX_CONTEXT_PROFILE_MASK_ARB, profile, 76837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon 0 77837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon }; 78837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs); 79837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon if (fGLContext) { 80837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon break; 81837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon } 82837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon } 83837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon } 84837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon } 85837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon if (!fGLContext) { 86837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE); 87837fcb68ff5bddbd30f6994fa859a1d98745ccadBrian Salomon } 8899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth if (!fGLContext) { 8999eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth return; 9099eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth } 9199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 9299eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth if (glXMakeCurrent(fDisplay, fWindow, fGLContext)) { 9399eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glClearStencil(0); 9499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glClearColor(0, 0, 0, 0); 9599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glStencilMask(0xffffffff); 9699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 9799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 9899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits); 9999eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount); 10099eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 10199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth XWindow root; 10299eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth int x, y; 10399eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth unsigned int border_width, depth; 10499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth XGetGeometry(fDisplay, fWindow, &root, &x, &y, 105d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon (unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth); 10699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glViewport(0, 0, fWidth, fHeight); 10799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth } 10899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth} 10999eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 110d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonGLWindowContext_xlib::~GLWindowContext_xlib() { 111d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon this->destroyContext(); 112d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} 113d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon 114d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonvoid GLWindowContext_xlib::onDestroyContext() { 11599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth if (!fDisplay || !fGLContext) { 11699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth return; 11799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth } 11899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glXMakeCurrent(fDisplay, None, nullptr); 11999eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glXDestroyContext(fDisplay, fGLContext); 12099eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth fGLContext = nullptr; 12199eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth} 12299eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 123d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonvoid GLWindowContext_xlib::onSwapBuffers() { 12499eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth if (fDisplay && fGLContext) { 12599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth glXSwapBuffers(fDisplay, fWindow); 12699eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth } 12799eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth} 12899eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 129d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} // anonymous namespace 130d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon 131d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonnamespace sk_app { 132d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon 133d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonnamespace window_context_factory { 134d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon 135d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomonWindowContext* NewGLForXlib(const XlibWindowInfo& winInfo, const DisplayParams& params) { 136d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon WindowContext* ctx = new GLWindowContext_xlib(winInfo, params); 137d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon if (!ctx->isValid()) { 138d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon delete ctx; 139d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon return nullptr; 140d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon } 141d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon return ctx; 142d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} 143d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon 144d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} // namespace window_context_factory 14599eb6e2d5abab2cb74e3d413fc99d5cbbfac8765jvanverth 146d1bdd1fcbd308afb9903f39d231742f5c951cf07bsalomon} // namespace sk_app 147