blink渲染知识16 - raster干了什么

本文详细探讨了Chrome浏览器中Raster线程如何处理和绘制待合成的图层,包括从WebCore线程到Impl线程的转移,多线程Raster化过程,以及如何将Raster任务分配到Raster线程执行。Raster线程主要负责将图层转换为纹理,利用GPU进行合成。同时,文章提到了Raster任务的调度、PicturePile的分析与绘制,以及内存和优先级管理等内容。
摘要由CSDN通过智能技术生成

我们知道,在childcompositor里,implthread里,pendingtreeraster之后,才会被activateactivetree. 而且raster任务由一些rasterthread执行,那么这些raster操作干了什么?

看看这篇chromium的官方英文文章:

https://www.chromium.org/developers/design-documents/impl-side-painting

引入了impl-sidepainting之后,raster操作从webcore线程挪到了impl线程,impl线程安排rastertaskrasterthread去真正执行。webcore线程绘制到skpicture里面。里面都是displaylist. 并且划分了picturepile,针对一个layer,划分成多个tile,每个tile有不同的位置,优先级,还有不同的resolution.impl线程针对tile排序,产生rastertaskraster线程去操作。

绘制的结果产生texture,通过sharedmemory供给gpumemory.

impl 线程合成时,根据resourceid, textureid)来检查该tile对应texture是否已经在gpu中了,而后可以合成。



1.30.1 Multithreaded Rasterization





Implementationstatus:

crbug.com/169282,andhttps://code.google.com/p/chromium/issues/list?q=label:Cr-Internals-Compositing-Rasterization

Thisfeature is referred to as "multithreaded painting" and"impl-side painting" in some forums.

Background& Problem Statement
Ourcurrent compositor thread architecture is built around the ideaof rasterizing layers on the main webkit thread and then, on thecompositor thread, drawing the bits of the layers that we havebased on their various animated and scrolled positions. Thisallows us to move the page up and down, e.g. due to fingerdragging, without having to block on the webkit thread. When atile is exposed that does not have contents, we draw acheckerboard and wait for the main thread to rasterize thattile.

    1. Wewant to be able to fill in checkerboards without requiring anew commit, since that requires going to a busy webkitthread and pulling in a whole new tree + damage. We also wantto be able to render tiles at multiple resolutions, andquality levels. These kinds of tricks reduce memory pressure,avoid the jarring interruption of checkerboards.

TheExcessive Checkerboarding Problem

A lot of our unwanted checkerboarding comes from invalidatesgetting intermixed with "requests" from the implthread to fill in missing tiles. In the current architecture, wecan only rasterize tiles on the main thread, using webkit'srendering data structures. If webkit's rendering tree iscompletely unchanged, then the page scrolls, all therasterization requests that go to the main thread are easilysatisifed by webkit.

However, any time javascript changes the rendering tree, we havethe following problem: we have some "newly exposed tiles"that the compositor thread needs to prevent checkerboarding.But, annoyingly, any of the previously-painted tiles that webkitsays were invalidated. We can only paint the new rendering tree-- the old rendering tree is gone. So, we have two options atthis point:

1.Draw the new tiles with the new rendering tree, and redraw theold tiles with the new rendering tree

2.Draw only the new tiles, and let the old tiles stick around.


#2doesn't work well at all, of course: if you have a page thattoggles between green and blue constantly, what you'd see is arandom mix of green and blue page at any given moment. We wantto preserve the "atomicity of rendering" --- meaningthat the complete state of a web page at rAF time is what getsput on the screen.


Thereis a variant on 2 where we draw the new tiles, as well as anyold tiles that are *onscreen*. If a tile is offscreen, then wemake a note that is is invalid, but dont repaint it. In thegreen-blue scenario, this causes the screen to be green or blue,but never both, as long as you dont scroll. We ship thison Chrome Android m18. Even so, this is undesirable: if youscroll, you'll see a mix of content. This is expedientperformance wise, but makes us all feel dirty.



Our other source of heavy checkerboarding is latency related.The work we do on the main thread is based on as scroll positionupdate message that comes from the impl thread. This message isitself not very latent, arriving on the main thread millisecondsafter it is sent. However, paints for a new set of tiles cantake 300ms + to complete, even with the relaxed atomicityapproach described above. By the time we have painted all 300msworth of work, the page has scrolled way past the originalscroll position, and half of the tiles we worked hard to prepareare irrelevant. We have discussed a variety of solutions here,but the real core problem is that the main thread cannot beupdated fast enough with the new scroll positions to really everkeep up properly.



Planned Solution

Displaylists. Namely, SkPictures,modified a bit to support partial updating. We call this aPicturepile,a name borrowed from the awesome folks behind Android Browser.Theidea is to only capture a display list of the webkit renderingtree on the main thread. Then, do rasterization on the implthread, which is much more responsive.

Onmain thread, web content is turned into PictureLayers. Picturelayers make a recording of the layer into a PicturePile.We track invalidations in SkRegions and during the display listcapture process, decide between re-capturing the entire layer orjust grabbing the invalidated area and drawing it on-top of thepreviously recorded base layer.

Duringcommit, we pass these PicturePiles to aPictureLayerImpl. Recall,layers can change in scale over time, under animation, pinchzoom, etc. To handle this, a PictureLayerImpl manages one ormore PictureLayerTiling objects (via a PictureLayerTilingSet),which is a decomposition of the layer's entire contents intotiles at a picture screenspace resolution. So for example, a512x512 layer might have a tiling into 4 256x256 tiles for a 1:1ratio of screenspace pixels to content pixels, but also 1256x256 tile for a 1:2 ratio of screenspace to conten space.We manage these tilings dyanmically.

一个layer可能被分成不同scale级别的tile.



A tiling itself takes thelayers entire size, not just the visible part, and breaks it upinto Tiles. Each tile represents a rectangle of the PicturePilepainted into a Resource ID [think, GL texture], at a givenresolution and quality setting.

Everytile is given a set of TilePriority values by thePictureLayerImpl based on its screen space position, animationand scroll velocity, and picture contents. Thesedifferent priorities encode how soon, in time units, the tilecould be visually useful onscreen. Key metrics are things like"how soon will it be visible" and "how soon willit be crisp" and "is this a tile we'd use if a crispone wasn't available?"


TheseTiles are registered to the TileManager, which keeps these tilessorted based on their priority and some global priority states.Tiles are binned in orders of urgency (needed now, needed in thenext second, needed eventually, never going to be needed) andthen sorted within their bin.The total GPU Memory budget is then assigned in decreasingpriority order to these tiles. Tiles that are given permissionto use memory are then added to a rasterization queue if needed.

