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
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)
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
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
|
1 /*
2 * Copyright (c) 2011, 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
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_WINDOW, 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_WINDOW) {
126 // detach the NSView from the NSOpenGLContext
127 CGLGraphicsConfigInfo *cglInfo = cglsdo->configInfo;
128 OGLContext *oglc = cglInfo->context;
129 CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
130 [ctxinfo->context clearDrawable];
131 }
132
133 oglsdo->drawableType = OGLSD_UNDEFINED;
134
135 JNF_COCOA_EXIT(env);
136 }
137
138 /**
139 * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo
140 * associated with the given OGLSDOps. This method can be called from
141 * shared code to retrieve the native GraphicsConfig data in a platform-
142 * independent manner.
143 */
144 jlong
145 OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo)
251 // already current to some drawable, we will make it current to
252 // its scratch surface)
253 if (oglc != currentContext) {
254 if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
255 return NULL;
256 }
257 }
258
259 // now bind to the fbobject associated with the destination surface;
260 // this means that all rendering will go into the fbobject destination
261 // (note that we unbind the currently bound texture first; this is
262 // recommended procedure when binding an fbobject)
263 j2d_glBindTexture(GL_TEXTURE_2D, 0);
264 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
265
266 return oglc;
267 }
268
269 JNF_COCOA_ENTER(env);
270
271 CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps;
272 NSView *nsView = (NSView *)cglsdo->peerData;
273
274 if ([ctxinfo->context view] != nsView) {
275 [ctxinfo->context makeCurrentContext];
276 [ctxinfo->context setView: nsView];
277 }
278
279 if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
280 // the GL_EXT_framebuffer_object extension is present, so we
281 // must bind to the default (windowing system provided)
282 // framebuffer
283 j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
284 }
285
286 JNF_COCOA_EXIT(env);
287
288 return oglc;
289 }
290
291 /**
292 * This function initializes a native window surface and caches the window
293 * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
294 * successful; JNI_FALSE otherwise.
295 */
296 jboolean
297 OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
298 {
299 J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
300
301 if (oglsdo == NULL) {
302 J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null");
303 return JNI_FALSE;
304 }
305
417
418 if (cglsdo->configInfo == NULL) {
419 free(cglsdo);
420 JNU_ThrowNullPointerException(env, "Config info is null in initOps");
421 }
422 }
423
424 JNIEXPORT void JNICALL
425 Java_sun_java2d_opengl_CGLSurfaceData_clearWindow
426 (JNIEnv *env, jobject cglsd)
427 {
428 J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_clearWindow");
429
430 OGLSDOps *oglsdo = (OGLSDOps*) SurfaceData_GetOps(env, cglsd);
431 CGLSDOps *cglsdo = (CGLSDOps*) oglsdo->privOps;
432
433 cglsdo->peerData = NULL;
434 cglsdo->layer = NULL;
435 }
436
437 #pragma mark -
438 #pragma mark "--- CGLSurfaceData methods - Mac OS X specific ---"
439
440 // Must be called on the QFT...
441 JNIEXPORT void JNICALL
442 Java_sun_java2d_opengl_CGLSurfaceData_validate
443 (JNIEnv *env, jobject jsurfacedata,
444 jint xoff, jint yoff, jint width, jint height, jboolean isOpaque)
445 {
446 J2dTraceLn2(J2D_TRACE_INFO, "CGLSurfaceData_validate: w=%d h=%d", width, height);
447
448 OGLSDOps *oglsdo = (OGLSDOps*)SurfaceData_GetOps(env, jsurfacedata);
449 oglsdo->needsInit = JNI_TRUE;
450 oglsdo->xOffset = xoff;
451 oglsdo->yOffset = yoff;
452
453 oglsdo->width = width;
454 oglsdo->height = height;
455 oglsdo->isOpaque = isOpaque;
456
|