示例#1
0
bool SkExampleWindow::setupBackend(DeviceType type) {
    fType = type;

    this->setConfig(SkBitmap::kARGB_8888_Config);
    this->setVisibleP(true);
    this->setClipToBounds(false);

    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
    if (false == result) {
        SkDebugf("Not possible to create backend.\n");
        detach();
        return false;
    }

    fInterface = GrGLCreateNativeInterface();

    SkASSERT(NULL != fInterface);

    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
    SkASSERT(NULL != fContext);

    setupRenderTarget();

    return true;
}
const GrGLInterface* SkNativeSharedGLContext::createGLContext(const int width, const int height) {
    SkASSERT(NULL == fContext);

    // Create the base pixmap and GLX pixmap.
    //
    // TODO(pcwalton): This is inefficient. It would be better to have the caller pass in the
    // pixmap.
    int screen = DefaultScreen(fDisplay);
    Drawable root = RootWindow(fDisplay, screen);
    fPixmap = XCreatePixmap(fDisplay, root, width, height, fVisualInfo->depth);
    fGlxPixmap = glXCreateGLXPixmap(fDisplay, fVisualInfo, fPixmap);

    fContext = glXCreateContext(fDisplay, fVisualInfo, NULL, true);
    if (NULL == fContext) {
        SkDebugf("glXCreateContext failed with %d.", fContext);
        return NULL;
    }

    glXMakeCurrent(fDisplay, fGlxPixmap, fContext);

    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (NULL == interface) {
        SkDebugf("Context could not create GL interface.\n");
        this->destroyGLContext();
        return NULL;
    }

    return interface;
}
示例#3
0
void SkV8ExampleWindow::windowSizeChanged() {
    if (FLAGS_gpu) {
        SkOSWindow::AttachmentInfo attachmentInfo;
        bool result = this->attach(
                SkOSWindow::kNativeGL_BackEndType, 0, false, &attachmentInfo);
        if (!result) {
            printf("Failed to attach.");
            exit(1);
        }

        fCurIntf = GrGLCreateNativeInterface();
        fCurContext = GrContext::Create(
                kOpenGL_GrBackend, (GrBackendContext) fCurIntf);
        if (NULL == fCurIntf || NULL == fCurContext) {
            printf("Failed to initialize GL.");
            exit(1);
        }

        GrBackendRenderTargetDesc desc;
        desc.fWidth = SkScalarRoundToInt(this->width());
        desc.fHeight = SkScalarRoundToInt(this->height());
        desc.fConfig = kSkia8888_GrPixelConfig;
        desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
        desc.fSampleCnt = attachmentInfo.fSampleCount;
        desc.fStencilBits = attachmentInfo.fStencilBits;
        GrGLint buffer;
        GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
        desc.fRenderTargetHandle = buffer;

        SkSafeUnref(fCurSurface);
        fCurSurface = SkSurface::MakeFromBackendRenderTarget(fCurContext, desc,
                                                             nullptr, nullptr).release();
    }
}
const GrGLInterface* SkNativeGLContext::createGLContext() {
    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

    if (!gWC) {
        WNDCLASS wc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = NULL;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hInstance = hInstance;
        wc.lpfnWndProc = (WNDPROC) DefWindowProc;
        wc.lpszClassName = TEXT("Griffin");
        wc.lpszMenuName = NULL;
        wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

        gWC = RegisterClass(&wc);
        if (!gWC) {
            SkDebugf("Could not register window class.\n");
            return NULL;
        }
    }

    if (!(fWindow = CreateWindow(TEXT("Griffin"),
                                 TEXT("The Invisible Man"),
                                 WS_OVERLAPPEDWINDOW,
                                 0, 0, 1, 1,
                                 NULL, NULL,
                                 hInstance, NULL))) {
        SkDebugf("Could not create window.\n");
        return NULL;
    }

    if (!(fDeviceContext = GetDC(fWindow))) {
        SkDebugf("Could not get device context.\n");
        this->destroyGLContext();
        return NULL;
    }

    // Requesting a Core profile would bar us from using NVPR. So we pass false.
    if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) {
        SkDebugf("Could not create rendering context.\n");
        this->destroyGLContext();
        return NULL;
    }

    if (!(wglMakeCurrent(fDeviceContext, fGlRenderContext))) {
        SkDebugf("Could not set the context.\n");
        this->destroyGLContext();
        return NULL;
    }
    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (NULL == interface) {
        SkDebugf("Could not create GL interface.\n");
        this->destroyGLContext();
        return NULL;
    }

    return interface;
}
const GrGLInterface* SkNativeSharedGLContext::createGLContext() {
    SkASSERT(NULL == fContext);

    XVisualInfo *visinfo;
    int screen = DefaultScreen(fDisplay);
    GLint att[] = {
        GLX_RGBA,
        GLX_DEPTH_SIZE, 24,
        None
    };

    visinfo = glXChooseVisual(fDisplay, screen, att);
    fContext = glXCreateContext(fDisplay, visinfo, fSharedContext, true);

    if (NULL == fContext) {
        SkDebugf("glXCreateContext failed with %d.", fContext);
        return NULL;
    }

    
    glXMakeCurrent(fDisplay, fGlxPixmap, fContext);

    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (NULL == interface) {
        SkDebugf("Context could not create GL interface.\n");
        this->destroyGLContext();
        return NULL;
    }

    return interface;
}
示例#6
0
void VisualBench::resetContext() {
    fInterface.reset(GrGLCreateNativeInterface());
    SkASSERT(fInterface);

    // setup contexts
    fContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface.get()));
    SkASSERT(fContext);

    // setup rendertargets
    this->setupRenderTarget();
}
示例#7
0
    Renderer(int width, int height) {
        canvas = NULL; context = NULL; renderTarget = NULL;
        //Initialize
        SkGraphics::Init();
        const GrGLInterface* interface = GrGLCreateNativeInterface();
        SkASSERT(NULL != interface);
        context = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)(interface));
        SkASSERT(NULL != context);

        updateRenderTarget(width, height);

        // if (NULL != context && NULL != renderTarget) {
        //     SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(context, renderTarget));
        //     canvas = new SkCanvas(device);
        // }
    }
