1 /* 2 * Copyright (c) 2003, 2012, 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 #ifndef HEADLESS 27 28 #include <stdlib.h> 29 30 #include "sun_java2d_opengl_OGLSurfaceData.h" 31 32 #include "jlong.h" 33 #include "jni_util.h" 34 #include "OGLSurfaceData.h" 35 36 /** 37 * The following methods are implemented in the windowing system (i.e. GLX 38 * and WGL) source files. 39 */ 40 extern jlong OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo); 41 extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo); 42 extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo); 43 44 void OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h); 45 46 /** 47 * This table contains the "pixel formats" for all system memory surfaces 48 * that OpenGL is capable of handling, indexed by the "PF_" constants defined 49 * in OGLSurfaceData.java. These pixel formats contain information that is 50 * passed to OpenGL when copying from a system memory ("Sw") surface to 51 * an OpenGL "Surface" (via glDrawPixels()) or "Texture" (via glTexImage2D()). 52 */ 53 OGLPixelFormat PixelFormats[] = { 54 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 55 4, 1, 0, }, /* 0 - IntArgb */ 56 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 57 4, 1, 1, }, /* 1 - IntArgbPre */ 58 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 59 4, 0, 1, }, /* 2 - IntRgb */ 60 { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 61 4, 0, 1, }, /* 3 - IntRgbx */ 62 { GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 63 4, 0, 1, }, /* 4 - IntBgr */ 64 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 65 4, 0, 1, }, /* 5 - IntBgrx */ 66 { GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 67 2, 0, 1, }, /* 6 - Ushort565Rgb */ 68 { GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 69 2, 0, 1, }, /* 7 - Ushort555Rgb */ 70 { GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 71 2, 0, 1, }, /* 8 - Ushort555Rgbx*/ 72 { GL_LUMINANCE, GL_UNSIGNED_BYTE, 73 1, 0, 1, }, /* 9 - ByteGray */ 74 { GL_LUMINANCE, GL_UNSIGNED_SHORT, 75 2, 0, 1, }, /*10 - UshortGray */ 76 { GL_BGR, GL_UNSIGNED_BYTE, 77 1, 0, 1, }, /*11 - ThreeByteBgr */}; 78 79 /** 80 * Given a starting value and a maximum limit, returns the first power-of-two 81 * greater than the starting value. If the resulting value is greater than 82 * the maximum limit, zero is returned. 83 */ 84 jint 85 OGLSD_NextPowerOfTwo(jint val, jint max) 86 { 87 jint i; 88 89 if (val > max) { 90 return 0; 91 } 92 93 for (i = 1; i < val; i *= 2); 94 95 return i; 96 } 97 98 /** 99 * Returns true if both given dimensions are a power of two. 100 */ 101 static jboolean 102 OGLSD_IsPowerOfTwo(jint width, jint height) 103 { 104 return (((width & (width-1)) | (height & (height-1))) == 0); 105 } 106 107 /** 108 * Initializes an OpenGL texture object. 109 * 110 * If the isOpaque parameter is JNI_FALSE, then the texture will have a 111 * full alpha channel; otherwise, the texture will be opaque (this can 112 * help save VRAM when translucency is not needed). 113 * 114 * If the GL_ARB_texture_non_power_of_two extension is present (texNonPow2 115 * is JNI_TRUE), the actual texture is allowed to have non-power-of-two 116 * dimensions, and therefore width==textureWidth and height==textureHeight. 117 * 118 * Failing that, if the GL_ARB_texture_rectangle extension is present 119 * (texRect is JNI_TRUE), the actual texture is allowed to have 120 * non-power-of-two dimensions, except that instead of using the usual 121 * GL_TEXTURE_2D target, we need to use the GL_TEXTURE_RECTANGLE_ARB target. 122 * Note that the GL_REPEAT wrapping mode is not allowed with this target, 123 * so if that mode is needed (e.g. as is the case in the TexturePaint code) 124 * one should pass JNI_FALSE to avoid using this extension. Also note that 125 * when the texture target is GL_TEXTURE_RECTANGLE_ARB, texture coordinates 126 * must be specified in the range [0,width] and [0,height] rather than 127 * [0,1] as is the case with the usual GL_TEXTURE_2D target (so take care)! 128 * 129 * Otherwise, the actual texture must have power-of-two dimensions, and 130 * therefore the textureWidth and textureHeight will be the next 131 * power-of-two greater than (or equal to) the requested width and height. 132 */ 133 static jboolean 134 OGLSD_InitTextureObject(OGLSDOps *oglsdo, 135 jboolean isOpaque, 136 jboolean texNonPow2, jboolean texRect, 137 jint width, jint height) 138 { 139 GLenum texTarget, texProxyTarget; 140 GLint format = GL_RGBA; 141 GLint size = GL_UNSIGNED_INT_8_8_8_8; 142 GLuint texID; 143 GLsizei texWidth, texHeight, realWidth, realHeight; 144 GLint texMax; 145 146 J2dTraceLn4(J2D_TRACE_INFO, 147 "OGLSD_InitTextureObject: w=%d h=%d opq=%d nonpow2=%d", 148 width, height, isOpaque, texNonPow2); 149 150 if (oglsdo == NULL) { 151 J2dRlsTraceLn(J2D_TRACE_ERROR, 152 "OGLSD_InitTextureObject: ops are null"); 153 return JNI_FALSE; 154 } 155 156 if (texNonPow2) { 157 // use non-pow2 dimensions with GL_TEXTURE_2D target 158 j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax); 159 texWidth = (width <= texMax) ? width : 0; 160 texHeight = (height <= texMax) ? height : 0; 161 texTarget = GL_TEXTURE_2D; 162 texProxyTarget = GL_PROXY_TEXTURE_2D; 163 } else if (texRect) { 164 // use non-pow2 dimensions with GL_TEXTURE_RECTANGLE_ARB target 165 j2d_glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texMax); 166 texWidth = (width <= texMax) ? width : 0; 167 texHeight = (height <= texMax) ? height : 0; 168 texTarget = GL_TEXTURE_RECTANGLE_ARB; 169 texProxyTarget = GL_PROXY_TEXTURE_RECTANGLE_ARB; 170 } else { 171 // find the appropriate power-of-two dimensions 172 j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax); 173 texWidth = OGLSD_NextPowerOfTwo(width, texMax); 174 texHeight = OGLSD_NextPowerOfTwo(height, texMax); 175 texTarget = GL_TEXTURE_2D; 176 texProxyTarget = GL_PROXY_TEXTURE_2D; 177 } 178 179 J2dTraceLn3(J2D_TRACE_VERBOSE, 180 " desired texture dimensions: w=%d h=%d max=%d", 181 texWidth, texHeight, texMax); 182 183 // if either dimension is 0, we cannot allocate a texture with the 184 // requested dimensions 185 if ((texWidth == 0) || (texHeight == 0)) { 186 J2dRlsTraceLn(J2D_TRACE_ERROR, 187 "OGLSD_InitTextureObject: texture dimensions too large"); 188 return JNI_FALSE; 189 } 190 191 // now use a proxy to determine whether we can create a texture with 192 // the calculated power-of-two dimensions and the given internal format 193 j2d_glTexImage2D(texProxyTarget, 0, format, 194 texWidth, texHeight, 0, 195 format, size, NULL); 196 j2d_glGetTexLevelParameteriv(texProxyTarget, 0, 197 GL_TEXTURE_WIDTH, &realWidth); 198 j2d_glGetTexLevelParameteriv(texProxyTarget, 0, 199 GL_TEXTURE_HEIGHT, &realHeight); 200 201 // if the requested dimensions and proxy dimensions don't match, 202 // we shouldn't attempt to create the texture 203 if ((realWidth != texWidth) || (realHeight != texHeight)) { 204 J2dRlsTraceLn2(J2D_TRACE_ERROR, 205 "OGLSD_InitTextureObject: actual (w=%d h=%d) != requested", 206 realWidth, realHeight); 207 return JNI_FALSE; 208 } 209 210 // initialize the texture with some dummy data (this allows us to create 211 // a texture object once with 2^n dimensions, and then use 212 // glTexSubImage2D() to provide further updates) 213 j2d_glGenTextures(1, &texID); 214 j2d_glBindTexture(texTarget, texID); 215 j2d_glTexImage2D(texTarget, 0, format, 216 texWidth, texHeight, 0, 217 format, size, NULL); 218 219 oglsdo->isOpaque = isOpaque; 220 oglsdo->xOffset = 0; 221 oglsdo->yOffset = 0; 222 oglsdo->width = width; 223 oglsdo->height = height; 224 oglsdo->textureID = texID; 225 oglsdo->textureWidth = texWidth; 226 oglsdo->textureHeight = texHeight; 227 oglsdo->textureTarget = texTarget; 228 OGLSD_INIT_TEXTURE_FILTER(oglsdo, GL_NEAREST); 229 OGLSD_RESET_TEXTURE_WRAP(texTarget); 230 231 J2dTraceLn3(J2D_TRACE_VERBOSE, " created texture: w=%d h=%d id=%d", 232 width, height, texID); 233 234 return JNI_TRUE; 235 } 236 237 /** 238 * Initializes an OpenGL texture, using the given width and height as 239 * a guide. See OGLSD_InitTextureObject() for more information. 240 */ 241 JNIEXPORT jboolean JNICALL 242 Java_sun_java2d_opengl_OGLSurfaceData_initTexture 243 (JNIEnv *env, jobject oglsd, 244 jlong pData, jboolean isOpaque, 245 jboolean texNonPow2, jboolean texRect, 246 jint width, jint height) 247 { 248 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 249 250 J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initTexture: w=%d h=%d", 251 width, height); 252 253 if (oglsdo == NULL) { 254 J2dRlsTraceLn(J2D_TRACE_ERROR, 255 "OGLSurfaceData_initTexture: ops are null"); 256 return JNI_FALSE; 257 } 258 259 /* 260 * We only use the GL_ARB_texture_rectangle extension if it is available 261 * and the requested bounds are not pow2 (it is probably faster to use 262 * GL_TEXTURE_2D for pow2 textures, and besides, our TexturePaint 263 * code relies on GL_REPEAT, which is not allowed for 264 * GL_TEXTURE_RECTANGLE_ARB targets). 265 */ 266 texRect = texRect && !OGLSD_IsPowerOfTwo(width, height); 267 268 if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, 269 width, height)) 270 { 271 J2dRlsTraceLn(J2D_TRACE_ERROR, 272 "OGLSurfaceData_initTexture: could not init texture object"); 273 return JNI_FALSE; 274 } 275 276 OGLSD_SetNativeDimensions(env, oglsdo, 277 oglsdo->textureWidth, oglsdo->textureHeight); 278 279 oglsdo->drawableType = OGLSD_TEXTURE; 280 // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() 281 282 return JNI_TRUE; 283 } 284 285 /** 286 * Initializes a framebuffer object based on the given textureID and its 287 * width/height. This method will iterate through all possible depth formats 288 * to find one that is supported by the drivers/hardware. (Since our use of 289 * the depth buffer is fairly simplistic, we hope to find a depth format that 290 * uses as little VRAM as possible.) If an appropriate depth buffer is found 291 * and all attachments are successful (i.e. the framebuffer object is 292 * "complete"), then this method will return JNI_TRUE and will initialize 293 * the values of fbobjectID and depthID using the IDs created by this method. 294 * Otherwise, this method returns JNI_FALSE. Note that the caller is only 295 * responsible for deleting the allocated fbobject and depth renderbuffer 296 * resources if this method returned JNI_TRUE. 297 */ 298 jboolean 299 OGLSD_InitFBObject(GLuint *fbobjectID, GLuint *depthID, 300 GLuint textureID, GLenum textureTarget, 301 jint textureWidth, jint textureHeight) 302 { 303 GLenum depthFormats[] = { 304 GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32 305 }; 306 GLuint fboTmpID, depthTmpID; 307 jboolean foundDepth = JNI_FALSE; 308 int i; 309 310 J2dTraceLn3(J2D_TRACE_INFO, "OGLSD_InitFBObject: w=%d h=%d texid=%d", 311 textureWidth, textureHeight, textureID); 312 313 // initialize framebuffer object 314 j2d_glGenFramebuffersEXT(1, &fboTmpID); 315 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboTmpID); 316 317 // attach color texture to framebuffer object 318 j2d_glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 319 GL_COLOR_ATTACHMENT0_EXT, 320 textureTarget, textureID, 0); 321 322 // attempt to create a depth renderbuffer of a particular format; we 323 // will start with the smallest size and then work our way up 324 for (i = 0; i < 3; i++) { 325 GLenum error, status; 326 GLenum depthFormat = depthFormats[i]; 327 int depthSize = 16 + (i * 8); 328 329 // initialize depth renderbuffer 330 j2d_glGenRenderbuffersEXT(1, &depthTmpID); 331 j2d_glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthTmpID); 332 j2d_glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat, 333 textureWidth, textureHeight); 334 335 // creation of depth buffer could potentially fail, so check for error 336 error = j2d_glGetError(); 337 if (error != GL_NO_ERROR) { 338 J2dTraceLn2(J2D_TRACE_VERBOSE, 339 "OGLSD_InitFBObject: could not create depth buffer: depth=%d error=%x", 340 depthSize, error); 341 j2d_glDeleteRenderbuffersEXT(1, &depthTmpID); 342 continue; 343 } 344 345 // attach depth renderbuffer to framebuffer object 346 j2d_glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 347 GL_DEPTH_ATTACHMENT_EXT, 348 GL_RENDERBUFFER_EXT, depthTmpID); 349 350 // now check for framebuffer "completeness" 351 status = j2d_glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 352 353 if (status == GL_FRAMEBUFFER_COMPLETE_EXT) { 354 // we found a valid format, so break out of the loop 355 J2dTraceLn1(J2D_TRACE_VERBOSE, 356 " framebuffer is complete: depth=%d", depthSize); 357 foundDepth = JNI_TRUE; 358 break; 359 } else { 360 // this depth format didn't work, so delete and try another format 361 J2dTraceLn2(J2D_TRACE_VERBOSE, 362 " framebuffer is incomplete: depth=%d status=%x", 363 depthSize, status); 364 j2d_glDeleteRenderbuffersEXT(1, &depthTmpID); 365 } 366 } 367 368 // unbind the texture and framebuffer objects (they will be bound again 369 // later as needed) 370 j2d_glBindTexture(textureTarget, 0); 371 j2d_glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); 372 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 373 374 if (!foundDepth) { 375 J2dRlsTraceLn(J2D_TRACE_ERROR, 376 "OGLSD_InitFBObject: could not find valid depth format"); 377 j2d_glDeleteFramebuffersEXT(1, &fboTmpID); 378 return JNI_FALSE; 379 } 380 381 *fbobjectID = fboTmpID; 382 *depthID = depthTmpID; 383 384 return JNI_TRUE; 385 } 386 387 /** 388 * Initializes a framebuffer object, using the given width and height as 389 * a guide. See OGLSD_InitTextureObject() and OGLSD_InitFBObject() 390 * for more information. 391 */ 392 JNIEXPORT jboolean JNICALL 393 Java_sun_java2d_opengl_OGLSurfaceData_initFBObject 394 (JNIEnv *env, jobject oglsd, 395 jlong pData, jboolean isOpaque, 396 jboolean texNonPow2, jboolean texRect, 397 jint width, jint height) 398 { 399 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 400 GLuint fbobjectID, depthID; 401 402 J2dTraceLn2(J2D_TRACE_INFO, 403 "OGLSurfaceData_initFBObject: w=%d h=%d", 404 width, height); 405 406 if (oglsdo == NULL) { 407 J2dRlsTraceLn(J2D_TRACE_ERROR, 408 "OGLSurfaceData_initFBObject: ops are null"); 409 return JNI_FALSE; 410 } 411 412 // initialize color texture object 413 if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, 414 width, height)) 415 { 416 J2dRlsTraceLn(J2D_TRACE_ERROR, 417 "OGLSurfaceData_initFBObject: could not init texture object"); 418 return JNI_FALSE; 419 } 420 421 // initialize framebuffer object using color texture created above 422 if (!OGLSD_InitFBObject(&fbobjectID, &depthID, 423 oglsdo->textureID, oglsdo->textureTarget, 424 oglsdo->textureWidth, oglsdo->textureHeight)) 425 { 426 J2dRlsTraceLn(J2D_TRACE_ERROR, 427 "OGLSurfaceData_initFBObject: could not init fbobject"); 428 j2d_glDeleteTextures(1, &oglsdo->textureID); 429 return JNI_FALSE; 430 } 431 432 oglsdo->drawableType = OGLSD_FBOBJECT; 433 // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() 434 oglsdo->fbobjectID = fbobjectID; 435 oglsdo->depthID = depthID; 436 437 OGLSD_SetNativeDimensions(env, oglsdo, 438 oglsdo->textureWidth, oglsdo->textureHeight); 439 440 // framebuffer objects differ from other OpenGL surfaces in that the 441 // value passed to glRead/DrawBuffer() must be GL_COLOR_ATTACHMENTn_EXT, 442 // rather than GL_FRONT (or GL_BACK) 443 oglsdo->activeBuffer = GL_COLOR_ATTACHMENT0_EXT; 444 445 return JNI_TRUE; 446 } 447 448 /** 449 * Initializes a surface in the backbuffer of a given double-buffered 450 * onscreen window for use in a BufferStrategy.Flip situation. The bounds of 451 * the backbuffer surface should always be kept in sync with the bounds of 452 * the underlying native window. 453 */ 454 JNIEXPORT jboolean JNICALL 455 Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer 456 (JNIEnv *env, jobject oglsd, 457 jlong pData) 458 { 459 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 460 461 J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_initFlipBackbuffer"); 462 463 if (oglsdo == NULL) { 464 J2dRlsTraceLn(J2D_TRACE_ERROR, 465 "OGLSurfaceData_initFlipBackbuffer: ops are null"); 466 return JNI_FALSE; 467 } 468 469 if (oglsdo->drawableType == OGLSD_UNDEFINED) { 470 if (!OGLSD_InitOGLWindow(env, oglsdo)) { 471 J2dRlsTraceLn(J2D_TRACE_ERROR, 472 "OGLSurfaceData_initFlipBackbuffer: could not init window"); 473 return JNI_FALSE; 474 } 475 } 476 477 if (oglsdo->drawableType != OGLSD_WINDOW) { 478 J2dRlsTraceLn(J2D_TRACE_ERROR, 479 "OGLSurfaceData_initFlipBackbuffer: drawable is not a window"); 480 return JNI_FALSE; 481 } 482 483 oglsdo->drawableType = OGLSD_FLIP_BACKBUFFER; 484 // x/yOffset have already been set in OGLSD_InitOGLWindow()... 485 // REMIND: for some reason, flipping won't work properly on IFB unless we 486 // explicitly use BACK_LEFT rather than BACK... 487 oglsdo->activeBuffer = GL_BACK_LEFT; 488 489 OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->width, oglsdo->height); 490 491 return JNI_TRUE; 492 } 493 494 JNIEXPORT jint JNICALL 495 Java_sun_java2d_opengl_OGLSurfaceData_getTextureTarget 496 (JNIEnv *env, jobject oglsd, 497 jlong pData) 498 { 499 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 500 501 J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_getTextureTarget"); 502 503 if (oglsdo == NULL) { 504 J2dRlsTraceLn(J2D_TRACE_ERROR, 505 "OGLSurfaceData_getTextureTarget: ops are null"); 506 return 0; 507 } 508 509 return (jint)oglsdo->textureTarget; 510 } 511 512 JNIEXPORT jint JNICALL 513 Java_sun_java2d_opengl_OGLSurfaceData_getTextureID 514 (JNIEnv *env, jobject oglsd, 515 jlong pData) 516 { 517 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 518 519 J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_getTextureID"); 520 521 if (oglsdo == NULL) { 522 J2dRlsTraceLn(J2D_TRACE_ERROR, 523 "OGLSurfaceData_getTextureID: ops are null"); 524 return 0L; 525 } 526 527 return (jint)oglsdo->textureID; 528 } 529 530 /** 531 * Initializes nativeWidth/Height fields of the surfaceData object with 532 * passed arguments. 533 */ 534 void 535 OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, 536 jint width, jint height) 537 { 538 jobject sdObject; 539 540 sdObject = (*env)->NewLocalRef(env, oglsdo->sdOps.sdObject); 541 if (sdObject == NULL) { 542 return; 543 } 544 545 JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); 546 if (!((*env)->ExceptionOccurred(env))) { 547 JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); 548 } 549 550 (*env)->DeleteLocalRef(env, sdObject); 551 } 552 553 /** 554 * Deletes native OpenGL resources associated with this surface. 555 */ 556 void 557 OGLSD_Delete(JNIEnv *env, OGLSDOps *oglsdo) 558 { 559 J2dTraceLn1(J2D_TRACE_INFO, "OGLSD_Delete: type=%d", 560 oglsdo->drawableType); 561 562 if (oglsdo->drawableType == OGLSD_TEXTURE) { 563 if (oglsdo->textureID != 0) { 564 j2d_glDeleteTextures(1, &oglsdo->textureID); 565 oglsdo->textureID = 0; 566 } 567 } else if (oglsdo->drawableType == OGLSD_FBOBJECT) { 568 if (oglsdo->textureID != 0) { 569 j2d_glDeleteTextures(1, &oglsdo->textureID); 570 oglsdo->textureID = 0; 571 } 572 if (oglsdo->depthID != 0) { 573 j2d_glDeleteRenderbuffersEXT(1, &oglsdo->depthID); 574 oglsdo->depthID = 0; 575 } 576 if (oglsdo->fbobjectID != 0) { 577 j2d_glDeleteFramebuffersEXT(1, &oglsdo->fbobjectID); 578 oglsdo->fbobjectID = 0; 579 } 580 } else { 581 // dispose windowing system resources (pbuffer, pixmap, etc) 582 OGLSD_DestroyOGLSurface(env, oglsdo); 583 } 584 } 585 586 /** 587 * This is the implementation of the general DisposeFunc defined in 588 * SurfaceData.h and used by the Disposer mechanism. It first flushes all 589 * native OpenGL resources and then frees any memory allocated within the 590 * native OGLSDOps structure. 591 */ 592 void 593 OGLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops) 594 { 595 OGLSDOps *oglsdo = (OGLSDOps *)ops; 596 jlong pConfigInfo = OGLSD_GetNativeConfigInfo(oglsdo); 597 598 JNU_CallStaticMethodByName(env, NULL, "sun/java2d/opengl/OGLSurfaceData", 599 "dispose", "(JJ)V", 600 ptr_to_jlong(ops), pConfigInfo); 601 } 602 603 /** 604 * This is the implementation of the general surface LockFunc defined in 605 * SurfaceData.h. 606 */ 607 jint 608 OGLSD_Lock(JNIEnv *env, 609 SurfaceDataOps *ops, 610 SurfaceDataRasInfo *pRasInfo, 611 jint lockflags) 612 { 613 JNU_ThrowInternalError(env, "OGLSD_Lock not implemented!"); 614 return SD_FAILURE; 615 } 616 617 /** 618 * This is the implementation of the general GetRasInfoFunc defined in 619 * SurfaceData.h. 620 */ 621 void 622 OGLSD_GetRasInfo(JNIEnv *env, 623 SurfaceDataOps *ops, 624 SurfaceDataRasInfo *pRasInfo) 625 { 626 JNU_ThrowInternalError(env, "OGLSD_GetRasInfo not implemented!"); 627 } 628 629 /** 630 * This is the implementation of the general surface UnlockFunc defined in 631 * SurfaceData.h. 632 */ 633 void 634 OGLSD_Unlock(JNIEnv *env, 635 SurfaceDataOps *ops, 636 SurfaceDataRasInfo *pRasInfo) 637 { 638 JNU_ThrowInternalError(env, "OGLSD_Unlock not implemented!"); 639 } 640 641 #endif /* !HEADLESS */