/*
 * Copyright 2004-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_WGLGraphicsConfig.h"

#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "WGLGraphicsConfig.h"
#include "WGLSurfaceData.h"

/**
 * 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 in any other thread.
 */
HGLRC sharedContext = 0;

/**
 * Attempts to initialize WGL and the core OpenGL library.  For this method
 * to return JNI_TRUE, the following must be true:
 *     - opengl32.dll must be loaded successfully (via LoadLibrary)
 *     - all core WGL/OGL function symbols from opengl32.dll must be
 *       available and loaded properly
 * If any of these requirements are not met, this method will return
 * JNI_FALSE, indicating there is no hope of using WGL/OpenGL for any
 * GraphicsConfig in the environment.
 */
JNIEXPORT jboolean JNICALL
Java_sun_java2d_opengl_WGLGraphicsConfig_initWGL(JNIEnv *env, jclass wglgc)
{
    J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_initWGL");

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

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

    return JNI_TRUE;
}

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

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_DestroyOGLContext");

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

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

    OGLContext_DestroyContextResources(oglc);

    ctxinfo = (WGLCtxInfo *)oglc->ctxInfo;
    if (ctxinfo != NULL) {
        // release the current context before we continue
        j2d_wglMakeCurrent(NULL, NULL);

        if (ctxinfo->context != 0) {
            j2d_wglDeleteContext(ctxinfo->context);
        }
        if (ctxinfo->scratchSurface != 0) {
            if (ctxinfo->scratchSurfaceDC != 0) {
                j2d_wglReleasePbufferDCARB(ctxinfo->scratchSurface,
                                           ctxinfo->scratchSurfaceDC);
            }
            j2d_wglDestroyPbufferARB(ctxinfo->scratchSurface);
        }

        free(ctxinfo);
    }

    free(oglc);
}

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

    J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig");

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

    if (wglinfo->context != NULL) {
        WGLGC_DestroyOGLContext(wglinfo->context);
    }

    free(wglinfo);
}

/**
 * Creates a temporary (non-visible) window that can be used for querying
 * the OpenGL capabilities of a given device.
 *
 * REMIND: should be able to create a window on a specific device...
 */
HWND
WGLGC_CreateScratchWindow(jint screennum)
{
    static jboolean firsttime = JNI_TRUE;

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateScratchWindow");

    if (firsttime) {
        WNDCLASS wc;

        // setup window class information
        ZeroMemory(&wc, sizeof(WNDCLASS));
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpfnWndProc = DefWindowProc;
        wc.lpszClassName = L"Tmp";
        if (RegisterClass(&wc) == 0) {
            J2dRlsTraceLn(J2D_TRACE_ERROR,
                "WGLGC_CreateScratchWindow: error registering window class");
            return 0;
        }

        firsttime = JNI_FALSE;
    }

    // create scratch window
    return CreateWindow(L"Tmp", L"Tmp", 0,
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, NULL, NULL,
                        GetModuleHandle(NULL), NULL);
}

/**
 * Returns a pixel format identifier that is suitable for Java 2D's needs
 * (must have a depth buffer, support for pbuffers, etc).  This method will
 * iterate through all pixel formats (if any) that match the requested
 * attributes and will attempt to find a pixel format with a minimal combined
 * depth+stencil buffer.  Note that we currently only need depth capabilities
 * (for shape clipping purposes), but wglChoosePixelFormatARB() will often
 * return a list of pixel formats 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 pixel format.  If no appropriate pixel
 * format can be found, this method returns 0.
 */
