1 /* 2 * Copyright (c) 2003, 2014, 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 package sun.java2d.opengl; 27 28 import java.awt.AlphaComposite; 29 import java.awt.Composite; 30 import java.awt.GraphicsEnvironment; 31 import java.awt.Rectangle; 32 import java.awt.Transparency; 33 import java.awt.image.ColorModel; 34 import java.awt.image.Raster; 35 import sun.awt.SunHints; 36 import sun.awt.image.PixelConverter; 37 import sun.java2d.pipe.hw.AccelSurface; 38 import sun.java2d.SunGraphics2D; 39 import sun.java2d.SurfaceData; 40 import sun.java2d.SurfaceDataProxy; 41 import sun.java2d.loops.CompositeType; 42 import sun.java2d.loops.GraphicsPrimitive; 43 import sun.java2d.loops.MaskFill; 44 import sun.java2d.loops.SurfaceType; 45 import sun.java2d.pipe.ParallelogramPipe; 46 import sun.java2d.pipe.PixelToParallelogramConverter; 47 import sun.java2d.pipe.RenderBuffer; 48 import sun.java2d.pipe.TextPipe; 49 import static sun.java2d.pipe.BufferedOpCodes.*; 50 import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; 51 52 /** 53 * This class describes an OpenGL "surface", that is, a region of pixels 54 * managed via OpenGL. An OGLSurfaceData can be tagged with one of three 55 * different SurfaceType objects for the purpose of registering loops, etc. 56 * This diagram shows the hierarchy of OGL SurfaceTypes: 57 * 58 * Any 59 * / \ 60 * OpenGLSurface OpenGLTexture 61 * | 62 * OpenGLSurfaceRTT 63 * 64 * OpenGLSurface 65 * This kind of surface can be rendered to using OpenGL APIs. It is also 66 * possible to copy an OpenGLSurface to another OpenGLSurface (or to itself). 67 * This is typically accomplished by calling MakeContextCurrent(dstSD, srcSD) 68 * and then calling glCopyPixels() (although there are other techniques to 69 * achieve the same goal). 70 * 71 * OpenGLTexture 72 * This kind of surface cannot be rendered to using OpenGL (in the same sense 73 * as in OpenGLSurface). However, it is possible to upload a region of pixels 74 * to an OpenGLTexture object via glTexSubImage2D(). One can also copy a 75 * surface of type OpenGLTexture to an OpenGLSurface by binding the texture 76 * to a quad and then rendering it to the destination surface (this process 77 * is known as "texture mapping"). 78 * 79 * OpenGLSurfaceRTT 80 * This kind of surface can be thought of as a sort of hybrid between 81 * OpenGLSurface and OpenGLTexture, in that one can render to this kind of 82 * surface as if it were of type OpenGLSurface, but the process of copying 83 * this kind of surface to another is more like an OpenGLTexture. (Note that 84 * "RTT" stands for "render-to-texture".) 85 * 86 * In addition to these SurfaceType variants, we have also defined some 87 * constants that describe in more detail the type of underlying OpenGL 88 * surface. This table helps explain the relationships between those 89 * "type" constants and their corresponding SurfaceType: 90 * 91 * OGL Type Corresponding SurfaceType 92 * -------- ------------------------- 93 * WINDOW OpenGLSurface 94 * PBUFFER OpenGLSurface 95 * TEXTURE OpenGLTexture 96 * FLIP_BACKBUFFER OpenGLSurface 97 * FBOBJECT OpenGLSurfaceRTT 98 */ 99 public abstract class OGLSurfaceData extends SurfaceData 100 implements AccelSurface { 101 102 /** 103 * OGL-specific surface types 104 * 105 * @see sun.java2d.pipe.hw.AccelSurface 106 */ 107 public static final int PBUFFER = RT_PLAIN; 108 public static final int FBOBJECT = RT_TEXTURE; 109 110 /** 111 * Pixel formats 112 */ 113 public static final int PF_INT_ARGB = 0; 114 public static final int PF_INT_ARGB_PRE = 1; 115 public static final int PF_INT_RGB = 2; 116 public static final int PF_INT_RGBX = 3; 117 public static final int PF_INT_BGR = 4; 118 public static final int PF_INT_BGRX = 5; 119 public static final int PF_USHORT_565_RGB = 6; 120 public static final int PF_USHORT_555_RGB = 7; 121 public static final int PF_USHORT_555_RGBX = 8; 122 public static final int PF_BYTE_GRAY = 9; 123 public static final int PF_USHORT_GRAY = 10; 124 public static final int PF_3BYTE_BGR = 11; 125 126 /** 127 * SurfaceTypes 128 */ 129 private static final String DESC_OPENGL_SURFACE = "OpenGL Surface"; 130 private static final String DESC_OPENGL_SURFACE_RTT = 131 "OpenGL Surface (render-to-texture)"; 132 private static final String DESC_OPENGL_TEXTURE = "OpenGL Texture"; 133 134 static final SurfaceType OpenGLSurface = 135 SurfaceType.Any.deriveSubType(DESC_OPENGL_SURFACE, 136 PixelConverter.ArgbPre.instance); 137 static final SurfaceType OpenGLSurfaceRTT = 138 OpenGLSurface.deriveSubType(DESC_OPENGL_SURFACE_RTT); 139 static final SurfaceType OpenGLTexture = 140 SurfaceType.Any.deriveSubType(DESC_OPENGL_TEXTURE); 141 142 /** This will be true if the fbobject system property has been enabled. */ 143 private static boolean isFBObjectEnabled; 144 145 /** This will be true if the lcdshader system property has been enabled.*/ 146 private static boolean isLCDShaderEnabled; 147 148 /** This will be true if the biopshader system property has been enabled.*/ 149 private static boolean isBIOpShaderEnabled; 150 151 /** This will be true if the gradshader system property has been enabled.*/ 152 private static boolean isGradShaderEnabled; 153 154 private OGLGraphicsConfig graphicsConfig; 155 protected int type; 156 // these fields are set from the native code when the surface is 157 // initialized 158 private int nativeWidth, nativeHeight; 159 160 protected static OGLRenderer oglRenderPipe; 161 protected static PixelToParallelogramConverter oglTxRenderPipe; 162 protected static ParallelogramPipe oglAAPgramPipe; 163 protected static OGLTextRenderer oglTextPipe; 164 protected static OGLDrawImage oglImagePipe; 165 166 protected native boolean initTexture(long pData, 167 boolean isOpaque, boolean texNonPow2, 168 boolean texRect, 169 int width, int height); 170 protected native boolean initFBObject(long pData, 171 boolean isOpaque, boolean texNonPow2, 172 boolean texRect, 173 int width, int height); 174 protected native boolean initFlipBackbuffer(long pData); 175 protected abstract boolean initPbuffer(long pData, long pConfigInfo, 176 boolean isOpaque, 177 int width, int height); 178 179 private native int getTextureTarget(long pData); 180 private native int getTextureID(long pData); 181 182 static { 183 if (!GraphicsEnvironment.isHeadless()) { 184 // fbobject currently enabled by default; use "false" to disable 185 String fbo = java.security.AccessController.doPrivileged( 186 new sun.security.action.GetPropertyAction( 187 "sun.java2d.opengl.fbobject")); 188 isFBObjectEnabled = !"false".equals(fbo); 189 190 // lcdshader currently enabled by default; use "false" to disable 191 String lcd = java.security.AccessController.doPrivileged( 192 new sun.security.action.GetPropertyAction( 193 "sun.java2d.opengl.lcdshader")); 194 isLCDShaderEnabled = !"false".equals(lcd); 195 196 // biopshader currently enabled by default; use "false" to disable 197 String biop = java.security.AccessController.doPrivileged( 198 new sun.security.action.GetPropertyAction( 199 "sun.java2d.opengl.biopshader")); 200 isBIOpShaderEnabled = !"false".equals(biop); 201 202 // gradshader currently enabled by default; use "false" to disable 203 String grad = java.security.AccessController.doPrivileged( 204 new sun.security.action.GetPropertyAction( 205 "sun.java2d.opengl.gradshader")); 206 isGradShaderEnabled = !"false".equals(grad); 207 208 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 209 oglImagePipe = new OGLDrawImage(); 210 oglTextPipe = new OGLTextRenderer(rq); 211 oglRenderPipe = new OGLRenderer(rq); 212 if (GraphicsPrimitive.tracingEnabled()) { 213 oglTextPipe = oglTextPipe.traceWrap(); 214 //The wrapped oglRenderPipe will wrap the AA pipe as well... 215 //oglAAPgramPipe = oglRenderPipe.traceWrap(); 216 } 217 oglAAPgramPipe = oglRenderPipe.getAAParallelogramPipe(); 218 oglTxRenderPipe = 219 new PixelToParallelogramConverter(oglRenderPipe, 220 oglRenderPipe, 221 1.0, 0.25, true); 222 223 OGLBlitLoops.register(); 224 OGLMaskFill.register(); 225 OGLMaskBlit.register(); 226 } 227 } 228 229 protected OGLSurfaceData(OGLGraphicsConfig gc, 230 ColorModel cm, int type) 231 { 232 super(getCustomSurfaceType(type), cm); 233 this.graphicsConfig = gc; 234 this.type = type; 235 setBlitProxyKey(gc.getProxyKey()); 236 } 237 238 @Override 239 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 240 return OGLSurfaceDataProxy.createProxy(srcData, graphicsConfig); 241 } 242 243 /** 244 * Returns the appropriate SurfaceType corresponding to the given OpenGL 245 * surface type constant (e.g. TEXTURE -> OpenGLTexture). 246 */ 247 private static SurfaceType getCustomSurfaceType(int oglType) { 248 switch (oglType) { 249 case TEXTURE: 250 return OpenGLTexture; 251 case FBOBJECT: 252 return OpenGLSurfaceRTT; 253 case PBUFFER: 254 default: 255 return OpenGLSurface; 256 } 257 } 258 259 /** 260 * Note: This should only be called from the QFT under the AWT lock. 261 * This method is kept separate from the initSurface() method below just 262 * to keep the code a bit cleaner. 263 */ 264 private void initSurfaceNow(int width, int height) { 265 boolean isOpaque = (getTransparency() == Transparency.OPAQUE); 266 boolean success = false; 267 268 switch (type) { 269 case PBUFFER: 270 success = initPbuffer(getNativeOps(), 271 graphicsConfig.getNativeConfigInfo(), 272 isOpaque, 273 width, height); 274 break; 275 276 case TEXTURE: 277 success = initTexture(getNativeOps(), 278 isOpaque, isTexNonPow2Available(), 279 isTexRectAvailable(), 280 width, height); 281 break; 282 283 case FBOBJECT: 284 success = initFBObject(getNativeOps(), 285 isOpaque, isTexNonPow2Available(), 286 isTexRectAvailable(), 287 width, height); 288 break; 289 290 case FLIP_BACKBUFFER: 291 success = initFlipBackbuffer(getNativeOps()); 292 break; 293 294 default: 295 break; 296 } 297 298 if (!success) { 299 throw new OutOfMemoryError("can't create offscreen surface"); 300 } 301 } 302 303 /** 304 * Initializes the appropriate OpenGL offscreen surface based on the value 305 * of the type parameter. If the surface creation fails for any reason, 306 * an OutOfMemoryError will be thrown. 307 */ 308 protected void initSurface(final int width, final int height) { 309 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 310 rq.lock(); 311 try { 312 switch (type) { 313 case TEXTURE: 314 case PBUFFER: 315 case FBOBJECT: 316 // need to make sure the context is current before 317 // creating the texture (or pbuffer, or fbobject) 318 OGLContext.setScratchSurface(graphicsConfig); 319 break; 320 default: 321 break; 322 } 323 rq.flushAndInvokeNow(new Runnable() { 324 public void run() { 325 initSurfaceNow(width, height); 326 } 327 }); 328 } finally { 329 rq.unlock(); 330 } 331 } 332 333 /** 334 * Returns the OGLContext for the GraphicsConfig associated with this 335 * surface. 336 */ 337 public final OGLContext getContext() { 338 return graphicsConfig.getContext(); 339 } 340 341 /** 342 * Returns the OGLGraphicsConfig associated with this surface. 343 */ 344 final OGLGraphicsConfig getOGLGraphicsConfig() { 345 return graphicsConfig; 346 } 347 348 /** 349 * Returns one of the surface type constants defined above. 350 */ 351 public final int getType() { 352 return type; 353 } 354 355 /** 356 * If this surface is backed by a texture object, returns the target 357 * for that texture (either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB). 358 * Otherwise, this method will return zero. 359 */ 360 public final int getTextureTarget() { 361 return getTextureTarget(getNativeOps()); 362 } 363 364 /** 365 * If this surface is backed by a texture object, returns the texture ID 366 * for that texture. 367 * Otherwise, this method will return zero. 368 */ 369 public final int getTextureID() { 370 return getTextureID(getNativeOps()); 371 } 372 373 /** 374 * Returns native resource of specified {@code resType} associated with 375 * this surface. 376 * 377 * Specifically, for {@code OGLSurfaceData} this method returns the 378 * the following: 379 * <pre> 380 * TEXTURE - texture id 381 * </pre> 382 * 383 * Note: the resource returned by this method is only valid on the rendering 384 * thread. 385 * 386 * @return native resource of specified type or 0L if 387 * such resource doesn't exist or can not be retrieved. 388 * @see sun.java2d.pipe.hw.AccelSurface#getNativeResource 389 */ 390 public long getNativeResource(int resType) { 391 if (resType == TEXTURE) { 392 return getTextureID(); 393 } 394 return 0L; 395 } 396 397 public Raster getRaster(int x, int y, int w, int h) { 398 throw new InternalError("not implemented yet"); 399 } 400 401 /** 402 * For now, we can only render LCD text if: 403 * - the fragment shader extension is available, and 404 * - the source color is opaque, and 405 * - blending is SrcOverNoEa or disabled 406 * - and the destination is opaque 407 * 408 * Eventually, we could enhance the native OGL text rendering code 409 * and remove the above restrictions, but that would require significantly 410 * more code just to support a few uncommon cases. 411 */ 412 public boolean canRenderLCDText(SunGraphics2D sg2d) { 413 return 414 graphicsConfig.isCapPresent(CAPS_EXT_LCD_SHADER) && 415 sg2d.surfaceData.getTransparency() == Transparency.OPAQUE && 416 sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR && 417 (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY || 418 (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA && canHandleComposite(sg2d.composite))); 419 } 420 421 private boolean canHandleComposite(Composite c) { 422 if (c instanceof AlphaComposite) { 423 AlphaComposite ac = (AlphaComposite)c; 424 425 return ac.getRule() == AlphaComposite.SRC_OVER && ac.getAlpha() >= 1f; 426 } 427 return false; 428 } 429 430 public void validatePipe(SunGraphics2D sg2d) { 431 TextPipe textpipe; 432 boolean validated = false; 433 434 // OGLTextRenderer handles both AA and non-AA text, but 435 // only works with the following modes: 436 // (Note: For LCD text we only enter this code path if 437 // canRenderLCDText() has already validated that the mode is 438 // CompositeType.SrcNoEa (opaque color), which will be subsumed 439 // by the CompositeType.SrcNoEa (any color) test below.) 440 441 if (/* CompositeType.SrcNoEa (any color) */ 442 (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY && 443 sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) || 444 445 /* CompositeType.SrcOver (any color) */ 446 (sg2d.compositeState == SunGraphics2D.COMP_ALPHA && 447 sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && 448 (((AlphaComposite)sg2d.composite).getRule() == 449 AlphaComposite.SRC_OVER)) || 450 451 /* CompositeType.Xor (any color) */ 452 (sg2d.compositeState == SunGraphics2D.COMP_XOR && 453 sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR)) 454 { 455 textpipe = oglTextPipe; 456 } else { 457 // do this to initialize textpipe correctly; we will attempt 458 // to override the non-text pipes below 459 super.validatePipe(sg2d); 460 textpipe = sg2d.textpipe; 461 validated = true; 462 } 463 464 PixelToParallelogramConverter txPipe = null; 465 OGLRenderer nonTxPipe = null; 466 467 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { 468 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) { 469 if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) { 470 txPipe = oglTxRenderPipe; 471 nonTxPipe = oglRenderPipe; 472 } 473 } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) { 474 if (OGLPaints.isValid(sg2d)) { 475 txPipe = oglTxRenderPipe; 476 nonTxPipe = oglRenderPipe; 477 } 478 // custom paints handled by super.validatePipe() below 479 } 480 } else { 481 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) { 482 if (graphicsConfig.isCapPresent(CAPS_PS30) && 483 (sg2d.imageComp == CompositeType.SrcOverNoEa || 484 sg2d.imageComp == CompositeType.SrcOver)) 485 { 486 if (!validated) { 487 super.validatePipe(sg2d); 488 validated = true; 489 } 490 PixelToParallelogramConverter aaConverter = 491 new PixelToParallelogramConverter(sg2d.shapepipe, 492 oglAAPgramPipe, 493 1.0/8.0, 0.499, 494 false); 495 sg2d.drawpipe = aaConverter; 496 sg2d.fillpipe = aaConverter; 497 sg2d.shapepipe = aaConverter; 498 } else if (sg2d.compositeState == SunGraphics2D.COMP_XOR) { 499 // install the solid pipes when AA and XOR are both enabled 500 txPipe = oglTxRenderPipe; 501 nonTxPipe = oglRenderPipe; 502 } 503 } 504 // other cases handled by super.validatePipe() below 505 } 506 507 if (txPipe != null) { 508 if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 509 sg2d.drawpipe = txPipe; 510 sg2d.fillpipe = txPipe; 511 } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) { 512 sg2d.drawpipe = txPipe; 513 sg2d.fillpipe = nonTxPipe; 514 } else { 515 sg2d.drawpipe = nonTxPipe; 516 sg2d.fillpipe = nonTxPipe; 517 } 518 // Note that we use the transforming pipe here because it 519 // will examine the shape and possibly perform an optimized 520 // operation if it can be simplified. The simplifications 521 // will be valid for all STROKE and TRANSFORM types. 522 sg2d.shapepipe = txPipe; 523 } else { 524 if (!validated) { 525 super.validatePipe(sg2d); 526 } 527 } 528 529 // install the text pipe based on our earlier decision 530 sg2d.textpipe = textpipe; 531 532 // always override the image pipe with the specialized OGL pipe 533 sg2d.imagepipe = oglImagePipe; 534 } 535 536 @Override 537 protected MaskFill getMaskFill(SunGraphics2D sg2d) { 538 if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) { 539 /* 540 * We can only accelerate non-Color MaskFill operations if 541 * all of the following conditions hold true: 542 * - there is an implementation for the given paintState 543 * - the current Paint can be accelerated for this destination 544 * - multitexturing is available (since we need to modulate 545 * the alpha mask texture with the paint texture) 546 * 547 * In all other cases, we return null, in which case the 548 * validation code will choose a more general software-based loop. 549 */ 550 if (!OGLPaints.isValid(sg2d) || 551 !graphicsConfig.isCapPresent(CAPS_MULTITEXTURE)) 552 { 553 return null; 554 } 555 } 556 return super.getMaskFill(sg2d); 557 } 558 559 public boolean copyArea(SunGraphics2D sg2d, 560 int x, int y, int w, int h, int dx, int dy) 561 { 562 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE && 563 sg2d.compositeState < SunGraphics2D.COMP_XOR) 564 { 565 x += sg2d.transX; 566 y += sg2d.transY; 567 568 oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy); 569 570 return true; 571 } 572 return false; 573 } 574 575 public void flush() { 576 invalidate(); 577 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 578 rq.lock(); 579 try { 580 // make sure we have a current context before 581 // disposing the native resources (e.g. texture object) 582 OGLContext.setScratchSurface(graphicsConfig); 583 584 RenderBuffer buf = rq.getBuffer(); 585 rq.ensureCapacityAndAlignment(12, 4); 586 buf.putInt(FLUSH_SURFACE); 587 buf.putLong(getNativeOps()); 588 589 // this call is expected to complete synchronously, so flush now 590 rq.flushNow(); 591 } finally { 592 rq.unlock(); 593 } 594 } 595 596 /** 597 * Disposes the native resources associated with the given OGLSurfaceData 598 * (referenced by the pData parameter). This method is invoked from 599 * the native Dispose() method from the Disposer thread when the 600 * Java-level OGLSurfaceData object is about to go away. Note that we 601 * also pass a reference to the native GLX/WGLGraphicsConfigInfo 602 * (pConfigInfo) for the purposes of making a context current. 603 */ 604 static void dispose(long pData, long pConfigInfo) { 605 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 606 rq.lock(); 607 try { 608 // make sure we have a current context before 609 // disposing the native resources (e.g. texture object) 610 OGLContext.setScratchSurface(pConfigInfo); 611 612 RenderBuffer buf = rq.getBuffer(); 613 rq.ensureCapacityAndAlignment(12, 4); 614 buf.putInt(DISPOSE_SURFACE); 615 buf.putLong(pData); 616 617 // this call is expected to complete synchronously, so flush now 618 rq.flushNow(); 619 } finally { 620 rq.unlock(); 621 } 622 } 623 624 static void swapBuffers(long window) { 625 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 626 rq.lock(); 627 try { 628 RenderBuffer buf = rq.getBuffer(); 629 rq.ensureCapacityAndAlignment(12, 4); 630 buf.putInt(SWAP_BUFFERS); 631 buf.putLong(window); 632 rq.flushNow(); 633 } finally { 634 rq.unlock(); 635 } 636 } 637 638 /** 639 * Returns true if OpenGL textures can have non-power-of-two dimensions 640 * when using the basic GL_TEXTURE_2D target. 641 */ 642 boolean isTexNonPow2Available() { 643 return graphicsConfig.isCapPresent(CAPS_TEXNONPOW2); 644 } 645 646 /** 647 * Returns true if OpenGL textures can have non-power-of-two dimensions 648 * when using the GL_TEXTURE_RECTANGLE_ARB target (only available when the 649 * GL_ARB_texture_rectangle extension is present). 650 */ 651 boolean isTexRectAvailable() { 652 return graphicsConfig.isCapPresent(CAPS_EXT_TEXRECT); 653 } 654 655 public Rectangle getNativeBounds() { 656 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 657 rq.lock(); 658 try { 659 return new Rectangle(nativeWidth, nativeHeight); 660 } finally { 661 rq.unlock(); 662 } 663 } 664 665 /** 666 * Returns true if the surface is an on-screen window surface or 667 * a FBO texture attached to an on-screen CALayer. 668 * 669 * Needed by Mac OS X port. 670 */ 671 boolean isOnScreen() { 672 return getType() == WINDOW; 673 } 674 }