Android位图对象作为绘图缓冲区

Android位图对象作为绘图缓冲区,android,bitmap,java-native-interface,Android,Bitmap,Java Native Interface,设置: 我已经实现了一种本机(读取JNI)机制,将像素从位图对象复制到本机内存。这是通过本机内存中的malloc()uint23\u t array完成的,然后使用memcpy()将像素复制到位图的本机指针中。这工作得很好,已经过测试。像素从位图对象成功保存在本机内存中,并复制回位图对象,在屏幕上可见。它的复制速度非常快,对于相当大的位图,复制速度可达几毫秒。但渲染速度非常慢 意图: 执行上述操作是为了打破默认android位图上的堆限制(请参阅)。在本机内存和目标画布之间,只有1个JavaBi

设置: 我已经实现了一种本机(读取JNI)机制,将像素从
位图
对象复制到本机内存。这是通过本机内存中的
malloc()
uint23\u t array
完成的,然后使用
memcpy()
将像素复制到位图的本机指针中。这工作得很好,已经过测试。像素从
位图
对象成功保存在本机内存中,并复制回
位图
对象,在屏幕上可见。它的复制速度非常快,对于相当大的位图,复制速度可达几毫秒。但渲染速度非常慢

意图: 执行上述操作是为了打破默认android
位图上的堆限制(请参阅)。在本机内存和目标画布之间,只有1个Java
Bitmap
对象充当缓冲区

保存形状:

  • 清除缓冲区位图
  • 在位图上绘制形状
  • 将像素复制到本机内存,并保存内存指针
  • 清除缓冲区位图
  • 因此,可以将任意数量的形状保存到本机内存中,而不会遇到堆大小限制。这很有效

    稍后需要绘制形状时(例如在
    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的速度,
    对于相当大的位图来说,高达几毫秒的时间实际上一点也不快。@DmitryZaitsev
    memcpy
    对于1000x1000 px的本机和后台数据,大约是3ms-8ms。瓶颈是Java端的
    Bitmap
    。在java端复制像素太慢了。@yoah你是对的。它可以归结为
    canvas.drawBitmap(int[],…)
    canvas.drawBitmap(bitmap,…)
    。第一个不是缓存的,但是速度很慢;第二个很快,但是缓存了,因此对我的意图没有用处。我每次都看到GL纹理被创建/销毁。虽然我不明白为什么安卓人会采用这种实现方式。无论如何,谢谢你的回答:)。我认为你对纹理缓存和显示列表的看法是正确的。当我使用
    int[]
    (像素)而不是
    位图
    作为缓冲区时,所有形状都正确绘制。