tile都有优先级排序,根据优先级决定是否给一个tile分配gpumemory.


Theraster thread scheduler is a very simple solution: on the implthread, we simply pop from the raster queue, dispatch the rastertask. We keep a certain number of jobs enqueued per thread,opting to not enqueue them all so that if the prioritizationchanges much in the future, we wont do redundant work.


JPEG/PNG/etcbitmaps are stored in the display lists in still-encoded notdecodedformto keep display list recording cost low and memory footprintsmall. Thus, the first time we draw a bitmap, a costly decodeand downsample operation may be needed. Thus, before dispatch,tiles are "cracked open" to determine whether anybitmaps need to be decompressed, using the SkLazyPixelRefinterface to WebCore's ImageDecodingStore. If decoding isneeded, the tile is held in a side queue while a decoding taskis dispatched to the raster threads. When the decodes are done,raster tasks are enqueued. webcore线程并不decodejpeg图片,当rastertask发现有图片需要解码时,会将此task挪到另一queue里,等decode完成后才从新enqueuetask.

This approach fixes the “atomicity of commits” problem byallowing us to servie checkerboard misses without havin to go tothe laggy, potentially changed main thread. Inthe previous example, when the compositor sees a checkerboardedtile, we can rasterize it without having to start a commit flow,allowing us to disallow commits entirely during flings and otherheavy animation use cases.

compositor线程发现一个tile没有内容显示时,可以触发raster工作,而不用让webcore线程去从新走一遍。这提高了效率,尤其当用户快速滚动时。

Hitch-free commits

A key challenge with thisapproach is switching from the old tree to the new tree. Inthe existingarchitecture, when we go to switch to the new tree, we havepainted and uploaded all the tiles, so the tree can beimmediately switched.

In the impl-side painting architecture, we need to createPictureLayerImpl's in order to begin rasterizing them. Moreover,those impls need to be attached together to theLayerTreeHostImpl in order to get their screenspace positions,which are essential in computing their priorities.



The obvious way to do this is to simply commit the main treeto the impl tree like we usually do. However, if we do that,then the impl tree now has holes in it where there wereinvalidations. At this point, the impl-side has two options whenvsync comes around: checkerboard, or drop the frame. Neither isvery cool.



Our solution is the LayerTreeImpl. Whereas the previousarchitecture's LayerTreeHostImpl had a root layer and all itsassociated state, we instead introduce LayerTreeImpl, which hasall the state associated with a layer tree: scrolling info,viewport, background color, etc. The LTHI then stores not one,but two LayerTreeImpl's: theactive tree is the one we are drawing, while the pending tree isthe one we are rasterizing. Priorityis given to the active tree, but once the pending tree is fullypainted, we activate it and throw away the old one. This allowsus to switch between old and new trees without janking.

我们在activetree上合成,在pendingtreeraster,pendingtree raster完成,就替换成activetree.这样提高了合成速度。

Handling GiantSkPictures

Onepotential challenge to impl-side painting compared to ourexisting painting model is that the SkPicture for a given layerare potentially unbounded. We plan to mitigate this by limitingthe PicturePile's size to a 10,000px (emperically determined)portion of the total layer size cenetered around the viewport atthe time of the picture pile's first creation. When the implthread starts needing tiles outside the pile's area, we willasynchronously trigger the main thread to go update the pilearound the new viewport center.

Choosingthe scale at which to raster


Wheneverwe compute the draw properties for a PictureLayerImpl, we alsodecide what tilings it should have, or in other words, at whatscales it should have sets of tiles. To do this we track twoscale values: The ideal scale, and the raster scale. The idealscale is the scale at which we should create tiles to give thetexels in the tile a 1:1 correspondence with pixels on thescreen. The raster scale is the high-resolution scale at whichwe are currently creating tiles. When we set the raster scale tobe equal to the ideal scale, we get crisp tiles. This is whatwe'd like to have at all times, but we limit this forperformance reasons. During a pinch gesture, or an acceleratedanimation, the raster scale lags behind the ideal scale. CSS canchange the scale of a layer through the DOM, and we limit howoften it is allowed to change the raster scale. Thisdecision to reset the raster scale to the ideal or leave italone is made in PictureLayerImpl::ManageTilings.Whenever the raster scale changes, we add a tiling both at theraster scale, and at a low resolution related to the rasterscale. These tilings aremarked as HIGH_RESOLUTION and LOW_RESOLUTION and are givenpriority as we raster tiles for the layer.

rasterscale是在manageTilings里面设置的,当改动时,我们会创建高/resolutiontile



Texture Upload

Onekey challenge on lowend devcies is that uploading a single256x256 texture can take many milliseconds, sometimes as crazyas 3-5ms. Because of this, we have to carefully throttleour texture uploads so that we dont drop a frame. To do this, weare adopting a new approach of async texture uploads. Instad ofissuing standard glTexImage calls, we instead place texturesinto shared memory and then instruct the GPU process to do theupload when-convenient. This enables the GPU process todo the upload during idle times, or even on another thread. Thecompositor then polls the GPU process via the queryinfrastructure to determine if the upload is complete. Only whenthe upload is complete will we draw with it.

Rasterthread并不把绘制完成的内容直接调用gltextImage提交给gpu,因为比较慢,而是把结果用sharedmemory共享给gpu线程,其实就是render线程。render线程会拿到raster结果,并提交到gpu.Compositorgpu线程查询该资源是否已经被提交,如果已经提交就拿来合成。



HandlingsetPictureListener

Ifthe embedder has a picture listener, we need to send aserialized SkPicture to the embedding process. We would need to,at every impl-side swapbuffers, serialize our SkPictures for allthe active layers (plus the bitmaps) and send them to the mainthread.



FollowupWork

Theinitial impl-side painting implementation is expected to enablethe following followup use cases:

Low-restiles: Fortiles that take a long time to rasterize, we may want torasterize them at half or third resolution. This oftendramatically reduces (5-6x anecdotally) raster cost and allowsus to avoid checkerboarding during fling. However, it is worthnoting that some Android users criticized this behavior on ICSdevices as making fonts look too ugly. High-dpi devices maychange the UX impact of this behavior on users.



Just-in-timescaling: Wecurrently do resizing of content at many layers in the pipeline.For example, we rasterize layers at their content resolutionwithout consideration to their screenspace transform. Thus, alayer that is -webkit-transform: scale(0.5)’d will actuallypaint at its full size. Similarly, we resize images insidewebkit at their content resolution. We could reducerasterization/decode costs and memory footprint if we could doall of this scaling using the draw-time transforms on the implthread.


