/*
 * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

#include <stdlib.h>
#include <string.h>

#include "sun_java2d_opengl_GLXGraphicsConfig.h"

#include "jni.h"
#include "jlong.h"
#include "GLXGraphicsConfig.h"
#include "GLXSurfaceData.h"
#include "awt_GraphicsEnv.h"
#include "awt_util.h"

#ifndef HEADLESS

extern Bool usingXinerama;

/**
 * This is a globally shared context used when creating textures.  When any
 * new contexts are created, they specify this context as the "share list"
 * context, which means any texture objects created when this shared context
 * is current will be available to any other context.
 */
static GLXContext sharedContext = 0;

/**
 * Attempts to initialize GLX and the core OpenGL library.  For this method
 * to return JNI_TRUE, the following must be true:
 *     - libGL must be loaded successfully (via dlopen)
 *     - all function symbols from libGL must be available and loaded properly
 *     - the GLX extension must be available through X11
 *     - client GLX version must be >= 1.3
 * If any of these requirements are not met, this method will return
 * JNI_FALSE, indicating there is no hope of using GLX/OpenGL for any
 * GraphicsConfig in the environment.
 */
static jboolean
GLXGC_InitGLX()
{
    int errorbase, eventbase;
    const char *version;

    J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGC_InitGLX");

    if (!OGLFuncs_OpenLibrary()) {
        return JNI_FALSE;
    }

    if (!OGLFuncs_InitPlatformFuncs() ||
        !OGLFuncs_InitBaseFuncs() ||
        !OGLFuncs_InitExtFuncs())
    {
        OGLFuncs_CloseLibrary();
        return JNI_FALSE;
    }

    if (!j2d_glXQueryExtension(awt_display, &errorbase, &eventbase)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "GLXGC_InitGLX: GLX extension is not present");
        OGLFuncs_CloseLibrary();
        return JNI_FALSE;
    }

    version = j2d_glXGetClientString(awt_display, GLX_VERSION);
    if (version == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "GLXGC_InitGLX: could not query GLX version");
        OGLFuncs_CloseLibrary();
        return JNI_FALSE;
    }

    // we now only verify that the client GLX version is >= 1.3 (if the
    // server does not support GLX 1.3, then we will find that out later
    // when we attempt to create a GLXFBConfig)
    J2dRlsTraceLn1(J2D_TRACE_INFO,
                   "GLXGC_InitGLX: client GLX version=%s", version);
    if (!((version[0] == '1' && version[2] >= '3') || (version[0] > '1'))) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "GLXGC_InitGLX: invalid GLX version; 1.3 is required");
        OGLFuncs_CloseLibrary();
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * Returns JNI_TRUE if GLX is available for the current display.  Note that
 * this method will attempt to initialize GLX (and all the necessary function
 * symbols) if it has not been already.  The AWT_LOCK must be acquired before
 * calling this method.
 */
jboolean
GLXGC_IsGLXAvailable()
{
    static jboolean glxAvailable = JNI_FALSE;
    static jboolean firstTime = JNI_TRUE;

    J2dTraceLn(J2D_TRACE_INFO, "GLXGC_IsGLXAvailable");

    if (firstTime) {
        glxAvailable = GLXGC_InitGLX();
        firstTime = JNI_FALSE;
    }

    return glxAvailable;
}

/**
 * Disposes all memory and resources allocated for the given OGLContext.
 */
static void
GLXGC_DestroyOGLContext(OGLContext *oglc)
{
    GLXCtxInfo *ctxinfo;

    J2dTraceLn(J2D_TRACE_INFO, "GLXGC_DestroyOGLContext");

    if (oglc == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "GLXGC_DestroyOGLContext: context is null");
        return;
    }

    // at this point, this context will be current to its scratch surface
    // so the following GL/GLX operations should be safe...

    OGLContext_DestroyContextResources(oglc);

    ctxinfo = (GLXCtxInfo *)oglc->ctxInfo;
    if (ctxinfo != NULL) {
        // release the current context before we continue
        j2d_glXMakeContextCurrent(awt_display, None, None, NULL);

        if (ctxinfo->context != 0) {
            j2d_glXDestroyContext(awt_display, ctxinfo->context);
        }
        if (ctxinfo->scratchSurface != 0) {
            j2d_glXDestroyPbuffer(awt_display, ctxinfo->scratchSurface);
        }

        free(ctxinfo);
    }

    free(oglc);
}

