Showing the changes to java/pkg/sun/java2d/opengl (15 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,762 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2007, 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.Composite; | ||
| 29 | import java.awt.Transparency; | ||
| 30 | import java.awt.geom.AffineTransform; | ||
| 31 | import java.awt.image.AffineTransformOp; | ||
| 32 | import java.awt.image.BufferedImage; | ||
| 33 | import java.awt.image.BufferedImageOp; | ||
| 34 | import java.lang.ref.WeakReference; | ||
| 35 | import sun.java2d.SurfaceData; | ||
| 36 | import sun.java2d.loops.Blit; | ||
| 37 | import sun.java2d.loops.CompositeType; | ||
| 38 | import sun.java2d.loops.GraphicsPrimitive; | ||
| 39 | import sun.java2d.loops.GraphicsPrimitiveMgr; | ||
| 40 | import sun.java2d.loops.ScaledBlit; | ||
| 41 | import sun.java2d.loops.SurfaceType; | ||
| 42 | import sun.java2d.loops.TransformBlit; | ||
| 43 | import sun.java2d.pipe.Region; | ||
| 44 | import sun.java2d.pipe.RenderBuffer; | ||
| 45 | import sun.java2d.pipe.RenderQueue; | ||
| 46 | import static sun.java2d.pipe.BufferedOpCodes.*; | ||
| 47 | |||
| 48 | class OGLBlitLoops { | ||
| 49 | |||
| 50 | static void register() { | ||
| 51 | Blit blitIntArgbPreToSurface = | ||
| 52 | new OGLSwToSurfaceBlit(SurfaceType.IntArgbPre, | ||
| 53 | OGLSurfaceData.PF_INT_ARGB_PRE); | ||
| 54 | Blit blitIntArgbPreToTexture = | ||
| 55 | new OGLSwToTextureBlit(SurfaceType.IntArgbPre, | ||
| 56 | OGLSurfaceData.PF_INT_ARGB_PRE); | ||
| 57 | |||
| 58 | GraphicsPrimitive[] primitives = { | ||
| 59 | // surface->surface ops | ||
| 60 | new OGLSurfaceToSurfaceBlit(), | ||
| 61 | new OGLSurfaceToSurfaceScale(), | ||
| 62 | new OGLSurfaceToSurfaceTransform(), | ||
| 63 | |||
| 64 | // render-to-texture surface->surface ops | ||
| 65 | new OGLRTTSurfaceToSurfaceBlit(), | ||
| 66 | new OGLRTTSurfaceToSurfaceScale(), | ||
| 67 | new OGLRTTSurfaceToSurfaceTransform(), | ||
| 68 | |||
| 69 | // surface->sw ops | ||
| 70 | new OGLSurfaceToSwBlit(SurfaceType.IntArgb, | ||
| 71 | OGLSurfaceData.PF_INT_ARGB), | ||
| 72 | |||
| 73 | // sw->surface ops | ||
| 74 | blitIntArgbPreToSurface, | ||
| 75 | new OGLSwToSurfaceBlit(SurfaceType.IntRgb, | ||
| 76 | OGLSurfaceData.PF_INT_RGB), | ||
| 77 | new OGLSwToSurfaceBlit(SurfaceType.IntRgbx, | ||
| 78 | OGLSurfaceData.PF_INT_RGBX), | ||
| 79 | new OGLSwToSurfaceBlit(SurfaceType.IntBgr, | ||
| 80 | OGLSurfaceData.PF_INT_BGR), | ||
| 81 | new OGLSwToSurfaceBlit(SurfaceType.IntBgrx, | ||
| 82 | OGLSurfaceData.PF_INT_BGRX), | ||
| 83 | new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr, | ||
| 84 | OGLSurfaceData.PF_3BYTE_BGR), | ||
| 85 | new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb, | ||
| 86 | OGLSurfaceData.PF_USHORT_565_RGB), | ||
| 87 | new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb, | ||
| 88 | OGLSurfaceData.PF_USHORT_555_RGB), | ||
| 89 | new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx, | ||
| 90 | OGLSurfaceData.PF_USHORT_555_RGBX), | ||
| 91 | new OGLSwToSurfaceBlit(SurfaceType.ByteGray, | ||
| 92 | OGLSurfaceData.PF_BYTE_GRAY), | ||
| 93 | new OGLSwToSurfaceBlit(SurfaceType.UshortGray, | ||
| 94 | OGLSurfaceData.PF_USHORT_GRAY), | ||
| 95 | new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface, | ||
| 96 | CompositeType.AnyAlpha, | ||
| 97 | blitIntArgbPreToSurface), | ||
| 98 | |||
| 99 | new OGLSwToSurfaceScale(SurfaceType.IntRgb, | ||
| 100 | OGLSurfaceData.PF_INT_RGB), | ||
| 101 | new OGLSwToSurfaceScale(SurfaceType.IntRgbx, | ||
| 102 | OGLSurfaceData.PF_INT_RGBX), | ||
| 103 | new OGLSwToSurfaceScale(SurfaceType.IntBgr, | ||
| 104 | OGLSurfaceData.PF_INT_BGR), | ||
| 105 | new OGLSwToSurfaceScale(SurfaceType.IntBgrx, | ||
| 106 | OGLSurfaceData.PF_INT_BGRX), | ||
| 107 | new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr, | ||
| 108 | OGLSurfaceData.PF_3BYTE_BGR), | ||
| 109 | new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb, | ||
| 110 | OGLSurfaceData.PF_USHORT_565_RGB), | ||
| 111 | new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb, | ||
| 112 | OGLSurfaceData.PF_USHORT_555_RGB), | ||
| 113 | new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx, | ||
| 114 | OGLSurfaceData.PF_USHORT_555_RGBX), | ||
| 115 | new OGLSwToSurfaceScale(SurfaceType.ByteGray, | ||
| 116 | OGLSurfaceData.PF_BYTE_GRAY), | ||
| 117 | new OGLSwToSurfaceScale(SurfaceType.UshortGray, | ||
| 118 | OGLSurfaceData.PF_USHORT_GRAY), | ||
| 119 | new OGLSwToSurfaceScale(SurfaceType.IntArgbPre, | ||
| 120 | OGLSurfaceData.PF_INT_ARGB_PRE), | ||
| 121 | |||
| 122 | new OGLSwToSurfaceTransform(SurfaceType.IntRgb, | ||
| 123 | OGLSurfaceData.PF_INT_RGB), | ||
| 124 | new OGLSwToSurfaceTransform(SurfaceType.IntRgbx, | ||
| 125 | OGLSurfaceData.PF_INT_RGBX), | ||
| 126 | new OGLSwToSurfaceTransform(SurfaceType.IntBgr, | ||
| 127 | OGLSurfaceData.PF_INT_BGR), | ||
| 128 | new OGLSwToSurfaceTransform(SurfaceType.IntBgrx, | ||
| 129 | OGLSurfaceData.PF_INT_BGRX), | ||
| 130 | new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr, | ||
| 131 | OGLSurfaceData.PF_3BYTE_BGR), | ||
| 132 | new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb, | ||
| 133 | OGLSurfaceData.PF_USHORT_565_RGB), | ||
| 134 | new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb, | ||
| 135 | OGLSurfaceData.PF_USHORT_555_RGB), | ||
| 136 | new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx, | ||
| 137 | OGLSurfaceData.PF_USHORT_555_RGBX), | ||
| 138 | new OGLSwToSurfaceTransform(SurfaceType.ByteGray, | ||
| 139 | OGLSurfaceData.PF_BYTE_GRAY), | ||
| 140 | new OGLSwToSurfaceTransform(SurfaceType.UshortGray, | ||
| 141 | OGLSurfaceData.PF_USHORT_GRAY), | ||
| 142 | new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, | ||
| 143 | OGLSurfaceData.PF_INT_ARGB_PRE), | ||
| 144 | |||
| 145 | // texture->surface ops | ||
| 146 | new OGLTextureToSurfaceBlit(), | ||
| 147 | new OGLTextureToSurfaceScale(), | ||
| 148 | new OGLTextureToSurfaceTransform(), | ||
| 149 | |||
| 150 | // sw->texture ops | ||
| 151 | blitIntArgbPreToTexture, | ||
| 152 | new OGLSwToTextureBlit(SurfaceType.IntRgb, | ||
| 153 | OGLSurfaceData.PF_INT_RGB), | ||
| 154 | new OGLSwToTextureBlit(SurfaceType.IntRgbx, | ||
| 155 | OGLSurfaceData.PF_INT_RGBX), | ||
| 156 | new OGLSwToTextureBlit(SurfaceType.IntBgr, | ||
| 157 | OGLSurfaceData.PF_INT_BGR), | ||
| 158 | new OGLSwToTextureBlit(SurfaceType.IntBgrx, | ||
| 159 | OGLSurfaceData.PF_INT_BGRX), | ||
| 160 | new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr, | ||
| 161 | OGLSurfaceData.PF_3BYTE_BGR), | ||
| 162 | new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb, | ||
| 163 | OGLSurfaceData.PF_USHORT_565_RGB), | ||
| 164 | new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb, | ||
| 165 | OGLSurfaceData.PF_USHORT_555_RGB), | ||
| 166 | new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx, | ||
| 167 | OGLSurfaceData.PF_USHORT_555_RGBX), | ||
| 168 | new OGLSwToTextureBlit(SurfaceType.ByteGray, | ||
| 169 | OGLSurfaceData.PF_BYTE_GRAY), | ||
| 170 | new OGLSwToTextureBlit(SurfaceType.UshortGray, | ||
| 171 | OGLSurfaceData.PF_USHORT_GRAY), | ||
| 172 | new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture, | ||
| 173 | CompositeType.SrcNoEa, | ||
| 174 | blitIntArgbPreToTexture), | ||
| 175 | }; | ||
| 176 | GraphicsPrimitiveMgr.register(primitives); | ||
| 177 | } | ||
| 178 | |||
| 179 | /** | ||
| 180 | * The following offsets are used to pack the parameters in | ||
| 181 | * createPackedParams(). (They are also used at the native level when | ||
| 182 | * unpacking the params.) | ||
| 183 | */ | ||
| 184 | private static final int OFFSET_SRCTYPE = 16; | ||
| 185 | private static final int OFFSET_HINT = 8; | ||
| 186 | private static final int OFFSET_TEXTURE = 3; | ||
| 187 | private static final int OFFSET_RTT = 2; | ||
| 188 | private static final int OFFSET_XFORM = 1; | ||
| 189 | private static final int OFFSET_ISOBLIT = 0; | ||
| 190 | |||
| 191 | /** | ||
| 192 | * Packs the given parameters into a single int value in order to save | ||
| 193 | * space on the rendering queue. | ||
| 194 | */ | ||
| 195 | private static int createPackedParams(boolean isoblit, boolean texture, | ||
| 196 | boolean rtt, boolean xform, | ||
| 197 | int hint, int srctype) | ||
| 198 | { | ||
| 199 | return | ||
| 200 | ((srctype << OFFSET_SRCTYPE) | | ||
| 201 | (hint << OFFSET_HINT ) | | ||
| 202 | ((texture ? 1 : 0) << OFFSET_TEXTURE) | | ||
| 203 | ((rtt ? 1 : 0) << OFFSET_RTT ) | | ||
| 204 | ((xform ? 1 : 0) << OFFSET_XFORM ) | | ||
| 205 | ((isoblit ? 1 : 0) << OFFSET_ISOBLIT)); | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Enqueues a BLIT operation with the given parameters. Note that the | ||
| 210 | * RenderQueue lock must be held before calling this method. | ||
| 211 | */ | ||
| 212 | private static void enqueueBlit(RenderQueue rq, | ||
| 213 | SurfaceData src, SurfaceData dst, | ||
| 214 | int packedParams, | ||
| 215 | int sx1, int sy1, | ||
| 216 | int sx2, int sy2, | ||
| 217 | double dx1, double dy1, | ||
| 218 | double dx2, double dy2) | ||
| 219 | { | ||
| 220 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 221 | RenderBuffer buf = rq.getBuffer(); | ||
| 222 | rq.ensureCapacityAndAlignment(72, 24); | ||
| 223 | buf.putInt(BLIT); | ||
| 224 | buf.putInt(packedParams); | ||
| 225 | buf.putInt(sx1).putInt(sy1); | ||
| 226 | buf.putInt(sx2).putInt(sy2); | ||
| 227 | buf.putDouble(dx1).putDouble(dy1); | ||
| 228 | buf.putDouble(dx2).putDouble(dy2); | ||
| 229 | buf.putLong(src.getNativeOps()); | ||
| 230 | buf.putLong(dst.getNativeOps()); | ||
| 231 | } | ||
| 232 | |||
| 233 | static void Blit(SurfaceData srcData, SurfaceData dstData, | ||
| 234 | Composite comp, Region clip, | ||
| 235 | AffineTransform xform, int hint, | ||
| 236 | int sx1, int sy1, | ||
| 237 | int sx2, int sy2, | ||
| 238 | double dx1, double dy1, | ||
| 239 | double dx2, double dy2, | ||
| 240 | int srctype, boolean texture) | ||
| 241 | { | ||
| 242 | int ctxflags = 0; | ||
| 243 | if (srcData.getTransparency() == Transparency.OPAQUE) { | ||
| 244 | ctxflags |= OGLContext.SRC_IS_OPAQUE; | ||
| 245 | } | ||
| 246 | |||
| 247 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 248 | rq.lock(); | ||
| 249 | try { | ||
| 250 | // make sure the RenderQueue keeps a hard reference to the | ||
| 251 | // source (sysmem) SurfaceData to prevent it from being | ||
| 252 | // disposed while the operation is processed on the QFT | ||
| 253 | rq.addReference(srcData); | ||
| 254 | |||
| 255 | OGLSurfaceData oglDst = (OGLSurfaceData)dstData; | ||
| 256 | if (texture) { | ||
| 257 | // make sure we have a current context before uploading | ||
| 258 | // the sysmem data to the texture object | ||
| 259 | OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig(); | ||
| 260 | OGLContext.setScratchSurface(gc); | ||
| 261 | } else { | ||
| 262 | OGLContext.validateContext(oglDst, oglDst, | ||
| 263 | clip, comp, xform, null, null, | ||
| 264 | ctxflags); | ||
| 265 | } | ||
| 266 | |||
| 267 | int packedParams = createPackedParams(false, texture, | ||
| 268 | false, xform != null, | ||
| 269 | hint, srctype); | ||
| 270 | enqueueBlit(rq, srcData, dstData, | ||
| 271 | packedParams, | ||
| 272 | sx1, sy1, sx2, sy2, | ||
| 273 | dx1, dy1, dx2, dy2); | ||
| 274 | |||
| 275 | // always flush immediately, since we (currently) have no means | ||
| 276 | // of tracking changes to the system memory surface | ||
| 277 | rq.flushNow(); | ||
| 278 | } finally { | ||
| 279 | rq.unlock(); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | /** | ||
| 284 | * Note: The srcImg and biop parameters are only used when invoked | ||
| 285 | * from the OGLBufImgOps.renderImageWithOp() method; in all other cases, | ||
| 286 | * this method can be called with null values for those two parameters, | ||
| 287 | * and they will be effectively ignored. | ||
| 288 | */ | ||
| 289 | static void IsoBlit(SurfaceData srcData, SurfaceData dstData, | ||
| 290 | BufferedImage srcImg, BufferedImageOp biop, | ||
| 291 | Composite comp, Region clip, | ||
| 292 | AffineTransform xform, int hint, | ||
| 293 | int sx1, int sy1, | ||
| 294 | int sx2, int sy2, | ||
| 295 | double dx1, double dy1, | ||
| 296 | double dx2, double dy2, | ||
| 297 | boolean texture) | ||
| 298 | { | ||
| 299 | int ctxflags = 0; | ||
| 300 | if (srcData.getTransparency() == Transparency.OPAQUE) { | ||
| 301 | ctxflags |= OGLContext.SRC_IS_OPAQUE; | ||
| 302 | } | ||
| 303 | |||
| 304 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 305 | rq.lock(); | ||
| 306 | try { | ||
| 307 | OGLSurfaceData oglSrc = (OGLSurfaceData)srcData; | ||
| 308 | OGLSurfaceData oglDst = (OGLSurfaceData)dstData; | ||
| 309 | int srctype = oglSrc.getType(); | ||
| 310 | boolean rtt; | ||
| 311 | OGLSurfaceData srcCtxData; | ||
| 312 | if (srctype == OGLSurfaceData.TEXTURE) { | ||
| 313 | // the source is a regular texture object; we substitute | ||
| 314 | // the destination surface for the purposes of making a | ||
| 315 | // context current | ||
| 316 | rtt = false; | ||
| 317 | srcCtxData = oglDst; | ||
| 318 | } else { | ||
| 319 | // the source is a pbuffer, backbuffer, or render-to-texture | ||
| 320 | // surface; we set rtt to true to differentiate this kind | ||
| 321 | // of surface from a regular texture object | ||
| 322 | rtt = true; | ||
| 323 | if (srctype == OGLSurfaceData.FBOBJECT) { | ||
| 324 | srcCtxData = oglDst; | ||
| 325 | } else { | ||
| 326 | srcCtxData = oglSrc; | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | OGLContext.validateContext(srcCtxData, oglDst, | ||
| 331 | clip, comp, xform, null, null, | ||
| 332 | ctxflags); | ||
| 333 | |||
| 334 | if (biop != null) { | ||
| 335 | OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop); | ||
| 336 | } | ||
| 337 | |||
| 338 | int packedParams = createPackedParams(true, texture, | ||
| 339 | rtt, xform != null, | ||
| 340 | hint, 0 /*unused*/); | ||
| 341 | enqueueBlit(rq, srcData, dstData, | ||
| 342 | packedParams, | ||
| 343 | sx1, sy1, sx2, sy2, | ||
| 344 | dx1, dy1, dx2, dy2); | ||
| 345 | |||
| 346 | if (biop != null) { | ||
| 347 | OGLBufImgOps.disableBufImgOp(rq, biop); | ||
| 348 | } | ||
| 349 | |||
| 350 | if (rtt && (oglDst.getType() == OGLSurfaceData.WINDOW)) { | ||
| 351 | // we only have to flush immediately when copying from a | ||
| 352 | // (non-texture) surface to the screen; otherwise Swing apps | ||
| 353 | // might appear unresponsive until the auto-flush completes | ||
| 354 | rq.flushNow(); | ||
| 355 | } | ||
| 356 | } finally { | ||
| 357 | rq.unlock(); | ||
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | class OGLSurfaceToSurfaceBlit extends Blit { | ||
| 363 | |||
| 364 | OGLSurfaceToSurfaceBlit() { | ||
| 365 | super(OGLSurfaceData.OpenGLSurface, | ||
| 366 | CompositeType.AnyAlpha, | ||
| 367 | OGLSurfaceData.OpenGLSurface); | ||
| 368 | } | ||
| 369 | |||
| 370 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 371 | Composite comp, Region clip, | ||
| 372 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 373 | { | ||
| 374 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 375 | null, null, | ||
| 376 | comp, clip, null, | ||
| 377 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 378 | sx, sy, sx+w, sy+h, | ||
| 379 | dx, dy, dx+w, dy+h, | ||
| 380 | false); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | |||
| 384 | class OGLSurfaceToSurfaceScale extends ScaledBlit { | ||
| 385 | |||
| 386 | OGLSurfaceToSurfaceScale() { | ||
| 387 | super(OGLSurfaceData.OpenGLSurface, | ||
| 388 | CompositeType.AnyAlpha, | ||
| 389 | OGLSurfaceData.OpenGLSurface); | ||
| 390 | } | ||
| 391 | |||
| 392 | public void Scale(SurfaceData src, SurfaceData dst, | ||
| 393 | Composite comp, Region clip, | ||
| 394 | int sx1, int sy1, | ||
| 395 | int sx2, int sy2, | ||
| 396 | double dx1, double dy1, | ||
| 397 | double dx2, double dy2) | ||
| 398 | { | ||
| 399 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 400 | null, null, | ||
| 401 | comp, clip, null, | ||
| 402 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 403 | sx1, sy1, sx2, sy2, | ||
| 404 | dx1, dy1, dx2, dy2, | ||
| 405 | false); | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | class OGLSurfaceToSurfaceTransform extends TransformBlit { | ||
| 410 | |||
| 411 | OGLSurfaceToSurfaceTransform() { | ||
| 412 | super(OGLSurfaceData.OpenGLSurface, | ||
| 413 | CompositeType.AnyAlpha, | ||
| 414 | OGLSurfaceData.OpenGLSurface); | ||
| 415 | } | ||
| 416 | |||
| 417 | public void Transform(SurfaceData src, SurfaceData dst, | ||
| 418 | Composite comp, Region clip, | ||
| 419 | AffineTransform at, int hint, | ||
| 420 | int sx, int sy, int dx, int dy, | ||
| 421 | int w, int h) | ||
| 422 | { | ||
| 423 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 424 | null, null, | ||
| 425 | comp, clip, at, hint, | ||
| 426 | sx, sy, sx+w, sy+h, | ||
| 427 | dx, dy, dx+w, dy+h, | ||
| 428 | false); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | class OGLRTTSurfaceToSurfaceBlit extends Blit { | ||
| 433 | |||
| 434 | OGLRTTSurfaceToSurfaceBlit() { | ||
| 435 | super(OGLSurfaceData.OpenGLSurfaceRTT, | ||
| 436 | CompositeType.AnyAlpha, | ||
| 437 | OGLSurfaceData.OpenGLSurface); | ||
| 438 | } | ||
| 439 | |||
| 440 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 441 | Composite comp, Region clip, | ||
| 442 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 443 | { | ||
| 444 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 445 | null, null, | ||
| 446 | comp, clip, null, | ||
| 447 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 448 | sx, sy, sx+w, sy+h, | ||
| 449 | dx, dy, dx+w, dy+h, | ||
| 450 | true); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | class OGLRTTSurfaceToSurfaceScale extends ScaledBlit { | ||
| 455 | |||
| 456 | OGLRTTSurfaceToSurfaceScale() { | ||
| 457 | super(OGLSurfaceData.OpenGLSurfaceRTT, | ||
| 458 | CompositeType.AnyAlpha, | ||
| 459 | OGLSurfaceData.OpenGLSurface); | ||
| 460 | } | ||
| 461 | |||
| 462 | public void Scale(SurfaceData src, SurfaceData dst, | ||
| 463 | Composite comp, Region clip, | ||
| 464 | int sx1, int sy1, | ||
| 465 | int sx2, int sy2, | ||
| 466 | double dx1, double dy1, | ||
| 467 | double dx2, double dy2) | ||
| 468 | { | ||
| 469 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 470 | null, null, | ||
| 471 | comp, clip, null, | ||
| 472 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 473 | sx1, sy1, sx2, sy2, | ||
| 474 | dx1, dy1, dx2, dy2, | ||
| 475 | true); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | class OGLRTTSurfaceToSurfaceTransform extends TransformBlit { | ||
| 480 | |||
| 481 | OGLRTTSurfaceToSurfaceTransform() { | ||
| 482 | super(OGLSurfaceData.OpenGLSurfaceRTT, | ||
| 483 | CompositeType.AnyAlpha, | ||
| 484 | OGLSurfaceData.OpenGLSurface); | ||
| 485 | } | ||
| 486 | |||
| 487 | public void Transform(SurfaceData src, SurfaceData dst, | ||
| 488 | Composite comp, Region clip, | ||
| 489 | AffineTransform at, int hint, | ||
| 490 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 491 | { | ||
| 492 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 493 | null, null, | ||
| 494 | comp, clip, at, hint, | ||
| 495 | sx, sy, sx+w, sy+h, | ||
| 496 | dx, dy, dx+w, dy+h, | ||
| 497 | true); | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | class OGLSurfaceToSwBlit extends Blit { | ||
| 502 | |||
| 503 | private int typeval; | ||
| 504 | |||
| 505 | // REMIND: destination will actually be opaque/premultiplied... | ||
| 506 | OGLSurfaceToSwBlit(SurfaceType dstType, int typeval) { | ||
| 507 | super(OGLSurfaceData.OpenGLSurface, | ||
| 508 | CompositeType.SrcNoEa, | ||
| 509 | dstType); | ||
| 510 | this.typeval = typeval; | ||
| 511 | } | ||
| 512 | |||
| 513 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 514 | Composite comp, Region clip, | ||
| 515 | int sx, int sy, int dx, int dy, | ||
| 516 | int w, int h) | ||
| 517 | { | ||
| 518 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 519 | rq.lock(); | ||
| 520 | try { | ||
| 521 | // make sure the RenderQueue keeps a hard reference to the | ||
| 522 | // destination (sysmem) SurfaceData to prevent it from being | ||
| 523 | // disposed while the operation is processed on the QFT | ||
| 524 | rq.addReference(dst); | ||
| 525 | |||
| 526 | RenderBuffer buf = rq.getBuffer(); | ||
| 527 | OGLContext.validateContext((OGLSurfaceData)src); | ||
| 528 | |||
| 529 | rq.ensureCapacityAndAlignment(48, 32); | ||
| 530 | buf.putInt(SURFACE_TO_SW_BLIT); | ||
| 531 | buf.putInt(sx).putInt(sy); | ||
| 532 | buf.putInt(dx).putInt(dy); | ||
| 533 | buf.putInt(w).putInt(h); | ||
| 534 | buf.putInt(typeval); | ||
| 535 | buf.putLong(src.getNativeOps()); | ||
| 536 | buf.putLong(dst.getNativeOps()); | ||
| 537 | |||
| 538 | // always flush immediately | ||
| 539 | rq.flushNow(); | ||
| 540 | } finally { | ||
| 541 | rq.unlock(); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 546 | class OGLSwToSurfaceBlit extends Blit { | ||
| 547 | |||
| 548 | private int typeval; | ||
| 549 | |||
| 550 | OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) { | ||
| 551 | super(srcType, | ||
| 552 | CompositeType.AnyAlpha, | ||
| 553 | OGLSurfaceData.OpenGLSurface); | ||
| 554 | this.typeval = typeval; | ||
| 555 | } | ||
| 556 | |||
| 557 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 558 | Composite comp, Region clip, | ||
| 559 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 560 | { | ||
| 561 | OGLBlitLoops.Blit(src, dst, | ||
| 562 | comp, clip, null, | ||
| 563 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 564 | sx, sy, sx+w, sy+h, | ||
| 565 | dx, dy, dx+w, dy+h, | ||
| 566 | typeval, false); | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | class OGLSwToSurfaceScale extends ScaledBlit { | ||
| 571 | |||
| 572 | private int typeval; | ||
| 573 | |||
| 574 | OGLSwToSurfaceScale(SurfaceType srcType, int typeval) { | ||
| 575 | super(srcType, | ||
| 576 | CompositeType.AnyAlpha, | ||
| 577 | OGLSurfaceData.OpenGLSurface); | ||
| 578 | this.typeval = typeval; | ||
| 579 | } | ||
| 580 | |||
| 581 | public void Scale(SurfaceData src, SurfaceData dst, | ||
| 582 | Composite comp, Region clip, | ||
| 583 | int sx1, int sy1, | ||
| 584 | int sx2, int sy2, | ||
| 585 | double dx1, double dy1, | ||
| 586 | double dx2, double dy2) | ||
| 587 | { | ||
| 588 | OGLBlitLoops.Blit(src, dst, | ||
| 589 | comp, clip, null, | ||
| 590 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 591 | sx1, sy1, sx2, sy2, | ||
| 592 | dx1, dy1, dx2, dy2, | ||
| 593 | typeval, false); | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | class OGLSwToSurfaceTransform extends TransformBlit { | ||
| 598 | |||
| 599 | private int typeval; | ||
| 600 | |||
| 601 | OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) { | ||
| 602 | super(srcType, | ||
| 603 | CompositeType.AnyAlpha, | ||
| 604 | OGLSurfaceData.OpenGLSurface); | ||
| 605 | this.typeval = typeval; | ||
| 606 | } | ||
| 607 | |||
| 608 | public void Transform(SurfaceData src, SurfaceData dst, | ||
| 609 | Composite comp, Region clip, | ||
| 610 | AffineTransform at, int hint, | ||
| 611 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 612 | { | ||
| 613 | OGLBlitLoops.Blit(src, dst, | ||
| 614 | comp, clip, at, hint, | ||
| 615 | sx, sy, sx+w, sy+h, | ||
| 616 | dx, dy, dx+w, dy+h, | ||
| 617 | typeval, false); | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | class OGLSwToTextureBlit extends Blit { | ||
| 622 | |||
| 623 | private int typeval; | ||
| 624 | |||
| 625 | OGLSwToTextureBlit(SurfaceType srcType, int typeval) { | ||
| 626 | super(srcType, | ||
| 627 | CompositeType.SrcNoEa, | ||
| 628 | OGLSurfaceData.OpenGLTexture); | ||
| 629 | this.typeval = typeval; | ||
| 630 | } | ||
| 631 | |||
| 632 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 633 | Composite comp, Region clip, | ||
| 634 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 635 | { | ||
| 636 | OGLBlitLoops.Blit(src, dst, | ||
| 637 | comp, clip, null, | ||
| 638 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 639 | sx, sy, sx+w, sy+h, | ||
| 640 | dx, dy, dx+w, dy+h, | ||
| 641 | typeval, true); | ||
| 642 | } | ||
| 643 | } | ||
| 644 | |||
| 645 | class OGLTextureToSurfaceBlit extends Blit { | ||
| 646 | |||
| 647 | OGLTextureToSurfaceBlit() { | ||
| 648 | super(OGLSurfaceData.OpenGLTexture, | ||
| 649 | CompositeType.AnyAlpha, | ||
| 650 | OGLSurfaceData.OpenGLSurface); | ||
| 651 | } | ||
| 652 | |||
| 653 | public void Blit(SurfaceData src, SurfaceData dst, | ||
| 654 | Composite comp, Region clip, | ||
| 655 | int sx, int sy, int dx, int dy, int w, int h) | ||
| 656 | { | ||
| 657 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 658 | null, null, | ||
| 659 | comp, clip, null, | ||
| 660 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 661 | sx, sy, sx+w, sy+h, | ||
| 662 | dx, dy, dx+w, dy+h, | ||
| 663 | true); | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | class OGLTextureToSurfaceScale extends ScaledBlit { | ||
| 668 | |||
| 669 | OGLTextureToSurfaceScale() { | ||
| 670 | super(OGLSurfaceData.OpenGLTexture, | ||
| 671 | CompositeType.AnyAlpha, | ||
| 672 | OGLSurfaceData.OpenGLSurface); | ||
| 673 | } | ||
| 674 | |||
| 675 | public void Scale(SurfaceData src, SurfaceData dst, | ||
| 676 | Composite comp, Region clip, | ||
| 677 | int sx1, int sy1, | ||
| 678 | int sx2, int sy2, | ||
| 679 | double dx1, double dy1, | ||
| 680 | double dx2, double dy2) | ||
| 681 | { | ||
| 682 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 683 | null, null, | ||
| 684 | comp, clip, null, | ||
| 685 | AffineTransformOp.TYPE_NEAREST_NEIGHBOR, | ||
| 686 | sx1, sy1, sx2, sy2, | ||
| 687 | dx1, dy1, dx2, dy2, | ||
| 688 | true); | ||
| 689 | } | ||
| 690 | } | ||
| 691 | |||
| 692 | class OGLTextureToSurfaceTransform extends TransformBlit { | ||
| 693 | |||
| 694 | OGLTextureToSurfaceTransform() { | ||
| 695 | super(OGLSurfaceData.OpenGLTexture, | ||
| 696 | CompositeType.AnyAlpha, | ||
| 697 | OGLSurfaceData.OpenGLSurface); | ||
| 698 | } | ||
| 699 | |||
| 700 | public void Transform(SurfaceData src, SurfaceData dst, | ||
| 701 | Composite comp, Region clip, | ||
| 702 | AffineTransform at, int hint, | ||
| 703 | int sx, int sy, int dx, int dy, | ||
| 704 | int w, int h) | ||
| 705 | { | ||
| 706 | OGLBlitLoops.IsoBlit(src, dst, | ||
| 707 | null, null, | ||
| 708 | comp, clip, at, hint, | ||
| 709 | sx, sy, sx+w, sy+h, | ||
| 710 | dx, dy, dx+w, dy+h, | ||
| 711 | true); | ||
| 712 | } | ||
| 713 | } | ||
| 714 | |||
| 715 | /** | ||
| 716 | * This general Blit implemenation converts any source surface to an | ||
| 717 | * intermediate IntArgbPre surface, and then uses the more specific | ||
| 718 | * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate | ||
| 719 | * (premultiplied) surface down to OpenGL. | ||
| 720 | */ | ||
| 721 | class OGLGeneralBlit extends Blit { | ||
| 722 | |||
| 723 | private Blit performop; | ||
| 724 | private WeakReference srcTmp; | ||
| 725 | |||
| 726 | OGLGeneralBlit(SurfaceType dstType, | ||
| 727 | CompositeType compType, | ||
| 728 | Blit performop) | ||
| 729 | { | ||
| 730 | super(SurfaceType.Any, compType, dstType); | ||
| 731 | this.performop = performop; | ||
| 732 | } | ||
| 733 | |||
| 734 | public synchronized void Blit(SurfaceData src, SurfaceData dst, | ||
| 735 | Composite comp, Region clip, | ||
| 736 | int sx, int sy, int dx, int dy, | ||
| 737 | int w, int h) | ||
| 738 | { | ||
| 739 | Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), | ||
| 740 | CompositeType.SrcNoEa, | ||
| 741 | SurfaceType.IntArgbPre); | ||
| 742 | |||
| 743 | SurfaceData cachedSrc = null; | ||
| 744 | if (srcTmp != null) { | ||
| 745 | // use cached intermediate surface, if available | ||
| 746 | cachedSrc = (SurfaceData)srcTmp.get(); | ||
| 747 | } | ||
| 748 | |||
| 749 | // convert source to IntArgbPre | ||
| 750 | src = convertFrom(convertsrc, src, sx, sy, w, h, | ||
| 751 | cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE); | ||
| 752 | |||
| 753 | // copy IntArgbPre intermediate surface to OpenGL surface | ||
| 754 | performop.Blit(src, dst, comp, clip, | ||
| 755 | 0, 0, dx, dy, w, h); | ||
| 756 | |||
| 757 | if (src != cachedSrc) { | ||
| 758 | // cache the intermediate surface | ||
| 759 | srcTmp = new WeakReference(src); | ||
| 760 | } | ||
| 761 | } | ||
| 762 | } | ||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2007, 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.image.AffineTransformOp; | ||
| 29 | import java.awt.image.BufferedImage; | ||
| 30 | import java.awt.image.BufferedImageOp; | ||
| 31 | import java.awt.image.ConvolveOp; | ||
| 32 | import java.awt.image.LookupOp; | ||
| 33 | import java.awt.image.RescaleOp; | ||
| 34 | import sun.java2d.SunGraphics2D; | ||
| 35 | import sun.java2d.SurfaceData; | ||
| 36 | import sun.java2d.loops.CompositeType; | ||
| 37 | import sun.java2d.pipe.BufferedBufImgOps; | ||
| 38 | import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; | ||
| 39 | |||
| 40 | class OGLBufImgOps extends BufferedBufImgOps { | ||
| 41 | |||
| 42 | /** | ||
| 43 | * This method is called from OGLDrawImage.transformImage() only. It | ||
| 44 | * validates the provided BufferedImageOp to determine whether the op | ||
| 45 | * is one that can be accelerated by the OGL pipeline. If the operation | ||
| 46 | * cannot be completed for any reason, this method returns false; | ||
| 47 | * otherwise, the given BufferedImage is rendered to the destination | ||
| 48 | * using the provided BufferedImageOp and this method returns true. | ||
| 49 | */ | ||
| 50 | static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img, | ||
| 51 | BufferedImageOp biop, int x, int y) | ||
| 52 | { | ||
| 53 | // Validate the provided BufferedImage (make sure it is one that | ||
| 54 | // is supported, and that its properties are acceleratable) | ||
| 55 | if (biop instanceof ConvolveOp) { | ||
| 56 | if (!isConvolveOpValid((ConvolveOp)biop)) { | ||
| 57 | return false; | ||
| 58 | } | ||
| 59 | } else if (biop instanceof RescaleOp) { | ||
| 60 | if (!isRescaleOpValid((RescaleOp)biop, img)) { | ||
| 61 | return false; | ||
| 62 | } | ||
| 63 | } else if (biop instanceof LookupOp) { | ||
| 64 | if (!isLookupOpValid((LookupOp)biop, img)) { | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | } else { | ||
| 68 | // No acceleration for other BufferedImageOps (yet) | ||
| 69 | return false; | ||
| 70 | } | ||
| 71 | |||
| 72 | SurfaceData dstData = sg.surfaceData; | ||
| 73 | if (!(dstData instanceof OGLSurfaceData) || | ||
| 74 | (sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) || | ||
| 75 | (sg.compositeState > SunGraphics2D.COMP_ALPHA)) | ||
| 76 | { | ||
| 77 | return false; | ||
| 78 | } | ||
| 79 | |||
| 80 | SurfaceData srcData = | ||
| 81 | dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT, | ||
| 82 | CompositeType.SrcOver, null); | ||
| 83 | if (!(srcData instanceof OGLSurfaceData)) { | ||
| 84 | // REMIND: this hack tries to ensure that we have a cached texture | ||
| 85 | srcData = | ||
| 86 | dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT, | ||
| 87 | CompositeType.SrcOver, null); | ||
| 88 | if (!(srcData instanceof OGLSurfaceData)) { | ||
| 89 | return false; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | // Verify that the source surface is actually a texture and | ||
| 94 | // that the operation is supported | ||
| 95 | OGLSurfaceData oglSrc = (OGLSurfaceData)srcData; | ||
| 96 | OGLGraphicsConfig gc = oglSrc.getOGLGraphicsConfig(); | ||
| 97 | if (oglSrc.getType() != OGLSurfaceData.TEXTURE || | ||
| 98 | !gc.isCapPresent(CAPS_EXT_BIOP_SHADER)) | ||
| 99 | { | ||
| 100 | return false; | ||
| 101 | } | ||
| 102 | |||
| 103 | int sw = img.getWidth(); | ||
| 104 | int sh = img.getHeight(); | ||
| 105 | OGLBlitLoops.IsoBlit(srcData, dstData, | ||
| 106 | img, biop, | ||
| 107 | sg.composite, sg.getCompClip(), | ||
| 108 | sg.transform, sg.interpolationType, | ||
| 109 | 0, 0, sw, sh, | ||
| 110 | x, y, x+sw, y+sh, | ||
| 111 | true); | ||
| 112 | |||
| 113 | return true; | ||
| 114 | } | ||
| 115 | } | ||
| @@ -0,0 +1,220 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2004, 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 sun.java2d.pipe.BufferedContext; | ||
| 29 | import sun.java2d.pipe.RenderBuffer; | ||
| 30 | import sun.java2d.pipe.RenderQueue; | ||
| 31 | import sun.java2d.pipe.hw.ContextCapabilities; | ||
| 32 | import static sun.java2d.pipe.BufferedOpCodes.*; | ||
| 33 | import static sun.java2d.pipe.hw.ContextCapabilities.*; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Note that the RenderQueue lock must be acquired before calling any of | ||
| 37 | * the methods in this class. | ||
| 38 | */ | ||
| 39 | public class OGLContext extends BufferedContext { | ||
| 40 | |||
| 41 | private final OGLGraphicsConfig config; | ||
| 42 | |||
| 43 | OGLContext(RenderQueue rq, OGLGraphicsConfig config) { | ||
| 44 | super(rq); | ||
| 45 | this.config = config; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Convenience method that delegates to setScratchSurface() below. | ||
| 50 | */ | ||
| 51 | static void setScratchSurface(OGLGraphicsConfig gc) { | ||
| 52 | setScratchSurface(gc.getNativeConfigInfo()); | ||
| 53 | } | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Makes the given GraphicsConfig's context current to its associated | ||
| 57 | * "scratch surface". Each GraphicsConfig maintains a native context | ||
| 58 | * (GLXContext on Unix, HGLRC on Windows) as well as a native pbuffer | ||
| 59 | * known as the "scratch surface". By making the context current to the | ||
| 60 | * scratch surface, we are assured that we have a current context for | ||
| 61 | * the relevant GraphicsConfig, and can therefore perform operations | ||
| 62 | * depending on the capabilities of that GraphicsConfig. For example, | ||
| 63 | * if the GraphicsConfig supports the GL_ARB_texture_non_power_of_two | ||
| 64 | * extension, then we should be able to make a non-pow2 texture for this | ||
| 65 | * GraphicsConfig once we make the context current to the scratch surface. | ||
| 66 | * | ||
| 67 | * This method should be used for operations with an OpenGL texture | ||
| 68 | * as the destination surface (e.g. a sw->texture blit loop), or in those | ||
| 69 | * situations where we may not otherwise have a current context (e.g. | ||
| 70 | * when disposing a texture-based surface). | ||
| 71 | */ | ||
| 72 | static void setScratchSurface(long pConfigInfo) { | ||
| 73 | // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread(); | ||
| 74 | |||
| 75 | // invalidate the current context | ||
| 76 | currentContext = null; | ||
| 77 | |||
| 78 | // set the scratch context | ||
| 79 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 80 | RenderBuffer buf = rq.getBuffer(); | ||
| 81 | rq.ensureCapacityAndAlignment(12, 4); | ||
| 82 | buf.putInt(SET_SCRATCH_SURFACE); | ||
| 83 | buf.putLong(pConfigInfo); | ||
| 84 | } | ||
| 85 | |||
| 86 | /** | ||
| 87 | * Invalidates the currentContext field to ensure that we properly | ||
| 88 | * revalidate the OGLContext (make it current, etc.) next time through | ||
| 89 | * the validate() method. This is typically invoked from methods | ||
| 90 | * that affect the current context state (e.g. disposing a context or | ||
| 91 | * surface). | ||
| 92 | */ | ||
| 93 | static void invalidateCurrentContext() { | ||
| 94 | // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread(); | ||
| 95 | |||
| 96 | // invalidate the current Java-level context so that we | ||
| 97 | // revalidate everything the next time around | ||
| 98 | if (currentContext != null) { | ||
| 99 | currentContext.invalidateContext(); | ||
| 100 | currentContext = null; | ||
| 101 | } | ||
| 102 | |||
| 103 | // invalidate the context reference at the native level, and | ||
| 104 | // then flush the queue so that we have no pending operations | ||
| 105 | // dependent on the current context | ||
| 106 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 107 | rq.ensureCapacity(4); | ||
| 108 | rq.getBuffer().putInt(INVALIDATE_CONTEXT); | ||
| 109 | rq.flushNow(); | ||
| 110 | } | ||
| 111 | |||
| 112 | public RenderQueue getRenderQueue() { | ||
| 113 | return OGLRenderQueue.getInstance(); | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Returns a string representing adapter id (vendor, renderer, version). | ||
| 118 | * Must be called on the rendering thread. | ||
| 119 | * | ||
| 120 | * @return an id string for the adapter | ||
| 121 | */ | ||
| 122 | static final native String getOGLIdString(); | ||
| 123 | |||
| 124 | @Override | ||
| 125 | public void saveState() { | ||
| 126 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 127 | |||
| 128 | // reset all attributes of this and current contexts | ||
| 129 | invalidateContext(); | ||
| 130 | invalidateCurrentContext(); | ||
| 131 | |||
| 132 | setScratchSurface(config); | ||
| 133 | |||
| 134 | // save the state on the native level | ||
| 135 | rq.ensureCapacity(4); | ||
| 136 | buf.putInt(SAVE_STATE); | ||
| 137 | rq.flushNow(); | ||
| 138 | } | ||
| 139 | |||
| 140 | @Override | ||
| 141 | public void restoreState() { | ||
| 142 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 143 | |||
| 144 | // reset all attributes of this and current contexts | ||
| 145 | invalidateContext(); | ||
| 146 | invalidateCurrentContext(); | ||
| 147 | |||
| 148 | setScratchSurface(config); | ||
| 149 | |||
| 150 | // restore the state on the native level | ||
| 151 | rq.ensureCapacity(4); | ||
| 152 | buf.putInt(RESTORE_STATE); | ||
| 153 | rq.flushNow(); | ||
| 154 | } | ||
| 155 | |||
| 156 | static class OGLContextCaps extends ContextCapabilities { | ||
| 157 | /** | ||
| 158 | * Indicates the presence of the GL_EXT_framebuffer_object extension. | ||
| 159 | * This cap will only be set if the fbobject system property has been | ||
| 160 | * enabled and we are able to create an FBO with depth buffer. | ||
| 161 | */ | ||
| 162 | static final int CAPS_EXT_FBOBJECT = | ||
| 163 | (CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE); | ||
| 164 | /** Indicates that the context supports a stored alpha channel. */ | ||
| 165 | static final int CAPS_STORED_ALPHA = CAPS_RT_PLAIN_ALPHA; | ||
| 166 | /** Indicates that the context is doublebuffered. */ | ||
| 167 | static final int CAPS_DOUBLEBUFFERED = (FIRST_PRIVATE_CAP << 0); | ||
| 168 | /** | ||
| 169 | * Indicates the presence of the GL_ARB_fragment_shader extension. | ||
| 170 | * This cap will only be set if the lcdshader system property has been | ||
| 171 | * enabled and the hardware supports the minimum number of texture units | ||
| 172 | */ | ||
| 173 | static final int CAPS_EXT_LCD_SHADER = (FIRST_PRIVATE_CAP << 1); | ||
| 174 | /** | ||
| 175 | * Indicates the presence of the GL_ARB_fragment_shader extension. | ||
| 176 | * This cap will only be set if the biopshader system property has been | ||
| 177 | * enabled and the hardware meets our minimum requirements. | ||
| 178 | */ | ||
| 179 | static final int CAPS_EXT_BIOP_SHADER = (FIRST_PRIVATE_CAP << 2); | ||
| 180 | /** | ||
| 181 | * Indicates the presence of the GL_ARB_fragment_shader extension. | ||
| 182 | * This cap will only be set if the gradshader system property has been | ||
| 183 | * enabled and the hardware meets our minimum requirements. | ||
| 184 | */ | ||
| 185 | static final int CAPS_EXT_GRAD_SHADER = (FIRST_PRIVATE_CAP << 3); | ||
| 186 | /** Indicates the presence of the GL_ARB_texture_rectangle extension. */ | ||
| 187 | static final int CAPS_EXT_TEXRECT = (FIRST_PRIVATE_CAP << 4); | ||
| 188 | |||
| 189 | OGLContextCaps(int caps, String adapterId) { | ||
| 190 | super(caps, adapterId); | ||
| 191 | } | ||
| 192 | |||
| 193 | @Override | ||
| 194 | public String toString() { | ||
| 195 | StringBuffer buf = new StringBuffer(super.toString()); | ||
| 196 | if ((caps & CAPS_EXT_FBOBJECT) != 0) { | ||
| 197 | buf.append("CAPS_EXT_FBOBJECT|"); | ||
| 198 | } | ||
| 199 | if ((caps & CAPS_STORED_ALPHA) != 0) { | ||
| 200 | buf.append("CAPS_STORED_ALPHA|"); | ||
| 201 | } | ||
| 202 | if ((caps & CAPS_DOUBLEBUFFERED) != 0) { | ||
| 203 | buf.append("CAPS_DOUBLEBUFFERED|"); | ||
| 204 | } | ||
| 205 | if ((caps & CAPS_EXT_LCD_SHADER) != 0) { | ||
| 206 | buf.append("CAPS_EXT_LCD_SHADER|"); | ||
| 207 | } | ||
| 208 | if ((caps & CAPS_EXT_BIOP_SHADER) != 0) { | ||
| 209 | buf.append("CAPS_BIOP_SHADER|"); | ||
| 210 | } | ||
| 211 | if ((caps & CAPS_EXT_GRAD_SHADER) != 0) { | ||
| 212 | buf.append("CAPS_EXT_GRAD_SHADER|"); | ||
| 213 | } | ||
| 214 | if ((caps & CAPS_EXT_TEXRECT) != 0) { | ||
| 215 | buf.append("CAPS_EXT_TEXRECT|"); | ||
| 216 | } | ||
| 217 | return buf.toString(); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | } | ||
| @@ -0,0 +1,113 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2007, 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.Color; | ||
| 29 | import java.awt.Image; | ||
| 30 | import java.awt.geom.AffineTransform; | ||
| 31 | import java.awt.image.AffineTransformOp; | ||
| 32 | import java.awt.image.BufferedImage; | ||
| 33 | import java.awt.image.BufferedImageOp; | ||
| 34 | import sun.java2d.SunGraphics2D; | ||
| 35 | import sun.java2d.SurfaceData; | ||
| 36 | import sun.java2d.loops.SurfaceType; | ||
| 37 | import sun.java2d.loops.TransformBlit; | ||
| 38 | import sun.java2d.pipe.DrawImage; | ||
| 39 | |||
| 40 | public class OGLDrawImage extends DrawImage { | ||
| 41 | |||
| 42 | @Override | ||
| 43 | protected void renderImageXform(SunGraphics2D sg, Image img, | ||
| 44 | AffineTransform tx, int interpType, | ||
| 45 | int sx1, int sy1, int sx2, int sy2, | ||
| 46 | Color bgColor) | ||
| 47 | { | ||
| 48 | // punt to the MediaLib-based transformImage() in the superclass if: | ||
| 49 | // - bicubic interpolation is specified | ||
| 50 | // - a background color is specified and will be used | ||
| 51 | // - the source surface is neither a texture nor render-to-texture | ||
| 52 | // surface, and a non-default interpolation hint is specified | ||
| 53 | // (we can only control the filtering for texture->surface | ||
| 54 | // copies) | ||
| 55 | // REMIND: we should tweak the sw->texture->surface | ||
| 56 | // transform case to handle filtering appropriately | ||
| 57 | // (see 4841762)... | ||
| 58 | // - an appropriate TransformBlit primitive could not be found | ||
| 59 | if (interpType != AffineTransformOp.TYPE_BICUBIC) { | ||
| 60 | SurfaceData dstData = sg.surfaceData; | ||
| 61 | SurfaceData srcData = | ||
| 62 | dstData.getSourceSurfaceData(img, | ||
| 63 | sg.TRANSFORM_GENERIC, | ||
| 64 | sg.imageComp, | ||
| 65 | bgColor); | ||
| 66 | |||
| 67 | if (srcData != null && | ||
| 68 | !isBgOperation(srcData, bgColor) && | ||
| 69 | (srcData.getSurfaceType() == OGLSurfaceData.OpenGLTexture || | ||
| 70 | srcData.getSurfaceType() == OGLSurfaceData.OpenGLSurfaceRTT || | ||
| 71 | interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR)) | ||
| 72 | { | ||
| 73 | SurfaceType srcType = srcData.getSurfaceType(); | ||
| 74 | SurfaceType dstType = dstData.getSurfaceType(); | ||
| 75 | TransformBlit blit = TransformBlit.getFromCache(srcType, | ||
| 76 | sg.imageComp, | ||
| 77 | dstType); | ||
| 78 | |||
| 79 | if (blit != null) { | ||
| 80 | blit.Transform(srcData, dstData, | ||
| 81 | sg.composite, sg.getCompClip(), | ||
| 82 | tx, interpType, | ||
| 83 | sx1, sy1, 0, 0, sx2-sx1, sy2-sy1); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | super.renderImageXform(sg, img, tx, interpType, | ||
| 90 | sx1, sy1, sx2, sy2, bgColor); | ||
| 91 | } | ||
| 92 | |||
| 93 | @Override | ||
| 94 | public void transformImage(SunGraphics2D sg, BufferedImage img, | ||
| 95 | BufferedImageOp op, int x, int y) | ||
| 96 | { | ||
| 97 | if (op != null) { | ||
| 98 | if (op instanceof AffineTransformOp) { | ||
| 99 | AffineTransformOp atop = (AffineTransformOp) op; | ||
| 100 | transformImage(sg, img, x, y, | ||
| 101 | atop.getTransform(), | ||
| 102 | atop.getInterpolationType()); | ||
| 103 | return; | ||
| 104 | } else { | ||
| 105 | if (OGLBufImgOps.renderImageWithOp(sg, img, op, x, y)) { | ||
| 106 | return; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | img = op.filter(img, null); | ||
| 110 | } | ||
| 111 | copyImage(sg, img, x, y, null); | ||
| 112 | } | ||
| 113 | } | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2005, 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 sun.java2d.SurfaceData; | ||
| 29 | import sun.awt.image.SurfaceManager; | ||
| 30 | import sun.java2d.pipe.hw.AccelGraphicsConfig; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * This interface collects the methods that are provided by both | ||
| 34 | * GLXGraphicsConfig and WGLGraphicsConfig, making it easier to invoke these | ||
| 35 | * methods directly from OGLSurfaceData. | ||
| 36 | */ | ||
| 37 | interface OGLGraphicsConfig extends | ||
| 38 | AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig | ||
| 39 | { | ||
| 40 | OGLContext getContext(); | ||
| 41 | long getNativeConfigInfo(); | ||
| 42 | boolean isCapPresent(int cap); | ||
| 43 | SurfaceData createManagedSurface(int w, int h, int transparency); | ||
| 44 | } | ||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2007, 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.Composite; | ||
| 29 | import sun.java2d.SurfaceData; | ||
| 30 | import sun.java2d.loops.CompositeType; | ||
| 31 | import sun.java2d.loops.GraphicsPrimitive; | ||
| 32 | import sun.java2d.loops.GraphicsPrimitiveMgr; | ||
| 33 | import sun.java2d.loops.SurfaceType; | ||
| 34 | import sun.java2d.pipe.Region; | ||
| 35 | import sun.java2d.pipe.BufferedMaskBlit; | ||
| 36 | import static sun.java2d.loops.CompositeType.*; | ||
| 37 | import static sun.java2d.loops.SurfaceType.*; | ||
| 38 | |||
| 39 | class OGLMaskBlit extends BufferedMaskBlit { | ||
| 40 | |||
| 41 | static void register() { | ||
| 42 | GraphicsPrimitive[] primitives = { | ||
| 43 | new OGLMaskBlit(IntArgb, SrcOver), | ||
| 44 | new OGLMaskBlit(IntArgbPre, SrcOver), | ||
| 45 | new OGLMaskBlit(IntRgb, SrcOver), | ||
| 46 | new OGLMaskBlit(IntRgb, SrcNoEa), | ||
| 47 | new OGLMaskBlit(IntBgr, SrcOver), | ||
| 48 | new OGLMaskBlit(IntBgr, SrcNoEa), | ||
| 49 | }; | ||
| 50 | GraphicsPrimitiveMgr.register(primitives); | ||
| 51 | } | ||
| 52 | |||
| 53 | private OGLMaskBlit(SurfaceType srcType, | ||
| 54 | CompositeType compType) | ||
| 55 | { | ||
| 56 | super(OGLRenderQueue.getInstance(), | ||
| 57 | srcType, compType, OGLSurfaceData.OpenGLSurface); | ||
| 58 | } | ||
| 59 | |||
| 60 | @Override | ||
| 61 | protected void validateContext(SurfaceData dstData, | ||
| 62 | Composite comp, Region clip) | ||
| 63 | { | ||
| 64 | OGLSurfaceData oglDst = (OGLSurfaceData)dstData; | ||
| 65 | OGLContext.validateContext(oglDst, oglDst, | ||
| 66 | clip, comp, null, null, null, | ||
| 67 | OGLContext.NO_CONTEXT_FLAGS); | ||
| 68 | } | ||
| 69 | } | ||
| @@ -0,0 +1,75 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2007, 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.Composite; | ||
| 29 | import sun.java2d.SunGraphics2D; | ||
| 30 | import sun.java2d.loops.GraphicsPrimitive; | ||
| 31 | import sun.java2d.loops.GraphicsPrimitiveMgr; | ||
| 32 | import sun.java2d.loops.CompositeType; | ||
| 33 | import sun.java2d.loops.SurfaceType; | ||
| 34 | import sun.java2d.pipe.BufferedMaskFill; | ||
| 35 | import static sun.java2d.loops.CompositeType.*; | ||
| 36 | import static sun.java2d.loops.SurfaceType.*; | ||
| 37 | |||
| 38 | class OGLMaskFill extends BufferedMaskFill { | ||
| 39 | |||
| 40 | static void register() { | ||
| 41 | GraphicsPrimitive[] primitives = { | ||
| 42 | new OGLMaskFill(AnyColor, SrcOver), | ||
| 43 | new OGLMaskFill(OpaqueColor, SrcNoEa), | ||
| 44 | new OGLMaskFill(GradientPaint, SrcOver), | ||
| 45 | new OGLMaskFill(OpaqueGradientPaint, SrcNoEa), | ||
| 46 | new OGLMaskFill(LinearGradientPaint, SrcOver), | ||
| 47 | new OGLMaskFill(OpaqueLinearGradientPaint, SrcNoEa), | ||
| 48 | new OGLMaskFill(RadialGradientPaint, SrcOver), | ||
| 49 | new OGLMaskFill(OpaqueRadialGradientPaint, SrcNoEa), | ||
| 50 | new OGLMaskFill(TexturePaint, SrcOver), | ||
| 51 | new OGLMaskFill(OpaqueTexturePaint, SrcNoEa), | ||
| 52 | }; | ||
| 53 | GraphicsPrimitiveMgr.register(primitives); | ||
| 54 | } | ||
| 55 | |||
| 56 | protected OGLMaskFill(SurfaceType srcType, CompositeType compType) { | ||
| 57 | super(OGLRenderQueue.getInstance(), | ||
| 58 | srcType, compType, OGLSurfaceData.OpenGLSurface); | ||
| 59 | } | ||
| 60 | |||
| 61 | @Override | ||
| 62 | protected native void maskFill(int x, int y, int w, int h, | ||
| 63 | int maskoff, int maskscan, int masklen, | ||
| 64 | byte[] mask); | ||
| 65 | |||
| 66 | @Override | ||
| 67 | protected void validateContext(SunGraphics2D sg2d, | ||
| 68 | Composite comp, int ctxflags) | ||
| 69 | { | ||
| 70 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 71 | OGLContext.validateContext(dstData, dstData, | ||
| 72 | sg2d.getCompClip(), comp, | ||
| 73 | null, sg2d.paint, sg2d, ctxflags); | ||
| 74 | } | ||
| 75 | } | ||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2007, 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.GradientPaint; | ||
| 29 | import java.awt.LinearGradientPaint; | ||
| 30 | import java.awt.MultipleGradientPaint; | ||
| 31 | import java.awt.MultipleGradientPaint.ColorSpaceType; | ||
| 32 | import java.awt.MultipleGradientPaint.CycleMethod; | ||
| 33 | import java.awt.RadialGradientPaint; | ||
| 34 | import java.awt.TexturePaint; | ||
| 35 | import java.awt.image.BufferedImage; | ||
| 36 | import java.util.HashMap; | ||
| 37 | import java.util.Map; | ||
| 38 | import sun.java2d.SunGraphics2D; | ||
| 39 | import sun.java2d.SurfaceData; | ||
| 40 | import sun.java2d.loops.CompositeType; | ||
| 41 | import static sun.java2d.pipe.BufferedPaints.*; | ||
| 42 | import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; | ||
| 43 | |||
| 44 | abstract class OGLPaints { | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Holds all registered implementations, using the corresponding | ||
| 48 | * SunGraphics2D.PAINT_* constant as the hash key. | ||
| 49 | */ | ||
| 50 | private static Map<Integer, OGLPaints> impls = | ||
| 51 | new HashMap<Integer, OGLPaints>(4, 1.0f); | ||
| 52 | |||
| 53 | static { | ||
| 54 | impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient()); | ||
| 55 | impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient()); | ||
| 56 | impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient()); | ||
| 57 | impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture()); | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Attempts to locate an implementation corresponding to the paint state | ||
| 62 | * of the provided SunGraphics2D object. If no implementation can be | ||
| 63 | * found, or if the paint cannot be accelerated under the conditions | ||
| 64 | * of the SunGraphics2D, this method returns false; otherwise, returns | ||
| 65 | * true. | ||
| 66 | */ | ||
| 67 | static boolean isValid(SunGraphics2D sg2d) { | ||
| 68 | OGLPaints impl = impls.get(sg2d.paintState); | ||
| 69 | return (impl != null && impl.isPaintValid(sg2d)); | ||
| 70 | } | ||
| 71 | |||
| 72 | /** | ||
| 73 | * Returns true if this implementation is able to accelerate the | ||
| 74 | * Paint object associated with, and under the conditions of, the | ||
| 75 | * provided SunGraphics2D instance; otherwise returns false. | ||
| 76 | */ | ||
| 77 | abstract boolean isPaintValid(SunGraphics2D sg2d); | ||
| 78 | |||
| 79 | /************************* GradientPaint support ****************************/ | ||
| 80 | |||
| 81 | private static class Gradient extends OGLPaints { | ||
| 82 | private Gradient() {} | ||
| 83 | |||
| 84 | /** | ||
| 85 | * There are no restrictions for accelerating GradientPaint, so | ||
| 86 | * this method always returns true. | ||
| 87 | */ | ||
| 88 | @Override | ||
| 89 | boolean isPaintValid(SunGraphics2D sg2d) { | ||
| 90 | return true; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | /************************** TexturePaint support ****************************/ | ||
| 95 | |||
| 96 | private static class Texture extends OGLPaints { | ||
| 97 | private Texture() {} | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Returns true if the given TexturePaint instance can be used by the | ||
| 101 | * accelerated OGLPaints.Texture implementation. A TexturePaint is | ||
| 102 | * considered valid if the following conditions are met: | ||
| 103 | * - the texture image dimensions are power-of-two (or the | ||
| 104 | * GL_ARB_texture_non_power_of_two extension is present) | ||
| 105 | * - the texture image can be (or is already) cached in an OpenGL | ||
| 106 | * texture object | ||
| 107 | */ | ||
| 108 | @Override | ||
| 109 | boolean isPaintValid(SunGraphics2D sg2d) { | ||
| 110 | TexturePaint paint = (TexturePaint)sg2d.paint; | ||
| 111 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 112 | BufferedImage bi = paint.getImage(); | ||
| 113 | |||
| 114 | // see if texture-non-pow2 extension is available | ||
| 115 | if (!dstData.isTexNonPow2Available()) { | ||
| 116 | int imgw = bi.getWidth(); | ||
| 117 | int imgh = bi.getHeight(); | ||
| 118 | |||
| 119 | // verify that the texture image dimensions are pow2 | ||
| 120 | if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) { | ||
| 121 | return false; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | SurfaceData srcData = | ||
| 126 | dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT, | ||
| 127 | CompositeType.SrcOver, null); | ||
| 128 | if (!(srcData instanceof OGLSurfaceData)) { | ||
| 129 | // REMIND: this is a hack that attempts to cache the system | ||
| 130 | // memory image from the TexturePaint instance into an | ||
| 131 | // OpenGL texture... | ||
| 132 | srcData = | ||
| 133 | dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT, | ||
| 134 | CompositeType.SrcOver, null); | ||
| 135 | if (!(srcData instanceof OGLSurfaceData)) { | ||
| 136 | return false; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | // verify that the source surface is actually a texture | ||
| 141 | OGLSurfaceData oglData = (OGLSurfaceData)srcData; | ||
| 142 | if (oglData.getType() != OGLSurfaceData.TEXTURE) { | ||
| 143 | return false; | ||
| 144 | } | ||
| 145 | |||
| 146 | return true; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | /****************** Shared MultipleGradientPaint support ********************/ | ||
| 151 | |||
| 152 | private static abstract class MultiGradient extends OGLPaints { | ||
| 153 | protected MultiGradient() {} | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Returns true if the given MultipleGradientPaint instance can be | ||
| 157 | * used by the accelerated OGLPaints.MultiGradient implementation. | ||
| 158 | * A MultipleGradientPaint is considered valid if the following | ||
| 159 | * conditions are met: | ||
| 160 | * - the number of gradient "stops" is <= MAX_FRACTIONS | ||
| 161 | * - the destination has support for fragment shaders | ||
| 162 | */ | ||
| 163 | @Override | ||
| 164 | boolean isPaintValid(SunGraphics2D sg2d) { | ||
| 165 | MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint; | ||
| 166 | // REMIND: ugh, this creates garbage; would be nicer if | ||
| 167 | // we had a MultipleGradientPaint.getNumStops() method... | ||
| 168 | if (paint.getFractions().length > MULTI_MAX_FRACTIONS) { | ||
| 169 | return false; | ||
| 170 | } | ||
| 171 | |||
| 172 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 173 | OGLGraphicsConfig gc = dstData.getOGLGraphicsConfig(); | ||
| 174 | if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) { | ||
| 175 | return false; | ||
| 176 | } | ||
| 177 | |||
| 178 | return true; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | /********************** LinearGradientPaint support *************************/ | ||
| 183 | |||
| 184 | private static class LinearGradient extends MultiGradient { | ||
| 185 | private LinearGradient() {} | ||
| 186 | |||
| 187 | @Override | ||
| 188 | boolean isPaintValid(SunGraphics2D sg2d) { | ||
| 189 | LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint; | ||
| 190 | |||
| 191 | if (paint.getFractions().length == 2 && | ||
| 192 | paint.getCycleMethod() != CycleMethod.REPEAT && | ||
| 193 | paint.getColorSpace() != ColorSpaceType.LINEAR_RGB) | ||
| 194 | { | ||
| 195 | // we can delegate to the optimized two-color gradient | ||
| 196 | // codepath, which does not require fragment shader support | ||
| 197 | return true; | ||
| 198 | } | ||
| 199 | |||
| 200 | return super.isPaintValid(sg2d); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | /********************** RadialGradientPaint support *************************/ | ||
| 205 | |||
| 206 | private static class RadialGradient extends MultiGradient { | ||
| 207 | private RadialGradient() {} | ||
| 208 | } | ||
| 209 | } | ||
| @@ -0,0 +1,239 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2005, 2007, 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 sun.java2d.pipe.RenderBuffer; | ||
| 29 | import sun.java2d.pipe.RenderQueue; | ||
| 30 | import static sun.java2d.pipe.BufferedOpCodes.*; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * OGL-specific implementation of RenderQueue. This class provides a | ||
| 34 | * single (daemon) thread that is responsible for periodically flushing | ||
| 35 | * the queue, thus ensuring that only one thread communicates with the native | ||
| 36 | * OpenGL libraries for the entire process. | ||
| 37 | */ | ||
| 38 | public class OGLRenderQueue extends RenderQueue { | ||
| 39 | |||
| 40 | private static OGLRenderQueue theInstance; | ||
| 41 | private final QueueFlusher flusher; | ||
| 42 | |||
| 43 | private OGLRenderQueue() { | ||
| 44 | flusher = new QueueFlusher(); | ||
| 45 | } | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Returns the single OGLRenderQueue instance. If it has not yet been | ||
| 49 | * initialized, this method will first construct the single instance | ||
| 50 | * before returning it. | ||
| 51 | */ | ||
| 52 | public static synchronized OGLRenderQueue getInstance() { | ||
| 53 | if (theInstance == null) { | ||
| 54 | theInstance = new OGLRenderQueue(); | ||
| 55 | } | ||
| 56 | return theInstance; | ||
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Flushes the single OGLRenderQueue instance synchronously. If an | ||
| 61 | * OGLRenderQueue has not yet been instantiated, this method is a no-op. | ||
| 62 | * This method is useful in the case of Toolkit.sync(), in which we want | ||
| 63 | * to flush the OGL pipeline, but only if the OGL pipeline is currently | ||
| 64 | * enabled. Since this class has few external dependencies, callers need | ||
| 65 | * not be concerned that calling this method will trigger initialization | ||
| 66 | * of the OGL pipeline and related classes. | ||
| 67 | */ | ||
| 68 | public static void sync() { | ||
| 69 | if (theInstance != null) { | ||
| 70 | theInstance.lock(); | ||
| 71 | try { | ||
| 72 | theInstance.ensureCapacity(4); | ||
| 73 | theInstance.getBuffer().putInt(SYNC); | ||
| 74 | theInstance.flushNow(); | ||
| 75 | } finally { | ||
| 76 | theInstance.unlock(); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Disposes the native memory associated with the given native | ||
| 83 | * graphics config info pointer on the single queue flushing thread. | ||
| 84 | */ | ||
| 85 | public static void disposeGraphicsConfig(long pConfigInfo) { | ||
| 86 | OGLRenderQueue rq = getInstance(); | ||
| 87 | rq.lock(); | ||
| 88 | try { | ||
| 89 | // make sure we make the context associated with the given | ||
| 90 | // GraphicsConfig current before disposing the native resources | ||
| 91 | OGLContext.setScratchSurface(pConfigInfo); | ||
| 92 | |||
| 93 | RenderBuffer buf = rq.getBuffer(); | ||
| 94 | rq.ensureCapacityAndAlignment(12, 4); | ||
| 95 | buf.putInt(DISPOSE_CONFIG); | ||
| 96 | buf.putLong(pConfigInfo); | ||
| 97 | |||
| 98 | // this call is expected to complete synchronously, so flush now | ||
| 99 | rq.flushNow(); | ||
| 100 | } finally { | ||
| 101 | rq.unlock(); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Returns true if the current thread is the OGL QueueFlusher thread. | ||
| 107 | */ | ||
| 108 | public static boolean isQueueFlusherThread() { | ||
| 109 | return (Thread.currentThread() == getInstance().flusher); | ||
| 110 | } | ||
| 111 | |||
| 112 | public void flushNow() { | ||
| 113 | // assert lock.isHeldByCurrentThread(); | ||
| 114 | try { | ||
| 115 | flusher.flushNow(); | ||
| 116 | } catch (Exception e) { | ||
| 117 | System.err.println("exception in flushNow:"); | ||
| 118 | e.printStackTrace(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | public void flushAndInvokeNow(Runnable r) { | ||
| 123 | // assert lock.isHeldByCurrentThread(); | ||
| 124 | try { | ||
| 125 | flusher.flushAndInvokeNow(r); | ||
| 126 | } catch (Exception e) { | ||
| 127 | System.err.println("exception in flushAndInvokeNow:"); | ||
| 128 | e.printStackTrace(); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | private native void flushBuffer(long buf, int limit); | ||
| 133 | |||
| 134 | private void flushBuffer() { | ||
| 135 | // assert lock.isHeldByCurrentThread(); | ||
| 136 | int limit = buf.position(); | ||
| 137 | if (limit > 0) { | ||
| 138 | // process the queue | ||
| 139 | flushBuffer(buf.getAddress(), limit); | ||
| 140 | } | ||
| 141 | // reset the buffer position | ||
| 142 | buf.clear(); | ||
| 143 | // clear the set of references, since we no longer need them | ||
| 144 | refSet.clear(); | ||
| 145 | } | ||
| 146 | |||
| 147 | private class QueueFlusher extends Thread { | ||
| 148 | private boolean needsFlush; | ||
| 149 | private Runnable task; | ||
| 150 | private Error error; | ||
| 151 | |||
| 152 | public QueueFlusher() { | ||
| 153 | super("Java2D Queue Flusher"); | ||
| 154 | setDaemon(true); | ||
| 155 | setPriority(Thread.MAX_PRIORITY); | ||
| 156 | start(); | ||
| 157 | } | ||
| 158 | |||
| 159 | public synchronized void flushNow() { | ||
| 160 | // wake up the flusher | ||
| 161 | needsFlush = true; | ||
| 162 | notify(); | ||
| 163 | |||
| 164 | // wait for flush to complete | ||
| 165 | while (needsFlush) { | ||
| 166 | try { | ||
| 167 | wait(); | ||
| 168 | } catch (InterruptedException e) { | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | // re-throw any error that may have occurred during the flush | ||
| 173 | if (error != null) { | ||
| 174 | throw error; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | public synchronized void flushAndInvokeNow(Runnable task) { | ||
| 179 | this.task = task; | ||
| 180 | flushNow(); | ||
| 181 | } | ||
| 182 | |||
| 183 | public synchronized void run() { | ||
| 184 | boolean timedOut = false; | ||
| 185 | while (true) { | ||
| 186 | while (!needsFlush) { | ||
| 187 | try { | ||
| 188 | timedOut = false; | ||
| 189 | /* | ||
| 190 | * Wait until we're woken up with a flushNow() call, | ||
| 191 | * or the timeout period elapses (so that we can | ||
| 192 | * flush the queue periodically). | ||
| 193 | */ | ||
| 194 | wait(100); | ||
| 195 | /* | ||
| 196 | * We will automatically flush the queue if the | ||
| 197 | * following conditions apply: | ||
| 198 | * - the wait() timed out | ||
| 199 | * - we can lock the queue (without blocking) | ||
| 200 | * - there is something in the queue to flush | ||
| 201 | * Otherwise, just continue (we'll flush eventually). | ||
| 202 | */ | ||
| 203 | if (!needsFlush && (timedOut = tryLock())) { | ||
| 204 | if (buf.position() > 0) { | ||
| 205 | needsFlush = true; | ||
| 206 | } else { | ||
| 207 | unlock(); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } catch (InterruptedException e) { | ||
| 211 | } | ||
| 212 | } | ||
| 213 | try { | ||
| 214 | // reset the throwable state | ||
| 215 | error = null; | ||
| 216 | // flush the buffer now | ||
| 217 | flushBuffer(); | ||
| 218 | // if there's a task, invoke that now as well | ||
| 219 | if (task != null) { | ||
| 220 | task.run(); | ||
| 221 | } | ||
| 222 | } catch (Error e) { | ||
| 223 | error = e; | ||
| 224 | } catch (Exception x) { | ||
| 225 | System.err.println("exception in QueueFlusher:"); | ||
| 226 | x.printStackTrace(); | ||
| 227 | } finally { | ||
| 228 | if (timedOut) { | ||
| 229 | unlock(); | ||
| 230 | } | ||
| 231 | task = null; | ||
| 232 | // allow the waiting thread to continue | ||
| 233 | needsFlush = false; | ||
| 234 | notify(); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } | ||
| @@ -0,0 +1,206 @@ | |||
| 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.Transparency; | ||
| 29 | import java.awt.geom.Path2D; | ||
| 30 | import sun.java2d.SunGraphics2D; | ||
| 31 | import sun.java2d.loops.GraphicsPrimitive; | ||
| 32 | import sun.java2d.pipe.BufferedRenderPipe; | ||
| 33 | import sun.java2d.pipe.ParallelogramPipe; | ||
| 34 | import sun.java2d.pipe.RenderQueue; | ||
| 35 | import sun.java2d.pipe.SpanIterator; | ||
| 36 | import static sun.java2d.pipe.BufferedOpCodes.*; | ||
| 37 | |||
| 38 | class OGLRenderer extends BufferedRenderPipe { | ||
| 39 | |||
| 40 | OGLRenderer(RenderQueue rq) { | ||
| 41 | super(rq); | ||
| 42 | } | ||
| 43 | |||
| 44 | @Override | ||
| 45 | protected void validateContext(SunGraphics2D sg2d) { | ||
| 46 | int ctxflags = | ||
| 47 | sg2d.paint.getTransparency() == Transparency.OPAQUE ? | ||
| 48 | OGLContext.SRC_IS_OPAQUE : OGLContext.NO_CONTEXT_FLAGS; | ||
| 49 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 50 | OGLContext.validateContext(dstData, dstData, | ||
| 51 | sg2d.getCompClip(), sg2d.composite, | ||
| 52 | null, sg2d.paint, sg2d, ctxflags); | ||
| 53 | } | ||
| 54 | |||
| 55 | @Override | ||
| 56 | protected void validateContextAA(SunGraphics2D sg2d) { | ||
| 57 | int ctxflags = OGLContext.NO_CONTEXT_FLAGS; | ||
| 58 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 59 | OGLContext.validateContext(dstData, dstData, | ||
| 60 | sg2d.getCompClip(), sg2d.composite, | ||
| 61 | null, sg2d.paint, sg2d, ctxflags); | ||
| 62 | } | ||
| 63 | |||
| 64 | void copyArea(SunGraphics2D sg2d, | ||
| 65 | int x, int y, int w, int h, int dx, int dy) | ||
| 66 | { | ||
| 67 | rq.lock(); | ||
| 68 | try { | ||
| 69 | int ctxflags = | ||
| 70 | sg2d.surfaceData.getTransparency() == Transparency.OPAQUE ? | ||
| 71 | OGLContext.SRC_IS_OPAQUE : OGLContext.NO_CONTEXT_FLAGS; | ||
| 72 | OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData; | ||
| 73 | OGLContext.validateContext(dstData, dstData, | ||
| 74 | sg2d.getCompClip(), sg2d.composite, | ||
| 75 | null, null, null, ctxflags); | ||
| 76 | |||
| 77 | rq.ensureCapacity(28); | ||
| 78 | buf.putInt(COPY_AREA); | ||
| 79 | buf.putInt(x).putInt(y).putInt(w).putInt(h); | ||
| 80 | buf.putInt(dx).putInt(dy); | ||
| 81 | } finally { | ||
| 82 | rq.unlock(); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | @Override | ||
| 87 | protected native void drawPoly(int[] xPoints, int[] yPoints, | ||
| 88 | int nPoints, boolean isClosed, | ||
| 89 | int transX, int transY); | ||
| 90 | |||
| 91 | OGLRenderer traceWrap() { | ||
| 92 | return new Tracer(this); | ||
| 93 | } | ||
| 94 | |||
| 95 | private class Tracer extends OGLRenderer { | ||
| 96 | private OGLRenderer oglr; | ||
| 97 | Tracer(OGLRenderer oglr) { | ||
| 98 | super(oglr.rq); | ||
| 99 | this.oglr = oglr; | ||
| 100 | } | ||
| 101 | public ParallelogramPipe getAAParallelogramPipe() { | ||
| 102 | final ParallelogramPipe realpipe = oglr.getAAParallelogramPipe(); | ||
| 103 | return new ParallelogramPipe() { | ||
| 104 | public void fillParallelogram(SunGraphics2D sg2d, | ||
| 105 | double ux1, double uy1, | ||
| 106 | double ux2, double uy2, | ||
| 107 | double x, double y, | ||
| 108 | double dx1, double dy1, | ||
| 109 | double dx2, double dy2) | ||
| 110 | { | ||
| 111 | GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram"); | ||
| 112 | realpipe.fillParallelogram(sg2d, | ||
| 113 | ux1, uy1, ux2, uy2, | ||
| 114 | x, y, dx1, dy1, dx2, dy2); | ||
| 115 | } | ||
| 116 | public void drawParallelogram(SunGraphics2D sg2d, | ||
| 117 | double ux1, double uy1, | ||
| 118 | double ux2, double uy2, | ||
| 119 | double x, double y, | ||
| 120 | double dx1, double dy1, | ||
| 121 | double dx2, double dy2, | ||
| 122 | double lw1, double lw2) | ||
| 123 | { | ||
| 124 | GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram"); | ||
| 125 | realpipe.drawParallelogram(sg2d, | ||
| 126 | ux1, uy1, ux2, uy2, | ||
| 127 | x, y, dx1, dy1, dx2, dy2, | ||
| 128 | lw1, lw2); | ||
| 129 | } | ||
| 130 | }; | ||
| 131 | } | ||
| 132 | protected void validateContext(SunGraphics2D sg2d) { | ||
| 133 | oglr.validateContext(sg2d); | ||
| 134 | } | ||
| 135 | public void drawLine(SunGraphics2D sg2d, | ||
| 136 | int x1, int y1, int x2, int y2) | ||
| 137 | { | ||
| 138 | GraphicsPrimitive.tracePrimitive("OGLDrawLine"); | ||
| 139 | oglr.drawLine(sg2d, x1, y1, x2, y2); | ||
| 140 | } | ||
| 141 | public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) { | ||
| 142 | GraphicsPrimitive.tracePrimitive("OGLDrawRect"); | ||
| 143 | oglr.drawRect(sg2d, x, y, w, h); | ||
| 144 | } | ||
| 145 | protected void drawPoly(SunGraphics2D sg2d, | ||
| 146 | int[] xPoints, int[] yPoints, | ||
| 147 | int nPoints, boolean isClosed) | ||
| 148 | { | ||
| 149 | GraphicsPrimitive.tracePrimitive("OGLDrawPoly"); | ||
| 150 | oglr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed); | ||
| 151 | } | ||
| 152 | public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) { | ||
| 153 | GraphicsPrimitive.tracePrimitive("OGLFillRect"); | ||
| 154 | oglr.fillRect(sg2d, x, y, w, h); | ||
| 155 | } | ||
| 156 | protected void drawPath(SunGraphics2D sg2d, | ||
| 157 | Path2D.Float p2df, int transx, int transy) | ||
| 158 | { | ||
| 159 | GraphicsPrimitive.tracePrimitive("OGLDrawPath"); | ||
| 160 | oglr.drawPath(sg2d, p2df, transx, transy); | ||
| 161 | } | ||
| 162 | protected void fillPath(SunGraphics2D sg2d, | ||
| 163 | Path2D.Float p2df, int transx, int transy) | ||
| 164 | { | ||
| 165 | GraphicsPrimitive.tracePrimitive("OGLFillPath"); | ||
| 166 | oglr.fillPath(sg2d, p2df, transx, transy); | ||
| 167 | } | ||
| 168 | protected void fillSpans(SunGraphics2D sg2d, SpanIterator si, | ||
| 169 | int transx, int transy) | ||
| 170 | { | ||
| 171 | GraphicsPrimitive.tracePrimitive("OGLFillSpans"); | ||
| 172 | oglr.fillSpans(sg2d, si, transx, transy); | ||
| 173 | } | ||
| 174 | public void fillParallelogram(SunGraphics2D sg2d, | ||
| 175 | double ux1, double uy1, | ||
| 176 | double ux2, double uy2, | ||
| 177 | double x, double y, | ||
| 178 | double dx1, double dy1, | ||
| 179 | double dx2, double dy2) | ||
| 180 | { | ||
| 181 | GraphicsPrimitive.tracePrimitive("OGLFillParallelogram"); | ||
| 182 | oglr.fillParallelogram(sg2d, | ||
| 183 | ux1, uy1, ux2, uy2, | ||
| 184 | x, y, dx1, dy1, dx2, dy2); | ||
| 185 | } | ||
| 186 | public void drawParallelogram(SunGraphics2D sg2d, | ||
| 187 | double ux1, double uy1, | ||
| 188 | double ux2, double uy2, | ||
| 189 | double x, double y, | ||
| 190 | double dx1, double dy1, | ||
| 191 | double dx2, double dy2, | ||
| 192 | double lw1, double lw2) | ||
| 193 | { | ||
| 194 | GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram"); | ||
| 195 | oglr.drawParallelogram(sg2d, | ||
| 196 | ux1, uy1, ux2, uy2, | ||
| 197 | x, y, dx1, dy1, dx2, dy2, lw1, lw2); | ||
| 198 | } | ||
| 199 | public void copyArea(SunGraphics2D sg2d, | ||
| 200 | int x, int y, int w, int h, int dx, int dy) | ||
| 201 | { | ||
| 202 | GraphicsPrimitive.tracePrimitive("OGLCopyArea"); | ||
| 203 | oglr.copyArea(sg2d, x, y, w, h, dx, dy); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | } | ||
| @@ -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 | } | ||
| @@ -0,0 +1,81 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2007, 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.Color; | ||
| 29 | import java.awt.Transparency; | ||
| 30 | |||
| 31 | import sun.java2d.SurfaceData; | ||
| 32 | import sun.java2d.SurfaceDataProxy; | ||
| 33 | import sun.java2d.loops.SurfaceType; | ||
| 34 | import sun.java2d.loops.CompositeType; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * The proxy class contains the logic for when to replace a | ||
| 38 | * SurfaceData with a cached OGL Texture and the code to create | ||
| 39 | * the accelerated surfaces. | ||
| 40 | */ | ||
| 41 | public class OGLSurfaceDataProxy extends SurfaceDataProxy { | ||
| 42 | public static SurfaceDataProxy createProxy(SurfaceData srcData, | ||
| 43 | OGLGraphicsConfig dstConfig) | ||
| 44 | { | ||
| 45 | if (srcData instanceof OGLSurfaceData) { | ||
| 46 | // srcData must be a VolatileImage which either matches | ||
| 47 | // our pixel format or not - either way we do not cache it... | ||
| 48 | return UNCACHED; | ||
| 49 | } | ||
| 50 | |||
| 51 | return new OGLSurfaceDataProxy(dstConfig, srcData.getTransparency()); | ||
| 52 | } | ||
| 53 | |||
| 54 | OGLGraphicsConfig oglgc; | ||
| 55 | int transparency; | ||
| 56 | |||
| 57 | public OGLSurfaceDataProxy(OGLGraphicsConfig oglgc, int transparency) { | ||
| 58 | this.oglgc = oglgc; | ||
| 59 | this.transparency = transparency; | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 63 | public SurfaceData validateSurfaceData(SurfaceData srcData, | ||
| 64 | SurfaceData cachedData, | ||
| 65 | int w, int h) | ||
| 66 | { | ||
| 67 | if (cachedData == null) { | ||
| 68 | cachedData = oglgc.createManagedSurface(w, h, transparency); | ||
| 69 | } | ||
| 70 | return cachedData; | ||
| 71 | } | ||
| 72 | |||
| 73 | @Override | ||
| 74 | public boolean isSupportedOperation(SurfaceData srcData, | ||
| 75 | int txtype, | ||
| 76 | CompositeType comp, | ||
| 77 | Color bgColor) | ||
| 78 | { | ||
| 79 | return (bgColor == null || transparency == Transparency.OPAQUE); | ||
| 80 | } | ||
| 81 | } | ||
| @@ -0,0 +1,71 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2006, 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.Composite; | ||
| 29 | import sun.font.GlyphList; | ||
| 30 | import sun.java2d.SunGraphics2D; | ||
| 31 | import sun.java2d.loops.GraphicsPrimitive; | ||
| 32 | import sun.java2d.pipe.BufferedTextPipe; | ||
| 33 | import sun.java2d.pipe.RenderQueue; | ||
| 34 | |||
| 35 | class OGLTextRenderer extends BufferedTextPipe { | ||
| 36 | |||
| 37 | OGLTextRenderer(RenderQueue rq) { | ||
| 38 | super(rq); | ||
| 39 | } | ||
| 40 | |||
| 41 | @Override | ||
| 42 | protected native void drawGlyphList(int numGlyphs, boolean usePositions, | ||
| 43 | boolean subPixPos, boolean rgbOrder, | ||
| 44 | int lcdContrast, | ||
| 45 | float glOrigX, float glOrigY, | ||
| 46 | long[] images, float[] positions); | ||
| 47 | |||
| 48 | @Override | ||
| 49 | protected void validateContext(SunGraphics2D sg2d, Composite comp) { | ||
| 50 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 51 | OGLSurfaceData oglDst = (OGLSurfaceData)sg2d.surfaceData; | ||
| 52 | OGLContext.validateContext(oglDst, oglDst, | ||
| 53 | sg2d.getCompClip(), comp, | ||
| 54 | null, sg2d.paint, sg2d, | ||
| 55 | OGLContext.NO_CONTEXT_FLAGS); | ||
| 56 | } | ||
| 57 | |||
| 58 | OGLTextRenderer traceWrap() { | ||
| 59 | return new Tracer(this); | ||
| 60 | } | ||
| 61 | |||
| 62 | private static class Tracer extends OGLTextRenderer { | ||
| 63 | Tracer(OGLTextRenderer ogltr) { | ||
| 64 | super(ogltr.rq); | ||
| 65 | } | ||
| 66 | protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) { | ||
| 67 | GraphicsPrimitive.tracePrimitive("OGLDrawGlyphs"); | ||
| 68 | super.drawGlyphList(sg2d, gl); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| @@ -0,0 +1,338 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2005, 2006, 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.Graphics; | ||
| 29 | import java.awt.GraphicsConfiguration; | ||
| 30 | import java.awt.Rectangle; | ||
| 31 | import sun.java2d.SunGraphics2D; | ||
| 32 | import sun.java2d.SurfaceData; | ||
| 33 | import sun.java2d.pipe.Region; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * This class contains a number of static utility methods that may be | ||
| 37 | * called (via reflection) by a third-party library, such as JOGL, in order | ||
| 38 | * to interoperate with the OGL-based Java 2D pipeline. | ||
| 39 | * | ||
| 40 | * WARNING: These methods are being made available as a temporary measure | ||
| 41 | * until we offer a more complete, public solution. Like any sun.* class, | ||
| 42 | * this class is not an officially supported public API; it may be modified | ||
| 43 | * at will or removed completely in a future release. | ||
| 44 | */ | ||
| 45 | class OGLUtilities { | ||
| 46 | |||
| 47 | /** | ||
| 48 | * These OGL-specific surface type constants are the same as those | ||
| 49 | * defined in the OGLSurfaceData class and are duplicated here so that | ||
| 50 | * clients of this API can access them more easily via reflection. | ||
| 51 | */ | ||
| 52 | public static final int UNDEFINED = OGLSurfaceData.UNDEFINED; | ||
| 53 | public static final int WINDOW = OGLSurfaceData.WINDOW; | ||
| 54 | public static final int PBUFFER = OGLSurfaceData.PBUFFER; | ||
| 55 | public static final int TEXTURE = OGLSurfaceData.TEXTURE; | ||
| 56 | public static final int FLIP_BACKBUFFER = OGLSurfaceData.FLIP_BACKBUFFER; | ||
| 57 | public static final int FBOBJECT = OGLSurfaceData.FBOBJECT; | ||
| 58 | |||
| 59 | private OGLUtilities() { | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Returns true if the current thread is the OGL QueueFlusher thread. | ||
| 64 | */ | ||
| 65 | public static boolean isQueueFlusherThread() { | ||
| 66 | return OGLRenderQueue.isQueueFlusherThread(); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Invokes the given Runnable on the OGL QueueFlusher thread with the | ||
| 71 | * OpenGL context corresponding to the given Graphics object made | ||
| 72 | * current. It is legal for OpenGL code executed in the given | ||
| 73 | * Runnable to change the current OpenGL context; it will be reset | ||
| 74 | * once the Runnable completes. No guarantees are made as to the | ||
| 75 | * state of the OpenGL context of the Graphics object; for | ||
| 76 | * example, calling code must set the scissor box using the return | ||
| 77 | * value from {@link #getOGLScissorBox} to avoid drawing | ||
| 78 | * over other Swing components, and must typically set the OpenGL | ||
| 79 | * viewport using the return value from {@link #getOGLViewport} to | ||
| 80 | * make the client's OpenGL rendering appear in the correct place | ||
| 81 | * relative to the scissor region. | ||
| 82 | * | ||
| 83 | * In order to avoid deadlock, it is important that the given Runnable | ||
| 84 | * does not attempt to acquire the AWT lock, as that will be handled | ||
| 85 | * automatically as part of the <code>rq.flushAndInvokeNow()</code> step. | ||
| 86 | * | ||
| 87 | * @param g the Graphics object for the corresponding destination surface; | ||
| 88 | * if null, the step making a context current to the destination surface | ||
| 89 | * will be skipped | ||
| 90 | * @param r the action to be performed on the QFT; cannot be null | ||
| 91 | * @return true if the operation completed successfully, or false if | ||
| 92 | * there was any problem making a context current to the surface | ||
| 93 | * associated with the given Graphics object | ||
| 94 | */ | ||
| 95 | public static boolean invokeWithOGLContextCurrent(Graphics g, Runnable r) { | ||
| 96 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 97 | rq.lock(); | ||
| 98 | try { | ||
| 99 | if (g != null) { | ||
| 100 | if (!(g instanceof SunGraphics2D)) { | ||
| 101 | return false; | ||
| 102 | } | ||
| 103 | SurfaceData sData = ((SunGraphics2D)g).surfaceData; | ||
| 104 | if (!(sData instanceof OGLSurfaceData)) { | ||
| 105 | return false; | ||
| 106 | } | ||
| 107 | |||
| 108 | // make a context current to the destination surface | ||
| 109 | OGLContext.validateContext((OGLSurfaceData)sData); | ||
| 110 | } | ||
| 111 | |||
| 112 | // invoke the given runnable on the QFT | ||
| 113 | rq.flushAndInvokeNow(r); | ||
| 114 | |||
| 115 | // invalidate the current context so that the next time we render | ||
| 116 | // with Java 2D, the context state will be completely revalidated | ||
| 117 | OGLContext.invalidateCurrentContext(); | ||
| 118 | } finally { | ||
| 119 | rq.unlock(); | ||
| 120 | } | ||
| 121 | |||
| 122 | return true; | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Invokes the given Runnable on the OGL QueueFlusher thread with the | ||
| 127 | * "shared" OpenGL context (corresponding to the given | ||
| 128 | * GraphicsConfiguration object) made current. This method is typically | ||
| 129 | * used when the Runnable needs a current context to complete its | ||
| 130 | * operation, but does not require that the context be made current to | ||
| 131 | * a particular surface. For example, an application may call this | ||
| 132 | * method so that the given Runnable can query the OpenGL capabilities | ||
| 133 | * of the given GraphicsConfiguration, without making a context current | ||
| 134 | * to a dummy surface (or similar hacky techniques). | ||
| 135 | * | ||
| 136 | * In order to avoid deadlock, it is important that the given Runnable | ||
| 137 | * does not attempt to acquire the AWT lock, as that will be handled | ||
| 138 | * automatically as part of the <code>rq.flushAndInvokeNow()</code> step. | ||
| 139 | * | ||
| 140 | * @param config the GraphicsConfiguration object whose "shared" | ||
| 141 | * context will be made current during this operation; if this value is | ||
| 142 | * null or if OpenGL is not enabled for the GraphicsConfiguration, this | ||
| 143 | * method will return false | ||
| 144 | * @param r the action to be performed on the QFT; cannot be null | ||
| 145 | * @return true if the operation completed successfully, or false if | ||
| 146 | * there was any problem making the shared context current | ||
| 147 | */ | ||
| 148 | public static boolean | ||
| 149 | invokeWithOGLSharedContextCurrent(GraphicsConfiguration config, | ||
| 150 | Runnable r) | ||
| 151 | { | ||
| 152 | if (!(config instanceof OGLGraphicsConfig)) { | ||
| 153 | return false; | ||
| 154 | } | ||
| 155 | |||
| 156 | OGLRenderQueue rq = OGLRenderQueue.getInstance(); | ||
| 157 | rq.lock(); | ||
| 158 | try { | ||
| 159 | // make the "shared" context current for the given GraphicsConfig | ||
| 160 | OGLContext.setScratchSurface((OGLGraphicsConfig)config); | ||
| 161 | |||
| 162 | // invoke the given runnable on the QFT | ||
| 163 | rq.flushAndInvokeNow(r); | ||
| 164 | |||
| 165 | // invalidate the current context so that the next time we render | ||
| 166 | // with Java 2D, the context state will be completely revalidated | ||
| 167 | OGLContext.invalidateCurrentContext(); | ||
| 168 | } finally { | ||
| 169 | rq.unlock(); | ||
| 170 | } | ||
| 171 | |||
| 172 | return true; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Returns the Rectangle describing the OpenGL viewport on the | ||
| 177 | * Java 2D surface associated with the given Graphics object and | ||
| 178 | * component width and height. When a third-party library is | ||
| 179 | * performing OpenGL rendering directly into the visible region of | ||
| 180 | * the associated surface, this viewport helps the application | ||
| 181 | * position the OpenGL output correctly on that surface. | ||
| 182 | * | ||
| 183 | * Note that the x/y values in the returned Rectangle object represent | ||
| 184 | * the lower-left corner of the viewport region, relative to the | ||
| 185 | * lower-left corner of the given surface. | ||
| 186 | * | ||
| 187 | * @param g the Graphics object for the corresponding destination surface; | ||
| 188 | * cannot be null | ||
| 189 | * @param componentWidth width of the component to be painted | ||
| 190 | * @param componentHeight height of the component to be painted | ||
| 191 | * @return a Rectangle describing the OpenGL viewport for the given | ||
| 192 | * destination surface and component dimensions, or null if the given | ||
| 193 | * Graphics object is invalid | ||
| 194 | */ | ||
| 195 | public static Rectangle getOGLViewport(Graphics g, | ||
| 196 | int componentWidth, | ||
| 197 | int componentHeight) | ||
| 198 | { | ||
| 199 | if (!(g instanceof SunGraphics2D)) { | ||
| 200 | return null; | ||
| 201 | } | ||
| 202 | |||
| 203 | SunGraphics2D sg2d = (SunGraphics2D)g; | ||
| 204 | SurfaceData sData = (SurfaceData)sg2d.surfaceData; | ||
| 205 | |||
| 206 | // this is the upper-left origin of the region to be painted, | ||
| 207 | // relative to the upper-left origin of the surface | ||
| 208 | // (in Java2D coordinates) | ||
| 209 | int x0 = sg2d.transX; | ||
| 210 | int y0 = sg2d.transY; | ||
| 211 | |||
| 212 | // this is the lower-left origin of the region to be painted, | ||
| 213 | // relative to the lower-left origin of the surface | ||
| 214 | // (in OpenGL coordinates) | ||
| 215 | Rectangle surfaceBounds = sData.getBounds(); | ||
| 216 | int x1 = x0; | ||
| 217 | int y1 = surfaceBounds.height - (y0 + componentHeight); | ||
| 218 | |||
| 219 | return new Rectangle(x1, y1, componentWidth, componentHeight); | ||
| 220 | } | ||
| 221 | |||
| 222 | /** | ||
| 223 | * Returns the Rectangle describing the OpenGL scissor box on the | ||
| 224 | * Java 2D surface associated with the given Graphics object. When a | ||
| 225 | * third-party library is performing OpenGL rendering directly | ||
| 226 | * into the visible region of the associated surface, this scissor box | ||
| 227 | * must be set to avoid drawing over existing rendering results. | ||
| 228 | * | ||
| 229 | * Note that the x/y values in the returned Rectangle object represent | ||
| 230 | * the lower-left corner of the scissor region, relative to the | ||
| 231 | * lower-left corner of the given surface. | ||
| 232 | * | ||
| 233 | * @param g the Graphics object for the corresponding destination surface; | ||
| 234 | * cannot be null | ||
| 235 | * @return a Rectangle describing the OpenGL scissor box for the given | ||
| 236 | * Graphics object and corresponding destination surface, or null if the | ||
| 237 | * given Graphics object is invalid or the clip region is non-rectangular | ||
| 238 | */ | ||
| 239 | public static Rectangle getOGLScissorBox(Graphics g) { | ||
| 240 | if (!(g instanceof SunGraphics2D)) { | ||
| 241 | return null; | ||
| 242 | } | ||
| 243 | |||
| 244 | SunGraphics2D sg2d = (SunGraphics2D)g; | ||
| 245 | SurfaceData sData = (SurfaceData)sg2d.surfaceData; | ||
| 246 | Region r = sg2d.getCompClip(); | ||
| 247 | if (!r.isRectangular()) { | ||
| 248 | // caller probably doesn't know how to handle shape clip | ||
| 249 | // appropriately, so just return null (Swing currently never | ||
| 250 | // sets a shape clip, but that could change in the future) | ||
| 251 | return null; | ||
| 252 | } | ||
| 253 | |||
| 254 | // this is the upper-left origin of the scissor box relative to the | ||
| 255 | // upper-left origin of the surface (in Java 2D coordinates) | ||
| 256 | int x0 = r.getLoX(); | ||
| 257 | int y0 = r.getLoY(); | ||
| 258 | |||
| 259 | // this is the width and height of the scissor region | ||
| 260 | int w = r.getWidth(); | ||
| 261 | int h = r.getHeight(); | ||
| 262 | |||
| 263 | // this is the lower-left origin of the scissor box relative to the | ||
| 264 | // lower-left origin of the surface (in OpenGL coordinates) | ||
| 265 | Rectangle surfaceBounds = sData.getBounds(); | ||
| 266 | int x1 = x0; | ||
| 267 | int y1 = surfaceBounds.height - (y0 + h); | ||
| 268 | |||
| 269 | return new Rectangle(x1, y1, w, h); | ||
| 270 | } | ||
| 271 | |||
| 272 | /** | ||
| 273 | * Returns an Object identifier for the Java 2D surface associated with | ||
| 274 | * the given Graphics object. This identifier may be used to determine | ||
| 275 | * whether the surface has changed since the last invocation of this | ||
| 276 | * operation, and thereby whether the OpenGL state corresponding to the | ||
| 277 | * old surface must be destroyed and recreated. | ||
| 278 | * | ||
| 279 | * @param g the Graphics object for the corresponding destination surface; | ||
| 280 | * cannot be null | ||
| 281 | * @return an identifier for the surface associated with the given | ||
| 282 | * Graphics object, or null if the given Graphics object is invalid | ||
| 283 | */ | ||
| 284 | public static Object getOGLSurfaceIdentifier(Graphics g) { | ||
| 285 | if (!(g instanceof SunGraphics2D)) { | ||
| 286 | return null; | ||
| 287 | } | ||
| 288 | return ((SunGraphics2D)g).surfaceData; | ||
| 289 | } | ||
| 290 | |||
| 291 | /** | ||
| 292 | * Returns one of the OGL-specific surface type constants (defined in | ||
| 293 | * this class), which describes the surface associated with the given | ||
| 294 | * Graphics object. | ||
| 295 | * | ||
| 296 | * @param g the Graphics object for the corresponding destination surface; | ||
| 297 | * cannot be null | ||
| 298 | * @return a constant that describes the surface associated with the | ||
| 299 | * given Graphics object; if the given Graphics object is invalid (i.e. | ||
| 300 | * is not associated with an OpenGL surface) this method will return | ||
| 301 | * <code>OGLUtilities.UNDEFINED</code> | ||
| 302 | */ | ||
| 303 | public static int getOGLSurfaceType(Graphics g) { | ||
| 304 | if (!(g instanceof SunGraphics2D)) { | ||
| 305 | return UNDEFINED; | ||
| 306 | } | ||
| 307 | SurfaceData sData = ((SunGraphics2D)g).surfaceData; | ||
| 308 | if (!(sData instanceof OGLSurfaceData)) { | ||
| 309 | return UNDEFINED; | ||
| 310 | } | ||
| 311 | return ((OGLSurfaceData)sData).getType(); | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * Returns the OpenGL texture target constant (either GL_TEXTURE_2D | ||
| 316 | * or GL_TEXTURE_RECTANGLE_ARB) for the surface associated with the | ||
| 317 | * given Graphics object. This method is only useful for those surface | ||
| 318 | * types that are backed by an OpenGL texture, namely {@code TEXTURE}, | ||
| 319 | * {@code FBOBJECT}, and (on Windows only) {@code PBUFFER}. | ||
| 320 | * | ||
| 321 | * @param g the Graphics object for the corresponding destination surface; | ||
| 322 | * cannot be null | ||
| 323 | * @return the texture target constant for the surface associated with the | ||
| 324 | * given Graphics object; if the given Graphics object is invalid (i.e. | ||
| 325 | * is not associated with an OpenGL surface), or the associated surface | ||
| 326 | * is not backed by an OpenGL texture, this method will return zero. | ||
| 327 | */ | ||
| 328 | public static int getOGLTextureType(Graphics g) { | ||
| 329 | if (!(g instanceof SunGraphics2D)) { | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | SurfaceData sData = ((SunGraphics2D)g).surfaceData; | ||
| 333 | if (!(sData instanceof OGLSurfaceData)) { | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | return ((OGLSurfaceData)sData).getTextureTarget(); | ||
| 337 | } | ||
| 338 | } | ||
| @@ -0,0 +1,21 @@ | |||
| 1 | <../../../../../mkconfig | ||
| 2 | |||
| 3 | TARG=\ | ||
| 4 | OGLBlitLoops.dis\ | ||
| 5 | OGLBufImgOps.dis\ | ||
| 6 | OGLContext.dis\ | ||
| 7 | OGLDrawImage.dis\ | ||
| 8 | OGLGraphicsConfig.dis\ | ||
| 9 | OGLMaskBlit.dis\ | ||
| 10 | OGLMaskFill.dis\ | ||
| 11 | OGLPaints.dis\ | ||
| 12 | OGLRenderer.dis\ | ||
| 13 | OGLRenderQueue.dis\ | ||
| 14 | OGLSurfaceData.dis\ | ||
| 15 | OGLSurfaceDataProxy.dis\ | ||
| 16 | OGLTextRenderer.dis\ | ||
| 17 | OGLUtilities.dis\ | ||
| 18 | |||
| 19 | DISBIN=$ROOT/java/dis/java/java/sun/java2d/opengl | ||
| 20 | |||
| 21 | <$ROOT/mkfiles/mkjava | ||