Acceleratedpainting: Aninteresting property of impl-side painting is that it cleans upour accelerated painting story. We would store the SkPicture fora layer, and then can decide to rasterize a layer with the GPUwithout having to involve the main thread at all in the process.








触发rastercallstack

等待之后,在ThreadProxy::ScheduledActionCommit()函数中还会创建rastertask:

#0 cc::TileManager::ScheduleTasks(this=0xa1c0fc00,

//这里应该会为每个需要rastertile创建一个rastertask 放入队列中。

tiles_that_need_to_be_rasterized=...) at../../cc/resources/tile_manager.cc:924

#1 0x9b7b301c in cc::TileManager::ManageTiles (this=0xa1c0fc00,state=...) at ../../cc/resources/tile_manager.cc:662

#2 0x9b7c0dfe in cc::LayerTreeHostImpl::ManageTiles(this=0x9e5f3600)

//这里调用tilemanger来处理managertiles

at ../../cc/trees/layer_tree_host_impl.cc:431

#3 0x9b7c53f2 in cc::LayerTreeHostImpl::CommitComplete(this=0x9e5f3600)

//commit完成。

at ../../cc/trees/layer_tree_host_impl.cc:346

#4 0x9b7ced86 in cc::ThreadProxy::ScheduledActionCommit(this=0x971cc1c0) at ../../cc/trees/thread_proxy.cc:1004

#5 0x9b7b6b3c in cc::Scheduler::ProcessScheduledActions





Raster task类:

