Support hardware bitmaps in bitmap shaders
Test: hwuimacro bitmapShaderEglImage --onscreen. bug:30999911 Change-Id: I9d16a1c217a4474841794cf27ce49e3f7823678e
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]];
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
73
libs/hwui/tests/common/scenes/BitmapShaders.cpp
Normal file
73
libs/hwui/tests/common/scenes/BitmapShaders.cpp
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user