1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrCopySurfaceOp.h" 9#include "GrGpu.h" 10 11// returns true if the read/written rect intersects the src/dst and false if not. 12static bool clip_src_rect_and_dst_point(const GrSurfaceProxy* dst, 13 const GrSurfaceProxy* src, 14 const SkIRect& srcRect, 15 const SkIPoint& dstPoint, 16 SkIRect* clippedSrcRect, 17 SkIPoint* clippedDstPoint) { 18 *clippedSrcRect = srcRect; 19 *clippedDstPoint = dstPoint; 20 21 // clip the left edge to src and dst bounds, adjusting dstPoint if necessary 22 if (clippedSrcRect->fLeft < 0) { 23 clippedDstPoint->fX -= clippedSrcRect->fLeft; 24 clippedSrcRect->fLeft = 0; 25 } 26 if (clippedDstPoint->fX < 0) { 27 clippedSrcRect->fLeft -= clippedDstPoint->fX; 28 clippedDstPoint->fX = 0; 29 } 30 31 // clip the top edge to src and dst bounds, adjusting dstPoint if necessary 32 if (clippedSrcRect->fTop < 0) { 33 clippedDstPoint->fY -= clippedSrcRect->fTop; 34 clippedSrcRect->fTop = 0; 35 } 36 if (clippedDstPoint->fY < 0) { 37 clippedSrcRect->fTop -= clippedDstPoint->fY; 38 clippedDstPoint->fY = 0; 39 } 40 41 // clip the right edge to the src and dst bounds. 42 if (clippedSrcRect->fRight > src->width()) { 43 clippedSrcRect->fRight = src->width(); 44 } 45 if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { 46 clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; 47 } 48 49 // clip the bottom edge to the src and dst bounds. 50 if (clippedSrcRect->fBottom > src->height()) { 51 clippedSrcRect->fBottom = src->height(); 52 } 53 if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { 54 clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; 55 } 56 57 // The above clipping steps may have inverted the rect if it didn't intersect either the src or 58 // dst bounds. 59 return !clippedSrcRect->isEmpty(); 60} 61 62std::unique_ptr<GrOp> GrCopySurfaceOp::Make(GrSurfaceProxy* dstProxy, GrSurfaceProxy* srcProxy, 63 const SkIRect& srcRect, 64 const SkIPoint& dstPoint) { 65 SkASSERT(dstProxy); 66 SkASSERT(srcProxy); 67 if (GrPixelConfigIsSint(dstProxy->config()) != GrPixelConfigIsSint(srcProxy->config())) { 68 return nullptr; 69 } 70 SkIRect clippedSrcRect; 71 SkIPoint clippedDstPoint; 72 // If the rect is outside the srcProxy or dstProxy then we've already succeeded. 73 if (!clip_src_rect_and_dst_point(dstProxy, srcProxy, srcRect, dstPoint, 74 &clippedSrcRect, &clippedDstPoint)) { 75 return nullptr; 76 } 77 78 return std::unique_ptr<GrOp>(new GrCopySurfaceOp(dstProxy, srcProxy, 79 clippedSrcRect, clippedDstPoint)); 80} 81 82void GrCopySurfaceOp::onExecute(GrOpFlushState* state) { 83 SkASSERT(!state->commandBuffer()); 84 85 if (!fDst.get()->instantiate(state->resourceProvider()) || 86 !fSrc.get()->instantiate(state->resourceProvider())) { 87 return; 88 } 89 90 state->gpu()->copySurface(fDst.get()->priv().peekSurface(), 91 fSrc.get()->priv().peekSurface(), fSrcRect, fDstPoint); 92} 93