498 } |
498 } |
499 |
499 |
500 class D3DSurfaceToSwBlit extends Blit { |
500 class D3DSurfaceToSwBlit extends Blit { |
501 |
501 |
502 private int typeval; |
502 private int typeval; |
|
503 private WeakReference<SurfaceData> srcTmp; |
503 |
504 |
504 // REMIND: destination will actually be opaque/premultiplied... |
505 // REMIND: destination will actually be opaque/premultiplied... |
505 D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { |
506 D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { |
506 super(D3DSurfaceData.D3DSurface, |
507 super(D3DSurfaceData.D3DSurface, |
507 CompositeType.SrcNoEa, |
508 CompositeType.SrcNoEa, |
508 dstType); |
509 dstType); |
509 this.typeval = typeval; |
510 this.typeval = typeval; |
510 } |
511 } |
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 |
512 public void Blit(SurfaceData src, SurfaceData dst, |
570 public void Blit(SurfaceData src, SurfaceData dst, |
513 Composite comp, Region clip, |
571 Composite comp, Region clip, |
514 int sx, int sy, int dx, int dy, |
572 int sx, int sy, int dx, int dy, |
515 int w, int h) |
573 int w, int h) |
516 { |
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 |
517 D3DRenderQueue rq = D3DRenderQueue.getInstance(); |
604 D3DRenderQueue rq = D3DRenderQueue.getInstance(); |
518 rq.lock(); |
605 rq.lock(); |
519 try { |
606 try { |
520 // make sure the RenderQueue keeps a hard reference to the |
607 // make sure the RenderQueue keeps a hard reference to the |
521 // destination (sysmem) SurfaceData to prevent it from being |
608 // destination (sysmem) SurfaceData to prevent it from being |