示例#8
0
void SkGLWidget::initializeGL() {
    fCurIntf = GrGLCreateNativeInterface();
    if (!fCurIntf) {
        return;
    }
    glStencilMask(0xffffffff);
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);

    fCurContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf);
    GrBackendRenderTargetDesc desc = this->getDesc(this->width(), this->height());
    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    GrRenderTarget* curRenderTarget = fCurContext->wrapBackendRenderTarget(desc);
    fGpuDevice = SkGpuDevice::Create(curRenderTarget);
    fCanvas = new SkCanvas(fGpuDevice);
    curRenderTarget->unref();
}
const GrGLInterface* SkNativeGLContext::createGLContext() {
    fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    EGLint majorVersion;
    EGLint minorVersion;
    eglInitialize(fDisplay, &majorVersion, &minorVersion);

    EGLint numConfigs;
    static const EGLint configAttribs[] = {
        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
    };

    EGLConfig surfaceConfig;
    eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);

    static const EGLint contextAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, contextAttribs);


    static const EGLint surfaceAttribs[] = {
            EGL_WIDTH, 1,
            EGL_HEIGHT, 1,
            EGL_NONE
        };
    fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);

    eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);

    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (!interface) {
        SkDebugf("Failed to create gl interface");
        this->destroyGLContext();
        return NULL;
    }
    return interface;
}
示例#10
0
void SkGLWidget::initializeGL() {
    if (!fCurIntf) {
        fCurIntf.reset(GrGLCreateNativeInterface());
    }
    if (!fCurIntf) {
        return;
    }
    // The call may come multiple times, for example after setSampleCount().  The QGLContext will be
    // different, but we do not have a mechanism to catch the destroying of QGLContext, so that
    // proper resource cleanup could be made.
    if (fCurContext) {
        fCurContext->abandonContext();
    }
    fGpuDevice.reset(NULL);
    fCanvas.reset(NULL);

    fCurContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf.get()));
}
示例#11
0
bool HelloWorldWindow::setUpBackend() {
    this->setVisibleP(true);
    this->setClipToBounds(false);

    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, false, &fAttachmentInfo);
    if (false == result) {
        SkDebugf("Not possible to create backend.\n");
        release();
        return false;
    }

    fInterface = GrGLCreateNativeInterface();
    SkASSERT(NULL != fInterface);

    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
    SkASSERT(NULL != fContext);

    this->setUpGpuBackedSurface();
    return true;
}
const GrGLInterface* SkNativeGLContext::createGLContext() {
    GLint major, minor;
    AGLContext ctx;

    aglGetVersion(&major, &minor);
    //SkDebugf("---- agl version %d %d\n", major, minor);

    const GLint pixelAttrs[] = {
        AGL_RGBA,
        AGL_ACCELERATED,
        AGL_NONE
    };
    AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
    if (NULL == format) {
        SkDebugf("Format could not be found.\n");
        this->destroyGLContext();
        return NULL;
    }
    fContext = aglCreateContext(format, NULL);
    if (NULL == fContext) {
        SkDebugf("Context could not be created.\n");
        this->destroyGLContext();
        return NULL;
    }
    aglDestroyPixelFormat(format);

    aglSetCurrentContext(fContext);
    
    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (NULL == interface) {
        SkDebugf("Context could not create GL interface.\n");
        this->destroyGLContext();
        return NULL;
    }
    
    return interface;
}
const GrGLInterface* GrGLDefaultInterface() {
    return GrGLCreateNativeInterface();
}
const GrGLInterface* SkNativeGLContext::createGLContext() {
    fDisplay = XOpenDisplay(0);

    if (!fDisplay) {
        SkDebugf("Failed to open X display.\n");
        this->destroyGLContext();
        return NULL;
    }

    // Get a matching FB config
    static int visual_attribs[] = {
        GLX_X_RENDERABLE    , True,
        GLX_DRAWABLE_TYPE   , GLX_PIXMAP_BIT,
        None
    };

#ifdef GLX_1_3
    //SkDebugf("Getting matching framebuffer configs.\n");
    int fbcount;
    GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay),
                                          visual_attribs, &fbcount);
    if (!fbc) {
        SkDebugf("Failed to retrieve a framebuffer config.\n");
        this->destroyGLContext();
        return NULL;
    }
    //SkDebugf("Found %d matching FB configs.\n", fbcount);

    // Pick the FB config/visual with the most samples per pixel
    //SkDebugf("Getting XVisualInfos.\n");
    int best_fbc = -1, best_num_samp = -1;

    int i;
    for (i = 0; i < fbcount; ++i) {
        XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]);
        if (vi) {
            int samp_buf, samples;
            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples);

            //SkDebugf("  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
            //       " SAMPLES = %d\n",
            //        i, (unsigned int)vi->visualid, samp_buf, samples);

            if (best_fbc < 0 || (samp_buf && samples > best_num_samp))
                best_fbc = i, best_num_samp = samples;
        }
        XFree(vi);
    }

    GLXFBConfig bestFbc = fbc[best_fbc];

    // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
    XFree(fbc);

    // Get a visual
    XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc);
    //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid);
