Pass Bitmap instead of SkBitmap for bitmap rect operation

Test: refactoring cl.
bug:32216791

Change-Id: I66d19194c57b3aa2c400aa87acffc774a533776a
This commit is contained in:
sergeyv
2016-10-17 13:07:38 -07:00
parent aed7f58fb0
commit fc9999505a
15 changed files with 92 additions and 80 deletions

View File

@@ -52,7 +52,7 @@ public:
}
bool valid() {
return !!mBitmap;
return mBitmap;
}
Bitmap& bitmap() {

View File

@@ -407,8 +407,7 @@ static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject j
jlong matrixHandle, jlong paintHandle) {
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkBitmap bitmap;
GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
}
@@ -419,8 +418,7 @@ static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbi
Canvas* canvas = get_canvas(canvasHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkBitmap bitmap;
GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
if (screenDensity != 0 && screenDensity != bitmapDensity) {
Paint filteredPaint;
if (paint) {

View File

@@ -631,13 +631,15 @@ void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) {
}
void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
SkBitmap bitmap;
op.vectorDrawable->getBitmapUpdateIfDirty().getSkBitmap(&bitmap);
SkBitmap* localBitmap = mAllocator.create<SkBitmap>(bitmap);
SkPaint* paint = op.vectorDrawable->getPaint();
const BitmapRectOp* resolvedOp = mAllocator.create_trivial<BitmapRectOp>(op.unmappedBounds,
op.localMatrix,
op.localClip,
paint,
&bitmap,
localBitmap,
Rect(bitmap.width(), bitmap.height()));
deferBitmapRectOp(*resolvedOp);
}

View File

@@ -478,8 +478,10 @@ void RecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Sk
restore();
}
void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
void RecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
if (matrix.isIdentity()) {
drawBitmap(&bitmap, paint);
} else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
@@ -490,7 +492,7 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
SkRect dst;
bitmap.getBounds(&src);
matrix.mapRect(&dst, src);
drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
drawBitmap(hwuiBitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
} else {
save(SaveFlags::Matrix);
@@ -500,9 +502,11 @@ void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
}
}
void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
void RecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
if (srcLeft == 0 && srcTop == 0
&& srcRight == bitmap.width()
&& srcBottom == bitmap.height()

View File

@@ -177,9 +177,8 @@ public:
// Bitmap-based
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override;
virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) override;
virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,

View File

@@ -497,15 +497,19 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint
mCanvas->drawBitmap(skBitmap, left, top, paint);
}
void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
SkAutoCanvasRestore acr(mCanvas.get(), true);
mCanvas->concat(matrix);
mCanvas->drawBitmap(bitmap, 0, 0, paint);
}
void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, const SkPaint* paint) {
SkBitmap bitmap;
hwuiBitmap.getSkBitmap(&bitmap);
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
mCanvas->drawBitmapRect(bitmap, srcRect, dstRect, paint);

View File

@@ -125,9 +125,8 @@ public:
const uint16_t* indices, int indexCount, const SkPaint& paint) override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override;
virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) override;
virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, const SkPaint* paint) override;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,

View File