/**
 * Disposes all memory and resources associated with the given
 * GLXGraphicsConfigInfo (including its native OGLContext data).
 */
void
OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo)
{
    GLXGraphicsConfigInfo *glxinfo =
        (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);

    J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig");

    if (glxinfo == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "OGLGC_DestroyOGLGraphicsConfig: info is null");
        return;
    }

    if (glxinfo->context != NULL) {
        GLXGC_DestroyOGLContext(glxinfo->context);
    }

    free(glxinfo);
}

/**
 * Attempts to create a new GLXFBConfig for the requested screen and visual.
 * If visualid is 0, this method will iterate through all GLXFBConfigs (if
 * any) that match the requested attributes and will attempt to find an
 * fbconfig with a minimal combined depth+stencil buffer.  Note that we
 * currently only need depth capabilities (for shape clipping purposes), but
 * glXChooseFBConfig() will often return a list of fbconfigs with the largest
 * depth buffer (and stencil) sizes at the top of the list.  Therefore, we
 * scan through the whole list to find the most VRAM-efficient fbconfig.
 * If visualid is non-zero, the GLXFBConfig associated with the given visual
 * is chosen (assuming it meets the requested attributes).  If there are no
 * valid GLXFBConfigs available, this method returns 0.
 */
static GLXFBConfig
GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid)
{
    GLXFBConfig *fbconfigs;
    GLXFBConfig chosenConfig = 0;
    int nconfs, i;
    int attrlist[] = {GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT,
                      GLX_RENDER_TYPE, GLX_RGBA_BIT,
                      GLX_CONFIG_CAVEAT, GLX_NONE, // avoid "slow" configs
                      GLX_DEPTH_SIZE, 16, // anything >= 16 will work for us
                      0};

    // this is the initial minimum value for the combined depth+stencil size
    // (we initialize it to some absurdly high value; realistic values will
    // be much less than this number)
    int minDepthPlusStencil = 512;

    J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x",
                   screennum, visualid);

    // find all fbconfigs for this screen with the provided attributes
    fbconfigs = j2d_glXChooseFBConfig(awt_display, screennum,
                                      attrlist, &nconfs);

    if ((fbconfigs == NULL) || (nconfs <= 0)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_InitFBConfig: could not find any valid fbconfigs");
        return 0;
    }

    J2dRlsTraceLn(J2D_TRACE_VERBOSE, "  candidate fbconfigs:");

    // iterate through the list of fbconfigs, looking for the one that matches
    // the requested VisualID and supports RGBA rendering as well as the
    // creation of windows and pbuffers
    for (i = 0; i < nconfs; i++) {
        XVisualInfo *xvi;
        VisualID fbvisualid;
        GLXFBConfig fbc = fbconfigs[i];

        // get VisualID from GLXFBConfig
        xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc);
        if (xvi == NULL) {
            continue;
        }
        fbvisualid = xvi->visualid;
        XFree(xvi);

        if (visualid == 0 || visualid == fbvisualid) {
            int dtype, rtype, depth, stencil, db, alpha, gamma;

            // get GLX-specific attributes from GLXFBConfig
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_DRAWABLE_TYPE, &dtype);
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_RENDER_TYPE, &rtype);
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_DEPTH_SIZE, &depth);
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_STENCIL_SIZE, &stencil);

            // these attributes don't affect our decision, but they are
            // interesting for trace logs, so we will query them anyway
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_DOUBLEBUFFER, &db);
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_ALPHA_SIZE, &alpha);

            J2dRlsTrace5(J2D_TRACE_VERBOSE,
                "[V]     id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=",
                         fbvisualid, db, alpha, depth, stencil);

#ifdef __sparc
            /*
             * Sun's OpenGL implementation will always
             * return at least two GLXFBConfigs (visuals) from
             * glXChooseFBConfig().  The first will be a linear (gamma
             * corrected) visual; the second will have the same capabilities
             * as the first, except it will be a non-linear (non-gamma
             * corrected) visual, which is the one we want, otherwise
             * everything will look "washed out".  So we will reject any
             * visuals that have gamma values other than 1.0 (the value
             * returned by glXGetFBConfigAttrib() will be scaled
             * by 100, so 100 corresponds to a gamma value of 1.0, 220
             * corresponds to 2.2, and so on).
             */
            j2d_glXGetFBConfigAttrib(awt_display, fbc,
                                     GLX_GAMMA_VALUE_SUN, &gamma);
            if (gamma != 100) {
                J2dRlsTrace(J2D_TRACE_VERBOSE, "false (linear visual)\n");
                continue;
            }
