在进行渲染时,有很多的渲染策略可以利用,在通常情况下,硬件渲染会比软件渲染更快,软件渲染则比较节省成本,但某些机制则必须依赖于硬件来进行。在进行照相机预览或者视频回放时,基于Overlay是常见的一种策略,可以提高流的流畅性。
基于Overlay的渲染通过在“LayerBuffer”模式的Layer中注册缓冲源“OverlaySource”来实现。
为了基于Overlay来创建Layer,在LayerBuffer中提供了如下参考过程:
代码:创建“LayerBuffer”模式的Layer的Overlay缓冲源
LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,sp< OverlayRef>* overlayRef,uint32_t w, uint32_t h, int32_t format)
: Source(layer), mVisibilityChanged(false),
mOverlay(0), mOverlayHandle(0), mOverlayDevice(0)
{
overlay_control_device_t* overlay_dev=mLayer.mFlinger->getOverlayEngine();
if (overlay_dev==NULL) {
return;
}
mOverlayDevice=overlay_dev;
overlay_t* overlay=overlay_dev->createOverlay(overlay_dev, w, h, format); //创建Overlay
if (overlay==NULL) {
return;
}
overlay_dev->setParameter(overlay_dev, overlay,OVERLAY_DITHER, OVERLAY_ENABLE);
mOverlay=overlay;
mWidth=overlay->w;
mHeight=overlay->h;
mFormat=overlay->format;
mWidthStride=overlay->w_stride;
mHeightStride=overlay->h_stride;
mInitialized=false;
mOverlayHandle=overlay->getHandleRef(overlay); //获取句柄
sp< O verlayChannel> channel=new OverlayChannel( &layer ); //设置对应的Layer
*overlayRef=new OverlayRef(mOverlayHandle, channel,mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
mLayer.mFlinger->signalEvent();
}
为了利用Overlay,需要首先创建Overlay对象,然后利用Overlay:: getBufferAddress()获得Overlay的地址,接着就可以操作Overlay了。参考过程如下:
代码:操作基于Overlay的surface的过程
int main(int argc, char** argv)
{
//创建线程池
sp< ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
//创建surfaceflinger的客户端
sp< SurfaceComposerClient> client=new SurfaceComposerClient();
//也即“LayerBuffer”模式的Layer
sp< Surface> surface=client->createSurface(getpid(), 0, 320, 240,PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
sp< ISurface> isurface=surface::getISurface(surface);
printf("isurface=%p\n", isurface.get());
sp< OverlayRef> ref=isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);
sp< Overlay> overlay=new Overlay(ref); //创建Overlay对象
overlay_buffer_t buffer;
overlay->dequeueBuffer(&buffer);
printf("buffer=%p\n", buffer);
void* address=overlay->getBufferAddress(buffer);
printf("address=%p\n", address); //在此操作Overlay的地址,执行想要的操作
overlay->queueBuffer(buffer);
return 0;
}
Overlay的驱动部分位于hardware\libhardware\modules\overlay目录下,关于Overlay的更底层实现,请参考overlay.cpp文件。