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