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