2015년 3월 23일 월요일

How to Draw

As you know a drawing process is so complicated and huge.
So I will explain a drawing with 2 parts. A front would be a related constructing main classes, how to work them and a layout process.
And a behind would be a related compositing, tile managing and gl working.

=== Class Construction ===

When I began to investigate the Chromium, I mistaken that the Blink is the Render Process. Although they are not same, I thought most parts in the Render Process is the Blink. But it is not.
In the Render Process has many graphic codes related a rendering. They are not in the Blink. They are the Chromium side.
At first, I will explain the Chromium side. Because they are handle most realm in drawing parts. A start point is a RenderViewImpl creating. A RenderViewImpl is the Chromium side. It become one of confused element. Because in the Blink it has RenderView. But these the RenderView and the RenderViewImpl is totally different. In the blink the RenderView`s filename is "renderview.cpp" and in the Chromium is "render_view_impl.cc". And there behavior is also different. There differences would be explained later. When the RenderViewimpl is created, all related classes are created. Below picture shows a result.



In fact, the RenderView`s ancestor class is the RenderWidget. The RenderWidget create the RenderWidgetCompositor. From the RenderWidgetCompositor to the LayerTreeHostImpl each class have important roles.
The RenderWidgetCompositor handle between the LayerTreeHost and the LayerTreeHostImpl. The LayerTreeHost is more closed to the Blink. It handle a layout and software rendering. But the LayerTreeHostImpl is more close to the GL behavior. It handle the outersurface and gl calls. The Thread Proxy is look like a bridge between the LayerTreeHost and the LayerTreeHostImpl. It has the Scheduler. From the Shceduler`s scheduling, rendering processes are triggered. The Scheduler has several steps. They will be explained more detailed in next section. The LayerTreeHostImpl is closed to a hardware rendering. Green boxes in upper picture`s LayerTreeHostImpl  are initialized after special scheduling queue. It is explained next chapter. In conclusion, if you understand classes construction, it would be good for understanding whole a rendering process.

=== Scheduler ===

All rendering related jobs are trigger by the Scheduler. The Scheduler has own state machine and work by schedule state. When some action change schedule state condition, the Scheduler triggers target action. For example, if all layers are ready to show, the Scheduler receives "ACTION_DRAW_AND_SWAP_IF_POSSIBLE" state and calls "swapbuffer" to a outputsurface. This step is described in "Scheduler::ProcessScheduledActions()". You can see how it works. Below picture shows a state looping sequence.


* ACTION_BEGIN_OUTPUT_SURFACE_CREATION
In this step, the Layer Tree Host Impl create the CompositorOutputSurface. It is inherited class from the MailboxOutputSurface. In here tile jobs have work with a tile manager.. And call to the BrowserProcess to show buffers.
* ACTION_SEND_BEGIN_MAIN_FRAME
In this step, a layout task is performed. This step is more detailed in next section.
* ACTION_COMMIT
From the RenderLayerCompositor tree, the Layer Tree Impl create a layerimpl tree. It ready to draw.
* ACTION_PREPARE_TILES
In this step, needed tiles are created. If changed area is small, only matched coordinated tiles are destroyed and created.
* ACTION_ACTIVATE_SYNC_TREE
If partial update is needed, only parts of tree would be updated. This step sync it.
* ACTION_DRAW_AND_SWAP_IF_POSSIBLE
This step is an outputsurface job. Shortly a "swapBuffer" command is called in this step. This step will be explained in a next document.


=== Layout ===
A layout process is divided as 3 big parts. First creating RenderLayers. Second layout. Finally creating compositing information.
A layout job is triggered by "ACTION_SEND_BEGIN_MAIN_FRAME" state. Then FrameView start to layout process.
In the "FrameView::updateLayoutAndStyleForPainting" all layout tasks are done.