static int
WGLGC_GetPixelFormatForDC(HDC hdc)
{
    int attrs[] = {
        WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
        WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE,
        WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
        WGL_DEPTH_BITS_ARB, 16, // anything >= 16 will work for us
        0
    };
    int pixfmts[32];
    int chosenPixFmt = 0;
    int nfmts, i;

    // 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;

    J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC");

    // find all pixel formats (maximum of 32) with the provided attributes
    if (!j2d_wglChoosePixelFormatARB(hdc, attrs, NULL, 32, pixfmts, &nfmts)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_GetPixelFormatForDC: error choosing pixel format");
        return 0;
    }

    if (nfmts <= 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_GetPixelFormatForDC: no pixel formats found");
        return 0;
    }

    J2dRlsTraceLn(J2D_TRACE_VERBOSE, "  candidate pixel formats:");

    // iterate through the list of pixel formats, looking for the one that
    // meets our requirements while keeping the combined depth+stencil sizes
    // to a minimum
    for (i = 0; i < nfmts; i++) {
        int attrKeys[] = {
            WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB,
            WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB
        };
        int attrVals[4];
        int pixfmt = pixfmts[i];
        int depth, stencil, db, alpha;

        j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 4,
                                         attrKeys, attrVals);

        depth   = attrVals[0];
        stencil = attrVals[1];
        db      = attrVals[2];
        alpha   = attrVals[3];

        J2dRlsTrace5(J2D_TRACE_VERBOSE,
            "[V]     pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=",
                     pixfmt, db, alpha, depth, stencil);

        if ((depth + stencil) < minDepthPlusStencil) {
            J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n");
            minDepthPlusStencil = depth + stencil;
            chosenPixFmt = pixfmt;
        } else {
            J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n");
        }
    }

    if (chosenPixFmt == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_GetPixelFormatForDC: could not find appropriate pixfmt");
        return 0;
    }

    J2dRlsTraceLn1(J2D_TRACE_INFO,
        "WGLGC_GetPixelFormatForDC: chose %d as the best pixel format",
                   chosenPixFmt);

    return chosenPixFmt;
}

/**
 * Sets a "basic" pixel format for the given HDC.  This method is used only
 * for initializing a scratch window far enough such that we can load
 * GL/WGL extension function pointers using wglGetProcAddress.  (This method
 * differs from the one above in that it does not use wglChoosePixelFormatARB,
 * which is a WGL extension function, since we can't use that method without
 * first loading the extension functions under a "basic" pixel format.)
 */
static jboolean
WGLGC_SetBasicPixelFormatForDC(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
    int pixfmt;

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_SetBasicPixelFormatForDC");

    // find pixel format
    ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pixfmt = ChoosePixelFormat(hdc, &pfd);

    if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_SetBasicPixelFormatForDC: error setting pixel format");
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * Creates a context that is compatible with the given pixel format
 * identifier.  Returns 0 if the context could not be created properly.
 */
static HGLRC
WGLGC_CreateContext(jint screennum, jint pixfmt)
{
    PIXELFORMATDESCRIPTOR pfd;
    HWND hwnd;
    HDC hdc;
    HGLRC hglrc;

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateContext");

    hwnd = WGLGC_CreateScratchWindow(screennum);
    if (hwnd == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_CreateContext: could not create scratch window");
        return 0;
    }

    // get the HDC for the scratch window
    hdc = GetDC(hwnd);
    if (hdc == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_CreateContext: could not get dc for scratch window");
        DestroyWindow(hwnd);
        return 0;
    }

    // set the pixel format for the scratch window
    if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_CreateContext: error setting pixel format");
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0;
    }

    // create a context based on the scratch window
    hglrc = j2d_wglCreateContext(hdc);

    // release the temporary resources
    ReleaseDC(hwnd, hdc);
    DestroyWindow(hwnd);

    return hglrc;
}

/**
 * Initializes the extension function pointers for the given device.  Note
 * that under WGL, extension functions have different entrypoints depending
 * on the device, so we must first make a context current for the given
 * device before attempting to load the function pointers via
 * wglGetProcAddress.
 *
 * REMIND: ideally the extension function pointers would not be global, but
 *         rather would be stored in a structure associated with the
 *         WGLGraphicsConfig, so that we use the correct function entrypoint
 *         depending on the destination device...
 */
static jboolean
WGLGC_InitExtFuncs(jint screennum)
{
    HWND hwnd;
    HDC hdc;
    HGLRC context;

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitExtFuncs");

    // create a scratch window
    hwnd = WGLGC_CreateScratchWindow(screennum);
    if (hwnd == 0) {
        return JNI_FALSE;
    }

    // get the HDC for the scratch window
    hdc = GetDC(hwnd);
    if (hdc == 0) {
        DestroyWindow(hwnd);
        return JNI_FALSE;
    }

    // find and set a basic pixel format for the scratch window
    if (!WGLGC_SetBasicPixelFormatForDC(hdc)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_InitExtFuncs: could not find appropriate pixfmt");
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return JNI_FALSE;
    }

    // create a temporary context
    context = j2d_wglCreateContext(hdc);
    if (context == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_InitExtFuncs: could not create temp WGL context");
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return JNI_FALSE;
    }

    // make the context current so that we can load the function pointers
    // using wglGetProcAddress
    if (!j2d_wglMakeCurrent(hdc, context)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_InitExtFuncs: could not make temp context current");
        j2d_wglDeleteContext(context);
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return JNI_FALSE;
    }

    if (!OGLFuncs_InitExtFuncs()) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGC_InitExtFuncs: could not initialize extension funcs");
        j2d_wglMakeCurrent(NULL, NULL);
        j2d_wglDeleteContext(context);
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return JNI_FALSE;
    }

    // destroy the temporary resources
    j2d_wglMakeCurrent(NULL, NULL);
    j2d_wglDeleteContext(context);
    ReleaseDC(hwnd, hdc);
    DestroyWindow(hwnd);

    return JNI_TRUE;
}

