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 side D3D interface supports copying surface contents to 554 // ST_INT_ARGB, ST_INT_ARGB_PRE and other pixel formats 555 final int type = typeval == D3DSurfaceData.ST_INT_ARGB_PRE ? 556 BufferedImage.TYPE_INT_ARGB_PRE : 557 BufferedImage.TYPE_INT_ARGB; 558 559 src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); 560 561 // copy intermediate SW to destination SW using complex clip 562 final Blit performop = Blit.getFromCache(src.getSurfaceType(), 563 CompositeType.SrcNoEa, 564 dst.getSurfaceType()); 565 performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); 566 567 if (src != cachedSrc) { 568 // cache the intermediate surface 569 srcTmp = new WeakReference<>(src); 570 } 571 } 572 573 public void Blit(SurfaceData src, SurfaceData dst, 574 Composite comp, Region clip, 575 int sx, int sy, int dx, int dy, 576 int w, int h) 577 { 578 if (clip != null) { 579 clip = clip.getIntersectionXYWH(dx, dy, w, h); 580 // At the end this method will flush the RenderQueue, we should exit 581 // from it as soon as possible. 582 if (clip.isEmpty()) { 583 return; 584 } 585 586 // Adjust final dst(x,y) and src(x,y) based on the clip. The 587 // logic is that, when clip limits drawing on the destination, 588 // corresponding pixels from the src should be skipped. 589 sx += clip.getLoX() - dx; 590 sy += clip.getLoY() - dy; 591 dx = clip.getLoX(); 592 dy = clip.getLoY(); 593 w = clip.getWidth(); 594 h = clip.getHeight(); 595 596 // Check if the clip is Rectangular. For non-rectangular clips 597 // complexClipBlit will convert Surface To Sysmem and perform 598 // regular Blit. 599 if (!clip.isRectangular()) { 600 complexClipBlit(src, dst, comp, clip, 601 sx, sy, dx, dy, 602 w, h); 603 return; 604 } 605 } 606 607 D3DRenderQueue rq = D3DRenderQueue.getInstance(); 608 rq.lock(); 609 try { 610 // make sure the RenderQueue keeps a hard reference to the 611 // destination (sysmem) SurfaceData to prevent it from being 612 // disposed while the operation is processed on the QFT 613 rq.addReference(dst); 614 615 RenderBuffer buf = rq.getBuffer(); 616 D3DContext.setScratchSurface(((D3DSurfaceData)src).getContext()); 617 618 rq.ensureCapacityAndAlignment(48, 32); 619 buf.putInt(SURFACE_TO_SW_BLIT); 620 buf.putInt(sx).putInt(sy); 621 buf.putInt(dx).putInt(dy); 622 buf.putInt(w).putInt(h); 623 buf.putInt(typeval); 624 buf.putLong(src.getNativeOps()); 625 buf.putLong(dst.getNativeOps()); 626 627 // always flush immediately 628 rq.flushNow(); 629 } finally { 630 rq.unlock(); 631 } 632 } 633 } 634 635 class D3DSwToSurfaceBlit extends Blit { 636 637 private int typeval; 638 639 D3DSwToSurfaceBlit(SurfaceType srcType, int typeval) { 640 super(srcType, 641 CompositeType.AnyAlpha, 642 D3DSurfaceData.D3DSurface); 643 this.typeval = typeval; 644 } 645 646 public void Blit(SurfaceData src, SurfaceData dst, 647 Composite comp, Region clip, 648 int sx, int sy, int dx, int dy, int w, int h) 649 { 650 D3DBlitLoops.Blit(src, dst, 651 comp, clip, null, 652 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 653 sx, sy, sx+w, sy+h, 654 dx, dy, dx+w, dy+h, 655 typeval, false); 656 } 657 } 658 659 class D3DSwToSurfaceScale extends ScaledBlit { 660 661 private int typeval; 662 663 D3DSwToSurfaceScale(SurfaceType srcType, int typeval) { 664 super(srcType, 665 CompositeType.AnyAlpha, 666 D3DSurfaceData.D3DSurface); 667 this.typeval = typeval; 668 } 669 670 public void Scale(SurfaceData src, SurfaceData dst, 671 Composite comp, Region clip, 672 int sx1, int sy1, 673 int sx2, int sy2, 674 double dx1, double dy1, 675 double dx2, double dy2) 676 { 677 D3DBlitLoops.Blit(src, dst, 678 comp, clip, null, 679 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 680 sx1, sy1, sx2, sy2, 681 dx1, dy1, dx2, dy2, 682 typeval, false); 683 } 684 } 685 686 class D3DSwToSurfaceTransform extends TransformBlit { 687 688 private int typeval; 689 690 D3DSwToSurfaceTransform(SurfaceType srcType, int typeval) { 691 super(srcType, 692 CompositeType.AnyAlpha, 693 D3DSurfaceData.D3DSurface); 694 this.typeval = typeval; 695 } 696 697 public void Transform(SurfaceData src, SurfaceData dst, 698 Composite comp, Region clip, 699 AffineTransform at, int hint, 700 int sx, int sy, int dx, int dy, int w, int h) 701 { 702 D3DBlitLoops.Blit(src, dst, 703 comp, clip, at, hint, 704 sx, sy, sx+w, sy+h, 705 dx, dy, dx+w, dy+h, 706 typeval, false); 707 } 708 } 709 710 class D3DSwToTextureBlit extends Blit { 711 712 private int typeval; 713 714 D3DSwToTextureBlit(SurfaceType srcType, int typeval) { 715 super(srcType, 716 CompositeType.SrcNoEa, 717 D3DSurfaceData.D3DTexture); 718 this.typeval = typeval; 719 } 720 721 public void Blit(SurfaceData src, SurfaceData dst, 722 Composite comp, Region clip, 723 int sx, int sy, int dx, int dy, int w, int h) 724 { 725 D3DBlitLoops.Blit(src, dst, 726 comp, clip, null, 727 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 728 sx, sy, sx+w, sy+h, 729 dx, dy, dx+w, dy+h, 730 typeval, true); 731 } 732 } 733 734 class D3DTextureToSurfaceBlit extends Blit { 735 736 D3DTextureToSurfaceBlit() { 737 super(D3DSurfaceData.D3DTexture, 738 CompositeType.AnyAlpha, 739 D3DSurfaceData.D3DSurface); 740 } 741 742 public void Blit(SurfaceData src, SurfaceData dst, 743 Composite comp, Region clip, 744 int sx, int sy, int dx, int dy, int w, int h) 745 { 746 D3DBlitLoops.IsoBlit(src, dst, 747 null, null, 748 comp, clip, null, 749 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 750 sx, sy, sx+w, sy+h, 751 dx, dy, dx+w, dy+h, 752 true); 753 } 754 } 755 756 class D3DTextureToSurfaceScale extends ScaledBlit { 757 758 D3DTextureToSurfaceScale() { 759 super(D3DSurfaceData.D3DTexture, 760 CompositeType.AnyAlpha, 761 D3DSurfaceData.D3DSurface); 762 } 763 764 public void Scale(SurfaceData src, SurfaceData dst, 765 Composite comp, Region clip, 766 int sx1, int sy1, 767 int sx2, int sy2, 768 double dx1, double dy1, 769 double dx2, double dy2) 770 { 771 D3DBlitLoops.IsoBlit(src, dst, 772 null, null, 773 comp, clip, null, 774 AffineTransformOp.TYPE_NEAREST_NEIGHBOR, 775 sx1, sy1, sx2, sy2, 776 dx1, dy1, dx2, dy2, 777 true); 778 } 779 } 780 781 class D3DTextureToSurfaceTransform extends TransformBlit { 782 783 D3DTextureToSurfaceTransform() { 784 super(D3DSurfaceData.D3DTexture, 785 CompositeType.AnyAlpha, 786 D3DSurfaceData.D3DSurface); 787 } 788 789 public void Transform(SurfaceData src, SurfaceData dst, 790 Composite comp, Region clip, 791 AffineTransform at, int hint, 792 int sx, int sy, int dx, int dy, 793 int w, int h) 794 { 795 D3DBlitLoops.IsoBlit(src, dst, 796 null, null, 797 comp, clip, at, hint, 798 sx, sy, sx+w, sy+h, 799 dx, dy, dx+w, dy+h, 800 true); 801 } 802 } 803 804 /** 805 * This general Blit implementation converts any source surface to an 806 * intermediate IntArgbPre surface, and then uses the more specific 807 * IntArgbPre->D3DSurface/Texture loop to get the intermediate 808 * (premultiplied) surface down to D3D using simple blit. 809 */ 810 class D3DGeneralBlit extends Blit { 811 812 private final Blit performop; 813 private WeakReference<SurfaceData> srcTmp; 814 815 D3DGeneralBlit(SurfaceType dstType, 816 CompositeType compType, 817 Blit performop) 818 { 819 super(SurfaceType.Any, compType, dstType); 820 this.performop = performop; 821 } 822 823 public synchronized void Blit(SurfaceData src, SurfaceData dst, 824 Composite comp, Region clip, 825 int sx, int sy, int dx, int dy, 826 int w, int h) 827 { 828 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 829 CompositeType.SrcNoEa, 830 SurfaceType.IntArgbPre); 831 832 SurfaceData cachedSrc = null; 833 if (srcTmp != null) { 834 // use cached intermediate surface, if available 835 cachedSrc = srcTmp.get(); 836 } 837 838 // convert source to IntArgbPre 839 src = convertFrom(convertsrc, src, sx, sy, w, h, 840 cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE); 841 842 // copy IntArgbPre intermediate surface to D3D surface 843 performop.Blit(src, dst, comp, clip, 844 0, 0, dx, dy, w, h); 845 846 if (src != cachedSrc) { 847 // cache the intermediate surface 848 srcTmp = new WeakReference<>(src); 849 } 850 } 851 } 852 853 /** 854 * This general TransformedBlit implementation converts any source surface to an 855 * intermediate IntArgbPre surface, and then uses the more specific 856 * IntArgbPre->D3DSurface/Texture loop to get the intermediate 857 * (premultiplied) surface down to D3D using simple transformBlit. 858 */ 859 final class D3DGeneralTransformedBlit extends TransformBlit { 860 861 private final TransformBlit performop; 862 private WeakReference<SurfaceData> srcTmp; 863 864 D3DGeneralTransformedBlit(final TransformBlit performop) { 865 super(SurfaceType.Any, CompositeType.AnyAlpha, 866 D3DSurfaceData.D3DSurface); 867 this.performop = performop; 868 } 869 870 @Override 871 public synchronized void Transform(SurfaceData src, SurfaceData dst, 872 Composite comp, Region clip, 873 AffineTransform at, int hint, int srcx, 874 int srcy, int dstx, int dsty, int width, 875 int height){ 876 Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), 877 CompositeType.SrcNoEa, 878 SurfaceType.IntArgbPre); 879 // use cached intermediate surface, if available 880 final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; 881 // convert source to IntArgbPre 882 src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, 883 BufferedImage.TYPE_INT_ARGB_PRE); 884 885 // transform IntArgbPre intermediate surface to D3D surface 886 performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, 887 width, height); 888 889 if (src != cachedSrc) { 890 // cache the intermediate surface 891 srcTmp = new WeakReference<>(src); 892 } 893 } 894 } 895 896 /* 897 * The following classes prohibit copying D3DSurfaces to the screen 898 * (the D3D->sysmem->GDI path is known to be very very slow). 899 * 900 * Note: we used to disable hw acceleration for the surafce manager associated 901 * with the source surface in these loops but it proved to be too cautious. 902 * 903 * In most cases d3d->screen copy happens only during some transitional 904 * period where the accelerated destination surface is being recreated or 905 * restored (for example, when Swing's backbuffer VI is copied to the screen 906 * but the D3DScreenSurfaceManager couldn't restore its surface). 907 * 908 * An exception is if for some reason we could not enable accelerated on-screen 909 * rendering for this window for some permanent reason (like window being too 910 * small, or a present BufferStrategy). 911 * 912 * This meant that we'd disable hw acceleration after the first failure 913 * completely (at least until the src image is recreated which in case of 914 * Swing back-buffer happens only after resize). 915 * 916 * Now we delegate to the VISM to figure out if the acceleration needs to 917 * be disabled or if we can wait for a while until the onscreen accelerated 918 * can resume (by marking the source surface lost and making sure the 919 * VISM has a chance to use the backup surface). 920 * 921 */ 922 923 class D3DSurfaceToGDIWindowSurfaceBlit extends Blit { 924 925 D3DSurfaceToGDIWindowSurfaceBlit() { 926 super(D3DSurfaceData.D3DSurface, 927 CompositeType.AnyAlpha, 928 GDIWindowSurfaceData.AnyGdi); 929 } 930 @Override 931 public void Blit(SurfaceData src, SurfaceData dst, 932 Composite comp, Region clip, 933 int sx, int sy, int dx, int dy, int w, int h) 934 { 935 // see comment above 936 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 937 } 938 939 } 940 941 class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit { 942 943 D3DSurfaceToGDIWindowSurfaceScale() { 944 super(D3DSurfaceData.D3DSurface, 945 CompositeType.AnyAlpha, 946 GDIWindowSurfaceData.AnyGdi); 947 } 948 @Override 949 public void Scale(SurfaceData src, SurfaceData dst, 950 Composite comp, Region clip, 951 int sx1, int sy1, 952 int sx2, int sy2, 953 double dx1, double dy1, 954 double dx2, double dy2) 955 { 956 // see comment above 957 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 958 } 959 } 960 961 class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit { 962 963 D3DSurfaceToGDIWindowSurfaceTransform() { 964 super(D3DSurfaceData.D3DSurface, 965 CompositeType.AnyAlpha, 966 GDIWindowSurfaceData.AnyGdi); 967 } 968 @Override 969 public void Transform(SurfaceData src, SurfaceData dst, 970 Composite comp, Region clip, 971 AffineTransform at, int hint, 972 int sx, int sy, int dx, int dy, 973 int w, int h) 974 { 975 // see comment above 976 D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst); 977 } 978 }