class RasterTaskImpl : public RasterTask {定义在tile_manager.cc中。

而实际的raster操作都给了classCC_EXPORT PicturePileImpl : public PicturePileBase

1.PicturePileImpl::AnalyzeInRect

2.void PicturePileImpl::RasterToBitmap(



PicturePileImpl::AnalyzeInRect

->RasterForAnalysis()

->void PicturePileImpl::RasterCommon(

有一个PictureRegionMap,维护了一堆picture,下面调用pictureraster.

->int Picture::Raster(













那么,picturePileImpl中的picture哪里来的?

bool PicturePile::UpdateAndExpandInvalidation(

中会调用Picture::Create函数。

貌似是要invalidate,然后根据rects算出需要创建一些picture.

看看callstack:



#0 cc::PicturePile::UpdateAndExpandInvalidation

//每个pictureLayer有一个picturePile. 这个函数会针对这个picturePile建立一系列Picture对象。逻辑上会针对rect判断是否创建Picture

这个函数的具体逻辑就是根据他的rect,计算出一堆invalid的或者说有变化的tile,其实也是子rect,这一堆tile就够成了invalidtiles. 然后把这些tile按照x,y坐标排序,也就是cluster操作,排完序后,针对每个tile建立一个picture.这些picture都存储到了picture_map_里面,这个map存储了PictureInfo

那么是否可以认为一个picturelayer 对应一个picturepile

(this=this@entry=0x94d96c00, painter=painter@entry=0x94d8e374,invalidation=invalidation@entry=0x94d1a880,background_color=background_color@entry=0,

contents_opaque=contents_opaque@entry=false,contents_fill_bounds_completely=contents_fill_bounds_completely@entry=false,visible_layer_rect=..., frame_number=frame_number@entry=2,

recording_mode=recording_mode@entry=cc::Picture::RECORD_NORMALLY,stats_instrumentation=0x96461300) at../../cc/resources/picture_pile.cc:159

#1 0x9d260696 in cc::PictureLayer::Update(this=0x94d1a600, queue=<optimized out>,occlusion=<optimized out>) at../../cc/layers/picture_layer.cc:139

#2 0x9d29e472 in cc::LayerTreeHost::PaintLayerContents(this=this@entry=0x9648a800, render_surface_layer_list=...,queue=queue@entry=0x94da28e0,did_paint_content=did_paint_content@entry=0x9a4c485e,

need_more_updates=need_more_updates@entry=0x9a4c485f) at../../cc/trees/layer_tree_host.cc:994

#3 0x9d29e858 in cc::LayerTreeHost::UpdateLayers(this=this@entry=0x9648a800, root_layer=0x9648ab00, queue=0x94da28e0)at ../../cc/trees/layer_tree_host.cc:830

#4 0x9d29ea96 in cc::LayerTreeHost::UpdateLayers(this=0x9648a800, queue=<optimized out>) at../../cc/trees/layer_tree_host.cc:696

#5 0x9d2b092e in cc::ThreadProxy::BeginMainFrame(this=0x94d861c0, begin_main_frame_state=...) at../../cc/trees/thread_proxy.cc:817

#6 0x9d2b1792 in Run (a1=..., object=<optimized out>,this=0x9a4c4ab8) at ../../base/bind_internal.h:190

#7 base::internal::InvokeHelper<true, void,base::internal::RunnableAdapter<void(cc::ThreadProxy::*)(scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrame

AndCommitState> >)>, void (base::WeakPtr<cc::ThreadProxy>const&, scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>>)>::MakeItSo(base::i

nternal::RunnableAdapter<void(cc::ThreadProxy::*)(scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>>)>, base::WeakPtr<cc::ThreadProxy>

const&,scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>>) (runnable=..., weak_ptr=..., a2=...) at../../base/bind_internal.h:909

#8 0x9d2b184a in base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(cc::ThreadProxy::*)(scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::T

hreadProxy::BeginMainFrameAndCommitState> >)>, void(cc::ThreadProxy*,scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>>), void (base::

WeakPtr<cc::ThreadProxy>,base::internal::PassedWrapper<scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>> >)>, void (cc::ThreadProxy*,

scoped_ptr<cc::ThreadProxy::BeginMainFrameAndCommitState,

//webcore线程要paint所有layer

base::DefaultDeleter<cc::ThreadProxy::BeginMainFrameAndCommitState>>)>::Run(base::internal::BindStateBase*) (base=0x96492aa0)

#9 0x9db19c48 in Run (this=0x9a4c4cb0) at../../base/callback.h:401

#10 base::MessageLoop::RunTask (this=this@entry=0xafe34440,pending_task=...) at ../../base/message_loop/message_loop.cc:464

#11 0x9db19d00 in base::MessageLoop::DeferOrRunPendingTask(this=this@entry=0xafe34440, pending_task=...) at../../base/message_loop/message_loop.cc:482

#12 0x9db1a416 in base::MessageLoop::DoWork (this=0xafe34440) at../../base/message_loop/message_loop.cc:596

#13 0x9db1a966 in base::MessagePumpDefault::Run (this=0x94d8e4a8,delegate=0xafe34440) at../../base/message_loop/message_pump_default.cc:32

#14 0x9db1a03a in base::MessageLoop::RunHandler (this=0xafe34440)at ../../base/message_loop/message_loop.cc:407

#15 0x9db215d8 in base::RunLoop::Run (this=this@entry=0x9a4c4d20)at ../../base/run_loop.cc:49

#16 0x9db1964c in base::MessageLoop::Run (this=<optimized out>)at ../../base/message_loop/message_loop.cc:300

#17 0x9db2a136 inbase::Thread::ThreadMain (this=0xa1fd4b50) at

//webcore线程

../../base/threading/thread.cc:225

#18 0x9db27f5e in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

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

#20 0xb6eb02d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#21 0x00000000 in ?? ()



还是需要看看webcore线程除了创建Picture还干了什么。

picture.cc中有rasterrecord函数,先看看Picture::Create干了什么:

Picture::Create

->1. new Picture(layer_rect)

  1. Picture::Record

    ->1. SkPictureRecorder::beginRecording

    1. 2. 拿到SkCanvas

    3. WebContentLayerImpl::PaintContents( SkCanvas* canvas,

    const gfx::Rect& clip,//这个cliprect就是要画的picturerect.

    gfx::RectF* opaque,

    ContentLayerClient::GraphicsContextStatusgraphics_context_status)

    -->OpaqueRectTrackingContentLayerDelegate::paintContents

    //这里已经是webcore,Webkit的代码了。

    ->GraphicsLayer::paint(), GraphicslayerOpaqueRectTrackingContentLayerDelegatem_painter.

    ->GraphicsLayer::paintGraphicsLayerContents

    ->CompositedLayerMapping::paintContents

    ->CompositedLayerMapping::doPaintTask

    ->RenderLayer::paintLayerContents































tile分成很多类型,有优先级:

// Tile manager classifying tiles into a few basic bins:

enum ManagedTileBin {

NOW_AND_READY_TO_DRAW_BIN = 0, // Ready to draw and withinviewport.

NOW_BIN = 1, // Needed ASAP.

SOON_BIN = 2, // Impl-side version ofprepainting.

EVENTUALLY_AND_ACTIVE_BIN = 3, // Nice to have, and has a taskor resource.

EVENTUALLY_BIN = 4, // Nice to have, if we've gotmemory and time.

AT_LAST_AND_ACTIVE_BIN = 5, // Only do this after all otherbins.

AT_LAST_BIN = 6, // Only do this after all otherbins.

NEVER_BIN = 7, // Dont bother.

NUM_BINS = 8

// NOTE: Be sure to update ManagedTileBinAsValue andkBinPolicyMap when adding

// or reordering fields.

};



tile raster mode tilepriority都是怎么计算的?

Tile priority是分tree的:一个tile有一个数组存储priority:

TilePriority priority_[NUM_TREES];

每个priority实例存有一个prioritybin:

enum PriorityBin { NOW, SOON, EVENTUALLY };





enum WhichTree {

// Note: these must be 0 and 1 because we index with them invarious places,

// e.g. in Tile::priority_.

ACTIVE_TREE = 0,

PENDING_TREE = 1,

NUM_TREES = 2

// Be sure to update WhichTreeAsValue when adding new fields.

};



tree也有treepriority:

enum TreePriority {

SAME_PRIORITY_FOR_BOTH_TREES,

SMOOTHNESS_TAKES_PRIORITY,

NEW_CONTENT_TAKES_PRIORITY







tile readyto draw如何评判?

bool ManagedTileState::TileVersion::IsReadyToDraw() const {

switch (mode_) {

case RESOURCE_MODE:

return !!resource_;

case SOLID_COLOR_MODE:

case PICTURE_PILE_MODE:

return true; //如果是solidcolor或者picturepile mode,直接返回true.

}

NOTREACHED();

return false;

}





一个tilestate里有rastermode:

enum RasterMode {

HIGH_QUALITY_RASTER_MODE = 0,

LOW_QUALITY_RASTER_MODE = 1,

NUM_RASTER_MODES = 2

};



针对每个rastemode有一个TileVersion.

每个tileVersion有一个mode:

enum Mode { RESOURCE_MODE, SOLID_COLOR_MODE, PICTURE_PILE_MODE };



所谓resource就是gpumemory.





仔细看看voidTileManager::ManageTiles干了什么?

→ 1. UpdatePrioritizedTileSetIfNeeded 根据设置的优先级获取指定优先级的tiles

  1. AssignGpuMemoryToTiles()这里并没有实际给上述得到的tiles分配gpumem, 成功分配了memtiles存储到tiles_that_need_to_be_rasterized里。而是根据resourcepool计算当前内存是否够分配,如果够,就更新数据量。而并没有实际分配。使用的resource_pool_ResourcePool.

  2. ScheduleTasks(tiles_that_need_to_be_rasterized);为这些tile建立rastertask.

    每个tile都有picturepile,









ResourcePool:

这个resourcepool是在LayerTreeHostImpl::CreateAndSetTileManager()里面建立的。且使用zerocopy(是指不需要把raster的结果copygpu线程,而是采用sharedmem,直接rastersharedmem),建立ResourcePool时的targetGL_TEXTURE_EXTERNAL_OES。而分配resource时,会走到ResourceProvider::CreateManagedResource.

一个调用ResourcePool分配资源的callstack

#0 cc::ResourceProvider::Resource::Resource (this=0xbe9afb00,texture_id=0, size=...,origin=cc::ResourceProvider::Resource::Internal, target=36197,filter=9729, texture_pool=24577, wrap_mode=33071,

hint=cc::ResourceProvider::TextureUsageAny,format=cc::RGBA_8888) at ../../cc/resources/resource_provider.cc:298

#1 0x9d52e3de in cc::ResourceProvider::CreateGLTexture(this=0x9a77fb60, size=..., target=<optimized out>,texture_pool=texture_pool@entry=24577,wrap_mode=wrap_mode@entry=33071,

hint=hint@entry=cc::ResourceProvider::TextureUsageAny,format=format@entry=cc::RGBA_8888) at../../cc/resources/resource_provider.cc:709

#2 0x9d52e59a in cc::ResourceProvider::CreateManagedResource(this=<optimized out>, size=..., target=<optimized out>,wrap_mode=wrap_mode@entry=33071,hint=hint@entry=cc::ResourceProvider::TextureUsageAny,

format=cc::RGBA_8888) at../../cc/resources/resource_provider.cc:677

