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 "GrTexture.h" 18 19 #include "SkUtils.h" 20 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