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