#3 0x9d530376 in cc::ScopedResource::AllocateManaged(this=0x7f660da8, size=..., target=<optimized out>,format=<optimized out>) at../../cc/resources/scoped_resource.cc:45

#4 0x9d52b160 in cc::ResourcePool::AcquireResource(this=0x7f616eb0, size=...) at ../../cc/resources/resource_pool.cc:69

#5 0x9d536330 in cc::TileManager::CreateRasterTask(this=this@entry=0xa0f09080, tile=tile@entry=0x7f1813c0) at../../cc/resources/tile_manager.cc:990

#6 0x9d5366b2 in cc::TileManager::ScheduleTasks(this=0xa0f09080, tiles_that_need_to_be_rasterized=...) at../../cc/resources/tile_manager.cc:948

#7 0x9d53611c in cc::TileManager::ManageTiles(this=0xa0f09080, state=...) at../../cc/resources/tile_manager.cc:662

#8 0x9d543f28 in cc::LayerTreeHostImpl::ManageTiles(this=0x900b2b00) at ../../cc/trees/layer_tree_host_impl.cc:433

#9 0x9d548566 in cc::LayerTreeHostImpl::CommitComplete(this=0x900b2b00)

//commit完成,正准备要创建raster工作。

at ../../cc/trees/layer_tree_host_impl.cc:348

#10 0x9d551f12 in cc::ThreadProxy::ScheduledActionCommit(this=0x95d3ce00) at ../../cc/trees/thread_proxy.cc:1004

#11 0x9d539c3c in cc::Scheduler::ProcessScheduledActions(this=this@entry=0xa0370a00) at ../../cc/scheduler/scheduler.cc:665

#12 0x9d539dd6 in cc::Scheduler::NotifyReadyToCommit(this=0xa0370a00) at ../../cc/scheduler/scheduler.cc:220

#13 0x9d52fdc6 in cc::ResourceUpdateController::OnTimerFired(this=0x98470900) at../../cc/resources/resource_update_controller.cc:111

#14 0x9d52fa7a in Run (object=<optimized out>,this=0xbe9b00e0) at ../../base/bind_internal.h:134

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

#16 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(cc::ResourceUpdateController::*)()>, void(cc::ResourceUpdateController*), void(base::WeakPtr<cc::ResourceUpdateContr

oller>)>, void(cc::ResourceUpdateController*)>::Run(base::internal::BindStateBase*)(base=0x7f660b38) at ../../base/bind_internal.h:1169

#17 0x9ddbac48 in Run (this=0xbe9b01f0) at../../base/callback.h:401

#18 base::MessageLoop::RunTask (this=this@entry=0xa031da20,pending_task=...) at ../../base/message_loop/message_loop.cc:464

#19 0x9ddbad00 in base::MessageLoop::DeferOrRunPendingTask(this=this@entry=0xa031da20, pending_task=...) at../../base/message_loop/message_loop.cc:482

#20 0x9ddbb416 in base::MessageLoop::DoWork (this=0xa031da20) at../../base/message_loop/message_loop.cc:596

#21 0x9dd9e4f8 in DoRunLoopOnce (delayed_scheduled_time_ticks=0,native_delegate=<optimized out>, obj=0xbe9b028c,env=0xb4f51240) at ../../base/message_loop/message_pump_android.cc:35

#22Java_com_jetpack_dolphin_webkit_org_chromium_base_SystemMessageHandler_nativeDoRunLoopOnce(env=0xb4f51240, jcaller=0xbe9b028c,messagePumpDelegateNative=<optimized out>,delayedScheduledTimeTicks=0)

at gen/base/jni/SystemMessageHandler_jni.h:42

#23 0xa09ba6c8 in ?? ()

#24 0xa09ba6c8 in ?? ()







一个实际raster工作的callstack:

#0 SkPicture::draw(this=0x93559c60, surface=0x91b01a7c, callback=0x91b01b74) at../../third_party/skia/src/core/SkPicture.cpp:281

#1 0x9d520c58 in cc::Picture::Raster (this=this@entry=0x95ff5c50,canvas=canvas@entry=0x91b01a7c, callback=callback@entry=0x91b01b74,negated_content_region=..., contents_scale=contents_scale@entry=1)

at ../../cc/resources/picture.cc:411

#2 0x9d526a6c in cc::PicturePileImpl::RasterCommon(this=0x9a780380, canvas=0x91b01a7c, callback=0x91b01b74,canvas_rect=..., contents_scale=contents_scale@entry=1,

rendering_stats_instrumentation=rendering_stats_instrumentation@entry=0x95f8ba80,is_analysis=is_analysis@entry=true) at../../cc/resources/picture_pile_impl.cc:312

#3 0x9d526b26 in cc::PicturePileImpl::RasterForAnalysis(this=this@entry=0x9a780380, canvas=canvas@entry=0x91b01a7c,canvas_rect=..., contents_scale=contents_scale@entry=1,

stats_instrumentation=stats_instrumentation@entry=0x95f8ba80)at ../../cc/resources/picture_pile_impl.cc:93

#4 0x9d526ebe in cc::PicturePileImpl::AnalyzeInRect(this=this@entry=0x9a780380, content_rect=...,contents_scale=<optimized out>,analysis=analysis@entry=0x9000c72c, stats_instrumentation=0x95f8ba80)

at ../../cc/resources/picture_pile_impl.cc:381

#5 0x9d533dd4 in Analyze(picture_pile=0x9a780380, this=0x9000c710) at../../cc/resources/tile_manager.cc:112

#6 AnalyzeAndRaster(picture_pile=0x9a780380, this=0x9000c710) at../../cc/resources/tile_manager.cc:97

#7 cc::(anonymous namespace)::RasterTaskImpl::RunOnWorkerThread(this=0x9000c710) at ../../cc/resources/tile_manager.cc:70

#8 0x9d531742 in cc::TaskGraphRunner::RunTaskWithLockAcquired(this=this@entry=0x9ea4a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:419

#9 0x9d53187a in cc::TaskGraphRunner::Run(this=0x9ea4a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:362

#10 0x9ddcab80 in base::DelegateSimpleThread::Run(this=0x9652aa60) at ../../base/threading/simple_thread.cc:81

#11 0x9ddcad8c in base::SimpleThread::ThreadMain(this=0x9652aa60) at ../../base/threading/simple_thread.cc:60

#12 0x9ddc8f5e in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

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

#14 0xb6eb02d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#15 0x00000000 in ?? ()



analysis阶段执行一些类似下面的逻辑:

