diff options
-rw-r--r-- | core/jni/android/graphics/Shader.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Program.h | 6 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.h | 4 | ||||
-rw-r--r-- | libs/hwui/tests/common/scenes/BitmapShaders.cpp | 73 |
7 files changed, 96 insertions, 11 deletions
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 0de46e6b4d04..7e417b443b4b 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -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); diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index e410d71e9676..9c4cb098b4c3 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -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; diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 1afc97839b44..0c2309faf4ea 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -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); diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 971c2a314d4c..34e6a06c3dc2 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -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]]; diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 2077b0ec87f9..c028f1158e70 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -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())); diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 3940381edf62..663238ca43f2 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -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; diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp new file mode 100644 index 000000000000..9b0b9507b503 --- /dev/null +++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp @@ -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; +};
\ No newline at end of file |