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
GLWindowContext_xlib(const XlibWindowInfo & winInfo,const DisplayParams & params)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
onInitializeContext()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
~GLWindowContext_xlib()114 GLWindowContext_xlib::~GLWindowContext_xlib() {
115 this->destroyContext();
116 }
117
onDestroyContext()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
onSwapBuffers()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
NewGLForXlib(const XlibWindowInfo & winInfo,const DisplayParams & params)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