#else
    int numVisuals;
    XVisualInfo visTemplate, *visReturn;

    visReturn = XGetVisualInfo(fDisplay, VisualNoMask, &visTemplate, &numVisuals);
    if (NULL == visReturn)
    {
        SkDebugf("Failed to get visual information.\n");
        this->destroyGLContext();
        return NULL;
    }

    int best = -1, best_num_samp = -1;

    for (int i = 0; i < numVisuals; ++i)
    {
        int samp_buf, samples;

        glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLE_BUFFERS, &samp_buf);
        glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLES, &samples);

        if (best < 0 || (samp_buf && samples > best_num_samp))
            best = i, best_num_samp = samples;
    }

    XVisualInfo temp = visReturn[best];
    XVisualInfo *vi = &temp;

    XFree(visReturn);
#endif

    fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth);

    if (!fPixmap) {
        SkDebugf("Failed to create pixmap.\n");
        this->destroyGLContext();
        return NULL;
    }

    fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap);

#ifdef GLX_1_3
    // Done with the visual info data
    XFree(vi);
#endif

    // Create the context

    // Install an X error handler so the application won't exit if GL 3.0
    // context allocation fails.
    //
    // Note this error handler is global.
    // All display connections in all threads of a process use the same
    // error handler, so be sure to guard against other threads issuing
    // X commands while this code is running.
    ctxErrorOccurred = false;
    int (*oldHandler)(Display*, XErrorEvent*) =
        XSetErrorHandler(&ctxErrorHandler);

    // Get the default screen's GLX extension list
    const char *glxExts = glXQueryExtensionsString(
        fDisplay, DefaultScreen(fDisplay)
    );
    // Check for the GLX_ARB_create_context extension string and the function.
    // If either is not present, use GLX 1.3 context creation method.
    if (!gluCheckExtension(
          reinterpret_cast<const GLubyte*>("GLX_ARB_create_context")
          , reinterpret_cast<const GLubyte*>(glxExts)))
    {
        //SkDebugf("GLX_ARB_create_context not found."
        //       " Using old-style GLX context.\n");
#ifdef GLX_1_3
        fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True);
