软件绘制源码流程分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件绘制源码流程分析相关的知识,希望对你有一定的参考价值。
Surface.lockCanvas
大致流程:
// 得到c层的 surface 对象
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
//声明 buffer
ANativeWindow_Buffer buffer;
// 获取GraphicBuffer
status_t err = surface->lock(&buffer, dirtyRectPtr);
// 创建 c层的SkiaCanvas对象,并且与java层的绑定
graphics::Canvas canvas(env, canvasObj);
// 设置buffer绑定到ANativeWindow_Buffer的bits结构中
canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));
Surface.lock
lock方法中 首先声明NativeWindowBuffer对象,然后调用dequeBuffe获取到ANativeWindwoBuffer对象接着请求SF真正创建GraphBuffer对象并返回NativeWindowBuffer
// 声明 ANativeWindowBuffer 对象
ANativeWindowBuffer* out;
//1 调用dequeueBuffer获取 ANativeWindowBuffer 对象
status_t err = dequeueBuffer(&out, &fenceFd);
// 2 创建GraphicBuffer 对象
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
//3.返回dequeueBuffer获取的ANativeWindowBuffer 对象
return err;
请求SF进程获取GraphBuffer
c层的surface对象调用lock方法传入ANatieWindow_Buffer,这块Buffer记录着lock方法返回的GraphBuffer绘制内存地址,绘制区域大小坐标等信息, ANatieWindow_Buffer内部变量bits用于之后和SkiaCanvas绑定用于直接渲染。
dequeneBuffer
// 从共享的位置mSharedBufferSlot,拿出GraphicBuffer
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
int buf = -1; //mSlots中对应的下标,需下一步 dequeneSF进程分配
// 跨进程 从SF进程的mSlots数组(BufferQueue)中分配一块 GraphicBuffer
status_t result = mGraphicBufferProducer->dequeueBuffer(
&buf, &fence, dqInput.width,
dqInput.height, dqInput.format,
dqInput.usage, &mBufferAge,
dqInput.getTimestamps ?
&frameTimestamps : nullptr);
// 得到GraphicBuffer
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
//请求 buffer
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
请求SF进程返回一个下标对应Slots中的位置,Slots才是SF中真正的GraphBuffer。然后把这个slot位置发送给SF返回真正可以用的Buffer空间,但是此时还并没有分配内存;当调用GraphBufferProducer对象的requestBuffer方法时将SF返回的那块SF中slots内存空间和对应的下标slot传入参数调用时 就可以真正的请求分配对应mSlot位置的GraphBuffer内存空间。
获取canvas
创建canvas对象,canvas的构造方法中表示native层没有bitamp不占内存,空画布,然后调用createCanvas方法返回来一个SkiaCanvas对象,内部通过SKiaBitmap承载绘制内容
//获取SkiaBitmap绑定到上面ANativeWindowBuffer中的bits属性中
if (surface.get() != nullptr)
if (outBitmap)
outBitmap->setInfo(imageInfo, rowBytes);
// 关键: 将bits指针设置给SKBitmap
outBitmap->setPixels(buffer->bits);
return true;
绑定SkiaBitmap到Buffer中的bits属性
Skiavas对象的mCanvas获取到SKBitmap对象然后和ANativeWindowBuffer的bits指针绑定,也就是SKBitmap指向了分配好的内存空间
unLockAndPost
// 设置一个空的bitmap,释放canvas的画布SKBitmap。也就是说此时SKBitmap不在引用到buffer了。
nativeCanvas->setBitmap(SkBitmap());
status_t err = mLockedBuffer->unlockAsync(&fd); //解除buffer的绑定
// 加入队列
err = queueBuffer(mLockedBuffer.get(), fd);
- 清空Canvas的 SKBitmap画布,解除与buffer的引用。
- 解除surface的buffer与 SF进程的GraphicBuffer的绑定。
- 将SF的GraphicBuffer入队BufferQueue,请求下一个vsync信号,通知SF来进行合成消费。
以上是关于软件绘制源码流程分析的主要内容,如果未能解决你的问题,请参考以下文章