Skip to content

Commit e651cc6

Browse files
author
Romain Guy
committed
Remove all Dalvik allocations from Cavnas.drawBitmap(int[], ...)
Change-Id: Ie28538a2104d21154fdc78a56525e7403f08287d
1 parent 99a6ddd commit e651cc6

File tree

9 files changed

+143
-16
lines changed

9 files changed

+143
-16
lines changed

core/java/android/view/GLES20Canvas.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -833,19 +833,40 @@ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
833833
@Override
834834
public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
835835
int width, int height, boolean hasAlpha, Paint paint) {
836+
if (width < 0) {
837+
throw new IllegalArgumentException("width must be >= 0");
838+
}
839+
840+
if (height < 0) {
841+
throw new IllegalArgumentException("height must be >= 0");
842+
}
843+
844+
if (Math.abs(stride) < width) {
845+
throw new IllegalArgumentException("abs(stride) must be >= width");
846+
}
847+
848+
int lastScanline = offset + (height - 1) * stride;
849+
int length = colors.length;
850+
851+
if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
852+
(lastScanline + width > length)) {
853+
throw new ArrayIndexOutOfBoundsException();
854+
}
855+
836856
// Shaders are ignored when drawing bitmaps
837857
int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
838858
try {
839-
final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
840-
final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config);
841859
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
842-
nDrawBitmap(mRenderer, b.mNativeBitmap, b.mBuffer, x, y, nativePaint);
843-
b.recycle();
860+
nDrawBitmap(mRenderer, colors, offset, stride, x, y,
861+
width, height, hasAlpha, nativePaint);
844862
} finally {
845863
if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
846864
}
847865
}
848866

867+
private static native void nDrawBitmap(int renderer, int[] colors, int offset, int stride,
868+
float x, float y, int width, int height, boolean hasAlpha, int nativePaint);
869+
849870
@Override
850871
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
851872
int width, int height, boolean hasAlpha, Paint paint) {

core/jni/android_view_GLES20Canvas.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
326326
// ----------------------------------------------------------------------------
327327

328328
static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
329-
OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, float left,
330-
float top, SkPaint* paint) {
329+
OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
330+
jfloat left, jfloat top, SkPaint* paint) {
331331
// This object allows the renderer to allocate a global JNI ref to the buffer object.
332332
JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
333333

@@ -354,6 +354,24 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject claz
354354
renderer->drawBitmap(bitmap, matrix, paint);
355355
}
356356