Upper picture shows a route path from the Scheduler to FrameView. In FrameView we can focus big 4 steps. But 4th path is just simple path, so I will skip it.
* creating RenderLayers
At first process, check document updating through "updateRenderTree". It check a dom tree recursive and check style updating. If some node is updated, then create the RenderLayer tree.
* layout
After creating RenderLayers, the FrameView call the layout. This task works in a RenderObject class family. In fact it works in the RenderBlock.
* updating compositing info
After layout, for accelerated compositing, many informations are needed to calcualte. It works in the RenderLayerCompositing. As we know if the Blink uses a compositing, it needs to create some special layers. "GraphicsLayer". The GraphicsLayer is metrial for root layer and other form layers of screen. A created root layer is registered in the RenderLayerCompositing and WebViewImpl. It is need to composite.
In contrasted with previous the "webkit", calculating compositing works in util class. Those are "CompositingInputsUpdater" and "CompositingRequirementsUpdater".


After upper three tasks, the GraphicsLayer calls setNeedsDisplayInRect. And the Scheduler trigger next step ACTION_COMMIT.
After this will explain next document.



An Upper picture shows all needed classes for rendering. Left side is more closed to the Layout, a right side of the RenderWidget is more closed to the Painting and the Drawing. The Painting is worked with sync trees and tiles. It also works with the Skia. The LayerTreeHostImpl is important class in the painting and the drawing. It handles all task related with the painting and drawing. 


=== Painting ===
The painting is began with "UpdateLayers" in the LayerTreeHost. With below picture, a painting is triggered in the PicturePile. In the PicturePile it calculates clip rect, set tiles and record pictures. The PictureLayer is a surface layer for painting. There are tiles on the PictureLayer, there are pictures on tiles.If you want to skip root layer painting, you can modify code in PictureLayer "update". The Painting logic is so complicated. I do not still understand totally.





=== Drawing ===
When a painting is finished, the Scheduler trigger a draw and a swap. As below picture shows that in the ThreadProxy::DrawSwapInternal, a drawing and a swapping are worked in same turn. At first, through DrawLayers in LayerTreeHostImpl, it draw texture on an outputSurface. This output surface has preserved when the Render Process created. At each drawing turn, output surface prepare again. But the MailboxOutputSurface preserve unique size textures and return pre-created texture when it needed. After returning backbuffer, renderer draw with render pass and quads on an output surface.




When a drawing on output surface is finished, a swap buffer is triggered. A swap buffer sequence is very simple. When an output surface`s texture created, it is delivered to the Browser Process. And EvasGL copies that texture to EvasGL texture.
It refreshing on user screen. This is a full sequence to draw.
In fact, some layout, painting`s detailed process is skipped. Because it is a very complicated, and need more investigation. I will update this article in more detailed.



Render Process Life Cycle

== Render Process Life Cycle ==

For knowing the Render Process life cycle, we need to know the Frame Tree cycle. Because the Render Process is created during a Frame Tree is constructing, and also is destroyed during the Frame tree is collapsing.
So, I will explain the Render Process life cycle with the Frame Tree.

==  Creating the Frame Tree ==

When the eweb_view is created by ewk api "ewk_view_add", it causes the Frame Tree is began to create. The Frame Tree is a member of the "WebContents", and it manages all Frame Tree Nodes. Each Frame Tree Node has the Render Frame Host Manager and the Render Frame Host. The Frame Tree has the Render View Host and the Render Frame Host Manager reference the Render View Host via the Frame Tree. In fact the Frame Tree has the Render View Host map and it manages Render View Hosts. But most case in EFL each Frame Tree only create one Render View Host. Meanwhile during the Render Frame Host is being created, the Render Process Host is also created by the Site Instance. As you know the Render Process Host is a kind of tunnel to communicate with the Render Process. The Site Instance is alive during an application is alive. When the browser re-access some previous sites, if the Site Instance has a url about that sites, then matched the Site Instance would be reused. In other words when the Browser Process need to use the Site Instance, they search a matched Site Instace with an url in a Site Instance map. If some Site Instance matched with an inputted url, the navigator use that Site Instance. But even the Site Instance is reused, the Render Process will be recreated with new url. Anyway The Frame Tree is handled by the Browser Process (in the "WebContents"). When the Render Process is killed, all contents of the Frame tree will also be destroyed except the Frame Tree instance itself. In conclusion when the Frame Tree finish to create the main Render Frame Host (finishing "ewk_view_add"), the Frame tree would be created like below picture.





==  When a web page is loading, how to create frames ==




