1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/private/SkOnce.h"
9cb93a386Sopenharmony_ci#include "tools/gpu/gl/GLTestContext.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include <X11/Xlib.h>
12cb93a386Sopenharmony_ci#include <GL/glx.h>
13cb93a386Sopenharmony_ci#include <GL/glu.h>
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#include <vector>
16cb93a386Sopenharmony_ci#include <utility>
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cinamespace {
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci/* Note: Skia requires glx 1.3 or newer */
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci/* This struct is taken from a mesa demo.  Please update as required */
23cb93a386Sopenharmony_cistatic const std::vector<std::pair<int, int>> gl_versions = {
24cb93a386Sopenharmony_ci   {1, 0},
25cb93a386Sopenharmony_ci   {1, 1},
26cb93a386Sopenharmony_ci   {1, 2},
27cb93a386Sopenharmony_ci   {1, 3},
28cb93a386Sopenharmony_ci   {1, 4},
29cb93a386Sopenharmony_ci   {1, 5},
30cb93a386Sopenharmony_ci   {2, 0},
31cb93a386Sopenharmony_ci   {2, 1},
32cb93a386Sopenharmony_ci   {3, 0},
33cb93a386Sopenharmony_ci   {3, 1},
34cb93a386Sopenharmony_ci   {3, 2},
35cb93a386Sopenharmony_ci   {3, 3},
36cb93a386Sopenharmony_ci   {4, 0},
37cb93a386Sopenharmony_ci   {4, 1},
38cb93a386Sopenharmony_ci   {4, 2},
39cb93a386Sopenharmony_ci   {4, 3},
40cb93a386Sopenharmony_ci   {4, 4},
41cb93a386Sopenharmony_ci};
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_cistatic const std::vector<std::pair<int, int>> gles_versions = {
44cb93a386Sopenharmony_ci    {2, 0},
45cb93a386Sopenharmony_ci    {3, 0},
46cb93a386Sopenharmony_ci};
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_cistatic bool ctxErrorOccurred = false;
49cb93a386Sopenharmony_cistatic int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
50cb93a386Sopenharmony_ci    ctxErrorOccurred = true;
51cb93a386Sopenharmony_ci    return 0;
52cb93a386Sopenharmony_ci}
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ciclass GLXGLTestContext : public sk_gpu_test::GLTestContext {
55cb93a386Sopenharmony_cipublic:
56cb93a386Sopenharmony_ci    GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareList);
57cb93a386Sopenharmony_ci    ~GLXGLTestContext() override;
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ciprivate:
60cb93a386Sopenharmony_ci    void destroyGLContext();
61cb93a386Sopenharmony_ci    static GLXContext CreateBestContext(bool isES, Display* display, GLXFBConfig bestFbc,
62cb93a386Sopenharmony_ci                                        GLXContext glxSharedContext);
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    void onPlatformMakeNotCurrent() const override;
65cb93a386Sopenharmony_ci    void onPlatformMakeCurrent() const override;
66cb93a386Sopenharmony_ci    std::function<void()> onPlatformGetAutoContextRestore() const override;
67cb93a386Sopenharmony_ci    GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    GLXContext fContext;
70cb93a386Sopenharmony_ci    Display* fDisplay;
71cb93a386Sopenharmony_ci    Pixmap fPixmap;
72cb93a386Sopenharmony_ci    GLXPixmap fGlxPixmap;
73cb93a386Sopenharmony_ci};
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_cistatic Display* get_display() {
76cb93a386Sopenharmony_ci    class AutoDisplay {
77cb93a386Sopenharmony_ci    public:
78cb93a386Sopenharmony_ci        AutoDisplay() { fDisplay = XOpenDisplay(nullptr); }
79cb93a386Sopenharmony_ci        ~AutoDisplay() {
80cb93a386Sopenharmony_ci            if (fDisplay) {
81cb93a386Sopenharmony_ci                XCloseDisplay(fDisplay);
82cb93a386Sopenharmony_ci            }
83cb93a386Sopenharmony_ci        }
84cb93a386Sopenharmony_ci        Display* display() const { return fDisplay; }
85cb93a386Sopenharmony_ci    private:
86cb93a386Sopenharmony_ci        Display* fDisplay;
87cb93a386Sopenharmony_ci    };
88cb93a386Sopenharmony_ci    static std::unique_ptr<AutoDisplay> ad;
89cb93a386Sopenharmony_ci    static SkOnce once;
90cb93a386Sopenharmony_ci    once([] { ad = std::make_unique<AutoDisplay>(); });
91cb93a386Sopenharmony_ci    return ad->display();
92cb93a386Sopenharmony_ci}
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_cistd::function<void()> context_restorer() {
95cb93a386Sopenharmony_ci    auto display = glXGetCurrentDisplay();
96cb93a386Sopenharmony_ci    auto drawable = glXGetCurrentDrawable();
97cb93a386Sopenharmony_ci    auto context = glXGetCurrentContext();
98cb93a386Sopenharmony_ci    // On some systems calling glXMakeCurrent with a null display crashes.
99cb93a386Sopenharmony_ci    if (!display) {
100cb93a386Sopenharmony_ci        display = get_display();
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci    return [display, drawable, context] { glXMakeCurrent(display, drawable, context); };
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ciGLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareContext)
106cb93a386Sopenharmony_ci    : fContext(nullptr)
107cb93a386Sopenharmony_ci    , fDisplay(nullptr)
108cb93a386Sopenharmony_ci    , fPixmap(0)
109cb93a386Sopenharmony_ci    , fGlxPixmap(0) {
110cb93a386Sopenharmony_ci    // We cross our fingers that this is the first X call in the program and that if the application
111cb93a386Sopenharmony_ci    // is actually threaded that this succeeds.
112cb93a386Sopenharmony_ci    static SkOnce gOnce;
113cb93a386Sopenharmony_ci    gOnce([] { XInitThreads(); });
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci    fDisplay = get_display();
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    GLXContext glxShareContext = shareContext ? shareContext->fContext : nullptr;
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci    if (!fDisplay) {
120cb93a386Sopenharmony_ci        SkDebugf("Failed to open X display.\n");
121cb93a386Sopenharmony_ci        this->destroyGLContext();
122cb93a386Sopenharmony_ci        return;
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci    // Get a matching FB config
126cb93a386Sopenharmony_ci    static int visual_attribs[] = {
127cb93a386Sopenharmony_ci        GLX_X_RENDERABLE    , True,
128cb93a386Sopenharmony_ci        GLX_DRAWABLE_TYPE   , GLX_PIXMAP_BIT,
129cb93a386Sopenharmony_ci        None
130cb93a386Sopenharmony_ci    };
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci    int glx_major, glx_minor;
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ci    // FBConfigs were added in GLX version 1.3.
135cb93a386Sopenharmony_ci    if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) ||
136cb93a386Sopenharmony_ci            ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) {
137cb93a386Sopenharmony_ci        SkDebugf("GLX version 1.3 or higher required.\n");
138cb93a386Sopenharmony_ci        this->destroyGLContext();
139cb93a386Sopenharmony_ci        return;
140cb93a386Sopenharmony_ci    }
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    //SkDebugf("Getting matching framebuffer configs.\n");
143cb93a386Sopenharmony_ci    int fbcount;
144cb93a386Sopenharmony_ci    GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay),
145cb93a386Sopenharmony_ci                                          visual_attribs, &fbcount);
146cb93a386Sopenharmony_ci    if (!fbc) {
147cb93a386Sopenharmony_ci        SkDebugf("Failed to retrieve a framebuffer config.\n");
148cb93a386Sopenharmony_ci        this->destroyGLContext();
149cb93a386Sopenharmony_ci        return;
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    //SkDebugf("Found %d matching FB configs.\n", fbcount);
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    // Pick the FB config/visual with the most samples per pixel
154cb93a386Sopenharmony_ci    //SkDebugf("Getting XVisualInfos.\n");
155cb93a386Sopenharmony_ci    int best_fbc = -1, best_num_samp = -1;
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    int i;
158cb93a386Sopenharmony_ci    for (i = 0; i < fbcount; ++i) {
159cb93a386Sopenharmony_ci        XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]);
160cb93a386Sopenharmony_ci        if (vi) {
161cb93a386Sopenharmony_ci            int samp_buf, samples;
162cb93a386Sopenharmony_ci            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
163cb93a386Sopenharmony_ci            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples);
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci            //SkDebugf("  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
166cb93a386Sopenharmony_ci            //       " SAMPLES = %d\n",
167cb93a386Sopenharmony_ci            //        i, (unsigned int)vi->visualid, samp_buf, samples);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci            if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) {
170cb93a386Sopenharmony_ci                best_fbc = i;
171cb93a386Sopenharmony_ci                best_num_samp = samples;
172cb93a386Sopenharmony_ci            }
173cb93a386Sopenharmony_ci        }
174cb93a386Sopenharmony_ci        XFree(vi);
175cb93a386Sopenharmony_ci    }
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci    GLXFBConfig bestFbc = fbc[best_fbc];
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
180cb93a386Sopenharmony_ci    XFree(fbc);
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    // Get a visual
183cb93a386Sopenharmony_ci    XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc);
184cb93a386Sopenharmony_ci    //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid);
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci    fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth);
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    if (!fPixmap) {
189cb93a386Sopenharmony_ci        SkDebugf("Failed to create pixmap.\n");
190cb93a386Sopenharmony_ci        this->destroyGLContext();
191cb93a386Sopenharmony_ci        return;
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap);
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    // Done with the visual info data
197cb93a386Sopenharmony_ci    XFree(vi);
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    // Get the default screen's GLX extension list
200cb93a386Sopenharmony_ci    const char *glxExts = glXQueryExtensionsString(
201cb93a386Sopenharmony_ci        fDisplay, DefaultScreen(fDisplay)
202cb93a386Sopenharmony_ci    );
203cb93a386Sopenharmony_ci    // Check for the GLX_ARB_create_context extension string and the function.
204cb93a386Sopenharmony_ci    // If either is not present, use GLX 1.3 context creation method.
205cb93a386Sopenharmony_ci    if (!gluCheckExtension(reinterpret_cast<const GLubyte*>("GLX_ARB_create_context"),
206cb93a386Sopenharmony_ci                           reinterpret_cast<const GLubyte*>(glxExts))) {
207cb93a386Sopenharmony_ci        if (kGLES_GrGLStandard != forcedGpuAPI) {
208cb93a386Sopenharmony_ci            fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, nullptr, True);
209cb93a386Sopenharmony_ci        }
210cb93a386Sopenharmony_ci    } else {
211cb93a386Sopenharmony_ci        if (kGLES_GrGLStandard == forcedGpuAPI) {
212cb93a386Sopenharmony_ci            if (gluCheckExtension(
213cb93a386Sopenharmony_ci                    reinterpret_cast<const GLubyte*>("GLX_EXT_create_context_es2_profile"),
214cb93a386Sopenharmony_ci                    reinterpret_cast<const GLubyte*>(glxExts))) {
215cb93a386Sopenharmony_ci                fContext = CreateBestContext(true, fDisplay, bestFbc, glxShareContext);
216cb93a386Sopenharmony_ci            }
217cb93a386Sopenharmony_ci        } else {
218cb93a386Sopenharmony_ci            fContext = CreateBestContext(false, fDisplay, bestFbc, glxShareContext);
219cb93a386Sopenharmony_ci        }
220cb93a386Sopenharmony_ci    }
221cb93a386Sopenharmony_ci    if (!fContext) {
222cb93a386Sopenharmony_ci        SkDebugf("Failed to create an OpenGL context.\n");
223cb93a386Sopenharmony_ci        this->destroyGLContext();
224cb93a386Sopenharmony_ci        return;
225cb93a386Sopenharmony_ci    }
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    // Verify that context is a direct context
228cb93a386Sopenharmony_ci    if (!glXIsDirect(fDisplay, fContext)) {
229cb93a386Sopenharmony_ci        //SkDebugf("Indirect GLX rendering context obtained.\n");
230cb93a386Sopenharmony_ci    } else {
231cb93a386Sopenharmony_ci        //SkDebugf("Direct GLX rendering context obtained.\n");
232cb93a386Sopenharmony_ci    }
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci    SkScopeExit restorer(context_restorer());
235cb93a386Sopenharmony_ci    //SkDebugf("Making context current.\n");
236cb93a386Sopenharmony_ci    if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
237cb93a386Sopenharmony_ci      SkDebugf("Could not set the context.\n");
238cb93a386Sopenharmony_ci        this->destroyGLContext();
239cb93a386Sopenharmony_ci        return;
240cb93a386Sopenharmony_ci    }
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_ci#ifdef SK_GL
243cb93a386Sopenharmony_ci    auto gl = GrGLMakeNativeInterface();
244cb93a386Sopenharmony_ci    if (!gl) {
245cb93a386Sopenharmony_ci        SkDebugf("Failed to create gl interface");
246cb93a386Sopenharmony_ci        this->destroyGLContext();
247cb93a386Sopenharmony_ci        return;
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    if (!gl->validate()) {
251cb93a386Sopenharmony_ci        SkDebugf("Failed to validate gl interface");
252cb93a386Sopenharmony_ci        this->destroyGLContext();
253cb93a386Sopenharmony_ci        return;
254cb93a386Sopenharmony_ci    }
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci    this->init(std::move(gl));
257cb93a386Sopenharmony_ci#else
258cb93a386Sopenharmony_ci    // Allow the GLTestContext creation to succeed without a GrGLInterface to support
259cb93a386Sopenharmony_ci    // GrContextFactory's persistent GL context workaround for Vulkan. We won't need the
260cb93a386Sopenharmony_ci    // GrGLInterface since we're not running the GL backend.
261cb93a386Sopenharmony_ci    this->init(nullptr);
262cb93a386Sopenharmony_ci#endif
263cb93a386Sopenharmony_ci}
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ciGLXGLTestContext::~GLXGLTestContext() {
267cb93a386Sopenharmony_ci    this->teardown();
268cb93a386Sopenharmony_ci    this->destroyGLContext();
269cb93a386Sopenharmony_ci}
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_civoid GLXGLTestContext::destroyGLContext() {
272cb93a386Sopenharmony_ci    if (fDisplay) {
273cb93a386Sopenharmony_ci        if (fContext) {
274cb93a386Sopenharmony_ci            if (glXGetCurrentContext() == fContext) {
275cb93a386Sopenharmony_ci                // This will ensure that the context is immediately deleted.
276cb93a386Sopenharmony_ci                glXMakeContextCurrent(fDisplay, None, None, nullptr);
277cb93a386Sopenharmony_ci            }
278cb93a386Sopenharmony_ci            glXDestroyContext(fDisplay, fContext);
279cb93a386Sopenharmony_ci            fContext = nullptr;
280cb93a386Sopenharmony_ci        }
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci        if (fGlxPixmap) {
283cb93a386Sopenharmony_ci            glXDestroyGLXPixmap(fDisplay, fGlxPixmap);
284cb93a386Sopenharmony_ci            fGlxPixmap = 0;
285cb93a386Sopenharmony_ci        }
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci        if (fPixmap) {
288cb93a386Sopenharmony_ci            XFreePixmap(fDisplay, fPixmap);
289cb93a386Sopenharmony_ci            fPixmap = 0;
290cb93a386Sopenharmony_ci        }
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci        fDisplay = nullptr;
293cb93a386Sopenharmony_ci    }
294cb93a386Sopenharmony_ci}
295cb93a386Sopenharmony_ci
296cb93a386Sopenharmony_ci/* Create a context with the highest possible version.
297cb93a386Sopenharmony_ci *
298cb93a386Sopenharmony_ci * Disable Xlib errors for the duration of this function (by default they abort
299cb93a386Sopenharmony_ci * the program) and try to get a context starting from the highest version
300cb93a386Sopenharmony_ci * number - there is no way to just directly ask what the highest supported
301cb93a386Sopenharmony_ci * version is.
302cb93a386Sopenharmony_ci *
303cb93a386Sopenharmony_ci * Returns the correct context or NULL on failure.
304cb93a386Sopenharmony_ci */
305cb93a386Sopenharmony_ciGLXContext GLXGLTestContext::CreateBestContext(bool isES, Display* display, GLXFBConfig bestFbc,
306cb93a386Sopenharmony_ci                                               GLXContext glxShareContext) {
307cb93a386Sopenharmony_ci    auto glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
308cb93a386Sopenharmony_ci        glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB");
309cb93a386Sopenharmony_ci    if (!glXCreateContextAttribsARB) {
310cb93a386Sopenharmony_ci        SkDebugf("Failed to get address of glXCreateContextAttribsARB");
311cb93a386Sopenharmony_ci        return nullptr;
312cb93a386Sopenharmony_ci    }
313cb93a386Sopenharmony_ci    GLXContext context = nullptr;
314cb93a386Sopenharmony_ci    // Install Xlib error handler that will set ctxErrorOccurred.
315cb93a386Sopenharmony_ci    // WARNING: It is global for all threads.
316cb93a386Sopenharmony_ci    ctxErrorOccurred = false;
317cb93a386Sopenharmony_ci    int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    auto versions = isES ? gles_versions : gl_versions;
320cb93a386Sopenharmony_ci    // Well, unfortunately GLX will not just give us the highest context so
321cb93a386Sopenharmony_ci    // instead we have to do this nastiness
322cb93a386Sopenharmony_ci    for (int i = versions.size() - 1; i >= 0 ; i--) {
323cb93a386Sopenharmony_ci        // WARNING: Don't try to optimize this and make this array static. The
324cb93a386Sopenharmony_ci        // glXCreateContextAttribsARB call writes to it upon failure and the
325cb93a386Sopenharmony_ci        // next call would fail too.
326cb93a386Sopenharmony_ci        std::vector<int> flags = {
327cb93a386Sopenharmony_ci            GLX_CONTEXT_MAJOR_VERSION_ARB, versions[i].first,
328cb93a386Sopenharmony_ci            GLX_CONTEXT_MINOR_VERSION_ARB, versions[i].second,
329cb93a386Sopenharmony_ci        };
330cb93a386Sopenharmony_ci        if (isES) {
331cb93a386Sopenharmony_ci            flags.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
332cb93a386Sopenharmony_ci            // the ES2 flag should work even for higher versions
333cb93a386Sopenharmony_ci            flags.push_back(GLX_CONTEXT_ES2_PROFILE_BIT_EXT);
334cb93a386Sopenharmony_ci        } else if (versions[i].first > 2) {
335cb93a386Sopenharmony_ci            flags.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
336cb93a386Sopenharmony_ci            flags.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
337cb93a386Sopenharmony_ci        }
338cb93a386Sopenharmony_ci        flags.push_back(0);
339cb93a386Sopenharmony_ci        context = glXCreateContextAttribsARB(display, bestFbc, glxShareContext, true,
340cb93a386Sopenharmony_ci                                             &flags[0]);
341cb93a386Sopenharmony_ci        // Sync to ensure any errors generated are processed.
342cb93a386Sopenharmony_ci        XSync(display, False);
343cb93a386Sopenharmony_ci
344cb93a386Sopenharmony_ci        if (!ctxErrorOccurred && context) {
345cb93a386Sopenharmony_ci            break;
346cb93a386Sopenharmony_ci        }
347cb93a386Sopenharmony_ci        // try again
348cb93a386Sopenharmony_ci        ctxErrorOccurred = false;
349cb93a386Sopenharmony_ci    }
350cb93a386Sopenharmony_ci    // Restore the original error handler.
351cb93a386Sopenharmony_ci    XSetErrorHandler(oldHandler);
352cb93a386Sopenharmony_ci    return context;
353cb93a386Sopenharmony_ci}
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_civoid GLXGLTestContext::onPlatformMakeNotCurrent() const {
356cb93a386Sopenharmony_ci    if (!glXMakeCurrent(fDisplay, None , nullptr)) {
357cb93a386Sopenharmony_ci        SkDebugf("Could not reset the context.\n");
358cb93a386Sopenharmony_ci    }
359cb93a386Sopenharmony_ci}
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_civoid GLXGLTestContext::onPlatformMakeCurrent() const {
362cb93a386Sopenharmony_ci    if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
363cb93a386Sopenharmony_ci        SkDebugf("Could not set the context.\n");
364cb93a386Sopenharmony_ci    }
365cb93a386Sopenharmony_ci}
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_cistd::function<void()> GLXGLTestContext::onPlatformGetAutoContextRestore() const {
368cb93a386Sopenharmony_ci    if (glXGetCurrentContext() == fContext) {
369cb93a386Sopenharmony_ci        return nullptr;
370cb93a386Sopenharmony_ci    }
371cb93a386Sopenharmony_ci    return context_restorer();
372cb93a386Sopenharmony_ci}
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ciGrGLFuncPtr GLXGLTestContext::onPlatformGetProcAddress(const char* procName) const {
375cb93a386Sopenharmony_ci    return glXGetProcAddress(reinterpret_cast<const GLubyte*>(procName));
376cb93a386Sopenharmony_ci}
377cb93a386Sopenharmony_ci
378cb93a386Sopenharmony_ci}  // anonymous namespace
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_cinamespace sk_gpu_test {
381cb93a386Sopenharmony_ciGLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
382cb93a386Sopenharmony_ci                                           GLTestContext *shareContext) {
383cb93a386Sopenharmony_ci    GLXGLTestContext *glxShareContext = reinterpret_cast<GLXGLTestContext *>(shareContext);
384cb93a386Sopenharmony_ci    GLXGLTestContext *ctx = new GLXGLTestContext(forcedGpuAPI, glxShareContext);
385cb93a386Sopenharmony_ci    if (!ctx->isValid()) {
386cb93a386Sopenharmony_ci        delete ctx;
387cb93a386Sopenharmony_ci        return nullptr;
388cb93a386Sopenharmony_ci    }
389cb93a386Sopenharmony_ci    return ctx;
390cb93a386Sopenharmony_ci}
391cb93a386Sopenharmony_ci}  // namespace sk_gpu_test
392