Skip to content
Dzmitry Malyshau edited this page Feb 9, 2017 · 4 revisions

Overview

Renderer::new() creates the WebRender (WR) instance with the following components:

  • RenderBackend (RB). It's not returned from the function, but instead put to work in a separate thread and communicate via messages with the following objects.
  • RenderApiSender, needed to produce RenderApi instances, each with a unique namespace.
  • Renderer owns the graphics context and does the actual rendering.

RenderApi is the front-end API to WR, it has methods for:

  • resource management
  • setting root pipeline/display list (DL)
  • scrolling

When issuing commands through RenderApi, they get serialized and sent over the IPC channel (not necessary through the IPC boundary) to RB.

RenderBackend:

  • owns ResourceCache, which in turn owns TextureCache
  • build_scene flattens the StackingContext and allocates all the GPU data into textures.
  • render() builds a new Frame by culling the primitives against layers/tiles and filling up the batch instance data
  • publish() sends a frame over the result channel
  • any messages requiring feedback provide a sender themselves

Render Pass

All the work in a produced Frame is based off a task tree. This tree is composed by the RB and flattened out into passes before sending to the Renderer. A RenderPass:

  • has list of tasks that are independent of each other
  • all these tasks depend on some tasks in the previous pass
  • is rendered into a texture array layer by layer. The previous pass's texture is seen as sCache texture sampler.

Each texture array is an atlas of the target regions that were requested by the tasks (see RenderTaskLocation::Dynamic). The width and height are the same across all passes, and the depth is as little as required to fit all the target regions.

Let's take the blur filter for example. Considering the source of the blur stored in pass[0] (supposing, a text run has been rendered there), the vertical pass will be done in pass[1]. Since the horizontal pass works off the vertical pass results, it will be assigned to the next pass[2].

Task Lifetime

  1. RenderTask gets created in ScreenTile::compile() and put into the tree with the root of CompiledScreenTile::main_render_task.
  2. CompiledScreenTile::build() is given a Vec<RenderPass>, and it starts calling RenderTask::assign_to_passes. The topmost tasks going to the last pass, their children going to the one below it, and so forth. We assume (and guarantee) that the number of passes equals to the depth of the tree. Tasks end up being stored in RenderPass::tasks.
  3. The Frame containing our render passes is being sent to the Renderer.
  4. RenderPass::build creates render targets if needed for the tasks storage allocation and calls RenderTarget::add_task, which dissects the task to be consumed by one of the batchers: Alpha, Clip, or Blur.
  5. Renderer::draw_target goes through the batchers and issues the specific draw calls.
Clone this wiki locally