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