blink渲染知识15- gl命令的生成和处理(command buffer)

这篇博客深入解析Android移动开发中GPU渲染过程,重点关注GL命令的生成,包括从RenderPass的Quads到DrawElements的调用链,以及CommandBuffer在渲染线程中的操作。博客内容涉及GLES2Implementation、CommandParser、Decoder和GPU调度的交互,揭示了Android Webview和硬件渲染器如何协同工作以执行GL命令。
摘要由CSDN通过智能技术生成

看看下面的stack:

是在render线程合成时的callstack, 主要是处理compositorframe中的renderpass里面的quard,并把它们drawglcontext上面。我们主要研究从此开始的gl的操作的过程。



他调用gl操作开始绘制:

#0 Init (_size=5,_command=299, this=0x85f00730) at../../gpu/command_buffer/common/cmd_buffer_common.h:52

注意,已经进入了commandbuffer里面了。

#1 SetCmd<gpu::gles2::cmds::DrawElements> (this=0x85f00730) at../../gpu/command_buffer/common/cmd_buffer_common.h:61

#2 SetHeader (this=0x85f00730) at../../gpu/command_buffer/common/../common/gles2_cmd_format_autogen.h:1913

#3 Init (_index_offset=0, _type=5123, _count=6, _mode=4,this=0x85f00730) at../../gpu/command_buffer/common/../common/gles2_cmd_format_autogen.h:1916

#4 DrawElements (index_offset=0, type=5123, count=6, mode=4,this=<optimized out>) at../../gpu/command_buffer/client/gles2_cmd_helper_autogen.h:419

#5 gpu::gles2::GLES2Implementation::DrawElements(this=0xa0803100, mode=4, count=6, type=5123, indices=0x0) at../../gpu/command_buffer/client/gles2_implementation.cc:878

#6 0x9bed9e1e in cc::GLRenderer::DrawQuadGeometry(this=this@entry=0x9f9fc000, frame=frame@entry=0xa1cff338,draw_transform=..., quad_rect=...,matrix_location=matrix_location@entry=0)

at ../../cc/output/gl_renderer.cc:2285

#7 0x9bedc310 in cc::GLRenderer::DrawSolidColorQuad(this=0x9f9fc000, frame=0xa1cff338, quad=0xa086f790) at../../cc/output/gl_renderer.cc:1545

#8 0x9bed7366 in cc::DirectRenderer::DrawRenderPass(this=this@entry=0x9f9fc000, frame=frame@entry=0xa1cff338,render_pass=render_pass@entry=0x9f7c92e0) at../../cc/output/direct_renderer.cc:386

#9 0x9bed754a in cc::DirectRenderer::DrawFrame(this=0x9f9fc000,

//这个函数会根据frame中的renderpass,遍历他们,并且把renderpass中的quard一个一个调用gl操作绘制出来。

render_passes_in_draw_order=0xa1cff63c,device_scale_factor=<optimized out>, device_viewport_rect=...,device_clip_rect=...,

disable_picture_quad_image_filtering=false) at../../cc/output/direct_renderer.cc:232

#100x9bf1263a in cc::LayerTreeHostImpl::DrawLayers(this=0xa0818c80, frame=0xa1cff620, frame_begin_time=...) at../../cc/trees/layer_tree_host_impl.cc:1605

#110x9bf18a34 in cc::SingleThreadProxy::DoComposite(this=this@entry=0xa085c220, frame_begin_time=...,frame=frame@entry=0xa1cff620) at../../cc/trees/single_thread_proxy.cc:432

#120x9bf19284 in cc::SingleThreadProxy::CompositeImmediately(this=0xa085c220, frame_begin_time=...) at../../cc/trees/single_thread_proxy.cc:350

#130x9bf08e3e in cc::LayerTreeHost::Composite(this=this@entry=0xa0803400, frame_begin_time=...) at../../cc/trees/layer_tree_host.cc:685

#140x9bf6feea in android_webview::HardwareRenderer::DrawGL(this=this@entry=0x9f923f80,stencil_enabled=stencil_enabled@entry=false,framebuffer_binding_ext=0, draw_info=draw_info@entry=0xa1cff8a8)

at ../../android_webview/browser/hardware_renderer.cc:224

