Skip to content

Commit 665a376

Browse files
Romain GuyAndroid (Google) Code Review
authored andcommitted
Merge "Work-around for a Skia rasterization bug Bug #6411457" into jb-dev
2 parents d51f90f + fdd6fc1 commit 665a376

File tree

3 files changed

+108
-38
lines changed

3 files changed

+108
-38
lines changed

libs/hwui/PathCache.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ namespace android {
2525
namespace uirenderer {
2626

2727
// Defined in ShapeCache.h
28-
void computePathBounds(const SkPath *path, const SkPaint* paint,
28+
29+
void computePathBounds(const SkPath* path, const SkPaint* paint,
2930
float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
3031
const SkRect& bounds = path->getBounds();
32+
computeBounds(bounds, paint, left, top, offset, width, height);
33+
}
3134

35+
void computeBounds(const SkRect& bounds, const SkPaint* paint,
36+
float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
3237
const float pathWidth = fmax(bounds.width(), 1.0f);
3338
const float pathHeight = fmax(bounds.height(), 1.0f);
3439

libs/hwui/ShapeCache.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,29 @@ PathTexture* RectShapeCache::getRect(float width, float height, SkPaint* paint)
105105
PathTexture* texture = get(entry);
106106

107107
if (!texture) {
108-
SkPath path;
109-
path.addRect(0.0f, 0.0f, width, height, SkPath::kCW_Direction);
108+
SkRect bounds;
109+
bounds.set(0.0f, 0.0f, width, height);
110110

111-
texture = addTexture(entry, &path, paint);
111+
float left, top, offset;
112+
uint32_t rectWidth, rectHeight;
113+
computeBounds(bounds, paint, left, top, offset, rectWidth, rectHeight);
114+
115+
if (!checkTextureSize(rectWidth, rectHeight)) return NULL;
116+
117+
purgeCache(rectWidth, rectHeight);
118+
119+
SkBitmap bitmap;
120+
initBitmap(bitmap, rectWidth, rectHeight);
121+
122+
SkPaint pathPaint(*paint);
123+
initPaint(pathPaint);
124+
125+
SkCanvas canvas(bitmap);
126+
canvas.translate(-left + offset, -top + offset);
127+
canvas.drawRect(bounds, pathPaint);
128+
129+
texture = createTexture(0, 0, offset, rectWidth, rectHeight, 0);
130+
addTexture(entry, &bitmap, texture);
112131
}
113132

114133
return texture;

libs/hwui/ShapeCache.h

Lines changed: 80 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,19 @@ class ShapeCache: public OnEntryRemoved<Entry, PathTexture*> {
336336

337337
protected:
338338
PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
339+
PathTexture* addTexture(const Entry& entry, SkBitmap* bitmap);
340+
void addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture);
341+
342+
/**
343+
* Ensures there is enough space in the cache for a texture of the specified
344+
* dimensions.
345+
*/
346+
void purgeCache(uint32_t width, uint32_t height);
347+
348+
void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height);
349+
void initPaint(SkPaint& paint);
350+
351+
bool checkTextureSize(uint32_t width, uint32_t height);
339352

340353
PathTexture* get(Entry entry) {
341354
return mCache.get(entry);
@@ -489,62 +502,97 @@ void ShapeCache<Entry>::removeTexture(PathTexture* texture) {
489502
}
490503
}
491504

492-
void computePathBounds(const SkPath *path, const SkPaint* paint,
505+
void computePathBounds(const SkPath* path, const SkPaint* paint,
506+
float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
507+
void computeBounds(const SkRect& bounds, const SkPaint* paint,
493508
float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
494509

495-
template<class Entry>
496-
PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
497-
const SkPaint* paint) {
498-
499-
float left, top, offset;
500-
uint32_t width, height;
501-
computePathBounds(path, paint, left, top, offset, width, height);
502-
503-
if (width > mMaxTextureSize || height > mMaxTextureSize) {
504-
ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
505-
mName, width, height, mMaxTextureSize, mMaxTextureSize);
506-
return NULL;
507-
}
510+
static PathTexture* createTexture(float left, float top, float offset,
511+
uint32_t width, uint32_t height, uint32_t id) {
512+
PathTexture* texture = new PathTexture;
513+
texture->left = left;
514+
texture->top = top;
515+
texture->offset = offset;
516+
texture->width = width;
517+
texture->height = height;
518+
texture->generation = id;
519+
return texture;
520+
}
508521

522+
template<class Entry>
523+
void ShapeCache<Entry>::purgeCache(uint32_t width, uint32_t height) {
509524
const uint32_t size = width * height;
510525
// Don't even try to cache a bitmap that's bigger than the cache
511526
if (size < mMaxSize) {
512527
while (mSize + size > mMaxSize) {
513528
mCache.removeOldest();
514529
}
515530
}
531+
}
516532

517-
PathTexture* texture = new PathTexture;
518-
texture->left = left;
519-
texture->top = top;
520-
texture->offset = offset;
521-
texture->width = width;
522-
texture->height = height;
523-
texture->generation = path->getGenerationID();
524-
525-
SkBitmap bitmap;
533+
template<class Entry>
534+
void ShapeCache<Entry>::initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
526535
bitmap.setConfig(SkBitmap::kA8_Config, width, height);
527536
bitmap.allocPixels();
528537
bitmap.eraseColor(0);
538+
}
529539

530-
SkPaint pathPaint(*paint);
531-
540+
template<class Entry>
541+
void ShapeCache<Entry>::initPaint(SkPaint& paint) {
532542
// Make sure the paint is opaque, color, alpha, filter, etc.
533543
// will be applied later when compositing the alpha8 texture
534-
pathPaint.setColor(0xff000000);
535-
pathPaint.setAlpha(255);
536-
pathPaint.setColorFilter(NULL);
537-
pathPaint.setMaskFilter(NULL);
538-
pathPaint.setShader(NULL);
544+
paint.setColor(0xff000000);
545+
paint.setAlpha(255);
546+
paint.setColorFilter(NULL);
547+
paint.setMaskFilter(NULL);
548+
paint.setShader(NULL);
539549
SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
540-
SkSafeUnref(pathPaint.setXfermode(mode));
550+
SkSafeUnref(paint.setXfermode(mode));
551+
}
552+
553+
template<class Entry>
554+
bool ShapeCache<Entry>::checkTextureSize(uint32_t width, uint32_t height) {
555+
if (width > mMaxTextureSize || height > mMaxTextureSize) {
556+
ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
557+
mName, width, height, mMaxTextureSize, mMaxTextureSize);
558+
return false;
559+
}
560+
return true;
561+
}
562+
563+
template<class Entry>
564+
PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
565+
const SkPaint* paint) {
566+
567+
float left, top, offset;
568+
uint32_t width, height;
569+
computePathBounds(path, paint, left, top, offset, width, height);
570+
571+
if (!checkTextureSize(width, height)) return NULL;
572+
573+
purgeCache(width, height);
574+
575+
SkBitmap bitmap;
576+
initBitmap(bitmap, width, height);
577+
578+
SkPaint pathPaint(*paint);
579+
initPaint(pathPaint);
541580

542581
SkCanvas canvas(bitmap);
543582
canvas.translate(-left + offset, -top + offset);
544583
canvas.drawPath(*path, pathPaint);
545584

546-
generateTexture(bitmap, texture);
585+
PathTexture* texture = createTexture(left, top, offset, width, height, path->getGenerationID());
586+
addTexture(entry, &bitmap, texture);
587+
588+
return texture;
589+
}
590+
591+
template<class Entry>
592+
void ShapeCache<Entry>::addTexture(const Entry& entry, SkBitmap* bitmap, PathTexture* texture) {
593+
generateTexture(*bitmap, texture);
547594

595+
uint32_t size = texture->width * texture->height;
548596
if (size < mMaxSize) {
549597
mSize += size;
550598
SHAPE_LOGD("ShapeCache::get: create %s: name, size, mSize = %d, %d, %d",
@@ -556,8 +604,6 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat
556604
} else {
557605
texture->cleanup = true;
558606
}
559-
560-
return texture;
561607
}
562608

563609
template<class Entry>

0 commit comments

Comments
 (0)