1 /* 2 * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "sun_java2d_opengl_WGLGraphicsConfig.h" 30 31 #include "jni.h" 32 #include "jni_util.h" 33 #include "jlong.h" 34 #include "WGLGraphicsConfig.h" 35 #include "WGLSurfaceData.h" 36 37 /** 38 * This is a globally shared context used when creating textures. When any 39 * new contexts are created, they specify this context as the "share list" 40 * context, which means any texture objects created when this shared context 41 * is current will be available to any other context in any other thread. 42 */ 43 HGLRC sharedContext = 0; 44 45 /** 46 * Attempts to initialize WGL and the core OpenGL library. For this method 47 * to return JNI_TRUE, the following must be true: 48 * - opengl32.dll must be loaded successfully (via LoadLibrary) 49 * - all core WGL/OGL function symbols from opengl32.dll must be 50 * available and loaded properly 51 * If any of these requirements are not met, this method will return 52 * JNI_FALSE, indicating there is no hope of using WGL/OpenGL for any 53 * GraphicsConfig in the environment. 54 */ 55 JNIEXPORT jboolean JNICALL 56 Java_sun_java2d_opengl_WGLGraphicsConfig_initWGL(JNIEnv *env, jclass wglgc) 57 { 58 J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_initWGL"); 59 60 if (!OGLFuncs_OpenLibrary()) { 61 return JNI_FALSE; 62 } 63 64 if (!OGLFuncs_InitPlatformFuncs() || 65 !OGLFuncs_InitBaseFuncs()) 66 { 67 OGLFuncs_CloseLibrary(); 68 return JNI_FALSE; 69 } 70 71 return JNI_TRUE; 72 } 73 74 /** 75 * Disposes all memory and resources allocated for the given OGLContext. 76 */ 77 static void 78 WGLGC_DestroyOGLContext(OGLContext *oglc) 79 { 80 WGLCtxInfo *ctxinfo; 81 82 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_DestroyOGLContext"); 83 84 if (oglc == NULL) { 85 J2dRlsTraceLn(J2D_TRACE_ERROR, 86 "WGLGC_DestroyOGLContext: context is null"); 87 return; 88 } 89 90 // at this point, this context will be current to its scratch surface, 91 // so the following operations should be safe... 92 93 OGLContext_DestroyContextResources(oglc); 94 95 ctxinfo = (WGLCtxInfo *)oglc->ctxInfo; 96 if (ctxinfo != NULL) { 97 // release the current context before we continue 98 j2d_wglMakeCurrent(NULL, NULL); 99 100 if (ctxinfo->context != 0) { 101 j2d_wglDeleteContext(ctxinfo->context); 102 } 103 if (ctxinfo->scratchSurface != 0) { 104 if (ctxinfo->scratchSurfaceDC != 0) { 105 j2d_wglReleasePbufferDCARB(ctxinfo->scratchSurface, 106 ctxinfo->scratchSurfaceDC); 107 } 108 j2d_wglDestroyPbufferARB(ctxinfo->scratchSurface); 109 } 110 111 free(ctxinfo); 112 } 113 114 free(oglc); 115 } 116 117 /** 118 * Disposes all memory and resources associated with the given 119 * WGLGraphicsConfigInfo (including its native OGLContext data). 120 */ 121 void 122 OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo) 123 { 124 WGLGraphicsConfigInfo *wglinfo = 125 (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 126 127 J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig"); 128 129 if (wglinfo == NULL) { 130 J2dRlsTraceLn(J2D_TRACE_ERROR, 131 "OGLGC_DestroyOGLGraphicsConfig: info is null"); 132 return; 133 } 134 135 if (wglinfo->context != NULL) { 136 WGLGC_DestroyOGLContext(wglinfo->context); 137 } 138 139 free(wglinfo); 140 } 141 142 /** 143 * Creates a temporary (non-visible) window that can be used for querying 144 * the OpenGL capabilities of a given device. 145 * 146 * REMIND: should be able to create a window on a specific device... 147 */ 148 HWND 149 WGLGC_CreateScratchWindow(jint screennum) 150 { 151 static jboolean firsttime = JNI_TRUE; 152 153 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateScratchWindow"); 154 155 if (firsttime) { 156 WNDCLASS wc; 157 158 // setup window class information 159 ZeroMemory(&wc, sizeof(WNDCLASS)); 160 wc.hInstance = GetModuleHandle(NULL); 161 wc.lpfnWndProc = DefWindowProc; 162 wc.lpszClassName = L"Tmp"; 163 if (RegisterClass(&wc) == 0) { 164 J2dRlsTraceLn(J2D_TRACE_ERROR, 165 "WGLGC_CreateScratchWindow: error registering window class"); 166 return 0; 167 } 168 169 firsttime = JNI_FALSE; 170 } 171 172 // create scratch window 173 return CreateWindow(L"Tmp", L"Tmp", 0, 174 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 175 CW_USEDEFAULT, NULL, NULL, 176 GetModuleHandle(NULL), NULL); 177 } 178 179 /** 180 * Returns a pixel format identifier that is suitable for Java 2D's needs 181 * (must have a depth buffer, support for pbuffers, etc). This method will 182 * iterate through all pixel formats (if any) that match the requested 183 * attributes and will attempt to find a pixel format with a minimal combined 184 * depth+stencil buffer. Note that we currently only need depth capabilities 185 * (for shape clipping purposes), but wglChoosePixelFormatARB() will often 186 * return a list of pixel formats with the largest depth buffer (and stencil) 187 * sizes at the top of the list. Therefore, we scan through the whole list 188 * to find the most VRAM-efficient pixel format. If no appropriate pixel 189 * format can be found, this method returns 0. 190 */ 191 static int 192 WGLGC_GetPixelFormatForDC(HDC hdc) 193 { 194 int attrs[] = { 195 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 196 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, 197 WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE, 198 WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 199 WGL_DEPTH_BITS_ARB, 16, // anything >= 16 will work for us 200 0 201 }; 202 int pixfmts[32]; 203 int chosenPixFmt = 0; 204 int nfmts, i; 205 206 // this is the initial minimum value for the combined depth+stencil size 207 // (we initialize it to some absurdly high value; realistic values will 208 // be much less than this number) 209 int minDepthPlusStencil = 512; 210 211 J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC"); 212 213 // find all pixel formats (maximum of 32) with the provided attributes 214 if (!j2d_wglChoosePixelFormatARB(hdc, attrs, NULL, 32, pixfmts, &nfmts)) { 215 J2dRlsTraceLn(J2D_TRACE_ERROR, 216 "WGLGC_GetPixelFormatForDC: error choosing pixel format"); 217 return 0; 218 } 219 220 if (nfmts <= 0) { 221 J2dRlsTraceLn(J2D_TRACE_ERROR, 222 "WGLGC_GetPixelFormatForDC: no pixel formats found"); 223 return 0; 224 } 225 226 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate pixel formats:"); 227 228 // iterate through the list of pixel formats, looking for the one that 229 // meets our requirements while keeping the combined depth+stencil sizes 230 // to a minimum 231 for (i = 0; i < nfmts; i++) { 232 int attrKeys[] = { 233 WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, 234 WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB 235 }; 236 int attrVals[4]; 237 int pixfmt = pixfmts[i]; 238 int depth, stencil, db, alpha; 239 240 j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 4, 241 attrKeys, attrVals); 242 243 depth = attrVals[0]; 244 stencil = attrVals[1]; 245 db = attrVals[2]; 246 alpha = attrVals[3]; 247 248 J2dRlsTrace5(J2D_TRACE_VERBOSE, 249 "[V] pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=", 250 pixfmt, db, alpha, depth, stencil); 251 252 if ((depth + stencil) < minDepthPlusStencil) { 253 J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); 254 minDepthPlusStencil = depth + stencil; 255 chosenPixFmt = pixfmt; 256 } else { 257 J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n"); 258 } 259 } 260 261 if (chosenPixFmt == 0) { 262 J2dRlsTraceLn(J2D_TRACE_ERROR, 263 "WGLGC_GetPixelFormatForDC: could not find appropriate pixfmt"); 264 return 0; 265 } 266 267 J2dRlsTraceLn1(J2D_TRACE_INFO, 268 "WGLGC_GetPixelFormatForDC: chose %d as the best pixel format", 269 chosenPixFmt); 270 271 return chosenPixFmt; 272 } 273 274 /** 275 * Sets a "basic" pixel format for the given HDC. This method is used only 276 * for initializing a scratch window far enough such that we can load 277 * GL/WGL extension function pointers using wglGetProcAddress. (This method 278 * differs from the one above in that it does not use wglChoosePixelFormatARB, 279 * which is a WGL extension function, since we can't use that method without 280 * first loading the extension functions under a "basic" pixel format.) 281 */ 282 static jboolean 283 WGLGC_SetBasicPixelFormatForDC(HDC hdc) 284 { 285 PIXELFORMATDESCRIPTOR pfd; 286 int pixfmt; 287 288 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_SetBasicPixelFormatForDC"); 289 290 // find pixel format 291 ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); 292 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 293 pfd.nVersion = 1; 294 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 295 pfd.iPixelType = PFD_TYPE_RGBA; 296 pixfmt = ChoosePixelFormat(hdc, &pfd); 297 298 if (!SetPixelFormat(hdc, pixfmt, &pfd)) { 299 J2dRlsTraceLn(J2D_TRACE_ERROR, 300 "WGLGC_SetBasicPixelFormatForDC: error setting pixel format"); 301 return JNI_FALSE; 302 } 303 304 return JNI_TRUE; 305 } 306 307 /** 308 * Creates a context that is compatible with the given pixel format 309 * identifier. Returns 0 if the context could not be created properly. 310 */ 311 static HGLRC 312 WGLGC_CreateContext(jint screennum, jint pixfmt) 313 { 314 PIXELFORMATDESCRIPTOR pfd; 315 HWND hwnd; 316 HDC hdc; 317 HGLRC hglrc; 318 319 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_CreateContext"); 320 321 hwnd = WGLGC_CreateScratchWindow(screennum); 322 if (hwnd == 0) { 323 J2dRlsTraceLn(J2D_TRACE_ERROR, 324 "WGLGC_CreateContext: could not create scratch window"); 325 return 0; 326 } 327 328 // get the HDC for the scratch window 329 hdc = GetDC(hwnd); 330 if (hdc == 0) { 331 J2dRlsTraceLn(J2D_TRACE_ERROR, 332 "WGLGC_CreateContext: could not get dc for scratch window"); 333 DestroyWindow(hwnd); 334 return 0; 335 } 336 337 // set the pixel format for the scratch window 338 if (!SetPixelFormat(hdc, pixfmt, &pfd)) { 339 J2dRlsTraceLn(J2D_TRACE_ERROR, 340 "WGLGC_CreateContext: error setting pixel format"); 341 ReleaseDC(hwnd, hdc); 342 DestroyWindow(hwnd); 343 return 0; 344 } 345 346 // create a context based on the scratch window 347 hglrc = j2d_wglCreateContext(hdc); 348 349 // release the temporary resources 350 ReleaseDC(hwnd, hdc); 351 DestroyWindow(hwnd); 352 353 return hglrc; 354 } 355 356 /** 357 * Initializes the extension function pointers for the given device. Note 358 * that under WGL, extension functions have different entrypoints depending 359 * on the device, so we must first make a context current for the given 360 * device before attempting to load the function pointers via 361 * wglGetProcAddress. 362 * 363 * REMIND: ideally the extension function pointers would not be global, but 364 * rather would be stored in a structure associated with the 365 * WGLGraphicsConfig, so that we use the correct function entrypoint 366 * depending on the destination device... 367 */ 368 static jboolean 369 WGLGC_InitExtFuncs(jint screennum) 370 { 371 HWND hwnd; 372 HDC hdc; 373 HGLRC context; 374 375 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitExtFuncs"); 376 377 // create a scratch window 378 hwnd = WGLGC_CreateScratchWindow(screennum); 379 if (hwnd == 0) { 380 return JNI_FALSE; 381 } 382 383 // get the HDC for the scratch window 384 hdc = GetDC(hwnd); 385 if (hdc == 0) { 386 DestroyWindow(hwnd); 387 return JNI_FALSE; 388 } 389 390 // find and set a basic pixel format for the scratch window 391 if (!WGLGC_SetBasicPixelFormatForDC(hdc)) { 392 J2dRlsTraceLn(J2D_TRACE_ERROR, 393 "WGLGC_InitExtFuncs: could not find appropriate pixfmt"); 394 ReleaseDC(hwnd, hdc); 395 DestroyWindow(hwnd); 396 return JNI_FALSE; 397 } 398 399 // create a temporary context 400 context = j2d_wglCreateContext(hdc); 401 if (context == 0) { 402 J2dRlsTraceLn(J2D_TRACE_ERROR, 403 "WGLGC_InitExtFuncs: could not create temp WGL context"); 404 ReleaseDC(hwnd, hdc); 405 DestroyWindow(hwnd); 406 return JNI_FALSE; 407 } 408 409 // make the context current so that we can load the function pointers 410 // using wglGetProcAddress 411 if (!j2d_wglMakeCurrent(hdc, context)) { 412 J2dRlsTraceLn(J2D_TRACE_ERROR, 413 "WGLGC_InitExtFuncs: could not make temp context current"); 414 j2d_wglDeleteContext(context); 415 ReleaseDC(hwnd, hdc); 416 DestroyWindow(hwnd); 417 return JNI_FALSE; 418 } 419 420 if (!OGLFuncs_InitExtFuncs()) { 421 J2dRlsTraceLn(J2D_TRACE_ERROR, 422 "WGLGC_InitExtFuncs: could not initialize extension funcs"); 423 j2d_wglMakeCurrent(NULL, NULL); 424 j2d_wglDeleteContext(context); 425 ReleaseDC(hwnd, hdc); 426 DestroyWindow(hwnd); 427 return JNI_FALSE; 428 } 429 430 // destroy the temporary resources 431 j2d_wglMakeCurrent(NULL, NULL); 432 j2d_wglDeleteContext(context); 433 ReleaseDC(hwnd, hdc); 434 DestroyWindow(hwnd); 435 436 return JNI_TRUE; 437 } 438 439 /** 440 * Initializes a new OGLContext, which includes the native WGL context handle 441 * and some other important information such as the associated pixel format. 442 */ 443 static OGLContext * 444 WGLGC_InitOGLContext(jint pixfmt, HGLRC context, 445 HPBUFFERARB scratch, HDC scratchDC, jint caps) 446 { 447 OGLContext *oglc; 448 WGLCtxInfo *ctxinfo; 449 450 J2dTraceLn(J2D_TRACE_INFO, "WGLGC_InitOGLContext"); 451 452 oglc = (OGLContext *)malloc(sizeof(OGLContext)); 453 if (oglc == NULL) { 454 J2dRlsTraceLn(J2D_TRACE_ERROR, 455 "WGLGC_InitOGLContext: could not allocate memory for oglc"); 456 return NULL; 457 } 458 459 memset(oglc, 0, sizeof(OGLContext)); 460 461 ctxinfo = (WGLCtxInfo *)malloc(sizeof(WGLCtxInfo)); 462 if (ctxinfo == NULL) { 463 J2dRlsTraceLn(J2D_TRACE_ERROR, 464 "WGLGC_InitOGLContext: could not allocate memory for ctxinfo"); 465 free(oglc); 466 return NULL; 467 } 468 469 ctxinfo->context = context; 470 ctxinfo->scratchSurface = scratch; 471 ctxinfo->scratchSurfaceDC = scratchDC; 472 oglc->ctxInfo = ctxinfo; 473 oglc->caps = caps; 474 475 return oglc; 476 } 477 478 /** 479 * Determines whether the WGL pipeline can be used for a given GraphicsConfig 480 * provided its screen number and visual ID. If the minimum requirements are 481 * met, the native WGLGraphicsConfigInfo structure is initialized for this 482 * GraphicsConfig with the necessary information (pixel format, etc.) 483 * and a pointer to this structure is returned as a jlong. If 484 * initialization fails at any point, zero is returned, indicating that WGL 485 * cannot be used for this GraphicsConfig (we should fallback on the existing 486 * DX pipeline). 487 */ 488 JNIEXPORT jlong JNICALL 489 Java_sun_java2d_opengl_WGLGraphicsConfig_getWGLConfigInfo(JNIEnv *env, 490 jclass wglgc, 491 jint screennum, 492 jint pixfmt) 493 { 494 OGLContext *oglc; 495 PIXELFORMATDESCRIPTOR pfd; 496 HWND hwnd; 497 HDC hdc; 498 HGLRC context; 499 HPBUFFERARB scratch; 500 HDC scratchDC; 501 WGLGraphicsConfigInfo *wglinfo; 502 const unsigned char *versionstr; 503 const char *extstr; 504 jint caps = CAPS_EMPTY; 505 int attrKeys[] = { WGL_DOUBLE_BUFFER_ARB}; 506 int attrVals[1]; 507 508 J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getWGLConfigInfo"); 509 510 // initialize GL/WGL extension functions 511 if (!WGLGC_InitExtFuncs(screennum)) { 512 J2dRlsTraceLn(J2D_TRACE_ERROR, 513 "WGLGraphicsConfig_getWGLConfigInfo: could not init ext funcs"); 514 return 0L; 515 } 516 517 // create a scratch window 518 hwnd = WGLGC_CreateScratchWindow(screennum); 519 if (hwnd == 0) { 520 return 0L; 521 } 522 523 // get the HDC for the scratch window 524 hdc = GetDC(hwnd); 525 if (hdc == 0) { 526 J2dRlsTraceLn(J2D_TRACE_ERROR, 527 "WGLGraphicsConfig_getWGLConfigInfo: could not get dc for scratch window"); 528 DestroyWindow(hwnd); 529 return 0L; 530 } 531 532 if (pixfmt == 0) { 533 // find an appropriate pixel format 534 pixfmt = WGLGC_GetPixelFormatForDC(hdc); 535 if (pixfmt == 0) { 536 J2dRlsTraceLn(J2D_TRACE_ERROR, 537 "WGLGraphicsConfig_getWGLConfigInfo: could not find appropriate pixfmt"); 538 ReleaseDC(hwnd, hdc); 539 DestroyWindow(hwnd); 540 return 0L; 541 } 542 } 543 544 if (sharedContext == 0) { 545 // create the one shared context 546 sharedContext = WGLGC_CreateContext(screennum, pixfmt); 547 if (sharedContext == 0) { 548 J2dRlsTraceLn(J2D_TRACE_ERROR, 549 "WGLGraphicsConfig_getWGLConfigInfo: could not create shared context"); 550 ReleaseDC(hwnd, hdc); 551 DestroyWindow(hwnd); 552 return 0L; 553 } 554 } 555 556 // set the pixel format for the scratch window 557 if (!SetPixelFormat(hdc, pixfmt, &pfd)) { 558 J2dRlsTraceLn(J2D_TRACE_ERROR, 559 "WGLGraphicsconfig_getWGLConfigInfo: error setting pixel format"); 560 ReleaseDC(hwnd, hdc); 561 DestroyWindow(hwnd); 562 return 0L; 563 } 564 565 // create the HGLRC (context) for this WGLGraphicsConfig 566 context = j2d_wglCreateContext(hdc); 567 if (context == 0) { 568 J2dRlsTraceLn(J2D_TRACE_ERROR, 569 "WGLGraphicsConfig_getWGLConfigInfo: could not create WGL context"); 570 ReleaseDC(hwnd, hdc); 571 DestroyWindow(hwnd); 572 return 0L; 573 } 574 575 // REMIND: when using wglShareLists, the two contexts must use an 576 // identical pixel format... 577 if (!j2d_wglShareLists(sharedContext, context)) { 578 J2dRlsTraceLn(J2D_TRACE_WARNING, 579 "WGLGraphicsConfig_getWGLConfigInfo: unable to share lists"); 580 } 581 582 // make the context current so that we can query the OpenGL version 583 // and extension strings 584 if (!j2d_wglMakeCurrent(hdc, context)) { 585 J2dRlsTraceLn(J2D_TRACE_ERROR, 586 "WGLGraphicsConfig_getWGLConfigInfo: could not make temp context current"); 587 j2d_wglDeleteContext(context); 588 ReleaseDC(hwnd, hdc); 589 DestroyWindow(hwnd); 590 return 0L; 591 } 592 593 // get version and extension strings 594 versionstr = j2d_glGetString(GL_VERSION); 595 extstr = j2d_wglGetExtensionsStringARB(hdc); 596 OGLContext_GetExtensionInfo(env, &caps); 597 598 J2dRlsTraceLn1(J2D_TRACE_INFO, 599 "WGLGraphicsConfig_getWGLConfigInfo: OpenGL version=%s", 600 (versionstr == NULL) ? "null" : (char *)versionstr); 601 602 if (!OGLContext_IsVersionSupported(versionstr)) { 603 J2dRlsTraceLn(J2D_TRACE_ERROR, 604 "WGLGraphicsConfig_getWGLConfigInfo: OpenGL 1.2 is required"); 605 j2d_wglMakeCurrent(NULL, NULL); 606 j2d_wglDeleteContext(context); 607 ReleaseDC(hwnd, hdc); 608 DestroyWindow(hwnd); 609 return 0L; 610 } 611 612 // check for required WGL extensions 613 if (!OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pbuffer") || 614 !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_make_current_read")|| 615 !OGLContext_IsExtensionAvailable(extstr, "WGL_ARB_pixel_format")) 616 { 617 J2dRlsTraceLn(J2D_TRACE_ERROR, 618 "WGLGraphicsConfig_getWGLConfigInfo: required ext(s) unavailable"); 619 j2d_wglMakeCurrent(NULL, NULL); 620 j2d_wglDeleteContext(context); 621 ReleaseDC(hwnd, hdc); 622 DestroyWindow(hwnd); 623 return 0L; 624 } 625 626 // get config-specific capabilities 627 j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 1, attrKeys, attrVals); 628 if (attrVals[0]) { 629 caps |= CAPS_DOUBLEBUFFERED; 630 } 631 632 // create the scratch pbuffer 633 scratch = j2d_wglCreatePbufferARB(hdc, pixfmt, 1, 1, NULL); 634 635 // destroy the temporary resources 636 j2d_wglMakeCurrent(NULL, NULL); 637 ReleaseDC(hwnd, hdc); 638 DestroyWindow(hwnd); 639 640 if (scratch == 0) { 641 J2dRlsTraceLn(J2D_TRACE_ERROR, 642 "WGLGraphicsConfig_getWGLConfigInfo: could not create scratch surface"); 643 j2d_wglDeleteContext(context); 644 return 0L; 645 } 646 647 // get the HDC for the scratch pbuffer 648 scratchDC = j2d_wglGetPbufferDCARB(scratch); 649 if (scratchDC == 0) { 650 J2dRlsTraceLn(J2D_TRACE_ERROR, 651 "WGLGraphicsConfig_getWGLConfigInfo: could not get hdc for scratch surface"); 652 j2d_wglDeleteContext(context); 653 j2d_wglDestroyPbufferARB(scratch); 654 return 0L; 655 } 656 657 // initialize the OGLContext, which wraps the pixfmt and HGLRC (context) 658 oglc = WGLGC_InitOGLContext(pixfmt, context, scratch, scratchDC, caps); 659 if (oglc == NULL) { 660 J2dRlsTraceLn(J2D_TRACE_ERROR, 661 "WGLGraphicsConfig_getWGLConfigInfo: could not create oglc"); 662 j2d_wglDeleteContext(context); 663 j2d_wglReleasePbufferDCARB(scratch, scratchDC); 664 j2d_wglDestroyPbufferARB(scratch); 665 return 0L; 666 } 667 668 J2dTraceLn(J2D_TRACE_VERBOSE, 669 "WGLGraphicsConfig_getWGLConfigInfo: finished checking dependencies"); 670 671 // create the WGLGraphicsConfigInfo record for this config 672 wglinfo = (WGLGraphicsConfigInfo *)malloc(sizeof(WGLGraphicsConfigInfo)); 673 if (wglinfo == NULL) { 674 J2dRlsTraceLn(J2D_TRACE_ERROR, 675 "WGLGraphicsConfig_getWGLConfigInfo: could not allocate memory for wglinfo"); 676 WGLGC_DestroyOGLContext(oglc); 677 return 0L; 678 } 679 680 wglinfo->screen = screennum; 681 wglinfo->pixfmt = pixfmt; 682 wglinfo->context = oglc; 683 684 return ptr_to_jlong(wglinfo); 685 } 686 687 JNIEXPORT jint JNICALL 688 Java_sun_java2d_opengl_WGLGraphicsConfig_getDefaultPixFmt(JNIEnv *env, 689 jclass wglgc, 690 jint screennum) 691 { 692 J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getDefaultPixFmt"); 693 694 // REMIND: eventually we should implement this method so that it finds 695 // the most appropriate default pixel format for the given 696 // device; for now, we'll just return 0, and then we'll find 697 // an appropriate pixel format in WGLGC_GetWGLConfigInfo()... 698 return 0; 699 } 700 701 JNIEXPORT jint JNICALL 702 Java_sun_java2d_opengl_WGLGraphicsConfig_getOGLCapabilities(JNIEnv *env, 703 jclass wglgc, 704 jlong configInfo) 705 { 706 WGLGraphicsConfigInfo *wglinfo = 707 (WGLGraphicsConfigInfo *)jlong_to_ptr(configInfo); 708 709 J2dTraceLn(J2D_TRACE_INFO, "WGLGraphicsConfig_getOGLCapabilities"); 710 711 if (wglinfo == NULL || wglinfo->context == NULL) { 712 return CAPS_EMPTY; 713 } 714 715 return wglinfo->context->caps; 716 }