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