有时候,analyze阶段就直接raster了。实际操作会调用到skPicture,SkPicturePlayback, 最终操作在skCanvas里面。

#0 SkCanvas::clipRect(this=0x91b01a7c, rect=...,

//canvasskCanvas

op=SkRegion::kIntersect_Op, doAA=false) at../../third_party/skia/src/core/SkCanvas.cpp:1330

#1 0x9d3765ea in SkPicturePlayback::draw(this=0x7ee35900, canvas=..., callback=0x91b01b74) at../../third_party/skia/src/core/SkPicturePlayback.cpp:1033

#2 0x9d520c58 in cc::Picture::Raster(this=this@entry=0x95ff5c50, canvas=canvas@entry=0x91b01a7c,callback=callback@entry=0x91b01b74, negated_content_region=...,contents_scale=contents_scale@entry=1)

at ../../cc/resources/picture.cc:411

#3 0x9d526a6c in cc::PicturePileImpl::RasterCommon(this=0x9a780380, canvas=0x91b01a7c, callback=0x91b01b74,canvas_rect=..., contents_scale=contents_scale@entry=1,

#3 0x9d526a6c in cc::PicturePileImpl::RasterCommon(this=0x9a780380, canvas=0x91b01a7c, callback=0x91b01b74,canvas_rect=..., contents_scale=contents_scale@entry=1,

rendering_stats_instrumentation=rendering_stats_instrumentation@entry=0x95f8ba80,is_analysis=is_analysis@entry=true) at../../cc/resources/picture_pile_impl.cc:312

#4 0x9d526b26 in cc::PicturePileImpl::RasterForAnalysis(this=this@entry=0x9a780380, canvas=canvas@entry=0x91b01a7c,canvas_rect=..., contents_scale=contents_scale@entry=1,

stats_instrumentation=stats_instrumentation@entry=0x95f8ba80)at ../../cc/resources/picture_pile_impl.cc:93

#5 0x9d526ebe in cc::PicturePileImpl::AnalyzeInRect(this=this@entry=0x9a780380, content_rect=...,contents_scale=<optimized out>,analysis=analysis@entry=0x9000c72c, stats_instrumentation=0x95f8ba80)

at ../../cc/resources/picture_pile_impl.cc:381

#6 0x9d533dd4 in Analyze(picture_pile=0x9a780380, this=0x9000c710)

//此时在analyze阶段

at ../../cc/resources/tile_manager.cc:112

#7 AnalyzeAndRaster(picture_pile=0x9a780380, this=0x9000c710) at../../cc/resources/tile_manager.cc:97





可以跟踪一下skCanvasdrawColor看看skCanvas的使用情况:

#0 0x9d362b2a in CallBitmapXferProc (procData=<optimized out>,proc=<optimized out>, rect=..., bitmap=...) at../../third_party/skia/src/core/SkDraw.cpp:247

#1 SkDraw::drawPaint(this=0x91b019c0, paint=...) at../../third_party/skia/src/core/SkDraw.cpp:279

实际是先调用SkBitmapDevice::drawPaint,然后SkBitmapDevice::drawPaint会调用SkDraw::drawPaint.而且SkBitmapDevice都会关联一个SkBitmap.而这个bitmap就是作为backend.

#2 0x9d35d466 in SkCanvas::internalDrawPaint (this=0x935f8900,paint=...) at ../../third_party/skia/src/core/SkCanvas.cpp:1867

#3 0x9d35c7dc in SkCanvas::drawColor(this=0x935f8900, c=4294572537, mode=SkXfermode::kSrc_Mode) at../../third_party/skia/src/core/SkCanvas.cpp:2375

#4 0x9d526ce4 in cc::PicturePileImpl::RasterToBitmap(this=this@entry=0x7eee9e20, canvas=0x935f8900,canvas_rect=..., contents_scale=3,rendering_stats_instrumentation=0x9946f380)

at ../../cc/resources/picture_pile_impl.cc:148

#5 0x9d533f2a in Raster (picture_pile=0x7eee9e20,this=0x980e0160) at ../../cc/resources/tile_manager.cc:156

#6 AnalyzeAndRaster(picture_pile=0x7eee9e20, this=0x980e0160) at../../cc/resources/tile_manager.cc:102

#7 cc::(anonymous namespace)::RasterTaskImpl::RunOnWorkerThread(this=0x980e0160) at ../../cc/resources/tile_manager.cc:70

#8 0x9d531742 in cc::TaskGraphRunner::RunTaskWithLockAcquired(this=this@entry=0x9ea4a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:419

#9 0x9d53187a in cc::TaskGraphRunner::Run (this=0x9ea4a0bc<cc::(anonymous namespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:362

#10 0x9ddcab80 in base::DelegateSimpleThread::Run(this=0x9652aa60) at ../../base/threading/simple_thread.cc:81

#11 0x9ddcad8c in base::SimpleThread::ThreadMain (this=0x9652aa60)at ../../base/threading/simple_thread.cc:60

#12 0x9ddc8f5e in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

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

#14 0xb6eb02d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so



研究一下skCanvasraster中的作用

SkCanvas可以向backend中绘制一个bitmap,那么我们需要看看backend是怎么创建的?究竟绘制到哪里了?继续往下跟。



