1 /* 2 * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.java2d.d3d; 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 java.lang.annotation.Native; 36 import sun.java2d.ScreenUpdateManager; 37 import sun.java2d.SurfaceData; 38 import sun.java2d.loops.Blit; 39 import sun.java2d.loops.CompositeType; 40 import sun.java2d.loops.GraphicsPrimitive; 41 import sun.java2d.loops.GraphicsPrimitiveMgr; 42 import sun.java2d.loops.ScaledBlit; 43 import sun.java2d.loops.SurfaceType; 44 import sun.java2d.loops.TransformBlit; 45 import sun.java2d.pipe.Region; 46 import sun.java2d.pipe.RenderBuffer; 47 import sun.java2d.pipe.RenderQueue; 48 import static sun.java2d.pipe.BufferedOpCodes.*; 49 import sun.java2d.windows.GDIWindowSurfaceData; 50 51 final class D3DBlitLoops { 52 53 static void register() { 54 Blit blitIntArgbPreToSurface = 55 new D3DSwToSurfaceBlit(SurfaceType.IntArgbPre, 56 D3DSurfaceData.ST_INT_ARGB_PRE); 57 Blit blitIntArgbPreToTexture = 58 new D3DSwToTextureBlit(SurfaceType.IntArgbPre, 59 D3DSurfaceData.ST_INT_ARGB_PRE); 60 TransformBlit transformBlitIntArgbPreToSurface = 61 new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre, 62 D3DSurfaceData.ST_INT_ARGB_PRE); 63 GraphicsPrimitive[] primitives = { 64 // prevent D3DSurface -> Screen blits 65 new D3DSurfaceToGDIWindowSurfaceBlit(), 66 new D3DSurfaceToGDIWindowSurfaceScale(), 67 new D3DSurfaceToGDIWindowSurfaceTransform(), 68 69 // surface->surface ops 70 new D3DSurfaceToSurfaceBlit(), 71 new D3DSurfaceToSurfaceScale(), 72 new D3DSurfaceToSurfaceTransform(), 73 74 // render-to-texture surface->surface ops 75 new D3DRTTSurfaceToSurfaceBlit(), 76 new D3DRTTSurfaceToSurfaceScale(), 77 new D3DRTTSurfaceToSurfaceTransform(), 78 79 // surface->sw ops 80 new D3DSurfaceToSwBlit(SurfaceType.IntArgb, 81 D3DSurfaceData.ST_INT_ARGB), 82 83 // sw->surface ops 84 blitIntArgbPreToSurface, 85 new D3DSwToSurfaceBlit(SurfaceType.IntArgb, 86 D3DSurfaceData.ST_INT_ARGB), 87 new D3DSwToSurfaceBlit(SurfaceType.IntRgb, 88 D3DSurfaceData.ST_INT_RGB), 89 new D3DSwToSurfaceBlit(SurfaceType.IntBgr, 90 D3DSurfaceData.ST_INT_BGR), 91 new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr, 92 D3DSurfaceData.ST_3BYTE_BGR), 93 new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb, 94 D3DSurfaceData.ST_USHORT_565_RGB), 95 new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb, 96 D3DSurfaceData.ST_USHORT_555_RGB), 97 new D3DSwToSurfaceBlit(SurfaceType.ByteIndexed, 98 D3DSurfaceData.ST_BYTE_INDEXED), 99 // REMIND: we don't have a native sw loop to back this loop up 100 // new D3DSwToSurfaceBlit(SurfaceType.ByteIndexedBm, 101 // D3DSurfaceData.ST_BYTE_INDEXED_BM), 102 new D3DGeneralBlit(D3DSurfaceData.D3DSurface, 103 CompositeType.AnyAlpha, 104 blitIntArgbPreToSurface), 105 106 new D3DSwToSurfaceScale(SurfaceType.IntArgb, 107 D3DSurfaceData.ST_INT_ARGB), 108 new D3DSwToSurfaceScale(SurfaceType.IntArgbPre, 109 D3DSurfaceData.ST_INT_ARGB_PRE), 110 new D3DSwToSurfaceScale(SurfaceType.IntRgb, 111 D3DSurfaceData.ST_INT_RGB), 112 new D3DSwToSurfaceScale(SurfaceType.IntBgr, 113 D3DSurfaceData.ST_INT_BGR), 114 new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr, 115 D3DSurfaceData.ST_3BYTE_BGR), 116 new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb, 117 D3DSurfaceData.ST_USHORT_565_RGB), 118 new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb, 119 D3DSurfaceData.ST_USHORT_555_RGB), 120 new D3DSwToSurfaceScale(SurfaceType.ByteIndexed, 121 D3DSurfaceData.ST_BYTE_INDEXED), 122 // REMIND: we don't have a native sw loop to back this loop up 123 // new D3DSwToSurfaceScale(SurfaceType.ByteIndexedBm, 124 // D3DSurfaceData.ST_BYTE_INDEXED_BM), 125 126 new D3DSwToSurfaceTransform(SurfaceType.IntArgb, 127 D3DSurfaceData.ST_INT_ARGB), 128 new D3DSwToSurfaceTransform(SurfaceType.IntRgb, 129 D3DSurfaceData.ST_INT_RGB), 130 new D3DSwToSurfaceTransform(SurfaceType.IntBgr, 131 D3DSurfaceData.ST_INT_BGR), 132 new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr, 133 D3DSurfaceData.ST_3BYTE_BGR), 134 new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb, 135 D3DSurfaceData.ST_USHORT_565_RGB), 136 new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb, 137 D3DSurfaceData.ST_USHORT_555_RGB), 138 new D3DSwToSurfaceTransform(SurfaceType.ByteIndexed, 139 D3DSurfaceData.ST_BYTE_INDEXED), 140 // REMIND: we don't have a native sw loop to back this loop up 141 // new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm, 142 // D3DSurfaceData.ST_BYTE_INDEXED_BM), 143 transformBlitIntArgbPreToSurface, 144 145 new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface), 146 147 // texture->surface ops 148 new D3DTextureToSurfaceBlit(), 149 new D3DTextureToSurfaceScale(), 150 new D3DTextureToSurfaceTransform(), 151 152 // sw->texture ops 153 blitIntArgbPreToTexture, 154 new D3DSwToTextureBlit(SurfaceType.IntRgb, 155 D3DSurfaceData.ST_INT_RGB), 156 new D3DSwToTextureBlit(SurfaceType.IntArgb, 157 D3DSurfaceData.ST_INT_ARGB), 158 new D3DSwToTextureBlit(SurfaceType.IntBgr, 159 D3DSurfaceData.ST_INT_BGR), 160 new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr, 161 D3DSurfaceData.ST_3BYTE_BGR), 162 new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb, 163 D3DSurfaceData.ST_USHORT_565_RGB), 164 new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb, 165 D3DSurfaceData.ST_USHORT_555_RGB), 166 new D3DSwToTextureBlit(SurfaceType.ByteIndexed, 167 D3DSurfaceData.ST_BYTE_INDEXED), 168 // REMIND: we don't have a native sw loop to back this loop up 169 // new D3DSwToTextureBlit(SurfaceType.ByteIndexedBm, 170 // D3DSurfaceData.ST_BYTE_INDEXED_BM), 171 new D3DGeneralBlit(D3DSurfaceData.D3DTexture, 172 CompositeType.SrcNoEa, 173 blitIntArgbPreToTexture), 174 }; 175 GraphicsPrimitiveMgr.register(primitives); 176 } 177 178 /** 179 * The following offsets are used to pack the parameters in 180 * createPackedParams(). (They are also used at the native level when 181 * unpacking the params.) 182 */ 183 @Native private static final int OFFSET_SRCTYPE = 16; 184 @Native private static final int OFFSET_HINT = 8; 185 @Native private static final int OFFSET_TEXTURE = 3; 186 @Native private static final int OFFSET_RTT = 2; 187 @Native private static final int OFFSET_XFORM = 1; 188 @Native private static final int OFFSET_ISOBLIT = 0; 189 190 /** 191 * Packs the given parameters into a single int value in order to save 192 * space on the rendering queue. 193 */ 194 private static int createPackedParams(boolean isoblit, boolean texture, 195 boolean rtt, boolean xform, 196 int hint, int srctype) 197 { 198 return 199 ((srctype << OFFSET_SRCTYPE) | 200 (hint << OFFSET_HINT ) | 201 ((texture ? 1 : 0) << OFFSET_TEXTURE) | 202 ((rtt ? 1 : 0) << OFFSET_RTT ) | 203 ((xform ? 1 : 0) << OFFSET_XFORM ) | 204 ((isoblit ? 1 : 0) << OFFSET_ISOBLIT)); 205 } 206 207 /** 208 * Enqueues a BLIT operation with the given parameters. Note that the 209 * RenderQueue lock must be held before calling this method. 210 */ 211 private static void enqueueBlit(RenderQueue rq, 212 SurfaceData src, SurfaceData dst, 213 int packedParams, 214 int sx1, int sy1, 215 int sx2, int sy2, 216 double dx1, double dy1, 217 double dx2, double dy2) 218 { 219 // assert rq.lock.isHeldByCurrentThread(); 220 RenderBuffer buf = rq.getBuffer(); 221 rq.ensureCapacityAndAlignment(72, 24); 222 buf.putInt(BLIT); 223 buf.putInt(packedParams); 224 buf.putInt(sx1).putInt(sy1); 225 buf.putInt(sx2).putInt(sy2); 226 buf.putDouble(dx1).putDouble(dy1); 227 buf.putDouble(dx2).putDouble(dy2); 228 buf.putLong(src.getNativeOps()); 229 buf.putLong(dst.getNativeOps()); 230 } 231 232 static void Blit(SurfaceData srcData, SurfaceData dstData, 233 Composite comp, Region clip, 234 AffineTransform xform, int hint, 235 int sx1, int sy1, 236 int sx2, int sy2, 237 double dx1, double dy1, 238 double dx2, double dy2, 239 int srctype, boolean texture) 240 { 241 int ctxflags = 0; 242 if (srcData.getTransparency() == Transparency.OPAQUE) { 243 ctxflags |= D3DContext.SRC_IS_OPAQUE; 244 } 245 246 D3DSurfaceData d3dDst = (D3DSurfaceData)dstData; 247 D3DRenderQueue rq = D3DRenderQueue.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 if (texture) { 256 // make sure we have a current context before uploading 257 // the sysmem data to the texture object 258 D3DContext.setScratchSurface(d3dDst.getContext()); 259 } else { 260 D3DContext.validateContext(d3dDst, d3dDst, 261 clip, comp, xform, null, null, 262 ctxflags); 263 } 264 265 int packedParams = createPackedParams(false, texture, 266 false, xform != null, 267 hint, srctype); 268 enqueueBlit(rq, srcData, dstData, 269 packedParams, 270 sx1, sy1, sx2, sy2, 271 dx1, dy1, dx2, dy2); 272 273 // always flush immediately, since we (currently) have no means 274 // of tracking changes to the system memory surface 275 rq.flushNow(); 276 } finally { 277 rq.unlock(); 278 } 279 280 if (d3dDst.getType() == D3DSurfaceData.WINDOW) { 281 // flush immediately when copying to the screen to improve 282 // responsiveness of applications using VI or BI backbuffers 283 D3DScreenUpdateManager mgr = 284 (D3DScreenUpdateManager)ScreenUpdateManager.getInstance(); 285 mgr.runUpdateNow(); 286 } 287 } 288 289 /** 290 * Note: The srcImg and biop parameters are only used when invoked 291 * from the D3DBufImgOps.renderImageWithOp() method; in all other cases, 292 * this method can be called with null values for those two parameters, 293 * and they will be effectively ignored. 294 */ 295 static void IsoBlit(SurfaceData srcData, SurfaceData dstData, 296 BufferedImage srcImg, BufferedImageOp biop, 297 Composite comp, Region clip, 298 AffineTransform xform, int hint, 299 int sx1, int sy1, 300 int sx2, int sy2, 301 double dx1, double dy1, 302 double dx2, double dy2, 303 boolean texture) 304 { 305 int ctxflags = 0; 306 if (srcData.getTransparency() == Transparency.OPAQUE) { 307 ctxflags |= D3DContext.SRC_IS_OPAQUE; 308 } 309 310 D3DSurfaceData d3dDst = (D3DSurfaceData)dstData; 311 D3DRenderQueue rq = D3DRenderQueue.getInstance(); 312 boolean rtt = false; 313 rq.lock(); 314 try { 315 D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData; 316 int srctype = d3dSrc.getType(); 317 D3DSurfaceData srcCtxData = d3dSrc; 318 if (srctype == D3DSurfaceData.TEXTURE) { 319 rtt = false; 320 } else { 321 // the source is a backbuffer, or render-to-texture 322 // surface; we set rtt to true to differentiate this kind 323 // of surface from a regular texture object 324 rtt = true; 325 } 326 327 D3DContext.validateContext(srcCtxData, d3dDst, 328 clip, comp, xform, null, null, 329 ctxflags); 330 331 if (biop != null) { 332 D3DBufImgOps.enableBufImgOp(rq, d3dSrc, srcImg, biop); 333 } 334 335 int packedParams = createPackedParams(true, texture, 336 rtt, xform != null, 337 hint, 0 /*unused*/); 338 enqueueBlit(rq, srcData, dstData, 339 packedParams, 340 sx1, sy1, sx2, sy2, 341 dx1, dy1, dx2, dy2); 342 343 if (biop != null) { 344 D3DBufImgOps.disableBufImgOp(rq, biop); 345 } 346 } finally { 347 rq.unlock(); 348 } 349 350 if (rtt && (d3dDst.getType() == D3DSurfaceData.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 D3DScreenUpdateManager mgr = 355 (D3DScreenUpdateManager)ScreenUpdateManager.getInstance(); 356 mgr.runUpdateNow(); 357 } 358 } 359 } 360 361 class D3DSurfaceToSurfaceBlit extends Blit { 362 363 D3DSurfaceToSurfaceBlit() { 364 super(D3DSurfaceData.D3DSurface, 365 CompositeType.AnyAlpha, 366 D3DSurfaceData.D3DSurface); 367 } 368 369 public void Blit(SurfaceData src, SurfaceData dst, 370 Composite comp, Region clip, 371 int sx, int sy, int dx, int dy, int w, int h) 372 { 373 D3DBlitLoops.IsoBlit(src, dst, 374 null, null, 375 comp, clip, null, 376 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 377 sx, sy, sx+w, sy+h, 378 dx, dy, dx+w, dy+h, 379 false); 380 } 381 } 382 383 class D3DSurfaceToSurfaceScale extends ScaledBlit { 384 385 D3DSurfaceToSurfaceScale() { 386 super(D3DSurfaceData.D3DSurface, 387 CompositeType.AnyAlpha, 388 D3DSurfaceData.D3DSurface); 389 } 390 391 public void Scale(SurfaceData src, SurfaceData dst, 392 Composite comp, Region clip, 393 int sx1, int sy1, 394 int sx2, int sy2, 395 double dx1, double dy1, 396 double dx2, double dy2) 397 { 398 D3DBlitLoops.IsoBlit(src, dst, 399 null, null, 400 comp, clip, null, 401 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 402 sx1, sy1, sx2, sy2, 403 dx1, dy1, dx2, dy2, 404 false); 405 } 406 } 407 408 class D3DSurfaceToSurfaceTransform extends TransformBlit { 409 410 D3DSurfaceToSurfaceTransform() { 411 super(D3DSurfaceData.D3DSurface, 412 CompositeType.AnyAlpha, 413 D3DSurfaceData.D3DSurface); 414 } 415 416 public void Transform(SurfaceData src, SurfaceData dst, 417 Composite comp, Region clip, 418 AffineTransform at, int hint, 419 int sx, int sy, int dx, int dy, 420 int w, int h) 421 { 422 D3DBlitLoops.IsoBlit(src, dst, 423 null, null, 424 comp, clip, at, hint, 425 sx, sy, sx+w, sy+h, 426 dx, dy, dx+w, dy+h, 427 false); 428 } 429 } 430 431 class D3DRTTSurfaceToSurfaceBlit extends Blit { 432 433 D3DRTTSurfaceToSurfaceBlit() { 434 super(D3DSurfaceData.D3DSurfaceRTT, 435 CompositeType.AnyAlpha, 436 D3DSurfaceData.D3DSurface); 437 } 438 439 public void Blit(SurfaceData src, SurfaceData dst, 440 Composite comp, Region clip, 441 int sx, int sy, int dx, int dy, int w, int h) 442 { 443 D3DBlitLoops.IsoBlit(src, dst, 444 null, null, 445 comp, clip, null, 446 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 447 sx, sy, sx+w, sy+h, 448 dx, dy, dx+w, dy+h, 449 true); 450 } 451 } 452 453 class D3DRTTSurfaceToSurfaceScale extends ScaledBlit { 454 455 D3DRTTSurfaceToSurfaceScale() { 456 super(D3DSurfaceData.D3DSurfaceRTT, 457 CompositeType.AnyAlpha, 458 D3DSurfaceData.D3DSurface); 459 } 460 461 public void Scale(SurfaceData src, SurfaceData dst, 462 Composite comp, Region clip, 463 int sx1, int sy1, 464 int sx2, int sy2, 465 double dx1, double dy1, 466 double dx2, double dy2) 467 { 468 D3DBlitLoops.IsoBlit(src, dst, 469 null, null, 470 comp, clip, null, 471 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 472 sx1, sy1, sx2, sy2, 473 dx1, dy1, dx2, dy2, 474 true); 475 } 476 } 477 478 class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { 479 480 D3DRTTSurfaceToSurfaceTransform() { 481 super(D3DSurfaceData.D3DSurfaceRTT, 482 CompositeType.AnyAlpha, 483 D3DSurfaceData.D3DSurface); 484 } 485 486 public void Transform(SurfaceData src, SurfaceData dst, 487 Composite comp, Region clip, 488 AffineTransform at, int hint, 489 int sx, int sy, int dx, int dy, int w, int h) 490 { 491 D3DBlitLoops.IsoBlit(src, dst, 492 null, null, 493 comp, clip, at, hint, 494 sx, sy, sx+w, sy+h, 495 dx, dy, dx+w, dy+h, 496 true); 497 } 498 } 499 500 class D3DSurfaceToSwBlit extends Blit { 501 502 private int typeval; 503 private WeakReference<SurfaceData> srcTmp; 504 505 // REMIND: destination will actually be opaque/premultiplied... 506 D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { 507 super(D3DSurfaceData.D3DSurface, 508 CompositeType.SrcNoEa, 509 dstType); 510 this.typeval = typeval; 511 } 512 513 /* 514 * Clip value is ignored in D3D SurfaceToSw blit. 515 * Root Cause: The native interfaces to D3D use StretchRect API followed 516 * by custom copy of pixels from Surface to Sysmem. As a result, clipping 517 * in D3DSurfaceToSw works 'only' for Rect clips, provided, proper srcX, 518 * srcY, dstX, dstY, width and height are passed to native interfaces. 519 * Non rect clips (For example: Shape clips) are ignored completely. 520 * 521 * Solution: There are three solutions possible to fix this issue. 522 * 1. Convert the entire Surface to Sysmem and perform regular Blit. 523 * An optimized version of this is to take up the conversion only 524 * when Shape clips are needed. Existing native interface will suffice 525 * for supporting Rect clips. 526 * 2. With help of existing classes we could perform SwToSurface, 527 * SurfaceToSurface (implements clip) and SurfaceToSw (complete copy) 528 * in order. 529 * 3. Modify the native D3D interface to accept clip and perform same logic 530 * as the second approach but at native side. 531 * 532 * Upon multiple experiments, the first approach has been found to be 533 * faster than the others as it deploys 1-draw/copy operation for rect clip 534 * and 2-draw/copy operations for shape clip compared to 3-draws/copy 535 * operations deployed by the remaining approaches. 536 * 537 * complexClipBlit method helps to convert or copy the contents from 538 * D3DSurface onto Sysmem and perform a regular Blit with the clip 539 * information as required. This method is used when non-rectangular 540 * clip is needed. 541 */ 542 private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, 543 Composite comp, Region clip, 544 int sx, int sy, int dx, int dy, 545 int w, int h) { 546 SurfaceData cachedSrc = null; 547 if (srcTmp != null) { 548 // use cached intermediate surface, if available 549 cachedSrc = srcTmp.get(); 550 } 551 552 // Type- indicates the pixel format of Sysmem based BufferedImage. 553 // Native d3d interfaces support on the fly conversion of pixels from 554 // d3d surface to destination sysmem memory of type IntARGB only. 555 final int type = BufferedImage.TYPE_INT_ARGB; 556 src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); 557 558 // copy intermediate SW to destination SW using complex clip 559 final Blit performop = Blit.getFromCache(src.getSurfaceType(), 560 CompositeType.SrcNoEa, 561 dst.getSurfaceType()); 562 performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); 563 564 if (src != cachedSrc) { 565 // cache the intermediate surface 566 srcTmp = new WeakReference<>(src); 567 } 568 } 569 570 public void Blit(SurfaceData src, SurfaceData dst, 571 Composite comp, Region clip, 572 int sx, int sy, int dx, int dy, 573 int w, int h) 574 { 575 if (clip != null) { 576 clip = clip.getIntersectionXYWH(dx, dy, w, h); 577 // At the end this method will flush the RenderQueue, we should exit 578 // from it as soon as possible. 579 if (clip.isEmpty()) { 580 return; 581 } 582 583 // Adjust final dst(x,y) and src(x,y) based on the clip. The 584 // logic is that, when clip limits drawing on the destination, 585 // corresponding pixels from the src should be skipped. 586 sx += clip.getLoX() - dx; 587 sy += clip.getLoY() - dy; 588 dx = clip.getLoX(); 589 dy = clip.getLoY(); 590 w = clip.getWidth(); 591 h = clip.getHeight(); 592 593 // Check if the clip is Rectangular. For non-rectangular clips 594 // complexClipBlit will convert Surface To Sysmem and perform 595 // regular Blit. 596 if (!clip.isRectangular()) { 597 complexClipBlit(src, dst, comp, clip, 598 sx, sy, dx, dy, 599 w, h); 600 return; 601 } 602 } 603 604 D3DRenderQueue rq = D3DRenderQueue.getInstance(); 605 rq.lock(); 606 try { 607 // make sure the RenderQueue keeps a hard reference to the 608 // destination (sysmem) SurfaceData to prevent it from being 609 // disposed while the operation is processed on the QFT 610 rq.addReference(dst); 611 612 RenderBuffer buf = rq.getBuffer(); 613 D3DContext.setScratchSurface(((D3DSurfaceData)src).getContext()); 614 615 rq.ensureCapacityAndAlignment(48, 32); 616 buf.putInt(SURFACE_TO_SW_BLIT); 617 buf.putInt(sx).putInt(sy); 618 buf.putInt(dx).putInt(dy); 619 buf.putInt(w).putInt(h); 620 buf.putInt(typeval); 621 buf.putLong(src.getNativeOps()); 622 buf.putLong(dst.getNativeOps()); 623 624 // always flush immediately 625 rq.flushNow(); 626 } finally { 627 rq.unlock(); 628 } 629 } 630 } 631 632 class D3DSwToSurfaceBlit extends Blit { 633 634 private int typeval; 635 636 D3DSwToSurfaceBlit(SurfaceType srcType, int typeval) { 637 super(srcType, 638 CompositeType.AnyAlpha, 639 D3DSurfaceData.D3DSurface); 640 this.typeval = typeval; 641 } 642 643 public void Blit(SurfaceData src, SurfaceData dst, 644 Composite comp, Region clip, 645 int sx, int sy, int dx, int dy, int w, int h) 646 { 647 D3DBlitLoops.Blit(src, dst, 648 comp, clip, null, 649 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 650 sx, sy, sx+w, sy+h, 651 dx, dy, dx+w, dy+h, 652 typeval, false); 653 } 654 } 655 656 class D3DSwToSurfaceScale extends ScaledBlit { 657 658 private int typeval; 659 660 D3DSwToSurfaceScale(SurfaceType srcType, int typeval) { 661 super(srcType, 662 CompositeType.AnyAlpha, 663 D3DSurfaceData.D3DSurface); 664 this.typeval = typeval; 665 } 666 667 public void Scale(SurfaceData src, SurfaceData dst, 668 Composite comp, Region clip, 669 int sx1, int sy1, 670 int sx2, int sy2, 671 double dx1, double dy1, 672 double dx2, double dy2) 673 { 674 D3DBlitLoops.Blit(src, dst, 675 comp, clip, null, 676 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 677 sx1, sy1, sx2, sy2, 678 dx1, dy1, dx2, dy2, 679 typeval, false); 680 } 681 } 682 683 class D3DSwToSurfaceTransform extends TransformBlit { 684 685 private int typeval; 686 687 D3DSwToSurfaceTransform(SurfaceType srcType, int typeval) { 688 super(srcType, 689 CompositeType.AnyAlpha, 690 D3DSurfaceData.D3DSurface); 691 this.typeval = typeval; 692 } 693 694 public void Transform(SurfaceData src, SurfaceData dst, 695 Composite comp, Region clip, 696 AffineTransform at, int hint, 697 int sx, int sy, int dx, int dy, int w, int h) 698 { 699 D3DBlitLoops.Blit(src, dst, 700 comp, clip, at, hint, 701 sx, sy, sx+w, sy+h, 702 dx, dy, dx+w, dy+h, 703 typeval, false); 704 } 705 } 706 707 class D3DSwToTextureBlit extends Blit { 708 709 private int typeval; 710 711 D3DSwToTextureBlit(SurfaceType srcType, int typeval) { 712 super(srcType, 713 CompositeType.SrcNoEa, 714 D3DSurfaceData.D3DTexture); 715 this.typeval = typeval; 716 } 717 718 public void Blit(SurfaceData src, SurfaceData dst, 719 Composite comp, Region clip, 720 int sx, int sy, int dx, int dy, int w, int h) 721 { 722 D3DBlitLoops.Blit(src, dst, 723 comp, clip, null, 724 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 725 sx, sy, sx+w, sy+h, 726 dx, dy, dx+w, dy+h, 727 typeval, true); 728 } 729 } 730 731 class D3DTextureToSurfaceBlit extends Blit { 732 733 D3DTextureToSurfaceBlit() { 734 super(D3DSurfaceData.D3DTexture, 735 CompositeType.AnyAlpha, 736 D3DSurfaceData.D3DSurface); 737 } 738 739 public void Blit(SurfaceData src, SurfaceData dst, 740 Composite comp, Region clip, 741 int sx, int sy, int dx, int dy, int w, int h) 742 { 743 D3DBlitLoops.IsoBlit(src, dst, 744 null, null, 745 comp, clip, null, 746 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 747 sx, sy, sx+w, sy+h, 748 dx, dy, dx+w, dy+h, 749 true); 750 } 751 } 752 753 class D3DTextureToSurfaceScale extends ScaledBlit { 754 755 D3DTextureToSurfaceScale() { 756 super(D3DSurfaceData.D3DTexture, 757 CompositeType.AnyAlpha, 758 D3DSurfaceData.D3DSurface); 759 } 760 761 public void Scale(SurfaceData src, SurfaceData dst, 762 Composite comp, Region clip, 763 int sx1, int sy1, 764 int sx2, int sy2, 765 double dx1, double dy1, 766 double dx2, double dy2) 767 { 768 D3DBlitLoops.IsoBlit(src, dst, 769 null, null, 770 comp, clip, null, 771 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 772 sx1, sy1, sx2, sy2, 773 dx1, dy1, dx2, dy2, 774 true); 775 } 776 } 777 778 class D3DTextureToSurfaceTransform extends TransformBlit { 779 780 D3DTextureToSurfaceTransform() { 781 super(D3DSurfaceData.D3DTexture, 782 CompositeType.AnyAlpha, 783 D3DSurfaceData.D3DSurface); 784 } 785 786 public void Transform(SurfaceData src, SurfaceData dst, 787 Composite comp, Region clip, 788 AffineTransform at, int hint, 789 int sx, int sy, int dx, int dy, 790 int w, int h) 791 { 792 D3DBlitLoops.IsoBlit(src, dst, 793 null, null, 794 comp, clip, at, hint, 795 sx, sy, sx+w, sy+h, 796 dx, dy, dx+w, dy+h, 797 true); 798 } 799 } 800 801 /** 802 * This general Blit implementation converts any source surface to an 803 * intermediate IntArgbPre surface, and then uses the more specific 804 * IntArgbPre->D3DSurface/Texture loop to get the intermediate 805 * (premultiplied) surface down to D3D using simple blit. 806 */ 807 class D3DGeneralBlit extends Blit { 808 809 private final Blit performop; 810 private WeakReference<SurfaceData> srcTmp; 811 812 D3DGeneralBlit(SurfaceType dstType, 813 CompositeType compType, 814 Blit performop) 815 { 816 super(SurfaceType.Any, compType, dstType); 817 this.performop = performop; 818 } 819 820 public synchronized void Blit(SurfaceData src, SurfaceData dst, 821 Composite comp, Region clip, 822 int sx, int sy, int dx, int dy, 823 int w, int h) 824 { 825 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 826 CompositeType.SrcNoEa, 827 SurfaceType.IntArgbPre); 828 829 SurfaceData cachedSrc = null; 830 if (srcTmp != null) { 831 // use cached intermediate surface, if available 832 cachedSrc = srcTmp.get(); 833 } 834 835 // convert source to IntArgbPre 836 src = convertFrom(convertsrc, src, sx, sy, w, h, 837 cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE); 838 839 // copy IntArgbPre intermediate surface to D3D surface 840 performop.Blit(src, dst, comp, clip, 841 0, 0, dx, dy, w, h); 842 843 if (src != cachedSrc) { 844 // cache the intermediate surface 845 srcTmp = new WeakReference<>(src); 846 } 847 } 848 } 849 850 /** 851 * This general TransformedBlit implementation converts any source surface to an 852 * intermediate IntArgbPre surface, and then uses the more specific 853 * IntArgbPre->D3DSurface/Texture loop to get the intermediate 854 * (premultiplied) surface down to D3D using simple transformBlit. 855 */ 856 final class D3DGeneralTransformedBlit extends TransformBlit { 857 858 private final TransformBlit performop; 859 private WeakReference<SurfaceData> srcTmp; 860 861 D3DGeneralTransformedBlit(final TransformBlit performop) { 862 super(SurfaceType.Any, CompositeType.AnyAlpha, 863 D3DSurfaceData.D3DSurface); 864 this.performop = performop; 865 } 866 867 @Override 868 public synchronized void Transform(SurfaceData src, SurfaceData dst, 869 Composite comp, Region clip, 870 AffineTransform at, int hint, int srcx, 871 int srcy, int dstx, int dsty, int width, 872 int height){ 873 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 874 CompositeType.SrcNoEa, 875 SurfaceType.IntArgbPre); 876 // use cached intermediate surface, if available 877 final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; 878 // convert source to IntArgbPre 879 src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, 880 BufferedImage.TYPE_INT_ARGB_PRE); 881 882 // transform IntArgbPre intermediate surface to D3D surface 883 performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, 884 width, height); 885 886 if (src != cachedSrc) { 887 // cache the intermediate surface 888 srcTmp = new WeakReference<>(src); 889 } 890 } 891 } 892 893 /* 894 * The following classes prohibit copying D3DSurfaces to the screen 895 * (the D3D->sysmem->GDI path is known to be very very slow). 896 * 897 * Note: we used to disable hw acceleration for the surafce manager associated 898 * with the source surface in these loops but it proved to be too cautious. 899 * 900 * In most cases d3d->screen copy happens only during some transitional 901 * period where the accelerated destination surface is being recreated or 902 * restored (for example, when Swing's backbuffer VI is copied to the screen 903 * but the D3DScreenSurfaceManager couldn't restore its surface). 904 * 905 * An exception is if for some reason we could not enable accelerated on-screen 906 * rendering for this window for some permanent reason (like window being too 907 * small, or a present BufferStrategy). 908 * 909 * This meant that we'd disable hw acceleration after the first failure 910 * completely (at least until the src image is recreated which in case of 911 * Swing back-buffer happens only after resize). 912 * 913 * Now we delegate to the VISM to figure out if the acceleration needs to 914 * be disabled or if we can wait for a while until the onscreen accelerated 915 * can resume (by marking the source surface lost and making sure the 916 * VISM has a chance to use the backup surface). 917 * 918 */ 919 920 class D3DSurfaceToGDIWindowSurfaceBlit extends Blit { 921 922 D3DSurfaceToGDIWindowSurfaceBlit() { 923 super(D3DSurfaceData.D3DSurface, 924 CompositeType.AnyAlpha, 925 GDIWindowSurfaceData.AnyGdi); 926 } 927 @Override 928 public void Blit(SurfaceData src, SurfaceData dst, 929 Composite comp, Region clip, 930 int sx, int sy, int dx, int dy, int w, int h) 931 { 932 // see comment above 933 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 934 } 935 936 } 937 938 class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit { 939 940 D3DSurfaceToGDIWindowSurfaceScale() { 941 super(D3DSurfaceData.D3DSurface, 942 CompositeType.AnyAlpha, 943 GDIWindowSurfaceData.AnyGdi); 944 } 945 @Override 946 public void Scale(SurfaceData src, SurfaceData dst, 947 Composite comp, Region clip, 948 int sx1, int sy1, 949 int sx2, int sy2, 950 double dx1, double dy1, 951 double dx2, double dy2) 952 { 953 // see comment above 954 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 955 } 956 } 957 958 class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit { 959 960 D3DSurfaceToGDIWindowSurfaceTransform() { 961 super(D3DSurfaceData.D3DSurface, 962 CompositeType.AnyAlpha, 963 GDIWindowSurfaceData.AnyGdi); 964 } 965 @Override 966 public void Transform(SurfaceData src, SurfaceData dst, 967 Composite comp, Region clip, 968 AffineTransform at, int hint, 969 int sx, int sy, int dx, int dy, 970 int w, int h) 971 { 972 // see comment above 973 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 974 } 975 }