@@ -107,16 +107,12 @@ void SkiaCanvasProxy::onDrawPath(const SkPath& path, const SkPaint& paint) {
void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
const SkPaint* paint) {
SkPixelRef* pxRef = bitmap.pixelRef();
sk_sp<Bitmap> hwuiBitmap = Bitmap::createFrom(bitmap.info(), *bitmap.pixelRef());
// HWUI doesn't support extractSubset(), so convert any subsetted bitmap into
// a drawBitmapRect(); pass through an un-subsetted bitmap.
if (pxRef && bitmap.dimensions() != pxRef->info().dimensions()) {
SkBitmap fullBitmap;
fullBitmap.setInfo(pxRef->info());
fullBitmap.setPixelRef(pxRef, 0, 0);
if (hwuiBitmap && bitmap.dimensions() != hwuiBitmap->info().dimensions()) {
SkIPoint origin = bitmap.pixelRefOrigin();
mCanvas->drawBitmap(fullBitmap, origin.fX, origin.fY,
mCanvas->drawBitmap(*hwuiBitmap, origin.fX, origin.fY,
origin.fX + bitmap.dimensions().width(),
origin.fY + bitmap.dimensions().height(),
left, top,
@@ -124,16 +120,16 @@ void SkiaCanvasProxy::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScal
top + bitmap.dimensions().height(),
paint);
} else {
auto hwuiBitmap= Bitmap::createFrom(bitmap.info(), *pxRef);
mCanvas->drawBitmap(*hwuiBitmap, left, top, paint);
}
}
void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* srcPtr,
void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& skBitmap, const SkRect* srcPtr,
const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(bitmap.width(), bitmap.height());
SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(skBitmap.width(), skBitmap.height());
// TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
mCanvas->drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
Bitmap* bitmap = reinterpret_cast<Bitmap*>(skBitmap.pixelRef());
mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
}

View File

@@ -502,18 +502,18 @@ int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
}
void Tree::drawStaging(Canvas* outCanvas) {
bool redrawNeeded = allocateBitmapIfNeeded(&mStagingCache.bitmap,
bool redrawNeeded = allocateBitmapIfNeeded(mStagingCache,
mStagingProperties.getScaledWidth(), mStagingProperties.getScaledHeight());
// draw bitmap cache
if (redrawNeeded || mStagingCache.dirty) {
updateBitmapCache(&mStagingCache.bitmap, true);
updateBitmapCache(*mStagingCache.bitmap, true);
mStagingCache.dirty = false;
}
SkPaint tmpPaint;
SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties);
outCanvas->drawBitmap(mStagingCache.bitmap, 0, 0,
mStagingCache.bitmap.width(), mStagingCache.bitmap.height(),
outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0,
mStagingCache.bitmap->width(), mStagingCache.bitmap->height(),
mStagingProperties.getBounds().left(), mStagingProperties.getBounds().top(),
mStagingProperties.getBounds().right(), mStagingProperties.getBounds().bottom(), paint);
}
@@ -535,46 +535,46 @@ SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
}
}
const SkBitmap& Tree::getBitmapUpdateIfDirty() {
bool redrawNeeded = allocateBitmapIfNeeded(&mCache.bitmap, mProperties.getScaledWidth(),
Bitmap& Tree::getBitmapUpdateIfDirty() {
bool redrawNeeded = allocateBitmapIfNeeded(mCache, mProperties.getScaledWidth(),
mProperties.getScaledHeight());
if (redrawNeeded || mCache.dirty) {
updateBitmapCache(&mCache.bitmap, false);
updateBitmapCache(*mCache.bitmap, false);
mCache.dirty = false;
}
return mCache.bitmap;
return *mCache.bitmap;
}
void Tree::updateBitmapCache(SkBitmap* outCache, bool useStagingData) {
outCache->eraseColor(SK_ColorTRANSPARENT);
SkCanvas outCanvas(*outCache);
void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) {
SkBitmap outCache;
bitmap.getSkBitmap(&outCache);
outCache.eraseColor(SK_ColorTRANSPARENT);
SkCanvas outCanvas(outCache);
float viewportWidth = useStagingData ?
mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
float viewportHeight = useStagingData ?
mStagingProperties.getViewportHeight() : mProperties.getViewportHeight();
float scaleX = outCache->width() / viewportWidth;
float scaleY = outCache->height() / viewportHeight;
float scaleX = outCache.width() / viewportWidth;
float scaleY = outCache.height() / viewportHeight;
mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY, useStagingData);
}
bool Tree::allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height) {
if (!canReuseBitmap(*outCache, width, height)) {
bool Tree::allocateBitmapIfNeeded(Cache& cache, int width, int height) {
if (!canReuseBitmap(cache.bitmap.get(), width, height)) {
#ifndef ANDROID_ENABLE_LINEAR_BLENDING
sk_sp<SkColorSpace> colorSpace = nullptr;
#else
sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
#endif
SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
outCache->setInfo(info);
// TODO: Count the bitmap cache against app's java heap
outCache->allocPixels(info);
cache.bitmap = Bitmap::allocateHeapBitmap(info);
return true;
}
return false;
}
bool Tree::canReuseBitmap(const SkBitmap& bitmap, int width, int height) {
return width == bitmap.width() && height == bitmap.height();
bool Tree::canReuseBitmap(Bitmap* bitmap, int width, int height) {
return bitmap && width == bitmap->width() && height == bitmap->height();
}
void Tree::onPropertyChanged(TreeProperties* prop) {

View File

@@ -18,6 +18,7 @@
#define ANDROID_HWUI_VPATH_H
#include "hwui/Canvas.h"
#include "hwui/Bitmap.h"
#include "DisplayList.h"
#include <SkBitmap.h>
@@ -561,7 +562,7 @@ public:
const SkRect& bounds, bool needsMirroring, bool canReuseCache);
void drawStaging(Canvas* canvas);
const SkBitmap& getBitmapUpdateIfDirty();
Bitmap& getBitmapUpdateIfDirty();
void setAllowCaching(bool allowCaching) {
mAllowCaching = allowCaching;
}
@@ -691,11 +692,15 @@ public:
void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; }
private:
struct Cache {
sk_sp<Bitmap> bitmap;
bool dirty = true;
};
SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height);
bool canReuseBitmap(const SkBitmap&, int width, int height);
void updateBitmapCache(SkBitmap* outCache, bool useStagingData);
bool allocateBitmapIfNeeded(Cache& cache, int width, int height);
bool canReuseBitmap(Bitmap*, int width, int height);
void updateBitmapCache(Bitmap& outCache, bool useStagingData);
// Cap the bitmap size, such that it won't hurt the performance too much
// and it won't crash due to a very large scale.
// The drawable will look blurry above this size.
@@ -708,10 +713,6 @@ private:
TreeProperties mStagingProperties = TreeProperties(this);
SkPaint mPaint;
struct Cache {
SkBitmap bitmap;
bool dirty = true;
};
Cache mStagingCache;
Cache mCache;

View File

@@ -23,9 +23,9 @@
namespace android {
static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
int32_t rowBytes32 = SkToS32(rowBytes);
int64_t bigSize = (int64_t) height * rowBytes32;
if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
return false; // allocation will be too large
}
@@ -45,13 +45,14 @@ static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, SkColorTable* ctable, Allo
}
size_t size;
if (!computeAllocationSize(*bitmap, &size)) {
return nullptr;
}
// we must respect the rowBytes value already set on the bitmap instead of
// attempting to compute our own.
const size_t rowBytes = bitmap->rowBytes();
if (!computeAllocationSize(rowBytes, bitmap->height(), &size)) {
return nullptr;
}
auto wrapper = alloc(size, info, rowBytes, ctable);
if (wrapper) {
wrapper->getSkBitmap(bitmap);
@@ -62,15 +63,11 @@ static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, SkColorTable* ctable, Allo
return wrapper;
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
return allocateBitmap(bitmap, ctable, &Bitmap::allocateHeapBitmap);
}
sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
return allocateBitmap(bitmap, ctable, &Bitmap::allocateAshmemBitmap);
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes,
static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes,
SkColorTable* ctable) {
void* addr = calloc(size, 1);
if (!addr) {
@@ -79,6 +76,19 @@ sk_sp<Bitmap> Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, s
return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, ctable));
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
return allocateBitmap(bitmap, ctable, &android::allocateHeapBitmap);
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(const SkImageInfo& info) {
size_t size;
if (!computeAllocationSize(info.minRowBytes(), info.height(), &size)) {
LOG_ALWAYS_FATAL("trying to allocate too large bitmap");
return nullptr;
}
return android::allocateHeapBitmap(size, info, info.minRowBytes(), nullptr);
}
sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info,
size_t rowBytes, SkColorTable* ctable) {
// Create new ashmem region with read/write priv

View File

@@ -34,8 +34,7 @@ typedef void (*FreeFunc)(void* addr, void* context);
class ANDROID_API Bitmap : public SkPixelRef {
public:
static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable);
static sk_sp<Bitmap> allocateHeapBitmap(size_t allocSize, const SkImageInfo& info,
size_t rowBytes, SkColorTable* ctable);
static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info);
static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable);
static sk_sp<Bitmap> allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info,

