0N/A/*
2362N/A * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <stdlib.h>
0N/A#include <string.h>
0N/A
0N/A#include "sun_java2d_opengl_WGLGraphicsConfig.h"
0N/A
0N/A#include "jni.h"
0N/A#include "jni_util.h"
0N/A#include "jlong.h"
0N/A#include "WGLGraphicsConfig.h"
0N/A#include "WGLSurfaceData.h"
0N/A
0N/A/**
0N/A * This is a globally shared context used when creating textures. When any
0N/A * new contexts are created, they specify this context as the "share list"
0N/A * context, which means any texture objects created when this shared context
0N/A * is current will be available to any other context in any other thread.
0N/A */
0N/AHGLRC sharedContext = 0;
0N/A
0N/A/**
0N/A * Attempts to initialize WGL and the core OpenGL library. For this method
0N/A * to return JNI_TRUE, the following must be true:
0N/A * - opengl32.dll must be loaded successfully (via LoadLibrary)
0N/A * - all core WGL/OGL function symbols from opengl32.dll must be
0N/A * available and loaded properly
0N/A * If any of these requirements are not met, this method will return
0N/A * JNI_FALSE, indicating there is no hope of using WGL/OpenGL for any
0N/A * GraphicsConfig in the environment.
0N/A */
0N/AJNIEXPORT jboolean JNICALL
0N/AJava_sun_java2d_opengl_WGLGraphicsConfig_initWGL(JNIEnv *env, jclass wglgc)
0N/A{
0N/A J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_initWGL");
0N/A
0N/A if (!OGLFuncs_OpenLibrary()) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A if (!OGLFuncs_InitPlatformFuncs() ||
0N/A !OGLFuncs_InitBaseFuncs())
0N/A {
0N/A OGLFuncs_CloseLibrary();
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A/**
0N/A * Disposes all memory and resources allocated for the given OGLContext.
0N/A */
0N/Astatic void
0N/AWGLGC_DestroyOGLContext(OGLContext *oglc)
0N/A{
0N/A WGLCtxInfo *ctxinfo;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_DestroyOGLContext");
0N/A
0N/A if (oglc == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_DestroyOGLContext: context is null");
0N/A return;
0N/A }
0N/A
0N/A // at this point, this context will be current to its scratch surface,
0N/A // so the following operations should be safe...
0N/A
0N/A OGLContext_DestroyContextResources(oglc);
0N/A
0N/A ctxinfo = (WGLCtxInfo *)oglc->ctxInfo;
0N/A if (ctxinfo != NULL) {
0N/A // release the current context before we continue
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A
0N/A if (ctxinfo->context != 0) {
0N/A j2d_wglDeleteContext(ctxinfo->context);
0N/A }
0N/A if (ctxinfo->scratchSurface != 0) {
0N/A if (ctxinfo->scratchSurfaceDC != 0) {
0N/A j2d_wglReleasePbufferDCARB(ctxinfo->scratchSurface,
0N/A ctxinfo->scratchSurfaceDC);
0N/A }
0N/A j2d_wglDestroyPbufferARB(ctxinfo->scratchSurface);
0N/A }
0N/A
0N/A free(ctxinfo);
0N/A }
0N/A
0N/A free(oglc);
0N/A}
0N/A
0N/A/**
0N/A * Disposes all memory and resources associated with the given
0N/A * WGLGraphicsConfigInfo (including its native OGLContext data).
0N/A */
0N/Avoid
0N/AOGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo)
0N/A{
0N/A WGLGraphicsConfigInfo *wglinfo =
0N/A (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig");
0N/A
0N/A if (wglinfo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLGC_DestroyOGLGraphicsConfig: info is null");
0N/A return;
0N/A }
0N/A
0N/A if (wglinfo->context != NULL) {
0N/A WGLGC_DestroyOGLContext(wglinfo->context);
0N/A }
0N/A
0N/A free(wglinfo);
0N/A}
0N/A
0N/A/**
0N/A * Creates a temporary (non-visible) window that can be used for querying
0N/A * the OpenGL capabilities of a given device.
0N/A *
0N/A * REMIND: should be able to create a window on a specific device...
0N/A */
0N/AHWND
0N/AWGLGC_CreateScratchWindow(jint screennum)
0N/A{
0N/A static jboolean firsttime = JNI_TRUE;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateScratchWindow");
0N/A
0N/A if (firsttime) {
0N/A WNDCLASS wc;
0N/A
0N/A // setup window class information
0N/A ZeroMemory(&wc, sizeof(WNDCLASS));
0N/A wc.hInstance = GetModuleHandle(NULL);
0N/A wc.lpfnWndProc = DefWindowProc;
0N/A wc.lpszClassName = L"Tmp";
0N/A if (RegisterClass(&wc) == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_CreateScratchWindow: error registering window class");
0N/A return 0;
0N/A }
0N/A
0N/A firsttime = JNI_FALSE;
0N/A }
0N/A
0N/A // create scratch window
0N/A return CreateWindow(L"Tmp", L"Tmp", 0,
0N/A CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0N/A CW_USEDEFAULT, NULL, NULL,
0N/A GetModuleHandle(NULL), NULL);
0N/A}
0N/A
0N/A/**
0N/A * Returns a pixel format identifier that is suitable for Java 2D's needs
0N/A * (must have a depth buffer, support for pbuffers, etc). This method will
0N/A * iterate through all pixel formats (if any) that match the requested
0N/A * attributes and will attempt to find a pixel format with a minimal combined
0N/A * depth+stencil buffer. Note that we currently only need depth capabilities
0N/A * (for shape clipping purposes), but wglChoosePixelFormatARB() will often
0N/A * return a list of pixel formats with the largest depth buffer (and stencil)
0N/A * sizes at the top of the list. Therefore, we scan through the whole list
0N/A * to find the most VRAM-efficient pixel format. If no appropriate pixel
0N/A * format can be found, this method returns 0.
0N/A */
0N/Astatic int
0N/AWGLGC_GetPixelFormatForDC(HDC hdc)
0N/A{
0N/A int attrs[] = {
0N/A WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
0N/A WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
0N/A WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE,
0N/A WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
0N/A WGL_DEPTH_BITS_ARB, 16, // anything >= 16 will work for us
0N/A 0
0N/A };
0N/A int pixfmts[32];
0N/A int chosenPixFmt = 0;
0N/A int nfmts, i;
0N/A
0N/A // this is the initial minimum value for the combined depth+stencil size
0N/A // (we initialize it to some absurdly high value; realistic values will
0N/A // be much less than this number)
0N/A int minDepthPlusStencil = 512;
0N/A
0N/A J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC");
0N/A
0N/A // find all pixel formats (maximum of 32) with the provided attributes
0N/A if (!j2d_wglChoosePixelFormatARB(hdc, attrs, NULL, 32, pixfmts, &nfmts)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_GetPixelFormatForDC: error choosing pixel format");
0N/A return 0;
0N/A }
0N/A
0N/A if (nfmts <= 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_GetPixelFormatForDC: no pixel formats found");
0N/A return 0;
0N/A }
0N/A
0N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate pixel formats:");
0N/A
0N/A // iterate through the list of pixel formats, looking for the one that
0N/A // meets our requirements while keeping the combined depth+stencil sizes
0N/A // to a minimum
0N/A for (i = 0; i < nfmts; i++) {
0N/A int attrKeys[] = {
0N/A WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB,
0N/A WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB
0N/A };
0N/A int attrVals[4];
0N/A int pixfmt = pixfmts[i];
0N/A int depth, stencil, db, alpha;
0N/A
0N/A j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 4,
0N/A attrKeys, attrVals);
0N/A
0N/A depth = attrVals[0];
0N/A stencil = attrVals[1];
0N/A db = attrVals[2];
0N/A alpha = attrVals[3];
0N/A
0N/A J2dRlsTrace5(J2D_TRACE_VERBOSE,
0N/A "[V] pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=",
0N/A pixfmt, db, alpha, depth, stencil);
0N/A
0N/A if ((depth + stencil) < minDepthPlusStencil) {
0N/A J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n");
0N/A minDepthPlusStencil = depth + stencil;
0N/A chosenPixFmt = pixfmt;
0N/A } else {
0N/A J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n");
0N/A }
0N/A }
0N/A
0N/A if (chosenPixFmt == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_GetPixelFormatForDC: could not find appropriate pixfmt");
0N/A return 0;
0N/A }
0N/A
0N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
0N/A "WGLGC_GetPixelFormatForDC: chose %d as the best pixel format",
0N/A chosenPixFmt);
0N/A
0N/A return chosenPixFmt;
0N/A}
0N/A
0N/A/**
0N/A * Sets a "basic" pixel format for the given HDC. This method is used only
0N/A * for initializing a scratch window far enough such that we can load
0N/A * GL/WGL extension function pointers using wglGetProcAddress. (This method
0N/A * differs from the one above in that it does not use wglChoosePixelFormatARB,
0N/A * which is a WGL extension function, since we can't use that method without
0N/A * first loading the extension functions under a "basic" pixel format.)
0N/A */
0N/Astatic jboolean
0N/AWGLGC_SetBasicPixelFormatForDC(HDC hdc)
0N/A{
0N/A PIXELFORMATDESCRIPTOR pfd;
0N/A int pixfmt;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_SetBasicPixelFormatForDC");
0N/A
0N/A // find pixel format
0N/A ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
0N/A pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
0N/A pfd.nVersion = 1;
0N/A pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
0N/A pfd.iPixelType = PFD_TYPE_RGBA;
0N/A pixfmt = ChoosePixelFormat(hdc, &pfd);
0N/A
0N/A if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_SetBasicPixelFormatForDC: error setting pixel format");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A/**
0N/A * Creates a context that is compatible with the given pixel format
0N/A * identifier. Returns 0 if the context could not be created properly.
0N/A */
0N/Astatic HGLRC
0N/AWGLGC_CreateContext(jint screennum, jint pixfmt)
0N/A{
0N/A PIXELFORMATDESCRIPTOR pfd;
0N/A HWND hwnd;
0N/A HDC hdc;
0N/A HGLRC hglrc;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateContext");
0N/A
0N/A hwnd = WGLGC_CreateScratchWindow(screennum);
0N/A if (hwnd == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_CreateContext: could not create scratch window");
0N/A return 0;
0N/A }
0N/A
0N/A // get the HDC for the scratch window
0N/A hdc = GetDC(hwnd);
0N/A if (hdc == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_CreateContext: could not get dc for scratch window");
0N/A DestroyWindow(hwnd);
0N/A return 0;
0N/A }
0N/A
0N/A // set the pixel format for the scratch window
0N/A if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_CreateContext: error setting pixel format");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0;
0N/A }
0N/A
0N/A // create a context based on the scratch window
0N/A hglrc = j2d_wglCreateContext(hdc);
0N/A
0N/A // release the temporary resources
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A
0N/A return hglrc;
0N/A}
0N/A
0N/A/**
0N/A * Initializes the extension function pointers for the given device. Note
0N/A * that under WGL, extension functions have different entrypoints depending
0N/A * on the device, so we must first make a context current for the given
0N/A * device before attempting to load the function pointers via
0N/A * wglGetProcAddress.
0N/A *
0N/A * REMIND: ideally the extension function pointers would not be global, but
0N/A * rather would be stored in a structure associated with the
0N/A * WGLGraphicsConfig, so that we use the correct function entrypoint
0N/A * depending on the destination device...
0N/A */
0N/Astatic jboolean
0N/AWGLGC_InitExtFuncs(jint screennum)
0N/A{
0N/A HWND hwnd;
0N/A HDC hdc;
0N/A HGLRC context;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitExtFuncs");
0N/A
0N/A // create a scratch window
0N/A hwnd = WGLGC_CreateScratchWindow(screennum);
0N/A if (hwnd == 0) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A // get the HDC for the scratch window
0N/A hdc = GetDC(hwnd);
0N/A if (hdc == 0) {
0N/A DestroyWindow(hwnd);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A // find and set a basic pixel format for the scratch window
0N/A if (!WGLGC_SetBasicPixelFormatForDC(hdc)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitExtFuncs: could not find appropriate pixfmt");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A // create a temporary context
0N/A context = j2d_wglCreateContext(hdc);
0N/A if (context == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitExtFuncs: could not create temp WGL context");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A // make the context current so that we can load the function pointers
0N/A // using wglGetProcAddress
0N/A if (!j2d_wglMakeCurrent(hdc, context)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitExtFuncs: could not make temp context current");
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A if (!OGLFuncs_InitExtFuncs()) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitExtFuncs: could not initialize extension funcs");
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A // destroy the temporary resources
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A/**
0N/A * Initializes a new OGLContext, which includes the native WGL context handle
0N/A * and some other important information such as the associated pixel format.
0N/A */
0N/Astatic OGLContext *
0N/AWGLGC_InitOGLContext(jint pixfmt, HGLRC context,
0N/A HPBUFFERARB scratch, HDC scratchDC, jint caps)
0N/A{
0N/A OGLContext *oglc;
0N/A WGLCtxInfo *ctxinfo;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitOGLContext");
0N/A
0N/A oglc = (OGLContext *)malloc(sizeof(OGLContext));
0N/A if (oglc == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitOGLContext: could not allocate memory for oglc");
0N/A return NULL;
0N/A }
0N/A
0N/A memset(oglc, 0, sizeof(OGLContext));
0N/A
0N/A ctxinfo = (WGLCtxInfo *)malloc(sizeof(WGLCtxInfo));
0N/A if (ctxinfo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGC_InitOGLContext: could not allocate memory for ctxinfo");
0N/A free(oglc);
0N/A return NULL;
0N/A }
0N/A
0N/A ctxinfo->context = context;
0N/A ctxinfo->scratchSurface = scratch;
0N/A ctxinfo->scratchSurfaceDC = scratchDC;
0N/A oglc->ctxInfo = ctxinfo;
0N/A oglc->caps = caps;
0N/A
0N/A return oglc;
0N/A}
0N/A
0N/A/**
0N/A * Determines whether the WGL pipeline can be used for a given GraphicsConfig
0N/A * provided its screen number and visual ID. If the minimum requirements are
0N/A * met, the native WGLGraphicsConfigInfo structure is initialized for this
0N/A * GraphicsConfig with the necessary information (pixel format, etc.)
0N/A * and a pointer to this structure is returned as a jlong. If
0N/A * initialization fails at any point, zero is returned, indicating that WGL
0N/A * cannot be used for this GraphicsConfig (we should fallback on the existing
0N/A * DX pipeline).
0N/A */
0N/AJNIEXPORT jlong JNICALL
0N/AJava_sun_java2d_opengl_WGLGraphicsConfig_getWGLConfigInfo(JNIEnv *env,
0N/A jclass wglgc,
0N/A jint screennum,
0N/A jint pixfmt)
0N/A{
0N/A OGLContext *oglc;
0N/A PIXELFORMATDESCRIPTOR pfd;
0N/A HWND hwnd;
0N/A HDC hdc;
0N/A HGLRC context;
0N/A HPBUFFERARB scratch;
0N/A HDC scratchDC;
0N/A WGLGraphicsConfigInfo *wglinfo;
0N/A const unsigned char *versionstr;
0N/A const char *extstr;
430N/A jint caps = CAPS_EMPTY;
0N/A int attrKeys[] = { WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB };
0N/A int attrVals[2];
0N/A
0N/A J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getWGLConfigInfo");
0N/A
0N/A // initialize GL/WGL extension functions
0N/A if (!WGLGC_InitExtFuncs(screennum)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not init ext funcs");
0N/A return 0L;
0N/A }
0N/A
0N/A // create a scratch window
0N/A hwnd = WGLGC_CreateScratchWindow(screennum);
0N/A if (hwnd == 0) {
0N/A return 0L;
0N/A }
0N/A
0N/A // get the HDC for the scratch window
0N/A hdc = GetDC(hwnd);
0N/A if (hdc == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not get dc for scratch window");
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A if (pixfmt == 0) {
0N/A // find an appropriate pixel format
0N/A pixfmt = WGLGC_GetPixelFormatForDC(hdc);
0N/A if (pixfmt == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not find appropriate pixfmt");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A }
0N/A
0N/A if (sharedContext == 0) {
0N/A // create the one shared context
0N/A sharedContext = WGLGC_CreateContext(screennum, pixfmt);
0N/A if (sharedContext == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not create shared context");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A }
0N/A
0N/A // set the pixel format for the scratch window
0N/A if (!SetPixelFormat(hdc, pixfmt, &pfd)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsconfig_getWGLConfigInfo: error setting pixel format");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A // create the HGLRC (context) for this WGLGraphicsConfig
0N/A context = j2d_wglCreateContext(hdc);
0N/A if (context == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not create WGL context");
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A // REMIND: when using wglShareLists, the two contexts must use an
0N/A // identical pixel format...
0N/A if (!j2d_wglShareLists(sharedContext, context)) {
0N/A J2dRlsTraceLn(J2D_TRACE_WARNING,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: unable to share lists");
0N/A }
0N/A
0N/A // make the context current so that we can query the OpenGL version
0N/A // and extension strings
0N/A if (!j2d_wglMakeCurrent(hdc, context)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not make temp context current");
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A // get version and extension strings
0N/A versionstr = j2d_glGetString(GL_VERSION);
0N/A extstr = j2d_wglGetExtensionsStringARB(hdc);
0N/A OGLContext_GetExtensionInfo(env, &caps);
0N/A
0N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: OpenGL version=%s",
0N/A (versionstr == NULL) ? "null" : (char *)versionstr);
0N/A
0N/A if (!OGLContext_IsVersionSupported(versionstr)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: OpenGL 1.2 is required");
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A // check for required WGL extensions
0N/A if (!OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pbuffer") ||
0N/A !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_make_current_read")||
0N/A !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pixel_format"))
0N/A {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: required ext(s) unavailable");
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A j2d_wglDeleteContext(context);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A return 0L;
0N/A }
0N/A
0N/A // get config-specific capabilities
0N/A j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 2, attrKeys, attrVals);
0N/A if (attrVals[0]) {
430N/A caps |= CAPS_DOUBLEBUFFERED;
0N/A }
0N/A if (attrVals[1] > 0) {
430N/A caps |= CAPS_STORED_ALPHA;
0N/A }
0N/A
0N/A // create the scratch pbuffer
0N/A scratch = j2d_wglCreatePbufferARB(hdc, pixfmt, 1, 1, NULL);
0N/A
0N/A // destroy the temporary resources
0N/A j2d_wglMakeCurrent(NULL, NULL);
0N/A ReleaseDC(hwnd, hdc);
0N/A DestroyWindow(hwnd);
0N/A
0N/A if (scratch == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not create scratch surface");
0N/A j2d_wglDeleteContext(context);
0N/A return 0L;
0N/A }
0N/A
0N/A // get the HDC for the scratch pbuffer
0N/A scratchDC = j2d_wglGetPbufferDCARB(scratch);
0N/A if (scratchDC == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not get hdc for scratch surface");
0N/A j2d_wglDeleteContext(context);
0N/A j2d_wglDestroyPbufferARB(scratch);
0N/A return 0L;
0N/A }
0N/A
0N/A // initialize the OGLContext, which wraps the pixfmt and HGLRC (context)
0N/A oglc = WGLGC_InitOGLContext(pixfmt, context, scratch, scratchDC, caps);
0N/A if (oglc == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not create oglc");
0N/A j2d_wglDeleteContext(context);
0N/A j2d_wglReleasePbufferDCARB(scratch, scratchDC);
0N/A j2d_wglDestroyPbufferARB(scratch);
0N/A return 0L;
0N/A }
0N/A
0N/A J2dTraceLn(J2D_TRACE_VERBOSE,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: finished checking dependencies");
0N/A
0N/A // create the WGLGraphicsConfigInfo record for this config
0N/A wglinfo = (WGLGraphicsConfigInfo *)malloc(sizeof(WGLGraphicsConfigInfo));
0N/A if (wglinfo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "WGLGraphicsConfig_getWGLConfigInfo: could not allocate memory for wglinfo");
0N/A WGLGC_DestroyOGLContext(oglc);
0N/A return 0L;
0N/A }
0N/A
0N/A wglinfo->screen = screennum;
0N/A wglinfo->pixfmt = pixfmt;
0N/A wglinfo->context = oglc;
0N/A
0N/A return ptr_to_jlong(wglinfo);
0N/A}
0N/A
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_java2d_opengl_WGLGraphicsConfig_getDefaultPixFmt(JNIEnv *env,
0N/A jclass wglgc,
0N/A jint screennum)
0N/A{
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getDefaultPixFmt");
0N/A
0N/A // REMIND: eventually we should implement this method so that it finds
0N/A // the most appropriate default pixel format for the given
0N/A // device; for now, we'll just return 0, and then we'll find
0N/A // an appropriate pixel format in WGLGC_GetWGLConfigInfo()...
0N/A return 0;
0N/A}
0N/A
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_java2d_opengl_WGLGraphicsConfig_getOGLCapabilities(JNIEnv *env,
0N/A jclass wglgc,
0N/A jlong configInfo)
0N/A{
0N/A WGLGraphicsConfigInfo *wglinfo =
0N/A (WGLGraphicsConfigInfo *)jlong_to_ptr(configInfo);
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getOGLCapabilities");
0N/A
0N/A if (wglinfo == NULL || wglinfo->context == NULL) {
430N/A return CAPS_EMPTY;
0N/A }
0N/A
0N/A return wglinfo->context->caps;
0N/A}