Android位图对象作为绘图缓冲区
设置: 我已经实现了一种本机(读取JNI)机制,将像素从Android位图对象作为绘图缓冲区,android,bitmap,java-native-interface,Android,Bitmap,Java Native Interface,设置: 我已经实现了一种本机(读取JNI)机制,将像素从位图对象复制到本机内存。这是通过本机内存中的malloc()uint23\u t array完成的,然后使用memcpy()将像素复制到位图的本机指针中。这工作得很好,已经过测试。像素从位图对象成功保存在本机内存中,并复制回位图对象,在屏幕上可见。它的复制速度非常快,对于相当大的位图,复制速度可达几毫秒。但渲染速度非常慢 意图: 执行上述操作是为了打破默认android位图上的堆限制(请参阅)。在本机内存和目标画布之间,只有1个JavaBi
位图
对象复制到本机内存。这是通过本机内存中的malloc()
uint23\u t array
完成的,然后使用memcpy()
将像素复制到位图的本机指针中。这工作得很好,已经过测试。像素从位图
对象成功保存在本机内存中,并复制回位图
对象,在屏幕上可见。它的复制速度非常快,对于相当大的位图,复制速度可达几毫秒。但渲染速度非常慢
意图:
执行上述操作是为了打破默认android位图上的堆限制(请参阅)。在本机内存和目标画布之间,只有1个JavaBitmap
对象充当缓冲区
保存形状:
清除缓冲区位图
在位图上绘制形状
将像素复制到本机内存,并保存内存指针
清除缓冲区位图
因此,可以将任意数量的形状保存到本机内存中,而不会遇到堆大小限制。这很有效
稍后需要绘制形状时(例如在onDraw()
)中):
清除缓冲区位图
使用保存的内存指针将像素从本机内存复制到缓冲区位图
在画布上绘制缓冲区位图
清除缓冲区位图
对下一个形状再次重复
问题当从内存快速绘制许多形状时,缓冲区位图
会出现各种延迟。基本上我们正在做
clear bitmap -> load pixels from memory onto it -> draw it on view canvas
在onDraw()
中,只有最新形状的像素会快速连续地绘制到画布上。似乎:
内部canvas.drawBitmap()
是异步的,有时会从位图中复制像素
Android的位图有一些隐藏的缓存机制李>
以前有人遇到过这样的麻烦吗?或者对此有什么见解
我知道可以在JNI中获取本机skia lib的画布实例并在其上绘制,但这是一种非标准方式。在最近的Android版本(3.0及以上,这是大多数设备)中,像素使用常规Java内存堆。随着硬件加速的引入,位图是异步绘制的,并且有一个缓存系统来管理作为纹理加载到GPU的位图。因此,您试图进行的黑客攻击可能会降低新设备的性能。如果您需要更多内存,请尝试在清单中使用largeHeap=“true”。在相对较新的Androids(如果我没记错的话,从3.0版开始)上使用硬件加速画布。drawBitmap
方法实际上不会绘制任何东西(以及dispatchDraw
,draw
和onDraw
)。相反,它会在显示列表中创建以下记录:
可能会无限期地缓存
可能(也将)在未来绘制,而不是立即绘制。它现在不是完全异步的,只是稍后在同一个线程中执行
我认为这两点就是你问题的答案
或者,您可以禁用视图/窗口的硬件加速,并查看您的方法是否有效
进一步阅读:
我不认为这两种可能性都是真的。我想知道您如何使用它查看不同图像的代码。@berserk我将尝试更新到源代码的链接。谢谢。好的,我会等的。我同意。另外,考虑到您只有16毫秒的时间来跟上60fps的速度,对于相当大的位图来说,高达几毫秒的时间实际上一点也不快。@DmitryZaitsevmemcpy
对于1000x1000 px的本机和后台数据,大约是3ms-8ms。瓶颈是Java端的Bitmap
。在java端复制像素太慢了。@yoah你是对的。它可以归结为canvas.drawBitmap(int[],…)
与canvas.drawBitmap(bitmap,…)
。第一个不是缓存的,但是速度很慢;第二个很快,但是缓存了,因此对我的意图没有用处。我每次都看到GL纹理被创建/销毁。虽然我不明白为什么安卓人会采用这种实现方式。无论如何,谢谢你的回答:)。我认为你对纹理缓存和显示列表的看法是正确的。当我使用int[]
(像素)而不是位图
作为缓冲区时,所有形状都正确绘制。