An upper picture is a summary how to create frames when a web page is loading. The main point is a web load trigger is from the Browser Process but a loading progress is managed by the Render Process.
A main Render Frame is created by the Browser Process, but child frames (like inline frames) are created by the Render Process during a web loading. Upper picture also shows a relation between the Render Frame and the WebLocalFrame. The Render Frame is the Chromium side but the WebLocalFrame is the Blink side. But They have 1:1 relationship. If new child frame is needed, the Blink (frame loader) call a "createChildFrame" api in the Render Frame class. Then the Render Frame receives new routing id from the Render Frame Host, and create a new WebLocalFrame to connect with the Blink.

==  Change a wep url through new url set ==

When new url is input through "ewk_view_url_set", the Browser Process creates new Render Process. I will explain with a below picture.



Assume the Browser Process already loads some web page like "www.naver.com". Cause "www.naver.com" has several inline frames, the Frame Tree also has matched the Render Frame Host. The Render Frame Host exists in the Render Frame Host Manager, and the Render Frame Host Manager exists in the Frame Tree Node. Set of the Frame Tree Nodes is the Frame Tree. the Frame Tree has root node and the root node number is 1. But when user inputs new url, new Render Process will be created and previous the Frame Tree contents will be collapsed. But root node is never destroyed while "WebContents" is living. As member instance of root node, a main Render Frame Host and the Render View Host will destructed. In other words, the Frame Tree will be existed even the Render Process is killed. And the Frame Tree`s root node is also exist. But the Render Frame Host and the Render View Host will be destructed, when the Render Process is killed. All Frame Tree Nodes except root node will also be destructed when the Render Process is died. In upper picture green boxes will be destructed when the Render Process is died. But it would be delayed till the Blink has succeed to commit load new URL. When new URL is setting the Render Frame Host Manager in root node, create new Render Process through the Site Instance. And After creating new Render Process, the Render Frame Host Manager will create new main Render Frame Host. This new main Render Frame Host is marked as pending. This pending is important. Till "didCommit" signal from the Render Process, the Frame Tree has two main Render Frame Hosts and Render View Host. But they share one root node and the Render Frame Host Manager. The Render Process will send message "FrameHostMsg_DidCommitProvisionalLoad" after the navigation request has been commit. Then the Render Frame Host begin to remove old frames. About that sequence is below picture.




Upper sequence is removing a old Render Frame Hosts process. Frame Tree Nodes are removed by root node`s "ResetForNewProcess" API. Through this API the Render Frame Host Manger and the Render Frame Host in each nodes are removed. But the Render Frame Host in a root node is still alive. And also the Render View Host in the Frame Tree is still alive. They are removed after the Render Process swap out. "FrameMsg_SwapOut" is a message to remove the Render Frames in the Render Process. After removing all frames in the Render Process, it sends a callback message "FrameHostMsg_SwapOut_ACK". In conclusion this message triggers to kill the Render Process. At this time both the main Render Frame Host and the Render View Host are also killed. The Render Process Host has the Child Process Launcher as a member instance. The Child Process Launcher communicate with the Zygote Process about a process life cycle. So through the Child Process Launcher, the Render Process can be died. You can check the Render Process kill command in "ChildProcessLauncher::Context::Terminate()". Before the Render Process is killed, many kinds of stuff must be released. You can check some behavior like IPC channel reset, GPU observer released and so on in "RenderProcessHostImpl::Cleanup()" and "RenderProcessHostImpl::~RenderProcessHostImpl()". Below picture is a simple sequence from "FrameHostMsg_SwapOut_ACK" to the Zygote terminating.




Through the Zygote, the real PID will be killed.

2014년 12월 12일 금요일

Content in Chromium

