• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 <initializer_list>
9 #include "Test.h"
10 
11 #if SK_SUPPORT_GPU
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrResourceProvider.h"
15 #include "GrSurfaceContext.h"
16 #include "GrSurfaceProxy.h"
17 #include "GrTextureProxy.h"
18 
19 #include "SkUtils.h"
20 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface,reporter,ctxInfo)21 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
22     GrContext* context = ctxInfo.grContext();
23     static const int kW = 10;
24     static const int kH = 10;
25     static const size_t kRowBytes = sizeof(uint32_t) * kW;
26 
27     GrSurfaceDesc baseDesc;
28     baseDesc.fConfig = kRGBA_8888_GrPixelConfig;
29     baseDesc.fWidth = kW;
30     baseDesc.fHeight = kH;
31 
32     SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
33     for (int i = 0; i < kW * kH; ++i) {
34         srcPixels.get()[i] = i;
35     }
36 
37     SkAutoTMalloc<uint32_t> dstPixels(kW * kH);
38     for (int i = 0; i < kW * kH; ++i) {
39         dstPixels.get()[i] = ~i;
40     }
41 
42     static const SkIRect kSrcRects[] {
43         { 0,  0, kW  , kH  },
44         {-1, -1, kW+1, kH+1},
45         { 1,  1, kW-1, kH-1},
46         { 5,  5, 6   , 6   },
47     };
48 
49     static const SkIPoint kDstPoints[] {
50         { 0   ,  0   },
51         { 1   ,  1   },
52         { kW/2,  kH/4},
53         { kW-1,  kH-1},
54         { kW  ,  kH  },
55         { kW+1,  kH+2},
56         {-1   , -1   },
57     };
58 
59     const SkImageInfo ii = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
60 
61     SkAutoTMalloc<uint32_t> read(kW * kH);
62 
63     for (auto sOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
64         for (auto dOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
65             for (auto sFlags: {kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags}) {
66                 for (auto dFlags: {kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags}) {
67                     for (auto srcRect : kSrcRects) {
68                         for (auto dstPoint : kDstPoints) {
69                             GrSurfaceDesc srcDesc = baseDesc;
70                             srcDesc.fOrigin = sOrigin;
71                             srcDesc.fFlags = sFlags;
72                             GrSurfaceDesc dstDesc = baseDesc;
73                             dstDesc.fOrigin = dOrigin;
74                             dstDesc.fFlags = dFlags;
75 
76                             sk_sp<GrTextureProxy> src(GrSurfaceProxy::MakeDeferred(
77                                                                     context->resourceProvider(),
78                                                                     srcDesc, SkBudgeted::kNo,
79                                                                     srcPixels.get(),
80                                                                     kRowBytes));
81 
82                             sk_sp<GrTextureProxy> dst(GrSurfaceProxy::MakeDeferred(
83                                                                     context->resourceProvider(),
84                                                                     dstDesc, SkBudgeted::kNo,
85                                                                     dstPixels.get(),
86                                                                     kRowBytes));
87                             if (!src || !dst) {
88                                 ERRORF(reporter,
89                                        "Could not create surfaces for copy surface test.");
90                                 continue;
91                             }
92 
93                             sk_sp<GrSurfaceContext> dstContext =
94                                    context->contextPriv().makeWrappedSurfaceContext(std::move(dst),
95                                                                                     nullptr);
96 
97                             bool result = dstContext->copy(src.get(), srcRect, dstPoint);
98 
99                             bool expectedResult = true;
100                             SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
101                                                    dstPoint.fY - srcRect.fTop };
102                             SkIRect copiedDstRect = SkIRect::MakeXYWH(dstPoint.fX,
103                                                                       dstPoint.fY,
104                                                                       srcRect.width(),
105                                                                       srcRect.height());
106 
107                             SkIRect copiedSrcRect;
108                             if (!copiedSrcRect.intersect(srcRect, SkIRect::MakeWH(kW, kH))) {
109                                 expectedResult = false;
110                             } else {
111                                 // If the src rect was clipped, apply same clipping to each side of
112                                 // copied dst rect.
113                                 copiedDstRect.fLeft += copiedSrcRect.fLeft - srcRect.fLeft;
114                                 copiedDstRect.fTop += copiedSrcRect.fTop - srcRect.fTop;
115                                 copiedDstRect.fRight -= copiedSrcRect.fRight - srcRect.fRight;
116                                 copiedDstRect.fBottom -= copiedSrcRect.fBottom - srcRect.fBottom;
117                             }
118                             if (copiedDstRect.isEmpty() ||
119                                 !copiedDstRect.intersect(SkIRect::MakeWH(kW, kH))) {
120                                 expectedResult = false;
121                             }
122                             // To make the copied src rect correct we would apply any dst clipping
123                             // back to the src rect, but we don't use it again so don't bother.
124                             if (expectedResult != result) {
125                                 ERRORF(reporter, "Expected return value %d from copySurface, got "
126                                        "%d.", expectedResult, result);
127                                 continue;
128                             }
129 
130                             if (!expectedResult || !result) {
131                                 continue;
132                             }
133 
134                             sk_memset32(read.get(), 0, kW * kH);
135                             if (!dstContext->readPixels(ii, read.get(), kRowBytes, 0, 0)) {
136                                 ERRORF(reporter, "Error calling readPixels");
137                                 continue;
138                             }
139 
140                             bool abort = false;
141                             // Validate that pixels inside copiedDstRect received the correct value
142                             // from src and that those outside were not modified.
143                             for (int y = 0; y < kH && !abort; ++y) {
144                                 for (int x = 0; x < kW; ++x) {
145                                     uint32_t r = read.get()[y * kW + x];
146                                     if (copiedDstRect.contains(x, y)) {
147                                         int sx = x - dstOffset.fX;
148                                         int sy = y - dstOffset.fY;
149                                         uint32_t s = srcPixels.get()[sy * kW + sx];
150                                         if (s != r) {
151                                             ERRORF(reporter, "Expected dst %d,%d to contain "
152                                                    "0x%08x copied from src location %d,%d. Got "
153                                                    "0x%08x", x, y, s, sx, sy, r);
154                                             abort = true;
155                                             break;
156                                         }
157                                     } else {
158                                         uint32_t d = dstPixels.get()[y * kW + x];
159                                         if (d != r) {
160                                             ERRORF(reporter, "Expected dst %d,%d to be unmodified ("
161                                                    "0x%08x). Got 0x%08x", x, y, d, r);
162                                             abort = true;
163                                             break;
164                                         }
165                                     }
166                                 }
167                             }
168                         }
169                     }
170                 }
171             }
172         }
173     }
174 }
175 #endif
176