View File

@@ -220,9 +220,9 @@ public:
// Bitmap-based
virtual void drawBitmap(Bitmap& bitmap, float left, float top,
const SkPaint* paint) = 0;
virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) = 0;
virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, const SkPaint* paint) = 0;
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,

View File

@@ -125,8 +125,7 @@ public:
static sk_sp<Bitmap> createBitmap(int width, int height,
SkColorType colorType = kN32_SkColorType) {
SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
size_t size = height * info.minRowBytes();
return Bitmap::allocateHeapBitmap(size, info, info.minRowBytes(), nullptr);
return Bitmap::allocateHeapBitmap(info);
}
static sk_sp<Bitmap> createBitmap(int width, int height, SkBitmap* outBitmap) {

View File

@@ -45,12 +45,14 @@ public:
int x = dp(32);
for (int i = 0; i < 4; i++) {
int y = (height / 4) * i;
SkBitmap thumb = TestUtils::createSkBitmap(thumbnailSize, thumbnailSize);
thumb.eraseColor(COLORS[i]);
sp<RenderNode> card = createCard(x, y, cardsize, cardsize, thumb);
SkBitmap bitmap;
sk_sp<Bitmap> thumb(TestUtils::createBitmap(thumbnailSize, thumbnailSize, &bitmap));
bitmap.eraseColor(COLORS[i]);
sp<RenderNode> card = createCard(x, y, cardsize, cardsize, *thumb);
card->mutateStagingProperties().setElevation(i * dp(8));
renderer.drawRenderNode(card.get());
mThumbnail = thumb;
mThumbnail = bitmap;
mCards.push_back(card);
}
@@ -68,8 +70,7 @@ public:
}
private:
sp<RenderNode> createCard(int x, int y, int width, int height,
const SkBitmap& thumb) {
sp<RenderNode> createCard(int x, int y, int width, int height, Bitmap& thumb) {
return TestUtils::createNode(x, y, x + width, y + height,
[&thumb, width, height](RenderProperties& props, Canvas& canvas) {
props.setElevation(dp(16));