357+
static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
358+
OpenGLRenderer* renderer, jintArray colors, jint offset, jint stride,
359+
jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, SkPaint* paint) {
360+
SkBitmap bitmap;
361+
SkBitmap::Config config = hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config;
362+
bitmap.setConfig(config, width, height);
363+
364+
if (!bitmap.allocPixels()) {
365+
return;
366+
}
367+
368+
if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, bitmap)) {
369+
return;
370+
}
371+
372+
renderer->drawBitmapData(&bitmap, left, top, paint);
373+
}
374+
357375
static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
358376
OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
359377
jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset,
@@ -880,6 +898,7 @@ static JNINativeMethod gMethods[] = {
880898
{ "nDrawBitmap", "(II[BFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
881899
{ "nDrawBitmap", "(II[BFFFFFFFFI)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
882900
{ "nDrawBitmap", "(II[BII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
901+
{ "nDrawBitmap", "(I[IIIFFIIZI)V", (void*) android_view_GLES20Canvas_drawBitmapData },
883902

884903
{ "nDrawBitmapMesh", "(II[BII[FI[III)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
885904

libs/hwui/DisplayListRenderer.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const char* DisplayList::OP_NAMES[] = {
4949
"DrawBitmap",
5050
"DrawBitmapMatrix",
5151
"DrawBitmapRect",
52+
"DrawBitmapData",
5253
"DrawBitmapMesh",
5354
"DrawPatch",
5455
"DrawColor",
@@ -434,6 +435,14 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
434435
(char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
435436
}
436437
break;
438+
case DrawBitmapData: {
439+
SkBitmap* bitmap = getBitmapData();
440+
float x = getFloat();
441+
float y = getFloat();
442+
SkPaint* paint = getPaint(renderer);
443+
ALOGD("%s%s %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], x, y, paint);
444+
}
445+
break;
437446
case DrawBitmapMesh: {
438447
int verticesCount = 0;
439448
uint32_t colorsCount = 0;
@@ -1020,6 +1029,19 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
10201029
renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
10211030
}
10221031
break;
1032+
case DrawBitmapData: {
1033+
SkBitmap* bitmap = getBitmapData();
1034+
float x = getFloat();
1035+
float y = getFloat();
1036+
SkPaint* paint = getPaint(renderer);
1037+
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
1038+
bitmap, x, y, paint);
1039+
if (bitmap) {
1040+
renderer.drawBitmap(bitmap, x, y, paint);
1041+
delete bitmap;
1042+
}
1043+
}
1044+
break;
10231045
case DrawBitmapMesh: {
10241046
int32_t verticesCount = 0;
10251047
uint32_t colorsCount = 0;
@@ -1487,6 +1509,15 @@ void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcT
14871509
addSkip(location);
14881510
}
14891511

1512+
void DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
1513+
const bool reject = quickReject(left, top, left + bitmap->width(), bitmap->height());
1514+
uint32_t* location = addOp(DisplayList::DrawBitmapData, reject);
1515+
addBitmapData(bitmap);
1516+
addPoint(left, top);
1517+
addPaint(paint);
1518+
addSkip(location);
1519+
}
1520+
14901521
void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
14911522
float* vertices, int* colors, SkPaint* paint) {
14921523
addOp(DisplayList::DrawBitmapMesh);

libs/hwui/DisplayListRenderer.h

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class DisplayList {
9191
DrawBitmap,
9292
DrawBitmapMatrix,
9393
DrawBitmapRect,
94+
DrawBitmapData,
9495
DrawBitmapMesh,
9596
DrawPatch,
9697
DrawColor,
@@ -422,6 +423,19 @@ class DisplayList {
422423
return (SkBitmap*) getInt();
423424
}
424425

426+
SkBitmap* getBitmapData() {
427+
SkBitmap* bitmap = new SkBitmap;
428+
bitmap->setConfig((SkBitmap::Config) getInt(), getInt(), getInt());
429+
if (!bitmap->allocPixels()) {
430+
delete bitmap;
431+
return NULL;
432+
}
433+
434+
bitmap->setPixels((void*) mReader.skip(bitmap->height() * bitmap->rowBytes()));
435+
436+
return bitmap;
437+
}
438+
425439
SkiaShader* getShader() {
426440
return (SkiaShader*) getInt();
427441
}
@@ -574,6 +588,7 @@ class DisplayListRenderer: public OpenGLRenderer {
574588
virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
575589
float srcRight, float srcBottom, float dstLeft, float dstTop,
576590
float dstRight, float dstBottom, SkPaint* paint);
591+
virtual void drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
577592
virtual void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
578593
float* vertices, int* colors, SkPaint* paint);
579594
virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
@@ -701,16 +716,23 @@ class DisplayListRenderer: public OpenGLRenderer {
701716

702717
void addInts(const int32_t* values, uint32_t count) {
703718
mWriter.writeInt(count);
704-
for (uint32_t i = 0; i < count; i++) {
705-
mWriter.writeInt(values[i]);
706-
}
719+
mWriter.write(values, count * sizeof(int32_t));
720+
}
721+
722+
void addBitmapData(SkBitmap* bitmap) {
723+
mWriter.writeInt(bitmap->config());
724+
mWriter.writeInt(bitmap->width());
725+
mWriter.writeInt(bitmap->height());
726+
727+
SkAutoLockPixels alp(*bitmap);
728+
void* src = bitmap->getPixels();
729+
730+
mWriter.write(src, bitmap->rowBytes() * bitmap->height());
707731
}
708732

709733
void addUInts(const uint32_t* values, int8_t count) {
710734
mWriter.writeInt(count);
711-
for (int8_t i = 0; i < count; i++) {
712-
mWriter.writeInt(values[i]);
713-
}
735+
mWriter.write(values, count * sizeof(uint32_t));
714736
}
715737

716738
inline void addFloat(float value) {
@@ -719,9 +741,7 @@ class DisplayListRenderer: public OpenGLRenderer {
719741

720742
void addFloats(const float* values, int32_t count) {
721743
mWriter.writeInt(count);
722-
for (int32_t i = 0; i < count; i++) {
723-
mWriter.writeScalar(values[i]);
724-
}
744+
mWriter.write(values, count * sizeof(float));
725745
}
726746

727747
inline void addPoint(float x, float y) {

libs/hwui/OpenGLRenderer.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,21 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* pai
15021502
restore();
15031503
}
15041504

1505+
void OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
1506+
const float right = left + bitmap->width();
1507+
const float bottom = top + bitmap->height();
1508+
1509+
if (quickReject(left, top, right, bottom)) {
1510+
return;
1511+
}
1512+
1513+
mCaches.activeTexture(0);
1514+
Texture* texture = mCaches.textureCache.getTransient(bitmap);
1515+
const AutoTexture autoCleanup(texture);
1516+
1517+
drawTextureRect(left, top, right, bottom, texture, paint);
1518+
}
1519+
15051520
void OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
15061521
float* vertices, int* colors, SkPaint* paint) {
15071522
// TODO: Do a quickReject

libs/hwui/OpenGLRenderer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class OpenGLRenderer {
115115
virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
116116
float srcRight, float srcBottom, float dstLeft, float dstTop,
117117
float dstRight, float dstBottom, SkPaint* paint);
118+
virtual void drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
118119
virtual void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
119120
float* vertices, int* colors, SkPaint* paint);
120121
virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,

libs/hwui/TextureCache.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ Texture* TextureCache::get(SkBitmap* bitmap) {
160160
return texture;
161161
}
162162

163+
Texture* TextureCache::getTransient(SkBitmap* bitmap) {
164+
Texture* texture = new Texture;
165+
texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
166+
texture->cleanup = true;
167+
168+
generateTexture(bitmap, texture, false);
169+
170+
return texture;
171+
}
172+
163173
void TextureCache::remove(SkBitmap* bitmap) {
164174
mCache.remove(bitmap);
165175
}

libs/hwui/TextureCache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> {
6666
* cannot be found in the cache, a new texture is generated.
6767
*/
6868
Texture* get(SkBitmap* bitmap);
69+
/**
70+
* Returns the texture associated with the specified bitmap. The generated
71+
* texture is not kept in the cache. The caller must destroy the texture.
72+
*/
73+
Texture* getTransient(SkBitmap* bitmap);
6974
/**
7075
* Removes the texture associated with the specified bitmap.
7176
* Upon remove the texture is freed.

tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMutateActivity.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected void onDraw(Canvas canvas) {
8787
int width = mBitmap1.getWidth();
8888
int height = mBitmap1.getHeight();
8989

90-
canvas.translate((getWidth() - width) / 2, (getHeight() - height) / 2);
90+
canvas.translate((getWidth() - width) / 2, 0);
9191

9292
for (int x = 0; x < width; x++) {
9393
int color = 0xff000000;
@@ -101,6 +101,11 @@ protected void onDraw(Canvas canvas) {
101101

102102
mBitmap1.setPixels(mPixels, 0, width, 0, 0, width, height);
103103
canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBitmapPaint);
104+
105+
canvas.save();
106+
canvas.translate(0.0f, height + 32);
107+
canvas.drawBitmap(mPixels, 0, width, 0.0f, 0.0f, width, height, false, mBitmapPaint);
108+
canvas.restore();
104109
}
105110
}
106111
}

0 commit comments

Comments
 (0)