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