Use SkMakeBitmapShader, avoid bitmap copy

CreateBitmapShader now forces a copy. This updates the call sites
to use SkMakeBitmapShader (in SkImagePriv.h) with
kNever_SkCopyPixelsMode.

This maintains the behavior where apps can modify the bitmap in
the shader after creating the shader.

This also ensures that the texture cache will work (since it's
based off of SkPixelRefs).

BUG:31594626
Change-Id: Ic75cb6cdc05c750b7946208e48a8127838d9c2f8
This commit is contained in:
Matt Sarett
2016-09-20 10:34:11 -04:00
parent 682ad3b4d3
commit 62feb3a0b4
4 changed files with 40 additions and 22 deletions

View File

@@ -1,5 +1,6 @@
#include "GraphicsJNI.h"
#include "SkGradientShader.h"
#include "SkImagePriv.h"
#include "SkShader.h"
#include "SkXfermode.h"
#include "core_jni_helpers.h"
@@ -94,12 +95,15 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
}
SkShader* s = SkShader::CreateBitmapShader(bitmap,
(SkShader::TileMode)tileModeX,
(SkShader::TileMode)tileModeY);
sk_sp<SkShader> s = SkMakeBitmapShader(bitmap,
(SkShader::TileMode)tileModeX,
(SkShader::TileMode)tileModeY,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
ThrowIAE_IfNull(env, s);
return reinterpret_cast<jlong>(s);
ThrowIAE_IfNull(env, s.get());
return reinterpret_cast<jlong>(s.release());
}
///////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -26,6 +26,7 @@
#include <SkDrawFilter.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkImagePriv.h>
#include <SkRSXform.h>
#include <SkShader.h>
#include <SkTemplates.h>
@@ -593,10 +594,13 @@ void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshH
if (paint) {
tmpPaint = *paint;
}
SkShader* shader = SkShader::CreateBitmapShader(bitmap,
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode);
SkSafeUnref(tmpPaint.setShader(shader));
sk_sp<SkShader> shader = SkMakeBitmapShader(bitmap,
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
tmpPaint.setShader(std::move(shader));
mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
texs, (const SkColor*)colors, NULL, indices,

View File

@@ -740,10 +740,13 @@ TEST(RecordingCanvas, refBitmapInShader_bitmapShader) {
SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
SkPaint paint;
SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(bitmap,
sk_sp<SkShader> shader = SkMakeBitmapShader(bitmap,
SkShader::TileMode::kClamp_TileMode,
SkShader::TileMode::kClamp_TileMode));
paint.setShader(shader);
SkShader::TileMode::kClamp_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
paint.setShader(std::move(shader));
canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
});
auto& bitmaps = dl->getBitmapResources();
@@ -754,21 +757,24 @@ TEST(RecordingCanvas, refBitmapInShader_composeShader) {
SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [&bitmap](RecordingCanvas& canvas) {
SkPaint paint;
SkAutoTUnref<SkShader> shader1(SkShader::CreateBitmapShader(bitmap,
sk_sp<SkShader> shader1 = SkMakeBitmapShader(bitmap,
SkShader::TileMode::kClamp_TileMode,
SkShader::TileMode::kClamp_TileMode));
SkShader::TileMode::kClamp_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
SkPoint center;
center.set(50, 50);
SkColor colors[2];
colors[0] = Color::Black;
colors[1] = Color::White;
SkAutoTUnref<SkShader> shader2(SkGradientShader::CreateRadial(center, 50, colors, nullptr, 2,
SkShader::TileMode::kRepeat_TileMode));
sk_sp<SkShader> shader2 = SkGradientShader::MakeRadial(center, 50, colors, nullptr, 2,
SkShader::TileMode::kRepeat_TileMode);
SkAutoTUnref<SkShader> composeShader(SkShader::CreateComposeShader(shader1, shader2,
SkXfermode::Mode::kMultiply_Mode));
paint.setShader(composeShader);
sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(std::move(shader1), std::move(shader2),
SkXfermode::Mode::kMultiply_Mode);
paint.setShader(std::move(composeShader));
canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
});
auto& bitmaps = dl->getBitmapResources();

View File

@@ -17,8 +17,9 @@
#include "tests/common/TestUtils.h"
#include <gtest/gtest.h>
#include <SkShader.h>
#include <SkColorMatrixFilter.h>
#include <SkImagePriv.h>
#include <SkShader.h>
using namespace android;
using namespace android::uirenderer;
@@ -29,10 +30,13 @@ using namespace android::uirenderer;
*/
TEST(SkiaBehavior, CreateBitmapShader1x1) {
SkBitmap origBitmap = TestUtils::createSkBitmap(1, 1);
SkAutoTUnref<SkShader> s(SkShader::CreateBitmapShader(
sk_sp<SkShader> s = SkMakeBitmapShader(
origBitmap,
SkShader::kClamp_TileMode,
SkShader::kRepeat_TileMode));
SkShader::kRepeat_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
SkBitmap bitmap;
SkShader::TileMode xy[2];