/**
 * Initializes a new OGLContext, which includes the native WGL context handle
 * and some other important information such as the associated pixel format.
 */
static OGLContext *
WGLGC_InitOGLContext(jint pixfmt, HGLRC context,
                     HPBUFFERARB scratch, HDC scratchDC, jint caps)
{
    OGLContext *oglc;
    WGLCtxInfo *ctxinfo;

    J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitOGLContext");

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

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

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

    ctxinfo->context = context;
    ctxinfo->scratchSurface = scratch;
    ctxinfo->scratchSurfaceDC = scratchDC;
    oglc->ctxInfo = ctxinfo;
    oglc->caps = caps;

    return oglc;
}

/**
 * Determines whether the WGL pipeline can be used for a given GraphicsConfig
 * provided its screen number and visual ID.  If the minimum requirements are
 * met, the native WGLGraphicsConfigInfo structure is initialized for this
 * GraphicsConfig with the necessary information (pixel format, etc.)
 * and a pointer to this structure is returned as a jlong.  If
 * initialization fails at any point, zero is returned, indicating that WGL
 * cannot be used for this GraphicsConfig (we should fallback on the existing
 * DX pipeline).
 */
JNIEXPORT jlong JNICALL
Java_sun_java2d_opengl_WGLGraphicsConfig_getWGLConfigInfo(JNIEnv *env,
                                                          jclass wglgc,
                                                          jint screennum,
                                                          jint pixfmt)
{
    OGLContext *oglc;
    PIXELFORMATDESCRIPTOR pfd;
    HWND hwnd;
    HDC hdc;
    HGLRC context;
    HPBUFFERARB scratch;
    HDC scratchDC;
    WGLGraphicsConfigInfo *wglinfo;
    const unsigned char *versionstr;
    const char *extstr;
    jint caps = sun_java2d_opengl_OGLContext_CAPS_EMPTY;
    int attrKeys[] = { WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB };
    int attrVals[2];

    J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getWGLConfigInfo");

    // initialize GL/WGL extension functions
    if (!WGLGC_InitExtFuncs(screennum)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not init ext funcs");
        return 0L;
    }

    // create a scratch window
    hwnd = WGLGC_CreateScratchWindow(screennum);
    if (hwnd == 0) {
        return 0L;
    }

    // get the HDC for the scratch window
    hdc = GetDC(hwnd);
    if (hdc == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not get dc for scratch window");
        DestroyWindow(hwnd);
        return 0L;
    }

    if (pixfmt == 0) {
        // find an appropriate pixel format
        pixfmt = WGLGC_GetPixelFormatForDC(hdc);
        if (pixfmt == 0) {
            J2dRlsTraceLn(J2D_TRACE_ERROR,
                "WGLGraphicsConfig_getWGLConfigInfo: could not find appropriate pixfmt");
            ReleaseDC(hwnd, hdc);
            DestroyWindow(hwnd);
            return 0L;
        }
    }

    if (sharedContext == 0) {
        // create the one shared context
        sharedContext = WGLGC_CreateContext(screennum, pixfmt);
        if (sharedContext == 0) {
            J2dRlsTraceLn(J2D_TRACE_ERROR,
                "WGLGraphicsConfig_getWGLConfigInfo: could not create shared context");
            ReleaseDC(hwnd, hdc);
            DestroyWindow(hwnd);
            return 0L;
        }
    }

    // set the pixel format for the scratch window
    if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsconfig_getWGLConfigInfo: error setting pixel format");
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0L;
    }

    // create the HGLRC (context) for this WGLGraphicsConfig
    context = j2d_wglCreateContext(hdc);
    if (context == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not create WGL context");
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0L;
    }

    // REMIND: when using wglShareLists, the two contexts must use an
    //         identical pixel format...
    if (!j2d_wglShareLists(sharedContext, context)) {
        J2dRlsTraceLn(J2D_TRACE_WARNING,
            "WGLGraphicsConfig_getWGLConfigInfo: unable to share lists");
    }

    // make the context current so that we can query the OpenGL version
    // and extension strings
    if (!j2d_wglMakeCurrent(hdc, context)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not make temp context current");
        j2d_wglDeleteContext(context);
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0L;
    }

    // get version and extension strings
    versionstr = j2d_glGetString(GL_VERSION);
    extstr = j2d_wglGetExtensionsStringARB(hdc);
    OGLContext_GetExtensionInfo(env, &caps);

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

    if (!OGLContext_IsVersionSupported(versionstr)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: OpenGL 1.2 is required");
        j2d_wglMakeCurrent(NULL, NULL);
        j2d_wglDeleteContext(context);
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0L;
    }

    // check for required WGL extensions
    if (!OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pbuffer") ||
        !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_make_current_read")||
        !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pixel_format"))
    {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: required ext(s) unavailable");
        j2d_wglMakeCurrent(NULL, NULL);
        j2d_wglDeleteContext(context);
        ReleaseDC(hwnd, hdc);
        DestroyWindow(hwnd);
        return 0L;
    }

    // get config-specific capabilities
    j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 2, attrKeys, attrVals);
    if (attrVals[0]) {
        caps |= sun_java2d_opengl_OGLContext_CAPS_DOUBLEBUFFERED;
    }
    if (attrVals[1] > 0) {
        caps |= sun_java2d_opengl_OGLContext_CAPS_STORED_ALPHA;
    }

    // create the scratch pbuffer
    scratch = j2d_wglCreatePbufferARB(hdc, pixfmt, 1, 1, NULL);

    // destroy the temporary resources
    j2d_wglMakeCurrent(NULL, NULL);
    ReleaseDC(hwnd, hdc);
    DestroyWindow(hwnd);

    if (scratch == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not create scratch surface");
        j2d_wglDeleteContext(context);
        return 0L;
    }

    // get the HDC for the scratch pbuffer
    scratchDC = j2d_wglGetPbufferDCARB(scratch);
    if (scratchDC == 0) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not get hdc for scratch surface");
        j2d_wglDeleteContext(context);
        j2d_wglDestroyPbufferARB(scratch);
        return 0L;
    }

    // initialize the OGLContext, which wraps the pixfmt and HGLRC (context)
    oglc = WGLGC_InitOGLContext(pixfmt, context, scratch, scratchDC, caps);
    if (oglc == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not create oglc");
        j2d_wglDeleteContext(context);
        j2d_wglReleasePbufferDCARB(scratch, scratchDC);
        j2d_wglDestroyPbufferARB(scratch);
        return 0L;
    }

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

    // create the WGLGraphicsConfigInfo record for this config
    wglinfo = (WGLGraphicsConfigInfo *)malloc(sizeof(WGLGraphicsConfigInfo));
    if (wglinfo == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "WGLGraphicsConfig_getWGLConfigInfo: could not allocate memory for wglinfo");
        WGLGC_DestroyOGLContext(oglc);
        return 0L;
    }

    wglinfo->screen = screennum;
    wglinfo->pixfmt = pixfmt;
    wglinfo->context = oglc;

    return ptr_to_jlong(wglinfo);
}

JNIEXPORT jint JNICALL
Java_sun_java2d_opengl_WGLGraphicsConfig_getDefaultPixFmt(JNIEnv *env,
                                                          jclass wglgc,
                                                          jint screennum)
{
    J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getDefaultPixFmt");

    // REMIND: eventually we should implement this method so that it finds
    //         the most appropriate default pixel format for the given
    //         device; for now, we'll just return 0, and then we'll find
    //         an appropriate pixel format in WGLGC_GetWGLConfigInfo()...
    return 0;
}

JNIEXPORT jint JNICALL
Java_sun_java2d_opengl_WGLGraphicsConfig_getOGLCapabilities(JNIEnv *env,
                                                            jclass wglgc,
                                                            jlong configInfo)
{
    WGLGraphicsConfigInfo *wglinfo =
        (WGLGraphicsConfigInfo *)jlong_to_ptr(configInfo);

    J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getOGLCapabilities");

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

    return wglinfo->context->caps;
}
