Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor how text shadows and elements are handled. #1498

Merged
merged 1 commit into from Jul 19, 2017

Conversation

@glennw
Copy link
Member

glennw commented Jul 19, 2017

While working on adding line decorations, I kept running into
issues and extra complexity. Instead, I've refactored how
text shadow contexts are handled. The implementation is a bit
complex in parts, but conceptually this fits in much better with
how the frame builder, prim store and GPU cache work.

Now, text-shadow primitives add text runs and decorations as
sub-primitives, using an index buffer of primitives. This means:

  • The code to manage the text-element stack and maintain correct
    paint order is much simpler.
  • The GPU cache layouts are much simpler. Text runs and decorations
    within a text-shadow element have the same layout as normal
    primitives (no weird offsets and packed layouts).
  • Text primitives that have both visual and shadows (which is the
    common case) share the same GPU primitive - so they only get
    built and uploaded once. This is quite a large performance win
    on pages with a lot of shadows.
  • The code to truncate glyph positions is moved from the CPU
    to the vertex shader, which is a significant performance win.
  • The paint order of shadows is reversed from the previous
    implementation, back to what it was originally.

This change is Reviewable

@glennw
Copy link
Member Author

glennw commented Jul 19, 2017

r? @kvark

Sorry for another large patch on this stuff!

@kvark
kvark approved these changes Jul 19, 2017
Copy link
Member

kvark left a comment

Looks like a great cleanup!

@@ -22,7 +33,7 @@ void main(void) {
vec2 size = res.uv_rect.zw - res.uv_rect.xy;
vec2 local_pos = glyph.offset + vec2(res.offset.x, -res.offset.y) / uDevicePixelRatio;
vec2 origin = prim.task.render_target_origin +
uDevicePixelRatio * (text.offset + local_pos);
uDevicePixelRatio * (local_pos + shadow.offset - shadow_geom.local_rect.p0);

This comment has been minimized.

@kvark

kvark Jul 19, 2017

Member

does everything that goes through cs_text_run has to have a shadow?

This comment has been minimized.

@glennw

glennw Jul 19, 2017

Author Member

Yep

local_clip,
clip_and_scroll);
} else if color.a > 0.0 {
let mut shadows = Vec::new();

This comment has been minimized.

@kvark

kvark Jul 19, 2017

Member

let's rename it to something like trivial_shadow?

for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let shadow_prim = &self.prim_store.cpu_text_shadows[shadow_metadata.cpu_prim_index.0];
if shadow_prim.shadow.blur_radius == 0.0 {

This comment has been minimized.

@kvark

kvark Jul 19, 2017

Member

somewhat unfortunate that we already have the same loop at the start of the function, maybe we could combine them?

This comment has been minimized.

@glennw

glennw Jul 19, 2017

Author Member

Unfortunately, we need to do part of it before adding the prim and part afterwards.

// text shadow primitives. Consider restructuring this code to
// avoid borrow checker issues.
match prim_kind {
PrimitiveKind::TextShadow => {

This comment has been minimized.

@kvark

kvark Jul 19, 2017

Member

nit: looks like a case for if let

@kvark
Copy link
Member

kvark commented Jul 19, 2017

r=me whether or not the notes are addressed

While working on adding line decorations, I kept running into
issues and extra complexity. Instead, I've refactored how
text shadow contexts are handled. The implementation is a bit
complex in parts, but conceptually this fits in much better with
how the frame builder, prim store and GPU cache work.

Now, text-shadow primitives add text runs and decorations as
sub-primitives, using an index buffer of primitives. This means:

* The code to manage the text-element stack and maintain correct
  paint order is much simpler.
* The GPU cache layouts are much simpler. Text runs and decorations
  within a text-shadow element have the same layout as normal
  primitives (no weird offsets and packed layouts).
* Text primitives that have both visual and shadows (which is the
  common case) share the same GPU primitive - so they only get
  built and uploaded once. This is quite a large performance win
  on pages with a lot of shadows.
* The code to truncate glyph positions is moved from the CPU
  to the vertex shader, which is a significant performance win.
* The paint order of shadows is reversed from the previous
  implementation, back to what it was originally.
@glennw glennw force-pushed the glennw:better-text-shadows-3 branch from 017ece1 to ef21f66 Jul 19, 2017
@glennw
Copy link
Member Author

glennw commented Jul 19, 2017

@kvark Thanks, issued addressed or explained above.

@bors-servo r=kvark

@bors-servo
Copy link
Contributor

bors-servo commented Jul 19, 2017

📌 Commit ef21f66 has been approved by kvark

@bors-servo
Copy link
Contributor

bors-servo commented Jul 19, 2017

Testing commit ef21f66 with merge b83c200...

bors-servo added a commit that referenced this pull request Jul 19, 2017
Refactor how text shadows and elements are handled.

While working on adding line decorations, I kept running into
issues and extra complexity. Instead, I've refactored how
text shadow contexts are handled. The implementation is a bit
complex in parts, but conceptually this fits in much better with
how the frame builder, prim store and GPU cache work.

Now, text-shadow primitives add text runs and decorations as
sub-primitives, using an index buffer of primitives. This means:

* The code to manage the text-element stack and maintain correct
  paint order is much simpler.
* The GPU cache layouts are much simpler. Text runs and decorations
  within a text-shadow element have the same layout as normal
  primitives (no weird offsets and packed layouts).
* Text primitives that have both visual and shadows (which is the
  common case) share the same GPU primitive - so they only get
  built and uploaded once. This is quite a large performance win
  on pages with a lot of shadows.
* The code to truncate glyph positions is moved from the CPU
  to the vertex shader, which is a significant performance win.
* The paint order of shadows is reversed from the previous
  implementation, back to what it was originally.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1498)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Jul 19, 2017

☀️ Test successful - status-travis
Approved by: kvark
Pushing b83c200 to master...

@bors-servo bors-servo merged commit ef21f66 into servo:master Jul 19, 2017
2 of 3 checks passed
2 of 3 checks passed
continuous-integration/appveyor/pr AppVeyor build failed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

4 participants
You can’t perform that action at this time.