#else
        fContext = glXCreateContext(fDisplay, vi, 0, True);
#endif

    }
#ifdef GLX_1_3
    else {
        //SkDebugf("Creating context.\n");

        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB =
            (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB");
        int context_attribs[] = {
            GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
            GLX_CONTEXT_MINOR_VERSION_ARB, 0,
            //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
            None
        };
        fContext = glXCreateContextAttribsARB(
            fDisplay, bestFbc, 0, True, context_attribs
        );

        // Sync to ensure any errors generated are processed.
        XSync(fDisplay, False);
        if (!ctxErrorOccurred && fContext) {
           //SkDebugf( "Created GL 3.0 context.\n" );
        } else {
            // Couldn't create GL 3.0 context.
            // Fall back to old-style 2.x context.
            // When a context version below 3.0 is requested,
            // implementations will return the newest context version compatible
            // with OpenGL versions less than version 3.0.

            // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
            context_attribs[1] = 1;
            // GLX_CONTEXT_MINOR_VERSION_ARB = 0
            context_attribs[3] = 0;

            ctxErrorOccurred = false;

            //SkDebugf("Failed to create GL 3.0 context."
            //       " Using old-style GLX context.\n");
            fContext = glXCreateContextAttribsARB(
                fDisplay, bestFbc, 0, True, context_attribs
            );
        }
    }
#endif

    // Sync to ensure any errors generated are processed.
    XSync(fDisplay, False);

    // Restore the original error handler
    XSetErrorHandler(oldHandler);

    if (ctxErrorOccurred || !fContext) {
        SkDebugf("Failed to create an OpenGL context.\n");
        this->destroyGLContext();
        return NULL;
    }

    // Verify that context is a direct context
    if (!glXIsDirect(fDisplay, fContext)) {
        //SkDebugf("Indirect GLX rendering context obtained.\n");
    } else {
        //SkDebugf("Direct GLX rendering context obtained.\n");
    }

    //SkDebugf("Making context current.\n");
    if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
      SkDebugf("Could not set the context.\n");
        this->destroyGLContext();
        return NULL;
    }

    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (!interface) {
        SkDebugf("Failed to create gl interface");
        this->destroyGLContext();
        return NULL;
    }
    return interface;
}
示例#15
0
extern "C" SkiaGrGLInterfaceRef
SkiaGrGLCreateNativeInterface() {
    return GrGLCreateNativeInterface();
}
sk_sp<const GrGLInterface> GlesDriver::getSkiaInterface() {
    sk_sp<const GrGLInterface> skiaInterface(GrGLCreateNativeInterface());
    return skiaInterface;
}
示例#17
0
const GrGLInterface* SkNativeGLContext::createGLContext() {
    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

    if (!gWC) {
        WNDCLASS wc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = NULL;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hInstance = hInstance;
        wc.lpfnWndProc = (WNDPROC) DefWindowProc;
        wc.lpszClassName = TEXT("Griffin");
        wc.lpszMenuName = NULL;
        wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

        gWC = RegisterClass(&wc);
        if (!gWC) {
            SkDebugf("Could not register window class.\n");
            return NULL;
        }
    }

    if (!(fWindow = CreateWindow(TEXT("Griffin"),
                                 TEXT("The Invisible Man"),
                                 WS_OVERLAPPEDWINDOW,
                                 0, 0, 1, 1,
                                 NULL, NULL,
                                 hInstance, NULL))) {
        SkDebugf("Could not create window.\n");
        return NULL;
    }

    if (!(fDeviceContext = GetDC(fWindow))) {
        SkDebugf("Could not get device context.\n");
        this->destroyGLContext();
        return NULL;
    }
    
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 0;
    pfd.cStencilBits = 0;
    pfd.iLayerType = PFD_MAIN_PLANE;
    
    int pixelFormat = 0;
    if (!(pixelFormat = ChoosePixelFormat(fDeviceContext, &pfd))) {
        SkDebugf("No matching pixel format descriptor.\n");
        this->destroyGLContext();
        return NULL;
    }
    
    if (!SetPixelFormat(fDeviceContext, pixelFormat, &pfd)) {
        SkDebugf("Could not set the pixel format %d.\n", pixelFormat);
        this->destroyGLContext();
        return NULL;
    }
    
    if (!(fGlRenderContext = wglCreateContext(fDeviceContext))) {
        SkDebugf("Could not create rendering context.\n");
        this->destroyGLContext();
        return NULL;
    }

    if (!(wglMakeCurrent(fDeviceContext, fGlRenderContext))) {
        SkDebugf("Could not set the context.\n");
        this->destroyGLContext();
        return NULL;
    }
    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (NULL == interface) {
        SkDebugf("Could not create GL interface.\n");
        this->destroyGLContext();
        return NULL;
    }

    return interface;
}
示例#18
0
const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) {
    fDisplay = XOpenDisplay(0);

    if (!fDisplay) {
        SkDebugf("Failed to open X display.\n");
        this->destroyGLContext();
        return NULL;
    }

    // Get a matching FB config
    static int visual_attribs[] = {
        GLX_X_RENDERABLE    , True,
        GLX_DRAWABLE_TYPE   , GLX_PIXMAP_BIT,
        None
    };

    int glx_major, glx_minor;

    // FBConfigs were added in GLX version 1.3.
    if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) ||
            ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) {
        SkDebugf("GLX version 1.3 or higher required.\n");
        this->destroyGLContext();
        return NULL;
    }

    //SkDebugf("Getting matching framebuffer configs.\n");
    int fbcount;
    GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay),
                                          visual_attribs, &fbcount);
    if (!fbc) {
        SkDebugf("Failed to retrieve a framebuffer config.\n");
        this->destroyGLContext();
        return NULL;
    }
    //SkDebugf("Found %d matching FB configs.\n", fbcount);

    // Pick the FB config/visual with the most samples per pixel
    //SkDebugf("Getting XVisualInfos.\n");
    int best_fbc = -1, best_num_samp = -1;

    int i;
    for (i = 0; i < fbcount; ++i) {
        XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]);
        if (vi) {
            int samp_buf, samples;
            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
            glXGetFBConfigAttrib(fDisplay, fbc[i], GLX_SAMPLES, &samples);

            //SkDebugf("  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
            //       " SAMPLES = %d\n",
            //        i, (unsigned int)vi->visualid, samp_buf, samples);

            if (best_fbc < 0 || (samp_buf && samples > best_num_samp))
                best_fbc = i, best_num_samp = samples;
        }
        XFree(vi);
    }

    GLXFBConfig bestFbc = fbc[best_fbc];

    // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
    XFree(fbc);

    // Get a visual
    XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc);
    //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid);

    fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth);

    if (!fPixmap) {
        SkDebugf("Failed to create pixmap.\n");
        this->destroyGLContext();
        return NULL;
    }

    fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap);

    // Done with the visual info data
    XFree(vi);

    // Create the context

    // Install an X error handler so the application won't exit if GL 3.0
    // context allocation fails.
    //
    // Note this error handler is global.
    // All display connections in all threads of a process use the same
    // error handler, so be sure to guard against other threads issuing
    // X commands while this code is running.
    ctxErrorOccurred = false;
    int (*oldHandler)(Display*, XErrorEvent*) =
        XSetErrorHandler(&ctxErrorHandler);

    // Get the default screen's GLX extension list
    const char *glxExts = glXQueryExtensionsString(
        fDisplay, DefaultScreen(fDisplay)
    );


    // Check for the GLX_ARB_create_context extension string and the function.
    // If either is not present, use GLX 1.3 context creation method.
    if (!gluCheckExtension(reinterpret_cast<const GLubyte*>("GLX_ARB_create_context"),
                           reinterpret_cast<const GLubyte*>(glxExts))) {
        if (kGLES_GrGLStandard != forcedGpuAPI) {
            fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True);
        }
    } else {
        //SkDebugf("Creating context.\n");
        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB =
            (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB");

        if (kGLES_GrGLStandard == forcedGpuAPI) {
            if (gluCheckExtension(
                    reinterpret_cast<const GLubyte*>("GLX_EXT_create_context_es2_profile"),
                    reinterpret_cast<const GLubyte*>(glxExts))) {
                static const int context_attribs_gles[] = {
                    GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
                    GLX_CONTEXT_MINOR_VERSION_ARB, 0,
                    GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
                    None
                };
                fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True,
                                                      context_attribs_gles);
            }
        } else {
            // Well, unfortunately GLX will not just give us the highest context so instead we have
            // to do this nastiness
            for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) {
                /* don't bother below GL 3.0 */
                if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) {
                    break;
                }
                // On Nvidia GPUs, to use Nv Path rendering we need a compatibility profile for the
                // time being.
                // TODO when Nvidia implements NVPR on Core profiles, we should start requesting
                // core here
                static const int context_attribs_gl[] = {
                      GLX_CONTEXT_MAJOR_VERSION_ARB, gl_versions[i].major,
                      GLX_CONTEXT_MINOR_VERSION_ARB, gl_versions[i].minor,
                      GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
                      None
                };
                fContext =
                        glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, context_attribs_gl);

                // Sync to ensure any errors generated are processed.
                XSync(fDisplay, False);

                if (!ctxErrorOccurred && fContext) {
                    break;
                }
                // try again
                ctxErrorOccurred = false;
            }

            // Couldn't create GL 3.0 context.
            // Fall back to old-style 2.x context.
            // When a context version below 3.0 is requested,
            // implementations will return the newest context version
            // compatible with OpenGL versions less than version 3.0.
            if (ctxErrorOccurred || !fContext) {
                static const int context_attribs_gl_fallback[] = {
                    GLX_CONTEXT_MAJOR_VERSION_ARB, 1,
                    GLX_CONTEXT_MINOR_VERSION_ARB, 0,
                    None
                };

                ctxErrorOccurred = false;

                fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True,
                                                      context_attribs_gl_fallback);
            }
        }
    }

    // Sync to ensure any errors generated are processed.
    XSync(fDisplay, False);

    // Restore the original error handler
    XSetErrorHandler(oldHandler);

    if (ctxErrorOccurred || !fContext) {
        SkDebugf("Failed to create an OpenGL context.\n");
        this->destroyGLContext();
        return NULL;
    }

    // Verify that context is a direct context
    if (!glXIsDirect(fDisplay, fContext)) {
        //SkDebugf("Indirect GLX rendering context obtained.\n");
    } else {
        //SkDebugf("Direct GLX rendering context obtained.\n");
    }

    //SkDebugf("Making context current.\n");
    if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
      SkDebugf("Could not set the context.\n");
        this->destroyGLContext();
        return NULL;
    }

    const GrGLInterface* interface = GrGLCreateNativeInterface();
    if (!interface) {
        SkDebugf("Failed to create gl interface");
        this->destroyGLContext();
        return NULL;
    }
    return interface;
}