1 /* 2 * Copyright (c) 2003, 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_GLXGraphicsConfig.h" 30 31 #include "jni.h" 32 #include "jlong.h" 33 #include "GLXGraphicsConfig.h" 34 #include "GLXSurfaceData.h" 35 #include "awt_GraphicsEnv.h" 36 #include "awt_util.h" 37 38 #ifndef HEADLESS 39 40 extern Bool usingXinerama; 41 42 /** 43 * This is a globally shared context used when creating textures. When any 44 * new contexts are created, they specify this context as the "share list" 45 * context, which means any texture objects created when this shared context 46 * is current will be available to any other context. 47 */ 48 static GLXContext sharedContext = 0; 49 50 /** 51 * Attempts to initialize GLX and the core OpenGL library. For this method 52 * to return JNI_TRUE, the following must be true: 53 * - libGL must be loaded successfully (via dlopen) 54 * - all function symbols from libGL must be available and loaded properly 55 * - the GLX extension must be available through X11 56 * - client GLX version must be >= 1.3 57 * If any of these requirements are not met, this method will return 58 * JNI_FALSE, indicating there is no hope of using GLX/OpenGL for any 59 * GraphicsConfig in the environment. 60 */ 61 static jboolean 62 GLXGC_InitGLX() 63 { 64 int errorbase, eventbase; 65 const char *version; 66 67 J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGC_InitGLX"); 68 69 if (!OGLFuncs_OpenLibrary()) { 70 return JNI_FALSE; 71 } 72 73 if (!OGLFuncs_InitPlatformFuncs() || 74 !OGLFuncs_InitBaseFuncs() || 75 !OGLFuncs_InitExtFuncs()) 76 { 77 OGLFuncs_CloseLibrary(); 78 return JNI_FALSE; 79 } 80 81 if (!j2d_glXQueryExtension(awt_display, &errorbase, &eventbase)) { 82 J2dRlsTraceLn(J2D_TRACE_ERROR, 83 "GLXGC_InitGLX: GLX extension is not present"); 84 OGLFuncs_CloseLibrary(); 85 return JNI_FALSE; 86 } 87 88 version = j2d_glXGetClientString(awt_display, GLX_VERSION); 89 if (version == NULL) { 90 J2dRlsTraceLn(J2D_TRACE_ERROR, 91 "GLXGC_InitGLX: could not query GLX version"); 92 OGLFuncs_CloseLibrary(); 93 return JNI_FALSE; 94 } 95 96 // we now only verify that the client GLX version is >= 1.3 (if the 97 // server does not support GLX 1.3, then we will find that out later 98 // when we attempt to create a GLXFBConfig) 99 J2dRlsTraceLn1(J2D_TRACE_INFO, 100 "GLXGC_InitGLX: client GLX version=%s", version); 101 if (!((version[0] == '1' && version[2] >= '3') || (version[0] > '1'))) { 102 J2dRlsTraceLn(J2D_TRACE_ERROR, 103 "GLXGC_InitGLX: invalid GLX version; 1.3 is required"); 104 OGLFuncs_CloseLibrary(); 105 return JNI_FALSE; 106 } 107 108 return JNI_TRUE; 109 } 110 111 /** 112 * Returns JNI_TRUE if GLX is available for the current display. Note that 113 * this method will attempt to initialize GLX (and all the necessary function 114 * symbols) if it has not been already. The AWT_LOCK must be acquired before 115 * calling this method. 116 */ 117 jboolean 118 GLXGC_IsGLXAvailable() 119 { 120 static jboolean glxAvailable = JNI_FALSE; 121 static jboolean firstTime = JNI_TRUE; 122 123 J2dTraceLn(J2D_TRACE_INFO, "GLXGC_IsGLXAvailable"); 124 125 if (firstTime) { 126 glxAvailable = GLXGC_InitGLX(); 127 firstTime = JNI_FALSE; 128 } 129 130 return glxAvailable; 131 } 132 133 /** 134 * Disposes all memory and resources allocated for the given OGLContext. 135 */ 136 static void 137 GLXGC_DestroyOGLContext(OGLContext *oglc) 138 { 139 GLXCtxInfo *ctxinfo; 140 141 J2dTraceLn(J2D_TRACE_INFO, "GLXGC_DestroyOGLContext"); 142 143 if (oglc == NULL) { 144 J2dRlsTraceLn(J2D_TRACE_ERROR, 145 "GLXGC_DestroyOGLContext: context is null"); 146 return; 147 } 148 149 // at this point, this context will be current to its scratch surface 150 // so the following GL/GLX operations should be safe... 151 152 OGLContext_DestroyContextResources(oglc); 153 154 ctxinfo = (GLXCtxInfo *)oglc->ctxInfo; 155 if (ctxinfo != NULL) { 156 // release the current context before we continue 157 j2d_glXMakeContextCurrent(awt_display, None, None, NULL); 158 159 if (ctxinfo->context != 0) { 160 j2d_glXDestroyContext(awt_display, ctxinfo->context); 161 } 162 if (ctxinfo->scratchSurface != 0) { 163 j2d_glXDestroyPbuffer(awt_display, ctxinfo->scratchSurface); 164 } 165 166 free(ctxinfo); 167 } 168 169 free(oglc); 170 } 171 172 /** 173 * Disposes all memory and resources associated with the given 174 * GLXGraphicsConfigInfo (including its native OGLContext data). 175 */ 176 void 177 OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo) 178 { 179 GLXGraphicsConfigInfo *glxinfo = 180 (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 181 182 J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig"); 183 184 if (glxinfo == NULL) { 185 J2dRlsTraceLn(J2D_TRACE_ERROR, 186 "OGLGC_DestroyOGLGraphicsConfig: info is null"); 187 return; 188 } 189 190 if (glxinfo->context != NULL) { 191 GLXGC_DestroyOGLContext(glxinfo->context); 192 } 193 194 free(glxinfo); 195 } 196 197 /** 198 * Attempts to create a new GLXFBConfig for the requested screen and visual. 199 * If visualid is 0, this method will iterate through all GLXFBConfigs (if 200 * any) that match the requested attributes and will attempt to find an 201 * fbconfig with a minimal combined depth+stencil buffer. Note that we 202 * currently only need depth capabilities (for shape clipping purposes), but 203 * glXChooseFBConfig() will often return a list of fbconfigs with the largest 204 * depth buffer (and stencil) sizes at the top of the list. Therefore, we 205 * scan through the whole list to find the most VRAM-efficient fbconfig. 206 * If visualid is non-zero, the GLXFBConfig associated with the given visual 207 * is chosen (assuming it meets the requested attributes). If there are no 208 * valid GLXFBConfigs available, this method returns 0. 209 */ 210 static GLXFBConfig 211 GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid) 212 { 213 GLXFBConfig *fbconfigs; 214 GLXFBConfig chosenConfig = 0; 215 int nconfs, i; 216 int attrlist[] = {GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT, 217 GLX_RENDER_TYPE, GLX_RGBA_BIT, 218 GLX_CONFIG_CAVEAT, GLX_NONE, // avoid "slow" configs 219 GLX_DEPTH_SIZE, 16, // anything >= 16 will work for us 220 0}; 221 222 // this is the initial minimum value for the combined depth+stencil size 223 // (we initialize it to some absurdly high value; realistic values will 224 // be much less than this number) 225 int minDepthPlusStencil = 512; 226 227 J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x", 228 screennum, visualid); 229 230 // find all fbconfigs for this screen with the provided attributes 231 fbconfigs = j2d_glXChooseFBConfig(awt_display, screennum, 232 attrlist, &nconfs); 233 234 if ((fbconfigs == NULL) || (nconfs <= 0)) { 235 J2dRlsTraceLn(J2D_TRACE_ERROR, 236 "GLXGC_InitFBConfig: could not find any valid fbconfigs"); 237 return 0; 238 } 239 240 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate fbconfigs:"); 241 242 // iterate through the list of fbconfigs, looking for the one that matches 243 // the requested VisualID and supports RGBA rendering as well as the 244 // creation of windows and pbuffers 245 for (i = 0; i < nconfs; i++) { 246 XVisualInfo *xvi; 247 VisualID fbvisualid; 248 GLXFBConfig fbc = fbconfigs[i]; 249 250 // get VisualID from GLXFBConfig 251 xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc); 252 if (xvi == NULL) { 253 continue; 254 } 255 fbvisualid = xvi->visualid; 256 XFree(xvi); 257 258 if (visualid == 0 || visualid == fbvisualid) { 259 int dtype, rtype, depth, stencil, db, alpha, gamma; 260 261 // get GLX-specific attributes from GLXFBConfig 262 j2d_glXGetFBConfigAttrib(awt_display, fbc, 263 GLX_DRAWABLE_TYPE, &dtype); 264 j2d_glXGetFBConfigAttrib(awt_display, fbc, 265 GLX_RENDER_TYPE, &rtype); 266 j2d_glXGetFBConfigAttrib(awt_display, fbc, 267 GLX_DEPTH_SIZE, &depth); 268 j2d_glXGetFBConfigAttrib(awt_display, fbc, 269 GLX_STENCIL_SIZE, &stencil); 270 271 // these attributes don't affect our decision, but they are 272 // interesting for trace logs, so we will query them anyway 273 j2d_glXGetFBConfigAttrib(awt_display, fbc, 274 GLX_DOUBLEBUFFER, &db); 275 j2d_glXGetFBConfigAttrib(awt_display, fbc, 276 GLX_ALPHA_SIZE, &alpha); 277 278 J2dRlsTrace5(J2D_TRACE_VERBOSE, 279 "[V] id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=", 280 fbvisualid, db, alpha, depth, stencil); 281 282 #ifdef __sparc 283 /* 284 * Sun's OpenGL implementation will always 285 * return at least two GLXFBConfigs (visuals) from 286 * glXChooseFBConfig(). The first will be a linear (gamma 287 * corrected) visual; the second will have the same capabilities 288 * as the first, except it will be a non-linear (non-gamma 289 * corrected) visual, which is the one we want, otherwise 290 * everything will look "washed out". So we will reject any 291 * visuals that have gamma values other than 1.0 (the value 292 * returned by glXGetFBConfigAttrib() will be scaled 293 * by 100, so 100 corresponds to a gamma value of 1.0, 220 294 * corresponds to 2.2, and so on). 295 */ 296 j2d_glXGetFBConfigAttrib(awt_display, fbc, 297 GLX_GAMMA_VALUE_SUN, &gamma); 298 if (gamma != 100) { 299 J2dRlsTrace(J2D_TRACE_VERBOSE, "false (linear visual)\n"); 300 continue; 301 } 302 #endif /* __sparc */ 303 304 if ((dtype & GLX_WINDOW_BIT) && 305 (dtype & GLX_PBUFFER_BIT) && 306 (rtype & GLX_RGBA_BIT) && 307 (depth >= 16)) 308 { 309 if (visualid == 0) { 310 // when visualid == 0, we loop through all configs 311 // looking for an fbconfig that has the smallest combined 312 // depth+stencil size (this keeps VRAM usage to a minimum) 313 if ((depth + stencil) < minDepthPlusStencil) { 314 J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); 315 minDepthPlusStencil = depth + stencil; 316 chosenConfig = fbc; 317 } else { 318 J2dRlsTrace(J2D_TRACE_VERBOSE, 319 "false (large depth)\n"); 320 } 321 continue; 322 } else { 323 // in this case, visualid == fbvisualid, which means 324 // we've found a valid fbconfig corresponding to the 325 // requested VisualID, so break out of the loop 326 J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); 327 chosenConfig = fbc; 328 break; 329 } 330 } else { 331 J2dRlsTrace(J2D_TRACE_VERBOSE, "false (bad match)\n"); 332 } 333 } 334 } 335 336 // free the list of fbconfigs 337 XFree(fbconfigs); 338 339 if (chosenConfig == 0) { 340 J2dRlsTraceLn(J2D_TRACE_ERROR, 341 "GLXGC_InitFBConfig: could not find an appropriate fbconfig"); 342 return 0; 343 } 344 345 return chosenConfig; 346 } 347 348 /** 349 * Returns the X11 VisualID that corresponds to the best GLXFBConfig for the 350 * given screen. If no valid visual could be found, this method returns zero. 351 * Note that this method will attempt to initialize GLX (and all the 352 * necessary function symbols) if it has not been already. The AWT_LOCK 353 * must be acquired before calling this method. 354 */ 355 VisualID 356 GLXGC_FindBestVisual(JNIEnv *env, jint screen) 357 { 358 GLXFBConfig fbc; 359 XVisualInfo *xvi; 360 VisualID visualid; 361 362 J2dRlsTraceLn1(J2D_TRACE_INFO, "GLXGC_FindBestVisual: scn=%d", screen); 363 364 if (!GLXGC_IsGLXAvailable()) { 365 J2dRlsTraceLn(J2D_TRACE_ERROR, 366 "GLXGC_FindBestVisual: could not initialize GLX"); 367 return 0; 368 } 369 370 fbc = GLXGC_InitFBConfig(env, screen, 0); 371 if (fbc == 0) { 372 J2dRlsTraceLn(J2D_TRACE_ERROR, 373 "GLXGC_FindBestVisual: could not find best visual"); 374 return 0; 375 } 376 377 xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc); 378 if (xvi == NULL) { 379 J2dRlsTraceLn(J2D_TRACE_ERROR, 380 "GLXGC_FindBestVisual: could not get visual for fbconfig"); 381 return 0; 382 } 383 384 visualid = xvi->visualid; 385 XFree(xvi); 386 387 J2dRlsTraceLn2(J2D_TRACE_INFO, 388 "GLXGC_FindBestVisual: chose 0x%x as the best visual for screen %d", 389 visualid, screen); 390 391 return visualid; 392 } 393 394 /** 395 * Creates a scratch pbuffer, which can be used to make a context current 396 * for extension queries, etc. 397 */ 398 static GLXPbuffer 399 GLXGC_InitScratchPbuffer(GLXFBConfig fbconfig) 400 { 401 int pbattrlist[] = {GLX_PBUFFER_WIDTH, 4, 402 GLX_PBUFFER_HEIGHT, 4, 403 GLX_PRESERVED_CONTENTS, GL_FALSE, 404 0}; 405 406 J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitScratchPbuffer"); 407 408 return j2d_glXCreatePbuffer(awt_display, fbconfig, pbattrlist); 409 } 410 411 /** 412 * Initializes a new OGLContext, which includes the native GLXContext handle 413 * and some other important information such as the associated GLXFBConfig. 414 */ 415 static OGLContext * 416 GLXGC_InitOGLContext(GLXFBConfig fbconfig, GLXContext context, 417 GLXPbuffer scratch, jint caps) 418 { 419 OGLContext *oglc; 420 GLXCtxInfo *ctxinfo; 421 422 J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitOGLContext"); 423 424 oglc = (OGLContext *)malloc(sizeof(OGLContext)); 425 if (oglc == NULL) { 426 J2dRlsTraceLn(J2D_TRACE_ERROR, 427 "GLXGC_InitOGLContext: could not allocate memory for oglc"); 428 return NULL; 429 } 430 431 memset(oglc, 0, sizeof(OGLContext)); 432 433 ctxinfo = (GLXCtxInfo *)malloc(sizeof(GLXCtxInfo)); 434 if (ctxinfo == NULL) { 435 J2dRlsTraceLn(J2D_TRACE_ERROR, 436 "GLXGC_InitOGLContext: could not allocate memory for ctxinfo"); 437 free(oglc); 438 return NULL; 439 } 440 441 ctxinfo->fbconfig = fbconfig; 442 ctxinfo->context = context; 443 ctxinfo->scratchSurface = scratch; 444 oglc->ctxInfo = ctxinfo; 445 oglc->caps = caps; 446 447 return oglc; 448 } 449 450 #endif /* !HEADLESS */ 451 452 /** 453 * Determines whether the GLX pipeline can be used for a given GraphicsConfig 454 * provided its screen number and visual ID. If the minimum requirements are 455 * met, the native GLXGraphicsConfigInfo structure is initialized for this 456 * GraphicsConfig with the necessary information (GLXFBConfig, etc.) 457 * and a pointer to this structure is returned as a jlong. If 458 * initialization fails at any point, zero is returned, indicating that GLX 459 * cannot be used for this GraphicsConfig (we should fallback on the existing 460 * X11 pipeline). 461 */ 462 JNIEXPORT jlong JNICALL 463 Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo(JNIEnv *env, 464 jclass glxgc, 465 jint screennum, 466 jint visnum) 467 { 468 #ifndef HEADLESS 469 OGLContext *oglc; 470 GLXFBConfig fbconfig; 471 GLXContext context; 472 GLXPbuffer scratch; 473 GLXGraphicsConfigInfo *glxinfo; 474 jint caps = CAPS_EMPTY; 475 int db; 476 const unsigned char *versionstr; 477 478 J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_getGLXConfigInfo"); 479 480 if (usingXinerama) { 481 // when Xinerama is enabled, the screen ID needs to be 0 482 screennum = 0; 483 } 484 485 fbconfig = GLXGC_InitFBConfig(env, screennum, (VisualID)visnum); 486 if (fbconfig == 0) { 487 J2dRlsTraceLn(J2D_TRACE_ERROR, 488 "GLXGraphicsConfig_getGLXConfigInfo: could not create fbconfig"); 489 return 0L; 490 } 491 492 if (sharedContext == 0) { 493 // create the one shared context 494 sharedContext = j2d_glXCreateNewContext(awt_display, fbconfig, 495 GLX_RGBA_TYPE, 0, GL_TRUE); 496 if (sharedContext == 0) { 497 J2dRlsTraceLn(J2D_TRACE_ERROR, 498 "GLXGraphicsConfig_getGLXConfigInfo: could not create shared context"); 499 return 0L; 500 } 501 } 502 503 // create the GLXContext for this GLXGraphicsConfig 504 context = j2d_glXCreateNewContext(awt_display, fbconfig, 505 GLX_RGBA_TYPE, sharedContext, 506 GL_TRUE); 507 if (context == 0) { 508 J2dRlsTraceLn(J2D_TRACE_ERROR, 509 "GLXGraphicsConfig_getGLXConfigInfo: could not create GLX context"); 510 return 0L; 511 } 512 513 // this is pretty sketchy, but it seems to be the easiest way to create 514 // some form of GLXDrawable using only the display and a GLXFBConfig 515 // (in order to make the context current for checking the version, 516 // extensions, etc)... 517 scratch = GLXGC_InitScratchPbuffer(fbconfig); 518 if (scratch == 0) { 519 J2dRlsTraceLn(J2D_TRACE_ERROR, 520 "GLXGraphicsConfig_getGLXConfigInfo: could not create scratch pbuffer"); 521 j2d_glXDestroyContext(awt_display, context); 522 return 0L; 523 } 524 525 // the context must be made current before we can query the 526 // version and extension strings 527 j2d_glXMakeContextCurrent(awt_display, scratch, scratch, context); 528 529 #ifdef __sparc 530 /* 531 * 6438225: The software rasterizer used by Sun's OpenGL libraries 532 * for certain boards has quality issues, and besides, performance 533 * of these boards is not high enough to justify the use of the 534 * OpenGL-based Java 2D pipeline. If we detect one of the following 535 * boards via the GL_RENDERER string, just give up: 536 * - FFB[2[+]] ("Creator[3D]") 537 * - PGX-series ("m64") 538 * - AFB ("Elite3D") 539 */ 540 { 541 const char *renderer = (const char *)j2d_glGetString(GL_RENDERER); 542 543 J2dRlsTraceLn1(J2D_TRACE_VERBOSE, 544 "GLXGraphicsConfig_getGLXConfigInfo: detected renderer (%s)", 545 (renderer == NULL) ? "null" : renderer); 546 547 if (renderer == NULL || 548 strncmp(renderer, "Creator", 7) == 0 || 549 strncmp(renderer, "SUNWm64", 7) == 0 || 550 strncmp(renderer, "Elite", 5) == 0) 551 { 552 J2dRlsTraceLn1(J2D_TRACE_ERROR, 553 "GLXGraphicsConfig_getGLXConfigInfo: unsupported board (%s)", 554 (renderer == NULL) ? "null" : renderer); 555 j2d_glXMakeContextCurrent(awt_display, None, None, NULL); 556 j2d_glXDestroyPbuffer(awt_display, scratch); 557 j2d_glXDestroyContext(awt_display, context); 558 return 0L; 559 } 560 } 561 #endif /* __sparc */ 562 563 versionstr = j2d_glGetString(GL_VERSION); 564 OGLContext_GetExtensionInfo(env, &caps); 565 566 // destroy the temporary resources 567 j2d_glXMakeContextCurrent(awt_display, None, None, NULL); 568 569 J2dRlsTraceLn1(J2D_TRACE_INFO, 570 "GLXGraphicsConfig_getGLXConfigInfo: OpenGL version=%s", 571 (versionstr == NULL) ? "null" : (char *)versionstr); 572 573 if (!OGLContext_IsVersionSupported(versionstr)) { 574 J2dRlsTraceLn(J2D_TRACE_ERROR, 575 "GLXGraphicsConfig_getGLXConfigInfo: OpenGL 1.2 is required"); 576 j2d_glXDestroyPbuffer(awt_display, scratch); 577 j2d_glXDestroyContext(awt_display, context); 578 return 0L; 579 } 580 581 // get config-specific capabilities 582 j2d_glXGetFBConfigAttrib(awt_display, fbconfig, GLX_DOUBLEBUFFER, &db); 583 if (db) { 584 caps |= CAPS_DOUBLEBUFFERED; 585 } 586 587 // initialize the OGLContext, which wraps the GLXFBConfig and GLXContext 588 oglc = GLXGC_InitOGLContext(fbconfig, context, scratch, caps); 589 if (oglc == NULL) { 590 J2dRlsTraceLn(J2D_TRACE_ERROR, 591 "GLXGraphicsConfig_getGLXConfigInfo: could not create oglc"); 592 j2d_glXDestroyPbuffer(awt_display, scratch); 593 j2d_glXDestroyContext(awt_display, context); 594 return 0L; 595 } 596 597 J2dTraceLn(J2D_TRACE_VERBOSE, 598 "GLXGraphicsConfig_getGLXConfigInfo: finished checking dependencies"); 599 600 // create the GLXGraphicsConfigInfo record for this config 601 glxinfo = (GLXGraphicsConfigInfo *)malloc(sizeof(GLXGraphicsConfigInfo)); 602 if (glxinfo == NULL) { 603 J2dRlsTraceLn(J2D_TRACE_ERROR, 604 "GLXGraphicsConfig_getGLXConfigInfo: could not allocate memory for glxinfo"); 605 GLXGC_DestroyOGLContext(oglc); 606 return 0L; 607 } 608 609 glxinfo->screen = screennum; 610 glxinfo->visual = visnum; 611 glxinfo->context = oglc; 612 glxinfo->fbconfig = fbconfig; 613 614 return ptr_to_jlong(glxinfo); 615 #else 616 return 0L; 617 #endif /* !HEADLESS */ 618 } 619 620 JNIEXPORT void JNICALL 621 Java_sun_java2d_opengl_GLXGraphicsConfig_initConfig(JNIEnv *env, 622 jobject glxgc, 623 jlong aData, 624 jlong configInfo) 625 { 626 #ifndef HEADLESS 627 GLXGraphicsConfigInfo *glxinfo; 628 AwtGraphicsConfigDataPtr configData = 629 (AwtGraphicsConfigDataPtr)jlong_to_ptr(aData); 630 631 J2dTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_initConfig"); 632 633 if (configData == NULL) { 634 JNU_ThrowNullPointerException(env, "Native GraphicsConfig missing"); 635 return; 636 } 637 638 glxinfo = (GLXGraphicsConfigInfo *)jlong_to_ptr(configInfo); 639 if (glxinfo == NULL) { 640 JNU_ThrowNullPointerException(env, 641 "GLXGraphicsConfigInfo data missing"); 642 return; 643 } 644 645 configData->glxInfo = glxinfo; 646 #endif /* !HEADLESS */ 647 } 648 649 JNIEXPORT jint JNICALL 650 Java_sun_java2d_opengl_GLXGraphicsConfig_getOGLCapabilities(JNIEnv *env, 651 jclass glxgc, 652 jlong configInfo) 653 { 654 #ifndef HEADLESS 655 GLXGraphicsConfigInfo *glxinfo = 656 (GLXGraphicsConfigInfo *)jlong_to_ptr(configInfo); 657 658 J2dTraceLn(J2D_TRACE_INFO, "GLXGraphicsConfig_getOGLCapabilities"); 659 660 if (glxinfo == NULL || glxinfo->context == NULL) { 661 return CAPS_EMPTY; 662 } 663 664 return glxinfo->context->caps; 665 #else 666 return CAPS_EMPTY; 667 #endif /* !HEADLESS */ 668 }