通常情况下,android.graphics.Canvas的画布缓冲区在native动态分配的一块内存区域或者是hal层分配的一块hardware buffer,如果能够为Canvas指定操作的内存地址,那么就可以使用Canvas已有的众多API方便实现各种图像绘制功能,并能在某些情况下减少内存COPY的动作。
比如使用系统中framebuffer device的缓冲区来作为Canvas的目标绘制区域,实现即绘即显。
Bitmap可以作为Canvas的绘制目标,如何将指定内存区域绑定到Bitmap并且Bitmap不会free这段内存将成为我们要解决的问题。
为Bitmap class增加method,其可接受指定的内存fb帧地址,
@Nullable
public static Bitmap createFbBitmap(int width, int height, @NonNull Config config,
@Nullable final long fbFrameAddr) {
return createFbBitmap(width, height, config, true, fbFrameAddr);
}
@Nullable
public static Bitmap createFbBitmap(int width, int height,
@NonNull Config config, boolean hasAlpha, final long fbFrameAddr) {
return createFbBitmap(null, width, height, config, hasAlpha, fbFrameAddr);
}
@Nullable
public static Bitmap createFbBitmap(@Nullable DisplayMetrics display, int width, int height,
@NonNull Config config, boolean hasAlpha, final long fbFrameAddr) {
return createFbBitmap(display, width, height, config, hasAlpha,
ColorSpace.get(ColorSpace.Named.SRGB), fbFrameAddr);
}
@Nullable
public static Bitmap createFbBitmap(@Nullable DisplayMetrics display, int width, int height,
@NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace,
final long fbFrameAddr) {
......
Bitmap bm = nativeCreateFb(null, 0, width, width, height, config.nativeInt, true,
colorSpace == null ? 0 : colorSpace.getNativeInstance(), fbFrameAddr);
......
}
将fb frame addr绑定到native Bitmap
ANDROID_API jobject Bitmap_Fb_creator(JNIEnv* env, jobject, jintArray jColors,
jint offset, jint stride, jint width, jint height,
jint configHandle, jboolean isMutable,
jlong colorSpacePtr, jlong fbFrameAddr) {
......
/* not free fb memory */
sk_sp<SkPixelRef> sk_pix_ref = sk_make_sp<SkPixelRef>(width, height, (void*)fbFrameAddr,
bitmap.info().minRowBytes());
sk_sp<Bitmap> nativeBitmap = Bitmap::createFrom(bitmap.info(), *sk_pix_ref);
......
}
从java app创建
long accelFbFrameBits = native_getAccelFbFrameBits(nId);
Log.d(TAG, "accelFbFrameBits[" + nId + "]: 0x" + Long.toHexString(accelFbFrameBits));
if(0 != accelFbFrameBits) {
mAccelFbFramesBitmap[nId] = Bitmap.createFbBitmap(mAccelFbFrameWidth, mAccelFbFrameHeight,
bmCfg, accelFbFrameBits);
}
创建与Bitmap绑定的Canvas,
mAccelFbFramesCanvas[nId] = new Canvas(mAccelFbFramesBitmap[nId]);
至此,可以使用Canvas的Java API对framebuffer缓冲区进行绘制了。