#150x9c5d1af8 in android_webview::AwContents::DrawGL(this=<optimized out>, draw_info=0xa1cff8a8) at../../android_webview/native/aw_contents.cc:435

#160x9c6d5bea in draw_gl_50 (this=0x9f9e4fa0, data=0xa1cff964,what=<optimized out>) at../../third_party/android_plat_support/draw_gl_functor.cpp:103

#17android::(anonymous namespace)::DrawGLFunctor::operator()(this=0x9f9e4fa0, what=<optimized out>, data=0xa1cff964) at../../third_party/android_plat_support/draw_gl_functor.cpp:58

#180xb66971ea in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#190xb668a754 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#200xb6680a34 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#210xb667ea76 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#220xb667e636 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#230xb668db42 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#240xb669d836 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#250xb669e750 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#260xb66a027c inandroid::uirenderer::renderthread::RenderThread::threadLoop()() from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#270xb6c564d6 in android::Thread::_threadLoop(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libutils.so

#280xb6de0f4e in android::AndroidRuntime::javaThreadShell(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libandroid_runtime.so

#290xb6c56046 in ?? () from/tmp/tshao-adb-gdb-libs/system/lib/libutils.so

#300xb6e9b2e4 in __pthread_start(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#310xb6e992d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#320x00000000 in ?? ()



GLES2Implementation是实现了GLES2Interface,并使用commandbuffer

