1/* 2 * Copyright (c) 2003, 2015, 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 26package sun.java2d.opengl; 27 28import java.awt.AlphaComposite; 29import java.awt.Composite; 30import java.awt.Transparency; 31import java.awt.geom.AffineTransform; 32import java.awt.image.AffineTransformOp; 33import java.awt.image.BufferedImage; 34import java.awt.image.BufferedImageOp; 35import java.lang.ref.WeakReference; 36import sun.java2d.SurfaceData; 37import sun.java2d.loops.Blit; 38import sun.java2d.loops.CompositeType; 39import sun.java2d.loops.GraphicsPrimitive; 40import sun.java2d.loops.GraphicsPrimitiveMgr; 41import sun.java2d.loops.ScaledBlit; 42import sun.java2d.loops.SurfaceType; 43import sun.java2d.loops.TransformBlit; 44import sun.java2d.pipe.Region; 45import sun.java2d.pipe.RenderBuffer; 46import sun.java2d.pipe.RenderQueue; 47import static sun.java2d.pipe.BufferedOpCodes.*; 48import java.lang.annotation.Native; 49 50final class OGLBlitLoops { 51 52 static void register() { 53 Blit blitIntArgbPreToSurface = 54 new OGLSwToSurfaceBlit(SurfaceType.IntArgbPre, 55 OGLSurfaceData.PF_INT_ARGB_PRE); 56 Blit blitIntArgbPreToTexture = 57 new OGLSwToTextureBlit(SurfaceType.IntArgbPre, 58 OGLSurfaceData.PF_INT_ARGB_PRE); 59 TransformBlit transformBlitIntArgbPreToSurface = 60 new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, 61 OGLSurfaceData.PF_INT_ARGB_PRE); 62 OGLSurfaceToSwBlit blitSurfaceToIntArgbPre = 63 new OGLSurfaceToSwBlit(SurfaceType.IntArgbPre, 64 OGLSurfaceData.PF_INT_ARGB_PRE); 65 66 GraphicsPrimitive[] primitives = { 67 // surface->surface ops 68 new OGLSurfaceToSurfaceBlit(), 69 new OGLSurfaceToSurfaceScale(), 70 new OGLSurfaceToSurfaceTransform(), 71 72 // render-to-texture surface->surface ops 73 new OGLRTTSurfaceToSurfaceBlit(), 74 new OGLRTTSurfaceToSurfaceScale(), 75 new OGLRTTSurfaceToSurfaceTransform(), 76 77 // surface->sw ops 78 new OGLSurfaceToSwBlit(SurfaceType.IntArgb, 79 OGLSurfaceData.PF_INT_ARGB), 80 blitSurfaceToIntArgbPre, 81 82 // sw->surface ops 83 blitIntArgbPreToSurface, 84 new OGLSwToSurfaceBlit(SurfaceType.IntRgb, 85 OGLSurfaceData.PF_INT_RGB), 86 new OGLSwToSurfaceBlit(SurfaceType.IntRgbx, 87 OGLSurfaceData.PF_INT_RGBX), 88 new OGLSwToSurfaceBlit(SurfaceType.IntBgr, 89 OGLSurfaceData.PF_INT_BGR), 90 new OGLSwToSurfaceBlit(SurfaceType.IntBgrx, 91 OGLSurfaceData.PF_INT_BGRX), 92 new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr, 93 OGLSurfaceData.PF_3BYTE_BGR), 94 new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb, 95 OGLSurfaceData.PF_USHORT_565_RGB), 96 new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb, 97 OGLSurfaceData.PF_USHORT_555_RGB), 98 new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx, 99 OGLSurfaceData.PF_USHORT_555_RGBX), 100 new OGLSwToSurfaceBlit(SurfaceType.ByteGray, 101 OGLSurfaceData.PF_BYTE_GRAY), 102 new OGLSwToSurfaceBlit(SurfaceType.UshortGray, 103 OGLSurfaceData.PF_USHORT_GRAY), 104 new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface, 105 CompositeType.AnyAlpha, 106 blitIntArgbPreToSurface), 107 108 new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface, 109 blitSurfaceToIntArgbPre, 110 blitSurfaceToIntArgbPre, 111 blitIntArgbPreToSurface), 112 new OGLAnyCompositeBlit(SurfaceType.Any, 113 null, 114 blitSurfaceToIntArgbPre, 115 blitIntArgbPreToSurface), 116 117 new OGLSwToSurfaceScale(SurfaceType.IntRgb, 118 OGLSurfaceData.PF_INT_RGB), 119 new OGLSwToSurfaceScale(SurfaceType.IntRgbx, 120 OGLSurfaceData.PF_INT_RGBX), 121 new OGLSwToSurfaceScale(SurfaceType.IntBgr, 122 OGLSurfaceData.PF_INT_BGR), 123 new OGLSwToSurfaceScale(SurfaceType.IntBgrx, 124 OGLSurfaceData.PF_INT_BGRX), 125 new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr, 126 OGLSurfaceData.PF_3BYTE_BGR), 127 new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb, 128 OGLSurfaceData.PF_USHORT_565_RGB), 129 new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb, 130 OGLSurfaceData.PF_USHORT_555_RGB), 131 new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx, 132 OGLSurfaceData.PF_USHORT_555_RGBX), 133 new OGLSwToSurfaceScale(SurfaceType.ByteGray, 134 OGLSurfaceData.PF_BYTE_GRAY), 135 new OGLSwToSurfaceScale(SurfaceType.UshortGray, 136 OGLSurfaceData.PF_USHORT_GRAY), 137 new OGLSwToSurfaceScale(SurfaceType.IntArgbPre, 138 OGLSurfaceData.PF_INT_ARGB_PRE), 139 140 new OGLSwToSurfaceTransform(SurfaceType.IntRgb, 141 OGLSurfaceData.PF_INT_RGB), 142 new OGLSwToSurfaceTransform(SurfaceType.IntRgbx, 143 OGLSurfaceData.PF_INT_RGBX), 144 new OGLSwToSurfaceTransform(SurfaceType.IntBgr, 145 OGLSurfaceData.PF_INT_BGR), 146 new OGLSwToSurfaceTransform(SurfaceType.IntBgrx, 147 OGLSurfaceData.PF_INT_BGRX), 148 new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr, 149 OGLSurfaceData.PF_3BYTE_BGR), 150 new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb, 151 OGLSurfaceData.PF_USHORT_565_RGB), 152 new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb, 153 OGLSurfaceData.PF_USHORT_555_RGB), 154 new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx, 155 OGLSurfaceData.PF_USHORT_555_RGBX), 156 new OGLSwToSurfaceTransform(SurfaceType.ByteGray, 157 OGLSurfaceData.PF_BYTE_GRAY), 158 new OGLSwToSurfaceTransform(SurfaceType.UshortGray, 159 OGLSurfaceData.PF_USHORT_GRAY), 160 transformBlitIntArgbPreToSurface, 161 162 new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface), 163 164 // texture->surface ops 165 new OGLTextureToSurfaceBlit(), 166 new OGLTextureToSurfaceScale(), 167 new OGLTextureToSurfaceTransform(), 168 169 // sw->texture ops 170 blitIntArgbPreToTexture, 171 new OGLSwToTextureBlit(SurfaceType.IntRgb, 172 OGLSurfaceData.PF_INT_RGB), 173 new OGLSwToTextureBlit(SurfaceType.IntRgbx, 174 OGLSurfaceData.PF_INT_RGBX), 175 new OGLSwToTextureBlit(SurfaceType.IntBgr, 176 OGLSurfaceData.PF_INT_BGR), 177 new OGLSwToTextureBlit(SurfaceType.IntBgrx, 178 OGLSurfaceData.PF_INT_BGRX), 179 new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr, 180 OGLSurfaceData.PF_3BYTE_BGR), 181 new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb, 182 OGLSurfaceData.PF_USHORT_565_RGB), 183 new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb, 184 OGLSurfaceData.PF_USHORT_555_RGB), 185 new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx, 186 OGLSurfaceData.PF_USHORT_555_RGBX), 187 new OGLSwToTextureBlit(SurfaceType.ByteGray, 188 OGLSurfaceData.PF_BYTE_GRAY), 189 new OGLSwToTextureBlit(SurfaceType.UshortGray, 190 OGLSurfaceData.PF_USHORT_GRAY), 191 new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture, 192 CompositeType.SrcNoEa, 193 blitIntArgbPreToTexture), 194 }; 195 GraphicsPrimitiveMgr.register(primitives); 196 } 197 198 /** 199 * The following offsets are used to pack the parameters in 200 * createPackedParams(). (They are also used at the native level when 201 * unpacking the params.) 202 */ 203 @Native private static final int OFFSET_SRCTYPE = 16; 204 @Native private static final int OFFSET_HINT = 8; 205 @Native private static final int OFFSET_TEXTURE = 3; 206 @Native private static final int OFFSET_RTT = 2; 207 @Native private static final int OFFSET_XFORM = 1; 208 @Native private static final int OFFSET_ISOBLIT = 0; 209 210 /** 211 * Packs the given parameters into a single int value in order to save 212 * space on the rendering queue. 213 */ 214 private static int createPackedParams(boolean isoblit, boolean texture, 215 boolean rtt, boolean xform, 216 int hint, int srctype) 217 { 218 return 219 ((srctype << OFFSET_SRCTYPE) | 220 (hint << OFFSET_HINT ) | 221 ((texture ? 1 : 0) << OFFSET_TEXTURE) | 222 ((rtt ? 1 : 0) << OFFSET_RTT ) | 223 ((xform ? 1 : 0) << OFFSET_XFORM ) | 224 ((isoblit ? 1 : 0) << OFFSET_ISOBLIT)); 225 } 226 227 /** 228 * Enqueues a BLIT operation with the given parameters. Note that the 229 * RenderQueue lock must be held before calling this method. 230 */ 231 private static void enqueueBlit(RenderQueue rq, 232 SurfaceData src, SurfaceData dst, 233 int packedParams, 234 int sx1, int sy1, 235 int sx2, int sy2, 236 double dx1, double dy1, 237 double dx2, double dy2) 238 { 239 // assert rq.lock.isHeldByCurrentThread(); 240 RenderBuffer buf = rq.getBuffer(); 241 rq.ensureCapacityAndAlignment(72, 24); 242 buf.putInt(BLIT); 243 buf.putInt(packedParams); 244 buf.putInt(sx1).putInt(sy1); 245 buf.putInt(sx2).putInt(sy2); 246 buf.putDouble(dx1).putDouble(dy1); 247 buf.putDouble(dx2).putDouble(dy2); 248 buf.putLong(src.getNativeOps()); 249 buf.putLong(dst.getNativeOps()); 250 } 251 252 static void Blit(SurfaceData srcData, SurfaceData dstData, 253 Composite comp, Region clip, 254 AffineTransform xform, int hint, 255 int sx1, int sy1, 256 int sx2, int sy2, 257 double dx1, double dy1, 258 double dx2, double dy2, 259 int srctype, boolean texture) 260 { 261 int ctxflags = 0; 262 if (srcData.getTransparency() == Transparency.OPAQUE) { 263 ctxflags |= OGLContext.SRC_IS_OPAQUE; 264 } 265 266 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 267 rq.lock(); 268 try { 269 // make sure the RenderQueue keeps a hard reference to the 270 // source (sysmem) SurfaceData to prevent it from being 271 // disposed while the operation is processed on the QFT 272 rq.addReference(srcData); 273 274 OGLSurfaceData oglDst = (OGLSurfaceData)dstData; 275 if (texture) { 276 // make sure we have a current context before uploading 277 // the sysmem data to the texture object 278 OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig(); 279 OGLContext.setScratchSurface(gc); 280 } else { 281 OGLContext.validateContext(oglDst, oglDst, 282 clip, comp, xform, null, null, 283 ctxflags); 284 } 285 286 int packedParams = createPackedParams(false, texture, 287 false, xform != null, 288 hint, srctype); 289 enqueueBlit(rq, srcData, dstData, 290 packedParams, 291 sx1, sy1, sx2, sy2, 292 dx1, dy1, dx2, dy2); 293 294 // always flush immediately, since we (currently) have no means 295 // of tracking changes to the system memory surface 296 rq.flushNow(); 297 } finally { 298 rq.unlock(); 299 } 300 } 301 302 /** 303 * Note: The srcImg and biop parameters are only used when invoked 304 * from the OGLBufImgOps.renderImageWithOp() method; in all other cases, 305 * this method can be called with null values for those two parameters, 306 * and they will be effectively ignored. 307 */ 308 static void IsoBlit(SurfaceData srcData, SurfaceData dstData, 309 BufferedImage srcImg, BufferedImageOp biop, 310 Composite comp, Region clip, 311 AffineTransform xform, int hint, 312 int sx1, int sy1, 313 int sx2, int sy2, 314 double dx1, double dy1, 315 double dx2, double dy2, 316 boolean texture) 317 { 318 int ctxflags = 0; 319 if (srcData.getTransparency() == Transparency.OPAQUE) { 320 ctxflags |= OGLContext.SRC_IS_OPAQUE; 321 } 322 323 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 324 rq.lock(); 325 try { 326 OGLSurfaceData oglSrc = (OGLSurfaceData)srcData; 327 OGLSurfaceData oglDst = (OGLSurfaceData)dstData; 328 int srctype = oglSrc.getType(); 329 boolean rtt; 330 OGLSurfaceData srcCtxData; 331 if (srctype == OGLSurfaceData.TEXTURE) { 332 // the source is a regular texture object; we substitute 333 // the destination surface for the purposes of making a 334 // context current 335 rtt = false; 336 srcCtxData = oglDst; 337 } else { 338 // the source is a pbuffer, backbuffer, or render-to-texture 339 // surface; we set rtt to true to differentiate this kind 340 // of surface from a regular texture object 341 rtt = true; 342 if (srctype == OGLSurfaceData.FBOBJECT) { 343 srcCtxData = oglDst; 344 } else { 345 srcCtxData = oglSrc; 346 } 347 } 348 349 OGLContext.validateContext(srcCtxData, oglDst, 350 clip, comp, xform, null, null, 351 ctxflags); 352 353 if (biop != null) { 354 OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop); 355 } 356 357 int packedParams = createPackedParams(true, texture, 358 rtt, xform != null, 359 hint, 0 /*unused*/); 360 enqueueBlit(rq, srcData, dstData, 361 packedParams, 362 sx1, sy1, sx2, sy2, 363 dx1, dy1, dx2, dy2); 364 365 if (biop != null) { 366 OGLBufImgOps.disableBufImgOp(rq, biop); 367 } 368 369 if (rtt && oglDst.isOnScreen()) { 370 // we only have to flush immediately when copying from a 371 // (non-texture) surface to the screen; otherwise Swing apps 372 // might appear unresponsive until the auto-flush completes 373 rq.flushNow(); 374 } 375 } finally { 376 rq.unlock(); 377 } 378 } 379} 380 381class OGLSurfaceToSurfaceBlit extends Blit { 382 383 OGLSurfaceToSurfaceBlit() { 384 super(OGLSurfaceData.OpenGLSurface, 385 CompositeType.AnyAlpha, 386 OGLSurfaceData.OpenGLSurface); 387 } 388 389 public void Blit(SurfaceData src, SurfaceData dst, 390 Composite comp, Region clip, 391 int sx, int sy, int dx, int dy, int w, int h) 392 { 393 OGLBlitLoops.IsoBlit(src, dst, 394 null, null, 395 comp, clip, null, 396 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 397 sx, sy, sx+w, sy+h, 398 dx, dy, dx+w, dy+h, 399 false); 400 } 401} 402 403class OGLSurfaceToSurfaceScale extends ScaledBlit { 404 405 OGLSurfaceToSurfaceScale() { 406 super(OGLSurfaceData.OpenGLSurface, 407 CompositeType.AnyAlpha, 408 OGLSurfaceData.OpenGLSurface); 409 } 410 411 public void Scale(SurfaceData src, SurfaceData dst, 412 Composite comp, Region clip, 413 int sx1, int sy1, 414 int sx2, int sy2, 415 double dx1, double dy1, 416 double dx2, double dy2) 417 { 418 OGLBlitLoops.IsoBlit(src, dst, 419 null, null, 420 comp, clip, null, 421 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 422 sx1, sy1, sx2, sy2, 423 dx1, dy1, dx2, dy2, 424 false); 425 } 426} 427 428class OGLSurfaceToSurfaceTransform extends TransformBlit { 429 430 OGLSurfaceToSurfaceTransform() { 431 super(OGLSurfaceData.OpenGLSurface, 432 CompositeType.AnyAlpha, 433 OGLSurfaceData.OpenGLSurface); 434 } 435 436 public void Transform(SurfaceData src, SurfaceData dst, 437 Composite comp, Region clip, 438 AffineTransform at, int hint, 439 int sx, int sy, int dx, int dy, 440 int w, int h) 441 { 442 OGLBlitLoops.IsoBlit(src, dst, 443 null, null, 444 comp, clip, at, hint, 445 sx, sy, sx+w, sy+h, 446 dx, dy, dx+w, dy+h, 447 false); 448 } 449} 450 451class OGLRTTSurfaceToSurfaceBlit extends Blit { 452 453 OGLRTTSurfaceToSurfaceBlit() { 454 super(OGLSurfaceData.OpenGLSurfaceRTT, 455 CompositeType.AnyAlpha, 456 OGLSurfaceData.OpenGLSurface); 457 } 458 459 public void Blit(SurfaceData src, SurfaceData dst, 460 Composite comp, Region clip, 461 int sx, int sy, int dx, int dy, int w, int h) 462 { 463 OGLBlitLoops.IsoBlit(src, dst, 464 null, null, 465 comp, clip, null, 466 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 467 sx, sy, sx+w, sy+h, 468 dx, dy, dx+w, dy+h, 469 true); 470 } 471} 472 473class OGLRTTSurfaceToSurfaceScale extends ScaledBlit { 474 475 OGLRTTSurfaceToSurfaceScale() { 476 super(OGLSurfaceData.OpenGLSurfaceRTT, 477 CompositeType.AnyAlpha, 478 OGLSurfaceData.OpenGLSurface); 479 } 480 481 public void Scale(SurfaceData src, SurfaceData dst, 482 Composite comp, Region clip, 483 int sx1, int sy1, 484 int sx2, int sy2, 485 double dx1, double dy1, 486 double dx2, double dy2) 487 { 488 OGLBlitLoops.IsoBlit(src, dst, 489 null, null, 490 comp, clip, null, 491 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 492 sx1, sy1, sx2, sy2, 493 dx1, dy1, dx2, dy2, 494 true); 495 } 496} 497 498class OGLRTTSurfaceToSurfaceTransform extends TransformBlit { 499 500 OGLRTTSurfaceToSurfaceTransform() { 501 super(OGLSurfaceData.OpenGLSurfaceRTT, 502 CompositeType.AnyAlpha, 503 OGLSurfaceData.OpenGLSurface); 504 } 505 506 public void Transform(SurfaceData src, SurfaceData dst, 507 Composite comp, Region clip, 508 AffineTransform at, int hint, 509 int sx, int sy, int dx, int dy, int w, int h) 510 { 511 OGLBlitLoops.IsoBlit(src, dst, 512 null, null, 513 comp, clip, at, hint, 514 sx, sy, sx+w, sy+h, 515 dx, dy, dx+w, dy+h, 516 true); 517 } 518} 519 520final class OGLSurfaceToSwBlit extends Blit { 521 522 private final int typeval; 523 private WeakReference<SurfaceData> srcTmp; 524 525 // destination will actually be ArgbPre or Argb 526 OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval) { 527 super(OGLSurfaceData.OpenGLSurface, 528 CompositeType.SrcNoEa, 529 dstType); 530 this.typeval = typeval; 531 } 532 533 private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, 534 Composite comp, Region clip, 535 int sx, int sy, int dx, int dy, 536 int w, int h) { 537 SurfaceData cachedSrc = null; 538 if (srcTmp != null) { 539 // use cached intermediate surface, if available 540 cachedSrc = srcTmp.get(); 541 } 542 543 // We can convert argb_pre data from OpenGL surface in two places: 544 // - During OpenGL surface -> SW blit 545 // - During SW -> SW blit 546 // The first one is faster when we use opaque OGL surface, because in 547 // this case we simply skip conversion and use color components as is. 548 // Because of this we align intermediate buffer type with type of 549 // destination not source. 550 final int type = typeval == OGLSurfaceData.PF_INT_ARGB_PRE ? 551 BufferedImage.TYPE_INT_ARGB_PRE : 552 BufferedImage.TYPE_INT_ARGB; 553 554 src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); 555 556 // copy intermediate SW to destination SW using complex clip 557 final Blit performop = Blit.getFromCache(src.getSurfaceType(), 558 CompositeType.SrcNoEa, 559 dst.getSurfaceType()); 560 performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); 561 562 if (src != cachedSrc) { 563 // cache the intermediate surface 564 srcTmp = new WeakReference<>(src); 565 } 566 } 567 568 public void Blit(SurfaceData src, SurfaceData dst, 569 Composite comp, Region clip, 570 int sx, int sy, int dx, int dy, 571 int w, int h) 572 { 573 if (clip != null) { 574 clip = clip.getIntersectionXYWH(dx, dy, w, h); 575 // At the end this method will flush the RenderQueue, we should exit 576 // from it as soon as possible. 577 if (clip.isEmpty()) { 578 return; 579 } 580 sx += clip.getLoX() - dx; 581 sy += clip.getLoY() - dy; 582 dx = clip.getLoX(); 583 dy = clip.getLoY(); 584 w = clip.getWidth(); 585 h = clip.getHeight(); 586 587 if (!clip.isRectangular()) { 588 complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 589 return; 590 } 591 } 592 593 OGLRenderQueue rq = OGLRenderQueue.getInstance(); 594 rq.lock(); 595 try { 596 // make sure the RenderQueue keeps a hard reference to the 597 // destination (sysmem) SurfaceData to prevent it from being 598 // disposed while the operation is processed on the QFT 599 rq.addReference(dst); 600 601 RenderBuffer buf = rq.getBuffer(); 602 OGLContext.validateContext((OGLSurfaceData)src); 603 604 rq.ensureCapacityAndAlignment(48, 32); 605 buf.putInt(SURFACE_TO_SW_BLIT); 606 buf.putInt(sx).putInt(sy); 607 buf.putInt(dx).putInt(dy); 608 buf.putInt(w).putInt(h); 609 buf.putInt(typeval); 610 buf.putLong(src.getNativeOps()); 611 buf.putLong(dst.getNativeOps()); 612 613 // always flush immediately 614 rq.flushNow(); 615 } finally { 616 rq.unlock(); 617 } 618 } 619} 620 621class OGLSwToSurfaceBlit extends Blit { 622 623 private int typeval; 624 625 OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) { 626 super(srcType, 627 CompositeType.AnyAlpha, 628 OGLSurfaceData.OpenGLSurface); 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, false); 642 } 643} 644 645class OGLSwToSurfaceScale extends ScaledBlit { 646 647 private int typeval; 648 649 OGLSwToSurfaceScale(SurfaceType srcType, int typeval) { 650 super(srcType, 651 CompositeType.AnyAlpha, 652 OGLSurfaceData.OpenGLSurface); 653 this.typeval = typeval; 654 } 655 656 public void Scale(SurfaceData src, SurfaceData dst, 657 Composite comp, Region clip, 658 int sx1, int sy1, 659 int sx2, int sy2, 660 double dx1, double dy1, 661 double dx2, double dy2) 662 { 663 OGLBlitLoops.Blit(src, dst, 664 comp, clip, null, 665 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 666 sx1, sy1, sx2, sy2, 667 dx1, dy1, dx2, dy2, 668 typeval, false); 669 } 670} 671 672class OGLSwToSurfaceTransform extends TransformBlit { 673 674 private int typeval; 675 676 OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) { 677 super(srcType, 678 CompositeType.AnyAlpha, 679 OGLSurfaceData.OpenGLSurface); 680 this.typeval = typeval; 681 } 682 683 public void Transform(SurfaceData src, SurfaceData dst, 684 Composite comp, Region clip, 685 AffineTransform at, int hint, 686 int sx, int sy, int dx, int dy, int w, int h) 687 { 688 OGLBlitLoops.Blit(src, dst, 689 comp, clip, at, hint, 690 sx, sy, sx+w, sy+h, 691 dx, dy, dx+w, dy+h, 692 typeval, false); 693 } 694} 695 696class OGLSwToTextureBlit extends Blit { 697 698 private int typeval; 699 700 OGLSwToTextureBlit(SurfaceType srcType, int typeval) { 701 super(srcType, 702 CompositeType.SrcNoEa, 703 OGLSurfaceData.OpenGLTexture); 704 this.typeval = typeval; 705 } 706 707 public void Blit(SurfaceData src, SurfaceData dst, 708 Composite comp, Region clip, 709 int sx, int sy, int dx, int dy, int w, int h) 710 { 711 OGLBlitLoops.Blit(src, dst, 712 comp, clip, null, 713 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 714 sx, sy, sx+w, sy+h, 715 dx, dy, dx+w, dy+h, 716 typeval, true); 717 } 718} 719 720class OGLTextureToSurfaceBlit extends Blit { 721 722 OGLTextureToSurfaceBlit() { 723 super(OGLSurfaceData.OpenGLTexture, 724 CompositeType.AnyAlpha, 725 OGLSurfaceData.OpenGLSurface); 726 } 727 728 public void Blit(SurfaceData src, SurfaceData dst, 729 Composite comp, Region clip, 730 int sx, int sy, int dx, int dy, int w, int h) 731 { 732 OGLBlitLoops.IsoBlit(src, dst, 733 null, null, 734 comp, clip, null, 735 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 736 sx, sy, sx+w, sy+h, 737 dx, dy, dx+w, dy+h, 738 true); 739 } 740} 741 742class OGLTextureToSurfaceScale extends ScaledBlit { 743 744 OGLTextureToSurfaceScale() { 745 super(OGLSurfaceData.OpenGLTexture, 746 CompositeType.AnyAlpha, 747 OGLSurfaceData.OpenGLSurface); 748 } 749 750 public void Scale(SurfaceData src, SurfaceData dst, 751 Composite comp, Region clip, 752 int sx1, int sy1, 753 int sx2, int sy2, 754 double dx1, double dy1, 755 double dx2, double dy2) 756 { 757 OGLBlitLoops.IsoBlit(src, dst, 758 null, null, 759 comp, clip, null, 760 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 761 sx1, sy1, sx2, sy2, 762 dx1, dy1, dx2, dy2, 763 true); 764 } 765} 766 767class OGLTextureToSurfaceTransform extends TransformBlit { 768 769 OGLTextureToSurfaceTransform() { 770 super(OGLSurfaceData.OpenGLTexture, 771 CompositeType.AnyAlpha, 772 OGLSurfaceData.OpenGLSurface); 773 } 774 775 public void Transform(SurfaceData src, SurfaceData dst, 776 Composite comp, Region clip, 777 AffineTransform at, int hint, 778 int sx, int sy, int dx, int dy, 779 int w, int h) 780 { 781 OGLBlitLoops.IsoBlit(src, dst, 782 null, null, 783 comp, clip, at, hint, 784 sx, sy, sx+w, sy+h, 785 dx, dy, dx+w, dy+h, 786 true); 787 } 788} 789 790/** 791 * This general Blit implementation converts any source surface to an 792 * intermediate IntArgbPre surface, and then uses the more specific 793 * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate 794 * (premultiplied) surface down to OpenGL using simple blit. 795 */ 796class OGLGeneralBlit extends Blit { 797 798 private final Blit performop; 799 private WeakReference<SurfaceData> srcTmp; 800 801 OGLGeneralBlit(SurfaceType dstType, 802 CompositeType compType, 803 Blit performop) 804 { 805 super(SurfaceType.Any, compType, dstType); 806 this.performop = performop; 807 } 808 809 public synchronized void Blit(SurfaceData src, SurfaceData dst, 810 Composite comp, Region clip, 811 int sx, int sy, int dx, int dy, 812 int w, int h) 813 { 814 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 815 CompositeType.SrcNoEa, 816 SurfaceType.IntArgbPre); 817 818 SurfaceData cachedSrc = null; 819 if (srcTmp != null) { 820 // use cached intermediate surface, if available 821 cachedSrc = srcTmp.get(); 822 } 823 824 // convert source to IntArgbPre 825 src = convertFrom(convertsrc, src, sx, sy, w, h, 826 cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE); 827 828 // copy IntArgbPre intermediate surface to OpenGL surface 829 performop.Blit(src, dst, comp, clip, 830 0, 0, dx, dy, w, h); 831 832 if (src != cachedSrc) { 833 // cache the intermediate surface 834 srcTmp = new WeakReference<>(src); 835 } 836 } 837} 838 839/** 840 * This general TransformedBlit implementation converts any source surface to an 841 * intermediate IntArgbPre surface, and then uses the more specific 842 * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate 843 * (premultiplied) surface down to OpenGL using simple transformBlit. 844 */ 845final class OGLGeneralTransformedBlit extends TransformBlit { 846 847 private final TransformBlit performop; 848 private WeakReference<SurfaceData> srcTmp; 849 850 OGLGeneralTransformedBlit(final TransformBlit performop) { 851 super(SurfaceType.Any, CompositeType.AnyAlpha, 852 OGLSurfaceData.OpenGLSurface); 853 this.performop = performop; 854 } 855 856 @Override 857 public synchronized void Transform(SurfaceData src, SurfaceData dst, 858 Composite comp, Region clip, 859 AffineTransform at, int hint, int srcx, 860 int srcy, int dstx, int dsty, int width, 861 int height){ 862 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 863 CompositeType.SrcNoEa, 864 SurfaceType.IntArgbPre); 865 // use cached intermediate surface, if available 866 final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; 867 // convert source to IntArgbPre 868 src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, 869 BufferedImage.TYPE_INT_ARGB_PRE); 870 871 // transform IntArgbPre intermediate surface to OpenGL surface 872 performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, 873 width, height); 874 875 if (src != cachedSrc) { 876 // cache the intermediate surface 877 srcTmp = new WeakReference<>(src); 878 } 879 } 880} 881 882/** 883 * This general OGLAnyCompositeBlit implementation can convert any source/target 884 * surface to an intermediate surface using convertsrc/convertdst loops, applies 885 * necessary composite operation, and then uses convertresult loop to get the 886 * intermediate surface down to OpenGL. 887 */ 888final class OGLAnyCompositeBlit extends Blit { 889 890 private WeakReference<SurfaceData> dstTmp; 891 private WeakReference<SurfaceData> srcTmp; 892 private final Blit convertsrc; 893 private final Blit convertdst; 894 private final Blit convertresult; 895 896 OGLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst, 897 Blit convertresult) { 898 super(srctype, CompositeType.Any, OGLSurfaceData.OpenGLSurface); 899 this.convertsrc = convertsrc; 900 this.convertdst = convertdst; 901 this.convertresult = convertresult; 902 } 903 904 public synchronized void Blit(SurfaceData src, SurfaceData dst, 905 Composite comp, Region clip, 906 int sx, int sy, int dx, int dy, 907 int w, int h) 908 { 909 if (convertsrc != null) { 910 SurfaceData cachedSrc = null; 911 if (srcTmp != null) { 912 // use cached intermediate surface, if available 913 cachedSrc = srcTmp.get(); 914 } 915 // convert source to IntArgbPre 916 src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc, 917 BufferedImage.TYPE_INT_ARGB_PRE); 918 if (src != cachedSrc) { 919 // cache the intermediate surface 920 srcTmp = new WeakReference<>(src); 921 } 922 } 923 924 SurfaceData cachedDst = null; 925 926 if (dstTmp != null) { 927 // use cached intermediate surface, if available 928 cachedDst = dstTmp.get(); 929 } 930 931 // convert destination to IntArgbPre 932 SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h, 933 cachedDst, BufferedImage.TYPE_INT_ARGB_PRE); 934 Region bufferClip = 935 clip == null ? null : clip.getTranslatedRegion(-dx, -dy); 936 937 Blit performop = Blit.getFromCache(src.getSurfaceType(), 938 CompositeType.Any, dstBuffer.getSurfaceType()); 939 performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h); 940 941 if (dstBuffer != cachedDst) { 942 // cache the intermediate surface 943 dstTmp = new WeakReference<>(dstBuffer); 944 } 945 // now blit the buffer back to the destination 946 convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx, 947 dy, w, h); 948 } 949} 950