#endif /* __sparc */

            if ((dtype & GLX_WINDOW_BIT) &&
                (dtype & GLX_PBUFFER_BIT) &&
                (rtype & GLX_RGBA_BIT) &&
                (depth >= 16))
            {
                if (visualid == 0) {
                    // when visualid == 0, we loop through all configs
                    // looking for an fbconfig that has the smallest combined
                    // depth+stencil size (this keeps VRAM usage to a minimum)
                    if ((depth + stencil) < minDepthPlusStencil) {
                        J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n");
                        minDepthPlusStencil = depth + stencil;
                        chosenConfig = fbc;
                    } else {
                        J2dRlsTrace(J2D_TRACE_VERBOSE,
                                    "false (large depth)\n");
                    }
                    continue;
                } else {
                    // in this case, visualid == fbvisualid, which means
                    // we've found a valid fbconfig corresponding to the
                    // requested VisualID, so break out of the loop
                    J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n");
                    chosenConfig = fbc;
                    break;
                }
            } else {
                J2dRlsTrace(J2D_TRACE_VERBOSE, "false (bad match)\n");
            }
        }
    }

    // free the list of fbconfigs
    XFree(fbconfigs);

    if (chosenConfig == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_InitFBConfig: could not find an appropriate fbconfig");
        return 0;
    }

    return chosenConfig;
}

/**
 * Returns the X11 VisualID that corresponds to the best GLXFBConfig for the
 * given screen.  If no valid visual could be found, this method returns zero.
 * Note that this method will attempt to initialize GLX (and all the
 * necessary function symbols) if it has not been already.  The AWT_LOCK
 * must be acquired before calling this method.
 */
VisualID
GLXGC_FindBestVisual(JNIEnv *env, jint screen)
{
    GLXFBConfig fbc;
    XVisualInfo *xvi;
    VisualID visualid;

    J2dRlsTraceLn1(J2D_TRACE_INFO, "GLXGC_FindBestVisual: scn=%d", screen);

    if (!GLXGC_IsGLXAvailable()) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_FindBestVisual: could not initialize GLX");
        return 0;
    }

    fbc = GLXGC_InitFBConfig(env, screen, 0);
    if (fbc == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_FindBestVisual: could not find best visual");
        return 0;
    }

    xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc);
    if (xvi == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_FindBestVisual: could not get visual for fbconfig");
        return 0;
    }

    visualid = xvi->visualid;
    XFree(xvi);

    J2dRlsTraceLn2(J2D_TRACE_INFO,
        "GLXGC_FindBestVisual: chose 0x%x as the best visual for screen %d",
                   visualid, screen);

    return visualid;
}

/**
 * Creates a scratch pbuffer, which can be used to make a context current
 * for extension queries, etc.
 */
static GLXPbuffer
GLXGC_InitScratchPbuffer(GLXFBConfig fbconfig)
{
    int pbattrlist[] = {GLX_PBUFFER_WIDTH, 1,
                        GLX_PBUFFER_HEIGHT, 1,
                        GLX_PRESERVED_CONTENTS, GL_FALSE,
                        0};

    J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitScratchPbuffer");

    return j2d_glXCreatePbuffer(awt_display, fbconfig, pbattrlist);
}

/**
 * Initializes a new OGLContext, which includes the native GLXContext handle
 * and some other important information such as the associated GLXFBConfig.
 */
static OGLContext *
GLXGC_InitOGLContext(GLXFBConfig fbconfig, GLXContext context,
                     GLXPbuffer scratch, jint caps)
{
    OGLContext *oglc;
    GLXCtxInfo *ctxinfo;

    J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitOGLContext");

    oglc = (OGLContext *)malloc(sizeof(OGLContext));
    if (oglc == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_InitOGLContext: could not allocate memory for oglc");
        return NULL;
    }

    memset(oglc, 0, sizeof(OGLContext));

    ctxinfo = (GLXCtxInfo *)malloc(sizeof(GLXCtxInfo));
    if (ctxinfo == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGC_InitOGLContext: could not allocate memory for ctxinfo");
        free(oglc);
        return NULL;
    }

    ctxinfo->fbconfig = fbconfig;
    ctxinfo->context = context;
    ctxinfo->scratchSurface = scratch;
    oglc->ctxInfo = ctxinfo;
    oglc->caps = caps;

    return oglc;
}

