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 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