voidGLES2Implementation::DrawElements(

-GLES2CmdHelper:DrawElements(GLenummode,

GLsizei count,

GLenum type,

GLuint index_offset) {

gles2::cmds::DrawElements* c= GetCmdSpace<gles2::cmds::DrawElements>();

if (c) {

c->Init(mode,count, type, index_offset);

}

上述的DrawElements定义在gles2_cmd_format_autogen.h中,


cmd_buffer_helper.h中定义了GetCmdSpace

template<typename T>

T*GetCmdSpace() {

COMPILE_ASSERT(T::kArgFlags == cmd::kFixed,Cmd_kArgFlags_not_kFixed);

int32space_needed = ComputeNumEntries(sizeof(T));

T* data =static_cast<T*>(GetSpace(space_needed));

ForceNullCheck(data);

return data;

}



void*GetSpace(int32 entries) {


if (entries >immediate_entry_count_) {

WaitForAvailableEntries(entries);

if (entries> immediate_entry_count_)

returnNULL;

}


CommandBufferEntry* space = &entries_[put_];

//可见,分配cmd是从一个固有的buffer里面分配。

put_ +=entries;

immediate_entry_count_ -= entries;


DCHECK_LE(put_, total_entry_count_);

return space;

}


那么这个entries_缓冲何时分配的,何时提交出去?

boolCommandBufferHelper::AllocateRingBuffer() {分配的,

实际是调用如下函数创建的sharedmemory

scoped_refptr<Buffer>CommandBufferService::CreateTransferBuffer(size_tsize,) {

*id = -1;


scoped_ptr<SharedMemory> shared_memory(new SharedMemory());

if (!shared_memory->CreateAndMapAnonymous(size))

return NULL;


static int32next_id = 1;

*id =next_id++;


if(!RegisterTransferBuffer(

*id,MakeBackingFromSharedMemory(shared_memory.Pass(), size))) {

*id = -1;

return NULL;

}


returnGetTransferBuffer(*id);

}


既然生成glcommand是直接在使用了sharedmemoryringbuffer里分配的cmdentry, 那么这些cmds如何交给gpu的?


InProcessCommandBuffer::InitializeOnGpuThread(这个函数里面建立了inprocess command buffer使用的各种组件。

搞清楚gpuScheduler,GLES2Decoder,CommandParser之间的关系。

CommandParser知道保存cmdssharedmemory地址,并且维护一个get/putindex, getindexcmd,getindex == put index时表明取完了。

CommandParserprocessCommand函数处理一个command,也有processAllCommands函数处理所有的commands,实际处理工作交给其handler_,也就是gles2::GLES2Decoder::Create创建的decoderDoCommand()函数

实际的decoderGLES2DecoderImpl


Gles2DecoderImpl::DoCommand其实根据cmd类型,调用对应的handle函数:

比如对于DrawElementscmd调用GLES2DecoderImpl::HandleDrawElements

->error::ErrorGLES2DecoderImpl::DoDrawElements(

->glDrawElements

->GLApiBase::glDrawElementsFn

会调用从driver拿到的gldrawElements函数。


我们看看实际的执行gl命令的callstack:

#0 gfx::GLApiBase::glDrawElementsFn(this=0x9e591218, mode=4, count=6,

//这个函数会调用driver里面拿到的drawElements操作。

type=5123,indices=0x0) at gen/ui/gl/gl_bindings_autogen_gl.cc:2956

#1 0x9c6b3d70 ingpu::gles2::GLES2DecoderImpl::DoDrawElements(this=this@entry=0x9f765900, function_name=<optimized out>,instanced=instanced@entry=false, mode=<optimized out>,count=count@entry=6,

type=type@entry=5123, offset=0, primcount=primcount@entry=0) at../../gpu/command_buffer/service/gles2_cmd_decoder.cc:6584

#2 0x9c6b3e62 ingpu::gles2::GLES2DecoderImpl::HandleDrawElements(this=this@entry=0x9f765900, immediate_data_size=<optimized out>,c=...) at ../../gpu/command_buffer/service/gles2_cmd_decoder.cc:6620

#3 0x9c6b7f5c ingpu::gles2::GLES2DecoderImpl::DoCommand(this=0x9f765900, command=299, arg_count=<optimized out>,cmd_data=0x94547730) at../../gpu/command_buffer/service/gles2_cmd_decoder.cc:3709

#4 0x9c692fa6 ingpu::CommandParser::ProcessCommand(this=0x9e5bc448)

//commandparser的实际工作交给commanddecoder

at../../gpu/command_buffer/service/cmd_parser.cc:67

#5 0x9c6bbb7a ingpu::GpuScheduler::PutChanged(this=0x9f8ddb30) at

//putChanged,就是告诉说commandbuffer里面的命令内容有变化,会调用commandparser处理里面的命令。

../../gpu/command_buffer/service/gpu_scheduler.cc:81

#6 0x9c6beeb0 inRun (object=<optimized out>, this=0xa1cff340) at../../base/bind_internal.h:134

#7 MakeItSo(weak_ptr=..., runnable=...) at ../../base/bind_internal.h:882

#8 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(gpu::InProcessCommandBuffer::*)()>, void(gpu::InProcessCommandBuffer*), void(base::WeakPtr<gpu::InProcessCommandBuff

er>)>, void(gpu::InProcessCommandBuffer*)>::Run(base::internal::BindStateBase*)(base=0x9e5bc460) at ../../base/bind_internal.h:1169

#9 0x9c6930ce inRun (this=0x9f73a8a0) at ../../base/callback.h:401

#10gpu::CommandBufferService::Flush(this=0x9f73a880,

//这里会修改put_offset,然后调用一个putoffset change callback:

put_offset_change_callback_,其实是GpuScheduler::PutChanged

put_offset=<optimized out>) at../../gpu/command_buffer/service/command_buffer_service.cc:81

#11 0x9c6bfd3a ingpu::InProcessCommandBuffer::FlushOnGpuThread(this=0x9eed1e40, put_offset=465) at../../gpu/command_buffer/service/in_process_command_buffer.cc:510

#12 0x9c6becfe inRun (a1=@0x9e57d958: 465, object=<optimized out>,this=0xa1cff3a0) at ../../base/bind_internal.h:190

#13 MakeItSo(a2=@0x9e57d958: 465, weak_ptr=..., runnable=...) at../../base/bind_internal.h:909

#14base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(gpu::InProcessCommandBuffer::*)(int)>, void(gpu::InProcessCommandBuffer*, int), void(base::WeakPtr<gpu::InProcessCom

mandBuffer>,int)>, void (gpu::InProcessCommandBuffer*,int)>::Run(base::internal::BindStateBase*) (base=0x9e57d940) at../../base/bind_internal.h:1253

#15 0x9b933468 inRun (this=0xa1cff3c0) at ../../base/callback.h:401

#16android_webview::DeferredGpuCommandService::RunTasks(this=this@entry=0x9e58da00) at../../android_webview/browser/deferred_gpu_command_service.cc:180