#endif /* !HEADLESS */

/**
 * Determines whether the GLX pipeline can be used for a given GraphicsConfig
 * provided its screen number and visual ID.  If the minimum requirements are
 * met, the native GLXGraphicsConfigInfo structure is initialized for this
 * GraphicsConfig with the necessary information (GLXFBConfig, etc.)
 * and a pointer to this structure is returned as a jlong.  If
 * initialization fails at any point, zero is returned, indicating that GLX
 * cannot be used for this GraphicsConfig (we should fallback on the existing
 * X11 pipeline).
 */
JNIEXPORT jlong JNICALL
Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo(JNIEnv *env,
                                                          jclass glxgc,
                                                          jint screennum,
                                                          jint visnum)
{
#ifndef HEADLESS
    OGLContext *oglc;
    GLXFBConfig fbconfig;
    GLXContext context;
    GLXPbuffer scratch;
    GLXGraphicsConfigInfo *glxinfo;
    jint caps = sun_java2d_opengl_OGLContext_CAPS_EMPTY;
    int db, alpha;
    const unsigned char *versionstr;

    J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_getGLXConfigInfo");

    if (usingXinerama) {
        // when Xinerama is enabled, the screen ID needs to be 0
        screennum = 0;
    }

    fbconfig = GLXGC_InitFBConfig(env, screennum, (VisualID)visnum);
    if (fbconfig == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: could not create fbconfig");
        return 0L;
    }

    if (sharedContext == 0) {
        // create the one shared context
        sharedContext = j2d_glXCreateNewContext(awt_display, fbconfig,
                                                GLX_RGBA_TYPE, 0, GL_TRUE);
        if (sharedContext == 0) {
            J2dRlsTraceLn(J2D_TRACE_ERROR,
                "GLXGraphicsConfig_getGLXConfigInfo: could not create shared context");
            return 0L;
        }
    }

    // create the GLXContext for this GLXGraphicsConfig
    context = j2d_glXCreateNewContext(awt_display, fbconfig,
                                      GLX_RGBA_TYPE, sharedContext,
                                      GL_TRUE);
    if (context == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: could not create GLX context");
        return 0L;
    }

    // this is pretty sketchy, but it seems to be the easiest way to create
    // some form of GLXDrawable using only the display and a GLXFBConfig
    // (in order to make the context current for checking the version,
    // extensions, etc)...
    scratch = GLXGC_InitScratchPbuffer(fbconfig);
    if (scratch == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: could not create scratch pbuffer");
        j2d_glXDestroyContext(awt_display, context);
        return 0L;
    }

    // the context must be made current before we can query the
    // version and extension strings
    j2d_glXMakeContextCurrent(awt_display, scratch, scratch, context);

#ifdef __sparc
    /*
     * 6438225: The software rasterizer used by Sun's OpenGL libraries
     * for certain boards has quality issues, and besides, performance
     * of these boards is not high enough to justify the use of the
     * OpenGL-based Java 2D pipeline.  If we detect one of the following
     * boards via the GL_RENDERER string, just give up:
     *   - FFB[2[+]] ("Creator[3D]")
     *   - PGX-series ("m64")
     *   - AFB ("Elite3D")
     */
    {
        const char *renderer = (const char *)j2d_glGetString(GL_RENDERER);

        J2dRlsTraceLn1(J2D_TRACE_VERBOSE,
            "GLXGraphicsConfig_getGLXConfigInfo: detected renderer (%s)",
            (renderer == NULL) ? "null" : renderer);

        if (renderer == NULL ||
            strncmp(renderer, "Creator", 7) == 0 ||
            strncmp(renderer, "SUNWm64", 7) == 0 ||
            strncmp(renderer, "Elite", 5) == 0)
        {
            J2dRlsTraceLn1(J2D_TRACE_ERROR,
                "GLXGraphicsConfig_getGLXConfigInfo: unsupported board (%s)",
                (renderer == NULL) ? "null" : renderer);
            j2d_glXMakeContextCurrent(awt_display, None, None, NULL);
            j2d_glXDestroyPbuffer(awt_display, scratch);
            j2d_glXDestroyContext(awt_display, context);
            return 0L;
        }
    }
#endif /* __sparc */

    versionstr = j2d_glGetString(GL_VERSION);
    OGLContext_GetExtensionInfo(env, &caps);

    // destroy the temporary resources
    j2d_glXMakeContextCurrent(awt_display, None, None, NULL);

    J2dRlsTraceLn1(J2D_TRACE_INFO,
        "GLXGraphicsConfig_getGLXConfigInfo: OpenGL version=%s",
                   (versionstr == NULL) ? "null" : (char *)versionstr);

    if (!OGLContext_IsVersionSupported(versionstr)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: OpenGL 1.2 is required");
        j2d_glXDestroyPbuffer(awt_display, scratch);
        j2d_glXDestroyContext(awt_display, context);
        return 0L;
    }

    // get config-specific capabilities
    j2d_glXGetFBConfigAttrib(awt_display, fbconfig, GLX_DOUBLEBUFFER, &db);
    if (db) {
        caps |= sun_java2d_opengl_OGLContext_CAPS_DOUBLEBUFFERED;
    }
    j2d_glXGetFBConfigAttrib(awt_display, fbconfig, GLX_ALPHA_SIZE, &alpha);
    if (alpha > 0) {
        caps |= sun_java2d_opengl_OGLContext_CAPS_STORED_ALPHA;
    }

    // initialize the OGLContext, which wraps the GLXFBConfig and GLXContext
    oglc = GLXGC_InitOGLContext(fbconfig, context, scratch, caps);
    if (oglc == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: could not create oglc");
        j2d_glXDestroyPbuffer(awt_display, scratch);
        j2d_glXDestroyContext(awt_display, context);
        return 0L;
    }

    J2dTraceLn(J2D_TRACE_VERBOSE,
        "GLXGraphicsConfig_getGLXConfigInfo: finished checking dependencies");

    // create the GLXGraphicsConfigInfo record for this config
    glxinfo = (GLXGraphicsConfigInfo *)malloc(sizeof(GLXGraphicsConfigInfo));
    if (glxinfo == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "GLXGraphicsConfig_getGLXConfigInfo: could not allocate memory for glxinfo");
        GLXGC_DestroyOGLContext(oglc);
        return 0L;
    }

    glxinfo->screen = screennum;
    glxinfo->visual = visnum;
    glxinfo->context = oglc;
    glxinfo->fbconfig = fbconfig;

    return ptr_to_jlong(glxinfo);
