1/* 2 * Copyright 2021 Google LLC 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 "gm/gm.h" 9#include "include/core/SkBitmap.h" 10#include "include/core/SkCanvas.h" 11#include "include/core/SkPaint.h" 12#include "include/core/SkSize.h" 13#include "include/core/SkSurface.h" 14#include "include/effects/SkRuntimeEffect.h" 15#include "src/gpu/GrCaps.h" 16#include "src/gpu/GrDirectContextPriv.h" 17#include "tests/Test.h" 18#include "tools/Resources.h" 19#include "tools/RuntimeBlendUtils.h" 20#include "tools/ToolUtils.h" 21 22static bool nearly_equal(const SkColor& x, const SkColor& y) { 23 const int kTolerance = 1; 24 return abs((int)SkColorGetA(x) - (int)SkColorGetA(y)) <= kTolerance && 25 abs((int)SkColorGetR(x) - (int)SkColorGetR(y)) <= kTolerance && 26 abs((int)SkColorGetG(x) - (int)SkColorGetG(y)) <= kTolerance && 27 abs((int)SkColorGetB(x) - (int)SkColorGetB(y)) <= kTolerance; 28} 29 30static void test_blend(skiatest::Reporter* r, SkSurface* surface) { 31 SkBitmap bitmap; 32 REPORTER_ASSERT(r, bitmap.tryAllocPixels(surface->imageInfo())); 33 34 for (int m = 0; m <= (int)SkBlendMode::kLastMode; ++m) { 35 SkBlendMode mode = (SkBlendMode)m; 36 for (int alpha : {0x80, 0xFF}) { 37 std::vector<SkColor> colors; 38 for (bool useRuntimeBlend : {false, true}) { 39 // Draw a solid red pixel. 40 SkPaint paint; 41 paint.setColor(SK_ColorRED); 42 paint.setBlendMode(SkBlendMode::kSrc); 43 surface->getCanvas()->drawRect(SkRect::MakeWH(1, 1), paint); 44 45 // Draw a blue pixel on top of it, using the passed-in blend mode. 46 paint.setColor(SkColorSetARGB(alpha, 0x00, 0x00, 0xFF)); 47 if (useRuntimeBlend) { 48 paint.setBlender(GetRuntimeBlendForBlendMode(mode)); 49 } else { 50 paint.setBlendMode(mode); 51 } 52 surface->getCanvas()->drawRect(SkRect::MakeWH(1, 1), paint); 53 54 // Read back the red/blue blended pixel. 55 REPORTER_ASSERT(r, surface->readPixels(bitmap.info(), bitmap.getPixels(), 56 bitmap.rowBytes(), /*srcX=*/0, /*srcY=*/0)); 57 colors.push_back(bitmap.getColor(/*x=*/0, /*y=*/0)); 58 } 59 60 REPORTER_ASSERT(r, nearly_equal(colors[0], colors[1]), 61 "Expected: %s %s blend matches. Actual: Built-in " 62 "A=%02X R=%02X G=%02X B=%02X, Runtime A=%02X R=%02X G=%02X B=%02X", 63 SkBlendMode_Name(mode), 64 (alpha == 0xFF) ? "solid" : "transparent", 65 SkColorGetA(colors[0]), 66 SkColorGetR(colors[0]), 67 SkColorGetG(colors[0]), 68 SkColorGetB(colors[0]), 69 SkColorGetA(colors[1]), 70 SkColorGetR(colors[1]), 71 SkColorGetG(colors[1]), 72 SkColorGetB(colors[1])); 73 } 74 } 75} 76 77DEF_TEST(SkRuntimeBlender_CPU, r) { 78 const SkImageInfo info = SkImageInfo::MakeN32Premul(/*width=*/1, /*height=*/1); 79 sk_sp<SkSurface> surface(SkSurface::MakeRaster(info)); 80 81 test_blend(r, surface.get()); 82} 83 84DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRuntimeBlender_GPU, r, ctxInfo) { 85 const SkImageInfo info = SkImageInfo::MakeN32Premul(/*width=*/1, /*height=*/1); 86 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctxInfo.directContext(), 87 SkBudgeted::kNo, info)); 88 test_blend(r, surface.get()); 89} 90