1 /* 2 * Copyright 2017 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 // This is a GPU-backend specific test. 9 10 #include "Test.h" 11 12 using namespace sk_gpu_test; 13 14 #include "GrContextFactory.h" 15 16 #include "SkCanvas.h" 17 #include "SkImagePriv.h" 18 #include "SkSurface.h" 19 20 static bool surface_is_expected_color(SkSurface* surf, const SkImageInfo& ii, SkColor color) { 21 SkBitmap bm; 22 bm.allocPixels(ii); 23 24 surf->readPixels(bm, 0, 0); 25 26 for (int y = 0; y < bm.height(); ++y) { 27 for (int x = 0; x < bm.width(); ++x) { 28 if (bm.getColor(x, y) != color) { 29 return false; 30 } 31 } 32 } 33 34 return true; 35 } 36 37 static void basic_test(skiatest::Reporter* reporter, GrContext* context) { 38 const SkImageInfo ii = SkImageInfo::Make(64, 64, kN32_SkColorType, kPremul_SkAlphaType); 39 40 SkBitmap bm; 41 bm.allocPixels(ii); 42 43 SkCanvas bmCanvas(bm); 44 bmCanvas.clear(SK_ColorRED); 45 46 // We start off with the raster image being all red. 47 sk_sp<SkImage> img = SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode); 48 49 sk_sp<SkSurface> gpuSurface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii); 50 SkCanvas* canvas = gpuSurface->getCanvas(); 51 52 // w/o pinning - the gpu draw always reflects the current state of the underlying bitmap 53 { 54 canvas->drawImage(img, 0, 0); 55 REPORTER_ASSERT(reporter, surface_is_expected_color(gpuSurface.get(), ii, SK_ColorRED)); 56 57 bmCanvas.clear(SK_ColorGREEN); 58 59 canvas->drawImage(img, 0, 0); 60 REPORTER_ASSERT(reporter, surface_is_expected_color(gpuSurface.get(), ii, SK_ColorGREEN)); 61 } 62 63 // w/ pinning - the gpu draw is stuck at the pinned state 64 { 65 SkImage_pinAsTexture(img.get(), context); // pin at blue 66 67 canvas->drawImage(img, 0, 0); 68 REPORTER_ASSERT(reporter, surface_is_expected_color(gpuSurface.get(), ii, SK_ColorGREEN)); 69 70 bmCanvas.clear(SK_ColorBLUE); 71 72 canvas->drawImage(img, 0, 0); 73 REPORTER_ASSERT(reporter, surface_is_expected_color(gpuSurface.get(), ii, SK_ColorGREEN)); 74 75 SkImage_unpinAsTexture(img.get(), context); 76 } 77 78 // once unpinned local changes will be picked up 79 { 80 canvas->drawImage(img, 0, 0); 81 REPORTER_ASSERT(reporter, surface_is_expected_color(gpuSurface.get(), ii, SK_ColorBLUE)); 82 } 83 } 84 85 // Deleting the context while there are still pinned images shouldn't result in a crash. 86 static void cleanup_test(skiatest::Reporter* reporter) { 87 88 const SkImageInfo ii = SkImageInfo::Make(64, 64, kN32_SkColorType, kPremul_SkAlphaType); 89 90 SkBitmap bm; 91 bm.allocPixels(ii); 92 93 SkCanvas bmCanvas(bm); 94 bmCanvas.clear(SK_ColorRED); 95 96 for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) { 97 GrContextFactory::ContextType ctxType = (GrContextFactory::ContextType) i; 98 99 { 100 sk_sp<SkImage> img; 101 GrContext* context = nullptr; 102 103 { 104 GrContextFactory testFactory; 105 ContextInfo info = testFactory.getContextInfo(ctxType); 106 context = info.grContext(); 107 if (!context) { 108 continue; 109 } 110 111 img = SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode); 112 if (!SkImage_pinAsTexture(img.get(), context)) { 113 continue; 114 } 115 } 116 117 // The GrContext used to pin the image is gone at this point! 118 // "context" isn't technically used in this call but it can't be null! 119 // We don't really want to support this use case but it currently happens. 120 SkImage_unpinAsTexture(img.get(), context); 121 } 122 } 123 } 124 125 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PinnedImageTest, reporter, ctxInfo) { 126 basic_test(reporter, ctxInfo.grContext()); 127 cleanup_test(reporter); 128 } 129