#else
    return 0L;
#endif /* !HEADLESS */
}

JNIEXPORT void JNICALL
Java_sun_java2d_opengl_GLXGraphicsConfig_initConfig(JNIEnv *env,
                                                    jobject glxgc,
                                                    jlong aData,
                                                    jlong configInfo)
{
#ifndef HEADLESS
    GLXGraphicsConfigInfo *glxinfo;
    AwtGraphicsConfigDataPtr configData =
        (AwtGraphicsConfigDataPtr)jlong_to_ptr(aData);

    J2dTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_initConfig");

    if (configData == NULL) {
        JNU_ThrowNullPointerException(env, "Native GraphicsConfig missing");
        return;
    }

    glxinfo = (GLXGraphicsConfigInfo *)jlong_to_ptr(configInfo);
    if (glxinfo == NULL) {
        JNU_ThrowNullPointerException(env,
                                      "GLXGraphicsConfigInfo data missing");
        return;
    }

    configData->glxInfo = glxinfo;
#endif /* !HEADLESS */
}

JNIEXPORT jint JNICALL
Java_sun_java2d_opengl_GLXGraphicsConfig_getOGLCapabilities(JNIEnv *env,
                                                            jclass glxgc,
                                                            jlong configInfo)
{
#ifndef HEADLESS
    GLXGraphicsConfigInfo *glxinfo =
        (GLXGraphicsConfigInfo *)jlong_to_ptr(configInfo);

    J2dTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_getOGLCapabilities");

    if (glxinfo == NULL || glxinfo->context == NULL) {
        return sun_java2d_opengl_OGLContext_CAPS_EMPTY;
    }

    return glxinfo->context->caps;
#else
    return sun_java2d_opengl_OGLContext_CAPS_EMPTY;
#endif /* !HEADLESS */
}
