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 */
40extern jlong OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo);
41extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo);
42extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo);
43
44void 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 */
53OGLPixelFormat 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 */
84jint
85OGLSD_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 */
101static jboolean
102OGLSD_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 */
133static jboolean
134OGLSD_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 */
241JNIEXPORT jboolean JNICALL
242Java_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 */
298jboolean
299OGLSD_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 */
392JNIEXPORT jboolean JNICALL
393Java_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 */
454JNIEXPORT jboolean JNICALL
455Java_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
494JNIEXPORT jint JNICALL
495Java_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
512JNIEXPORT jint JNICALL
513Java_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 */
534void
535OGLSD_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 */
556void
557OGLSD_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 */
592void
593OGLSD_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 */
607jint
608OGLSD_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 */
621void
622OGLSD_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 */
633void
634OGLSD_Unlock(JNIEnv *env,
635 SurfaceDataOps *ops,
636 SurfaceDataRasInfo *pRasInfo)
637{
638 JNU_ThrowInternalError(env, "OGLSD_Unlock not implemented!");
639}
640
641#endif /* !HEADLESS */
642