#17 0x9b933630 inandroid_webview::DeferredGpuCommandService::ScheduleTask(base::Callback<void()> const&) (this=0x9e58da00, task=...) at../../android_webview/browser/deferred_gpu_command_service.cc:101

#18 0x9c6bf212 inQueueTask (task=...,this=0x9eed1e40) at../../gpu/command_buffer/service/in_process_command_buffer.h:177

#19gpu::InProcessCommandBuffer::Flush(this=0x9eed1e40, put_offset=465) at../../gpu/command_buffer/service/in_process_command_buffer.cc:559

#20 0x9ba0cae8 ingpu::CommandBufferHelper::Flush(this=0xa0883698) at../../gpu/command_buffer/client/cmd_buffer_helper.cc:156

#21 0x9b9374c8 inandroid_webview::ParentOutputSurface::SwapBuffers
//就是把commandbufferflush了,也就是让gpu执行命令

(this=0xac926cc0,frame=<optimized out>) at../../android_webview/browser/parent_output_surface.cc:22

#22 0x9b8a2cea incc::GLRenderer::SwapBuffers(this=0x9f8e0000, metadata=...) at../../cc/output/gl_renderer.cc:2357

#23 0x9b8d3874 incc::LayerTreeHostImpl::SwapBuffers(this=0x9f765580,

//parentcompositor合成完成后,调用swapbuffer。我认为,此时


frame=...) at../../cc/trees/layer_tree_host_impl.cc:1687

#24 0x9b8dd350 incc::SingleThreadProxy::CompositeImmediately

//parentcompositor的合成

(this=0x9f8abac0,frame_begin_time=...) at ../../cc/trees/single_thread_proxy.cc:364

#25 0x9b8ccef6 incc::LayerTreeHost::Composite(this=this@entry=0xa1bf7a00, frame_begin_time=...) at../../cc/trees/layer_tree_host.cc:685

#26 0x9b933fea inandroid_webview::HardwareRenderer::DrawGL(this=this@entry=0x9eed1c00,stencil_enabled=stencil_enabled@entry=false,framebuffer_binding_ext=0, draw_info=draw_info@entry=0xa1cff8a8)

at../../android_webview/browser/hardware_renderer.cc:224

#27 0x9bf95d58 inandroid_webview::AwContents::DrawGL(this=<optimized out>, draw_info=0xa1cff8a8) at../../android_webview/native/aw_contents.cc:435

#28 0x9c099e8a indraw_gl_50 (this=0x9f8ff690, data=0xa1cff964, what=<optimizedout>) at../../third_party/android_plat_support/draw_gl_functor.cpp:103

#29android::(anonymous namespace)::DrawGLFunctor::operator()(this=0x9f8ff690, what=<optimized out>, data=0xa1cff964) at../../third_party/android_plat_support/draw_gl_functor.cpp:58

#30 0xb66ae1ea in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#31 0xb66a1754 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#32 0xb6697a34 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#33 0xb6695a76 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#34 0xb6695636 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#35 0xb66a4b42 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#36 0xb66b4836 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#37 0xb66b5750 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#38 0xb66b727c inandroid::uirenderer::renderthread::RenderThread::threadLoop()() from

//render线程,那么可以说明,gpu 线程,其实就是render线程。

/tmp/tshao-adb-gdb-libs/system/lib/libhwui.so

#39 0xb6c6d4d6 inandroid::Thread::_threadLoop(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libutils.so

#40 0xb6df7f4e inandroid::AndroidRuntime::javaThreadShell(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libandroid_runtime.so

#41 0xb6c6d046 in?? () from /tmp/tshao-adb-gdb-libs/system/lib/libutils.so

#42 0xb6eb22e4 in__pthread_start(void*) () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#43 0xb6eb02d4 in__start_thread () from /tmp/tshao-adb-gdb-libs/system/lib/libc.so

#44 0x00000000 in?? ()


那么。我们可以看出来:

render线程执行DrawGL的过程中,函数SingleThreadProxy::CompositeImmediately会先调用DoComposite来完成合成工作,这里会遍历compositorframe里面的renderpass,并针对所有的quard生成glcmds,保存到commandbuffer里面。


DoComposite完成后,会调用LayerTreeHostImpl::SwapBuffers,实际上执行的工作是:flush当前的commandbuffer里面的gl命令,也就是在glcontext下面执行gl命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值