20c6a947af
This creates SkImageShader instances that do not perform color space conversion, nor do they premultiply their pixels (if they started out unpremultiplied). These are useful for runtime shaders that want non-color inputs (like normal maps or lookup tables). Includes GM that demonstrates lack of color conversion, and lack of premultiplication in the context of a lighting shader. Bug: skia:10479 Change-Id: Ic07aa8b8d3407ae5f81bc075648fdcba6d4cce29 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/477299 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
148 lines
4.8 KiB
C++
148 lines
4.8 KiB
C++
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "include/core/SkBitmap.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkShader.h"
|
|
#include "include/core/SkSurface.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/gpu/GrDirectContext.h"
|
|
#include "tests/Test.h"
|
|
#include "tools/Resources.h"
|
|
|
|
static void test_bitmap_equality(skiatest::Reporter* reporter, SkBitmap& bm1, SkBitmap& bm2) {
|
|
REPORTER_ASSERT(reporter, bm1.computeByteSize() == bm2.computeByteSize());
|
|
REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getPixels(), bm2.getPixels(), bm1.computeByteSize()));
|
|
}
|
|
|
|
static void paint_source(SkSurface* sourceSurface) {
|
|
SkCanvas* sourceCanvas = sourceSurface->getCanvas();
|
|
sourceCanvas->clear(0xFFDEDEDE);
|
|
|
|
SkPaint paintColor;
|
|
paintColor.setColor(0xFFFF0000);
|
|
paintColor.setStyle(SkPaint::kFill_Style);
|
|
|
|
SkRect rect = SkRect::MakeXYWH(
|
|
SkIntToScalar(1),
|
|
SkIntToScalar(0),
|
|
SkIntToScalar(1),
|
|
SkIntToScalar(sourceSurface->height()));
|
|
|
|
sourceCanvas->drawRect(rect, paintColor);
|
|
}
|
|
|
|
static void run_shader_test(skiatest::Reporter* reporter, SkSurface* sourceSurface,
|
|
SkSurface* destinationSurface, SkImageInfo& info) {
|
|
paint_source(sourceSurface);
|
|
|
|
sk_sp<SkImage> sourceImage(sourceSurface->makeImageSnapshot());
|
|
sk_sp<SkShader> sourceShader = sourceImage->makeShader(
|
|
SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions());
|
|
|
|
SkPaint paint;
|
|
paint.setShader(sourceShader);
|
|
|
|
SkCanvas* destinationCanvas = destinationSurface->getCanvas();
|
|
destinationCanvas->clear(SK_ColorTRANSPARENT);
|
|
destinationCanvas->drawPaint(paint);
|
|
|
|
SkBitmap bmOrig;
|
|
bmOrig.allocN32Pixels(info.width(), info.height());
|
|
sourceSurface->readPixels(bmOrig, 0, 0);
|
|
|
|
|
|
SkBitmap bm;
|
|
bm.allocN32Pixels(info.width(), info.height());
|
|
destinationSurface->readPixels(bm, 0, 0);
|
|
|
|
test_bitmap_equality(reporter, bmOrig, bm);
|
|
|
|
// Test with a translated shader
|
|
SkMatrix matrix;
|
|
matrix.setTranslate(SkIntToScalar(-1), SkIntToScalar(0));
|
|
|
|
sk_sp<SkShader> sourceShaderTranslated = sourceImage->makeShader(
|
|
SkTileMode::kRepeat,
|
|
SkTileMode::kRepeat,
|
|
SkSamplingOptions(), &matrix);
|
|
|
|
destinationCanvas->clear(SK_ColorTRANSPARENT);
|
|
|
|
SkPaint paintTranslated;
|
|
paintTranslated.setShader(sourceShaderTranslated);
|
|
|
|
destinationCanvas->drawPaint(paintTranslated);
|
|
|
|
SkBitmap bmt;
|
|
bmt.allocN32Pixels(info.width(), info.height());
|
|
destinationSurface->readPixels(bmt, 0, 0);
|
|
|
|
// Test correctness
|
|
{
|
|
for (int y = 0; y < info.height(); y++) {
|
|
REPORTER_ASSERT(reporter, 0xFFFF0000 == bmt.getColor(0, y));
|
|
|
|
for (int x = 1; x < info.width(); x++) {
|
|
REPORTER_ASSERT(reporter, 0xFFDEDEDE == bmt.getColor(x, y));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DEF_TEST(ImageNewShader, reporter) {
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
|
|
|
|
auto sourceSurface(SkSurface::MakeRaster(info));
|
|
auto destinationSurface(SkSurface::MakeRaster(info));
|
|
|
|
run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
|
|
}
|
|
|
|
static void gpu_to_gpu(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
|
|
|
|
auto sourceSurface(SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info));
|
|
auto destinationSurface(SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info));
|
|
|
|
run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
|
|
}
|
|
|
|
static void raster_to_gpu(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(5, 5);
|
|
|
|
auto sourceSurface(SkSurface::MakeRaster(info));
|
|
auto destinationSurface(SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info));
|
|
|
|
run_shader_test(reporter, sourceSurface.get(), destinationSurface.get(), info);
|
|
}
|
|
|
|
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageNewShader_GPU, reporter, ctxInfo) {
|
|
auto dContext = ctxInfo.directContext();
|
|
|
|
// GPU -> GPU
|
|
gpu_to_gpu(reporter, dContext);
|
|
|
|
// GPU -> RASTER not currently supported
|
|
|
|
// RASTER -> GPU
|
|
raster_to_gpu(reporter, dContext);
|
|
}
|
|
|
|
DEF_TEST(ImageRawShader, reporter) {
|
|
auto image = GetResourceAsImage("images/mandrill_32.png");
|
|
REPORTER_ASSERT(reporter, image);
|
|
|
|
// We should be able to turn this into a "raw" image shader:
|
|
REPORTER_ASSERT(reporter, image->makeRawShader(SkSamplingOptions{}));
|
|
|
|
// ... but not if we request cubic filtering
|
|
REPORTER_ASSERT(reporter,
|
|
!image->makeRawShader(SkSamplingOptions{SkCubicResampler::Mitchell()}));
|
|
}
|