Merge "Support hardware bitmaps in bitmap shaders"

This commit is contained in:
Sergei Vasilinetc
2016-11-16 17:43:04 +00:00
committed by Android (Google) Code Review
7 changed files with 96 additions and 11 deletions

View File

@@ -93,7 +93,7 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap,
if (jbitmap) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
}
sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);

View File

@@ -133,7 +133,7 @@ struct ProgramDescription {
// Shaders
bool hasBitmap;
bool isBitmapNpot;
bool useShaderBasedWrap;
bool hasVertexAlpha;
bool useShadowAlphaInterp;
@@ -180,7 +180,7 @@ struct ProgramDescription {
modulate = false;
hasBitmap = false;
isBitmapNpot = false;
useShaderBasedWrap = false;
hasGradient = false;
gradientType = kGradientLinear;
@@ -234,7 +234,7 @@ struct ProgramDescription {
if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
if (hasBitmap) {
key |= PROGRAM_KEY_BITMAP;
if (isBitmapNpot) {
if (useShaderBasedWrap) {
key |= PROGRAM_KEY_BITMAP_NPOT;
key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;

View File

@@ -707,7 +707,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (blendFramebuffer) {
generateBlend(shader, "blendFramebuffer", description.framebufferMode);
}
if (description.isBitmapNpot) {
if (description.useShaderBasedWrap) {
generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
}
if (description.hasGradient) {
@@ -736,7 +736,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
}
if (description.hasBitmap) {
if (!description.isBitmapNpot) {
if (!description.useShaderBasedWrap) {
shader.append(gFS_Main_FetchBitmap);
} else {
shader.append(gFS_Main_FetchBitmapNpot);

View File

@@ -58,7 +58,7 @@ static inline void bindUniformColor(int slot, FloatColor color) {
}
static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
caches->textureState().bindTexture(texture->id());
caches->textureState().bindTexture(texture->target(), texture->id());
texture->setWrapST(wrapS, wrapT);
}
@@ -218,10 +218,13 @@ bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& model
const float height = outData->bitmapTexture->height();
description->hasBitmap = true;
if (!caches.extensions().hasNPot()
// gralloc doesn't support non-clamp modes
if (hwuiBitmap->isHardware() || (!caches.extensions().hasNPot()
&& (!isPowerOfTwo(width) || !isPowerOfTwo(height))
&& (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode)) {
description->isBitmapNpot = true;
&& (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) {
// need non-clamp mode, but it's not supported for this draw,
// so enable custom shader logic to mimic
description->useShaderBasedWrap = true;
description->bitmapWrapS = gTileModes[xy[0]];
description->bitmapWrapT = gTileModes[xy[1]];

View File

@@ -413,7 +413,6 @@ void* Bitmap::getStorage() const {
case PixelStorageType::Heap:
return mPixelStorage.heap.address;
case PixelStorageType::Hardware:
LOG_ALWAYS_FATAL_IF("Can't get address for hardware bitmap");
return nullptr;
}
}
@@ -470,6 +469,12 @@ void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
}
void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
outBitmap->setInfo(info(), rowBytes());
outBitmap->setPixelRef(this);
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
}
void Bitmap::getBounds(SkRect* bounds) const {
SkASSERT(bounds);
bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));

View File

@@ -85,6 +85,10 @@ public:
void getSkBitmap(SkBitmap* outBitmap);
// Ugly hack: in case of hardware bitmaps, it sets nullptr as pixels pointer
// so it would crash if anyone tries to render this bitmap.
void getSkBitmapForShaders(SkBitmap* outBitmap);
int getAshmemFd() const;
size_t getAllocationByteCount() const;

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TestSceneBase.h"
#include "utils/Color.h"
#include "tests/common/BitmapAllocationTestUtils.h"
class BitmapShaders;
static bool _BitmapShaders(
BitmapAllocationTestUtils::registerBitmapAllocationScene<BitmapShaders>(
"bitmapShader", "Draws bitmap shaders with repeat and mirror modes."));
class BitmapShaders : public TestScene {
public:
BitmapShaders(BitmapAllocationTestUtils::BitmapAllocator allocator)
: TestScene()
, mAllocator(allocator) { }
sp<RenderNode> card;
void createContent(int width, int height, Canvas& canvas) override {
canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
sk_sp<Bitmap> hwuiBitmap = mAllocator(200, 200, kRGBA_8888_SkColorType,
[](SkBitmap& skBitmap) {
skBitmap.eraseColor(Color::White);
SkCanvas skCanvas(skBitmap);
SkPaint skPaint;
skPaint.setColor(Color::Red_500);
skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
skPaint.setColor(Color::Blue_500);
skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
});
SkBitmap bitmap;
SkPaint paint;
hwuiBitmap->getSkBitmapForShaders(&bitmap);
sk_sp<SkShader> repeatShader = SkMakeBitmapShader(bitmap,
SkShader::TileMode::kRepeat_TileMode,
SkShader::TileMode::kRepeat_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
paint.setShader(std::move(repeatShader));
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
sk_sp<SkShader> mirrorShader = SkMakeBitmapShader(bitmap,
SkShader::TileMode::kMirror_TileMode,
SkShader::TileMode::kMirror_TileMode,
nullptr,
kNever_SkCopyPixelsMode,
nullptr);
paint.setShader(std::move(mirrorShader));
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
}
void doFrame(int frameNr) override { }
BitmapAllocationTestUtils::BitmapAllocator mAllocator;
};