Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GLWindowContext_unix.cpp
Go to the documentation of this file.
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
13
14#include <GL/gl.h>
15
19
20namespace {
21
22static bool gCtxErrorOccurred = false;
23static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
24 gCtxErrorOccurred = true;
25 return 0;
26}
27
28class GLWindowContext_xlib : public GLWindowContext {
29public:
30 GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
31 ~GLWindowContext_xlib() override;
32
33 void onDestroyContext() override;
34
35protected:
37 void onSwapBuffers() override;
38
39private:
40 GLWindowContext_xlib(void*, const DisplayParams&);
41
42 Display* fDisplay;
43 XWindow fWindow;
44 GLXFBConfig* fFBConfig;
45 XVisualInfo* fVisualInfo;
46 GLXContext fGLContext;
47};
48
49GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
51 , fDisplay(winInfo.fDisplay)
52 , fWindow(winInfo.fWindow)
53 , fFBConfig(winInfo.fFBConfig)
54 , fVisualInfo(winInfo.fVisualInfo)
55 , fGLContext() {
56 fWidth = winInfo.fWidth;
57 fHeight = winInfo.fHeight;
58 this->initializeContext();
59}
60
61using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
62
63sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
64 SkASSERT(fDisplay);
65 SkASSERT(!fGLContext);
67 bool current = false;
68
69 // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
70 // created with this rather than glXCreateContext.
71 CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB(
72 (const GLubyte*)"glXCreateContextAttribsARB");
73 if (createContextAttribs && fFBConfig) {
74 // Install Xlib error handler that will set gCtxErrorOccurred
75 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
76
77 // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features
78 // have been removed).
79 for (int minor = 2; minor >= 0 && !fGLContext; --minor) {
80 // Ganesh prefers a core profile which incidentally allows RenderDoc to work correctly.
81 for (int profile : {GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
82 GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB}) {
83 gCtxErrorOccurred = false;
84 int attribs[] = {
85 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor,
86 GLX_CONTEXT_PROFILE_MASK_ARB, profile,
87 0
88 };
89 fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs);
90
91 // Sync to ensure any errors generated are processed.
92 XSync(fDisplay, False);
93 if (gCtxErrorOccurred) { continue; }
94
95 if (fGLContext && profile == GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&
96 glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
97 current = true;
98 // Look to see if RenderDoc is attached. If so, re-create the context with a
99 // core profile.
100 interface = GrGLInterfaces::MakeGLX();
101 if (interface && interface->fExtensions.has("GL_EXT_debug_tool")) {
102 interface.reset();
103 glXMakeCurrent(fDisplay, None, nullptr);
104 glXDestroyContext(fDisplay, fGLContext);
105 current = false;
106 fGLContext = nullptr;
107 }
108 }
109 if (fGLContext) {
110 break;
111 }
112 }
113 }
114 // Restore the original error handler
115 XSetErrorHandler(oldHandler);
116 }
117 if (!fGLContext) {
118 fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
119 }
120 if (!fGLContext) {
121 return nullptr;
122 }
123
124 if (!current && !glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
125 return nullptr;
126 }
127
128 const char* glxExtensions = glXQueryExtensionsString(fDisplay, DefaultScreen(fDisplay));
129 if (glxExtensions) {
130 if (strstr(glxExtensions, "GLX_EXT_swap_control")) {
131 PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT =
132 (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB(
133 (const GLubyte*)"glXSwapIntervalEXT");
134 glXSwapIntervalEXT(fDisplay, fWindow, fDisplayParams.fDisableVsync ? 0 : 1);
135 }
136 }
137
138 glClearStencil(0);
139 glClearColor(0, 0, 0, 0);
140 glStencilMask(0xffffffff);
141 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
142
143 glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
144 glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
145 fSampleCount = std::max(fSampleCount, 1);
146
148 int x, y;
149 unsigned int border_width, depth;
150 XGetGeometry(fDisplay, fWindow, &root, &x, &y, (unsigned int*)&fWidth, (unsigned int*)&fHeight,
151 &border_width, &depth);
152 glViewport(0, 0, fWidth, fHeight);
153
154 return interface ? interface : GrGLInterfaces::MakeGLX();
155}
156
157GLWindowContext_xlib::~GLWindowContext_xlib() {
158 this->destroyContext();
159}
160
161void GLWindowContext_xlib::onDestroyContext() {
162 if (!fDisplay || !fGLContext) {
163 return;
164 }
165 glXMakeCurrent(fDisplay, None, nullptr);
166 glXDestroyContext(fDisplay, fGLContext);
167 fGLContext = nullptr;
168}
169
170void GLWindowContext_xlib::onSwapBuffers() {
171 if (fDisplay && fGLContext) {
172 glXSwapBuffers(fDisplay, fWindow);
173 }
174}
175
176} // anonymous namespace
177
178namespace skwindow {
179
180std::unique_ptr<WindowContext> MakeGLForXlib(const XlibWindowInfo& winInfo,
181 const DisplayParams& params) {
182 std::unique_ptr<WindowContext> ctx(new GLWindowContext_xlib(winInfo, params));
183 if (!ctx->isValid()) {
184 return nullptr;
185 }
186 return ctx;
187}
188
189} // namespace skwindow
#define SkASSERT(cond)
Definition SkAssert.h:116
Type::kYUV Type::kRGBA() int(0.7 *637)
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
virtual void onSwapBuffers()=0
virtual sk_sp< const GrGLInterface > onInitializeContext()=0
const EmbeddedViewParams * params
double y
double x
SK_API sk_sp< const GrGLInterface > MakeGLX()