| /* | |
| * Copyright (c) 2004, 2015, Oracle and/or its affiliates. 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. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.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 = CAPS_EMPTY; | |
| int attrKeys[] = { WGL_DOUBLE_BUFFER_ARB}; | |
| int attrVals[1]; | |
| 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, 1, attrKeys, attrVals); | |
| if (attrVals[0]) { | |
| caps |= CAPS_DOUBLEBUFFERED; | |
| } | |
| // 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 CAPS_EMPTY; | |
| } | |
| return wglinfo->context->caps; | |
| } |