1 /* 2 * Copyright (c) 2011, 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 #import <stdlib.h> 27 #import <JavaNativeFoundation/JavaNativeFoundation.h> 28 29 #import "sun_java2d_opengl_CGLSurfaceData.h" 30 31 #import "jni.h" 32 #import "jni_util.h" 33 #import "OGLRenderQueue.h" 34 #import "CGLGraphicsConfig.h" 35 #import "CGLSurfaceData.h" 36 #import "CGLLayer.h" 37 #import "ThreadUtilities.h" 38 39 /* JDK's glext.h is already included and will prevent the Apple glext.h 40 * being included, so define the externs directly 41 */ 42 extern void glBindFramebufferEXT(GLenum target, GLuint framebuffer); 43 extern CGLError CGLTexImageIOSurface2D( 44 CGLContextObj ctx, GLenum target, GLenum internal_format, 45 GLsizei width, GLsizei height, GLenum format, GLenum type, 46 IOSurfaceRef ioSurface, GLuint plane); 47 48 /** 49 * The methods in this file implement the native windowing system specific 50 * layer (CGL) for the OpenGL-based Java 2D pipeline. 51 */ 52 53 #pragma mark - 54 #pragma mark "--- Mac OS X specific methods for GL pipeline ---" 55 56 // TODO: hack that's called from OGLRenderQueue to test out unlockFocus behavior 57 #if 0 58 void 59 OGLSD_UnlockFocus(OGLContext *oglc, OGLSDOps *dstOps) 60 { 61 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 62 CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps; 63 fprintf(stderr, "about to unlock focus: %p %p\n", 64 cglsdo->peerData, ctxinfo->context); 65 66 NSOpenGLView *nsView = cglsdo->peerData; 67 if (nsView != NULL) { 68 JNF_COCOA_ENTER(env); 69 [nsView unlockFocus]; 70 JNF_COCOA_EXIT(env); 71 } 72 } 73 #endif 74 75 /** 76 * Makes the given context current to its associated "scratch" surface. If 77 * the operation is successful, this method will return JNI_TRUE; otherwise, 78 * returns JNI_FALSE. 79 */ 80 static jboolean 81 CGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc) 82 { 83 J2dTraceLn(J2D_TRACE_INFO, "CGLSD_MakeCurrentToScratch"); 84 85 if (oglc == NULL) { 86 J2dRlsTraceLn(J2D_TRACE_ERROR, 87 "CGLSD_MakeCurrentToScratch: context is null"); 88 return JNI_FALSE; 89 } 90 91 JNF_COCOA_ENTER(env); 92 93 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 94 #if USE_NSVIEW_FOR_SCRATCH 95 [ctxinfo->context makeCurrentContext]; 96 [ctxinfo->context setView: ctxinfo->scratchSurface]; 97 #else 98 [ctxinfo->context clearDrawable]; 99 [ctxinfo->context makeCurrentContext]; 100 [ctxinfo->context setPixelBuffer: ctxinfo->scratchSurface 101 cubeMapFace: 0 102 mipMapLevel: 0 103 currentVirtualScreen: [ctxinfo->context currentVirtualScreen]]; 104 #endif 105 106 JNF_COCOA_EXIT(env); 107 108 return JNI_TRUE; 109 } 110 111 /** 112 * This function disposes of any native windowing system resources associated 113 * with this surface. For instance, if the given OGLSDOps is of type 114 * OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer 115 * surface. 116 */ 117 void 118 OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo) 119 { 120 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface"); 121 122 JNF_COCOA_ENTER(env); 123 124 CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; 125 if (oglsdo->drawableType == OGLSD_PBUFFER) { 126 if (oglsdo->textureID != 0) { 127 j2d_glDeleteTextures(1, &oglsdo->textureID); 128 oglsdo->textureID = 0; 129 } 130 if (cglsdo->pbuffer != NULL) { 131 [cglsdo->pbuffer release]; 132 cglsdo->pbuffer = NULL; 133 } 134 } else if (oglsdo->drawableType == OGLSD_WINDOW) { 135 // detach the NSView from the NSOpenGLContext 136 CGLGraphicsConfigInfo *cglInfo = cglsdo->configInfo; 137 OGLContext *oglc = cglInfo->context; 138 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 139 [ctxinfo->context clearDrawable]; 140 } 141 142 oglsdo->drawableType = OGLSD_UNDEFINED; 143 144 JNF_COCOA_EXIT(env); 145 } 146 147 /** 148 * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo 149 * associated with the given OGLSDOps. This method can be called from 150 * shared code to retrieve the native GraphicsConfig data in a platform- 151 * independent manner. 152 */ 153 jlong 154 OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo) 155 { 156 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo"); 157 158 if (oglsdo == NULL) { 159 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: ops are null"); 160 return 0L; 161 } 162 163 CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; 164 if (cglsdo == NULL) { 165 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: cgl ops are null"); 166 return 0L; 167 } 168 169 return ptr_to_jlong(cglsdo->configInfo); 170 } 171 172 /** 173 * Makes the given GraphicsConfig's context current to its associated 174 * "scratch" surface. If there is a problem making the context current, 175 * this method will return NULL; otherwise, returns a pointer to the 176 * OGLContext that is associated with the given GraphicsConfig. 177 */ 178 OGLContext * 179 OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo) 180 { 181 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext"); 182 183 CGLGraphicsConfigInfo *cglInfo = (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 184 if (cglInfo == NULL) { 185 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: cgl config info is null"); 186 return NULL; 187 } 188 189 OGLContext *oglc = cglInfo->context; 190 if (oglc == NULL) { 191 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: ogl context is null"); 192 return NULL; 193 } 194 195 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 196 197 JNF_COCOA_ENTER(env); 198 199 // avoid changing the context's target view whenever possible, since 200 // calling setView causes flickering; as long as our context is current 201 // to some view, it's not necessary to switch to the scratch surface 202 if ([ctxinfo->context view] == nil) { 203 // it seems to be necessary to explicitly flush between context changes 204 OGLContext *currentContext = OGLRenderQueue_GetCurrentContext(); 205 if (currentContext != NULL) { 206 j2d_glFlush(); 207 } 208 209 if (!CGLSD_MakeCurrentToScratch(env, oglc)) { 210 return NULL; 211 } 212 // make sure our context is current 213 } else if ([NSOpenGLContext currentContext] != ctxinfo->context) { 214 [ctxinfo->context makeCurrentContext]; 215 } 216 217 if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) { 218 // the GL_EXT_framebuffer_object extension is present, so this call 219 // will ensure that we are bound to the scratch surface (and not 220 // some other framebuffer object) 221 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 222 } 223 224 JNF_COCOA_EXIT(env); 225 226 return oglc; 227 } 228 229 /** 230 * Makes a context current to the given source and destination 231 * surfaces. If there is a problem making the context current, this method 232 * will return NULL; otherwise, returns a pointer to the OGLContext that is 233 * associated with the destination surface. 234 */ 235 OGLContext * 236 OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps) 237 { 238 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent"); 239 240 CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps; 241 242 J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", srcOps->drawableType, srcOps, dstOps->drawableType, dstOps); 243 244 OGLContext *oglc = dstCGLOps->configInfo->context; 245 if (oglc == NULL) { 246 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_MakeOGLContextCurrent: context is null"); 247 return NULL; 248 } 249 250 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 251 252 // it seems to be necessary to explicitly flush between context changes 253 OGLContext *currentContext = OGLRenderQueue_GetCurrentContext(); 254 if (currentContext != NULL) { 255 j2d_glFlush(); 256 } 257 258 if (dstOps->drawableType == OGLSD_FBOBJECT) { 259 // first make sure we have a current context (if the context isn't 260 // already current to some drawable, we will make it current to 261 // its scratch surface) 262 if (oglc != currentContext) { 263 if (!CGLSD_MakeCurrentToScratch(env, oglc)) { 264 return NULL; 265 } 266 } 267 268 // now bind to the fbobject associated with the destination surface; 269 // this means that all rendering will go into the fbobject destination 270 // (note that we unbind the currently bound texture first; this is 271 // recommended procedure when binding an fbobject) 272 j2d_glBindTexture(GL_TEXTURE_2D, 0); 273 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID); 274 275 return oglc; 276 } 277 278 JNF_COCOA_ENTER(env); 279 280 // set the current surface 281 if (dstOps->drawableType == OGLSD_PBUFFER) { 282 // REMIND: pbuffers are not fully tested yet... 283 [ctxinfo->context clearDrawable]; 284 [ctxinfo->context makeCurrentContext]; 285 [ctxinfo->context setPixelBuffer: dstCGLOps->pbuffer 286 cubeMapFace: 0 287 mipMapLevel: 0 288 currentVirtualScreen: [ctxinfo->context currentVirtualScreen]]; 289 } else { 290 CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps; 291 NSView *nsView = (NSView *)cglsdo->peerData; 292 293 if ([ctxinfo->context view] != nsView) { 294 [ctxinfo->context makeCurrentContext]; 295 [ctxinfo->context setView: nsView]; 296 } 297 } 298 299 if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) { 300 // the GL_EXT_framebuffer_object extension is present, so we 301 // must bind to the default (windowing system provided) 302 // framebuffer 303 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 304 } 305 306 if ((srcOps != dstOps) && (srcOps->drawableType == OGLSD_PBUFFER)) { 307 // bind pbuffer to the render texture object (since we are preparing 308 // to copy from the pbuffer) 309 CGLSDOps *srcCGLOps = (CGLSDOps *)srcOps->privOps; 310 j2d_glBindTexture(GL_TEXTURE_2D, srcOps->textureID); 311 [ctxinfo->context 312 setTextureImageToPixelBuffer: srcCGLOps->pbuffer 313 colorBuffer: GL_FRONT]; 314 } 315 316 JNF_COCOA_EXIT(env); 317 318 return oglc; 319 } 320 321 /** 322 * This function initializes a native window surface and caches the window 323 * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was 324 * successful; JNI_FALSE otherwise. 325 */ 326 jboolean 327 OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) 328 { 329 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow"); 330 331 if (oglsdo == NULL) { 332 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null"); 333 return JNI_FALSE; 334 } 335 336 CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; 337 if (cglsdo == NULL) { 338 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: cgl ops are null"); 339 return JNI_FALSE; 340 } 341 342 AWTView *v = cglsdo->peerData; 343 if (v == NULL) { 344 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: view is invalid"); 345 return JNI_FALSE; 346 } 347 348 JNF_COCOA_ENTER(env); 349 NSRect surfaceBounds = [v bounds]; 350 oglsdo->drawableType = OGLSD_WINDOW; 351 oglsdo->isOpaque = JNI_TRUE; 352 oglsdo->width = surfaceBounds.size.width; 353 oglsdo->height = surfaceBounds.size.height; 354 JNF_COCOA_EXIT(env); 355 356 J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height); 357 358 return JNI_TRUE; 359 } 360 361 void 362 OGLSD_SwapBuffers(JNIEnv *env, jlong pPeerData) 363 { 364 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers"); 365 366 JNF_COCOA_ENTER(env); 367 [[NSOpenGLContext currentContext] flushBuffer]; 368 JNF_COCOA_EXIT(env); 369 } 370 371 void 372 OGLSD_Flush(JNIEnv *env) 373 { 374 OGLSDOps *dstOps = OGLRenderQueue_GetCurrentDestination(); 375 if (dstOps != NULL) { 376 CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps; 377 CGLLayer *layer = (CGLLayer*)dstCGLOps->layer; 378 if (layer != NULL) { 379 [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ 380 AWT_ASSERT_APPKIT_THREAD; 381 [layer setNeedsDisplay]; 382 383 #ifdef REMOTELAYER 384 /* If there's a remote layer (being used for testing) 385 * then we want to have that also receive the texture. 386 * First sync. up its dimensions with that of the layer 387 * we have attached to the local window and tell it that 388 * it also needs to copy the texture. 389 */ 390 if (layer.remoteLayer != nil) { 391 CGLLayer* remoteLayer = layer.remoteLayer; 392 remoteLayer.target = GL_TEXTURE_2D; 393 remoteLayer.textureID = layer.textureID; 394 remoteLayer.textureWidth = layer.textureWidth; 395 remoteLayer.textureHeight = layer.textureHeight; 396 [remoteLayer setNeedsDisplay]; 397 } 398 #endif /* REMOTELAYER */ 399 }]; 400 } 401 } 402 } 403 404 #pragma mark - 405 #pragma mark "--- CGLSurfaceData methods ---" 406 407 extern LockFunc OGLSD_Lock; 408 extern GetRasInfoFunc OGLSD_GetRasInfo; 409 extern UnlockFunc OGLSD_Unlock; 410 extern DisposeFunc OGLSD_Dispose; 411 412 JNIEXPORT void JNICALL 413 Java_sun_java2d_opengl_CGLSurfaceData_initOps 414 (JNIEnv *env, jobject cglsd, 415 jlong pConfigInfo, jlong pPeerData, jlong layerPtr, 416 jint xoff, jint yoff, jboolean isOpaque) 417 { 418 J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_initOps"); 419 J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); 420 J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); 421 422 OGLSDOps *oglsdo = (OGLSDOps *) 423 SurfaceData_InitOps(env, cglsd, sizeof(OGLSDOps)); 424 CGLSDOps *cglsdo = (CGLSDOps *)malloc(sizeof(CGLSDOps)); 425 if (cglsdo == NULL) { 426 JNU_ThrowOutOfMemoryError(env, "creating native cgl ops"); 427 return; 428 } 429 430 oglsdo->privOps = cglsdo; 431 432 oglsdo->sdOps.Lock = OGLSD_Lock; 433 oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo; 434 oglsdo->sdOps.Unlock = OGLSD_Unlock; 435 oglsdo->sdOps.Dispose = OGLSD_Dispose; 436 437 oglsdo->drawableType = OGLSD_UNDEFINED; 438 oglsdo->activeBuffer = GL_FRONT; 439 oglsdo->needsInit = JNI_TRUE; 440 oglsdo->xOffset = xoff; 441 oglsdo->yOffset = yoff; 442 oglsdo->isOpaque = isOpaque; 443 444 cglsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData); 445 cglsdo->layer = (CGLLayer *)jlong_to_ptr(layerPtr); 446 cglsdo->configInfo = (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); 447 448 if (cglsdo->configInfo == NULL) { 449 free(cglsdo); 450 JNU_ThrowNullPointerException(env, "Config info is null in initOps"); 451 } 452 } 453 454 JNIEXPORT void JNICALL 455 Java_sun_java2d_opengl_CGLSurfaceData_clearWindow 456 (JNIEnv *env, jobject cglsd) 457 { 458 J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_clearWindow"); 459 460 OGLSDOps *oglsdo = (OGLSDOps*) SurfaceData_GetOps(env, cglsd); 461 CGLSDOps *cglsdo = (CGLSDOps*) oglsdo->privOps; 462 463 cglsdo->peerData = NULL; 464 cglsdo->layer = NULL; 465 } 466 467 JNIEXPORT jboolean JNICALL 468 Java_sun_java2d_opengl_CGLSurfaceData_initPbuffer 469 (JNIEnv *env, jobject cglsd, 470 jlong pData, jlong pConfigInfo, jboolean isOpaque, 471 jint width, jint height) 472 { 473 J2dTraceLn3(J2D_TRACE_INFO, "CGLSurfaceData_initPbuffer: w=%d h=%d opq=%d", width, height, isOpaque); 474 475 OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); 476 if (oglsdo == NULL) { 477 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: ops are null"); 478 return JNI_FALSE; 479 } 480 481 CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; 482 if (cglsdo == NULL) { 483 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: cgl ops are null"); 484 return JNI_FALSE; 485 } 486 487 CGLGraphicsConfigInfo *cglInfo = (CGLGraphicsConfigInfo *) 488 jlong_to_ptr(pConfigInfo); 489 if (cglInfo == NULL) { 490 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: cgl config info is null"); 491 return JNI_FALSE; 492 } 493 494 // find the maximum allowable texture dimensions (this value ultimately 495 // determines our maximum pbuffer size) 496 int pbMax = 0; 497 j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &pbMax); 498 499 int pbWidth = 0; 500 int pbHeight = 0; 501 if (OGLC_IS_CAP_PRESENT(cglInfo->context, CAPS_TEXNONPOW2)) { 502 // use non-power-of-two dimensions directly 503 pbWidth = (width <= pbMax) ? width : 0; 504 pbHeight = (height <= pbMax) ? height : 0; 505 } else { 506 // find the appropriate power-of-two dimensions 507 pbWidth = OGLSD_NextPowerOfTwo(width, pbMax); 508 pbHeight = OGLSD_NextPowerOfTwo(height, pbMax); 509 } 510 511 J2dTraceLn3(J2D_TRACE_VERBOSE, " desired pbuffer dimensions: w=%d h=%d max=%d", pbWidth, pbHeight, pbMax); 512 513 // if either dimension is 0, we cannot allocate a pbuffer/texture with the 514 // requested dimensions 515 if (pbWidth == 0 || pbHeight == 0) { 516 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: dimensions too large"); 517 return JNI_FALSE; 518 } 519 520 int format = isOpaque ? GL_RGB : GL_RGBA; 521 522 JNF_COCOA_ENTER(env); 523 524 cglsdo->pbuffer = 525 [[NSOpenGLPixelBuffer alloc] 526 initWithTextureTarget: GL_TEXTURE_2D 527 textureInternalFormat: format 528 textureMaxMipMapLevel: 0 529 pixelsWide: pbWidth 530 pixelsHigh: pbHeight]; 531 if (cglsdo->pbuffer == nil) { 532 J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: could not create pbuffer"); 533 return JNI_FALSE; 534 } 535 536 // make sure the actual dimensions match those that we requested 537 GLsizei actualWidth = [cglsdo->pbuffer pixelsWide]; 538 GLsizei actualHeight = [cglsdo->pbuffer pixelsHigh]; 539 if (actualWidth != pbWidth || actualHeight != pbHeight) { 540 J2dRlsTraceLn2(J2D_TRACE_ERROR, "CGLSurfaceData_initPbuffer: actual (w=%d h=%d) != requested", actualWidth, actualHeight); 541 [cglsdo->pbuffer release]; 542 return JNI_FALSE; 543 } 544 545 GLuint texID = 0; 546 j2d_glGenTextures(1, &texID); 547 j2d_glBindTexture(GL_TEXTURE_2D, texID); 548 549 oglsdo->drawableType = OGLSD_PBUFFER; 550 oglsdo->isOpaque = isOpaque; 551 oglsdo->width = width; 552 oglsdo->height = height; 553 oglsdo->textureID = texID; 554 oglsdo->textureWidth = pbWidth; 555 oglsdo->textureHeight = pbHeight; 556 oglsdo->activeBuffer = GL_FRONT; 557 oglsdo->needsInit = JNI_TRUE; 558 559 OGLSD_INIT_TEXTURE_FILTER(oglsdo, GL_NEAREST); 560 561 JNF_COCOA_EXIT(env); 562 563 return JNI_TRUE; 564 } 565 566 #pragma mark - 567 #pragma mark "--- CGLSurfaceData methods - Mac OS X specific ---" 568 569 // Must be called on the QFT... 570 JNIEXPORT void JNICALL 571 Java_sun_java2d_opengl_CGLSurfaceData_validate 572 (JNIEnv *env, jobject jsurfacedata, 573 jint xoff, jint yoff, jint width, jint height, jboolean isOpaque) 574 { 575 J2dTraceLn2(J2D_TRACE_INFO, "CGLSurfaceData_validate: w=%d h=%d", width, height); 576 577 OGLSDOps *oglsdo = (OGLSDOps*)SurfaceData_GetOps(env, jsurfacedata); 578 oglsdo->needsInit = JNI_TRUE; 579 oglsdo->xOffset = xoff; 580 oglsdo->yOffset = yoff; 581 582 oglsdo->width = width; 583 oglsdo->height = height; 584 oglsdo->isOpaque = isOpaque; 585 586 if (oglsdo->drawableType == OGLSD_WINDOW) { 587 OGLContext_SetSurfaces(env, ptr_to_jlong(oglsdo), ptr_to_jlong(oglsdo)); 588 589 // we have to explicitly tell the NSOpenGLContext that its target 590 // drawable has changed size 591 CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; 592 OGLContext *oglc = cglsdo->configInfo->context; 593 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; 594 595 JNF_COCOA_ENTER(env); 596 [ctxinfo->context update]; 597 JNF_COCOA_EXIT(env); 598 } 599 }