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