void SkDraw::drawPaint(const SkPaint& paint) const {

->void SkScan::FillIRect(const SkIRect& r, const SkRegion*clip,

SkBlitter* blitter) {

->调用blitterblitrect操作,blitter根据device的颜色模式,有多种blitter,我们使用的是:

SkBlitter* SkBlitter::Choose函数返回的blitter.SkARGB32_Blitter

->SkARGB32_Blitter::blitRect(x,y,width,height)

->SkBlitRow::ColorRect32

->Color32_arm_neon, 这个函数平台相关了,是SkBlitRow::ColorProcproc.

->sk_memset32

->memset32_neon 汇编代码。位于memset32_neon.s









下面是一个raster线程在raster时选择blittercallstacK

#0 SkBlitter::Choose(device=..., matrix=..., origPaint=...,allocator=allocator@entry=0x96cff344,drawCoverage=drawCoverage@entry=false) at

选择blitter,SkBlitter里面shader是空的,颜色模式是kN32_SkColorType:,并且建立的blitterSkARGB32_Blitter

../../third_party/skia/src/core/SkBlitter.cpp:854

#1 0x9cb52036 in SkAutoBlitterChoose::SkAutoBlitterChoose(this=0x96cff340, device=..., matrix=..., paint=...,drawCoverage=false) at ../../third_party/skia/src/core/SkDraw.cpp:50

#2 0x9cb52d7c in SkDraw::drawPath (this=0x96cff758,origSrcPath=..., origPaint=..., prePathMatrix=<optimized out>,pathIsMutable=true, drawCoverage=false) at../../third_party/skia/src/core/SkDraw.cpp:1081

#3 0x9cb3e79c in SkBitmapDevice::drawRRect (this=0x98dade20,draw=..., rrect=..., paint=...) at../../third_party/skia/src/core/SkBitmapDevice.cpp:222

#4 0x9cb4d7d0 in SkCanvas::drawRRect (this=0x98d3d900, rrect=...,paint=...) at ../../third_party/skia/src/core/SkCanvas.cpp:1966

#5 0x9cb667f8 in SkPicturePlayback::draw (this=0xa3faf500,canvas=..., callback=0x0) at../../third_party/skia/src/core/SkPicturePlayback.cpp:1129

#6 0x9cd10c98 in cc::Picture::Raster (this=this@entry=0x9675ecc0,canvas=canvas@entry=0x98d3d900, callback=callback@entry=0x0,negated_content_region=..., contents_scale=contents_scale@entry=3)

at ../../cc/resources/picture.cc:411

#7 0x9cd16aac in cc::PicturePileImpl::RasterCommon(this=this@entry=0x9fe44b00, canvas=canvas@entry=0x98d3d900,callback=callback@entry=0x0, canvas_rect=...,contents_scale=contents_scale@entry=3,

rendering_stats_instrumentation=rendering_stats_instrumentation@entry=0x9673e3c0,is_analysis=is_analysis@entry=false) at../../cc/resources/picture_pile_impl.cc:312

#8 0x9cd16d78 in cc::PicturePileImpl::RasterToBitmap(this=this@entry=0x9fe44b00, canvas=0x98d3d900, canvas_rect=...,contents_scale=3, rendering_stats_instrumentation=0x9673e3c0)

at ../../cc/resources/picture_pile_impl.cc:163

#9 0x9cd23f6a in Raster (picture_pile=0x9fe44b00,this=0x98da0e40) at ../../cc/resources/tile_manager.cc:156

#10 AnalyzeAndRaster (picture_pile=0x9fe44b00, this=0x98da0e40) at../../cc/resources/tile_manager.cc:102

#11 cc::(anonymous namespace)::RasterTaskImpl::RunOnWorkerThread(this=0x98da0e40) at ../../cc/resources/tile_manager.cc:70

#12 0x9cd21782 in cc::TaskGraphRunner::RunTaskWithLockAcquired(this=this@entry=0x9e23a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:419

#13 0x9cd218ba in cc::TaskGraphRunner::Run (this=0x9e23a0bc<cc::(anonymous namespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:362

#14 0x9d5bafe8 in base::DelegateSimpleThread::Run(this=0x94d572e0) at ../../base/threading/simple_thread.cc:81







下面是一个调用blitter操作的callstack

#0 memset32_neon () at../../third_party/skia/src/opts/memset32_neon.S:16

汇编的memset函数。

#1 0x9cb78b8a in sk_memset32(dst=0x96e74824, value=4294967295, count=375) at../../third_party/skia/src/core/SkUtils.cpp:144

#2 0x9cb4613e in SkBlitRow::ColorRect32(dst=0x96e74824, width=375, height=371, rowBytes=1536,color=4294967295) at../../third_party/skia/src/core/SkBlitRow_D32.cpp:209

#3 0x9cb4856e in SkARGB32_Blitter::blitRect(this=<optimized out>, x=<optimized out>, y=<optimizedout>, width=375, height=372) at../../third_party/skia/src/core/SkBlitter_ARGB32.cpp:218

#4 0x9cb46d1e in SkRectClipBlitter::blitAntiRect(this=<optimized out>, left=9, y=<optimized out>,width=<optimized out>, height=372, leftAlpha=<optimizedout>, rightAlpha=<optimized out>)

at ../../third_party/skia/src/core/SkBlitter.cpp:381

#5 0x9cb70c60 in SuperBlitter::blitRect(this=0x96cfe9f0, x=<optimized out>, y=1536, width=1500,height=0) at ../../third_party/skia/src/core/SkScan_AntiPath.cpp:354

#6 0x9cb72ea8 in walk_convex_edges(blitter=blitter@entry=0x96cfe9f0, stop_y=stop_y@entry=1536,proc=0x0, start_y=<optimized out>, prevHead=0x96cfe8cc) at../../third_party/skia/src/core/SkScan_Path.cpp:262

#7 0x9cb73366 in sk_fill_path(path=..., clipRect=0x96cfe990, blitter=0x96cfe9f0, start_y=24,stop_y=1536, shiftEdgesUp=2, clipRgn=...) at../../third_party/skia/src/core/SkScan_Path.cpp:504

#8 0x9cb7106e in SkScan::AntiFillPath (path=..., origClip=...,blitter=0x96cfe9c4, blitter@entry=0x96cff348, forceRLE=<optimizedout>) at ../../third_party/skia/src/core/SkScan_AntiPath.cpp:695

#9 0x9cb71148 in SkScan::AntiFillPath(path=..., clip=..., blitter=0x96cff348) at../../third_party/skia/src/core/SkScan_AntiPath.cpp:732

#10 0x9cb52dda in SkDraw::drawPath(this=0x96cff758, origSrcPath=..., origPaint=...,prePathMatrix=<optimized out>, pathIsMutable=true,drawCoverage=false) at../../third_party/skia/src/core/SkDraw.cpp:1105

#11 0x9cb3e79c in SkBitmapDevice::drawRRect(this=0x98dade20, draw=..., rrect=..., paint=...) at../../third_party/skia/src/core/SkBitmapDevice.cpp:222

#12 0x9cb4d7d0 in SkCanvas::drawRRect(this=0x98d3d900, rrect=..., paint=...) at../../third_party/skia/src/core/SkCanvas.cpp:1966

#13 0x9cb667f8 in SkPicturePlayback::draw(this=0xa3faf500, canvas=..., callback=0x0) at../../third_party/skia/src/core/SkPicturePlayback.cpp:1129

//这里到了skia里面了,这里playback之前recordskpicture内容到bitmap里面。

#14 0x9cd10c98 in cc::Picture::Raster(this=this@entry=0x9675ecc0, canvas=canvas@entry=0x98d3d900,callback=callback@entry=0x0, negated_content_region=...,contents_scale=contents_scale@entry=3)

at ../../cc/resources/picture.cc:411

#15 0x9cd16aac in cc::PicturePileImpl::RasterCommon(this=this@entry=0x9fe44b00, canvas=canvas@entry=0x98d3d900,callback=callback@entry=0x0, canvas_rect=...,contents_scale=contents_scale@entry=3,

#16 0x9cd16d78 in cc::PicturePileImpl::RasterToBitmap(this=this@entry=0x9fe44b00, canvas=0x98d3d900, canvas_rect=...,contents_scale=3, rendering_stats_instrumentation=0x9673e3c0)

at ../../cc/resources/picture_pile_impl.cc:163

#17 0x9cd23f6a in Raster(picture_pile=0x9fe44b00, this=0x98da0e40) at../../cc/resources/tile_manager.cc:156

#18 AnalyzeAndRaster(picture_pile=0x9fe44b00, this=0x98da0e40) at../../cc/resources/tile_manager.cc:102

#19 cc::(anonymous namespace)::RasterTaskImpl::RunOnWorkerThread(this=0x98da0e40) at ../../cc/resources/tile_manager.cc:70

#20 0x9cd21782 in cc::TaskGraphRunner::RunTaskWithLockAcquired(this=this@entry=0x9e23a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:419

#21 0x9cd218ba in cc::TaskGraphRunner::Run (this=0x9e23a0bc<cc::(anonymous namespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:362

#22 0x9d5bafe8 in base::DelegateSimpleThread::Run(this=0x94d572e0) at ../../base/threading/simple_thread.cc:81

#23 0x9d5bb1f4 in base::SimpleThread::ThreadMain(this=0x94d572e0) at

raster线程

../../base/threading/simple_thread.cc:60

#24 0x9d5b93c6 in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

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

#26 0xb6e9b2d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#27 0x00000000 in ?? ()







那么一张普通的图片是如何raster的?

可以浏览一下我自己的带一张图片的网页。

#0 S32A_Opaque_BlitRow32_neon_src_alpha(dst=0x9596c000,

//平台相关的code

src=0x97397e00, count=384, alpha=255) at../../third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp:764

