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 | +} | |