A name of "Content" in the Chromium makes me confused at first. Normally I have known a meaning of content is related with contents from web. So I first step in investigating with same idea. But as I read code and check how it works, that is not simple and even very huge in the Chromium. Totally different with web contents.
(from http://www.chromium.org/developers/content-module)

As Upper picture shown, a content is related with all other modules. At first I can not understand easily what that means. But that picture has said that "A content does everything in the Chromium".
In fact files in src/content are all content. So I think start with very small point is more easy to know how it works. Between the BrowserProcess and the RenderProcess(and other process like GPU, Plugin..) they communicate with the IPC. If you want to know what a content do, I recommend to start from there. You can realize what they do with APIs those have prefix "on". For example in "render_frame_impl.cc" there is an "OnNavigate" api. That activate that a Renderer start to navigate web pages with input url.

 A content has api sets called as a "content client". Each process has their own content clients apis. The BrowserProcess has a "contentBrowserClient". Similar with the "BrowserProcess", the RenderProcess has a "contentRendererClient".
 All api interfaces are predefined in a "contenClient". If you really want to use those api, you implement that api in proprer inherited from contentClient class. All contentClients class families are inherited from "contentClient". (contentBrowerclient is inherited from contentClient). All contentClient apis are located in proper code positions.

in content_browser_client.cc
WebContentsViewDelegate* ContentBrowserClient::GetWebContentsViewDelegate(
    WebContents* web_contents) {
  return NULL;
}
Upper code snippet is one of api in content_browser_client.cc. It seems to get webContentsViewDelegate. But return is not implemented. If you want to get some meaningful return, you need to describe some code what you want. And that api is using in web_content_impl.cc
void WebContentsImpl::Init(const WebContents::CreateParams& params) {
 .......
  WebContentsViewDelegate* delegate =
      GetContentClient()->browser()->GetWebContentsViewDelegate(this);
... 
When WebContentsImpl launch an init method, contentBrowserClient api is used.
All contentClient apis are able to use like this.

A content in the chromium is very huge part, and covers both the BrowserProcess and the RenderProcess.  But if you understand content what and how to work, reading the chromium is more easily.







2014년 11월 30일 일요일

Space Slide Show


link : https://github.com/swamful/spaceSlideShow

 This effect is made for a slide show.
Many pictures are scattered to a space, and come to a view port in turn. 
 It would give us to feel navigating in a space.




2014년 11월 29일 토요일

Zygote in Chromium

When I begin to investigate Chromium, I have been known that the Zygote is used in Chromium. In fact, I had heard the Zygote as a word in the Android. But I don`t know accuracy about that. So After I read articles and codes, I can understand why the Chromium use the Zygote.


Upper picture shows  the Browser Process create the Zygote and other processes.
At first the Browser Process create the Zygote with fork and exec.
When we create a child process, we usually use "fork" command. A "fork" is copy all about  parent`s memory . Code, Stack, Data and Heap. It means both parent and child`s statuses are same. But sometimes it would be very dangerous.

When you make a new tab Chrome (usually) starts a new process for that tab. How is this done? It would seem natural to just fork(), but fork can't be used safely in the presence of threads. fork only forks the current thread but other threads may be holding locks (including e.g. inside glibc or in the allocator) which would never be released after the fork.
from https://code.google.com/p/chromium/wiki/LinuxZygote 

As quoted article say, if forked process would be locked by parent`s  another thread. It is not expected situation. But if parent process does not have any thread, this dangerous situation is disappeared. The Zygote has no threads, till new process has launched. It`s a just like a proxy. When parent process`s all resources are derived to child process, system library`s status is same. This is very important fact. Because when child process is created with "fork + exec", it has a possible that both using system library`s versions are different. Assume when parent process is running, one of using library is upgraded. Then between new installed library and using library by parent process has a version gap. Some api would be changed. And later child process has been launched with new version library. It would cause a crash.

 In conclusion, the Browser Process launch the Zygote prcoess with "fork+exec" rather than only "fork", for preventing thread lock. And the between Browser process and Zygote process are able to use same version libraries because when the Browser process is launched, the Zygote process is also launched. When the Browser process send a creating new child message through the IPC to the Zygote process, the Zygote fork a child process with "fork". It is for maintaining same version library between a parent and a child processes. This is why the Chromium use the Zygote.






2014년 11월 27일 목요일

Left Setting View Moving Effect




link : https://github.com/swamful/leftSettingEffect

Currently, hidden left extra view is a fashion. 
So I decided to make it with more sensitive showing way. 

At first when app is launched, just gray MainView would be shown. That view is just normal view. Hidden left view is still not shown. But if you drag a MainView to right, a MainView would open like a half opened door and hidden left view begin to show. Finally a MainView stays half opened status and left lists will be shown with appearing animation. 

Below video is recorded a simulator on my MacBook . 
In fact, my device is too old. MacBookPro 2010 mid. Simulator in video show a moving seem to be rough. But if you try on own your iPhone, the moving would be very smooth.