#1 0x9cb487c0 in SkARGB32_Shader_Blitter::blitRect(this=<optimized out>, x=0, y=0, width=384, height=384) at../../third_party/skia/src/core/SkBlitter_ARGB32.cpp:404

#2 0x9cb70552 in blitrect(blitter=<optimized out>, r=...) at../../third_party/skia/src/core/SkScan.cpp:15

#3 0x9cb7061e in SkScan::FillIRect (r=...,clip=clip@entry=0x9451f638, blitter=blitter@entry=0x96cfef10) at../../third_party/skia/src/core/SkScan.cpp:30

#4 0x9cb706e6 in SkScan::FillRect (r=..., clip=0x9451f638,blitter=0x96cfef10) at ../../third_party/skia/src/core/SkScan.cpp:61

#5 0x9cb707d6 in SkScan::FillRect(r=..., clip=..., blitter=<optimized out>) at../../third_party/skia/src/core/SkScan.cpp:103

#6 0x9cb53526 in SkDraw::drawRect(this=this@entry=0x96cff13c, rect=..., paint=...) at../../third_party/skia/src/core/SkDraw.cpp:845

#7 0x9cb548c2 in SkDraw::drawBitmap(this=0x96cff6f4, bitmap=..., prematrix=..., origPaint=...) at../../third_party/skia/src/core/SkDraw.cpp:1280

#8 0x9cb3eacc in SkBitmapDevice::drawBitmapRect(this=0x7c6afc90, draw=..., bitmap=..., src=<optimized out>,dst=..., paint=..., flags=SkCanvas::kNone_DrawBitmapRectFlag)

at ../../third_party/skia/src/core/SkBitmapDevice.cpp:305

#9 0x9cb4df54 in SkCanvas::internalDrawBitmapRect(this=0x96944f00,

//这里绘制bitmap的一部分。

bitmap=..., src=0x7f0110c4, dst=..., paint=<optimized out>,flags=SkCanvas::kNone_DrawBitmapRectFlag)

at ../../third_party/skia/src/core/SkCanvas.cpp:2076

#10 0x9cb66718 in SkPicturePlayback::draw(this=0x7ab12f80, canvas=..., callback=0x0) at../../third_party/skia/src/core/SkPicturePlayback.cpp:1091

#11 0x9cd10c98 in cc::Picture::Raster(this=this@entry=0x7d40fb30, canvas=canvas@entry=0x96944f00,callback=callback@entry=0x0, negated_content_region=...,contents_scale=contents_scale@entry=1.04651165)

at ../../cc/resources/picture.cc:411

#12 0x9cd16aac in cc::PicturePileImpl::RasterCommon(this=this@entry=0x7f013de0, canvas=canvas@entry=0x96944f00,callback=callback@entry=0x0, canvas_rect=...,contents_scale=contents_scale@entry=1.04651165,

rendering_stats_instrumentation=rendering_stats_instrumentation@entry=0x7ab11cc0,is_analysis=is_analysis@entry=false) at../../cc/resources/picture_pile_impl.cc:312

#13 0x9cd16d78 in cc::PicturePileImpl::RasterToBitmap(this=this@entry=0x7f013de0, canvas=0x96944f00, canvas_rect=...,contents_scale=1.04651165,rendering_stats_instrumentation=0x7ab11cc0)

#14 0x9cd23f6a in Raster (picture_pile=0x7f013de0,this=0x90ff33c0) at ../../cc/resources/tile_manager.cc:156

#15 AnalyzeAndRaster(picture_pile=0x7f013de0, this=0x90ff33c0) at../../cc/resources/tile_manager.cc:102

#16 cc::(anonymous namespace)::RasterTaskImpl::RunOnWorkerThread(this=0x90ff33c0) at ../../cc/resources/tile_manager.cc:70

#17 0x9cd21782 in cc::TaskGraphRunner::RunTaskWithLockAcquired(this=this@entry=0x9e23a0bc <cc::(anonymousnamespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:419

#18 0x9cd218ba in cc::TaskGraphRunner::Run (this=0x9e23a0bc<cc::(anonymous namespace)::g_task_graph_runner+4>) at../../cc/resources/task_graph_runner.cc:362

#19 0x9d5bafe8 in base::DelegateSimpleThread::Run(this=0x94d572e0) at ../../base/threading/simple_thread.cc:81

#20 0x9d5bb1f4 in base::SimpleThread::ThreadMain(this=0x94d572e0) at ../../base/threading/simple_thread.cc:60

#21 0x9d5b93c6 in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

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

#23 0xb6e9b2d4 in __start_thread () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#24 0x00000000 in ?? ()



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值