зеркало из https://github.com/mozilla/gecko-dev.git
Merge graphics branch to m-c a=merge
MozReview-Commit-ID: 3R6vECA8sI1
This commit is contained in:
Коммит
15777c0256
|
@ -49,14 +49,14 @@ skip-if(Android)
|
|||
skip-if(Android) == webgl-color-test.html?frame=1&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=1&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=1&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&__&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
|
@ -66,14 +66,14 @@ skip-if(Android)
|
|||
skip-if(Android) == webgl-color-test.html?frame=6&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=6&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=6&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=6&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=6&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) fails-if(webrender) == webgl-color-test.html?frame=6&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) == webgl-color-test.html?frame=6&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
|
@ -83,14 +83,14 @@ skip-if(Android)
|
|||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=1&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=1&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
|
||||
|
@ -100,14 +100,14 @@ skip-if(Android)
|
|||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) pref(webgl.force-layers-readback,true) fails-if(webrender) == webgl-color-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
skip-if(Android) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
|
||||
|
||||
# Check for hanging bindings/state settings:
|
||||
skip-if(Android) == webgl-hanging-fb-test.html?__&________ wrapper.html?green.png
|
||||
|
@ -157,7 +157,7 @@ skip-if(!winWidget) pref(webgl.disable-angle,true) == webgl-color-test.html?nat
|
|||
== stroketext-shadow.html stroketext-shadow-ref.html
|
||||
|
||||
# focus rings
|
||||
pref(canvas.focusring.enabled,true) skip-if(cocoaWidget) skip-if(winWidget) needs-focus fails-if(webrender) == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
|
||||
pref(canvas.focusring.enabled,true) skip-if(cocoaWidget) skip-if(winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
|
||||
pref(canvas.customfocusring.enabled,true) skip-if(Android||cocoaWidget||winWidget) fuzzy-if(gtkWidget,64,410) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
|
||||
|
||||
# Check that captureStream() displays in a local video element
|
||||
|
|
|
@ -62,4 +62,4 @@ pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784
|
|||
pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html
|
||||
|
||||
# Test video with rotation information can be rotated.
|
||||
fails-if(webrender) == bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
|
||||
== bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
# basic sanity checking
|
||||
random-if(!haveTestPlugin) != plugin-sanity.html about:blank
|
||||
fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) fails-if(webrender) == plugin-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,164000) fails-if(webrender) == plugin-alpha-opacity.html div-alpha-opacity.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832
|
||||
# fuzzy because of anti-aliasing in dashed border
|
||||
fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fails-if(webrender) == border-padding-1.html border-padding-1-ref.html # bug 629430
|
||||
fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-1.html border-padding-1-ref.html # bug 629430
|
||||
fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430
|
||||
skip-if(!webrender) pref(layers.advanced.border-layers,true) fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html
|
||||
fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) skip-if(!haveTestPlugin||Android) fails-if(webrender) == border-padding-3.html border-padding-3-ref.html # bug 629430 # bug 773482
|
||||
fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) skip-if(!haveTestPlugin||Android) == border-padding-3.html border-padding-3-ref.html # bug 629430 # bug 773482
|
||||
# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
|
||||
#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
|
||||
#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) fails-if(webrender) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) fails-if(webrender) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) fails-if(webrender) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) fails-if(webrender) == plugin-background.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) fails-if(webrender) == plugin-background-1-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) fails-if(webrender) == plugin-background-2-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) fails-if(webrender) == plugin-background-5-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) fails-if(webrender) == plugin-background-10-step.html plugin-background-ref.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-1-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-2-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-5-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-10-step.html plugin-background-ref.html
|
||||
random-if(!haveTestPlugin) == plugin-transform-1.html plugin-transform-1-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-transform-2.html plugin-transform-2-ref.html
|
||||
skip-if(!haveTestPlugin) == shrink-1.html shrink-1-ref.html
|
||||
|
|
|
@ -79,4 +79,4 @@ to make sure that mozjs_sys also has its Cargo.lock file updated if needed, henc
|
|||
the need to run the cargo update command in js/src as well. Hopefully this will
|
||||
be resolved soon.
|
||||
|
||||
Latest Commit: 501e3d79c8a3019762bd8bd2d00eecf7811a84de
|
||||
Latest Commit: e30fb2914928c0e596d8632ed234647c0fd1492e
|
||||
|
|
|
@ -69,10 +69,12 @@ enum class TextureFlags : uint32_t {
|
|||
// This flag is only used in the parent process.
|
||||
INVALID_COMPOSITOR = 1 << 12,
|
||||
// The texture was created by converting from YCBCR to RGB
|
||||
RGB_FROM_YCBCR = 1 << 13,
|
||||
RGB_FROM_YCBCR = 1 << 13,
|
||||
// The texture is used for snapshot.
|
||||
SNAPSHOT = 1 << 14,
|
||||
|
||||
// OR union of all valid bits
|
||||
ALL_BITS = (1 << 14) - 1,
|
||||
ALL_BITS = (1 << 15) - 1,
|
||||
// the default flags
|
||||
DEFAULT = NO_FLAGS
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace layers {
|
|||
already_AddRefed<TextureHost>
|
||||
CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -26,7 +27,7 @@ CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
|
|||
return MakeAndAddRef<MacIOSurfaceTextureHostBasic>(aFlags, desc);
|
||||
}
|
||||
#endif
|
||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -43,6 +43,7 @@ class Compositor;
|
|||
class ThebesBufferData;
|
||||
class TiledContentHost;
|
||||
class CompositableParentManager;
|
||||
class WebRenderImageHost;
|
||||
struct EffectChain;
|
||||
|
||||
struct ImageCompositeNotificationInfo {
|
||||
|
@ -148,6 +149,7 @@ public:
|
|||
void SetLayer(Layer* aLayer) { mLayer = aLayer; }
|
||||
|
||||
virtual TiledContentHost* AsTiledContentHost() { return nullptr; }
|
||||
virtual WebRenderImageHost* AsWebRenderImageHost() { return nullptr; }
|
||||
|
||||
typedef uint32_t AttachFlags;
|
||||
static const AttachFlags NO_FLAGS = 0;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "LayerScope.h"
|
||||
#include "LayersLogging.h" // for AppendToString
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/ipc/Shmem.h" // for Shmem
|
||||
#include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
|
@ -20,6 +21,7 @@
|
|||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/GPUVideoTextureHost.h"
|
||||
#include "mozilla/layers/WebRenderTextureHost.h"
|
||||
#include "nsAString.h"
|
||||
#include "mozilla/RefPtr.h" // for nsRefPtr
|
||||
#include "nsPrintfCString.h" // for nsPrintfCString
|
||||
|
@ -160,18 +162,21 @@ TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId)
|
|||
|
||||
// implemented in TextureHostOGL.cpp
|
||||
already_AddRefed<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags);
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags);
|
||||
|
||||
// implemented in TextureHostBasic.cpp
|
||||
already_AddRefed<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags);
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags);
|
||||
|
||||
// implemented in TextureD3D11.cpp
|
||||
already_AddRefed<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags);
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags);
|
||||
|
||||
already_AddRefed<TextureHost>
|
||||
TextureHost::Create(const SurfaceDescriptor& aDesc,
|
||||
|
@ -184,19 +189,19 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
|||
case SurfaceDescriptor::TSurfaceDescriptorDIB:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorGPUVideo:
|
||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
|
||||
|
||||
case SurfaceDescriptor::TEGLImageDescriptor:
|
||||
case SurfaceDescriptor::TSurfaceTextureDescriptor:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
|
||||
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
||||
return CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
|
||||
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
|
||||
if (aBackend == LayersBackend::LAYERS_OPENGL ||
|
||||
aBackend == LayersBackend::LAYERS_WR) {
|
||||
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
|
||||
return CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
|
||||
} else {
|
||||
return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
|
||||
return CreateTextureHostBasic(aDesc, aDeallocator, aBackend, aFlags);
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
|
@ -209,16 +214,28 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
|||
#ifdef XP_WIN
|
||||
case SurfaceDescriptor::TSurfaceDescriptorD3D10:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
|
||||
return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags);
|
||||
return CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
|
||||
#endif
|
||||
default:
|
||||
MOZ_CRASH("GFX: Unsupported Surface type host");
|
||||
}
|
||||
}
|
||||
|
||||
bool WrapWithWebRenderTextureHost(LayersBackend aBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
if (!gfxVars::UseWebRender() ||
|
||||
(aFlags & TextureFlags::SNAPSHOT) ||
|
||||
(aBackend != LayersBackend::LAYERS_WR)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureHost>
|
||||
CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
|
@ -232,12 +249,18 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
|||
bufferDesc.desc(),
|
||||
aDeallocator,
|
||||
aFlags);
|
||||
if (WrapWithWebRenderTextureHost(aBackend, aFlags)) {
|
||||
result = new WebRenderTextureHost(aFlags, result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MemoryOrShmem::Tuintptr_t: {
|
||||
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
|
||||
bufferDesc.desc(),
|
||||
aFlags);
|
||||
if (WrapWithWebRenderTextureHost(aBackend, aFlags)) {
|
||||
result = new WebRenderTextureHost(aFlags, result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -54,6 +54,7 @@ class TextureSourceBasic;
|
|||
class DataTextureSource;
|
||||
class PTextureParent;
|
||||
class TextureParent;
|
||||
class WebRenderTextureHost;
|
||||
class WrappingTextureSourceYCbCrBasic;
|
||||
|
||||
/**
|
||||
|
@ -584,6 +585,8 @@ public:
|
|||
|
||||
virtual BufferTextureHost* AsBufferTextureHost() { return nullptr; }
|
||||
|
||||
virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; }
|
||||
|
||||
protected:
|
||||
void ReadUnlock();
|
||||
|
||||
|
@ -880,6 +883,7 @@ private:
|
|||
already_AddRefed<TextureHost>
|
||||
CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags);
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -633,12 +633,13 @@ DXGIYCbCrTextureData::Deallocate(LayersIPCChannel*)
|
|||
already_AddRefed<TextureHost>
|
||||
CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
|
||||
break;
|
||||
}
|
||||
case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
|
||||
|
|
|
@ -1130,7 +1130,10 @@ CompositorBridgeChild::HandleFatalError(const char* aName, const char* aMsg) con
|
|||
}
|
||||
|
||||
PWebRenderBridgeChild*
|
||||
CompositorBridgeChild::AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*, uint32_t *aIdNamespace)
|
||||
CompositorBridgeChild::AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize&,
|
||||
TextureFactoryIdentifier*,
|
||||
uint32_t *aIdNamespace)
|
||||
{
|
||||
WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId);
|
||||
child->AddIPDLReference();
|
||||
|
|
|
@ -223,7 +223,9 @@ public:
|
|||
|
||||
void WillEndTransaction();
|
||||
|
||||
PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*,
|
||||
PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize&,
|
||||
TextureFactoryIdentifier*,
|
||||
uint32_t*) override;
|
||||
bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;
|
||||
|
||||
|
|
|
@ -1575,6 +1575,7 @@ CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
|
|||
|
||||
PWebRenderBridgeParent*
|
||||
CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize& aSize,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint32_t* aIdNamespace)
|
||||
{
|
||||
|
@ -1591,7 +1592,8 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipel
|
|||
|
||||
MOZ_ASSERT(mWidget);
|
||||
RefPtr<widget::CompositorWidget> widget = mWidget;
|
||||
RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget));
|
||||
RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(
|
||||
gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget), aSize);
|
||||
RefPtr<WebRenderCompositableHolder> holder = new WebRenderCompositableHolder();
|
||||
MOZ_ASSERT(api); // TODO have a fallback
|
||||
api->SetRootPipeline(aPipelineId);
|
||||
|
|
|
@ -455,6 +455,7 @@ public:
|
|||
}
|
||||
|
||||
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize& aSize,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint32_t* aIdNamespace) override;
|
||||
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
|
||||
|
|
|
@ -199,6 +199,7 @@ CrossProcessCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
|
|||
|
||||
PWebRenderBridgeParent*
|
||||
CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize& aSize,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint32_t *aIdNamespace)
|
||||
{
|
||||
|
@ -222,7 +223,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::Pipeli
|
|||
|
||||
WebRenderBridgeParent* parent = nullptr;
|
||||
RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI();
|
||||
RefPtr<WebRenderCompositableHolder> holder = root->CompositableHolder();
|
||||
RefPtr<WebRenderCompositableHolder> holder = new WebRenderCompositableHolder();
|
||||
parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, root->CompositorScheduler(), Move(api), Move(holder));
|
||||
|
||||
parent->AddRef(); // IPDL reference
|
||||
|
|
|
@ -155,6 +155,7 @@ public:
|
|||
virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override;
|
||||
|
||||
PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
|
||||
const LayoutDeviceIntSize& aSize,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint32_t* aIdNamespace) override;
|
||||
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
|
||||
virtual bool UsesImageBridge() const { return false; }
|
||||
|
||||
virtual bool UsesWebRenderBridge() const { return false; }
|
||||
|
||||
protected:
|
||||
void Finalize() {}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasi
|
|||
using mozilla::CSSIntRegion from "Units.h";
|
||||
using mozilla::LayoutDeviceIntPoint from "Units.h";
|
||||
using mozilla::LayoutDeviceIntRegion from "Units.h";
|
||||
using mozilla::LayoutDeviceIntSize from "Units.h";
|
||||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||
using class mozilla::layers::FrameUniformityData from "mozilla/layers/FrameUniformityData.h";
|
||||
using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
|
||||
|
@ -242,7 +243,7 @@ parent:
|
|||
sync SyncWithCompositor();
|
||||
|
||||
// The pipelineId is the same as the layersId
|
||||
sync PWebRenderBridge(PipelineId pipelineId)
|
||||
sync PWebRenderBridge(PipelineId pipelineId, LayoutDeviceIntSize aSize)
|
||||
returns (TextureFactoryIdentifier textureFactoryIdentifier, uint32_t idNamespace); //XXX: use the WrIdNamespace type
|
||||
|
||||
child:
|
||||
|
|
|
@ -12,7 +12,7 @@ include protocol PTexture;
|
|||
using WrBorderRadius from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrBorderSide from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrColor from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrLayoutSize from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrSize from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrRect from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrPoint from "mozilla/webrender/webrender_ffi.h";
|
||||
using WrGradientStop from "mozilla/webrender/webrender_ffi.h";
|
||||
|
@ -32,118 +32,11 @@ using mozilla::LayerIntRegion from "Units.h";
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct OpDPPushStackingContext {
|
||||
WrRect bounds;
|
||||
WrRect overflow;
|
||||
MaybeImageMask mask;
|
||||
float opacity;
|
||||
Animation[] animations;
|
||||
Matrix4x4 matrix;
|
||||
WrMixBlendMode mixBlendMode;
|
||||
uint64_t scrollid;
|
||||
};
|
||||
|
||||
struct OpDPPopStackingContext { };
|
||||
|
||||
struct OpDPPushScrollLayer {
|
||||
WrRect bounds;
|
||||
WrRect overflow;
|
||||
MaybeImageMask mask;
|
||||
uint64_t scrollid;
|
||||
};
|
||||
|
||||
struct OpDPPopScrollLayer { };
|
||||
|
||||
struct OpDPPushRect {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
WrColor color;
|
||||
};
|
||||
|
||||
struct OpDPPushBorder {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
WrBorderSide top;
|
||||
WrBorderSide right;
|
||||
WrBorderSide bottom;
|
||||
WrBorderSide left;
|
||||
WrBorderRadius radius;
|
||||
};
|
||||
|
||||
struct OpDPPushLinearGradient {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
WrPoint startPoint;
|
||||
WrPoint endPoint;
|
||||
WrGradientExtendMode extendMode;
|
||||
WrGradientStop[] stops;
|
||||
};
|
||||
|
||||
struct OpDPPushRadialGradient {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
WrPoint startCenter;
|
||||
WrPoint endCenter;
|
||||
float startRadius;
|
||||
float endRadius;
|
||||
WrGradientExtendMode extendMode;
|
||||
WrGradientStop[] stops;
|
||||
};
|
||||
|
||||
struct OpDPPushImage {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
MaybeImageMask mask;
|
||||
ImageRendering filter;
|
||||
ImageKey key;
|
||||
};
|
||||
|
||||
struct OpAddExternalImage {
|
||||
uint64_t externalImageId;
|
||||
ImageKey key;
|
||||
};
|
||||
|
||||
struct OpDPPushIframe {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
PipelineId pipelineId;
|
||||
};
|
||||
|
||||
struct OpDPPushText {
|
||||
WrRect bounds;
|
||||
WrRect clip;
|
||||
WrGlyphArray[] glyph_array;
|
||||
float glyph_size;
|
||||
FontKey key;
|
||||
};
|
||||
|
||||
struct OpDPPushBoxShadow {
|
||||
WrRect rect;
|
||||
WrRect clip;
|
||||
WrRect box_bounds;
|
||||
WrPoint offset;
|
||||
WrColor color;
|
||||
float blur_radius;
|
||||
float spread_radius;
|
||||
float border_radius;
|
||||
WrBoxShadowClipMode clip_mode;
|
||||
};
|
||||
|
||||
union WebRenderCommand {
|
||||
OpDPPushStackingContext;
|
||||
OpDPPopStackingContext;
|
||||
OpDPPushScrollLayer;
|
||||
OpDPPopScrollLayer;
|
||||
OpDPPushRect;
|
||||
OpDPPushBorder;
|
||||
OpDPPushLinearGradient;
|
||||
OpDPPushRadialGradient;
|
||||
OpDPPushImage;
|
||||
OpDPPushIframe;
|
||||
OpDPPushText;
|
||||
OpDPPushBoxShadow;
|
||||
};
|
||||
|
||||
union WebRenderParentCommand {
|
||||
OpAddExternalImage;
|
||||
CompositableOperation;
|
||||
|
|
|
@ -191,6 +191,7 @@ EXPORTS.mozilla.layers += [
|
|||
'SourceSurfaceVolatileData.h',
|
||||
'TextureWrapperImage.h',
|
||||
'TransactionIdAllocator.h',
|
||||
'wr/WebRenderBorderLayer.h',
|
||||
'wr/WebRenderBridgeChild.h',
|
||||
'wr/WebRenderBridgeParent.h',
|
||||
'wr/WebRenderCompositableHolder.h',
|
||||
|
@ -199,6 +200,7 @@ EXPORTS.mozilla.layers += [
|
|||
'wr/WebRenderLayerManager.h',
|
||||
'wr/WebRenderLayersLogging.h',
|
||||
'wr/WebRenderMessageUtils.h',
|
||||
'wr/WebRenderTextureHost.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_X11']:
|
||||
|
@ -389,6 +391,7 @@ UNIFIED_SOURCES += [
|
|||
'wr/WebRenderLayersLogging.cpp',
|
||||
'wr/WebRenderPaintedLayer.cpp',
|
||||
'wr/WebRenderTextLayer.cpp',
|
||||
'wr/WebRenderTextureHost.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
|
|
|
@ -40,13 +40,16 @@ class Compositor;
|
|||
already_AddRefed<TextureHost>
|
||||
CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend aBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc,
|
||||
aDeallocator, aFlags);
|
||||
aDeallocator,
|
||||
aBackend,
|
||||
aFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,60 +17,62 @@ namespace layers {
|
|||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
void
|
||||
WebRenderBorderLayer::RenderLayer()
|
||||
/* static */void
|
||||
WebRenderBorderLayer::CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
|
||||
WebRenderLayer* aLayer,
|
||||
BorderColors& aColors,
|
||||
BorderCorners& aCorners,
|
||||
BorderWidths& aWidths,
|
||||
BorderStyles& aBorderStyles,
|
||||
Rect aRect,
|
||||
Rect aClipRect,
|
||||
Rect aRelBounds,
|
||||
Rect aOverflow)
|
||||
{
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(aRelBounds),
|
||||
wr::ToWrRect(aOverflow),
|
||||
nullptr,
|
||||
1.0f,
|
||||
aLayer->GetLayer()->GetTransform(),
|
||||
wr::MixBlendMode::Normal);
|
||||
aBuilder.PushBorder(wr::ToWrRect(aRect), aBuilder.BuildClipRegion(wr::ToWrRect(aClipRect)),
|
||||
wr::ToWrBorderWidths(aWidths[0], aWidths[1], aWidths[2], aWidths[3]),
|
||||
wr::ToWrBorderSide(aColors[0], aBorderStyles[0]),
|
||||
wr::ToWrBorderSide(aColors[1], aBorderStyles[1]),
|
||||
wr::ToWrBorderSide(aColors[2], aBorderStyles[2]),
|
||||
wr::ToWrBorderSide(aColors[3], aBorderStyles[3]),
|
||||
wr::ToWrBorderRadius(aCorners[eCornerTopLeft], aCorners[eCornerTopRight],
|
||||
aCorners[eCornerBottomLeft], aCorners[eCornerBottomRight]));
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
LayerIntRect bounds = GetVisibleRegion().GetBounds();
|
||||
Rect rect(0, 0, bounds.width, bounds.height);
|
||||
Rect clip;
|
||||
Matrix4x4 transform = GetTransform();
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(IntRectToRect(GetClipRect().ref().ToUnknownRect())));
|
||||
} else {
|
||||
clip = rect;
|
||||
}
|
||||
void
|
||||
WebRenderBorderLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
|
||||
Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
gfx::Rect rect = GetWrBoundsRect();
|
||||
gfx::Rect clipRect = GetWrClipRect(rect);
|
||||
|
||||
Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
DumpLayerInfo("BorderLayer", rect);
|
||||
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("BorderLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s\n",
|
||||
this->GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(rect).c_str(),
|
||||
Stringify(clip).c_str());
|
||||
}
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
Nothing(),
|
||||
1.0f,
|
||||
GetAnimations(),
|
||||
transform,
|
||||
WrMixBlendMode::Normal,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushBorder(wr::ToWrRect(rect), wr::ToWrRect(clip),
|
||||
wr::ToWrBorderSide(mWidths[0], mColors[0], mBorderStyles[0]),
|
||||
wr::ToWrBorderSide(mWidths[1], mColors[1], mBorderStyles[1]),
|
||||
wr::ToWrBorderSide(mWidths[2], mColors[2], mBorderStyles[2]),
|
||||
wr::ToWrBorderSide(mWidths[3], mColors[3], mBorderStyles[3]),
|
||||
wr::ToWrBorderRadius(mCorners[0], mCorners[1], mCorners[3], mCorners[2])));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
nullptr,
|
||||
1.0f,
|
||||
//GetAnimations(),
|
||||
GetTransform(),
|
||||
wr::MixBlendMode::Normal);
|
||||
aBuilder.PushBorder(wr::ToWrRect(rect), aBuilder.BuildClipRegion(wr::ToWrRect(clipRect)),
|
||||
wr::ToWrBorderWidths(mWidths[0], mWidths[1], mWidths[2], mWidths[3]),
|
||||
wr::ToWrBorderSide(mColors[0], mBorderStyles[0]),
|
||||
wr::ToWrBorderSide(mColors[1], mBorderStyles[1]),
|
||||
wr::ToWrBorderSide(mColors[2], mBorderStyles[2]),
|
||||
wr::ToWrBorderSide(mColors[3], mBorderStyles[3]),
|
||||
wr::ToWrBorderRadius(mCorners[eCornerTopLeft], mCorners[eCornerTopRight],
|
||||
mCorners[eCornerBottomLeft], mCorners[eCornerBottomRight]));
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -21,6 +21,18 @@ public:
|
|||
MOZ_COUNT_CTOR(WebRenderBorderLayer);
|
||||
}
|
||||
|
||||
static void
|
||||
CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
|
||||
WebRenderLayer* aLayer,
|
||||
BorderColors& aColors,
|
||||
BorderCorners& aCorners,
|
||||
BorderWidths& aWidths,
|
||||
BorderStyles& aBorderStyles,
|
||||
gfx::Rect aRect,
|
||||
gfx::Rect aClipRect,
|
||||
gfx::Rect aRelBounds,
|
||||
gfx::Rect aOverflow);
|
||||
|
||||
protected:
|
||||
virtual ~WebRenderBorderLayer()
|
||||
{
|
||||
|
@ -29,7 +41,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -46,20 +46,6 @@ WebRenderBridgeChild::ActorDestroy(ActorDestroyReason why)
|
|||
mDestroyed = true;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::AddWebRenderCommand(const WebRenderCommand& aCmd)
|
||||
{
|
||||
MOZ_ASSERT(mIsInTransaction);
|
||||
mCommands.AppendElement(aCmd);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands)
|
||||
{
|
||||
MOZ_ASSERT(mIsInTransaction);
|
||||
mCommands.AppendElements(aCommands);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::AddWebRenderParentCommand(const WebRenderParentCommand& aCmd)
|
||||
{
|
||||
|
@ -88,114 +74,8 @@ WebRenderBridgeChild::DPBegin(const gfx::IntSize& aSize)
|
|||
return true;
|
||||
}
|
||||
|
||||
wr::BuiltDisplayList
|
||||
WebRenderBridgeChild::ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
||||
InfallibleTArray<WebRenderCommand>& aCommands)
|
||||
{
|
||||
wr::DisplayListBuilder builder(mPipelineId);
|
||||
builder.Begin(ViewAs<LayerPixel>(aSize));
|
||||
|
||||
for (InfallibleTArray<WebRenderCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
|
||||
const WebRenderCommand& cmd = aCommands[i];
|
||||
|
||||
switch (cmd.type()) {
|
||||
case WebRenderCommand::TOpDPPushStackingContext: {
|
||||
const OpDPPushStackingContext& op = cmd.get_OpDPPushStackingContext();
|
||||
builder.PushStackingContext(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr), op.opacity(), op.matrix(), op.mixBlendMode());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPopStackingContext: {
|
||||
builder.PopStackingContext();
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushScrollLayer: {
|
||||
const OpDPPushScrollLayer& op = cmd.get_OpDPPushScrollLayer();
|
||||
builder.PushScrollLayer(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr));
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPopScrollLayer: {
|
||||
builder.PopScrollLayer();
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushRect: {
|
||||
const OpDPPushRect& op = cmd.get_OpDPPushRect();
|
||||
builder.PushRect(op.bounds(), op.clip(), op.color());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushBorder: {
|
||||
const OpDPPushBorder& op = cmd.get_OpDPPushBorder();
|
||||
builder.PushBorder(op.bounds(), op.clip(),
|
||||
op.top(), op.right(), op.bottom(), op.left(),
|
||||
op.radius());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushLinearGradient: {
|
||||
const OpDPPushLinearGradient& op = cmd.get_OpDPPushLinearGradient();
|
||||
builder.PushLinearGradient(op.bounds(), op.clip(),
|
||||
op.startPoint(), op.endPoint(),
|
||||
op.stops(), op.extendMode());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushRadialGradient: {
|
||||
const OpDPPushRadialGradient& op = cmd.get_OpDPPushRadialGradient();
|
||||
builder.PushRadialGradient(op.bounds(), op.clip(),
|
||||
op.startCenter(), op.endCenter(),
|
||||
op.startRadius(), op.endRadius(),
|
||||
op.stops(), op.extendMode());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushImage: {
|
||||
const OpDPPushImage& op = cmd.get_OpDPPushImage();
|
||||
builder.PushImage(op.bounds(), op.clip(),
|
||||
op.mask().ptrOr(nullptr), op.filter(), wr::ImageKey(op.key()));
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushIframe: {
|
||||
const OpDPPushIframe& op = cmd.get_OpDPPushIframe();
|
||||
builder.PushIFrame(op.bounds(), op.clip(), op.pipelineId());
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushText: {
|
||||
const OpDPPushText& op = cmd.get_OpDPPushText();
|
||||
const nsTArray<WrGlyphArray>& glyph_array = op.glyph_array();
|
||||
|
||||
for (size_t i = 0; i < glyph_array.Length(); i++) {
|
||||
const nsTArray<WrGlyphInstance>& glyphs = glyph_array[i].glyphs;
|
||||
builder.PushText(op.bounds(),
|
||||
op.clip(),
|
||||
glyph_array[i].color,
|
||||
op.key(),
|
||||
Range<const WrGlyphInstance>(glyphs.Elements(), glyphs.Length()),
|
||||
op.glyph_size());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushBoxShadow: {
|
||||
const OpDPPushBoxShadow& op = cmd.get_OpDPPushBoxShadow();
|
||||
builder.PushBoxShadow(op.rect(),
|
||||
op.clip(),
|
||||
op.box_bounds(),
|
||||
op.offset(),
|
||||
op.color(),
|
||||
op.blur_radius(),
|
||||
op.spread_radius(),
|
||||
op.border_radius(),
|
||||
op.clip_mode());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
}
|
||||
}
|
||||
builder.End();
|
||||
wr::BuiltDisplayList dl;
|
||||
builder.Finalize(dl.dl_desc, dl.dl, dl.aux_desc, dl.aux);
|
||||
return dl;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId)
|
||||
WebRenderBridgeChild::DPEnd(wr::DisplayListBuilder &aBuilder, const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId)
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(mIsInTransaction);
|
||||
|
@ -209,7 +89,7 @@ WebRenderBridgeChild::DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aT
|
|||
}
|
||||
}
|
||||
|
||||
wr::BuiltDisplayList dl = ProcessWebrenderCommands(aSize, mCommands);
|
||||
wr::BuiltDisplayList dl = aBuilder.Finalize();
|
||||
ByteBuffer dlData(Move(dl.dl));
|
||||
ByteBuffer auxData(Move(dl.aux));
|
||||
|
||||
|
@ -221,7 +101,6 @@ WebRenderBridgeChild::DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aT
|
|||
dlData, dl.dl_desc, auxData, dl.aux_desc);
|
||||
}
|
||||
|
||||
mCommands.Clear();
|
||||
mParentCommands.Clear();
|
||||
mDestroyedActors.Clear();
|
||||
mReadLocks.Clear();
|
||||
|
|
|
@ -16,6 +16,10 @@ namespace widget {
|
|||
class CompositorWidget;
|
||||
}
|
||||
|
||||
namespace wr {
|
||||
class DisplayListBuilder;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CompositableClient;
|
||||
|
@ -30,16 +34,16 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild
|
|||
public:
|
||||
explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
|
||||
|
||||
void AddWebRenderCommand(const WebRenderCommand& aCmd);
|
||||
void AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands);
|
||||
void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
|
||||
void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
|
||||
|
||||
bool DPBegin(const gfx::IntSize& aSize);
|
||||
void DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId);
|
||||
void DPEnd(wr::DisplayListBuilder &aBuilder, const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId);
|
||||
|
||||
CompositorBridgeChild* GetCompositorBridgeChild();
|
||||
|
||||
wr::PipelineId GetPipeline() { return mPipelineId; }
|
||||
|
||||
// KnowsCompositor
|
||||
TextureForwarder* GetTextureForwarder() override;
|
||||
LayersIPCActor* GetLayersIPCActor() override;
|
||||
|
@ -70,9 +74,6 @@ private:
|
|||
|
||||
uint64_t GetNextExternalImageId();
|
||||
|
||||
wr::BuiltDisplayList ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
||||
InfallibleTArray<WebRenderCommand>& aCommands);
|
||||
|
||||
// CompositableForwarder
|
||||
void Connect(CompositableClient* aCompositable,
|
||||
ImageContainer* aImageContainer = nullptr) override;
|
||||
|
@ -110,7 +111,6 @@ private:
|
|||
|
||||
bool AddOpDestroy(const OpDestroy& aOp);
|
||||
|
||||
nsTArray<WebRenderCommand> mCommands;
|
||||
nsTArray<WebRenderParentCommand> mParentCommands;
|
||||
nsTArray<OpDestroy> mDestroyedActors;
|
||||
nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "mozilla/layers/WebRenderCompositableHolder.h"
|
||||
#include "mozilla/layers/WebRenderTextureHost.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "mozilla/widget/CompositorWidget.h"
|
||||
|
||||
|
@ -239,7 +240,7 @@ WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
|
|||
AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
|
||||
|
||||
++mWrEpoch; // Update webrender epoch
|
||||
ProcessWebrenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
|
||||
ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
|
||||
dl, dlDesc, aux, auxDesc);
|
||||
HoldPendingTransactionId(mWrEpoch, aTransactionId);
|
||||
}
|
||||
|
@ -277,7 +278,7 @@ WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
||||
WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
|
||||
InfallibleTArray<WebRenderParentCommand>& aCommands, const wr::Epoch& aEpoch,
|
||||
const ByteBuffer& dl,
|
||||
const WrBuiltDisplayListDescriptor& dlDesc,
|
||||
|
@ -289,14 +290,34 @@ WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
|||
|
||||
for (InfallibleTArray<WebRenderParentCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
|
||||
const WebRenderParentCommand& cmd = aCommands[i];
|
||||
|
||||
switch (cmd.type()) {
|
||||
case WebRenderParentCommand::TOpAddExternalImage: {
|
||||
const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
|
||||
wr::ImageKey key = op.key();
|
||||
MOZ_ASSERT(mExternalImageIds.Get(op.externalImageId()).get());
|
||||
|
||||
RefPtr<CompositableHost> host = mExternalImageIds.Get(op.externalImageId());
|
||||
if (!host) {
|
||||
NS_ERROR("CompositableHost does not exist");
|
||||
break;
|
||||
}
|
||||
// XXX select Texture for video in CompositeToTarget().
|
||||
TextureHost* texture = host->GetAsTextureHost();
|
||||
if (!texture) {
|
||||
NS_ERROR("TextureHost does not exist");
|
||||
break;
|
||||
}
|
||||
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
|
||||
if (wrTexture) {
|
||||
// XXX handling YUV
|
||||
gfx::SurfaceFormat format =
|
||||
wrTexture->GetFormat() == SurfaceFormat::YUV ? SurfaceFormat::B8G8R8A8 : wrTexture->GetFormat();
|
||||
wr::ImageDescriptor descriptor(wrTexture->GetSize(), wrTexture->GetRGBStride(), format);
|
||||
mApi->AddExternalImageBuffer(key,
|
||||
descriptor,
|
||||
wrTexture->GetExternalImageKey());
|
||||
mCompositableHolder->HoldExternalImage(aEpoch, texture->AsWebRenderTextureHost());
|
||||
keysToDelete.push_back(key);
|
||||
break;
|
||||
}
|
||||
RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
|
||||
|
@ -310,8 +331,7 @@ WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
|||
}
|
||||
|
||||
IntSize size = dSurf->GetSize();
|
||||
wr::ImageDescriptor descriptor(size, map.mStride, SurfaceFormat::B8G8R8A8);
|
||||
wr::ImageKey key = op.key();
|
||||
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
|
||||
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
|
||||
mApi->AddImage(key, descriptor, slice);
|
||||
|
||||
|
@ -335,6 +355,10 @@ WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (mWidget) {
|
||||
LayoutDeviceIntSize size = mWidget->GetClientSize();
|
||||
mApi->SetWindowParameters(size);
|
||||
}
|
||||
mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height),
|
||||
mPipelineId,
|
||||
dlDesc, dl.mData, dl.mLength,
|
||||
|
@ -427,7 +451,6 @@ WebRenderBridgeParent::RecvAddExternalImageId(const uint64_t& aImageId,
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mCompositableHolder->AddExternalImageId(aImageId, host);
|
||||
mExternalImageIds.Put(aImageId, host);
|
||||
|
||||
return IPC_OK();
|
||||
|
@ -450,7 +473,6 @@ WebRenderBridgeParent::RecvAddExternalImageIdForCompositable(const uint64_t& aIm
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mCompositableHolder->AddExternalImageId(aImageId, host);
|
||||
mExternalImageIds.Put(aImageId, host);
|
||||
|
||||
return IPC_OK();
|
||||
|
@ -464,7 +486,6 @@ WebRenderBridgeParent::RecvRemoveExternalImageId(const uint64_t& aImageId)
|
|||
}
|
||||
MOZ_ASSERT(mExternalImageIds.Get(aImageId).get());
|
||||
mExternalImageIds.Remove(aImageId);
|
||||
mCompositableHolder->RemoveExternalImageId(aImageId);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -530,8 +551,6 @@ WebRenderBridgeParent::FlushPendingTransactionIds()
|
|||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t
|
||||
WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
|
||||
{
|
||||
|
@ -544,6 +563,9 @@ WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
|
|||
}
|
||||
mPendingTransactionIds.pop();
|
||||
}
|
||||
|
||||
mCompositableHolder->Update(aEpoch);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -571,13 +593,18 @@ WebRenderBridgeParent::ScheduleComposition()
|
|||
void
|
||||
WebRenderBridgeParent::ClearResources()
|
||||
{
|
||||
DeleteOldImages();
|
||||
if (mCompositableHolder) {
|
||||
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
|
||||
uint64_t externalImageId = iter.Key();
|
||||
mCompositableHolder->RemoveExternalImageId(externalImageId);
|
||||
if (mApi) {
|
||||
++mWrEpoch; // Update webrender epoch
|
||||
mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
|
||||
if (!mKeysToDelete.empty()) {
|
||||
// XXX Sync wait.
|
||||
mApi->WaitFlushed();
|
||||
DeleteOldImages();
|
||||
}
|
||||
}
|
||||
if (mCompositableHolder) {
|
||||
mCompositableHolder->Destroy();
|
||||
}
|
||||
mExternalImageIds.Clear();
|
||||
|
||||
if (mWidget && mCompositorScheduler) {
|
||||
|
|
|
@ -152,7 +152,7 @@ private:
|
|||
virtual ~WebRenderBridgeParent();
|
||||
|
||||
void DeleteOldImages();
|
||||
void ProcessWebrenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderParentCommand>& commands, const wr::Epoch& aEpoch,
|
||||
void ProcessWebRenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderParentCommand>& commands, const wr::Epoch& aEpoch,
|
||||
const ByteBuffer& dl,
|
||||
const WrBuiltDisplayListDescriptor& dlDesc,
|
||||
const ByteBuffer& aux,
|
||||
|
|
|
@ -46,7 +46,7 @@ WebRenderCanvasLayer::Initialize(const Data& aData)
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderCanvasLayer::RenderLayer()
|
||||
WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
UpdateCompositableClient();
|
||||
|
||||
|
@ -61,58 +61,40 @@ WebRenderCanvasLayer::RenderLayer()
|
|||
if (needsYFlip) {
|
||||
transform.PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1);
|
||||
}
|
||||
gfx::Rect rect(0, 0, mBounds.width, mBounds.height);
|
||||
rect = RelativeToVisible(rect);
|
||||
|
||||
gfx::Rect clip;
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(IntRectToRect(GetClipRect().ref().ToUnknownRect())));
|
||||
} else {
|
||||
clip = rect;
|
||||
}
|
||||
|
||||
gfx::Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
Maybe<WrImageMask> mask = buildMaskLayer();
|
||||
wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
gfx::Rect rect = RelativeToVisible(gfx::Rect(0, 0, mBounds.width, mBounds.height));
|
||||
gfx::Rect clipRect = GetWrClipRect(rect);
|
||||
|
||||
Maybe<WrImageMask> mask = BuildWrMaskLayer();
|
||||
WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect));
|
||||
|
||||
wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
|
||||
wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
DumpLayerInfo("CanvasLayer", rect);
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("CanvasLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, texture-filter=%s, mix-blend-mode=%s\n",
|
||||
printf_stderr("CanvasLayer %p texture-filter=%s\n",
|
||||
this->GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(rect).c_str(),
|
||||
Stringify(clip).c_str(),
|
||||
Stringify(filter).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
Stringify(filter).c_str());
|
||||
}
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask,
|
||||
1.0f,
|
||||
GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
WrImageKey key;
|
||||
key.mNamespace = WrBridge()->GetNamespace();
|
||||
key.mHandle = WrBridge()->GetNextResourceId();
|
||||
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask.ptrOr(nullptr),
|
||||
1.0f,
|
||||
//GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode);
|
||||
aBuilder.PushImage(wr::ToWrRect(rect), clip, filter, key);
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -45,7 +45,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
|
||||
protected:
|
||||
uint64_t mExternalImageId;
|
||||
|
|
|
@ -17,59 +17,31 @@ namespace layers {
|
|||
using namespace mozilla::gfx;
|
||||
|
||||
void
|
||||
WebRenderColorLayer::RenderLayer()
|
||||
WebRenderColorLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
|
||||
gfx::Matrix4x4 transform = GetTransform();
|
||||
LayerIntRegion visibleRegion = GetVisibleRegion();
|
||||
LayerIntRect bounds = visibleRegion.GetBounds();
|
||||
Rect rect(0, 0, bounds.width, bounds.height);
|
||||
Rect clip;
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(IntRectToRect(GetClipRect().ref().ToUnknownRect())));
|
||||
} else {
|
||||
clip = rect;
|
||||
}
|
||||
|
||||
gfx::Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
Maybe<WrImageMask> mask = buildMaskLayer();
|
||||
gfx::Rect rect = GetWrBoundsRect();
|
||||
gfx::Rect clipRect = GetWrClipRect(rect);
|
||||
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("ColorLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, mix-blend-mode=%s\n",
|
||||
this->GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(rect).c_str(),
|
||||
Stringify(clip).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
}
|
||||
Maybe<WrImageMask> mask = BuildWrMaskLayer();
|
||||
WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect));
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
DumpLayerInfo("ColorLayer", rect);
|
||||
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask,
|
||||
mask.ptrOr(nullptr),
|
||||
1.0f,
|
||||
GetAnimations(),
|
||||
//GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushRect(wr::ToWrRect(rect), wr::ToWrRect(clip), wr::ToWrColor(mColor)));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
mixBlendMode);
|
||||
aBuilder.PushRect(wr::ToWrRect(rect), clip, wr::ToWrColor(mColor));
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "WebRenderCompositableHolder.h"
|
||||
|
||||
#include "CompositableHost.h"
|
||||
//#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/WebRenderImageHost.h"
|
||||
#include "mozilla/layers/WebRenderTextureHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -22,36 +23,36 @@ WebRenderCompositableHolder::WebRenderCompositableHolder()
|
|||
WebRenderCompositableHolder::~WebRenderCompositableHolder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WebRenderCompositableHolder);
|
||||
Destroy();
|
||||
MOZ_ASSERT(mWebRenderTextureHosts.empty());
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCompositableHolder::Destroy()
|
||||
{
|
||||
mCompositableHosts.Clear();
|
||||
while (!mWebRenderTextureHosts.empty()) {
|
||||
mWebRenderTextureHosts.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCompositableHolder::AddExternalImageId(uint64_t aExternalImageId, CompositableHost* aHost)
|
||||
WebRenderCompositableHolder::HoldExternalImage(const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
|
||||
{
|
||||
MOZ_ASSERT(!mCompositableHosts.Get(aExternalImageId));
|
||||
mCompositableHosts.Put(aExternalImageId, aHost);
|
||||
MOZ_ASSERT(aTexture);
|
||||
// Hold WebRenderTextureHost until end of its usage on RenderThread
|
||||
mWebRenderTextureHosts.push(ForwardingTextureHosts(aEpoch, aTexture));
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCompositableHolder::RemoveExternalImageId(uint64_t aExternalImageId)
|
||||
WebRenderCompositableHolder::Update(const wr::Epoch& aEpoch)
|
||||
{
|
||||
MOZ_ASSERT(mCompositableHosts.Get(aExternalImageId));
|
||||
mCompositableHosts.Remove(aExternalImageId);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCompositableHolder::UpdateExternalImages()
|
||||
{
|
||||
for (auto iter = mCompositableHosts.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<CompositableHost>& host = iter.Data();
|
||||
// XXX Change to correct TextrueSource handling here.
|
||||
host->BindTextureSource();
|
||||
if (mWebRenderTextureHosts.empty()) {
|
||||
return;
|
||||
}
|
||||
while (!mWebRenderTextureHosts.empty()) {
|
||||
if (aEpoch <= mWebRenderTextureHosts.front().mEpoch) {
|
||||
break;
|
||||
}
|
||||
mWebRenderTextureHosts.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,21 @@
|
|||
#ifndef MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H
|
||||
#define MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
#include <queue>
|
||||
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace wr {
|
||||
class WebRenderAPI;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CompositableHost;
|
||||
class WebRenderTextureHost;
|
||||
|
||||
class WebRenderCompositableHolder final
|
||||
{
|
||||
|
@ -21,20 +30,26 @@ public:
|
|||
explicit WebRenderCompositableHolder();
|
||||
|
||||
protected:
|
||||
virtual ~WebRenderCompositableHolder();
|
||||
~WebRenderCompositableHolder();
|
||||
|
||||
public:
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
void AddExternalImageId(uint64_t aExternalImageId, CompositableHost* aHost);
|
||||
void RemoveExternalImageId(uint64_t aExternalImageId);
|
||||
void UpdateExternalImages();
|
||||
void Destroy();
|
||||
void HoldExternalImage(const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture);
|
||||
void Update(const wr::Epoch& aEpoch);
|
||||
|
||||
private:
|
||||
|
||||
// Holds CompositableHosts that are bound to external image ids.
|
||||
nsDataHashtable<nsUint64HashKey, RefPtr<CompositableHost> > mCompositableHosts;
|
||||
struct ForwardingTextureHosts {
|
||||
ForwardingTextureHosts(const wr::Epoch& aEpoch, TextureHost* aTexture)
|
||||
: mEpoch(aEpoch)
|
||||
, mTexture(aTexture)
|
||||
{}
|
||||
wr::Epoch mEpoch;
|
||||
CompositableTextureHostRef mTexture;
|
||||
};
|
||||
|
||||
// Holds forwarding WebRenderTextureHosts.
|
||||
std::queue<ForwardingTextureHosts> mWebRenderTextureHosts;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -15,25 +15,17 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
void
|
||||
WebRenderContainerLayer::RenderLayer()
|
||||
WebRenderContainerLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
|
||||
nsTArray<LayerPolygon> children = SortChildrenBy3DZOrder(SortMode::WITHOUT_GEOMETRY);
|
||||
gfx::Matrix4x4 transform = GetTransform();
|
||||
gfx::Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
|
||||
gfx::Matrix4x4 transform = GetTransform();
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
Maybe<WrImageMask> mask = buildMaskLayer();
|
||||
|
||||
Maybe<WrImageMask> mask = BuildWrMaskLayer();
|
||||
|
||||
wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("ContainerLayer %p using bounds=%s, overflow=%s, transform=%s, mix-blend-mode=%s\n",
|
||||
|
@ -43,33 +35,29 @@ WebRenderContainerLayer::RenderLayer()
|
|||
Stringify(transform).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
}
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask,
|
||||
GetLocalOpacity(),
|
||||
GetLayer()->GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask.ptrOr(nullptr),
|
||||
GetLocalOpacity(),
|
||||
//GetLayer()->GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode);
|
||||
for (LayerPolygon& child : children) {
|
||||
if (child.layer->IsBackfaceHidden()) {
|
||||
continue;
|
||||
}
|
||||
ToWebRenderLayer(child.layer)->RenderLayer();
|
||||
ToWebRenderLayer(child.layer)->RenderLayer(aBuilder);
|
||||
}
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPopStackingContext());
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderRefLayer::RenderLayer()
|
||||
WebRenderRefLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
|
||||
gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
|
||||
gfx::Matrix4x4 transform;// = GetTransform();
|
||||
gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
|
||||
|
||||
WrClipRegion clipRegion = aBuilder.BuildClipRegion(wr::ToWrRect(relBounds));
|
||||
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("RefLayer %p (%" PRIu64 ") using bounds/overflow=%s, transform=%s\n",
|
||||
|
@ -79,7 +67,7 @@ WebRenderRefLayer::RenderLayer()
|
|||
Stringify(transform).c_str());
|
||||
}
|
||||
|
||||
WrBridge()->AddWebRenderCommand(OpDPPushIframe(wr::ToWrRect(relBounds), wr::ToWrRect(relBounds), wr::AsPipelineId(mId)));
|
||||
aBuilder.PushIFrame(wr::ToWrRect(relBounds), clipRegion, wr::AsPipelineId(mId));
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -31,7 +31,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
|
||||
{
|
||||
|
|
|
@ -16,18 +16,19 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
void
|
||||
WebRenderDisplayItemLayer::RenderLayer()
|
||||
WebRenderDisplayItemLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
if (mItem) {
|
||||
wr::DisplayListBuilder builder(WrBridge()->GetPipeline());
|
||||
// We might have recycled this layer. Throw away the old commands.
|
||||
mCommands.Clear();
|
||||
mParentCommands.Clear();
|
||||
mItem->CreateWebRenderCommands(mCommands, mParentCommands, this);
|
||||
mItem->CreateWebRenderCommands(builder, mParentCommands, this);
|
||||
mBuiltDisplayList = builder.Finalize();
|
||||
}
|
||||
// else we have an empty transaction and just use the
|
||||
// old commands.
|
||||
|
||||
WrBridge()->AddWebRenderCommands(mCommands);
|
||||
aBuilder.PushBuiltDisplayList(Move(mBuiltDisplayList));
|
||||
WrBridge()->AddWebRenderParentCommands(mParentCommands);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,16 +29,15 @@ public:
|
|||
protected:
|
||||
virtual ~WebRenderDisplayItemLayer()
|
||||
{
|
||||
mCommands.Clear();
|
||||
MOZ_COUNT_DTOR(WebRenderDisplayItemLayer);
|
||||
}
|
||||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
|
||||
private:
|
||||
nsTArray<WebRenderCommand> mCommands;
|
||||
wr::BuiltDisplayList mBuiltDisplayList;
|
||||
nsTArray<WebRenderParentCommand> mParentCommands;
|
||||
RefPtr<ImageClient> mImageClient;
|
||||
RefPtr<ImageContainer> mImageContainer;
|
||||
|
|
|
@ -102,7 +102,10 @@ WebRenderImageHost::GetCompositionTime() const
|
|||
TextureHost*
|
||||
WebRenderImageHost::GetAsTextureHost(IntRect* aPictureRect)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
TimedImage* img = ChooseImage();
|
||||
if (img) {
|
||||
return img->mTextureHost;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
|
||||
virtual void CleanupResources() override;
|
||||
|
||||
virtual WebRenderImageHost* AsWebRenderImageHost() override { return this; }
|
||||
|
||||
protected:
|
||||
// ImageComposite
|
||||
virtual TimeStamp GetCompositionTime() const override;
|
||||
|
|
|
@ -80,7 +80,7 @@ WebRenderImageLayer::ClearCachedResources()
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderImageLayer::RenderLayer()
|
||||
WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
if (!mContainer) {
|
||||
return;
|
||||
|
@ -127,62 +127,108 @@ WebRenderImageLayer::RenderLayer()
|
|||
return;
|
||||
}
|
||||
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
gfx::Matrix4x4 transform = GetTransform();
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
|
||||
Matrix4x4 transform = GetTransform();
|
||||
Rect rect(0, 0, size.width, size.height);
|
||||
Rect clip;
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(IntRectToRect(GetClipRect().ref().ToUnknownRect())));
|
||||
} else {
|
||||
clip = rect;
|
||||
gfx::Rect rect = gfx::Rect(0, 0, size.width, size.height);
|
||||
if (mScaleMode != ScaleMode::SCALE_NONE) {
|
||||
NS_ASSERTION(mScaleMode == ScaleMode::STRETCH,
|
||||
"No other scalemodes than stretch and none supported yet.");
|
||||
rect = gfx::Rect(0, 0, mScaleToSize.width, mScaleToSize.height);
|
||||
}
|
||||
rect = RelativeToVisible(rect);
|
||||
gfx::Rect clipRect = GetWrClipRect(rect);
|
||||
|
||||
Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
Maybe<WrImageMask> mask = BuildWrMaskLayer();
|
||||
WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect));
|
||||
|
||||
Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
Maybe<WrImageMask> mask = buildMaskLayer();
|
||||
wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
DumpLayerInfo("Image Layer", rect);
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("ImageLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, texture-filter=%s, mix-blend-mode=%s\n",
|
||||
this->GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(rect).c_str(),
|
||||
Stringify(clip).c_str(),
|
||||
Stringify(filter).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
printf_stderr("ImageLayer %p texture-filter=%s \n",
|
||||
GetLayer(),
|
||||
Stringify(filter).c_str());
|
||||
}
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask,
|
||||
1.0f,
|
||||
GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
WrImageKey key;
|
||||
key.mNamespace = WrBridge()->GetNamespace();
|
||||
key.mHandle = WrBridge()->GetNextResourceId();
|
||||
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask.ptrOr(nullptr),
|
||||
1.0f,
|
||||
//GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode);
|
||||
aBuilder.PushImage(wr::ToWrRect(rect), clip, filter, key);
|
||||
aBuilder.PopStackingContext();
|
||||
|
||||
//mContainer->SetImageFactory(originalIF);
|
||||
}
|
||||
|
||||
Maybe<WrImageMask>
|
||||
WebRenderImageLayer::RenderMaskLayer()
|
||||
{
|
||||
if (!mContainer) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
CompositableType type = GetImageClientType();
|
||||
if (type == CompositableType::UNKNOWN) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(GetImageClientType() != CompositableType::UNKNOWN);
|
||||
|
||||
if (GetImageClientType() == CompositableType::IMAGE && !mImageClient) {
|
||||
mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
|
||||
WrBridge(),
|
||||
TextureFlags::DEFAULT);
|
||||
if (!mImageClient) {
|
||||
return Nothing();
|
||||
}
|
||||
mImageClient->Connect();
|
||||
}
|
||||
|
||||
if (!mExternalImageId) {
|
||||
if (GetImageClientType() == CompositableType::IMAGE_BRIDGE) {
|
||||
MOZ_ASSERT(!mImageClient);
|
||||
mExternalImageId = WrBridge()->AllocExternalImageId(mContainer->GetAsyncContainerHandle());
|
||||
} else {
|
||||
// Handle CompositableType::IMAGE case
|
||||
MOZ_ASSERT(mImageClient);
|
||||
mExternalImageId = WrBridge()->AllocExternalImageIdForCompositable(mImageClient);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(mExternalImageId);
|
||||
|
||||
// XXX Not good for async ImageContainer case.
|
||||
AutoLockImage autoLock(mContainer);
|
||||
Image* image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return Nothing();
|
||||
}
|
||||
if (mImageClient && !mImageClient->UpdateImage(mContainer, /* unused */0)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
WrImageKey key;
|
||||
key.mNamespace = WrBridge()->GetNamespace();
|
||||
key.mHandle = WrBridge()->GetNextResourceId();
|
||||
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
|
||||
|
||||
gfx::IntSize size = image->GetSize();
|
||||
WrImageMask imageMask;
|
||||
imageMask.image = key;
|
||||
imageMask.rect = wr::ToWrRect(Rect(0, 0, size.width, size.height));
|
||||
imageMask.repeat = false;
|
||||
return Some(imageMask);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -32,7 +32,8 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
Maybe<WrImageMask> RenderMaskLayer() override;
|
||||
|
||||
protected:
|
||||
CompositableType GetImageClientType();
|
||||
|
|
|
@ -109,92 +109,80 @@ WebRenderLayer::TransformedVisibleBoundsRelativeToParent()
|
|||
}
|
||||
|
||||
Maybe<WrImageMask>
|
||||
WebRenderLayer::buildMaskLayer() {
|
||||
Maybe<WrImageMask> mask = Nothing();
|
||||
WrImageMask imageMask;
|
||||
Layer* maskLayer = GetLayer()->GetMaskLayer();
|
||||
|
||||
if (maskLayer) {
|
||||
RefPtr<SourceSurface> surface = WebRenderLayer::ToWebRenderLayer(maskLayer)->GetAsSourceSurface();
|
||||
if (surface) {
|
||||
Matrix transform;
|
||||
Matrix4x4 effectiveTransform = maskLayer->GetEffectiveTransform();
|
||||
DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform);
|
||||
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
|
||||
//XXX: let's assert that the mask transform is the same as the layer transform
|
||||
//transform.PostTranslate(-aDeviceOffset.x, -aDeviceOffset.y);
|
||||
{
|
||||
RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
|
||||
DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::MapType::READ);
|
||||
gfx::IntSize size = surface->GetSize();
|
||||
MOZ_RELEASE_ASSERT(surface->GetFormat() == SurfaceFormat::A8, "bad format");
|
||||
wr::ByteBuffer buf(size.height * map.GetStride(), map.GetData());
|
||||
WrImageKey maskKey;
|
||||
maskKey.mNamespace = WrBridge()->GetNamespace();
|
||||
maskKey.mHandle = WrBridge()->GetNextResourceId();
|
||||
WrBridge()->SendAddImage(maskKey, size, map.GetStride(), SurfaceFormat::A8, buf);
|
||||
|
||||
imageMask.image = maskKey;
|
||||
imageMask.rect = wr::ToWrRect(Rect(0, 0, size.width, size.height));
|
||||
imageMask.repeat = false;
|
||||
WrManager()->AddImageKeyForDiscard(maskKey);
|
||||
mask = Some(imageMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
WrScrollFrameStackingContextGenerator::WrScrollFrameStackingContextGenerator(
|
||||
WebRenderLayer* aLayer)
|
||||
: mLayer(aLayer)
|
||||
WebRenderLayer::BuildWrMaskLayer()
|
||||
{
|
||||
Matrix4x4 identity;
|
||||
Layer* layer = mLayer->GetLayer();
|
||||
for (size_t i = layer->GetScrollMetadataCount(); i > 0; i--) {
|
||||
const FrameMetrics& fm = layer->GetFrameMetrics(i - 1);
|
||||
if (!fm.IsScrollable()) {
|
||||
continue;
|
||||
}
|
||||
Rect bounds = fm.GetCompositionBounds().ToUnknownRect();
|
||||
Rect overflow = (fm.GetExpandedScrollableRect() * fm.LayersPixelsPerCSSPixel()).ToUnknownRect();
|
||||
Point scrollPos = (fm.GetScrollOffset() * fm.LayersPixelsPerCSSPixel()).ToUnknownPoint();
|
||||
Rect parentBounds = mLayer->ParentStackingContextBounds(i);
|
||||
bounds.MoveBy(-parentBounds.x, -parentBounds.y);
|
||||
// Subtract the MT scroll position from the overflow here so that the WR
|
||||
// scroll offset (which is the APZ async scroll component) always fits in
|
||||
// the available overflow. If we didn't do this and WR did bounds checking
|
||||
// on the scroll offset, we'd fail those checks.
|
||||
overflow.MoveBy(bounds.x - scrollPos.x, bounds.y - scrollPos.y);
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("Pushing stacking context id %" PRIu64 " with bounds=%s, overflow=%s\n",
|
||||
fm.GetScrollId(), Stringify(bounds).c_str(), Stringify(overflow).c_str());
|
||||
}
|
||||
|
||||
/* mLayer->WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushScrollLayer(wr::ToWrRect(bounds),
|
||||
wr::ToWrRect(overflow),
|
||||
Nothing(),
|
||||
fm.GetScrollId()));*/
|
||||
if (GetLayer()->GetMaskLayer()) {
|
||||
WebRenderLayer* maskLayer = ToWebRenderLayer(GetLayer()->GetMaskLayer());
|
||||
return maskLayer->RenderMaskLayer();
|
||||
}
|
||||
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
WrScrollFrameStackingContextGenerator::~WrScrollFrameStackingContextGenerator()
|
||||
gfx::Rect
|
||||
WebRenderLayer::GetWrBoundsRect()
|
||||
{
|
||||
Layer* layer = mLayer->GetLayer();
|
||||
for (size_t i = 0; i < layer->GetScrollMetadataCount(); i++) {
|
||||
const FrameMetrics& fm = layer->GetFrameMetrics(i);
|
||||
if (!fm.IsScrollable()) {
|
||||
continue;
|
||||
}
|
||||
if (gfxPrefs::LayersDump()) printf_stderr("Popping stacking context id %" PRIu64"\n", fm.GetScrollId());
|
||||
// mLayer->WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
}
|
||||
LayerIntRect bounds = GetLayer()->GetVisibleRegion().GetBounds();
|
||||
return Rect(0, 0, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
gfx::Rect
|
||||
WebRenderLayer::GetWrClipRect(gfx::Rect& aRect)
|
||||
{
|
||||
gfx::Rect clip;
|
||||
Layer* layer = GetLayer();
|
||||
Matrix4x4 transform = layer->GetTransform();
|
||||
if (layer->GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(
|
||||
IntRectToRect(layer->GetClipRect().ref().ToUnknownRect()))
|
||||
);
|
||||
} else {
|
||||
clip = aRect;
|
||||
}
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
gfx::Rect
|
||||
WebRenderLayer::GetWrRelBounds()
|
||||
{
|
||||
gfx::Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
gfx::Matrix4x4 transform = GetLayer()->GetTransform();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
|
||||
return relBounds;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderLayer::DumpLayerInfo(const char* aLayerType, gfx::Rect& aRect)
|
||||
{
|
||||
if (!gfxPrefs::LayersDump()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix4x4 transform = GetLayer()->GetTransform();
|
||||
Rect clip = GetWrClipRect(aRect);
|
||||
Rect relBounds = GetWrRelBounds();
|
||||
Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetLayer()->GetMixBlendMode());
|
||||
|
||||
printf_stderr("%s %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, mix-blend-mode=%s\n",
|
||||
aLayerType,
|
||||
GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(aRect).c_str(),
|
||||
Stringify(clip).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
}
|
||||
|
||||
WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
|
||||
: mWidget(aWidget)
|
||||
|
@ -218,14 +206,15 @@ WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild,
|
|||
MOZ_ASSERT(mWrChild == nullptr);
|
||||
MOZ_ASSERT(aTextureFactoryIdentifier);
|
||||
|
||||
LayoutDeviceIntSize size = mWidget->GetClientSize();
|
||||
TextureFactoryIdentifier textureFactoryIdentifier;
|
||||
uint32_t id_namespace;
|
||||
PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
|
||||
size,
|
||||
&textureFactoryIdentifier,
|
||||
&id_namespace);
|
||||
MOZ_ASSERT(bridge);
|
||||
mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
|
||||
LayoutDeviceIntSize size = mWidget->GetClientSize();
|
||||
WrBridge()->SendCreate(size.ToUnknownSize());
|
||||
WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
|
||||
WrBridge()->SetNamespace(id_namespace);
|
||||
|
@ -316,12 +305,13 @@ WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
|||
return;
|
||||
}
|
||||
|
||||
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer();
|
||||
wr::DisplayListBuilder builder(WrBridge()->GetPipeline());
|
||||
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder);
|
||||
|
||||
bool sync = mTarget != nullptr;
|
||||
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
|
||||
|
||||
WrBridge()->DPEnd(size.ToUnknownSize(), sync, mLatestTransactionId);
|
||||
WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId);
|
||||
|
||||
MakeSnapshotIfRequired(size);
|
||||
|
||||
|
@ -346,7 +336,7 @@ WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
|
|||
SurfaceFormat::B8G8R8A8,
|
||||
aSize.ToUnknownSize(),
|
||||
BackendType::SKIA,
|
||||
TextureFlags::DEFAULT);
|
||||
TextureFlags::SNAPSHOT);
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/layers/TransactionIdAllocator.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
|
@ -28,7 +29,12 @@ class WebRenderLayer
|
|||
{
|
||||
public:
|
||||
virtual Layer* GetLayer() = 0;
|
||||
virtual void RenderLayer() = 0;
|
||||
virtual void RenderLayer(wr::DisplayListBuilder& aBuilder) = 0;
|
||||
virtual Maybe<WrImageMask> RenderMaskLayer()
|
||||
{
|
||||
MOZ_ASSERT(false);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; }
|
||||
static inline WebRenderLayer*
|
||||
|
@ -48,17 +54,11 @@ public:
|
|||
gfx::Point GetOffsetToParent();
|
||||
gfx::Rect TransformedVisibleBoundsRelativeToParent();
|
||||
protected:
|
||||
Maybe<WrImageMask> buildMaskLayer();
|
||||
|
||||
};
|
||||
|
||||
class MOZ_RAII WrScrollFrameStackingContextGenerator
|
||||
{
|
||||
public:
|
||||
explicit WrScrollFrameStackingContextGenerator(WebRenderLayer* aLayer);
|
||||
~WrScrollFrameStackingContextGenerator();
|
||||
private:
|
||||
WebRenderLayer* mLayer;
|
||||
gfx::Rect GetWrBoundsRect();
|
||||
gfx::Rect GetWrRelBounds();
|
||||
gfx::Rect GetWrClipRect(gfx::Rect& aRect);
|
||||
void DumpLayerInfo(const char* aLayerType, gfx::Rect& aRect);
|
||||
Maybe<WrImageMask> BuildWrMaskLayer();
|
||||
};
|
||||
|
||||
class WebRenderLayerManager final : public LayerManager
|
||||
|
|
|
@ -99,174 +99,23 @@ struct ParamTraits<WrImageFormat>
|
|||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrBorderStyle>
|
||||
: public ContiguousEnumSerializer<
|
||||
WrBorderStyle,
|
||||
WrBorderStyle::None,
|
||||
WrBorderStyle::Sentinel>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrColor>
|
||||
struct ParamTraits<WrSize>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrColor& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.r);
|
||||
WriteParam(aMsg, aParam.g);
|
||||
WriteParam(aMsg, aParam.b);
|
||||
WriteParam(aMsg, aParam.a);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrColor* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->r)
|
||||
&& ReadParam(aMsg, aIter, &aResult->g)
|
||||
&& ReadParam(aMsg, aIter, &aResult->b)
|
||||
&& ReadParam(aMsg, aIter, &aResult->a);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrGlyphInstance>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrGlyphInstance& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.index);
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrGlyphInstance* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->index)
|
||||
&& ReadParam(aMsg, aIter, &aResult->x)
|
||||
&& ReadParam(aMsg, aIter, &aResult->y);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrGlyphArray>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrGlyphArray& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.color);
|
||||
size_t length = aParam.glyphs.Length();
|
||||
|
||||
WriteParam(aMsg, length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
WriteParam(aMsg, aParam.glyphs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrGlyphArray* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &aResult->color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length;
|
||||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->glyphs.SetLength(length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (!ReadParam(aMsg, aIter, &aResult->glyphs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrGradientStop>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrGradientStop& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.offset);
|
||||
WriteParam(aMsg, aParam.color);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrGradientStop* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->offset)
|
||||
&& ReadParam(aMsg, aIter, &aResult->color);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrBorderSide>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrBorderSide& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.width);
|
||||
WriteParam(aMsg, aParam.color);
|
||||
WriteParam(aMsg, aParam.style);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrBorderSide* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->width)
|
||||
&& ReadParam(aMsg, aIter, &aResult->color)
|
||||
&& ReadParam(aMsg, aIter, &aResult->style);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrLayoutSize>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrLayoutSize& aParam)
|
||||
Write(Message* aMsg, const WrSize& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.width);
|
||||
WriteParam(aMsg, aParam.height);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrLayoutSize* aResult)
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrSize* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->width)
|
||||
&& ReadParam(aMsg, aIter, &aResult->height);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrBorderRadius>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrBorderRadius& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.top_left);
|
||||
WriteParam(aMsg, aParam.top_right);
|
||||
WriteParam(aMsg, aParam.bottom_left);
|
||||
WriteParam(aMsg, aParam.bottom_right);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrBorderRadius* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->top_left)
|
||||
&& ReadParam(aMsg, aIter, &aResult->top_right)
|
||||
&& ReadParam(aMsg, aIter, &aResult->bottom_left)
|
||||
&& ReadParam(aMsg, aIter, &aResult->bottom_right);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrRect>
|
||||
{
|
||||
|
@ -307,26 +156,6 @@ struct ParamTraits<WrPoint>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrImageMask>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WrImageMask& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.image);
|
||||
WriteParam(aMsg, aParam.rect);
|
||||
WriteParam(aMsg, aParam.repeat);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WrImageMask* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->image)
|
||||
&& ReadParam(aMsg, aIter, &aResult->rect)
|
||||
&& ReadParam(aMsg, aIter, &aResult->repeat);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrBuiltDisplayListDescriptor>
|
||||
{
|
||||
|
@ -365,43 +194,6 @@ struct ParamTraits<WrAuxiliaryListsDescriptor>
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrImageRendering>
|
||||
: public ContiguousEnumSerializer<
|
||||
WrImageRendering,
|
||||
WrImageRendering::Auto,
|
||||
WrImageRendering::Sentinel>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrMixBlendMode>
|
||||
: public ContiguousEnumSerializer<
|
||||
WrMixBlendMode,
|
||||
WrMixBlendMode::Normal,
|
||||
WrMixBlendMode::Sentinel>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrBoxShadowClipMode>
|
||||
: public ContiguousEnumSerializer<
|
||||
WrBoxShadowClipMode,
|
||||
WrBoxShadowClipMode::None,
|
||||
WrBoxShadowClipMode::Sentinel>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WrGradientExtendMode>
|
||||
: public ContiguousEnumSerializer<
|
||||
WrGradientExtendMode,
|
||||
WrGradientExtendMode::Clamp,
|
||||
WrGradientExtendMode::Sentinel>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // GFX_WEBRENDERMESSAGEUTILS_H
|
||||
|
|
|
@ -114,7 +114,7 @@ WebRenderPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback)
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderPaintedLayer::RenderLayer()
|
||||
WebRenderPaintedLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
// XXX We won't keep using ContentClient for WebRenderPaintedLayer in the future and
|
||||
// there is a crash problem for ContentClient on MacOS. So replace ContentClient with
|
||||
|
@ -182,63 +182,36 @@ WebRenderPaintedLayer::RenderLayer()
|
|||
mImageContainer->SetCurrentImageInTransaction(image);
|
||||
if (!mImageClient->UpdateImage(mImageContainer, /* unused */0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
||||
|
||||
Matrix4x4 transform = GetTransform();
|
||||
|
||||
// Since we are creating a stacking context below using the visible region of
|
||||
// this layer, we need to make sure the image display item has coordinates
|
||||
// relative to the visible region.
|
||||
Rect rect(0, 0, size.width, size.height);
|
||||
Rect clip;
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToVisible(transform.Inverse().TransformBounds(IntRectToRect(GetClipRect().ref().ToUnknownRect())));
|
||||
} else {
|
||||
clip = rect;
|
||||
}
|
||||
|
||||
Maybe<WrImageMask> mask = buildMaskLayer();
|
||||
Rect relBounds = VisibleBoundsRelativeToParent();
|
||||
if (!transform.IsIdentity()) {
|
||||
// WR will only apply the 'translate' of the transform, so we need to do the scale/rotation manually.
|
||||
gfx::Matrix4x4 boundTransform = transform;
|
||||
boundTransform._41 = 0.0f;
|
||||
boundTransform._42 = 0.0f;
|
||||
boundTransform._43 = 0.0f;
|
||||
relBounds.MoveTo(boundTransform.TransformPoint(relBounds.TopLeft()));
|
||||
}
|
||||
gfx::Matrix4x4 transform = GetTransform();
|
||||
gfx::Rect relBounds = GetWrRelBounds();
|
||||
gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
|
||||
Rect overflow(0, 0, relBounds.width, relBounds.height);
|
||||
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
gfx::Rect rect(0, 0, size.width, size.height);
|
||||
gfx::Rect clipRect = GetWrClipRect(rect);
|
||||
|
||||
if (gfxPrefs::LayersDump()) {
|
||||
printf_stderr("PaintedLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, mix-blend-mode=%s\n",
|
||||
this->GetLayer(),
|
||||
Stringify(relBounds).c_str(),
|
||||
Stringify(overflow).c_str(),
|
||||
Stringify(transform).c_str(),
|
||||
Stringify(rect).c_str(),
|
||||
Stringify(clip).c_str(),
|
||||
Stringify(mixBlendMode).c_str());
|
||||
}
|
||||
Maybe<WrImageMask> mask = BuildWrMaskLayer();
|
||||
WrClipRegion clip = aBuilder.BuildClipRegion(wr::ToWrRect(clipRect));
|
||||
|
||||
wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
||||
|
||||
DumpLayerInfo("PaintedLayer", rect);
|
||||
|
||||
WrBridge()->AddWebRenderCommand(
|
||||
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask,
|
||||
1.0f,
|
||||
GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode,
|
||||
FrameMetrics::NULL_SCROLL_ID));
|
||||
WrImageKey key;
|
||||
key.mNamespace = WrBridge()->GetNamespace();
|
||||
key.mHandle = WrBridge()->GetNextResourceId();
|
||||
WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), wr::ImageRendering::Auto, key));
|
||||
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
||||
|
||||
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
|
||||
wr::ToWrRect(overflow),
|
||||
mask.ptrOr(nullptr),
|
||||
1.0f,
|
||||
//GetAnimations(),
|
||||
transform,
|
||||
mixBlendMode);
|
||||
aBuilder.PushImage(wr::ToWrRect(rect), clip, wr::ImageRendering::Auto, key);
|
||||
aBuilder.PopStackingContext();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
}
|
||||
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
void PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates);
|
||||
void RenderLayerWithReadback(ReadbackProcessor *aReadback);
|
||||
RefPtr<ContentClient> mContentClient;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace layers {
|
|||
using namespace mozilla::gfx;
|
||||
|
||||
void
|
||||
WebRenderTextLayer::RenderLayer()
|
||||
WebRenderTextLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
|
||||
{
|
||||
if (mBounds.IsEmpty()) {
|
||||
return;
|
||||
|
@ -39,10 +39,8 @@ WebRenderTextLayer::RenderLayer()
|
|||
Stringify(clip).c_str());
|
||||
}
|
||||
|
||||
nsTArray<WebRenderCommand> commands;
|
||||
mGlyphHelper.BuildWebRenderCommands(WrBridge(), commands, mGlyphs, mFont,
|
||||
mGlyphHelper.BuildWebRenderCommands(WrBridge(), aBuilder, mGlyphs, mFont,
|
||||
GetOffsetToParent(), rect, clip);
|
||||
WrBridge()->AddWebRenderCommands(commands);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -31,7 +31,7 @@ protected:
|
|||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
|
||||
|
||||
protected:
|
||||
gfx::WebRenderGlyphHelper mGlyphHelper;
|
||||
|
@ -40,4 +40,4 @@ protected:
|
|||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GFX_WEBRENDERTEXTLAYER_H
|
||||
#endif // GFX_WEBRENDERTEXTLAYER_H
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebRenderTextureHost.h"
|
||||
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/webrender/RenderTextureHost.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
uint64_t WebRenderTextureHost::sSerialCounter(0);
|
||||
|
||||
WebRenderTextureHost::WebRenderTextureHost(TextureFlags aFlags,
|
||||
TextureHost* aTexture)
|
||||
: TextureHost(aFlags)
|
||||
, mExternalImageId(++sSerialCounter)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WebRenderTextureHost);
|
||||
mWrappedTextureHost = aTexture;
|
||||
|
||||
// XXX support only BufferTextureHost for now.
|
||||
BufferTextureHost* bufferTexture = aTexture->AsBufferTextureHost();
|
||||
MOZ_ASSERT(bufferTexture);
|
||||
RefPtr<wr::RenderTextureHost> texture =
|
||||
new wr::RenderTextureHost(bufferTexture->GetBuffer(),
|
||||
bufferTexture->GetBufferDescriptor());
|
||||
wr::RenderThread::Get()->RegisterExternalImage(mExternalImageId, texture);
|
||||
}
|
||||
|
||||
WebRenderTextureHost::~WebRenderTextureHost()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WebRenderTextureHost);
|
||||
wr::RenderThread::Get()->UnregisterExternalImage(mExternalImageId);
|
||||
}
|
||||
|
||||
bool
|
||||
WebRenderTextureHost::Lock()
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderTextureHost::Unlock()
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
WebRenderTextureHost::BindTextureSource(CompositableTextureSourceRef& aTexture)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface>
|
||||
WebRenderTextureHost::GetAsSurface()
|
||||
{
|
||||
if (!mWrappedTextureHost) {
|
||||
return nullptr;
|
||||
}
|
||||
return mWrappedTextureHost->GetAsSurface();
|
||||
}
|
||||
|
||||
Compositor*
|
||||
WebRenderTextureHost::GetCompositor()
|
||||
{
|
||||
//MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderTextureHost::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
}
|
||||
|
||||
YUVColorSpace
|
||||
WebRenderTextureHost::GetYUVColorSpace() const
|
||||
{
|
||||
if (mWrappedTextureHost) {
|
||||
return mWrappedTextureHost->GetYUVColorSpace();
|
||||
}
|
||||
return YUVColorSpace::UNKNOWN;
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
WebRenderTextureHost::GetSize() const
|
||||
{
|
||||
if (!mWrappedTextureHost) {
|
||||
return gfx::IntSize();
|
||||
}
|
||||
return mWrappedTextureHost->GetSize();
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
WebRenderTextureHost::GetFormat() const
|
||||
{
|
||||
if (!mWrappedTextureHost) {
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
return mWrappedTextureHost->GetFormat();
|
||||
}
|
||||
|
||||
int32_t
|
||||
WebRenderTextureHost::GetRGBStride()
|
||||
{
|
||||
if (!mWrappedTextureHost) {
|
||||
return 0;
|
||||
}
|
||||
gfx::SurfaceFormat format = GetFormat();
|
||||
if (GetFormat() == SurfaceFormat::YUV) {
|
||||
// XXX this stride is used until yuv image rendering by webrender is used.
|
||||
// Software converted RGB buffers strides are aliened to 16
|
||||
return GetAlignedStride<16>(GetSize().width, BytesPerPixel(SurfaceFormat::B8G8R8A8));
|
||||
}
|
||||
return ImageDataSerializer::ComputeRGBStride(format, GetSize().width);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_WEBRENDERTEXTUREHOST_H
|
||||
#define MOZILLA_GFX_WEBRENDERTEXTUREHOST_H
|
||||
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class WebRenderTextureHost : public TextureHost
|
||||
{
|
||||
public:
|
||||
WebRenderTextureHost(TextureFlags aFlags,
|
||||
TextureHost* aTexture);
|
||||
virtual ~WebRenderTextureHost();
|
||||
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual Compositor* GetCompositor() override;
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
|
||||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
|
||||
|
||||
virtual YUVColorSpace GetYUVColorSpace() const override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
virtual const char* Name() override { return "WebRenderTextureHost"; }
|
||||
#endif
|
||||
|
||||
virtual WebRenderTextureHost* AsWebRenderTextureHost() override { return this; }
|
||||
|
||||
uint64_t GetExternalImageKey() { return mExternalImageId; }
|
||||
|
||||
int32_t GetRGBStride();
|
||||
protected:
|
||||
RefPtr<TextureHost> mWrappedTextureHost;
|
||||
uint64_t mExternalImageId;
|
||||
|
||||
static uint64_t sSerialCounter;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_GFX_WEBRENDERTEXTUREHOST_H
|
|
@ -148,6 +148,7 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
|
|||
|
||||
// host deserialization
|
||||
RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
|
||||
LayersBackend::LAYERS_NONE,
|
||||
texture->GetFlags());
|
||||
|
||||
ASSERT_TRUE(host.get() != nullptr);
|
||||
|
@ -192,6 +193,7 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
|
|||
|
||||
// host deserialization
|
||||
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
|
||||
LayersBackend::LAYERS_NONE,
|
||||
client->GetFlags());
|
||||
|
||||
RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());
|
||||
|
|
|
@ -460,13 +460,15 @@ private:
|
|||
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.border-layers", LayersAllowBorderLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.text-layers", LayersAllowTextLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.bullet-layers", LayersAllowBulletLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.caret-layers", LayersAllowCaretLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.boxshadow-outer-layers", LayersAllowOuterBoxShadow, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.boxshadow-inset-layers", LayersAllowInsetBoxShadow, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.outline-layers", LayersAllowOutlineLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.boxshadow-outer-layers", LayersAllowOuterBoxShadow, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.bullet-layers", LayersAllowBulletLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.button-foreground-layers", LayersAllowButtonForegroundLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.caret-layers", LayersAllowCaretLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.displaybuttonborder-layers", LayersAllowDisplayButtonBorder, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.image-layers", LayersAllowImageLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.outline-layers", LayersAllowOutlineLayers, bool, false);
|
||||
DECL_GFX_PREF(Live, "layers.advanced.text-layers", LayersAllowTextLayers, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.amd-switchable-gfx.enabled", LayersAMDSwitchableGfxEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled", AsyncPanZoomEnabledDoNotUseDirectly, bool, true);
|
||||
DECL_GFX_PREF(Once, "layers.async-pan-zoom.separate-event-thread", AsyncPanZoomSeparateEventThread, bool, false);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIClipboardHelper.h"
|
||||
|
@ -1460,7 +1461,7 @@ WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
|
|||
|
||||
void
|
||||
WebRenderGlyphHelper::BuildWebRenderCommands(WebRenderBridgeChild* aBridge,
|
||||
nsTArray<WebRenderCommand>& aCommands,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
const nsTArray<GlyphArray>& aGlyphs,
|
||||
ScaledFont* aFont,
|
||||
const Point& aOffset,
|
||||
|
@ -1481,30 +1482,28 @@ WebRenderGlyphHelper::BuildWebRenderCommands(WebRenderBridgeChild* aBridge,
|
|||
|
||||
aBridge->SendAddRawFont(key, fontBuffer, mIndex);
|
||||
|
||||
nsTArray<WrGlyphArray> wr_glyphs;
|
||||
wr_glyphs.SetLength(aGlyphs.Length());
|
||||
WrClipRegion clipRegion = aBuilder.BuildClipRegion(wr::ToWrRect(aClip));
|
||||
|
||||
for (size_t i = 0; i < aGlyphs.Length(); i++) {
|
||||
GlyphArray glyph_array = aGlyphs[i];
|
||||
nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
|
||||
|
||||
nsTArray<WrGlyphInstance>& wr_glyph_instances = wr_glyphs[i].glyphs;
|
||||
nsTArray<WrGlyphInstance> wr_glyph_instances;
|
||||
wr_glyph_instances.SetLength(glyphs.Length());
|
||||
wr_glyphs[i].color = glyph_array.color().value();
|
||||
|
||||
for (size_t j = 0; j < glyphs.Length(); j++) {
|
||||
wr_glyph_instances[j].index = glyphs[j].mIndex;
|
||||
wr_glyph_instances[j].x = glyphs[j].mPosition.x - aOffset.x;
|
||||
wr_glyph_instances[j].y = glyphs[j].mPosition.y - aOffset.y;
|
||||
}
|
||||
}
|
||||
aBuilder.PushText(wr::ToWrRect(aBounds),
|
||||
clipRegion,
|
||||
glyph_array.color().value(),
|
||||
key,
|
||||
Range<const WrGlyphInstance>(wr_glyph_instances.Elements(), wr_glyph_instances.Length()),
|
||||
mGlyphSize);
|
||||
|
||||
aCommands.AppendElement(OpDPPushText(
|
||||
wr::ToWrRect(aBounds),
|
||||
wr::ToWrRect(aClip),
|
||||
wr_glyphs,
|
||||
mGlyphSize,
|
||||
key));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -35,6 +35,9 @@ class WebRenderCommand;
|
|||
namespace image {
|
||||
class ImageRegion;
|
||||
} // namespace image
|
||||
namespace wr {
|
||||
class DisplayListBuilder;
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
class gfxUtils {
|
||||
|
@ -328,7 +331,7 @@ public:
|
|||
}
|
||||
|
||||
void BuildWebRenderCommands(layers::WebRenderBridgeChild* aChild,
|
||||
nsTArray<layers::WebRenderCommand>& aCommands,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
const nsTArray<layers::GlyphArray>& aGlyphs,
|
||||
ScaledFont* aFont,
|
||||
const Point& aOffset,
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
[package]
|
||||
name = "webrender"
|
||||
version = "0.19.0"
|
||||
version = "0.24.0"
|
||||
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/servo/webrender"
|
||||
build = "build.rs"
|
||||
|
||||
[features]
|
||||
default = ["codegen", "freetype-lib"]
|
||||
codegen = ["webrender_traits/codegen"]
|
||||
default = ["freetype-lib"]
|
||||
freetype-lib = ["freetype/servo-freetype-sys"]
|
||||
serde_derive = ["webrender_traits/serde_derive"]
|
||||
profiler = ["thread_profiler/thread_profiler"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -19,7 +17,7 @@ bincode = "1.0.0-alpha2"
|
|||
bit-set = "0.4"
|
||||
byteorder = "1.0"
|
||||
euclid = "0.11"
|
||||
fnv="1.0"
|
||||
fnv = "1.0"
|
||||
gleam = "0.2.30"
|
||||
lazy_static = "0.2"
|
||||
log = "0.3"
|
||||
|
@ -27,7 +25,7 @@ num-traits = "0.1.32"
|
|||
offscreen_gl_context = {version = "0.6", features = ["serde", "osmesa"]}
|
||||
time = "0.1"
|
||||
threadpool = "1.3.2"
|
||||
webrender_traits = {path = "../webrender_traits", default-features = false}
|
||||
webrender_traits = {path = "../webrender_traits"}
|
||||
bitflags = "0.7"
|
||||
gamma-lut = "0.1"
|
||||
thread_profiler = "0.1.1"
|
||||
|
@ -39,7 +37,7 @@ angle = {git = "https://github.com/servo/angle", branch = "servo"}
|
|||
freetype = { version = "0.2", default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
servo-dwrote = "0.2"
|
||||
dwrote = "0.3"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-graphics = "0.7.0"
|
||||
|
|
|
@ -625,12 +625,9 @@ struct YuvImage {
|
|||
YuvImage fetch_yuv_image(int index) {
|
||||
YuvImage image;
|
||||
|
||||
ivec2 uv = get_fetch_uv_4(index);
|
||||
ivec2 uv = get_fetch_uv_1(index);
|
||||
|
||||
image.y_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(0, 0));
|
||||
image.u_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(1, 0));
|
||||
image.v_st_rect = texelFetchOffset(sData64, uv, 0, ivec2(2, 0));
|
||||
vec4 size_color_space = texelFetchOffset(sData64, uv, 0, ivec2(3, 0));
|
||||
vec4 size_color_space = texelFetchOffset(sData16, uv, 0, ivec2(0, 0));
|
||||
image.size = size_color_space.xy;
|
||||
image.color_space = int(size_color_space.z);
|
||||
|
||||
|
|
|
@ -151,6 +151,22 @@ vec3 Luminosity(vec3 Cb, vec3 Cs) {
|
|||
return SetLum(Cb, Lum(Cs));
|
||||
}
|
||||
|
||||
const int MixBlendMode_Multiply = 1;
|
||||
const int MixBlendMode_Screen = 2;
|
||||
const int MixBlendMode_Overlay = 3;
|
||||
const int MixBlendMode_Darken = 4;
|
||||
const int MixBlendMode_Lighten = 5;
|
||||
const int MixBlendMode_ColorDodge = 6;
|
||||
const int MixBlendMode_ColorBurn = 7;
|
||||
const int MixBlendMode_HardLight = 8;
|
||||
const int MixBlendMode_SoftLight = 9;
|
||||
const int MixBlendMode_Difference = 10;
|
||||
const int MixBlendMode_Exclusion = 11;
|
||||
const int MixBlendMode_Hue = 12;
|
||||
const int MixBlendMode_Saturation = 13;
|
||||
const int MixBlendMode_Color = 14;
|
||||
const int MixBlendMode_Luminosity = 15;
|
||||
|
||||
void main(void) {
|
||||
vec4 Cb = texture(sCache, vUv0);
|
||||
vec4 Cs = texture(sCache, vUv1);
|
||||
|
@ -159,60 +175,62 @@ void main(void) {
|
|||
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
|
||||
switch (vOp) {
|
||||
case 1:
|
||||
case MixBlendMode_Multiply:
|
||||
result.rgb = Multiply(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 2:
|
||||
case MixBlendMode_Screen:
|
||||
result.rgb = Screen(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 3:
|
||||
result.rgb = HardLight(Cs.rgb, Cb.rgb); // Overlay is inverse of Hardlight
|
||||
case MixBlendMode_Overlay:
|
||||
// Overlay is inverse of Hardlight
|
||||
result.rgb = HardLight(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case 4:
|
||||
// mix-blend-mode: darken
|
||||
case MixBlendMode_Darken:
|
||||
result.rgb = min(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case 5:
|
||||
// mix-blend-mode: lighten
|
||||
case MixBlendMode_Lighten:
|
||||
result.rgb = max(Cs.rgb, Cb.rgb);
|
||||
break;
|
||||
case 6:
|
||||
case MixBlendMode_ColorDodge:
|
||||
result.r = ColorDodge(Cb.r, Cs.r);
|
||||
result.g = ColorDodge(Cb.g, Cs.g);
|
||||
result.b = ColorDodge(Cb.b, Cs.b);
|
||||
break;
|
||||
case 7:
|
||||
case MixBlendMode_ColorBurn:
|
||||
result.r = ColorBurn(Cb.r, Cs.r);
|
||||
result.g = ColorBurn(Cb.g, Cs.g);
|
||||
result.b = ColorBurn(Cb.b, Cs.b);
|
||||
break;
|
||||
case 8:
|
||||
case MixBlendMode_HardLight:
|
||||
result.rgb = HardLight(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 9:
|
||||
case MixBlendMode_SoftLight:
|
||||
result.r = SoftLight(Cb.r, Cs.r);
|
||||
result.g = SoftLight(Cb.g, Cs.g);
|
||||
result.b = SoftLight(Cb.b, Cs.b);
|
||||
break;
|
||||
case 10:
|
||||
case MixBlendMode_Difference:
|
||||
result.rgb = Difference(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 11:
|
||||
case MixBlendMode_Exclusion:
|
||||
result.rgb = Exclusion(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 12:
|
||||
case MixBlendMode_Hue:
|
||||
result.rgb = Hue(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 13:
|
||||
case MixBlendMode_Saturation:
|
||||
result.rgb = Saturation(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 14:
|
||||
case MixBlendMode_Color:
|
||||
result.rgb = Color(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
case 15:
|
||||
case MixBlendMode_Luminosity:
|
||||
result.rgb = Luminosity(Cb.rgb, Cs.rgb);
|
||||
break;
|
||||
}
|
||||
|
||||
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
|
||||
result.a = Cs.a;
|
||||
|
||||
oFragColor = result;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ void main(void) {
|
|||
|
||||
vec2 texture_size = vec2(textureSize(sCache, 0));
|
||||
|
||||
vec2 st0 = (backdrop_task.render_target_origin + vec2(0.0, backdrop_task.size.y)) / texture_size;
|
||||
vec2 st1 = (backdrop_task.render_target_origin + vec2(backdrop_task.size.x, 0.0)) / texture_size;
|
||||
vec2 st0 = backdrop_task.render_target_origin / texture_size;
|
||||
vec2 st1 = (backdrop_task.render_target_origin + backdrop_task.size) / texture_size;
|
||||
vUv0 = vec3(mix(st0, st1, aPosition.xy), backdrop_task.render_target_layer_index);
|
||||
|
||||
st0 = src_task.render_target_origin / texture_size;
|
||||
|
|
|
@ -12,25 +12,33 @@ void main(void) {
|
|||
|
||||
RectWithSize segment_rect;
|
||||
vec2 axis;
|
||||
vec4 adjusted_color_g0 = g0.color;
|
||||
vec4 adjusted_color_g1 = g1.color;
|
||||
if (gradient.start_end_point.y == gradient.start_end_point.w) {
|
||||
float x0 = mix(gradient.start_end_point.x,
|
||||
gradient.start_end_point.z,
|
||||
g0.offset.x);
|
||||
float x1 = mix(gradient.start_end_point.x,
|
||||
gradient.start_end_point.z,
|
||||
g1.offset.x);
|
||||
segment_rect.p0 = vec2(x0, prim.local_rect.p0.y);
|
||||
segment_rect.size = vec2(x1 - x0, prim.local_rect.size.y);
|
||||
vec2 x = mix(gradient.start_end_point.xx, gradient.start_end_point.zz,
|
||||
vec2(g0.offset.x, g1.offset.x));
|
||||
// The start and end point of gradient might exceed the geometry rect. So clamp
|
||||
// it to the geometry rect.
|
||||
x = clamp(x, prim.local_rect.p0.xx, prim.local_rect.p0.xx + prim.local_rect.size.xx);
|
||||
vec2 adjusted_offset =
|
||||
(x - gradient.start_end_point.xx) / (gradient.start_end_point.zz - gradient.start_end_point.xx);
|
||||
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
|
||||
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
|
||||
segment_rect.p0 = vec2(x.x, prim.local_rect.p0.y);
|
||||
segment_rect.size = vec2(x.y - x.x, prim.local_rect.size.y);
|
||||
axis = vec2(1.0, 0.0);
|
||||
} else {
|
||||
float y0 = mix(gradient.start_end_point.y,
|
||||
gradient.start_end_point.w,
|
||||
g0.offset.x);
|
||||
float y1 = mix(gradient.start_end_point.y,
|
||||
gradient.start_end_point.w,
|
||||
g1.offset.x);
|
||||
segment_rect.p0 = vec2(prim.local_rect.p0.x, y0);
|
||||
segment_rect.size = vec2(prim.local_rect.size.x, y1 - y0);
|
||||
vec2 y = mix(gradient.start_end_point.yy, gradient.start_end_point.ww,
|
||||
vec2(g0.offset.x, g1.offset.x));
|
||||
// The start and end point of gradient might exceed the geometry rect. So clamp
|
||||
// it to the geometry rect.
|
||||
y = clamp(y, prim.local_rect.p0.yy, prim.local_rect.p0.yy + prim.local_rect.size.yy);
|
||||
vec2 adjusted_offset =
|
||||
(y - gradient.start_end_point.yy) / (gradient.start_end_point.ww - gradient.start_end_point.yy);
|
||||
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
|
||||
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
|
||||
segment_rect.p0 = vec2(prim.local_rect.p0.x, y.x);
|
||||
segment_rect.size = vec2(prim.local_rect.size.x, y.y - y.x);
|
||||
axis = vec2(0.0, 1.0);
|
||||
}
|
||||
|
||||
|
@ -56,5 +64,5 @@ void main(void) {
|
|||
|
||||
write_clip(vi.screen_pos, prim.clip_area);
|
||||
|
||||
vColor = mix(g0.color, g1.color, dot(f, axis));
|
||||
vColor = mix(adjusted_color_g0, adjusted_color_g1, dot(f, axis));
|
||||
}
|
||||
|
|
|
@ -31,5 +31,5 @@ void main(void) {
|
|||
|
||||
alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize))));
|
||||
|
||||
oFragColor = vec4(1.0, 1.0, 1.0, alpha) * textureLod(sColor0, st, 0.0);
|
||||
oFragColor = vec4(alpha) * textureLod(sColor0, st, 0.0);
|
||||
}
|
||||
|
|
|
@ -23,20 +23,23 @@ void main(void) {
|
|||
#endif
|
||||
|
||||
YuvImage image = fetch_yuv_image(prim.prim_index);
|
||||
ResourceRect y_rect = fetch_resource_rect(prim.user_data.x);
|
||||
ResourceRect u_rect = fetch_resource_rect(prim.user_data.x + 1);
|
||||
ResourceRect v_rect = fetch_resource_rect(prim.user_data.x + 2);
|
||||
|
||||
vec2 y_texture_size = vec2(textureSize(sColor0, 0));
|
||||
vec2 y_st0 = image.y_st_rect.xy / y_texture_size;
|
||||
vec2 y_st1 = image.y_st_rect.zw / y_texture_size;
|
||||
vec2 y_st0 = y_rect.uv_rect.xy / y_texture_size;
|
||||
vec2 y_st1 = y_rect.uv_rect.zw / y_texture_size;
|
||||
|
||||
vTextureSizeY = y_st1 - y_st0;
|
||||
vTextureOffsetY = y_st0;
|
||||
|
||||
vec2 uv_texture_size = vec2(textureSize(sColor1, 0));
|
||||
vec2 u_st0 = image.u_st_rect.xy / uv_texture_size;
|
||||
vec2 u_st1 = image.u_st_rect.zw / uv_texture_size;
|
||||
vec2 u_st0 = u_rect.uv_rect.xy / uv_texture_size;
|
||||
vec2 u_st1 = u_rect.uv_rect.zw / uv_texture_size;
|
||||
|
||||
vec2 v_st0 = image.v_st_rect.xy / uv_texture_size;
|
||||
vec2 v_st1 = image.v_st_rect.zw / uv_texture_size;
|
||||
vec2 v_st0 = v_rect.uv_rect.xy / uv_texture_size;
|
||||
vec2 v_st1 = v_rect.uv_rect.zw / uv_texture_size;
|
||||
|
||||
// This assumes the U and V surfaces have the same size.
|
||||
vTextureSizeUv = u_st1 - u_st0;
|
||||
|
|
|
@ -4,11 +4,16 @@
|
|||
|
||||
use euclid::Point3D;
|
||||
use geometry::ray_intersects_rect;
|
||||
use mask_cache::{ClipSource, MaskCacheInfo};
|
||||
use prim_store::GpuBlock32;
|
||||
use renderer::VertexDataStore;
|
||||
use spring::{DAMPING, STIFFNESS, Spring};
|
||||
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
|
||||
use webrender_traits::{LayerToWorldTransform, PipelineId, ScrollEventPhase, ScrollLayerId};
|
||||
use webrender_traits::{ScrollLayerRect, ScrollLocation, ScrollToWorldTransform, WorldPoint};
|
||||
use webrender_traits::{WorldPoint4D};
|
||||
use tiling::PackedLayerIndex;
|
||||
use util::TransformedRect;
|
||||
use webrender_traits::{ClipRegion, LayerPixel, LayerPoint, LayerRect, LayerSize};
|
||||
use webrender_traits::{LayerToScrollTransform, LayerToWorldTransform, PipelineId};
|
||||
use webrender_traits::{ScrollEventPhase, ScrollLayerId, ScrollLayerRect, ScrollLocation};
|
||||
use webrender_traits::{ServoScrollRootId, WorldPoint, WorldPoint4D};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
const CAN_OVERSCROLL: bool = true;
|
||||
|
@ -16,9 +21,67 @@ const CAN_OVERSCROLL: bool = true;
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
const CAN_OVERSCROLL: bool = false;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipInfo {
|
||||
/// The ClipSource for this node, which is used to generate mask_cache_info.
|
||||
pub clip_source: ClipSource,
|
||||
|
||||
/// The MaskCacheInfo for this node, which is produced by processing the
|
||||
/// provided ClipSource.
|
||||
pub mask_cache_info: Option<MaskCacheInfo>,
|
||||
|
||||
/// The packed layer index for this node, which is used to render a clip mask
|
||||
/// for it, if necessary.
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
|
||||
/// The final transformed rectangle of this clipping region for this node,
|
||||
/// which depends on the screen rectangle and the transformation of all of
|
||||
/// the parents.
|
||||
pub xf_rect: Option<TransformedRect>,
|
||||
|
||||
/// An external identifier that is used to scroll this clipping node
|
||||
/// from the API.
|
||||
pub scroll_root_id: Option<ServoScrollRootId>,
|
||||
}
|
||||
|
||||
impl ClipInfo {
|
||||
pub fn new(clip_region: &ClipRegion,
|
||||
clip_store: &mut VertexDataStore<GpuBlock32>,
|
||||
packed_layer_index: PackedLayerIndex,
|
||||
scroll_root_id: Option<ServoScrollRootId>)
|
||||
-> ClipInfo {
|
||||
// We pass true here for the MaskCacheInfo because this type of
|
||||
// mask needs an extra clip for the clip rectangle.
|
||||
let clip_source = ClipSource::Region(clip_region.clone());
|
||||
ClipInfo {
|
||||
mask_cache_info: MaskCacheInfo::new(&clip_source, true, clip_store),
|
||||
clip_source: clip_source,
|
||||
packed_layer_index: packed_layer_index,
|
||||
xf_rect: None,
|
||||
scroll_root_id: scroll_root_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_masking(&self) -> bool {
|
||||
match self.mask_cache_info {
|
||||
Some(ref info) => info.is_masking(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum NodeType {
|
||||
/// Transform for this layer, relative to parent reference frame. A reference
|
||||
/// frame establishes a new coordinate space in the tree.
|
||||
ReferenceFrame(LayerToScrollTransform),
|
||||
|
||||
/// Other nodes just do clipping, but no transformation.
|
||||
Clip(ClipInfo),
|
||||
}
|
||||
|
||||
/// Contains scrolling and transform information stacking contexts.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipScrollNode {
|
||||
/// Manages scrolling offset, overscroll state etc.
|
||||
pub scrolling: ScrollingState,
|
||||
|
@ -26,44 +89,78 @@ pub struct ClipScrollNode {
|
|||
/// Size of the content inside the scroll region (in logical pixels)
|
||||
pub content_size: LayerSize,
|
||||
|
||||
/// Viewing rectangle
|
||||
/// Viewing rectangle in the coordinate system of the parent reference frame.
|
||||
pub local_viewport_rect: LayerRect,
|
||||
|
||||
/// Viewing rectangle clipped against parent layer(s)
|
||||
/// Clip rect of this node - typically the same as viewport rect, except
|
||||
/// in overscroll cases.
|
||||
pub local_clip_rect: LayerRect,
|
||||
|
||||
/// Viewport rectangle clipped against parent layer(s) viewport rectangles.
|
||||
/// This is in the coordinate system of the parent reference frame.
|
||||
pub combined_local_viewport_rect: LayerRect,
|
||||
|
||||
/// World transform for the viewport rect itself.
|
||||
/// World transform for the viewport rect itself. This is the parent
|
||||
/// reference frame transformation plus the scrolling offsets provided by
|
||||
/// the nodes in between the reference frame and this node.
|
||||
pub world_viewport_transform: LayerToWorldTransform,
|
||||
|
||||
/// World transform for content within this layer
|
||||
/// World transform for content transformed by this node.
|
||||
pub world_content_transform: LayerToWorldTransform,
|
||||
|
||||
/// Transform for this layer, relative to parent scrollable layer.
|
||||
pub local_transform: LayerToScrollTransform,
|
||||
|
||||
/// Pipeline that this layer belongs to
|
||||
pub pipeline_id: PipelineId,
|
||||
|
||||
/// Parent layer. If this is None, we are the root node.
|
||||
pub parent: Option<ScrollLayerId>,
|
||||
|
||||
/// Child layers
|
||||
pub children: Vec<ScrollLayerId>,
|
||||
|
||||
/// Whether or not this node is a reference frame.
|
||||
pub node_type: NodeType,
|
||||
}
|
||||
|
||||
impl ClipScrollNode {
|
||||
pub fn new(local_viewport_rect: &LayerRect,
|
||||
pub fn new(pipeline_id: PipelineId,
|
||||
parent_id: ScrollLayerId,
|
||||
local_viewport_rect: &LayerRect,
|
||||
content_size: LayerSize,
|
||||
local_transform: &LayerToScrollTransform,
|
||||
pipeline_id: PipelineId)
|
||||
clip_info: ClipInfo)
|
||||
-> ClipScrollNode {
|
||||
ClipScrollNode {
|
||||
scrolling: ScrollingState::new(),
|
||||
content_size: content_size,
|
||||
local_viewport_rect: *local_viewport_rect,
|
||||
combined_local_viewport_rect: *local_viewport_rect,
|
||||
local_clip_rect: *local_viewport_rect,
|
||||
combined_local_viewport_rect: LayerRect::zero(),
|
||||
world_viewport_transform: LayerToWorldTransform::identity(),
|
||||
world_content_transform: LayerToWorldTransform::identity(),
|
||||
local_transform: *local_transform,
|
||||
parent: Some(parent_id),
|
||||
children: Vec::new(),
|
||||
pipeline_id: pipeline_id,
|
||||
node_type: NodeType::Clip(clip_info),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_reference_frame(parent_id: Option<ScrollLayerId>,
|
||||
local_viewport_rect: &LayerRect,
|
||||
content_size: LayerSize,
|
||||
local_transform: &LayerToScrollTransform,
|
||||
pipeline_id: PipelineId)
|
||||
-> ClipScrollNode {
|
||||
ClipScrollNode {
|
||||
scrolling: ScrollingState::new(),
|
||||
content_size: content_size,
|
||||
local_viewport_rect: *local_viewport_rect,
|
||||
local_clip_rect: *local_viewport_rect,
|
||||
combined_local_viewport_rect: LayerRect::zero(),
|
||||
world_viewport_transform: LayerToWorldTransform::identity(),
|
||||
world_content_transform: LayerToWorldTransform::identity(),
|
||||
parent: parent_id,
|
||||
children: Vec::new(),
|
||||
pipeline_id: pipeline_id,
|
||||
node_type: NodeType::ReferenceFrame(*local_transform),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,9 +214,16 @@ impl ClipScrollNode {
|
|||
}
|
||||
|
||||
pub fn update_transform(&mut self,
|
||||
parent_world_transform: &ScrollToWorldTransform,
|
||||
parent_viewport_rect: &ScrollLayerRect) {
|
||||
let inv_transform = match self.local_transform.inverse() {
|
||||
parent_reference_frame_transform: &LayerToWorldTransform,
|
||||
parent_combined_viewport_rect: &ScrollLayerRect,
|
||||
parent_accumulated_scroll_offset: LayerPoint) {
|
||||
|
||||
let local_transform = match self.node_type {
|
||||
NodeType::ReferenceFrame(transform) => transform,
|
||||
NodeType::Clip(_) => LayerToScrollTransform::identity(),
|
||||
};
|
||||
|
||||
let inv_transform = match local_transform.inverse() {
|
||||
Some(transform) => transform,
|
||||
None => {
|
||||
// If a transform function causes the current transformation matrix of an object
|
||||
|
@ -129,18 +233,40 @@ impl ClipScrollNode {
|
|||
}
|
||||
};
|
||||
|
||||
let parent_viewport_rect_in_local_space = inv_transform.transform_rect(parent_viewport_rect)
|
||||
.translate(&-self.scrolling.offset);
|
||||
let local_viewport_rect = self.local_viewport_rect.translate(&-self.scrolling.offset);
|
||||
let viewport_rect = parent_viewport_rect_in_local_space.intersection(&local_viewport_rect)
|
||||
.unwrap_or(LayerRect::zero());
|
||||
// We are trying to move the combined viewport rectangle of our parent nodes into the
|
||||
// coordinate system of this node, so we must invert our transformation (only for
|
||||
// reference frames) and then apply the scroll offset of all the parent layers.
|
||||
let parent_combined_viewport_in_local_space =
|
||||
inv_transform.pre_translated(-parent_accumulated_scroll_offset.x,
|
||||
-parent_accumulated_scroll_offset.y,
|
||||
0.0)
|
||||
.transform_rect(parent_combined_viewport_rect);
|
||||
|
||||
self.combined_local_viewport_rect = viewport_rect;
|
||||
self.world_viewport_transform = parent_world_transform.pre_mul(&self.local_transform);
|
||||
self.world_content_transform = self.world_viewport_transform
|
||||
.pre_translated(self.scrolling.offset.x,
|
||||
self.scrolling.offset.y,
|
||||
0.0);
|
||||
// Now that we have the combined viewport rectangle of the parent nodes in local space,
|
||||
// we do the intersection and get our combined viewport rect in the coordinate system
|
||||
// starting from our origin.
|
||||
self.combined_local_viewport_rect =
|
||||
parent_combined_viewport_in_local_space.intersection(&self.local_clip_rect)
|
||||
.unwrap_or(LayerRect::zero());
|
||||
|
||||
// The transformation for this viewport in world coordinates is the transformation for
|
||||
// our parent reference frame, plus any accumulated scrolling offsets from nodes
|
||||
// between our reference frame and this node. For reference frames, we also include
|
||||
// whatever local transformation this reference frame provides. This can be combined
|
||||
// with the local_viewport_rect to get its position in world space.
|
||||
self.world_viewport_transform =
|
||||
parent_reference_frame_transform
|
||||
.pre_translated(parent_accumulated_scroll_offset.x,
|
||||
parent_accumulated_scroll_offset.y,
|
||||
0.0)
|
||||
.pre_mul(&local_transform.with_destination::<LayerPixel>());
|
||||
|
||||
// The transformation for any content inside of us is the viewport transformation, plus
|
||||
// whatever scrolling offset we supply as well.
|
||||
self.world_content_transform =
|
||||
self.world_viewport_transform.pre_translated(self.scrolling.offset.x,
|
||||
self.scrolling.offset.y,
|
||||
0.0);
|
||||
}
|
||||
|
||||
pub fn scrollable_height(&self) -> f32 {
|
||||
|
@ -265,7 +391,7 @@ impl ClipScrollNode {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ScrollingState {
|
||||
pub offset: LayerPoint,
|
||||
pub spring: Spring,
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollingState};
|
||||
use fnv::FnvHasher;
|
||||
use clip_scroll_node::{ClipScrollNode, ScrollingState};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::hash::BuildHasherDefault;
|
||||
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId};
|
||||
use webrender_traits::{ScrollEventPhase, ScrollLayerId, ScrollLayerInfo, ScrollLayerPixel};
|
||||
use webrender_traits::{ScrollLayerRect, ScrollLayerState, ScrollLocation, ScrollToWorldTransform};
|
||||
use webrender_traits::{ServoScrollRootId, WorldPoint, as_scroll_parent_rect};
|
||||
use webrender_traits::{LayerPoint, LayerRect, LayerToScrollTransform, LayerToWorldTransform};
|
||||
use webrender_traits::{PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerInfo};
|
||||
use webrender_traits::{ScrollLayerRect, ScrollLayerState, ScrollLocation, ServoScrollRootId};
|
||||
use webrender_traits::{WorldPoint, as_scroll_parent_rect};
|
||||
|
||||
pub type ScrollStates = HashMap<ScrollLayerId, ScrollingState, BuildHasherDefault<FnvHasher>>;
|
||||
|
||||
|
@ -48,7 +48,7 @@ impl ClipScrollTree {
|
|||
current_scroll_layer_id: None,
|
||||
root_reference_frame_id: ScrollLayerId::root_reference_frame(dummy_pipeline),
|
||||
topmost_scroll_layer_id: ScrollLayerId::root_scroll_layer(dummy_pipeline),
|
||||
current_reference_frame_id: 1,
|
||||
current_reference_frame_id: 0,
|
||||
pipelines_to_discard: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
@ -67,26 +67,6 @@ impl ClipScrollTree {
|
|||
self.topmost_scroll_layer_id
|
||||
}
|
||||
|
||||
pub fn establish_root(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
viewport_size: &LayerSize,
|
||||
content_size: &LayerSize) {
|
||||
debug_assert!(self.nodes.is_empty());
|
||||
|
||||
let identity = LayerToScrollTransform::identity();
|
||||
let viewport = LayerRect::new(LayerPoint::zero(), *viewport_size);
|
||||
|
||||
let root_reference_frame_id = ScrollLayerId::root_reference_frame(pipeline_id);
|
||||
self.root_reference_frame_id = root_reference_frame_id;
|
||||
let reference_frame = ClipScrollNode::new(&viewport, viewport.size, &identity, pipeline_id);
|
||||
self.nodes.insert(self.root_reference_frame_id, reference_frame);
|
||||
|
||||
let scroll_node = ClipScrollNode::new(&viewport, *content_size, &identity, pipeline_id);
|
||||
let topmost_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
|
||||
self.topmost_scroll_layer_id = topmost_scroll_layer_id;
|
||||
self.add_node(scroll_node, topmost_scroll_layer_id, root_reference_frame_id);
|
||||
}
|
||||
|
||||
pub fn collect_nodes_bouncing_back(&self)
|
||||
-> HashSet<ScrollLayerId, BuildHasherDefault<FnvHasher>> {
|
||||
let mut nodes_bouncing_back = HashSet::with_hasher(Default::default());
|
||||
|
@ -129,16 +109,16 @@ impl ClipScrollTree {
|
|||
|
||||
pub fn get_scroll_node_state(&self) -> Vec<ScrollLayerState> {
|
||||
let mut result = vec![];
|
||||
for (scroll_layer_id, scroll_node) in self.nodes.iter() {
|
||||
match scroll_layer_id.info {
|
||||
ScrollLayerInfo::Scrollable(_, servo_scroll_root_id) => {
|
||||
for (_, node) in self.nodes.iter() {
|
||||
match node.node_type {
|
||||
NodeType::Clip(ref info) if info.scroll_root_id.is_some() => {
|
||||
result.push(ScrollLayerState {
|
||||
pipeline_id: scroll_node.pipeline_id,
|
||||
scroll_root_id: servo_scroll_root_id,
|
||||
scroll_offset: scroll_node.scrolling.offset,
|
||||
pipeline_id: node.pipeline_id,
|
||||
scroll_root_id: info.scroll_root_id.unwrap(),
|
||||
scroll_offset: node.scrolling.offset,
|
||||
})
|
||||
}
|
||||
ScrollLayerInfo::ReferenceFrame(..) => {}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
result
|
||||
|
@ -177,10 +157,10 @@ impl ClipScrollTree {
|
|||
continue;
|
||||
}
|
||||
|
||||
match layer_id.info {
|
||||
ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
|
||||
ScrollLayerInfo::ReferenceFrame(..) => continue,
|
||||
ScrollLayerInfo::Scrollable(..) => {}
|
||||
match node.node_type {
|
||||
NodeType::Clip(ref info) if info.scroll_root_id != Some(scroll_root_id) => continue,
|
||||
NodeType::ReferenceFrame(..) => continue,
|
||||
NodeType::Clip(_) => {},
|
||||
}
|
||||
|
||||
found_node = true;
|
||||
|
@ -258,16 +238,26 @@ impl ClipScrollTree {
|
|||
},
|
||||
};
|
||||
|
||||
let scroll_node_info = if switch_node {
|
||||
topmost_scroll_layer_id.info
|
||||
let scroll_layer_id = if switch_node {
|
||||
topmost_scroll_layer_id
|
||||
} else {
|
||||
scroll_layer_id.info
|
||||
scroll_layer_id
|
||||
};
|
||||
|
||||
let scroll_root_id = match scroll_node_info {
|
||||
ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
|
||||
_ => unreachable!("Tried to scroll a reference frame."),
|
||||
// TODO(mrobinson): Once we remove the concept of shared scroll root ids we can remove
|
||||
// this entirely and just scroll the node based on the ScrollLayerId.
|
||||
let scroll_root_id = {
|
||||
let node = self.nodes.get_mut(&scroll_layer_id).unwrap();
|
||||
let scroll_root_id = match node.node_type {
|
||||
NodeType::Clip(ref info) => info.scroll_root_id,
|
||||
NodeType::ReferenceFrame(..) => unreachable!("Tried to scroll a reference frame."),
|
||||
};
|
||||
|
||||
if scroll_root_id.is_none() {
|
||||
return node.scroll(scroll_location, phase);
|
||||
}
|
||||
|
||||
scroll_root_id
|
||||
};
|
||||
|
||||
let mut scrolled_a_node = false;
|
||||
|
@ -276,10 +266,9 @@ impl ClipScrollTree {
|
|||
continue;
|
||||
}
|
||||
|
||||
match layer_id.info {
|
||||
ScrollLayerInfo::Scrollable(_, id) if id != scroll_root_id => continue,
|
||||
ScrollLayerInfo::ReferenceFrame(..) => continue,
|
||||
_ => {}
|
||||
match node.node_type {
|
||||
NodeType::Clip(ref info) if info.scroll_root_id == scroll_root_id => { }
|
||||
_ => continue,
|
||||
}
|
||||
|
||||
let scrolled_this_node = node.scroll(scroll_location, phase);
|
||||
|
@ -288,31 +277,49 @@ impl ClipScrollTree {
|
|||
scrolled_a_node
|
||||
}
|
||||
|
||||
pub fn update_all_node_transforms(&mut self) {
|
||||
pub fn update_all_node_transforms(&mut self, pan: LayerPoint) {
|
||||
if self.nodes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let root_reference_frame_id = self.root_reference_frame_id();
|
||||
let root_viewport = self.nodes[&root_reference_frame_id].local_viewport_rect;
|
||||
let root_viewport = self.nodes[&root_reference_frame_id].local_clip_rect;
|
||||
self.update_node_transform(root_reference_frame_id,
|
||||
&ScrollToWorldTransform::identity(),
|
||||
&as_scroll_parent_rect(&root_viewport));
|
||||
&LayerToWorldTransform::create_translation(pan.x, pan.y, 0.0),
|
||||
&as_scroll_parent_rect(&root_viewport),
|
||||
LayerPoint::zero());
|
||||
}
|
||||
|
||||
fn update_node_transform(&mut self,
|
||||
layer_id: ScrollLayerId,
|
||||
parent_world_transform: &ScrollToWorldTransform,
|
||||
parent_viewport_rect: &ScrollLayerRect) {
|
||||
parent_reference_frame_transform: &LayerToWorldTransform,
|
||||
parent_viewport_rect: &ScrollLayerRect,
|
||||
parent_accumulated_scroll_offset: LayerPoint) {
|
||||
// TODO(gw): This is an ugly borrow check workaround to clone these.
|
||||
// Restructure this to avoid the clones!
|
||||
let (node_transform_for_children, viewport_rect, node_children) = {
|
||||
let (reference_frame_transform, viewport_rect, accumulated_scroll_offset, node_children) = {
|
||||
match self.nodes.get_mut(&layer_id) {
|
||||
Some(node) => {
|
||||
node.update_transform(parent_world_transform, parent_viewport_rect);
|
||||
node.update_transform(parent_reference_frame_transform,
|
||||
parent_viewport_rect,
|
||||
parent_accumulated_scroll_offset);
|
||||
|
||||
(node.world_content_transform.with_source::<ScrollLayerPixel>(),
|
||||
// The transformation we are passing is the transformation of the parent
|
||||
// reference frame and the offset is the accumulated offset of all the nodes
|
||||
// between us and the parent reference frame. If we are a reference frame,
|
||||
// we need to reset both these values.
|
||||
let (transform, offset) = match node.node_type {
|
||||
NodeType::ReferenceFrame(..) =>
|
||||
(node.world_viewport_transform, LayerPoint::zero()),
|
||||
NodeType::Clip(_) => {
|
||||
(*parent_reference_frame_transform,
|
||||
parent_accumulated_scroll_offset + node.scrolling.offset)
|
||||
}
|
||||
};
|
||||
|
||||
(transform,
|
||||
as_scroll_parent_rect(&node.combined_local_viewport_rect),
|
||||
offset,
|
||||
node.children.clone())
|
||||
}
|
||||
None => return,
|
||||
|
@ -321,8 +328,9 @@ impl ClipScrollTree {
|
|||
|
||||
for child_layer_id in node_children {
|
||||
self.update_node_transform(child_layer_id,
|
||||
&node_transform_for_children,
|
||||
&viewport_rect);
|
||||
&reference_frame_transform,
|
||||
&viewport_rect,
|
||||
accumulated_scroll_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,8 +351,9 @@ impl ClipScrollTree {
|
|||
|
||||
node.finalize(&scrolling_state);
|
||||
|
||||
let scroll_root_id = match scroll_layer_id.info {
|
||||
ScrollLayerInfo::Scrollable(_, scroll_root_id) => scroll_root_id,
|
||||
let scroll_root_id = match node.node_type {
|
||||
NodeType::Clip(ref info) if info.scroll_root_id.is_some() =>
|
||||
info.scroll_root_id.unwrap(),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
|
@ -359,27 +368,35 @@ impl ClipScrollTree {
|
|||
}
|
||||
|
||||
pub fn add_reference_frame(&mut self,
|
||||
rect: LayerRect,
|
||||
transform: LayerToScrollTransform,
|
||||
rect: &LayerRect,
|
||||
transform: &LayerToScrollTransform,
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: ScrollLayerId) -> ScrollLayerId {
|
||||
parent_id: Option<ScrollLayerId>)
|
||||
-> ScrollLayerId {
|
||||
let reference_frame_id = ScrollLayerId {
|
||||
pipeline_id: pipeline_id,
|
||||
info: ScrollLayerInfo::ReferenceFrame(self.current_reference_frame_id),
|
||||
};
|
||||
self.current_reference_frame_id += 1;
|
||||
|
||||
let node = ClipScrollNode::new(&rect, rect.size, &transform, pipeline_id);
|
||||
self.add_node(node, reference_frame_id, parent_id);
|
||||
let node = ClipScrollNode::new_reference_frame(parent_id,
|
||||
&rect,
|
||||
rect.size,
|
||||
&transform,
|
||||
pipeline_id);
|
||||
self.add_node(node, reference_frame_id);
|
||||
reference_frame_id
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, node: ClipScrollNode, id: ScrollLayerId, parent_id: ScrollLayerId) {
|
||||
pub fn add_node(&mut self, node: ClipScrollNode, id: ScrollLayerId) {
|
||||
// When the parent node is None this means we are adding the root.
|
||||
match node.parent {
|
||||
Some(parent_id) => self.nodes.get_mut(&parent_id).unwrap().add_child(id),
|
||||
None => self.root_reference_frame_id = id,
|
||||
}
|
||||
|
||||
debug_assert!(!self.nodes.contains_key(&id));
|
||||
self.nodes.insert(id, node);
|
||||
|
||||
debug_assert!(parent_id != id);
|
||||
self.nodes.get_mut(&parent_id).unwrap().add_child(id);
|
||||
}
|
||||
|
||||
pub fn discard_frame_state_for_pipeline(&mut self, pipeline_id: PipelineId) {
|
||||
|
|
|
@ -22,6 +22,9 @@ use std::path::PathBuf;
|
|||
use webrender_traits::{ColorF, ImageFormat};
|
||||
use webrender_traits::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintSize};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct FrameId(usize);
|
||||
|
||||
#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
|
||||
const GL_FORMAT_A: gl::GLuint = gl::RED;
|
||||
|
||||
|
@ -497,6 +500,7 @@ pub struct GpuFrameProfile<T> {
|
|||
samples: Vec<GpuSample<T>>,
|
||||
next_query: usize,
|
||||
pending_query: gl::GLuint,
|
||||
frame_id: FrameId,
|
||||
}
|
||||
|
||||
impl<T> GpuFrameProfile<T> {
|
||||
|
@ -509,6 +513,7 @@ impl<T> GpuFrameProfile<T> {
|
|||
samples: Vec::new(),
|
||||
next_query: 0,
|
||||
pending_query: 0,
|
||||
frame_id: FrameId(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,10 +524,12 @@ impl<T> GpuFrameProfile<T> {
|
|||
samples: Vec::new(),
|
||||
next_query: 0,
|
||||
pending_query: 0,
|
||||
frame_id: FrameId(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn begin_frame(&mut self) {
|
||||
fn begin_frame(&mut self, frame_id: FrameId) {
|
||||
self.frame_id = frame_id;
|
||||
self.next_query = 0;
|
||||
self.pending_query = 0;
|
||||
self.samples.clear();
|
||||
|
@ -572,7 +579,7 @@ impl<T> GpuFrameProfile<T> {
|
|||
}
|
||||
|
||||
fn is_valid(&self) -> bool {
|
||||
self.next_query <= MAX_EVENTS_PER_FRAME
|
||||
self.next_query > 0 && self.next_query <= MAX_EVENTS_PER_FRAME
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
|
@ -619,18 +626,18 @@ impl<T> GpuProfiler<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn build_samples(&mut self) -> Option<Vec<GpuSample<T>>> {
|
||||
pub fn build_samples(&mut self) -> Option<(FrameId, Vec<GpuSample<T>>)> {
|
||||
let frame = &mut self.frames[self.next_frame];
|
||||
if frame.is_valid() {
|
||||
Some(frame.build_samples())
|
||||
Some((frame.frame_id, frame.build_samples()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn begin_frame(&mut self) {
|
||||
pub fn begin_frame(&mut self, frame_id: FrameId) {
|
||||
let frame = &mut self.frames[self.next_frame];
|
||||
frame.begin_frame();
|
||||
frame.begin_frame(frame_id);
|
||||
}
|
||||
|
||||
pub fn end_frame(&mut self) {
|
||||
|
@ -821,6 +828,10 @@ pub struct Device {
|
|||
next_vao_id: gl::GLuint,
|
||||
|
||||
max_texture_size: u32,
|
||||
|
||||
// Frame counter. This is used to map between CPU
|
||||
// frames and GPU frames.
|
||||
frame_id: FrameId,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
|
@ -860,7 +871,8 @@ impl Device {
|
|||
next_vao_id: 1,
|
||||
//file_watcher: file_watcher,
|
||||
|
||||
max_texture_size: gl::get_integer_v(gl::MAX_TEXTURE_SIZE) as u32
|
||||
max_texture_size: gl::get_integer_v(gl::MAX_TEXTURE_SIZE) as u32,
|
||||
frame_id: FrameId(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,7 +915,7 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn begin_frame(&mut self, device_pixel_ratio: f32) {
|
||||
pub fn begin_frame(&mut self, device_pixel_ratio: f32) -> FrameId {
|
||||
debug_assert!(!self.inside_frame);
|
||||
self.inside_frame = true;
|
||||
self.device_pixel_ratio = device_pixel_ratio;
|
||||
|
@ -938,6 +950,8 @@ impl Device {
|
|||
|
||||
// Default is sampler 0, always
|
||||
gl::active_texture(gl::TEXTURE0);
|
||||
|
||||
self.frame_id
|
||||
}
|
||||
|
||||
pub fn bind_texture(&mut self,
|
||||
|
@ -1826,6 +1840,8 @@ impl Device {
|
|||
}
|
||||
|
||||
gl::active_texture(gl::TEXTURE0);
|
||||
|
||||
self.frame_id.0 += 1;
|
||||
}
|
||||
|
||||
pub fn assign_ubo_binding(&self, program_id: ProgramId, name: &str, value: u32) -> u32 {
|
||||
|
@ -1886,6 +1902,30 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clear_target_rect(&self,
|
||||
color: Option<[f32; 4]>,
|
||||
depth: Option<f32>,
|
||||
rect: DeviceIntRect) {
|
||||
let mut clear_bits = 0;
|
||||
|
||||
if let Some(color) = color {
|
||||
gl::clear_color(color[0], color[1], color[2], color[3]);
|
||||
clear_bits |= gl::COLOR_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if let Some(depth) = depth {
|
||||
gl::clear_depth(depth as f64);
|
||||
clear_bits |= gl::DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if clear_bits != 0 {
|
||||
gl::enable(gl::SCISSOR_TEST);
|
||||
gl::scissor(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
||||
gl::clear(clear_bits);
|
||||
gl::disable(gl::SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_depth(&self) {
|
||||
gl::enable(gl::DEPTH_TEST);
|
||||
}
|
||||
|
@ -1923,7 +1963,7 @@ impl Device {
|
|||
}
|
||||
|
||||
pub fn set_blend_mode_premultiplied_alpha(&self) {
|
||||
gl::blend_func(gl::SRC_ALPHA, gl::ZERO);
|
||||
gl::blend_func(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
|
||||
gl::blend_equation(gl::FUNC_ADD);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::rect::rect;
|
||||
use fnv::FnvHasher;
|
||||
use internal_types::{ANGLE_FLOAT_TO_FIXED, AxisDirection};
|
||||
use internal_types::{LowLevelFilterOp};
|
||||
use internal_types::{RendererFrame};
|
||||
use frame_builder::{FrameBuilder, FrameBuilderConfig};
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
|
||||
use profiler::TextureCacheProfileCounters;
|
||||
use resource_cache::ResourceCache;
|
||||
|
@ -16,11 +16,12 @@ use scene::{Scene, SceneProperties};
|
|||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use tiling::{AuxiliaryListsMap, CompositeOps, PrimitiveFlags};
|
||||
use webrender_traits::{AuxiliaryLists, ClipRegion, ColorF, DisplayItem, Epoch, FilterOp};
|
||||
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform, TileOffset};
|
||||
use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerState};
|
||||
use webrender_traits::{ScrollLocation, ScrollPolicy, ServoScrollRootId, SpecificDisplayItem};
|
||||
use webrender_traits::{StackingContext, WorldPoint, ImageDisplayItem, DeviceUintSize};
|
||||
use webrender_traits::{AuxiliaryLists, ClipDisplayItem, ClipRegion, ColorF, DeviceUintRect};
|
||||
use webrender_traits::{DeviceUintSize, DisplayItem, Epoch, FilterOp, ImageDisplayItem, LayerPoint};
|
||||
use webrender_traits::{LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform};
|
||||
use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId};
|
||||
use webrender_traits::{ScrollLayerState, ScrollLocation, ScrollPolicy, ServoScrollRootId};
|
||||
use webrender_traits::{SpecificDisplayItem, StackingContext, TileOffset, WorldPoint};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
||||
pub struct FrameId(pub u32);
|
||||
|
@ -31,6 +32,28 @@ struct FlattenContext<'a> {
|
|||
scene: &'a Scene,
|
||||
builder: &'a mut FrameBuilder,
|
||||
resource_cache: &'a mut ResourceCache,
|
||||
replacements: Vec<(ScrollLayerId, ScrollLayerId)>,
|
||||
}
|
||||
|
||||
impl<'a> FlattenContext<'a> {
|
||||
fn new(scene: &'a Scene,
|
||||
builder: &'a mut FrameBuilder,
|
||||
resource_cache: &'a mut ResourceCache)
|
||||
-> FlattenContext<'a> {
|
||||
FlattenContext {
|
||||
scene: scene,
|
||||
builder: builder,
|
||||
resource_cache: resource_cache,
|
||||
replacements: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn scroll_layer_id_with_replacement(&self, id: ScrollLayerId) -> ScrollLayerId {
|
||||
match self.replacements.last() {
|
||||
Some(&(to_replace, replacement)) if to_replace == id => replacement,
|
||||
_ => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: doc
|
||||
|
@ -141,10 +164,15 @@ impl<'a> DisplayListTraversal<'a> {
|
|||
}
|
||||
|
||||
pub fn skip_current_stacking_context(&mut self) {
|
||||
let mut depth = 0;
|
||||
for item in self {
|
||||
if item.item == SpecificDisplayItem::PopStackingContext {
|
||||
return;
|
||||
match item.item {
|
||||
SpecificDisplayItem::PushStackingContext(..) => depth += 1,
|
||||
SpecificDisplayItem::PopStackingContext if depth == 0 => return,
|
||||
SpecificDisplayItem::PopStackingContext => depth -= 1,
|
||||
_ => {}
|
||||
}
|
||||
debug_assert!(depth >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +256,12 @@ impl Frame {
|
|||
self.clip_scroll_tree.discard_frame_state_for_pipeline(pipeline_id);
|
||||
}
|
||||
|
||||
pub fn create(&mut self, scene: &Scene, resource_cache: &mut ResourceCache) {
|
||||
pub fn create(&mut self,
|
||||
scene: &Scene,
|
||||
resource_cache: &mut ResourceCache,
|
||||
window_size: DeviceUintSize,
|
||||
inner_rect: DeviceUintRect,
|
||||
device_pixel_ratio: f32) {
|
||||
let root_pipeline_id = match scene.root_pipeline_id {
|
||||
Some(root_pipeline_id) => root_pipeline_id,
|
||||
None => return,
|
||||
|
@ -245,6 +278,11 @@ impl Frame {
|
|||
None => return,
|
||||
};
|
||||
|
||||
if window_size.width == 0 || window_size.height == 0 {
|
||||
println!("ERROR: Invalid window dimensions! Please call api.set_window_size()");
|
||||
return;
|
||||
}
|
||||
|
||||
let old_scrolling_states = self.reset();
|
||||
self.pipeline_auxiliary_lists = scene.pipeline_auxiliary_lists.clone();
|
||||
|
||||
|
@ -258,10 +296,6 @@ impl Frame {
|
|||
}
|
||||
};
|
||||
|
||||
self.clip_scroll_tree.establish_root(root_pipeline_id,
|
||||
&root_pipeline.viewport_size,
|
||||
&root_clip.main.size);
|
||||
|
||||
let background_color = root_pipeline.background_color.and_then(|color| {
|
||||
if color.a > 0.0 {
|
||||
Some(color)
|
||||
|
@ -270,97 +304,63 @@ impl Frame {
|
|||
}
|
||||
});
|
||||
|
||||
let mut frame_builder = FrameBuilder::new(root_pipeline.viewport_size,
|
||||
let mut frame_builder = FrameBuilder::new(window_size,
|
||||
background_color,
|
||||
self.frame_builder_config);
|
||||
|
||||
{
|
||||
let mut context = FlattenContext {
|
||||
scene: scene,
|
||||
builder: &mut frame_builder,
|
||||
resource_cache: resource_cache
|
||||
};
|
||||
let mut context = FlattenContext::new(scene, &mut frame_builder, resource_cache);
|
||||
|
||||
let scroll_layer_id = context.builder.push_root(root_pipeline_id,
|
||||
&root_pipeline.viewport_size,
|
||||
&root_clip.main.size,
|
||||
&mut self.clip_scroll_tree);
|
||||
|
||||
context.builder.setup_viewport_offset(window_size,
|
||||
inner_rect,
|
||||
device_pixel_ratio,
|
||||
&mut self.clip_scroll_tree);
|
||||
|
||||
let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
|
||||
let reference_frame_id = self.clip_scroll_tree.root_reference_frame_id();
|
||||
let topmost_scroll_layer_id = self.clip_scroll_tree.topmost_scroll_layer_id();
|
||||
debug_assert!(reference_frame_id != topmost_scroll_layer_id);
|
||||
|
||||
let viewport_rect = LayerRect::new(LayerPoint::zero(), root_pipeline.viewport_size);
|
||||
let clip = ClipRegion::simple(&viewport_rect);
|
||||
context.builder.push_clip_scroll_node(reference_frame_id,
|
||||
&clip,
|
||||
&LayerPoint::zero(),
|
||||
&root_pipeline.viewport_size);
|
||||
context.builder.push_clip_scroll_node(topmost_scroll_layer_id,
|
||||
&clip,
|
||||
&LayerPoint::zero(),
|
||||
&root_clip.main.size);
|
||||
|
||||
self.flatten_stacking_context(&mut traversal,
|
||||
root_pipeline_id,
|
||||
&mut context,
|
||||
reference_frame_id,
|
||||
topmost_scroll_layer_id,
|
||||
LayerToScrollTransform::identity(),
|
||||
scroll_layer_id,
|
||||
LayerPoint::zero(),
|
||||
0,
|
||||
&root_stacking_context,
|
||||
root_clip);
|
||||
|
||||
context.builder.pop_clip_scroll_node();
|
||||
context.builder.pop_clip_scroll_node();
|
||||
}
|
||||
|
||||
self.frame_builder = Some(frame_builder);
|
||||
self.clip_scroll_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
|
||||
}
|
||||
|
||||
fn flatten_scroll_layer<'a>(&mut self,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
context: &mut FlattenContext,
|
||||
current_reference_frame_id: ScrollLayerId,
|
||||
parent_scroll_layer_id: ScrollLayerId,
|
||||
layer_relative_transform: LayerToScrollTransform,
|
||||
level: i32,
|
||||
clip: &ClipRegion,
|
||||
content_size: &LayerSize,
|
||||
new_scroll_layer_id: ScrollLayerId) {
|
||||
// Avoid doing unnecessary work for empty stacking contexts.
|
||||
if traversal.current_stacking_context_empty() {
|
||||
traversal.skip_current_stacking_context();
|
||||
return;
|
||||
}
|
||||
fn flatten_clip<'a>(&mut self,
|
||||
context: &mut FlattenContext,
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: ScrollLayerId,
|
||||
item: &ClipDisplayItem,
|
||||
reference_frame_relative_offset: LayerPoint,
|
||||
clip: &ClipRegion) {
|
||||
let clip_rect = clip.main.translate(&reference_frame_relative_offset);
|
||||
context.builder.add_clip_scroll_node(item.id,
|
||||
parent_id,
|
||||
pipeline_id,
|
||||
&clip_rect,
|
||||
&item.content_size,
|
||||
item.scroll_root_id,
|
||||
clip,
|
||||
&mut self.clip_scroll_tree);
|
||||
|
||||
let clip_rect = clip.main;
|
||||
let node = ClipScrollNode::new(&clip_rect,
|
||||
*content_size,
|
||||
&layer_relative_transform,
|
||||
pipeline_id);
|
||||
self.clip_scroll_tree.add_node(node, new_scroll_layer_id, parent_scroll_layer_id);
|
||||
context.builder.push_clip_scroll_node(new_scroll_layer_id,
|
||||
clip,
|
||||
&clip_rect.origin,
|
||||
&content_size);
|
||||
|
||||
self.flatten_items(traversal,
|
||||
pipeline_id,
|
||||
context,
|
||||
current_reference_frame_id,
|
||||
new_scroll_layer_id,
|
||||
LayerToScrollTransform::identity(),
|
||||
level);
|
||||
|
||||
context.builder.pop_clip_scroll_node();
|
||||
}
|
||||
|
||||
fn flatten_stacking_context<'a>(&mut self,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
context: &mut FlattenContext,
|
||||
current_reference_frame_id: ScrollLayerId,
|
||||
current_scroll_layer_id: ScrollLayerId,
|
||||
layer_relative_transform: LayerToScrollTransform,
|
||||
context_scroll_layer_id: ScrollLayerId,
|
||||
mut reference_frame_relative_offset: LayerPoint,
|
||||
level: i32,
|
||||
stacking_context: &StackingContext,
|
||||
clip_region: &ClipRegion) {
|
||||
|
@ -384,92 +384,102 @@ impl Frame {
|
|||
return;
|
||||
}
|
||||
|
||||
let stacking_context_transform = context.scene
|
||||
.properties
|
||||
.resolve_layout_transform(&stacking_context.transform);
|
||||
let mut scroll_layer_id =
|
||||
context.scroll_layer_id_with_replacement(context_scroll_layer_id);
|
||||
|
||||
let mut transform =
|
||||
layer_relative_transform.pre_translated(stacking_context.bounds.origin.x,
|
||||
stacking_context.bounds.origin.y,
|
||||
0.0)
|
||||
.pre_mul(&stacking_context_transform)
|
||||
.pre_mul(&stacking_context.perspective);
|
||||
|
||||
let mut reference_frame_id = current_reference_frame_id;
|
||||
let mut scroll_layer_id = match stacking_context.scroll_policy {
|
||||
ScrollPolicy::Fixed => current_reference_frame_id,
|
||||
ScrollPolicy::Scrollable => current_scroll_layer_id,
|
||||
};
|
||||
if stacking_context.scroll_policy == ScrollPolicy::Fixed {
|
||||
context.replacements.push((context_scroll_layer_id,
|
||||
context.builder.current_reference_frame_id()));
|
||||
}
|
||||
|
||||
// If we have a transformation, we establish a new reference frame. This means
|
||||
// that fixed position stacking contexts are positioned relative to us.
|
||||
if stacking_context_transform != LayoutTransform::identity() ||
|
||||
stacking_context.perspective != LayoutTransform::identity() {
|
||||
scroll_layer_id = self.clip_scroll_tree.add_reference_frame(clip_region.main,
|
||||
transform,
|
||||
pipeline_id,
|
||||
scroll_layer_id);
|
||||
reference_frame_id = scroll_layer_id;
|
||||
transform = LayerToScrollTransform::identity();
|
||||
let is_reference_frame = stacking_context.transform.is_some() ||
|
||||
stacking_context.perspective.is_some();
|
||||
if is_reference_frame {
|
||||
let transform = stacking_context.transform.as_ref();
|
||||
let transform = context.scene.properties.resolve_layout_transform(transform);
|
||||
let perspective =
|
||||
stacking_context.perspective.unwrap_or_else(LayoutTransform::identity);
|
||||
let transform =
|
||||
LayerToScrollTransform::create_translation(reference_frame_relative_offset.x,
|
||||
reference_frame_relative_offset.y,
|
||||
0.0)
|
||||
.pre_translated(stacking_context.bounds.origin.x,
|
||||
stacking_context.bounds.origin.y,
|
||||
0.0)
|
||||
.pre_mul(&transform)
|
||||
.pre_mul(&perspective);
|
||||
|
||||
scroll_layer_id = context.builder.push_reference_frame(Some(scroll_layer_id),
|
||||
pipeline_id,
|
||||
&clip_region.main,
|
||||
&transform,
|
||||
&mut self.clip_scroll_tree);
|
||||
context.replacements.push((context_scroll_layer_id, scroll_layer_id));
|
||||
reference_frame_relative_offset = LayerPoint::zero();
|
||||
} else {
|
||||
reference_frame_relative_offset = LayerPoint::new(
|
||||
reference_frame_relative_offset.x + stacking_context.bounds.origin.x,
|
||||
reference_frame_relative_offset.y + stacking_context.bounds.origin.y);
|
||||
}
|
||||
|
||||
// TODO(gw): Int with overflow etc
|
||||
context.builder.push_stacking_context(reference_frame_relative_offset,
|
||||
clip_region.main,
|
||||
pipeline_id,
|
||||
level == 0,
|
||||
composition_operations);
|
||||
|
||||
if level == 0 {
|
||||
if let Some(pipeline) = context.scene.pipeline_map.get(&pipeline_id) {
|
||||
if let Some(bg_color) = pipeline.background_color {
|
||||
|
||||
// Adding a dummy layer for this rectangle in order to disable clipping.
|
||||
let no_clip = ClipRegion::simple(&clip_region.main);
|
||||
context.builder.push_stacking_context(clip_region.main,
|
||||
transform,
|
||||
pipeline_id,
|
||||
scroll_layer_id,
|
||||
CompositeOps::empty());
|
||||
|
||||
//Note: we don't use the original clip region here,
|
||||
// Note: we don't use the original clip region here,
|
||||
// it's already processed by the node we just pushed.
|
||||
context.builder.add_solid_rectangle(&clip_region.main,
|
||||
&no_clip,
|
||||
let background_rect = LayerRect::new(LayerPoint::zero(), clip_region.main.size);
|
||||
context.builder.add_solid_rectangle(scroll_layer_id,
|
||||
&clip_region.main,
|
||||
&ClipRegion::simple(&background_rect),
|
||||
&bg_color,
|
||||
PrimitiveFlags::None);
|
||||
|
||||
context.builder.pop_stacking_context();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gw): Int with overflow etc
|
||||
context.builder.push_stacking_context(clip_region.main,
|
||||
transform,
|
||||
pipeline_id,
|
||||
scroll_layer_id,
|
||||
composition_operations);
|
||||
|
||||
self.flatten_items(traversal,
|
||||
pipeline_id,
|
||||
context,
|
||||
reference_frame_id,
|
||||
scroll_layer_id,
|
||||
transform,
|
||||
reference_frame_relative_offset,
|
||||
level);
|
||||
|
||||
if level == 0 && self.frame_builder_config.enable_scrollbars {
|
||||
let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
|
||||
context.builder.add_solid_rectangle(
|
||||
scroll_layer_id,
|
||||
&scrollbar_rect,
|
||||
&ClipRegion::simple(&scrollbar_rect),
|
||||
&DEFAULT_SCROLLBAR_COLOR,
|
||||
PrimitiveFlags::Scrollbar(self.clip_scroll_tree.topmost_scroll_layer_id(), 4.0));
|
||||
}
|
||||
|
||||
if stacking_context.scroll_policy == ScrollPolicy::Fixed {
|
||||
context.replacements.pop();
|
||||
}
|
||||
|
||||
if is_reference_frame {
|
||||
context.replacements.pop();
|
||||
context.builder.pop_reference_frame();
|
||||
}
|
||||
|
||||
context.builder.pop_stacking_context();
|
||||
}
|
||||
|
||||
fn flatten_iframe<'a>(&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: ScrollLayerId,
|
||||
bounds: &LayerRect,
|
||||
context: &mut FlattenContext,
|
||||
current_scroll_layer_id: ScrollLayerId,
|
||||
layer_relative_transform: LayerToScrollTransform) {
|
||||
reference_frame_relative_offset: LayerPoint) {
|
||||
|
||||
let pipeline = match context.scene.pipeline_map.get(&pipeline_id) {
|
||||
Some(pipeline) => pipeline,
|
||||
|
@ -493,61 +503,56 @@ impl Frame {
|
|||
self.pipeline_epoch_map.insert(pipeline_id, pipeline.epoch);
|
||||
|
||||
let iframe_rect = LayerRect::new(LayerPoint::zero(), bounds.size);
|
||||
let transform = layer_relative_transform.pre_translated(bounds.origin.x,
|
||||
bounds.origin.y,
|
||||
0.0);
|
||||
let iframe_reference_frame_id =
|
||||
self.clip_scroll_tree.add_reference_frame(iframe_rect,
|
||||
transform,
|
||||
pipeline_id,
|
||||
current_scroll_layer_id);
|
||||
let iframe_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
|
||||
let node = ClipScrollNode::new(&LayerRect::new(LayerPoint::zero(), iframe_rect.size),
|
||||
iframe_clip.main.size,
|
||||
&LayerToScrollTransform::identity(),
|
||||
pipeline_id);
|
||||
self.clip_scroll_tree.add_node(node.clone(),
|
||||
iframe_scroll_layer_id,
|
||||
iframe_reference_frame_id);
|
||||
let transform = LayerToScrollTransform::create_translation(
|
||||
reference_frame_relative_offset.x + bounds.origin.x,
|
||||
reference_frame_relative_offset.y + bounds.origin.y,
|
||||
0.0);
|
||||
|
||||
context.builder.push_clip_scroll_node(iframe_reference_frame_id,
|
||||
iframe_clip,
|
||||
&LayerPoint::zero(),
|
||||
&iframe_rect.size);
|
||||
context.builder.push_clip_scroll_node(iframe_scroll_layer_id,
|
||||
iframe_clip,
|
||||
&LayerPoint::zero(),
|
||||
&iframe_clip.main.size);
|
||||
let iframe_reference_frame_id =
|
||||
context.builder.push_reference_frame(Some(parent_id),
|
||||
pipeline_id,
|
||||
&iframe_rect,
|
||||
&transform,
|
||||
&mut self.clip_scroll_tree);
|
||||
|
||||
let iframe_scroll_layer_id = ScrollLayerId::root_scroll_layer(pipeline_id);
|
||||
context.builder.add_clip_scroll_node(
|
||||
iframe_scroll_layer_id,
|
||||
iframe_reference_frame_id,
|
||||
pipeline_id,
|
||||
&LayerRect::new(LayerPoint::zero(), iframe_rect.size),
|
||||
&iframe_clip.main.size,
|
||||
Some(ServoScrollRootId(0)),
|
||||
iframe_clip,
|
||||
&mut self.clip_scroll_tree);
|
||||
|
||||
let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
|
||||
|
||||
self.flatten_stacking_context(&mut traversal,
|
||||
pipeline_id,
|
||||
context,
|
||||
iframe_reference_frame_id,
|
||||
iframe_scroll_layer_id,
|
||||
LayerToScrollTransform::identity(),
|
||||
LayerPoint::zero(),
|
||||
0,
|
||||
&iframe_stacking_context,
|
||||
iframe_clip);
|
||||
|
||||
context.builder.pop_clip_scroll_node();
|
||||
context.builder.pop_clip_scroll_node();
|
||||
context.builder.pop_reference_frame();
|
||||
}
|
||||
|
||||
fn flatten_items<'a>(&mut self,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
context: &mut FlattenContext,
|
||||
current_reference_frame_id: ScrollLayerId,
|
||||
current_scroll_layer_id: ScrollLayerId,
|
||||
layer_relative_transform: LayerToScrollTransform,
|
||||
reference_frame_relative_offset: LayerPoint,
|
||||
level: i32) {
|
||||
while let Some(item) = traversal.next() {
|
||||
let scroll_layer_id = context.scroll_layer_id_with_replacement(item.scroll_layer_id);
|
||||
match item.item {
|
||||
SpecificDisplayItem::WebGL(ref info) => {
|
||||
context.builder.add_webgl_rectangle(item.rect,
|
||||
&item.clip, info.context_id);
|
||||
context.builder.add_webgl_rectangle(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
info.context_id);
|
||||
}
|
||||
SpecificDisplayItem::Image(ref info) => {
|
||||
let image = context.resource_cache.get_image_properties(info.image_key);
|
||||
|
@ -555,9 +560,16 @@ impl Frame {
|
|||
// The image resource is tiled. We have to generate an image primitive
|
||||
// for each tile.
|
||||
let image_size = DeviceUintSize::new(image.descriptor.width, image.descriptor.height);
|
||||
self.decompose_tiled_image(context, &item, info, image_size, tile_size as u32);
|
||||
self.decompose_image(scroll_layer_id,
|
||||
context,
|
||||
&item.rect,
|
||||
&item.clip,
|
||||
info,
|
||||
image_size,
|
||||
tile_size as u32);
|
||||
} else {
|
||||
context.builder.add_image(item.rect,
|
||||
context.builder.add_image(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
&info.stretch_size,
|
||||
&info.tile_spacing,
|
||||
|
@ -568,7 +580,8 @@ impl Frame {
|
|||
}
|
||||
}
|
||||
SpecificDisplayItem::YuvImage(ref info) => {
|
||||
context.builder.add_yuv_image(item.rect,
|
||||
context.builder.add_yuv_image(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
info.y_image_key,
|
||||
info.u_image_key,
|
||||
|
@ -576,7 +589,8 @@ impl Frame {
|
|||
info.color_space);
|
||||
}
|
||||
SpecificDisplayItem::Text(ref text_info) => {
|
||||
context.builder.add_text(item.rect,
|
||||
context.builder.add_text(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
text_info.font_key,
|
||||
text_info.size,
|
||||
|
@ -586,31 +600,35 @@ impl Frame {
|
|||
text_info.glyph_options);
|
||||
}
|
||||
SpecificDisplayItem::Rectangle(ref info) => {
|
||||
context.builder.add_solid_rectangle(&item.rect,
|
||||
context.builder.add_solid_rectangle(scroll_layer_id,
|
||||
&item.rect,
|
||||
&item.clip,
|
||||
&info.color,
|
||||
PrimitiveFlags::None);
|
||||
}
|
||||
SpecificDisplayItem::Gradient(ref info) => {
|
||||
context.builder.add_gradient(item.rect,
|
||||
context.builder.add_gradient(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
info.start_point,
|
||||
info.end_point,
|
||||
info.stops,
|
||||
info.extend_mode);
|
||||
info.gradient.start_point,
|
||||
info.gradient.end_point,
|
||||
info.gradient.stops,
|
||||
info.gradient.extend_mode);
|
||||
}
|
||||
SpecificDisplayItem::RadialGradient(ref info) => {
|
||||
context.builder.add_radial_gradient(item.rect,
|
||||
context.builder.add_radial_gradient(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
info.start_center,
|
||||
info.start_radius,
|
||||
info.end_center,
|
||||
info.end_radius,
|
||||
info.stops,
|
||||
info.extend_mode);
|
||||
info.gradient.start_center,
|
||||
info.gradient.start_radius,
|
||||
info.gradient.end_center,
|
||||
info.gradient.end_radius,
|
||||
info.gradient.stops,
|
||||
info.gradient.extend_mode);
|
||||
}
|
||||
SpecificDisplayItem::BoxShadow(ref box_shadow_info) => {
|
||||
context.builder.add_box_shadow(&box_shadow_info.box_bounds,
|
||||
context.builder.add_box_shadow(scroll_layer_id,
|
||||
&box_shadow_info.box_bounds,
|
||||
&item.clip,
|
||||
&box_shadow_info.offset,
|
||||
&box_shadow_info.color,
|
||||
|
@ -620,47 +638,117 @@ impl Frame {
|
|||
box_shadow_info.clip_mode);
|
||||
}
|
||||
SpecificDisplayItem::Border(ref info) => {
|
||||
context.builder.add_border(item.rect, &item.clip, info);
|
||||
context.builder.add_border(scroll_layer_id,
|
||||
item.rect,
|
||||
&item.clip,
|
||||
info);
|
||||
}
|
||||
SpecificDisplayItem::PushStackingContext(ref info) => {
|
||||
self.flatten_stacking_context(traversal,
|
||||
pipeline_id,
|
||||
context,
|
||||
current_reference_frame_id,
|
||||
current_scroll_layer_id,
|
||||
layer_relative_transform,
|
||||
item.scroll_layer_id,
|
||||
reference_frame_relative_offset,
|
||||
level + 1,
|
||||
&info.stacking_context,
|
||||
&item.clip);
|
||||
}
|
||||
SpecificDisplayItem::PushScrollLayer(ref info) => {
|
||||
self.flatten_scroll_layer(traversal,
|
||||
pipeline_id,
|
||||
context,
|
||||
current_reference_frame_id,
|
||||
current_scroll_layer_id,
|
||||
layer_relative_transform,
|
||||
level,
|
||||
&item.clip,
|
||||
&info.content_size,
|
||||
info.id);
|
||||
}
|
||||
SpecificDisplayItem::Iframe(ref info) => {
|
||||
self.flatten_iframe(info.pipeline_id,
|
||||
scroll_layer_id,
|
||||
&item.rect,
|
||||
context,
|
||||
current_scroll_layer_id,
|
||||
layer_relative_transform);
|
||||
reference_frame_relative_offset);
|
||||
}
|
||||
SpecificDisplayItem::PopStackingContext |
|
||||
SpecificDisplayItem::PopScrollLayer => return,
|
||||
SpecificDisplayItem::Clip(ref info) => {
|
||||
self.flatten_clip(context,
|
||||
pipeline_id,
|
||||
scroll_layer_id,
|
||||
&info,
|
||||
reference_frame_relative_offset,
|
||||
&item.clip);
|
||||
}
|
||||
SpecificDisplayItem::PopStackingContext => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Decomposes an image display item that is repeated into an image per individual repetition.
|
||||
/// We need to do this when we are unable to perform the repetition in the shader,
|
||||
/// for example if the image is tiled.
|
||||
///
|
||||
/// In all of the "decompose" methods below, we independently handle horizontal and vertical
|
||||
/// decomposition. This lets us generate the minimum amount of primitives by, for example,
|
||||
/// decompositing the repetition horizontally while repeating vertically in the shader (for
|
||||
/// an image where the width is too bug but the height is not).
|
||||
///
|
||||
/// decompose_image and decompose_image_row handle image repetitions while decompose_tiled_image
|
||||
/// takes care of the decomposition required by the internal tiling of the image.
|
||||
fn decompose_image(&mut self,
|
||||
scroll_layer_id: ScrollLayerId,
|
||||
context: &mut FlattenContext,
|
||||
item_rect: &LayerRect,
|
||||
item_clip: &ClipRegion,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
tile_size: u32) {
|
||||
let no_vertical_tiling = image_size.height <= tile_size;
|
||||
let no_vertical_spacing = info.tile_spacing.height == 0.0;
|
||||
if no_vertical_tiling && no_vertical_spacing {
|
||||
self.decompose_image_row(scroll_layer_id, context, item_rect, item_clip, info, image_size, tile_size);
|
||||
return;
|
||||
}
|
||||
|
||||
// Decompose each vertical repetition into rows.
|
||||
let layout_stride = info.stretch_size.height + info.tile_spacing.height;
|
||||
let num_repetitions = (item_rect.size.height / layout_stride).ceil() as u32;
|
||||
for i in 0..num_repetitions {
|
||||
if let Some(row_rect) = rect(
|
||||
item_rect.origin.x,
|
||||
item_rect.origin.y + (i as f32) * layout_stride,
|
||||
item_rect.size.width,
|
||||
info.stretch_size.height
|
||||
).intersection(&item_rect) {
|
||||
self.decompose_image_row(scroll_layer_id, context, &row_rect, item_clip, info, image_size, tile_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decompose_image_row(&mut self,
|
||||
scroll_layer_id: ScrollLayerId,
|
||||
context: &mut FlattenContext,
|
||||
item_rect: &LayerRect,
|
||||
item_clip: &ClipRegion,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
tile_size: u32) {
|
||||
let no_horizontal_tiling = image_size.width <= tile_size;
|
||||
let no_horizontal_spacing = info.tile_spacing.width == 0.0;
|
||||
if no_horizontal_tiling && no_horizontal_spacing {
|
||||
self.decompose_tiled_image(scroll_layer_id, context, item_rect, item_clip, info, image_size, tile_size);
|
||||
return;
|
||||
}
|
||||
|
||||
// Decompose each horizontal repetition.
|
||||
let layout_stride = info.stretch_size.width + info.tile_spacing.width;
|
||||
let num_repetitions = (item_rect.size.width / layout_stride).ceil() as u32;
|
||||
for i in 0..num_repetitions {
|
||||
if let Some(decomposed_rect) = rect(
|
||||
item_rect.origin.x + (i as f32) * layout_stride,
|
||||
item_rect.origin.y,
|
||||
info.stretch_size.width,
|
||||
item_rect.size.height,
|
||||
).intersection(&item_rect) {
|
||||
self.decompose_tiled_image(scroll_layer_id, context, &decomposed_rect, item_clip, info, image_size, tile_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decompose_tiled_image(&mut self,
|
||||
scroll_layer_id: ScrollLayerId,
|
||||
context: &mut FlattenContext,
|
||||
item: &DisplayItem,
|
||||
item_rect: &LayerRect,
|
||||
item_clip: &ClipRegion,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
tile_size: u32) {
|
||||
|
@ -688,11 +776,6 @@ impl Frame {
|
|||
// each generated image primitive corresponds to a tile in the texture cache, with the
|
||||
// assumption that the smaller tiles with leftover sizes are sized to fit their own
|
||||
// irregular size in the texture cache.
|
||||
|
||||
// TODO(nical) supporting tiled repeated images isn't implemented yet.
|
||||
// One way to implement this is to have another level of decomposition on top of this one,
|
||||
// and generate a set of image primitive per repetition just like we have a primitive
|
||||
// per tile here.
|
||||
//
|
||||
// For the case where we don't tile along an axis, we can still perform the repetition in
|
||||
// the shader (for this particular axis), and it is worth special-casing for this to avoid
|
||||
|
@ -700,29 +783,21 @@ impl Frame {
|
|||
// This can happen with very tall and thin images used as a repeating background.
|
||||
// Apparently web authors do that...
|
||||
|
||||
let mut stretch_size = info.stretch_size;
|
||||
|
||||
let mut repeat_x = false;
|
||||
let mut repeat_y = false;
|
||||
|
||||
if stretch_size.width < item.rect.size.width {
|
||||
if image_size.width < tile_size {
|
||||
// we don't actually tile in this dimmension so repeating can be done in the shader.
|
||||
repeat_x = true;
|
||||
} else {
|
||||
println!("Unimplemented! repeating a tiled image (x axis)");
|
||||
stretch_size.width = item.rect.size.width;
|
||||
}
|
||||
if info.stretch_size.width < item_rect.size.width {
|
||||
// If this assert blows up it means we haven't properly decomposed the image in decompose_image_row.
|
||||
debug_assert!(image_size.width <= tile_size);
|
||||
// we don't actually tile in this dimmension so repeating can be done in the shader.
|
||||
repeat_x = true;
|
||||
}
|
||||
|
||||
if stretch_size.height < item.rect.size.height {
|
||||
// we don't actually tile in this dimmension so repeating can be done in the shader.
|
||||
if image_size.height < tile_size {
|
||||
repeat_y = true;
|
||||
} else {
|
||||
println!("Unimplemented! repeating a tiled image (y axis)");
|
||||
stretch_size.height = item.rect.size.height;
|
||||
}
|
||||
if info.stretch_size.height < item_rect.size.height {
|
||||
// If this assert blows up it means we haven't properly decomposed the image in decompose_image.
|
||||
debug_assert!(image_size.height <= tile_size);
|
||||
// we don't actually tile in this dimmension so repeating can be done in the shader.
|
||||
repeat_y = true;
|
||||
}
|
||||
|
||||
let tile_size_f32 = tile_size as f32;
|
||||
|
@ -738,8 +813,8 @@ impl Frame {
|
|||
|
||||
// Strected size of the tile in layout space.
|
||||
let stretched_tile_size = LayerSize::new(
|
||||
img_dw * stretch_size.width,
|
||||
img_dh * stretch_size.height
|
||||
img_dw * info.stretch_size.width,
|
||||
img_dh * info.stretch_size.height
|
||||
);
|
||||
|
||||
// The size in pixels of the tiles on the right and bottom edges, smaller
|
||||
|
@ -749,7 +824,11 @@ impl Frame {
|
|||
|
||||
for ty in 0..num_tiles_y {
|
||||
for tx in 0..num_tiles_x {
|
||||
self.add_tile_primitive(context, item, info,
|
||||
self.add_tile_primitive(scroll_layer_id,
|
||||
context,
|
||||
item_rect,
|
||||
item_clip,
|
||||
info,
|
||||
TileOffset::new(tx, ty),
|
||||
stretched_tile_size,
|
||||
1.0, 1.0,
|
||||
|
@ -757,7 +836,11 @@ impl Frame {
|
|||
}
|
||||
if leftover.width != 0 {
|
||||
// Tiles on the right edge that are smaller than the tile size.
|
||||
self.add_tile_primitive(context, item, info,
|
||||
self.add_tile_primitive(scroll_layer_id,
|
||||
context,
|
||||
item_rect,
|
||||
item_clip,
|
||||
info,
|
||||
TileOffset::new(num_tiles_x, ty),
|
||||
stretched_tile_size,
|
||||
(leftover.width as f32) / tile_size_f32,
|
||||
|
@ -769,29 +852,41 @@ impl Frame {
|
|||
if leftover.height != 0 {
|
||||
for tx in 0..num_tiles_x {
|
||||
// Tiles on the bottom edge that are smaller than the tile size.
|
||||
self.add_tile_primitive(context, item, info,
|
||||
self.add_tile_primitive(scroll_layer_id,
|
||||
context,
|
||||
item_rect,
|
||||
item_clip,
|
||||
info,
|
||||
TileOffset::new(tx, num_tiles_y),
|
||||
stretched_tile_size,
|
||||
1.0,
|
||||
(leftover.height as f32) / tile_size_f32,
|
||||
repeat_x, repeat_y);
|
||||
repeat_x,
|
||||
repeat_y);
|
||||
}
|
||||
|
||||
if leftover.width != 0 {
|
||||
// Finally, the bottom-right tile with a "leftover" size.
|
||||
self.add_tile_primitive(context, item, info,
|
||||
self.add_tile_primitive(scroll_layer_id,
|
||||
context,
|
||||
item_rect,
|
||||
item_clip,
|
||||
info,
|
||||
TileOffset::new(num_tiles_x, num_tiles_y),
|
||||
stretched_tile_size,
|
||||
(leftover.width as f32) / tile_size_f32,
|
||||
(leftover.height as f32) / tile_size_f32,
|
||||
repeat_x, repeat_y);
|
||||
repeat_x,
|
||||
repeat_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_tile_primitive(&mut self,
|
||||
scroll_layer_id: ScrollLayerId,
|
||||
context: &mut FlattenContext,
|
||||
item: &DisplayItem,
|
||||
item_rect: &LayerRect,
|
||||
item_clip: &ClipRegion,
|
||||
info: &ImageDisplayItem,
|
||||
tile_offset: TileOffset,
|
||||
stretched_tile_size: LayerSize,
|
||||
|
@ -814,7 +909,7 @@ impl Frame {
|
|||
);
|
||||
|
||||
let mut prim_rect = LayerRect::new(
|
||||
item.rect.origin + LayerPoint::new(
|
||||
item_rect.origin + LayerPoint::new(
|
||||
tile_offset.x as f32 * stretched_tile_size.width,
|
||||
tile_offset.y as f32 * stretched_tile_size.height,
|
||||
),
|
||||
|
@ -823,18 +918,19 @@ impl Frame {
|
|||
|
||||
if repeat_x {
|
||||
assert_eq!(tile_offset.x, 0);
|
||||
prim_rect.size.width = item.rect.size.width;
|
||||
prim_rect.size.width = item_rect.size.width;
|
||||
}
|
||||
|
||||
if repeat_y {
|
||||
assert_eq!(tile_offset.y, 0);
|
||||
prim_rect.size.height = item.rect.size.height;
|
||||
prim_rect.size.height = item_rect.size.height;
|
||||
}
|
||||
|
||||
// Fix up the primitive's rect if it overflows the original item rect.
|
||||
if let Some(prim_rect) = prim_rect.intersection(&item.rect) {
|
||||
context.builder.add_image(prim_rect,
|
||||
&item.clip,
|
||||
if let Some(prim_rect) = prim_rect.intersection(&item_rect) {
|
||||
context.builder.add_image(scroll_layer_id,
|
||||
prim_rect,
|
||||
&item_clip,
|
||||
&stretched_size,
|
||||
&info.tile_spacing,
|
||||
None,
|
||||
|
@ -848,9 +944,10 @@ impl Frame {
|
|||
resource_cache: &mut ResourceCache,
|
||||
auxiliary_lists_map: &AuxiliaryListsMap,
|
||||
device_pixel_ratio: f32,
|
||||
pan: LayerPoint,
|
||||
texture_cache_profile: &mut TextureCacheProfileCounters)
|
||||
-> RendererFrame {
|
||||
self.clip_scroll_tree.update_all_node_transforms();
|
||||
self.clip_scroll_tree.update_all_node_transforms(pan);
|
||||
let frame = self.build_frame(resource_cache,
|
||||
auxiliary_lists_map,
|
||||
device_pixel_ratio,
|
||||
|
@ -869,7 +966,7 @@ impl Frame {
|
|||
let frame = frame_builder.as_mut().map(|builder|
|
||||
builder.build(resource_cache,
|
||||
self.id,
|
||||
&self.clip_scroll_tree,
|
||||
&mut self.clip_scroll_tree,
|
||||
auxiliary_lists_map,
|
||||
device_pixel_ratio,
|
||||
texture_cache_profile)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -5,11 +5,21 @@
|
|||
use device::TextureFilter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Add;
|
||||
use webrender_traits::ImageFormat;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub struct GpuStoreAddress(pub i32);
|
||||
|
||||
|
||||
impl Add<i32> for GpuStoreAddress {
|
||||
type Output = GpuStoreAddress;
|
||||
|
||||
fn add(self, other: i32) -> GpuStoreAddress {
|
||||
GpuStoreAddress(self.0 + other)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GpuStoreLayout {
|
||||
fn image_format() -> ImageFormat;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use std::sync::Arc;
|
|||
use tiling;
|
||||
use renderer::BlendMode;
|
||||
use webrender_traits::{Epoch, ColorF, PipelineId, DeviceIntSize};
|
||||
use webrender_traits::{ImageFormat, NativeFontHandle, MixBlendMode};
|
||||
use webrender_traits::{ImageFormat, NativeFontHandle};
|
||||
use webrender_traits::{ExternalImageId, ScrollLayerId, WebGLCommand};
|
||||
use webrender_traits::{ImageData};
|
||||
use webrender_traits::{DeviceUintRect};
|
||||
|
@ -492,26 +492,13 @@ pub enum LowLevelFilterOp {
|
|||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum HardwareCompositeOp {
|
||||
Multiply,
|
||||
Max,
|
||||
Min,
|
||||
Alpha,
|
||||
}
|
||||
|
||||
impl HardwareCompositeOp {
|
||||
pub fn from_mix_blend_mode(mix_blend_mode: MixBlendMode) -> Option<HardwareCompositeOp> {
|
||||
match mix_blend_mode {
|
||||
MixBlendMode::Multiply => Some(HardwareCompositeOp::Multiply),
|
||||
MixBlendMode::Lighten => Some(HardwareCompositeOp::Max),
|
||||
MixBlendMode::Darken => Some(HardwareCompositeOp::Min),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_blend_mode(&self) -> BlendMode {
|
||||
match self {
|
||||
&HardwareCompositeOp::Multiply => BlendMode::Multiply,
|
||||
&HardwareCompositeOp::Max => BlendMode::Max,
|
||||
&HardwareCompositeOp::Min => BlendMode::Min,
|
||||
&HardwareCompositeOp::Alpha => BlendMode::Alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,20 @@ impl FontContext {
|
|||
self.cg_fonts.insert((*font_key).clone(), native_font_handle);
|
||||
}
|
||||
|
||||
pub fn delete_font(&mut self, font_key: &FontKey) {
|
||||
if let Some(cg_font) = self.cg_fonts.remove(font_key) {
|
||||
// Unstable Rust has a retain() method on HashMap that will
|
||||
// let us do this in-place. https://github.com/rust-lang/rust/issues/36648
|
||||
let ct_font_keys = self.ct_fonts.keys()
|
||||
.filter(|k| k.0 == *font_key)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
for ct_font_key in ct_font_keys {
|
||||
self.ct_fonts.remove(&ct_font_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ct_font(&mut self,
|
||||
font_key: FontKey,
|
||||
size: Au) -> Option<CTFont> {
|
||||
|
|
|
@ -13,6 +13,7 @@ use freetype::freetype::{FT_Library, FT_Set_Char_Size};
|
|||
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
|
||||
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
|
||||
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
|
||||
use freetype::freetype::{FT_Done_Face};
|
||||
|
||||
use std::{mem, ptr, slice};
|
||||
use std::collections::HashMap;
|
||||
|
@ -88,6 +89,15 @@ impl FontContext {
|
|||
panic!("TODO: Not supported on Linux");
|
||||
}
|
||||
|
||||
pub fn delete_font(&mut self, font_key: &FontKey) {
|
||||
if let Some(face) = self.faces.remove(font_key) {
|
||||
let result = unsafe {
|
||||
FT_Done_Face(face.face)
|
||||
};
|
||||
assert!(result.succeeded());
|
||||
}
|
||||
}
|
||||
|
||||
fn load_glyph(&self,
|
||||
font_key: FontKey,
|
||||
size: Au,
|
||||
|
|
|
@ -143,6 +143,10 @@ impl FontContext {
|
|||
self.fonts.insert((*font_key).clone(), face);
|
||||
}
|
||||
|
||||
pub fn delete_font(&mut self, font_key: &FontKey) {
|
||||
self.fonts.remove(font_key);
|
||||
}
|
||||
|
||||
// Assumes RGB format from dwrite, which is 3 bytes per pixel as dwrite
|
||||
// doesn't output an alpha value via GlyphRunAnalysis::CreateAlphaTexture
|
||||
#[allow(dead_code)]
|
||||
|
@ -230,13 +234,8 @@ impl FontContext {
|
|||
let length = pixels.len() / 3;
|
||||
let mut rgba_pixels: Vec<u8> = vec![0; length * 4];
|
||||
for i in 0..length {
|
||||
// TODO(vlad): we likely need to do something smarter
|
||||
// This is what skia does
|
||||
let alpha = ((pixels[i*3+0] as u32 +
|
||||
pixels[i*3+1] as u32 +
|
||||
pixels[i*3+2] as u32)
|
||||
/ 3) as u8;
|
||||
|
||||
// Only take the G channel, as its closest to D2D
|
||||
let alpha = pixels[i*3 + 1] as u8;
|
||||
rgba_pixels[i*4+0] = alpha;
|
||||
rgba_pixels[i*4+1] = alpha;
|
||||
rgba_pixels[i*4+2] = alpha;
|
||||
|
@ -278,22 +277,24 @@ impl FontContext {
|
|||
|
||||
let mut pixels = analysis.create_alpha_texture(texture_type, bounds);
|
||||
|
||||
let lut_correction = match glyph_options {
|
||||
Some(option) => {
|
||||
if option.force_gdi_rendering {
|
||||
&self.gdi_gamma_lut
|
||||
} else {
|
||||
&self.gamma_lut
|
||||
}
|
||||
},
|
||||
None => &self.gamma_lut
|
||||
};
|
||||
if render_mode != FontRenderMode::Mono {
|
||||
let lut_correction = match glyph_options {
|
||||
Some(option) => {
|
||||
if option.force_gdi_rendering {
|
||||
&self.gdi_gamma_lut
|
||||
} else {
|
||||
&self.gamma_lut
|
||||
}
|
||||
},
|
||||
None => &self.gamma_lut
|
||||
};
|
||||
|
||||
lut_correction.preblend_rgb(&mut pixels, width, height,
|
||||
ColorLut::new(key.color.r,
|
||||
key.color.g,
|
||||
key.color.b,
|
||||
key.color.a));
|
||||
lut_correction.preblend_rgb(&mut pixels, width, height,
|
||||
ColorLut::new(key.color.r,
|
||||
key.color.g,
|
||||
key.color.b,
|
||||
key.color.a));
|
||||
}
|
||||
|
||||
let rgba_pixels = self.convert_to_rgba(&mut pixels, render_mode);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use internal_types::{SourceTexture, PackedTexel};
|
|||
use mask_cache::{ClipSource, MaskCacheInfo};
|
||||
use renderer::{VertexDataStore, GradientDataStore};
|
||||
use render_task::{RenderTask, RenderTaskLocation};
|
||||
use resource_cache::{ImageProperties, ResourceCache};
|
||||
use resource_cache::{CacheItem, ImageProperties, ResourceCache};
|
||||
use std::mem;
|
||||
use std::usize;
|
||||
use util::TransformedRect;
|
||||
|
@ -157,23 +157,17 @@ pub struct ImagePrimitiveGpu {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct YuvImagePrimitiveCpu {
|
||||
pub y_key: ImageKey,
|
||||
pub u_key: ImageKey,
|
||||
pub v_key: ImageKey,
|
||||
pub y_texture_id: SourceTexture,
|
||||
pub u_texture_id: SourceTexture,
|
||||
pub v_texture_id: SourceTexture,
|
||||
pub yuv_key: [ImageKey; 3],
|
||||
pub yuv_texture_id: [SourceTexture; 3],
|
||||
|
||||
// The first address of yuv resource_address. Use "yuv_resource_address + N-th" to get the N-th channel data.
|
||||
// e.g. yuv_resource_address + 0 => y channel resource_address
|
||||
pub yuv_resource_address: GpuStoreAddress,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct YuvImagePrimitiveGpu {
|
||||
pub y_uv0: DevicePoint,
|
||||
pub y_uv1: DevicePoint,
|
||||
pub u_uv0: DevicePoint,
|
||||
pub u_uv1: DevicePoint,
|
||||
pub v_uv0: DevicePoint,
|
||||
pub v_uv1: DevicePoint,
|
||||
pub size: LayerSize,
|
||||
pub color_space: f32,
|
||||
pub padding: f32,
|
||||
|
@ -182,12 +176,6 @@ pub struct YuvImagePrimitiveGpu {
|
|||
impl YuvImagePrimitiveGpu {
|
||||
pub fn new(size: LayerSize, color_space: YuvColorSpace) -> Self {
|
||||
YuvImagePrimitiveGpu {
|
||||
y_uv0: DevicePoint::zero(),
|
||||
y_uv1: DevicePoint::zero(),
|
||||
u_uv0: DevicePoint::zero(),
|
||||
u_uv1: DevicePoint::zero(),
|
||||
v_uv0: DevicePoint::zero(),
|
||||
v_uv1: DevicePoint::zero(),
|
||||
size: size,
|
||||
color_space: color_space as u32 as f32,
|
||||
padding: 0.0,
|
||||
|
@ -676,8 +664,10 @@ impl PrimitiveStore {
|
|||
self.cpu_images.push(image_cpu);
|
||||
metadata
|
||||
}
|
||||
PrimitiveContainer::YuvImage(image_cpu, image_gpu) => {
|
||||
let gpu_address = self.gpu_data64.push(image_gpu);
|
||||
PrimitiveContainer::YuvImage(mut image_cpu, image_gpu) => {
|
||||
image_cpu.yuv_resource_address = self.gpu_resource_rects.alloc(3);
|
||||
|
||||
let gpu_address = self.gpu_data16.push(image_gpu);
|
||||
|
||||
let metadata = PrimitiveMetadata {
|
||||
is_opaque: true,
|
||||
|
@ -855,6 +845,35 @@ impl PrimitiveStore {
|
|||
Self::resolve_clip_cache_internal(&mut self.gpu_data32, clip_info, resource_cache)
|
||||
}
|
||||
|
||||
fn resolve_image(resource_cache: &ResourceCache,
|
||||
deferred_resolves: &mut Vec<DeferredResolve>,
|
||||
image_key: ImageKey,
|
||||
image_uv_address: GpuStoreAddress,
|
||||
image_rendering: ImageRendering,
|
||||
tile_offset: Option<TileOffset>) -> (SourceTexture, Option<CacheItem>) {
|
||||
let image_properties = resource_cache.get_image_properties(image_key);
|
||||
|
||||
// Check if an external image that needs to be resolved
|
||||
// by the render thread.
|
||||
match image_properties.external_id {
|
||||
Some(external_id) => {
|
||||
// This is an external texture - we will add it to
|
||||
// the deferred resolves list to be patched by
|
||||
// the render thread...
|
||||
deferred_resolves.push(DeferredResolve {
|
||||
image_properties: image_properties,
|
||||
resource_address: image_uv_address,
|
||||
});
|
||||
|
||||
(SourceTexture::External(external_id), None)
|
||||
}
|
||||
None => {
|
||||
let cache_item = resource_cache.get_cached_image(image_key, image_rendering, tile_offset);
|
||||
(cache_item.texture_id, Some(cache_item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_primitives(&mut self,
|
||||
resource_cache: &ResourceCache,
|
||||
device_pixel_ratio: f32) -> Vec<DeferredResolve> {
|
||||
|
@ -902,25 +921,12 @@ impl PrimitiveStore {
|
|||
ImagePrimitiveKind::Image(image_key, image_rendering, tile_offset, _) => {
|
||||
// Check if an external image that needs to be resolved
|
||||
// by the render thread.
|
||||
let image_properties = resource_cache.get_image_properties(image_key);
|
||||
|
||||
match image_properties.external_id {
|
||||
Some(external_id) => {
|
||||
// This is an external texture - we will add it to
|
||||
// the deferred resolves list to be patched by
|
||||
// the render thread...
|
||||
deferred_resolves.push(DeferredResolve {
|
||||
resource_address: image_cpu.resource_address,
|
||||
image_properties: image_properties,
|
||||
});
|
||||
|
||||
(SourceTexture::External(external_id), None)
|
||||
}
|
||||
None => {
|
||||
let cache_item = resource_cache.get_cached_image(image_key, image_rendering, tile_offset);
|
||||
(cache_item.texture_id, Some(cache_item))
|
||||
}
|
||||
}
|
||||
PrimitiveStore::resolve_image(resource_cache,
|
||||
&mut deferred_resolves,
|
||||
image_key,
|
||||
image_cpu.resource_address,
|
||||
image_rendering,
|
||||
tile_offset)
|
||||
}
|
||||
ImagePrimitiveKind::WebGL(context_id) => {
|
||||
let cache_item = resource_cache.get_webgl_texture(&context_id);
|
||||
|
@ -947,29 +953,30 @@ impl PrimitiveStore {
|
|||
}
|
||||
PrimitiveKind::YuvImage => {
|
||||
let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
let image_gpu: &mut YuvImagePrimitiveGpu = unsafe {
|
||||
mem::transmute(self.gpu_data64.get_mut(metadata.gpu_prim_index))
|
||||
};
|
||||
|
||||
if image_cpu.y_texture_id == SourceTexture::Invalid {
|
||||
let y_cache_item = resource_cache.get_cached_image(image_cpu.y_key, ImageRendering::Auto, None);
|
||||
image_cpu.y_texture_id = y_cache_item.texture_id;
|
||||
image_gpu.y_uv0 = y_cache_item.uv0;
|
||||
image_gpu.y_uv1 = y_cache_item.uv1;
|
||||
}
|
||||
//yuv
|
||||
for channel in 0..3 {
|
||||
if image_cpu.yuv_texture_id[channel] == SourceTexture::Invalid {
|
||||
// Check if an external image that needs to be resolved
|
||||
// by the render thread.
|
||||
let resource_address = image_cpu.yuv_resource_address + channel as i32;
|
||||
|
||||
if image_cpu.u_texture_id == SourceTexture::Invalid {
|
||||
let u_cache_item = resource_cache.get_cached_image(image_cpu.u_key, ImageRendering::Auto, None);
|
||||
image_cpu.u_texture_id = u_cache_item.texture_id;
|
||||
image_gpu.u_uv0 = u_cache_item.uv0;
|
||||
image_gpu.u_uv1 = u_cache_item.uv1;
|
||||
}
|
||||
|
||||
if image_cpu.v_texture_id == SourceTexture::Invalid {
|
||||
let v_cache_item = resource_cache.get_cached_image(image_cpu.v_key, ImageRendering::Auto, None);
|
||||
image_cpu.v_texture_id = v_cache_item.texture_id;
|
||||
image_gpu.v_uv0 = v_cache_item.uv0;
|
||||
image_gpu.v_uv1 = v_cache_item.uv1;
|
||||
let (texture_id, cache_item) =
|
||||
PrimitiveStore::resolve_image(resource_cache,
|
||||
&mut deferred_resolves,
|
||||
image_cpu.yuv_key[channel],
|
||||
resource_address,
|
||||
ImageRendering::Auto,
|
||||
None);
|
||||
// texture_id
|
||||
image_cpu.yuv_texture_id[channel] = texture_id;
|
||||
// uv coordinates
|
||||
if let Some(cache_item) = cache_item {
|
||||
let resource_rect = self.gpu_resource_rects.get_mut(image_cpu.yuv_resource_address + channel as i32);
|
||||
resource_rect.uv0 = cache_item.uv0;
|
||||
resource_rect.uv1 = cache_item.uv1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1188,9 +1195,9 @@ impl PrimitiveStore {
|
|||
let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
prim_needs_resolve = true;
|
||||
|
||||
resource_cache.request_image(image_cpu.y_key, ImageRendering::Auto, None);
|
||||
resource_cache.request_image(image_cpu.u_key, ImageRendering::Auto, None);
|
||||
resource_cache.request_image(image_cpu.v_key, ImageRendering::Auto, None);
|
||||
for channel in 0..3 {
|
||||
resource_cache.request_image(image_cpu.yuv_key[channel], ImageRendering::Auto, None);
|
||||
}
|
||||
|
||||
// TODO(nical): Currently assuming no tile_spacing for yuv images.
|
||||
metadata.is_opaque = true;
|
||||
|
@ -1335,10 +1342,10 @@ impl From<RadialGradientPrimitiveGpu> for GpuBlock32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<YuvImagePrimitiveGpu> for GpuBlock64 {
|
||||
fn from(data: YuvImagePrimitiveGpu) -> GpuBlock64 {
|
||||
impl From<YuvImagePrimitiveGpu> for GpuBlock16 {
|
||||
fn from(data: YuvImagePrimitiveGpu) -> GpuBlock16 {
|
||||
unsafe {
|
||||
mem::transmute::<YuvImagePrimitiveGpu, GpuBlock64>(data)
|
||||
mem::transmute::<YuvImagePrimitiveGpu, GpuBlock16>(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ impl IntProfileCounter {
|
|||
pub fn set(&mut self, amount: usize) {
|
||||
self.value = amount;
|
||||
}
|
||||
|
||||
pub fn get(&self) -> usize {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl ProfileCounter for IntProfileCounter {
|
||||
|
@ -153,6 +157,10 @@ impl TimeProfileCounter {
|
|||
self.nanoseconds += ns;
|
||||
val
|
||||
}
|
||||
|
||||
pub fn get(&self) -> u64 {
|
||||
self.nanoseconds
|
||||
}
|
||||
}
|
||||
|
||||
impl ProfileCounter for TimeProfileCounter {
|
||||
|
|
|
@ -66,6 +66,7 @@ pub fn should_record_msg(msg: &ApiMsg) -> bool {
|
|||
match msg {
|
||||
&ApiMsg::AddRawFont(..) |
|
||||
&ApiMsg::AddNativeFont(..) |
|
||||
&ApiMsg::DeleteFont(..) |
|
||||
&ApiMsg::AddImage(..) |
|
||||
&ApiMsg::GenerateFrame(..) |
|
||||
&ApiMsg::UpdateImage(..) |
|
||||
|
|
|
@ -18,6 +18,7 @@ use std::sync::mpsc::Sender;
|
|||
use texture_cache::TextureCache;
|
||||
use thread_profiler::register_thread_with_profiler;
|
||||
use threadpool::ThreadPool;
|
||||
use webrender_traits::{DeviceIntPoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize, LayerPoint};
|
||||
use webrender_traits::{ApiMsg, AuxiliaryLists, BuiltDisplayList, IdNamespace, ImageData};
|
||||
use webrender_traits::{PipelineId, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId};
|
||||
use webrender_traits::channel::{PayloadHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
|
||||
|
@ -34,7 +35,13 @@ pub struct RenderBackend {
|
|||
payload_tx: PayloadSender,
|
||||
result_tx: Sender<ResultMsg>,
|
||||
|
||||
device_pixel_ratio: f32,
|
||||
// TODO(gw): Consider using strongly typed units here.
|
||||
hidpi_factor: f32,
|
||||
page_zoom_factor: f32,
|
||||
pinch_zoom_factor: f32,
|
||||
pan: DeviceIntPoint,
|
||||
window_size: DeviceUintSize,
|
||||
inner_rect: DeviceUintRect,
|
||||
next_namespace_id: IdNamespace,
|
||||
|
||||
resource_cache: ResourceCache,
|
||||
|
@ -59,7 +66,7 @@ impl RenderBackend {
|
|||
payload_rx: PayloadReceiver,
|
||||
payload_tx: PayloadSender,
|
||||
result_tx: Sender<ResultMsg>,
|
||||
device_pixel_ratio: f32,
|
||||
hidpi_factor: f32,
|
||||
texture_cache: TextureCache,
|
||||
enable_aa: bool,
|
||||
workers: Arc<Mutex<ThreadPool>>,
|
||||
|
@ -69,7 +76,8 @@ impl RenderBackend {
|
|||
recorder: Option<Box<ApiRecordingReceiver>>,
|
||||
main_thread_dispatcher: Arc<Mutex<Option<Box<RenderDispatcher>>>>,
|
||||
blob_image_renderer: Option<Box<BlobImageRenderer>>,
|
||||
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>) -> RenderBackend {
|
||||
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>,
|
||||
initial_window_size: DeviceUintSize) -> RenderBackend {
|
||||
|
||||
let resource_cache = ResourceCache::new(texture_cache, workers, blob_image_renderer, enable_aa);
|
||||
|
||||
|
@ -80,7 +88,10 @@ impl RenderBackend {
|
|||
payload_rx: payload_rx,
|
||||
payload_tx: payload_tx,
|
||||
result_tx: result_tx,
|
||||
device_pixel_ratio: device_pixel_ratio,
|
||||
hidpi_factor: hidpi_factor,
|
||||
page_zoom_factor: 1.0,
|
||||
pinch_zoom_factor: 1.0,
|
||||
pan: DeviceIntPoint::zero(),
|
||||
resource_cache: resource_cache,
|
||||
scene: Scene::new(),
|
||||
frame: Frame::new(config),
|
||||
|
@ -92,7 +103,9 @@ impl RenderBackend {
|
|||
recorder: recorder,
|
||||
main_thread_dispatcher: main_thread_dispatcher,
|
||||
next_webgl_id: 0,
|
||||
vr_compositor_handler: vr_compositor_handler
|
||||
vr_compositor_handler: vr_compositor_handler,
|
||||
window_size: initial_window_size,
|
||||
inner_rect: DeviceUintRect::new(DeviceUintPoint::zero(), initial_window_size),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +130,9 @@ impl RenderBackend {
|
|||
self.resource_cache
|
||||
.add_font_template(id, FontTemplate::Native(native_font_handle));
|
||||
}
|
||||
ApiMsg::DeleteFont(id) => {
|
||||
self.resource_cache.delete_font_template(id);
|
||||
}
|
||||
ApiMsg::GetGlyphDimensions(glyph_keys, tx) => {
|
||||
let mut glyph_dimensions = Vec::with_capacity(glyph_keys.len());
|
||||
for glyph_key in &glyph_keys {
|
||||
|
@ -137,6 +153,19 @@ impl RenderBackend {
|
|||
ApiMsg::DeleteImage(id) => {
|
||||
self.resource_cache.delete_image_template(id);
|
||||
}
|
||||
ApiMsg::SetPageZoom(factor) => {
|
||||
self.page_zoom_factor = factor.get();
|
||||
}
|
||||
ApiMsg::SetPinchZoom(factor) => {
|
||||
self.pinch_zoom_factor = factor.get();
|
||||
}
|
||||
ApiMsg::SetPan(pan) => {
|
||||
self.pan = pan;
|
||||
}
|
||||
ApiMsg::SetWindowParameters(window_size, inner_rect) => {
|
||||
self.window_size = window_size;
|
||||
self.inner_rect = inner_rect;
|
||||
}
|
||||
ApiMsg::CloneApi(sender) => {
|
||||
let result = self.next_namespace_id;
|
||||
|
||||
|
@ -398,6 +427,10 @@ impl RenderBackend {
|
|||
self.frame.discard_frame_state_for_pipeline(pipeline_id);
|
||||
}
|
||||
|
||||
fn accumulated_scale_factor(&self) -> f32 {
|
||||
self.hidpi_factor * self.page_zoom_factor * self.pinch_zoom_factor
|
||||
}
|
||||
|
||||
fn build_scene(&mut self) {
|
||||
// Flatten the stacking context hierarchy
|
||||
if let Some(id) = self.current_bound_webgl_context_id {
|
||||
|
@ -418,17 +451,25 @@ impl RenderBackend {
|
|||
webgl_context.unbind();
|
||||
}
|
||||
|
||||
self.frame.create(&self.scene, &mut self.resource_cache);
|
||||
let accumulated_scale_factor = self.accumulated_scale_factor();
|
||||
self.frame.create(&self.scene,
|
||||
&mut self.resource_cache,
|
||||
self.window_size,
|
||||
self.inner_rect,
|
||||
accumulated_scale_factor);
|
||||
}
|
||||
|
||||
fn render(&mut self,
|
||||
texture_cache_profile: &mut TextureCacheProfileCounters)
|
||||
-> RendererFrame {
|
||||
let accumulated_scale_factor = self.accumulated_scale_factor();
|
||||
let pan = LayerPoint::new(self.pan.x as f32 / accumulated_scale_factor,
|
||||
self.pan.y as f32 / accumulated_scale_factor);
|
||||
let frame = self.frame.build(&mut self.resource_cache,
|
||||
&self.scene.pipeline_auxiliary_lists,
|
||||
self.device_pixel_ratio,
|
||||
accumulated_scale_factor,
|
||||
pan,
|
||||
texture_cache_profile);
|
||||
|
||||
frame
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ use mask_cache::MaskCacheInfo;
|
|||
use prim_store::{PrimitiveCacheKey, PrimitiveIndex};
|
||||
use std::{cmp, f32, i32, mem, usize};
|
||||
use tiling::{ClipScrollGroupIndex, PackedLayerIndex, RenderPass, RenderTargetIndex};
|
||||
use tiling::{ScrollLayerIndex, StackingContextIndex};
|
||||
use tiling::{StackingContextIndex};
|
||||
use webrender_traits::{DeviceIntLength, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use webrender_traits::MixBlendMode;
|
||||
use webrender_traits::{MixBlendMode, ScrollLayerId};
|
||||
|
||||
const FLOATS_PER_RENDER_TASK_INFO: usize = 12;
|
||||
|
||||
|
@ -33,7 +33,7 @@ pub enum RenderTaskKey {
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum MaskCacheKey {
|
||||
Primitive(PrimitiveIndex),
|
||||
ScrollLayer(ScrollLayerIndex),
|
||||
ScrollLayer(ScrollLayerId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -62,6 +62,7 @@ pub struct AlphaRenderTask {
|
|||
screen_origin: DeviceIntPoint,
|
||||
pub opaque_items: Vec<AlphaRenderItem>,
|
||||
pub alpha_items: Vec<AlphaRenderItem>,
|
||||
pub isolate_clear: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -144,6 +145,7 @@ pub struct RenderTask {
|
|||
impl RenderTask {
|
||||
pub fn new_alpha_batch(task_index: RenderTaskIndex,
|
||||
screen_origin: DeviceIntPoint,
|
||||
isolate_clear: bool,
|
||||
location: RenderTaskLocation) -> RenderTask {
|
||||
RenderTask {
|
||||
id: RenderTaskId::Static(task_index),
|
||||
|
@ -153,6 +155,7 @@ impl RenderTask {
|
|||
screen_origin: screen_origin,
|
||||
alpha_items: Vec::new(),
|
||||
opaque_items: Vec::new(),
|
||||
isolate_clear: isolate_clear,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
use debug_colors;
|
||||
use debug_render::DebugRenderer;
|
||||
use device::{DepthFunction, Device, ProgramId, TextureId, VertexFormat, GpuMarker, GpuProfiler};
|
||||
use device::{TextureFilter, VAOId, VertexUsageHint, FileWatcherHandler, TextureTarget, ShaderError};
|
||||
use device::{DepthFunction, Device, FrameId, ProgramId, TextureId, VertexFormat, GpuMarker, GpuProfiler};
|
||||
use device::{GpuSample, TextureFilter, VAOId, VertexUsageHint, FileWatcherHandler, TextureTarget, ShaderError};
|
||||
use euclid::Matrix4D;
|
||||
use fnv::FnvHasher;
|
||||
use frame_builder::FrameBuilderConfig;
|
||||
|
@ -29,7 +29,7 @@ use render_backend::RenderBackend;
|
|||
use render_task::RenderTaskData;
|
||||
use std;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::f32;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -46,7 +46,7 @@ use time::precise_time_ns;
|
|||
use thread_profiler::{register_thread_with_profiler, write_profile};
|
||||
use util::TransformedRectKind;
|
||||
use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
|
||||
use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender, RendererKind};
|
||||
use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender};
|
||||
use webrender_traits::{DeviceIntRect, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
|
||||
use webrender_traits::{ImageDescriptor, BlobImageRenderer};
|
||||
use webrender_traits::channel;
|
||||
|
@ -75,14 +75,55 @@ const GPU_TAG_PRIM_BORDER: GpuProfileTag = GpuProfileTag { label: "Border", colo
|
|||
const GPU_TAG_PRIM_CACHE_IMAGE: GpuProfileTag = GpuProfileTag { label: "CacheImage", color: debug_colors::SILVER };
|
||||
const GPU_TAG_BLUR: GpuProfileTag = GpuProfileTag { label: "Blur", color: debug_colors::VIOLET };
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum RendererKind {
|
||||
Native,
|
||||
OSMesa,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GpuProfile {
|
||||
pub frame_id: FrameId,
|
||||
pub paint_time_ns: u64,
|
||||
}
|
||||
|
||||
impl GpuProfile {
|
||||
fn new<T>(frame_id: FrameId, samples: &[GpuSample<T>]) -> GpuProfile {
|
||||
let mut paint_time_ns = 0;
|
||||
for sample in samples {
|
||||
paint_time_ns += sample.time_ns;
|
||||
}
|
||||
GpuProfile {
|
||||
frame_id: frame_id,
|
||||
paint_time_ns: paint_time_ns,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CpuProfile {
|
||||
pub frame_id: FrameId,
|
||||
pub composite_time_ns: u64,
|
||||
pub draw_calls: usize,
|
||||
}
|
||||
|
||||
impl CpuProfile {
|
||||
fn new(frame_id: FrameId,
|
||||
composite_time_ns: u64,
|
||||
draw_calls: usize) -> CpuProfile {
|
||||
CpuProfile {
|
||||
frame_id: frame_id,
|
||||
composite_time_ns: composite_time_ns,
|
||||
draw_calls: draw_calls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum BlendMode {
|
||||
None,
|
||||
Alpha,
|
||||
|
||||
Multiply,
|
||||
Max,
|
||||
Min,
|
||||
PremultipliedAlpha,
|
||||
|
||||
// Use the color of the text itself as a constant color blend factor.
|
||||
Subpixel(ColorF),
|
||||
|
@ -429,6 +470,7 @@ pub struct Renderer {
|
|||
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
|
||||
|
||||
enable_profiler: bool,
|
||||
max_recorded_profiles: usize,
|
||||
clear_framebuffer: bool,
|
||||
clear_color: ColorF,
|
||||
debug: DebugRenderer,
|
||||
|
@ -477,7 +519,12 @@ pub struct Renderer {
|
|||
|
||||
// Optional trait object that handles WebVR commands.
|
||||
// Some WebVR commands such as SubmitFrame must be synced with the WebGL render thread.
|
||||
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>
|
||||
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>,
|
||||
|
||||
/// List of profile results from previous frames. Can be retrieved
|
||||
/// via get_frame_profiles().
|
||||
cpu_profiles: VecDeque<CpuProfile>,
|
||||
gpu_profiles: VecDeque<GpuProfile>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -513,7 +560,8 @@ impl Renderer {
|
|||
/// };
|
||||
/// let (renderer, sender) = Renderer::new(opts);
|
||||
/// ```
|
||||
pub fn new(mut options: RendererOptions) -> Result<(Renderer, RenderApiSender), InitError> {
|
||||
pub fn new(mut options: RendererOptions,
|
||||
initial_window_size: DeviceUintSize) -> Result<(Renderer, RenderApiSender), InitError> {
|
||||
let (api_tx, api_rx) = try!{ channel::msg_channel() };
|
||||
let (payload_tx, payload_rx) = try!{ channel::payload_channel() };
|
||||
let (result_tx, result_rx) = channel();
|
||||
|
@ -805,7 +853,8 @@ impl Renderer {
|
|||
recorder,
|
||||
backend_main_thread_dispatcher,
|
||||
blob_image_renderer,
|
||||
backend_vr_compositor);
|
||||
backend_vr_compositor,
|
||||
initial_window_size);
|
||||
backend.run(backend_profile_counters);
|
||||
})};
|
||||
|
||||
|
@ -842,6 +891,7 @@ impl Renderer {
|
|||
profile_counters: RendererProfileCounters::new(),
|
||||
profiler: Profiler::new(),
|
||||
enable_profiler: options.enable_profiler,
|
||||
max_recorded_profiles: options.max_recorded_profiles,
|
||||
clear_framebuffer: options.clear_framebuffer,
|
||||
clear_color: options.clear_color,
|
||||
last_time: 0,
|
||||
|
@ -858,7 +908,9 @@ impl Renderer {
|
|||
dummy_cache_texture_id: dummy_cache_texture_id,
|
||||
external_image_handler: None,
|
||||
external_images: HashMap::with_hasher(Default::default()),
|
||||
vr_compositor_handler: vr_compositor
|
||||
vr_compositor_handler: vr_compositor,
|
||||
cpu_profiles: VecDeque::new(),
|
||||
gpu_profiles: VecDeque::new(),
|
||||
};
|
||||
|
||||
let sender = RenderApiSender::new(api_tx, payload_tx);
|
||||
|
@ -960,6 +1012,13 @@ impl Renderer {
|
|||
self.external_image_handler = Some(handler);
|
||||
}
|
||||
|
||||
/// Retrieve (and clear) the current list of recorded frame profiles.
|
||||
pub fn get_frame_profiles(&mut self) -> (Vec<CpuProfile>, Vec<GpuProfile>) {
|
||||
let cpu_profiles = self.cpu_profiles.drain(..).collect();
|
||||
let gpu_profiles = self.gpu_profiles.drain(..).collect();
|
||||
(cpu_profiles, gpu_profiles)
|
||||
}
|
||||
|
||||
/// Renders the current frame.
|
||||
///
|
||||
/// A Frame is supplied by calling [set_root_stacking_context()][newframe].
|
||||
|
@ -973,13 +1032,19 @@ impl Renderer {
|
|||
|
||||
// Block CPU waiting for last frame's GPU profiles to arrive.
|
||||
// In general this shouldn't block unless heavily GPU limited.
|
||||
if let Some(samples) = self.gpu_profile.build_samples() {
|
||||
if let Some((gpu_frame_id, samples)) = self.gpu_profile.build_samples() {
|
||||
if self.max_recorded_profiles > 0 {
|
||||
while self.gpu_profiles.len() >= self.max_recorded_profiles {
|
||||
self.gpu_profiles.pop_front();
|
||||
}
|
||||
self.gpu_profiles.push_back(GpuProfile::new(gpu_frame_id, &samples));
|
||||
}
|
||||
profile_timers.gpu_samples = samples;
|
||||
}
|
||||
|
||||
profile_timers.cpu_time.profile(|| {
|
||||
self.device.begin_frame(frame.device_pixel_ratio);
|
||||
self.gpu_profile.begin_frame();
|
||||
let cpu_frame_id = profile_timers.cpu_time.profile(|| {
|
||||
let cpu_frame_id = self.device.begin_frame(frame.device_pixel_ratio);
|
||||
self.gpu_profile.begin_frame(cpu_frame_id);
|
||||
{
|
||||
let _gm = self.gpu_profile.add_marker(GPU_TAG_INIT);
|
||||
|
||||
|
@ -994,12 +1059,23 @@ impl Renderer {
|
|||
self.draw_tile_frame(frame, &framebuffer_size);
|
||||
|
||||
self.gpu_profile.end_frame();
|
||||
cpu_frame_id
|
||||
});
|
||||
|
||||
let current_time = precise_time_ns();
|
||||
let ns = current_time - self.last_time;
|
||||
self.profile_counters.frame_time.set(ns);
|
||||
|
||||
if self.max_recorded_profiles > 0 {
|
||||
while self.cpu_profiles.len() >= self.max_recorded_profiles {
|
||||
self.cpu_profiles.pop_front();
|
||||
}
|
||||
let cpu_profile = CpuProfile::new(cpu_frame_id,
|
||||
profile_timers.cpu_time.get(),
|
||||
self.profile_counters.draw_calls.get());
|
||||
self.cpu_profiles.push_back(cpu_profile);
|
||||
}
|
||||
|
||||
if self.enable_profiler {
|
||||
self.profiler.draw_profile(&frame.profile_counters,
|
||||
&self.backend_profile_counters,
|
||||
|
@ -1180,7 +1256,9 @@ impl Renderer {
|
|||
target_dimensions: DeviceUintSize) {
|
||||
let transform_kind = batch.key.flags.transform_kind();
|
||||
let needs_clipping = batch.key.flags.needs_clipping();
|
||||
debug_assert!(!needs_clipping || batch.key.blend_mode == BlendMode::Alpha);
|
||||
debug_assert!(!needs_clipping ||
|
||||
batch.key.blend_mode == BlendMode::Alpha ||
|
||||
batch.key.blend_mode == BlendMode::PremultipliedAlpha);
|
||||
|
||||
match batch.data {
|
||||
PrimitiveBatchData::Instances(ref data) => {
|
||||
|
@ -1205,8 +1283,7 @@ impl Renderer {
|
|||
AlphaBatchKind::TextRun => {
|
||||
let shader = match batch.key.blend_mode {
|
||||
BlendMode::Subpixel(..) => self.ps_text_run_subpixel.get(&mut self.device, transform_kind),
|
||||
BlendMode::Alpha | BlendMode::None => self.ps_text_run.get(&mut self.device, transform_kind),
|
||||
_ => unreachable!(),
|
||||
BlendMode::Alpha | BlendMode::PremultipliedAlpha | BlendMode::None => self.ps_text_run.get(&mut self.device, transform_kind),
|
||||
};
|
||||
(GPU_TAG_PRIM_TEXT_RUN, shader)
|
||||
}
|
||||
|
@ -1290,20 +1367,18 @@ impl Renderer {
|
|||
let width = readback.data[2];
|
||||
let height = readback.data[3];
|
||||
|
||||
// Need to invert the y coordinates when reading back from
|
||||
// the framebuffer.
|
||||
let y0 = if render_target.is_some() {
|
||||
src_y as i32
|
||||
} else {
|
||||
target_dimensions.height as i32 - height as i32 - src_y as i32
|
||||
};
|
||||
let mut src = DeviceIntRect::new(DeviceIntPoint::new(src_x as i32, src_y as i32),
|
||||
DeviceIntSize::new(width as i32, height as i32));
|
||||
let mut dest = DeviceIntRect::new(DeviceIntPoint::new(dest_x as i32, dest_y as i32),
|
||||
DeviceIntSize::new(width as i32, height as i32));
|
||||
|
||||
let src = DeviceIntRect::new(DeviceIntPoint::new(src_x as i32,
|
||||
y0),
|
||||
DeviceIntSize::new(width as i32, height as i32));
|
||||
let dest = DeviceIntRect::new(DeviceIntPoint::new(dest_x as i32,
|
||||
dest_y as i32),
|
||||
DeviceIntSize::new(width as i32, height as i32));
|
||||
// Need to invert the y coordinates and flip the image vertically when
|
||||
// reading back from the framebuffer.
|
||||
if render_target.is_none() {
|
||||
src.origin.y = target_dimensions.height as i32 - src.size.height - src.origin.y;
|
||||
dest.origin.y += dest.size.height;
|
||||
dest.size.height = -dest.size.height;
|
||||
}
|
||||
|
||||
self.device.blit_render_target(render_target,
|
||||
Some(src),
|
||||
|
@ -1381,6 +1456,11 @@ impl Renderer {
|
|||
|
||||
self.device.clear_target(clear_color, clear_depth);
|
||||
|
||||
let isolate_clear_color = Some([0.0, 0.0, 0.0, 0.0]);
|
||||
for isolate_clear in &target.isolate_clears {
|
||||
self.device.clear_target_rect(isolate_clear_color, None, *isolate_clear);
|
||||
}
|
||||
|
||||
projection
|
||||
};
|
||||
|
||||
|
@ -1501,22 +1581,14 @@ impl Renderer {
|
|||
BlendMode::None => {
|
||||
self.device.set_blend(false);
|
||||
}
|
||||
BlendMode::Multiply => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_multiply();
|
||||
}
|
||||
BlendMode::Max => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_max();
|
||||
}
|
||||
BlendMode::Min => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_min();
|
||||
}
|
||||
BlendMode::Alpha => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_alpha();
|
||||
}
|
||||
BlendMode::PremultipliedAlpha => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_premultiplied_alpha();
|
||||
}
|
||||
BlendMode::Subpixel(color) => {
|
||||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_subpixel(color);
|
||||
|
@ -1601,10 +1673,8 @@ impl Renderer {
|
|||
// Some tests use a restricted viewport smaller than the main screen size.
|
||||
// Ensure we clear the framebuffer in these tests.
|
||||
// TODO(gw): Find a better solution for this?
|
||||
let viewport_size = DeviceIntSize::new((frame.viewport_size.width * frame.device_pixel_ratio) as i32,
|
||||
(frame.viewport_size.height * frame.device_pixel_ratio) as i32);
|
||||
let needs_clear = viewport_size.width < framebuffer_size.width as i32 ||
|
||||
viewport_size.height < framebuffer_size.height as i32;
|
||||
let needs_clear = frame.window_size.width < framebuffer_size.width ||
|
||||
frame.window_size.height < framebuffer_size.height;
|
||||
|
||||
self.device.disable_depth_write();
|
||||
self.device.disable_stencil();
|
||||
|
@ -1778,6 +1848,7 @@ pub struct RendererOptions {
|
|||
pub resource_override_path: Option<PathBuf>,
|
||||
pub enable_aa: bool,
|
||||
pub enable_profiler: bool,
|
||||
pub max_recorded_profiles: usize,
|
||||
pub debug: bool,
|
||||
pub enable_scrollbars: bool,
|
||||
pub precache_shaders: bool,
|
||||
|
@ -1799,6 +1870,7 @@ impl Default for RendererOptions {
|
|||
resource_override_path: None,
|
||||
enable_aa: true,
|
||||
enable_profiler: false,
|
||||
max_recorded_profiles: 0,
|
||||
debug: false,
|
||||
enable_scrollbars: false,
|
||||
precache_shaders: false,
|
||||
|
|
|
@ -41,6 +41,8 @@ enum GlyphCacheMsg {
|
|||
AddFont(FontKey, FontTemplate),
|
||||
/// Request glyphs for a text run.
|
||||
RequestGlyphs(FontKey, Au, ColorF, Vec<GlyphInstance>, FontRenderMode, Option<GlyphOptions>),
|
||||
// Remove an existing font.
|
||||
DeleteFont(FontKey),
|
||||
/// Finished requesting glyphs. Reply with new glyphs.
|
||||
EndFrame,
|
||||
}
|
||||
|
@ -260,6 +262,13 @@ impl ResourceCache {
|
|||
self.font_templates.insert(font_key, template);
|
||||
}
|
||||
|
||||
pub fn delete_font_template(&mut self, font_key: FontKey) {
|
||||
self.glyph_cache_tx
|
||||
.send(GlyphCacheMsg::DeleteFont(font_key))
|
||||
.unwrap();
|
||||
self.font_templates.remove(&font_key);
|
||||
}
|
||||
|
||||
pub fn add_image_template(&mut self,
|
||||
image_key: ImageKey,
|
||||
descriptor: ImageDescriptor,
|
||||
|
@ -839,6 +848,23 @@ fn spawn_glyph_cache_thread(workers: Arc<Mutex<ThreadPool>>) -> (Sender<GlyphCac
|
|||
});
|
||||
}
|
||||
}
|
||||
GlyphCacheMsg::DeleteFont(font_key) => {
|
||||
profile_scope!("DeleteFont");
|
||||
|
||||
// Delete a font from the font context in each worker thread.
|
||||
let barrier = Arc::new(Barrier::new(worker_count));
|
||||
for _ in 0..worker_count {
|
||||
let barrier = barrier.clone();
|
||||
workers.lock().unwrap().execute(move || {
|
||||
FONT_CONTEXT.with(|font_context| {
|
||||
let mut font_context = font_context.borrow_mut();
|
||||
font_context.delete_font(&font_key);
|
||||
});
|
||||
barrier.wait();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
GlyphCacheMsg::RequestGlyphs(key, size, color, glyph_instances, render_mode, glyph_options) => {
|
||||
profile_scope!("RequestGlyphs");
|
||||
|
||||
|
|
|
@ -41,7 +41,14 @@ impl SceneProperties {
|
|||
}
|
||||
|
||||
/// Get the current value for a transform property.
|
||||
pub fn resolve_layout_transform(&self, property: &PropertyBinding<LayoutTransform>) -> LayoutTransform {
|
||||
pub fn resolve_layout_transform(&self,
|
||||
property: Option<&PropertyBinding<LayoutTransform>>)
|
||||
-> LayoutTransform {
|
||||
let property = match property {
|
||||
Some(property) => property,
|
||||
None => return LayoutTransform::identity(),
|
||||
};
|
||||
|
||||
match *property {
|
||||
PropertyBinding::Value(matrix) => matrix,
|
||||
PropertyBinding::Binding(ref key) => {
|
||||
|
|
|
@ -7,7 +7,7 @@ use fnv::FnvHasher;
|
|||
use gpu_store::GpuStoreAddress;
|
||||
use internal_types::{ANGLE_FLOAT_TO_FIXED, BatchTextures, CacheTextureId, LowLevelFilterOp};
|
||||
use internal_types::SourceTexture;
|
||||
use mask_cache::{ClipSource, MaskCacheInfo};
|
||||
use mask_cache::MaskCacheInfo;
|
||||
use prim_store::{CLIP_DATA_GPU_SIZE, DeferredResolve, GpuBlock128, GpuBlock16, GpuBlock32};
|
||||
use prim_store::{GpuBlock64, GradientData, PrimitiveCacheKey, PrimitiveGeometry, PrimitiveIndex};
|
||||
use prim_store::{PrimitiveKind, PrimitiveMetadata, PrimitiveStore, TexelRect};
|
||||
|
@ -23,9 +23,9 @@ use std::hash::BuildHasherDefault;
|
|||
use texture_cache::TexturePage;
|
||||
use util::{TransformedRect, TransformedRectKind};
|
||||
use webrender_traits::{AuxiliaryLists, ColorF, DeviceIntPoint, DeviceIntRect, DeviceUintPoint};
|
||||
use webrender_traits::{DeviceUintSize, FontRenderMode, ImageRendering, LayerRect, LayerSize};
|
||||
use webrender_traits::{LayerToScrollTransform, LayerToWorldTransform, MixBlendMode, PipelineId};
|
||||
use webrender_traits::{ScrollLayerId, WorldPoint4D, WorldToLayerTransform};
|
||||
use webrender_traits::{DeviceUintSize, FontRenderMode, ImageRendering, LayerPoint, LayerRect};
|
||||
use webrender_traits::{LayerToWorldTransform, MixBlendMode, PipelineId, ScrollLayerId};
|
||||
use webrender_traits::{WorldPoint4D, WorldToLayerTransform};
|
||||
|
||||
// Special sentinel value recognized by the shader. It is considered to be
|
||||
// a dummy task that doesn't mask out anything.
|
||||
|
@ -105,7 +105,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
}
|
||||
PrimitiveKind::YuvImage => {
|
||||
let image_cpu = &self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
[image_cpu.y_texture_id, image_cpu.u_texture_id, image_cpu.v_texture_id]
|
||||
image_cpu.yuv_texture_id
|
||||
}
|
||||
PrimitiveKind::TextRun => {
|
||||
let text_run_cpu = &self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
|
@ -128,6 +128,13 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
BlendMode::Alpha
|
||||
}
|
||||
}
|
||||
PrimitiveKind::Image => {
|
||||
if needs_blending {
|
||||
BlendMode::PremultipliedAlpha
|
||||
} else {
|
||||
BlendMode::None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if needs_blending {
|
||||
BlendMode::Alpha
|
||||
|
@ -277,6 +284,8 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
});
|
||||
}
|
||||
AlphaBatchKind::YuvImage => {
|
||||
let image_yuv_cpu = &self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
|
||||
data.push(PrimitiveInstance {
|
||||
task_index: task_index,
|
||||
clip_task_index: clip_task_index,
|
||||
|
@ -284,7 +293,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
global_prim_id: global_prim_id,
|
||||
prim_address: prim_address,
|
||||
sub_index: 0,
|
||||
user_data: [ 0, 0 ],
|
||||
user_data: [ image_yuv_cpu.yuv_resource_address.0, 0 ],
|
||||
z_sort_index: z_sort_index,
|
||||
});
|
||||
}
|
||||
|
@ -391,14 +400,11 @@ pub struct ScrollbarPrimitive {
|
|||
pub border_radius: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PrimitiveRunCmd {
|
||||
PushStackingContext(StackingContextIndex),
|
||||
PopStackingContext,
|
||||
|
||||
PushScrollLayer(ScrollLayerIndex),
|
||||
PopScrollLayer,
|
||||
|
||||
PrimitiveRun(PrimitiveIndex, usize),
|
||||
PrimitiveRun(PrimitiveIndex, usize, ScrollLayerId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -870,6 +876,7 @@ pub struct RenderTarget {
|
|||
pub vertical_blurs: Vec<BlurCommand>,
|
||||
pub horizontal_blurs: Vec<BlurCommand>,
|
||||
pub readbacks: Vec<DeviceIntRect>,
|
||||
pub isolate_clears: Vec<DeviceIntRect>,
|
||||
page_allocator: TexturePage,
|
||||
}
|
||||
|
||||
|
@ -884,6 +891,7 @@ impl RenderTarget {
|
|||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
readbacks: Vec::new(),
|
||||
isolate_clears: Vec::new(),
|
||||
page_allocator: TexturePage::new(CacheTextureId(0), size),
|
||||
}
|
||||
}
|
||||
|
@ -909,6 +917,16 @@ impl RenderTarget {
|
|||
opaque_items: info.opaque_items,
|
||||
alpha_items: info.alpha_items,
|
||||
});
|
||||
|
||||
if info.isolate_clear {
|
||||
let location = match task.location {
|
||||
RenderTaskLocation::Dynamic(origin, size) => {
|
||||
DeviceIntRect::new(origin.unwrap().0, size)
|
||||
}
|
||||
RenderTaskLocation::Fixed => panic!()
|
||||
};
|
||||
self.isolate_clears.push(location);
|
||||
}
|
||||
}
|
||||
RenderTaskKind::VerticalBlur(_, prim_index) => {
|
||||
// Find the child render task that we are applying
|
||||
|
@ -1301,53 +1319,79 @@ pub struct StackingContextIndex(pub usize);
|
|||
#[derive(Debug)]
|
||||
pub struct StackingContext {
|
||||
pub pipeline_id: PipelineId,
|
||||
pub local_transform: LayerToScrollTransform,
|
||||
|
||||
// Offset in the parent reference frame to the origin of this stacking
|
||||
// context's coordinate system.
|
||||
pub reference_frame_offset: LayerPoint,
|
||||
|
||||
// Bounds of this stacking context in its own coordinate system.
|
||||
pub local_rect: LayerRect,
|
||||
|
||||
pub bounding_rect: DeviceIntRect,
|
||||
pub composite_ops: CompositeOps,
|
||||
pub clip_scroll_groups: Vec<ClipScrollGroupIndex>,
|
||||
|
||||
// Signifies that this stacking context should be drawn in a separate render pass
|
||||
// with a transparent background and then composited back to its parent. Used to
|
||||
// support mix-blend-mode in certain cases.
|
||||
pub should_isolate: bool,
|
||||
|
||||
// Set for the root stacking context of a display list or an iframe. Used for determining
|
||||
// when to isolate a mix-blend-mode composite.
|
||||
pub is_page_root: bool,
|
||||
|
||||
pub is_visible: bool,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
pub fn new(pipeline_id: PipelineId,
|
||||
local_transform: LayerToScrollTransform,
|
||||
reference_frame_offset: LayerPoint,
|
||||
local_rect: LayerRect,
|
||||
composite_ops: CompositeOps,
|
||||
clip_scroll_group_index: ClipScrollGroupIndex)
|
||||
is_page_root: bool,
|
||||
composite_ops: CompositeOps)
|
||||
-> StackingContext {
|
||||
StackingContext {
|
||||
pipeline_id: pipeline_id,
|
||||
local_transform: local_transform,
|
||||
reference_frame_offset: reference_frame_offset,
|
||||
local_rect: local_rect,
|
||||
bounding_rect: DeviceIntRect::zero(),
|
||||
composite_ops: composite_ops,
|
||||
clip_scroll_groups: vec![clip_scroll_group_index],
|
||||
clip_scroll_groups: Vec::new(),
|
||||
should_isolate: false,
|
||||
is_page_root: is_page_root,
|
||||
is_visible: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clip_scroll_group(&self) -> ClipScrollGroupIndex {
|
||||
pub fn clip_scroll_group(&self, scroll_layer_id: ScrollLayerId) -> ClipScrollGroupIndex {
|
||||
// Currently there is only one scrolled stacking context per context,
|
||||
// but eventually this will be selected from the vector based on the
|
||||
// scroll layer of this primitive.
|
||||
self.clip_scroll_groups[0]
|
||||
for group in &self.clip_scroll_groups {
|
||||
if group.1 == scroll_layer_id {
|
||||
return *group;
|
||||
}
|
||||
}
|
||||
unreachable!("Looking for non-existent ClipScrollGroup");
|
||||
}
|
||||
|
||||
pub fn can_contribute_to_scene(&self) -> bool {
|
||||
!self.composite_ops.will_make_invisible()
|
||||
}
|
||||
|
||||
pub fn has_clip_scroll_group(&self, id: ScrollLayerId) -> bool {
|
||||
self.clip_scroll_groups.iter().rev().any(|index| index.1 == id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct ClipScrollGroupIndex(pub usize);
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct ClipScrollGroupIndex(pub usize, pub ScrollLayerId);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipScrollGroup {
|
||||
pub stacking_context_index: StackingContextIndex,
|
||||
pub scroll_layer_id: ScrollLayerId,
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
pub pipeline_id: PipelineId,
|
||||
pub xf_rect: Option<TransformedRect>,
|
||||
}
|
||||
|
||||
|
@ -1357,18 +1401,6 @@ impl ClipScrollGroup {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct ScrollLayerIndex(pub usize);
|
||||
|
||||
pub struct ScrollLayer {
|
||||
pub scroll_layer_id: ScrollLayerId,
|
||||
pub parent_index: ScrollLayerIndex,
|
||||
pub clip_source: ClipSource,
|
||||
pub clip_cache_info: Option<MaskCacheInfo>,
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
pub xf_rect: Option<TransformedRect>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct PackedLayer {
|
||||
|
@ -1393,6 +1425,31 @@ impl PackedLayer {
|
|||
pub fn empty() -> PackedLayer {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn set_transform(&mut self, transform: LayerToWorldTransform) {
|
||||
self.transform = transform;
|
||||
self.inv_transform = self.transform.inverse().unwrap();
|
||||
}
|
||||
|
||||
pub fn set_rect(&mut self,
|
||||
local_rect: Option<LayerRect>,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32)
|
||||
-> Option<TransformedRect> {
|
||||
let local_rect = match local_rect {
|
||||
Some(rect) if !rect.is_empty() => rect,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let xf_rect = TransformedRect::new(&local_rect, &self.transform, device_pixel_ratio);
|
||||
if !xf_rect.bounding_rect.intersects(screen_rect) {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.screen_vertices = xf_rect.vertices.clone();
|
||||
self.local_clip_rect = local_rect;
|
||||
Some(xf_rect)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -1412,13 +1469,6 @@ impl CompositeOps {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> CompositeOps {
|
||||
CompositeOps {
|
||||
filters: Vec::new(),
|
||||
mix_blend_mode: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
self.filters.len() + if self.mix_blend_mode.is_some() { 1 } else { 0 }
|
||||
}
|
||||
|
@ -1437,7 +1487,7 @@ impl CompositeOps {
|
|||
/// A rendering-oriented representation of frame::Frame built by the render backend
|
||||
/// and presented to the renderer.
|
||||
pub struct Frame {
|
||||
pub viewport_size: LayerSize,
|
||||
pub window_size: DeviceUintSize,
|
||||
pub background_color: Option<ColorF>,
|
||||
pub device_pixel_ratio: f32,
|
||||
pub cache_size: DeviceUintSize,
|
||||
|
|
|
@ -5,13 +5,12 @@ authors = ["The Mozilla Project Developers"]
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
webrender_traits = {path = "../webrender_traits", version = "0.20.0"}
|
||||
webrender_traits = {path = "../webrender_traits", version = "0.25.0"}
|
||||
euclid = "0.11"
|
||||
app_units = "0.4"
|
||||
gleam = "0.2"
|
||||
|
||||
[dependencies.webrender]
|
||||
path = "../webrender"
|
||||
version = "0.19.0"
|
||||
version = "0.24.0"
|
||||
default-features = false
|
||||
features = ["codegen"]
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RenderTextureHost.h"
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gfx;
|
||||
using namespace layers;
|
||||
|
||||
namespace wr {
|
||||
|
||||
RenderTextureHost::RenderTextureHost(uint8_t* aBuffer, const BufferDescriptor& aDescriptor)
|
||||
: mBuffer(aBuffer)
|
||||
, mDescriptor(aDescriptor)
|
||||
, mLocked(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RenderTextureHost);
|
||||
|
||||
switch (mDescriptor.type()) {
|
||||
case BufferDescriptor::TYCbCrDescriptor: {
|
||||
const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
|
||||
mSize = ycbcr.ySize();
|
||||
mFormat = gfx::SurfaceFormat::YUV;
|
||||
break;
|
||||
}
|
||||
case BufferDescriptor::TRGBDescriptor: {
|
||||
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
||||
mSize = rgb.size();
|
||||
mFormat = rgb.format();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gfxCriticalError() << "Bad buffer host descriptor " << (int)mDescriptor.type();
|
||||
MOZ_CRASH("GFX: Bad descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
RenderTextureHost::~RenderTextureHost()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RenderTextureHost);
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface>
|
||||
RenderTextureHost::GetAsSurface()
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> result;
|
||||
if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
|
||||
GetBuffer(), mDescriptor.get_YCbCrDescriptor());
|
||||
if (NS_WARN_IF(!result)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
result =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
|
||||
ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()),
|
||||
mSize, mFormat);
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
RenderTextureHost::Lock()
|
||||
{
|
||||
MOZ_ASSERT(!mLocked);
|
||||
|
||||
// XXX temporal workaround for YUV handling
|
||||
if (!mSurface) {
|
||||
mSurface = GetAsSurface();
|
||||
if (!mSurface) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mSurface->Map(DataSourceSurface::MapType::READ_WRITE, &mMap))) {
|
||||
mSurface = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
mLocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RenderTextureHost::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mLocked);
|
||||
mLocked = false;
|
||||
if (mSurface) {
|
||||
mSurface->Unmap();
|
||||
}
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
RenderTextureHost::GetDataForRender() const
|
||||
{
|
||||
MOZ_ASSERT(mLocked);
|
||||
MOZ_ASSERT(mSurface);
|
||||
return mMap.mData;
|
||||
}
|
||||
|
||||
size_t
|
||||
RenderTextureHost::GetBufferSizeForRender() const
|
||||
{
|
||||
MOZ_ASSERT(mLocked);
|
||||
MOZ_ASSERT(mSurface);
|
||||
return mMap.mStride * mSurface->GetSize().height;
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_RENDERTEXTUREHOST_H
|
||||
#define MOZILLA_GFX_RENDERTEXTUREHOST_H
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace wr {
|
||||
|
||||
class RenderTextureHost
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RenderTextureHost)
|
||||
|
||||
RenderTextureHost(uint8_t* aBuffer, const layers::BufferDescriptor& aDescriptor);
|
||||
|
||||
bool Lock();
|
||||
|
||||
void Unlock();
|
||||
|
||||
gfx::IntSize GetSize() const { return mSize; }
|
||||
|
||||
gfx::SurfaceFormat GetFormat() const { return mFormat; }
|
||||
|
||||
uint8_t* GetDataForRender() const;
|
||||
size_t GetBufferSizeForRender() const;
|
||||
|
||||
protected:
|
||||
~RenderTextureHost();
|
||||
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
|
||||
uint8_t* GetBuffer() const { return mBuffer; }
|
||||
|
||||
uint8_t* mBuffer;
|
||||
layers::BufferDescriptor mDescriptor;
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
RefPtr<gfx::DataSourceSurface> mSurface;
|
||||
gfx::DataSourceSurface::MappedSurface mMap;
|
||||
bool mLocked;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_GFX_RENDERTEXTUREHOST_H
|
|
@ -5,11 +5,12 @@
|
|||
|
||||
#include "RenderThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/webrender/RendererOGL.h"
|
||||
#include "mozilla/widget/CompositorWidget.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/webrender/RendererOGL.h"
|
||||
#include "mozilla/webrender/RenderTextureHost.h"
|
||||
#include "mozilla/widget/CompositorWidget.h"
|
||||
#include "base/task.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -19,6 +20,7 @@ static StaticRefPtr<RenderThread> sRenderThread;
|
|||
|
||||
RenderThread::RenderThread(base::Thread* aThread)
|
||||
: mThread(aThread)
|
||||
, mRenderTextureMapLock("RenderThread.mRenderTextureMapLock")
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -194,6 +196,30 @@ RenderThread::UpdateAndRender(wr::WindowId aWindowId)
|
|||
));
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::RegisterExternalImage(uint64_t aExternalImageId, RenderTextureHost* aTexture)
|
||||
{
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
MOZ_ASSERT(!mRenderTextures.Get(aExternalImageId));
|
||||
mRenderTextures.Put(aExternalImageId, aTexture);
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::UnregisterExternalImage(uint64_t aExternalImageId)
|
||||
{
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
MOZ_ASSERT(mRenderTextures.Get(aExternalImageId).get());
|
||||
mRenderTextures.Remove(aExternalImageId);
|
||||
}
|
||||
|
||||
RenderTextureHost*
|
||||
RenderThread::GetRenderTexture(uint64_t aExternalImageId)
|
||||
{
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
MOZ_ASSERT(mRenderTextures.Get(aExternalImageId).get());
|
||||
return mRenderTextures.Get(aExternalImageId).get();
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "base/message_loop.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
|
@ -21,6 +22,7 @@ namespace mozilla {
|
|||
namespace wr {
|
||||
|
||||
class RendererOGL;
|
||||
class RenderTextureHost;
|
||||
class RenderThread;
|
||||
|
||||
/// Base class for an event that can be scheduled to run on the render thread.
|
||||
|
@ -99,6 +101,13 @@ public:
|
|||
|
||||
/// Can only be called from the render thread.
|
||||
void UpdateAndRender(wr::WindowId aWindowId);
|
||||
|
||||
void RegisterExternalImage(uint64_t aExternalImageId, RenderTextureHost* aTexture);
|
||||
|
||||
void UnregisterExternalImage(uint64_t aExternalImageId);
|
||||
|
||||
RenderTextureHost* GetRenderTexture(uint64_t aExternalImageId);
|
||||
|
||||
private:
|
||||
explicit RenderThread(base::Thread* aThread);
|
||||
|
||||
|
@ -108,6 +117,9 @@ private:
|
|||
base::Thread* const mThread;
|
||||
|
||||
std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
|
||||
|
||||
Mutex mRenderTextureMapLock;
|
||||
nsDataHashtable<nsUint64HashKey, RefPtr<RenderTextureHost> > mRenderTextures;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/webrender/RenderTextureHost.h"
|
||||
#include "mozilla/widget/CompositorWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -16,11 +17,20 @@ namespace wr {
|
|||
|
||||
WrExternalImage LockExternalImage(void* aObj, WrExternalImageId aId)
|
||||
{
|
||||
return WrExternalImage { /*WrExternalImageIdType::TextureHandle, */0.0f, 0.0f, 0.0f, 0.0f, 0 };
|
||||
RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
|
||||
RenderTextureHost* texture = renderer->GetRenderTexture(aId.id);
|
||||
MOZ_ASSERT(texture);
|
||||
texture->Lock();
|
||||
return WrExternalImage { WrExternalImageIdType::RawData, 0.0f, 0.0f, 0.0f, 0.0f, 0,
|
||||
texture->GetDataForRender(), texture->GetBufferSizeForRender() };
|
||||
}
|
||||
|
||||
void UnlockExternalImage(void* aObj, WrExternalImageId aId)
|
||||
{
|
||||
RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj);
|
||||
RenderTextureHost* texture = renderer->GetRenderTexture(aId.id);
|
||||
MOZ_ASSERT(texture);
|
||||
texture->Unlock();
|
||||
}
|
||||
|
||||
void ReleaseExternalImage(void* aObj, WrExternalImageId aId)
|
||||
|
@ -120,5 +130,11 @@ RendererOGL::FlushRenderedEpochs()
|
|||
return wr_renderer_flush_rendered_epochs(mWrRenderer);
|
||||
}
|
||||
|
||||
RenderTextureHost*
|
||||
RendererOGL::GetRenderTexture(uint64_t aExternalImageId)
|
||||
{
|
||||
return mThread->GetRenderTexture(aExternalImageId);
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -31,6 +31,8 @@ class CompositorWidget;
|
|||
|
||||
namespace wr {
|
||||
|
||||
class RenderTextureHost;
|
||||
|
||||
/// Owns the WebRender renderer and GL context.
|
||||
///
|
||||
/// There is one renderer per window, all owned by the render thread.
|
||||
|
@ -72,6 +74,8 @@ public:
|
|||
|
||||
WrRenderedEpochs* FlushRenderedEpochs();
|
||||
|
||||
RenderTextureHost* GetRenderTexture(uint64_t aExternalImageId);
|
||||
|
||||
protected:
|
||||
|
||||
RefPtr<RenderThread> mThread;
|
||||
|
|
|
@ -21,7 +21,8 @@ public:
|
|||
bool* aUseANGLE,
|
||||
RefPtr<widget::CompositorWidget>&& aWidget,
|
||||
layers::SynchronousTask* aTask,
|
||||
bool aEnableProfiler)
|
||||
bool aEnableProfiler,
|
||||
LayoutDeviceIntSize aSize)
|
||||
: mWrApi(aApi)
|
||||
, mMaxTextureSize(aMaxTextureSize)
|
||||
, mUseANGLE(aUseANGLE)
|
||||
|
@ -29,6 +30,7 @@ public:
|
|||
, mCompositorWidget(Move(aWidget))
|
||||
, mTask(aTask)
|
||||
, mEnableProfiler(aEnableProfiler)
|
||||
, mSize(aSize)
|
||||
{
|
||||
MOZ_COUNT_CTOR(NewRenderer);
|
||||
}
|
||||
|
@ -51,7 +53,8 @@ public:
|
|||
*mUseANGLE = gl->IsANGLE();
|
||||
|
||||
WrRenderer* wrRenderer = nullptr;
|
||||
if (!wr_window_new(aWindowId, gl.get(), this->mEnableProfiler, mWrApi, &wrRenderer)) {
|
||||
if (!wr_window_new(aWindowId, mSize.width, mSize.height, gl.get(),
|
||||
this->mEnableProfiler, mWrApi, &wrRenderer)) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(wrRenderer);
|
||||
|
@ -79,6 +82,7 @@ private:
|
|||
RefPtr<widget::CompositorWidget> mCompositorWidget;
|
||||
layers::SynchronousTask* mTask;
|
||||
bool mEnableProfiler;
|
||||
LayoutDeviceIntSize mSize;
|
||||
};
|
||||
|
||||
class RemoveRenderer : public RendererEvent
|
||||
|
@ -110,7 +114,8 @@ private:
|
|||
already_AddRefed<WebRenderAPI>
|
||||
WebRenderAPI::Create(bool aEnableProfiler,
|
||||
layers::CompositorBridgeParentBase* aBridge,
|
||||
RefPtr<widget::CompositorWidget>&& aWidget)
|
||||
RefPtr<widget::CompositorWidget>&& aWidget,
|
||||
LayoutDeviceIntSize aSize)
|
||||
{
|
||||
MOZ_ASSERT(aBridge);
|
||||
MOZ_ASSERT(aWidget);
|
||||
|
@ -127,7 +132,7 @@ WebRenderAPI::Create(bool aEnableProfiler,
|
|||
// the next time we need to access the WrApi object.
|
||||
layers::SynchronousTask task("Create Renderer");
|
||||
auto event = MakeUnique<NewRenderer>(&wrApi, aBridge, &maxTextureSize, &useANGLE,
|
||||
Move(aWidget), &task, aEnableProfiler);
|
||||
Move(aWidget), &task, aEnableProfiler, aSize);
|
||||
RenderThread::Get()->RunEvent(id, Move(event));
|
||||
|
||||
task.Wait();
|
||||
|
@ -184,6 +189,19 @@ WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
|
|||
aux_size);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::ClearRootDisplayList(Epoch aEpoch,
|
||||
WrPipelineId pipeline_id)
|
||||
{
|
||||
wr_api_clear_root_display_list(mWrApi, aEpoch, pipeline_id);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::SetWindowParameters(LayoutDeviceIntSize size)
|
||||
{
|
||||
wr_api_set_window_parameters(mWrApi, size.width, size.height);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::Readback(gfx::IntSize size,
|
||||
uint8_t *buffer,
|
||||
|
@ -231,6 +249,42 @@ WebRenderAPI::Readback(gfx::IntSize size,
|
|||
task.Wait();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::WaitFlushed()
|
||||
{
|
||||
class WaitFlushedEvent : public RendererEvent
|
||||
{
|
||||
public:
|
||||
explicit WaitFlushedEvent(layers::SynchronousTask* aTask)
|
||||
: mTask(aTask)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WaitFlushedEvent);
|
||||
}
|
||||
|
||||
~WaitFlushedEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WaitFlushedEvent);
|
||||
}
|
||||
|
||||
virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override
|
||||
{
|
||||
layers::AutoCompleteTask complete(mTask);
|
||||
}
|
||||
|
||||
layers::SynchronousTask* mTask;
|
||||
};
|
||||
|
||||
layers::SynchronousTask task("WaitFlushed");
|
||||
auto event = MakeUnique<WaitFlushedEvent>(&task);
|
||||
// This event will be passed from wr_backend thread to renderer thread. That
|
||||
// implies that all frame data have been processed when the renderer runs this
|
||||
// read-back event. Then, we could make sure this read-back event gets the
|
||||
// latest result.
|
||||
RunOnRenderThread(Move(event));
|
||||
|
||||
task.Wait();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
|
||||
{
|
||||
|
@ -238,12 +292,12 @@ WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
|
|||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::AddImage(ImageKey key, const ImageDescriptor& aDescritptor,
|
||||
WebRenderAPI::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
|
||||
Range<uint8_t> aBytes)
|
||||
{
|
||||
wr_api_add_image(mWrApi,
|
||||
key,
|
||||
&aDescritptor,
|
||||
&aDescriptor,
|
||||
&aBytes[0], aBytes.length());
|
||||
}
|
||||
|
||||
|
@ -262,25 +316,23 @@ WebRenderAPI::AddExternalImageHandle(ImageKey key,
|
|||
|
||||
void
|
||||
WebRenderAPI::AddExternalImageBuffer(ImageKey key,
|
||||
gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
uint64_t aHandle)
|
||||
{
|
||||
auto format = SurfaceFormatToWrImageFormat(aFormat).value();
|
||||
wr_api_add_external_image_buffer(mWrApi,
|
||||
key,
|
||||
aSize.width, aSize.height, format,
|
||||
&aDescriptor,
|
||||
aHandle);
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderAPI::UpdateImageBuffer(ImageKey aKey,
|
||||
const ImageDescriptor& aDescritptor,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
Range<uint8_t> aBytes)
|
||||
{
|
||||
wr_api_update_image(mWrApi,
|
||||
aKey,
|
||||
&aDescritptor,
|
||||
&aDescriptor,
|
||||
&aBytes[0], aBytes.length());
|
||||
}
|
||||
|
||||
|
@ -366,17 +418,16 @@ DisplayListBuilder::End()
|
|||
wr_dp_end(mWrState);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
|
||||
wr::VecU8& dl_data,
|
||||
WrAuxiliaryListsDescriptor& aux_descriptor,
|
||||
wr::VecU8& aux_data)
|
||||
BuiltDisplayList
|
||||
DisplayListBuilder::Finalize()
|
||||
{
|
||||
wr_api_finalize_builder(mWrState,
|
||||
dl_descriptor,
|
||||
dl_data.inner,
|
||||
aux_descriptor,
|
||||
aux_data.inner);
|
||||
BuiltDisplayList dl;
|
||||
wr_api_finalize_builder(mWrState,
|
||||
dl.dl_desc,
|
||||
dl.dl.inner,
|
||||
dl.aux_desc,
|
||||
dl.aux.inner);
|
||||
return dl;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -397,6 +448,16 @@ DisplayListBuilder::PopStackingContext()
|
|||
wr_dp_pop_stacking_context(mWrState);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::PushBuiltDisplayList(BuiltDisplayList dl)
|
||||
{
|
||||
wr_dp_push_built_display_list(mWrState,
|
||||
dl.dl_desc,
|
||||
dl.dl.Extract(),
|
||||
dl.aux_desc,
|
||||
dl.aux.Extract());
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::PushScrollLayer(const WrRect& aBounds,
|
||||
const WrRect& aOverflow,
|
||||
|
@ -413,7 +474,7 @@ DisplayListBuilder::PopScrollLayer()
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushRect(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrColor& aColor)
|
||||
{
|
||||
wr_dp_push_rect(mWrState, aBounds, aClip, aColor);
|
||||
|
@ -421,7 +482,7 @@ DisplayListBuilder::PushRect(const WrRect& aBounds,
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushLinearGradient(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrPoint& aStartPoint,
|
||||
const WrPoint& aEndPoint,
|
||||
const nsTArray<WrGradientStop>& aStops,
|
||||
|
@ -436,7 +497,7 @@ DisplayListBuilder::PushLinearGradient(const WrRect& aBounds,
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushRadialGradient(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrPoint& aStartCenter,
|
||||
const WrPoint& aEndCenter,
|
||||
float aStartRadius,
|
||||
|
@ -454,17 +515,16 @@ DisplayListBuilder::PushRadialGradient(const WrRect& aBounds,
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushImage(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrImageMask* aMask,
|
||||
const WrClipRegion& aClip,
|
||||
wr::ImageRendering aFilter,
|
||||
wr::ImageKey aImage)
|
||||
{
|
||||
wr_dp_push_image(mWrState, aBounds, aClip, aMask, aFilter, aImage);
|
||||
wr_dp_push_image(mWrState, aBounds, aClip, aFilter, aImage);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::PushIFrame(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
PipelineId aPipeline)
|
||||
{
|
||||
wr_dp_push_iframe(mWrState, aBounds, aClip, aPipeline);
|
||||
|
@ -472,7 +532,8 @@ DisplayListBuilder::PushIFrame(const WrRect& aBounds,
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushBorder(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrBorderWidths& aWidths,
|
||||
const WrBorderSide& aTop,
|
||||
const WrBorderSide& aRight,
|
||||
const WrBorderSide& aBottom,
|
||||
|
@ -480,13 +541,27 @@ DisplayListBuilder::PushBorder(const WrRect& aBounds,
|
|||
const WrBorderRadius& aRadius)
|
||||
{
|
||||
wr_dp_push_border(mWrState, aBounds, aClip,
|
||||
aTop, aRight, aBottom, aLeft,
|
||||
aRadius);
|
||||
aWidths, aTop, aRight, aBottom, aLeft, aRadius);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::PushBorderImage(const WrRect& aBounds,
|
||||
const WrClipRegion& aClip,
|
||||
const WrBorderWidths& aWidths,
|
||||
wr::ImageKey aImage,
|
||||
const WrNinePatchDescriptor& aPatch,
|
||||
const WrSideOffsets2Df32& aOutset,
|
||||
const WrRepeatMode& aRepeatHorizontal,
|
||||
const WrRepeatMode& aRepeatVertical)
|
||||
{
|
||||
wr_dp_push_border_image(mWrState, aBounds, aClip,
|
||||
aWidths, aImage, aPatch, aOutset,
|
||||
aRepeatHorizontal, aRepeatVertical);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListBuilder::PushText(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const gfx::Color& aColor,
|
||||
wr::FontKey aFontKey,
|
||||
Range<const WrGlyphInstance> aGlyphBuffer,
|
||||
|
@ -501,7 +576,7 @@ DisplayListBuilder::PushText(const WrRect& aBounds,
|
|||
|
||||
void
|
||||
DisplayListBuilder::PushBoxShadow(const WrRect& aRect,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrRect& aBoxBounds,
|
||||
const WrPoint& aOffset,
|
||||
const WrColor& aColor,
|
||||
|
@ -516,5 +591,26 @@ DisplayListBuilder::PushBoxShadow(const WrRect& aRect,
|
|||
aClipMode);
|
||||
}
|
||||
|
||||
WrClipRegion
|
||||
DisplayListBuilder::BuildClipRegion(const WrRect& aMain,
|
||||
const WrImageMask* aMask)
|
||||
{
|
||||
return wr_dp_new_clip_region(mWrState,
|
||||
aMain,
|
||||
nullptr, 0,
|
||||
aMask);
|
||||
}
|
||||
|
||||
WrClipRegion
|
||||
DisplayListBuilder::BuildClipRegion(const WrRect& aMain,
|
||||
const nsTArray<WrComplexClipRegion>& aComplex,
|
||||
const WrImageMask* aMask)
|
||||
{
|
||||
return wr_dp_new_clip_region(mWrState,
|
||||
aMain,
|
||||
aComplex.Elements(), aComplex.Length(),
|
||||
aMask);
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/Range.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "GLTypes.h"
|
||||
#include "Units.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -21,6 +22,7 @@ class CompositorWidget;
|
|||
|
||||
namespace layers {
|
||||
class CompositorBridgeParentBase;
|
||||
class WebRenderBridgeParent;
|
||||
}
|
||||
|
||||
namespace wr {
|
||||
|
@ -29,8 +31,6 @@ class DisplayListBuilder;
|
|||
class RendererOGL;
|
||||
class RendererEvent;
|
||||
|
||||
|
||||
|
||||
class WebRenderAPI
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(WebRenderAPI);
|
||||
|
@ -39,12 +39,14 @@ public:
|
|||
/// This can be called on the compositor thread only.
|
||||
static already_AddRefed<WebRenderAPI> Create(bool aEnableProfiler,
|
||||
layers::CompositorBridgeParentBase* aBridge,
|
||||
RefPtr<widget::CompositorWidget>&& aWidget);
|
||||
RefPtr<widget::CompositorWidget>&& aWidget,
|
||||
LayoutDeviceIntSize aSize);
|
||||
|
||||
wr::WindowId GetId() const { return mId; }
|
||||
|
||||
void GenerateFrame();
|
||||
|
||||
void SetWindowParameters(LayoutDeviceIntSize size);
|
||||
void SetRootDisplayList(gfx::Color aBgColor,
|
||||
Epoch aEpoch,
|
||||
LayerSize aViewportSize,
|
||||
|
@ -56,6 +58,9 @@ public:
|
|||
uint8_t *aux_data,
|
||||
size_t aux_size);
|
||||
|
||||
void ClearRootDisplayList(Epoch aEpoch,
|
||||
WrPipelineId pipeline_id);
|
||||
|
||||
void SetRootPipeline(wr::PipelineId aPipeline);
|
||||
|
||||
void AddImage(wr::ImageKey aKey,
|
||||
|
@ -68,8 +73,7 @@ public:
|
|||
uint64_t aHandle);
|
||||
|
||||
void AddExternalImageBuffer(ImageKey key,
|
||||
gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const ImageDescriptor& aDescriptor,
|
||||
uint64_t aHandle);
|
||||
|
||||
void UpdateImageBuffer(wr::ImageKey aKey,
|
||||
|
@ -100,6 +104,8 @@ protected:
|
|||
{}
|
||||
|
||||
~WebRenderAPI();
|
||||
// Should be used only for shutdown handling
|
||||
void WaitFlushed();
|
||||
|
||||
WrAPI* mWrApi;
|
||||
wr::WindowId mId;
|
||||
|
@ -107,6 +113,7 @@ protected:
|
|||
bool mUseANGLE;
|
||||
|
||||
friend class DisplayListBuilder;
|
||||
friend class layers::WebRenderBridgeParent;
|
||||
};
|
||||
|
||||
/// This is a simple C++ wrapper around WrState defined in the rust bindings.
|
||||
|
@ -122,10 +129,7 @@ public:
|
|||
void Begin(const LayerIntSize& aSize);
|
||||
|
||||
void End();
|
||||
void Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
|
||||
wr::VecU8& dl_data,
|
||||
WrAuxiliaryListsDescriptor& aux_descriptor,
|
||||
wr::VecU8& aux_data);
|
||||
wr::BuiltDisplayList Finalize();
|
||||
|
||||
void PushStackingContext(const WrRect& aBounds, // TODO: We should work with strongly typed rects
|
||||
const WrRect& aOverflow,
|
||||
|
@ -136,6 +140,8 @@ public:
|
|||
|
||||
void PopStackingContext();
|
||||
|
||||
void PushBuiltDisplayList(wr::BuiltDisplayList dl);
|
||||
|
||||
void PushScrollLayer(const WrRect& aBounds, // TODO: We should work with strongly typed rects
|
||||
const WrRect& aOverflow,
|
||||
const WrImageMask* aMask); // TODO: needs a wrapper.
|
||||
|
@ -144,18 +150,18 @@ public:
|
|||
|
||||
|
||||
void PushRect(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrColor& aColor);
|
||||
|
||||
void PushLinearGradient(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrPoint& aStartPoint,
|
||||
const WrPoint& aEndPoint,
|
||||
const nsTArray<WrGradientStop>& aStops,
|
||||
wr::GradientExtendMode aExtendMode);
|
||||
|
||||
void PushRadialGradient(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrPoint& aStartCenter,
|
||||
const WrPoint& aEndCenter,
|
||||
float aStartRadius,
|
||||
|
@ -164,32 +170,41 @@ public:
|
|||
wr::GradientExtendMode aExtendMode);
|
||||
|
||||
void PushImage(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrImageMask* aMask,
|
||||
const WrClipRegion& aClip,
|
||||
wr::ImageRendering aFilter,
|
||||
wr::ImageKey aImage);
|
||||
|
||||
void PushIFrame(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
wr::PipelineId aPipeline);
|
||||
|
||||
void PushBorder(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrBorderWidths& aWidths,
|
||||
const WrBorderSide& aTop,
|
||||
const WrBorderSide& aRight,
|
||||
const WrBorderSide& aBbottom,
|
||||
const WrBorderSide& aLeft,
|
||||
const WrBorderRadius& aRadius);
|
||||
|
||||
void PushBorderImage(const WrRect& aBounds,
|
||||
const WrClipRegion& aClip,
|
||||
const WrBorderWidths& aWidths,
|
||||
wr::ImageKey aImage,
|
||||
const WrNinePatchDescriptor& aPatch,
|
||||
const WrSideOffsets2Df32& aOutset,
|
||||
const WrRepeatMode& aRepeatHorizontal,
|
||||
const WrRepeatMode& aRepeatVertical);
|
||||
|
||||
void PushText(const WrRect& aBounds,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const gfx::Color& aColor,
|
||||
wr::FontKey aFontKey,
|
||||
Range<const WrGlyphInstance> aGlyphBuffer,
|
||||
float aGlyphSize);
|
||||
|
||||
void PushBoxShadow(const WrRect& aRect,
|
||||
const WrRect& aClip,
|
||||
const WrClipRegion& aClip,
|
||||
const WrRect& aBoxBounds,
|
||||
const WrPoint& aOffset,
|
||||
const WrColor& aColor,
|
||||
|
@ -198,6 +213,12 @@ public:
|
|||
const float& aBorderRadius,
|
||||
const WrBoxShadowClipMode& aClipMode);
|
||||
|
||||
WrClipRegion BuildClipRegion(const WrRect& aMain,
|
||||
const WrImageMask* aMask = nullptr);
|
||||
WrClipRegion BuildClipRegion(const WrRect& aMain,
|
||||
const nsTArray<WrComplexClipRegion>& aComplex,
|
||||
const WrImageMask* aMask = nullptr);
|
||||
|
||||
// Try to avoid using this when possible.
|
||||
WrState* Raw() { return mWrState; }
|
||||
protected:
|
||||
|
|
|
@ -177,10 +177,9 @@ static inline WrBorderStyle ToWrBorderStyle(const uint8_t& style)
|
|||
return WrBorderStyle::None;
|
||||
}
|
||||
|
||||
static inline WrBorderSide ToWrBorderSide(const LayerCoord width, const gfx::Color& color, const uint8_t& style)
|
||||
static inline WrBorderSide ToWrBorderSide(const gfx::Color& color, const uint8_t& style)
|
||||
{
|
||||
WrBorderSide bs;
|
||||
bs.width = width;
|
||||
bs.color = ToWrColor(color);
|
||||
bs.style = ToWrBorderStyle(style);
|
||||
return bs;
|
||||
|
@ -194,9 +193,9 @@ static inline WrPoint ToWrPoint(const LayerPoint point)
|
|||
return lp;
|
||||
}
|
||||
|
||||
static inline WrLayoutSize ToWrLayoutSize(const LayerSize size)
|
||||
static inline WrSize ToWrSize(const LayerSize size)
|
||||
{
|
||||
WrLayoutSize ls;
|
||||
WrSize ls;
|
||||
ls.width = size.width;
|
||||
ls.height = size.height;
|
||||
return ls;
|
||||
|
@ -206,13 +205,71 @@ static inline WrBorderRadius ToWrBorderRadius(const LayerSize& topLeft, const La
|
|||
const LayerSize& bottomLeft, const LayerSize& bottomRight)
|
||||
{
|
||||
WrBorderRadius br;
|
||||
br.top_left = ToWrLayoutSize(topLeft);
|
||||
br.top_right = ToWrLayoutSize(topRight);
|
||||
br.bottom_left = ToWrLayoutSize(bottomLeft);
|
||||
br.bottom_right = ToWrLayoutSize(bottomRight);
|
||||
br.top_left = ToWrSize(topLeft);
|
||||
br.top_right = ToWrSize(topRight);
|
||||
br.bottom_left = ToWrSize(bottomLeft);
|
||||
br.bottom_right = ToWrSize(bottomRight);
|
||||
return br;
|
||||
}
|
||||
|
||||
static inline WrBorderWidths ToWrBorderWidths(float top, float right, float bottom, float left)
|
||||
{
|
||||
WrBorderWidths bw;
|
||||
bw.top = top;
|
||||
bw.right = right;
|
||||
bw.bottom = bottom;
|
||||
bw.left = left;
|
||||
return bw;
|
||||
}
|
||||
|
||||
static inline WrNinePatchDescriptor ToWrNinePatchDescriptor(uint32_t width, uint32_t height,
|
||||
const WrSideOffsets2Du32& slice)
|
||||
{
|
||||
WrNinePatchDescriptor patch;
|
||||
patch.width = width;
|
||||
patch.height = height;
|
||||
patch.slice = slice;
|
||||
return patch;
|
||||
}
|
||||
|
||||
static inline WrSideOffsets2Du32 ToWrSideOffsets2Du32(uint32_t top, uint32_t right, uint32_t bottom, uint32_t left)
|
||||
{
|
||||
WrSideOffsets2Du32 offset;
|
||||
offset.top = top;
|
||||
offset.right = right;
|
||||
offset.bottom = bottom;
|
||||
offset.left = left;
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline WrSideOffsets2Df32 ToWrSideOffsets2Df32(float top, float right, float bottom, float left)
|
||||
{
|
||||
WrSideOffsets2Df32 offset;
|
||||
offset.top = top;
|
||||
offset.right = right;
|
||||
offset.bottom = bottom;
|
||||
offset.left = left;
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline WrRepeatMode ToWrRepeatMode(uint8_t repeatMode)
|
||||
{
|
||||
switch (repeatMode) {
|
||||
case NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH:
|
||||
return WrRepeatMode::Stretch;
|
||||
case NS_STYLE_BORDER_IMAGE_REPEAT_REPEAT:
|
||||
return WrRepeatMode::Repeat;
|
||||
case NS_STYLE_BORDER_IMAGE_REPEAT_ROUND:
|
||||
return WrRepeatMode::Round;
|
||||
case NS_STYLE_BORDER_IMAGE_REPEAT_SPACE:
|
||||
return WrRepeatMode::Space;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
|
||||
return WrRepeatMode::Stretch;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static inline WrRect ToWrRect(const gfx::RectTyped<T>& rect)
|
||||
{
|
||||
|
@ -258,6 +315,22 @@ struct VecU8 {
|
|||
src.inner.capacity = 0;
|
||||
}
|
||||
|
||||
VecU8&
|
||||
operator=(VecU8&& src) {
|
||||
inner = src.inner;
|
||||
src.inner.data = nullptr;
|
||||
src.inner.capacity = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
WrVecU8
|
||||
Extract() {
|
||||
WrVecU8 ret = inner;
|
||||
inner.data = nullptr;
|
||||
inner.capacity = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
~VecU8() {
|
||||
if (inner.data) {
|
||||
wr_vec_u8_free(inner);
|
||||
|
|
|
@ -9,6 +9,7 @@ with Files('**'):
|
|||
|
||||
EXPORTS.mozilla.webrender += [
|
||||
'RendererOGL.h',
|
||||
'RenderTextureHost.h',
|
||||
'RenderThread.h',
|
||||
'webrender_ffi.h',
|
||||
'WebRenderAPI.h',
|
||||
|
@ -17,6 +18,7 @@ EXPORTS.mozilla.webrender += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'RendererOGL.cpp',
|
||||
'RenderTextureHost.cpp',
|
||||
'RenderThread.cpp',
|
||||
'WebRenderAPI.cpp',
|
||||
]
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -23,6 +23,9 @@ struct WrType { \
|
|||
bool operator<(const WrType& rhs) const { \
|
||||
return mHandle < rhs.mHandle; \
|
||||
} \
|
||||
bool operator<=(const WrType& rhs) const { \
|
||||
return mHandle <= rhs.mHandle; \
|
||||
} \
|
||||
}; \
|
||||
// ---
|
||||
|
||||
|
@ -115,14 +118,13 @@ enum class WrImageRendering: uint32_t
|
|||
Sentinel /* this must be last, for IPC serialization purposes */
|
||||
};
|
||||
|
||||
// TODO(Jerry): handle shmem or cpu raw buffers.
|
||||
//enum class WrExternalImageIdType: uint32_t
|
||||
//{
|
||||
// TextureHandle = 0,
|
||||
// MemOrShmem = 1,
|
||||
//
|
||||
// Sentinel /* this must be last, for IPC serialization purposes */
|
||||
//};
|
||||
enum class WrExternalImageIdType: uint32_t
|
||||
{
|
||||
NativeTexture, // Currently, we only support gl texture handle.
|
||||
RawData,
|
||||
|
||||
Sentinel /* this must be last, for IPC serialization purposes */
|
||||
};
|
||||
|
||||
enum class WrMixBlendMode: uint32_t
|
||||
{
|
||||
|
@ -154,6 +156,16 @@ enum class WrGradientExtendMode : uint32_t
|
|||
Sentinel /* this must be last, for IPC serialization purposes */
|
||||
};
|
||||
|
||||
enum class WrRepeatMode : uint32_t
|
||||
{
|
||||
Stretch = 0,
|
||||
Repeat = 1,
|
||||
Round = 2,
|
||||
Space = 3,
|
||||
|
||||
Sentinel /* this must be last, for IPC serialization purposes */
|
||||
};
|
||||
|
||||
// -----
|
||||
// Typedefs for struct fields and function signatures below.
|
||||
// -----
|
||||
|
@ -164,6 +176,60 @@ typedef uint64_t WrImageIdType;
|
|||
// Structs used in C++ code with corresponding types in Rust code
|
||||
// -----
|
||||
|
||||
struct WrItemRange
|
||||
{
|
||||
size_t start;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct WrBuiltDisplayListDescriptor {
|
||||
size_t display_list_items_size;
|
||||
};
|
||||
|
||||
struct WrAuxiliaryListsDescriptor {
|
||||
size_t gradient_stops_size;
|
||||
size_t complex_clip_regions_size;
|
||||
size_t filters_size;
|
||||
size_t glyph_instances_size;
|
||||
};
|
||||
|
||||
struct WrPoint
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
bool operator==(const WrPoint& aRhs) const {
|
||||
return x == aRhs.x && y == aRhs.y;
|
||||
}
|
||||
|
||||
operator mozilla::gfx::Point() const { return mozilla::gfx::Point(x, y); }
|
||||
};
|
||||
|
||||
struct WrSize
|
||||
{
|
||||
float width;
|
||||
float height;
|
||||
|
||||
bool operator==(const WrSize& aRhs) const
|
||||
{
|
||||
return width == aRhs.width && height == aRhs.height;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrRect
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float width;
|
||||
float height;
|
||||
|
||||
bool operator==(const WrRect& aRhs) const
|
||||
{
|
||||
return x == aRhs.x && y == aRhs.y &&
|
||||
width == aRhs.width && height == aRhs.height;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrColor
|
||||
{
|
||||
float r;
|
||||
|
@ -229,33 +295,20 @@ struct WrGradientStop {
|
|||
};
|
||||
|
||||
struct WrBorderSide {
|
||||
float width;
|
||||
WrColor color;
|
||||
WrBorderStyle style;
|
||||
|
||||
bool operator==(const WrBorderSide& aRhs) const
|
||||
{
|
||||
return width == aRhs.width && color == aRhs.color &&
|
||||
style == aRhs.style;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrLayoutSize
|
||||
{
|
||||
float width;
|
||||
float height;
|
||||
|
||||
bool operator==(const WrLayoutSize& aRhs) const
|
||||
{
|
||||
return width == aRhs.width && height == aRhs.height;
|
||||
return color == aRhs.color && style == aRhs.style;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrBorderRadius {
|
||||
WrLayoutSize top_left;
|
||||
WrLayoutSize top_right;
|
||||
WrLayoutSize bottom_left;
|
||||
WrLayoutSize bottom_right;
|
||||
WrSize top_left;
|
||||
WrSize top_right;
|
||||
WrSize bottom_left;
|
||||
WrSize bottom_right;
|
||||
|
||||
bool operator==(const WrBorderRadius& aRhs) const
|
||||
{
|
||||
|
@ -264,30 +317,55 @@ struct WrBorderRadius {
|
|||
}
|
||||
};
|
||||
|
||||
struct WrRect
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float width;
|
||||
float height;
|
||||
struct WrBorderWidths {
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
|
||||
bool operator==(const WrRect& aRhs) const
|
||||
bool operator==(const WrBorderWidths& aRhs) const
|
||||
{
|
||||
return x == aRhs.x && y == aRhs.y &&
|
||||
width == aRhs.width && height == aRhs.height;
|
||||
return left == aRhs.left && top == aRhs.top &&
|
||||
right == aRhs.right && bottom == aRhs.bottom;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrPoint
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
struct WrSideOffsets2Du32 {
|
||||
uint32_t top;
|
||||
uint32_t right;
|
||||
uint32_t bottom;
|
||||
uint32_t left;
|
||||
|
||||
bool operator==(const WrPoint& aRhs) const {
|
||||
return x == aRhs.x && y == aRhs.y;
|
||||
bool operator==(const WrSideOffsets2Du32& aRhs) const
|
||||
{
|
||||
return top == aRhs.top && right == aRhs.right &&
|
||||
bottom == aRhs.bottom && left == aRhs.left;
|
||||
}
|
||||
};
|
||||
|
||||
operator mozilla::gfx::Point() const { return mozilla::gfx::Point(x, y); }
|
||||
struct WrSideOffsets2Df32 {
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
float left;
|
||||
|
||||
bool operator==(const WrSideOffsets2Df32& aRhs) const
|
||||
{
|
||||
return top == aRhs.top && right == aRhs.right &&
|
||||
bottom == aRhs.bottom && left == aRhs.left;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrNinePatchDescriptor {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
WrSideOffsets2Du32 slice;
|
||||
|
||||
bool operator==(const WrNinePatchDescriptor& aRhs) const
|
||||
{
|
||||
return width == aRhs.width && height == aRhs.height &&
|
||||
slice == aRhs.slice;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrImageMask
|
||||
|
@ -302,6 +380,20 @@ struct WrImageMask
|
|||
}
|
||||
};
|
||||
|
||||
struct WrComplexClipRegion
|
||||
{
|
||||
WrRect rect;
|
||||
WrBorderRadius radii;
|
||||
};
|
||||
|
||||
struct WrClipRegion
|
||||
{
|
||||
WrRect main;
|
||||
WrItemRange complex;
|
||||
WrImageMask image_mask;
|
||||
bool has_image_mask;
|
||||
};
|
||||
|
||||
struct WrExternalImageId
|
||||
{
|
||||
WrImageIdType id;
|
||||
|
@ -309,7 +401,7 @@ struct WrExternalImageId
|
|||
|
||||
struct WrExternalImage
|
||||
{
|
||||
//WrExternalImageIdType type;
|
||||
WrExternalImageIdType type;
|
||||
|
||||
// Texture coordinate
|
||||
float u0, v0;
|
||||
|
@ -318,10 +410,9 @@ struct WrExternalImage
|
|||
// external buffer handle
|
||||
uint32_t handle;
|
||||
|
||||
// TODO(Jerry): handle shmem or cpu raw buffers.
|
||||
//// shmem or memory buffer
|
||||
//// uint8_t* buff;
|
||||
//// size_t size;
|
||||
// handle RawData.
|
||||
uint8_t* buff;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef WrExternalImage (*LockExternalImageCallback)(void*, WrExternalImageId);
|
||||
|
@ -344,17 +435,6 @@ struct WrImageDescriptor {
|
|||
bool is_opaque;
|
||||
};
|
||||
|
||||
struct WrBuiltDisplayListDescriptor {
|
||||
size_t display_list_items_size;
|
||||
};
|
||||
|
||||
struct WrAuxiliaryListsDescriptor {
|
||||
size_t gradient_stops_size;
|
||||
size_t complex_clip_regions_size;
|
||||
size_t filters_size;
|
||||
size_t glyph_instances_size;
|
||||
};
|
||||
|
||||
struct WrVecU8 {
|
||||
uint8_t *data;
|
||||
size_t length;
|
||||
|
@ -401,6 +481,13 @@ WR_INLINE void
|
|||
wr_renderer_render(WrRenderer* renderer, uint32_t width, uint32_t height)
|
||||
WR_FUNC;
|
||||
|
||||
// It is the responsibility of the caller to manage the dst_buffer memory
|
||||
// and also free it at the proper time.
|
||||
WR_INLINE const uint8_t*
|
||||
wr_renderer_readback(uint32_t width, uint32_t height,
|
||||
uint8_t* dst_buffer, size_t buffer_length)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_renderer_set_profiler_enabled(WrRenderer* renderer, bool enabled)
|
||||
WR_FUNC;
|
||||
|
@ -427,6 +514,8 @@ wr_rendered_epochs_delete(WrRenderedEpochs* pipeline_epochs) WR_DESTRUCTOR_SAFE_
|
|||
|
||||
WR_INLINE bool
|
||||
wr_window_new(WrWindowId window_id,
|
||||
uint32_t window_width,
|
||||
uint32_t window_height,
|
||||
void* aGLContext,
|
||||
bool enable_profiler,
|
||||
WrAPI** out_api,
|
||||
|
@ -447,8 +536,9 @@ wr_api_add_external_image_handle(WrAPI* api, WrImageKey key, uint32_t width, uin
|
|||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_add_external_image_buffer(WrAPI* api, WrImageKey key, uint32_t width, uint32_t height,
|
||||
WrImageFormat format, uint64_t external_image_id)
|
||||
wr_api_add_external_image_buffer(WrAPI* api, WrImageKey key,
|
||||
const WrImageDescriptor* descriptor,
|
||||
uint64_t external_image_id)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
|
@ -465,6 +555,10 @@ WR_INLINE void
|
|||
wr_api_set_root_pipeline(WrAPI* api, WrPipelineId pipeline_id)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_set_window_parameters(WrAPI* api, int width, int height)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_set_root_display_list(WrAPI* api, WrEpoch epoch, float w, float h,
|
||||
WrPipelineId pipeline_id,
|
||||
|
@ -476,6 +570,10 @@ wr_api_set_root_display_list(WrAPI* api, WrEpoch epoch, float w, float h,
|
|||
size_t aux_size)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_clear_root_display_list(WrAPI* api, WrEpoch epoch, WrPipelineId pipeline_id)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_generate_frame(WrAPI* api)
|
||||
WR_FUNC;
|
||||
|
@ -488,6 +586,10 @@ WR_INLINE void
|
|||
wr_api_add_raw_font(WrAPI* api, WrFontKey key, uint8_t* font_buffer, size_t buffer_size)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE WrIdNamespace
|
||||
wr_api_get_namespace(WrAPI* api)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE WrState*
|
||||
wr_state_new(WrPipelineId pipeline_id)
|
||||
WR_FUNC;
|
||||
|
@ -496,6 +598,21 @@ WR_INLINE void
|
|||
wr_state_delete(WrState* state)
|
||||
WR_DESTRUCTOR_SAFE_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_begin(WrState* wrState, uint32_t width, uint32_t height)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_end(WrState* wrState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE WrClipRegion
|
||||
wr_dp_new_clip_region(WrState* wrState,
|
||||
WrRect main,
|
||||
const WrComplexClipRegion* complex, size_t complexCount,
|
||||
const WrImageMask* image_mask)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_stacking_context(WrState *wrState, WrRect bounds,
|
||||
WrRect overflow, const WrImageMask *mask,
|
||||
|
@ -517,41 +634,50 @@ WR_INLINE void
|
|||
wr_dp_pop_scroll_layer(WrState *wrState)
|
||||
WR_FUNC;
|
||||
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_begin(WrState* wrState, uint32_t width, uint32_t height)
|
||||
wr_dp_push_iframe(WrState* wrState, WrRect bounds, WrClipRegion clip, WrPipelineId layers_id)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_end(WrState* wrState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_rect(WrState* wrState, WrRect bounds, WrRect clip,
|
||||
wr_dp_push_rect(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrColor color)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_text(WrState* wrState, WrRect bounds, WrRect clip, WrColor color,
|
||||
wr_dp_push_image(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrImageRendering filter, WrImageKey key)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_text(WrState* wrState, WrRect bounds, WrClipRegion clip, WrColor color,
|
||||
WrFontKey font_Key, const WrGlyphInstance* glyphs,
|
||||
uint32_t glyph_count, float glyph_size)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_border(WrState* wrState, WrRect bounds, WrRect clip,
|
||||
wr_dp_push_border(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrBorderWidths widths,
|
||||
WrBorderSide top, WrBorderSide right, WrBorderSide bottom, WrBorderSide left,
|
||||
WrBorderRadius radius)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_linear_gradient(WrState* wrState, WrRect bounds, WrRect clip,
|
||||
wr_dp_push_border_image(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrBorderWidths widths,
|
||||
WrImageKey image, WrNinePatchDescriptor patch, WrSideOffsets2Df32 outset,
|
||||
WrRepeatMode repeat_horizontal,
|
||||
WrRepeatMode repeat_vertical)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_linear_gradient(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrPoint startPoint, WrPoint endPoint,
|
||||
const WrGradientStop* stops, size_t stopsCount,
|
||||
WrGradientExtendMode extendMode)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_radial_gradient(WrState* wrState, WrRect bounds, WrRect clip,
|
||||
wr_dp_push_radial_gradient(WrState* wrState, WrRect bounds, WrClipRegion clip,
|
||||
WrPoint startCenter, WrPoint endCenter,
|
||||
float startRadius, float endRadius,
|
||||
const WrGradientStop* stops, size_t stopsCount,
|
||||
|
@ -559,32 +685,12 @@ wr_dp_push_radial_gradient(WrState* wrState, WrRect bounds, WrRect clip,
|
|||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_image(WrState* wrState, WrRect bounds, WrRect clip,
|
||||
const WrImageMask* mask, WrImageRendering filter, WrImageKey key)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_iframe(WrState* wrState, WrRect bounds, WrRect clip, WrPipelineId layers_id)
|
||||
WR_FUNC;
|
||||
|
||||
// It is the responsibility of the caller to manage the dst_buffer memory
|
||||
// and also free it at the proper time.
|
||||
WR_INLINE const uint8_t*
|
||||
wr_renderer_readback(uint32_t width, uint32_t height,
|
||||
uint8_t* dst_buffer, size_t buffer_length)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_box_shadow(WrState* wrState, WrRect rect, WrRect clip,
|
||||
wr_dp_push_box_shadow(WrState* wrState, WrRect rect, WrClipRegion clip,
|
||||
WrRect box_bounds, WrPoint offset, WrColor color,
|
||||
float blur_radius, float spread_radius, float border_radius,
|
||||
WrBoxShadowClipMode clip_mode)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE WrIdNamespace
|
||||
wr_api_get_namespace(WrAPI* api)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_api_finalize_builder(WrState* wrState,
|
||||
WrBuiltDisplayListDescriptor& dl_descriptor,
|
||||
|
@ -593,6 +699,14 @@ wr_api_finalize_builder(WrState* wrState,
|
|||
WrVecU8& aux_data)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_built_display_list(WrState* wrState,
|
||||
WrBuiltDisplayListDescriptor dl_descriptor,
|
||||
WrVecU8 dl_data,
|
||||
WrAuxiliaryListsDescriptor aux_descriptor,
|
||||
WrVecU8 aux_data)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_vec_u8_free(WrVecU8 dl_data)
|
||||
WR_FUNC;
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
[package]
|
||||
name = "webrender_traits"
|
||||
version = "0.20.0"
|
||||
version = "0.25.0"
|
||||
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/servo/webrender"
|
||||
build = "build.rs"
|
||||
|
||||
[features]
|
||||
default = ["codegen"]
|
||||
nightly = ["euclid/unstable", "serde/unstable"]
|
||||
codegen = ["serde_codegen", "serde_codegen/with-syntex"]
|
||||
ipc = ["ipc-channel"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -21,15 +18,10 @@ heapsize = "0.3.6"
|
|||
ipc-channel = {version = "0.7", optional = true}
|
||||
offscreen_gl_context = {version = "0.6", features = ["serde"]}
|
||||
serde = "0.9"
|
||||
serde_derive = {version = "0.9", optional = true}
|
||||
serde_derive = "0.9"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-graphics = "0.7"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
servo-dwrote = "0.2"
|
||||
|
||||
[build-dependencies.serde_codegen]
|
||||
version = "0.9"
|
||||
default_features = false
|
||||
optional = true
|
||||
dwrote = "0.3"
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[cfg(all(feature = "serde_codegen", not(feature = "serde_derive")))]
|
||||
mod inner {
|
||||
extern crate serde_codegen;
|
||||
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
|
||||
let src = Path::new("src/types.rs");
|
||||
let dst = Path::new(&out_dir).join("types.rs");
|
||||
|
||||
serde_codegen::expand(&src, &dst).unwrap();
|
||||
println!("cargo:rerun-if-changed=src/types.rs");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "serde_derive", not(feature = "serde_codegen")))]
|
||||
mod inner {
|
||||
pub fn main() {}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "serde_codegen", feature = "serde_derive"))]
|
||||
mod inner {
|
||||
pub fn main() {
|
||||
panic!("serde_codegen and serde_derive are both used. \
|
||||
You probably forgot --no-default-features.")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "serde_codegen", feature = "serde_derive")))]
|
||||
mod inner {
|
||||
pub fn main() {
|
||||
panic!("Neither serde_codegen nor serde_derive are used. "
|
||||
"You probably want --features serde_derive --no-default-features.")
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
inner::main();
|
||||
}
|
|
@ -6,16 +6,136 @@ use byteorder::{LittleEndian, WriteBytesExt};
|
|||
use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
|
||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||
use std::cell::Cell;
|
||||
use {ApiMsg, ColorF, DisplayListBuilder, Epoch, ImageDescriptor};
|
||||
use {FontKey, IdNamespace, ImageKey, NativeFontHandle, PipelineId};
|
||||
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId};
|
||||
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand, TileSize};
|
||||
use {DeviceIntSize, DynamicProperties, LayoutPoint, LayoutSize, WorldPoint, PropertyBindingKey, PropertyBindingId};
|
||||
use {BuiltDisplayList, AuxiliaryLists};
|
||||
use VRCompositorCommand;
|
||||
use ExternalEvent;
|
||||
use {ColorF, ImageDescriptor};
|
||||
use {FontKey, ImageKey, NativeFontHandle, ServoScrollRootId};
|
||||
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};
|
||||
use {DeviceIntSize, LayoutPoint, LayoutSize, WorldPoint};
|
||||
use {DeviceIntPoint, DeviceUintRect, DeviceUintSize, LayoutTransform};
|
||||
use {BuiltDisplayList, BuiltDisplayListDescriptor, AuxiliaryLists, AuxiliaryListsDescriptor};
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub type TileSize = u16;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum ApiMsg {
|
||||
AddRawFont(FontKey, Vec<u8>),
|
||||
AddNativeFont(FontKey, NativeFontHandle),
|
||||
DeleteFont(FontKey),
|
||||
/// Gets the glyph dimensions
|
||||
GetGlyphDimensions(Vec<GlyphKey>, MsgSender<Vec<Option<GlyphDimensions>>>),
|
||||
/// Adds an image from the resource cache.
|
||||
AddImage(ImageKey, ImageDescriptor, ImageData, Option<TileSize>),
|
||||
/// Updates the the resource cache with the new image data.
|
||||
UpdateImage(ImageKey, ImageDescriptor, Vec<u8>),
|
||||
/// Drops an image from the resource cache.
|
||||
DeleteImage(ImageKey),
|
||||
CloneApi(MsgSender<IdNamespace>),
|
||||
/// Supplies a new frame to WebRender.
|
||||
///
|
||||
/// After receiving this message, WebRender will read the display list, followed by the
|
||||
/// auxiliary lists, from the payload channel.
|
||||
SetRootDisplayList(Option<ColorF>,
|
||||
Epoch,
|
||||
PipelineId,
|
||||
LayoutSize,
|
||||
BuiltDisplayListDescriptor,
|
||||
AuxiliaryListsDescriptor,
|
||||
bool),
|
||||
SetPageZoom(ZoomFactor),
|
||||
SetPinchZoom(ZoomFactor),
|
||||
SetPan(DeviceIntPoint),
|
||||
SetRootPipeline(PipelineId),
|
||||
SetWindowParameters(DeviceUintSize, DeviceUintRect),
|
||||
Scroll(ScrollLocation, WorldPoint, ScrollEventPhase),
|
||||
ScrollLayersWithScrollId(LayoutPoint, PipelineId, ServoScrollRootId),
|
||||
TickScrollingBounce,
|
||||
TranslatePointToLayerSpace(WorldPoint, MsgSender<(LayoutPoint, PipelineId)>),
|
||||
GetScrollLayerState(MsgSender<Vec<ScrollLayerState>>),
|
||||
RequestWebGLContext(DeviceIntSize, GLContextAttributes, MsgSender<Result<(WebGLContextId, GLLimits), String>>),
|
||||
ResizeWebGLContext(WebGLContextId, DeviceIntSize),
|
||||
WebGLCommand(WebGLContextId, WebGLCommand),
|
||||
GenerateFrame(Option<DynamicProperties>),
|
||||
// WebVR commands that must be called in the WebGL render thread.
|
||||
VRCompositorCommand(WebGLContextId, VRCompositorCommand),
|
||||
/// An opaque handle that must be passed to the render notifier. It is used by Gecko
|
||||
/// to forward gecko-specific messages to the render thread preserving the ordering
|
||||
/// within the other messages.
|
||||
ExternalEvent(ExternalEvent),
|
||||
ShutDown,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ApiMsg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&ApiMsg::AddRawFont(..) => { write!(f, "ApiMsg::AddRawFont") }
|
||||
&ApiMsg::AddNativeFont(..) => { write!(f, "ApiMsg::AddNativeFont") }
|
||||
&ApiMsg::DeleteFont(..) => { write!(f, "ApiMsg::DeleteFont") }
|
||||
&ApiMsg::GetGlyphDimensions(..) => { write!(f, "ApiMsg::GetGlyphDimensions") }
|
||||
&ApiMsg::AddImage(..) => { write!(f, "ApiMsg::AddImage") }
|
||||
&ApiMsg::UpdateImage(..) => { write!(f, "ApiMsg::UpdateImage") }
|
||||
&ApiMsg::DeleteImage(..) => { write!(f, "ApiMsg::DeleteImage") }
|
||||
&ApiMsg::CloneApi(..) => { write!(f, "ApiMsg::CloneApi") }
|
||||
&ApiMsg::SetRootDisplayList(..) => { write!(f, "ApiMsg::SetRootDisplayList") }
|
||||
&ApiMsg::SetRootPipeline(..) => { write!(f, "ApiMsg::SetRootPipeline") }
|
||||
&ApiMsg::Scroll(..) => { write!(f, "ApiMsg::Scroll") }
|
||||
&ApiMsg::ScrollLayersWithScrollId(..) => { write!(f, "ApiMsg::ScrollLayersWithScrollId") }
|
||||
&ApiMsg::TickScrollingBounce => { write!(f, "ApiMsg::TickScrollingBounce") }
|
||||
&ApiMsg::TranslatePointToLayerSpace(..) => { write!(f, "ApiMsg::TranslatePointToLayerSpace") }
|
||||
&ApiMsg::GetScrollLayerState(..) => { write!(f, "ApiMsg::GetScrollLayerState") }
|
||||
&ApiMsg::RequestWebGLContext(..) => { write!(f, "ApiMsg::RequestWebGLContext") }
|
||||
&ApiMsg::ResizeWebGLContext(..) => { write!(f, "ApiMsg::ResizeWebGLContext") }
|
||||
&ApiMsg::WebGLCommand(..) => { write!(f, "ApiMsg::WebGLCommand") }
|
||||
&ApiMsg::GenerateFrame(..) => { write!(f, "ApiMsg::GenerateFrame") }
|
||||
&ApiMsg::VRCompositorCommand(..) => { write!(f, "ApiMsg::VRCompositorCommand") }
|
||||
&ApiMsg::ExternalEvent(..) => { write!(f, "ApiMsg::ExternalEvent") }
|
||||
&ApiMsg::ShutDown => { write!(f, "ApiMsg::ShutDown") }
|
||||
&ApiMsg::SetPageZoom(..) => { write!(f, "ApiMsg::SetPageZoom") }
|
||||
&ApiMsg::SetPinchZoom(..) => { write!(f, "ApiMsg::SetPinchZoom") }
|
||||
&ApiMsg::SetPan(..) => { write!(f, "ApiMsg::SetPan") }
|
||||
&ApiMsg::SetWindowParameters(..) => { write!(f, "ApiMsg::SetWindowParameters") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct Epoch(pub u32);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct PipelineId(pub u32, pub u32);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub struct IdNamespace(pub u32);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub struct ResourceId(pub u32);
|
||||
|
||||
/// An opaque pointer-sized value.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct ExternalEvent {
|
||||
raw: usize,
|
||||
}
|
||||
|
||||
unsafe impl Send for ExternalEvent {}
|
||||
|
||||
impl ExternalEvent {
|
||||
pub fn from_raw(raw: usize) -> Self { ExternalEvent { raw: raw } }
|
||||
/// Consumes self to make it obvious that the event should be forwarded only once.
|
||||
pub fn unwrap(self) -> usize { self.raw }
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct RenderApiSender {
|
||||
api_sender: MsgSender<ApiMsg>,
|
||||
payload_sender: PayloadSender,
|
||||
}
|
||||
|
||||
impl RenderApiSender {
|
||||
pub fn new(api_sender: MsgSender<ApiMsg>,
|
||||
payload_sender: PayloadSender)
|
||||
|
@ -70,6 +190,11 @@ impl RenderApi {
|
|||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn delete_font(&self, key: FontKey) {
|
||||
let msg = ApiMsg::DeleteFont(key);
|
||||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
/// Gets the dimensions for the supplied glyph keys
|
||||
///
|
||||
/// Note: Internally, the internal texture cache doesn't store
|
||||
|
@ -193,6 +318,28 @@ impl RenderApi {
|
|||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn set_page_zoom(&self, page_zoom: ZoomFactor) {
|
||||
let msg = ApiMsg::SetPageZoom(page_zoom);
|
||||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn set_pinch_zoom(&self, pinch_zoom: ZoomFactor) {
|
||||
let msg = ApiMsg::SetPinchZoom(pinch_zoom);
|
||||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn set_pan(&self, pan: DeviceIntPoint) {
|
||||
let msg = ApiMsg::SetPan(pan);
|
||||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn set_window_parameters(&self,
|
||||
window_size: DeviceUintSize,
|
||||
inner_rect: DeviceUintRect) {
|
||||
let msg = ApiMsg::SetWindowParameters(window_size, inner_rect);
|
||||
self.api_sender.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn tick_scrolling_bounce_animations(&self) {
|
||||
let msg = ApiMsg::TickScrollingBounce;
|
||||
self.api_sender.send(msg).unwrap();
|
||||
|
@ -275,3 +422,139 @@ impl RenderApi {
|
|||
(namespace, id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum ScrollEventPhase {
|
||||
/// The user started scrolling.
|
||||
Start,
|
||||
/// The user performed a scroll. The Boolean flag indicates whether the user's fingers are
|
||||
/// down, if a touchpad is in use. (If false, the event is a touchpad fling.)
|
||||
Move(bool),
|
||||
/// The user ended scrolling.
|
||||
End,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct ScrollLayerState {
|
||||
pub pipeline_id: PipelineId,
|
||||
pub scroll_root_id: ServoScrollRootId,
|
||||
pub scroll_offset: LayoutPoint,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub enum ScrollLocation {
|
||||
/// Scroll by a certain amount.
|
||||
Delta(LayoutPoint),
|
||||
/// Scroll to very top of element.
|
||||
Start,
|
||||
/// Scroll to very bottom of element.
|
||||
End
|
||||
}
|
||||
|
||||
/// Represents a zoom factor.
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub struct ZoomFactor(f32);
|
||||
|
||||
impl ZoomFactor {
|
||||
/// Construct a new zoom factor.
|
||||
pub fn new(scale: f32) -> ZoomFactor {
|
||||
ZoomFactor(scale)
|
||||
}
|
||||
|
||||
/// Get the zoom factor as an untyped float.
|
||||
pub fn get(&self) -> f32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)]
|
||||
pub struct PropertyBindingId {
|
||||
namespace: u32,
|
||||
uid: u32,
|
||||
}
|
||||
|
||||
/// A unique key that is used for connecting animated property
|
||||
/// values to bindings in the display list.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PropertyBindingKey<T> {
|
||||
pub id: PropertyBindingId,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Construct a property value from a given key and value.
|
||||
impl<T: Copy> PropertyBindingKey<T> {
|
||||
pub fn with(&self, value: T) -> PropertyValue<T> {
|
||||
PropertyValue {
|
||||
key: *self,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A binding property can either be a specific value
|
||||
/// (the normal, non-animated case) or point to a binding location
|
||||
/// to fetch the current value from.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum PropertyBinding<T> {
|
||||
Value(T),
|
||||
Binding(PropertyBindingKey<T>),
|
||||
}
|
||||
|
||||
impl<T> From<T> for PropertyBinding<T> {
|
||||
fn from(value: T) -> PropertyBinding<T> {
|
||||
PropertyBinding::Value(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<PropertyBindingKey<T>> for PropertyBinding<T> {
|
||||
fn from(key: PropertyBindingKey<T>) -> PropertyBinding<T> {
|
||||
PropertyBinding::Binding(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// The current value of an animated property. This is
|
||||
/// supplied by the calling code.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub struct PropertyValue<T> {
|
||||
pub key: PropertyBindingKey<T>,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// When using generate_frame(), a list of PropertyValue structures
|
||||
/// can optionally be supplied to provide the current value of any
|
||||
/// animated properties.
|
||||
#[derive(Clone, Deserialize, Serialize, Debug)]
|
||||
pub struct DynamicProperties {
|
||||
pub transforms: Vec<PropertyValue<LayoutTransform>>,
|
||||
pub floats: Vec<PropertyValue<f32>>,
|
||||
}
|
||||
|
||||
pub type VRCompositorId = u64;
|
||||
|
||||
// WebVR commands that must be called in the WebGL render thread.
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum VRCompositorCommand {
|
||||
Create(VRCompositorId),
|
||||
SyncPoses(VRCompositorId, f64, f64, MsgSender<Result<Vec<u8>,()>>),
|
||||
SubmitFrame(VRCompositorId, [f32; 4], [f32; 4]),
|
||||
Release(VRCompositorId)
|
||||
}
|
||||
|
||||
// Trait object that handles WebVR commands.
|
||||
// Receives the texture_id associated to the WebGLContext.
|
||||
pub trait VRCompositorHandler: Send {
|
||||
fn handle(&mut self, command: VRCompositorCommand, texture_id: Option<u32>);
|
||||
}
|
||||
|
||||
pub trait RenderNotifier: Send {
|
||||
fn new_frame_ready(&mut self);
|
||||
fn new_scroll_frame_ready(&mut self, composite_needed: bool);
|
||||
fn external_event(&mut self, _evt: ExternalEvent) { unimplemented!() }
|
||||
fn shut_down(&mut self) {}
|
||||
}
|
||||
|
||||
// Trait to allow dispatching functions to a specific thread or event loop.
|
||||
pub trait RenderDispatcher: Send {
|
||||
fn dispatch(&self, Box<Fn() + Send>);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ColorF {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
known_heap_size!(0, ColorF);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, PartialEq, PartialOrd, Ord, Serialize)]
|
||||
pub struct ColorU {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
impl From<ColorF> for ColorU {
|
||||
fn from(color: ColorF) -> ColorU {
|
||||
ColorU {
|
||||
r: ColorU::round_to_int(color.r),
|
||||
g: ColorU::round_to_int(color.g),
|
||||
b: ColorU::round_to_int(color.b),
|
||||
a: ColorU::round_to_int(color.a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ColorF> for ColorU {
|
||||
fn into(self) -> ColorF {
|
||||
ColorF {
|
||||
r: self.r as f32 / 255.0,
|
||||
g: self.g as f32 / 255.0,
|
||||
b: self.b as f32 / 255.0,
|
||||
a: self.a as f32 / 255.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorU {
|
||||
fn round_to_int(x: f32) -> u8 {
|
||||
debug_assert!((0.0 <= x) && (x <= 1.0));
|
||||
let f = (255.0 * x) + 0.5;
|
||||
let val = f.floor();
|
||||
debug_assert!(val <= 255.0);
|
||||
val as u8
|
||||
}
|
||||
|
||||
pub fn new(r: u8, g: u8, b: u8, a: u8) -> ColorU {
|
||||
ColorU {
|
||||
r: r,
|
||||
g: g,
|
||||
b: b,
|
||||
a: a,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,379 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::SideOffsets2D;
|
||||
use display_list::AuxiliaryListsBuilder;
|
||||
use {BorderRadius, ClipRegion, ColorF, ComplexClipRegion};
|
||||
use {FontKey, ImageKey, PipelineId, ScrollLayerId, ScrollLayerInfo, ServoScrollRootId};
|
||||
use {ImageMask, ItemRange};
|
||||
use {LayoutSize, LayoutPoint, LayoutRect};
|
||||
use {ColorF, FontKey, ImageKey, PipelineId, WebGLContextId};
|
||||
use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use {PropertyBinding};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct DisplayItem {
|
||||
pub item: SpecificDisplayItem,
|
||||
pub rect: LayoutRect,
|
||||
pub clip: ClipRegion,
|
||||
pub scroll_layer_id: ScrollLayerId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum SpecificDisplayItem {
|
||||
Clip(ClipDisplayItem),
|
||||
Rectangle(RectangleDisplayItem),
|
||||
Text(TextDisplayItem),
|
||||
Image(ImageDisplayItem),
|
||||
YuvImage(YuvImageDisplayItem),
|
||||
WebGL(WebGLDisplayItem),
|
||||
Border(BorderDisplayItem),
|
||||
BoxShadow(BoxShadowDisplayItem),
|
||||
Gradient(GradientDisplayItem),
|
||||
RadialGradient(RadialGradientDisplayItem),
|
||||
Iframe(IframeDisplayItem),
|
||||
PushStackingContext(PushStackingContextDisplayItem),
|
||||
PopStackingContext,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ItemRange {
|
||||
pub start: usize,
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ClipDisplayItem {
|
||||
pub content_size: LayoutSize,
|
||||
pub id: ScrollLayerId,
|
||||
pub parent_id: ScrollLayerId,
|
||||
pub scroll_root_id: Option<ServoScrollRootId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RectangleDisplayItem {
|
||||
pub color: ColorF,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct TextDisplayItem {
|
||||
pub glyphs: ItemRange,
|
||||
pub font_key: FontKey,
|
||||
pub size: Au,
|
||||
pub color: ColorF,
|
||||
pub blur_radius: Au,
|
||||
pub glyph_options: Option<GlyphOptions>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
|
||||
pub struct GlyphOptions {
|
||||
// These are currently only used on windows for dwrite fonts.
|
||||
pub use_embedded_bitmap: bool,
|
||||
pub force_gdi_rendering: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct WebGLDisplayItem {
|
||||
pub context_id: WebGLContextId,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NormalBorder {
|
||||
pub left: BorderSide,
|
||||
pub right: BorderSide,
|
||||
pub top: BorderSide,
|
||||
pub bottom: BorderSide,
|
||||
pub radius: BorderRadius,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum RepeatMode {
|
||||
Stretch,
|
||||
Repeat,
|
||||
Round,
|
||||
Space,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NinePatchDescriptor {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub slice: SideOffsets2D<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ImageBorder {
|
||||
pub image_key: ImageKey,
|
||||
pub patch: NinePatchDescriptor,
|
||||
pub outset: SideOffsets2D<f32>,
|
||||
pub repeat_horizontal: RepeatMode,
|
||||
pub repeat_vertical: RepeatMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GradientBorder {
|
||||
pub gradient: Gradient,
|
||||
pub outset: SideOffsets2D<f32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradientBorder {
|
||||
pub gradient: RadialGradient,
|
||||
pub outset: SideOffsets2D<f32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum BorderDetails {
|
||||
Normal(NormalBorder),
|
||||
Image(ImageBorder),
|
||||
Gradient(GradientBorder),
|
||||
RadialGradient(RadialGradientBorder),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BorderDisplayItem {
|
||||
pub widths: BorderWidths,
|
||||
pub details: BorderDetails,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BorderRadius {
|
||||
pub top_left: LayoutSize,
|
||||
pub top_right: LayoutSize,
|
||||
pub bottom_left: LayoutSize,
|
||||
pub bottom_right: LayoutSize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BorderWidths {
|
||||
pub left: f32,
|
||||
pub top: f32,
|
||||
pub right: f32,
|
||||
pub bottom: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BorderSide {
|
||||
pub color: ColorF,
|
||||
pub style: BorderStyle,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum BorderStyle {
|
||||
None = 0,
|
||||
Solid = 1,
|
||||
Double = 2,
|
||||
Dotted = 3,
|
||||
Dashed = 4,
|
||||
Hidden = 5,
|
||||
Groove = 6,
|
||||
Ridge = 7,
|
||||
Inset = 8,
|
||||
Outset = 9,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum BoxShadowClipMode {
|
||||
None = 0,
|
||||
Outset = 1,
|
||||
Inset = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BoxShadowDisplayItem {
|
||||
pub box_bounds: LayoutRect,
|
||||
pub offset: LayoutPoint,
|
||||
pub color: ColorF,
|
||||
pub blur_radius: f32,
|
||||
pub spread_radius: f32,
|
||||
pub border_radius: f32,
|
||||
pub clip_mode: BoxShadowClipMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub enum ExtendMode {
|
||||
Clamp,
|
||||
Repeat,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Gradient {
|
||||
pub start_point: LayoutPoint,
|
||||
pub end_point: LayoutPoint,
|
||||
pub stops: ItemRange,
|
||||
pub extend_mode: ExtendMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GradientDisplayItem {
|
||||
pub gradient: Gradient,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GradientStop {
|
||||
pub offset: f32,
|
||||
pub color: ColorF,
|
||||
}
|
||||
known_heap_size!(0, GradientStop);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradient {
|
||||
pub start_center: LayoutPoint,
|
||||
pub start_radius: f32,
|
||||
pub end_center: LayoutPoint,
|
||||
pub end_radius: f32,
|
||||
pub stops: ItemRange,
|
||||
pub extend_mode: ExtendMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradientDisplayItem {
|
||||
pub gradient: RadialGradient,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushStackingContextDisplayItem {
|
||||
pub stacking_context: StackingContext,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StackingContext {
|
||||
pub scroll_policy: ScrollPolicy,
|
||||
pub bounds: LayoutRect,
|
||||
pub z_index: i32,
|
||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
pub perspective: Option<LayoutTransform>,
|
||||
pub mix_blend_mode: MixBlendMode,
|
||||
pub filters: ItemRange,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum ScrollPolicy {
|
||||
Scrollable = 0,
|
||||
Fixed = 1,
|
||||
}
|
||||
|
||||
known_heap_size!(0, ScrollPolicy);
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum MixBlendMode {
|
||||
Normal = 0,
|
||||
Multiply = 1,
|
||||
Screen = 2,
|
||||
Overlay = 3,
|
||||
Darken = 4,
|
||||
Lighten = 5,
|
||||
ColorDodge = 6,
|
||||
ColorBurn = 7,
|
||||
HardLight = 8,
|
||||
SoftLight = 9,
|
||||
Difference = 10,
|
||||
Exclusion = 11,
|
||||
Hue = 12,
|
||||
Saturation = 13,
|
||||
Color = 14,
|
||||
Luminosity = 15,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub enum FilterOp {
|
||||
Blur(Au),
|
||||
Brightness(f32),
|
||||
Contrast(f32),
|
||||
Grayscale(f32),
|
||||
HueRotate(f32),
|
||||
Invert(f32),
|
||||
Opacity(PropertyBinding<f32>),
|
||||
Saturate(f32),
|
||||
Sepia(f32),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IframeDisplayItem {
|
||||
pub pipeline_id: PipelineId,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ImageDisplayItem {
|
||||
pub image_key: ImageKey,
|
||||
pub stretch_size: LayoutSize,
|
||||
pub tile_spacing: LayoutSize,
|
||||
pub image_rendering: ImageRendering,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ImageRendering {
|
||||
Auto = 0,
|
||||
CrispEdges = 1,
|
||||
Pixelated = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct YuvImageDisplayItem {
|
||||
pub y_image_key: ImageKey,
|
||||
pub u_image_key: ImageKey,
|
||||
pub v_image_key: ImageKey,
|
||||
pub color_space: YuvColorSpace,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum YuvColorSpace {
|
||||
Rec601 = 1, // The values must match the ones in prim_shared.glsl
|
||||
Rec709 = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ImageMask {
|
||||
pub image: ImageKey,
|
||||
pub rect: LayoutRect,
|
||||
pub repeat: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ClipRegion {
|
||||
pub main: LayoutRect,
|
||||
pub complex: ItemRange,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ComplexClipRegion {
|
||||
/// The boundaries of the rectangle.
|
||||
pub rect: LayoutRect,
|
||||
/// Border radii of this rectangle.
|
||||
pub radii: BorderRadius,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
pub fn new(scroll_policy: ScrollPolicy,
|
||||
bounds: LayoutRect,
|
||||
z_index: i32,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: Vec<FilterOp>,
|
||||
auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
|
||||
-> StackingContext {
|
||||
StackingContext {
|
||||
scroll_policy: scroll_policy,
|
||||
bounds: bounds,
|
||||
z_index: z_index,
|
||||
transform: transform,
|
||||
perspective: perspective,
|
||||
mix_blend_mode: mix_blend_mode,
|
||||
filters: auxiliary_lists_builder.add_filters(&filters),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BorderRadius {
|
||||
pub fn zero() -> BorderRadius {
|
||||
|
@ -141,26 +509,48 @@ impl ComplexClipRegion {
|
|||
}
|
||||
}
|
||||
|
||||
impl FontKey {
|
||||
pub fn new(key0: u32, key1: u32) -> FontKey {
|
||||
FontKey(key0, key1)
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ServoScrollRootId(pub usize);
|
||||
|
||||
impl ImageKey {
|
||||
pub fn new(key0: u32, key1: u32) -> ImageKey {
|
||||
ImageKey(key0, key1)
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ScrollLayerId {
|
||||
pub pipeline_id: PipelineId,
|
||||
pub info: ScrollLayerInfo,
|
||||
}
|
||||
|
||||
impl ScrollLayerId {
|
||||
pub fn new(pipeline_id: PipelineId,
|
||||
index: usize,
|
||||
scroll_root_id: ServoScrollRootId)
|
||||
-> ScrollLayerId {
|
||||
pub fn root_scroll_layer(pipeline_id: PipelineId) -> ScrollLayerId {
|
||||
ScrollLayerId {
|
||||
pipeline_id: pipeline_id,
|
||||
info: ScrollLayerInfo::Scrollable(index, scroll_root_id),
|
||||
info: ScrollLayerInfo::Scrollable(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> ScrollLayerId {
|
||||
ScrollLayerId {
|
||||
pipeline_id: pipeline_id,
|
||||
info: ScrollLayerInfo::ReferenceFrame(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_reference_frame(&self) -> bool {
|
||||
match self.info {
|
||||
ScrollLayerInfo::Scrollable(..) => false,
|
||||
ScrollLayerInfo::ReferenceFrame(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(pipeline_id: PipelineId, index: usize) -> ScrollLayerId {
|
||||
ScrollLayerId {
|
||||
pipeline_id: pipeline_id,
|
||||
info: ScrollLayerInfo::Scrollable(index),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ScrollLayerInfo {
|
||||
Scrollable(usize),
|
||||
ReferenceFrame(usize),
|
||||
}
|
||||
|
|
|
@ -5,17 +5,54 @@
|
|||
use app_units::Au;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
use {AuxiliaryLists, AuxiliaryListsDescriptor, BorderDisplayItem};
|
||||
use {BoxShadowClipMode, BoxShadowDisplayItem, BuiltDisplayList};
|
||||
use {BuiltDisplayListDescriptor, ClipRegion, ComplexClipRegion, ColorF};
|
||||
use {DisplayItem, ExtendMode, FilterOp, YuvColorSpace};
|
||||
use {FontKey, GlyphInstance, GradientDisplayItem, RadialGradientDisplayItem, GradientStop, IframeDisplayItem};
|
||||
use {ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange, MixBlendMode, PipelineId};
|
||||
use {PushScrollLayerItem, PushStackingContextDisplayItem, RectangleDisplayItem, ScrollLayerId};
|
||||
use {ScrollPolicy, ServoScrollRootId, SpecificDisplayItem, StackingContext, TextDisplayItem};
|
||||
use {WebGLContextId, WebGLDisplayItem, YuvImageDisplayItem};
|
||||
use {LayoutTransform, LayoutPoint, LayoutRect, LayoutSize};
|
||||
use {BorderDetails, BorderWidths, GlyphOptions, PropertyBinding};
|
||||
use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem};
|
||||
use {ClipDisplayItem, ClipRegion, ColorF, ComplexClipRegion, DisplayItem, ExtendMode, FilterOp};
|
||||
use {FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem, GradientStop};
|
||||
use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange};
|
||||
use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, MixBlendMode, PipelineId};
|
||||
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
|
||||
use {RectangleDisplayItem, ScrollLayerId, ScrollPolicy, ServoScrollRootId, SpecificDisplayItem};
|
||||
use {StackingContext, TextDisplayItem, WebGLContextId, WebGLDisplayItem, YuvColorSpace};
|
||||
use YuvImageDisplayItem;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct AuxiliaryLists {
|
||||
/// The concatenation of: gradient stops, complex clip regions, filters, and glyph instances,
|
||||
/// in that order.
|
||||
data: Vec<u8>,
|
||||
descriptor: AuxiliaryListsDescriptor,
|
||||
}
|
||||
|
||||
/// Describes the memory layout of the auxiliary lists.
|
||||
///
|
||||
/// Auxiliary lists consist of some number of gradient stops, complex clip regions, filters, and
|
||||
/// glyph instances, in that order.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub struct AuxiliaryListsDescriptor {
|
||||
gradient_stops_size: usize,
|
||||
complex_clip_regions_size: usize,
|
||||
filters_size: usize,
|
||||
glyph_instances_size: usize,
|
||||
}
|
||||
|
||||
/// A display list.
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct BuiltDisplayList {
|
||||
data: Vec<u8>,
|
||||
descriptor: BuiltDisplayListDescriptor,
|
||||
}
|
||||
|
||||
/// Describes the memory layout of a display list.
|
||||
///
|
||||
/// A display list consists of some number of display list items, followed by a number of display
|
||||
/// items.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Deserialize, Serialize)]
|
||||
pub struct BuiltDisplayListDescriptor {
|
||||
/// The size in bytes of the display list items in this display list.
|
||||
display_list_items_size: usize,
|
||||
}
|
||||
|
||||
impl BuiltDisplayListDescriptor {
|
||||
pub fn size(&self) -> usize {
|
||||
|
@ -51,6 +88,7 @@ pub struct DisplayListBuilder {
|
|||
pub list: Vec<DisplayItem>,
|
||||
auxiliary_lists_builder: AuxiliaryListsBuilder,
|
||||
pub pipeline_id: PipelineId,
|
||||
clip_stack: Vec<ScrollLayerId>,
|
||||
next_scroll_layer_id: usize,
|
||||
}
|
||||
|
||||
|
@ -60,7 +98,10 @@ impl DisplayListBuilder {
|
|||
list: Vec::new(),
|
||||
auxiliary_lists_builder: AuxiliaryListsBuilder::new(),
|
||||
pipeline_id: pipeline_id,
|
||||
next_scroll_layer_id: 0,
|
||||
clip_stack: vec![ScrollLayerId::root_scroll_layer(pipeline_id)],
|
||||
|
||||
// We start at 1 here, because the root scroll id is always 0.
|
||||
next_scroll_layer_id: 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,21 +111,33 @@ impl DisplayListBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn push_item(&mut self, item: SpecificDisplayItem, rect: LayoutRect, clip: ClipRegion) {
|
||||
self.list.push(DisplayItem {
|
||||
item: item,
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
scroll_layer_id: *self.clip_stack.last().unwrap(),
|
||||
});
|
||||
}
|
||||
|
||||
fn push_new_empty_item(&mut self, item: SpecificDisplayItem) {
|
||||
self.list.push(DisplayItem {
|
||||
item: item,
|
||||
rect: LayoutRect::zero(),
|
||||
clip: ClipRegion::simple(&LayoutRect::zero()),
|
||||
scroll_layer_id: *self.clip_stack.last().unwrap(),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn push_rect(&mut self,
|
||||
rect: LayoutRect,
|
||||
clip: ClipRegion,
|
||||
color: ColorF) {
|
||||
let item = RectangleDisplayItem {
|
||||
let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem {
|
||||
color: color,
|
||||
};
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::Rectangle(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_image(&mut self,
|
||||
|
@ -94,20 +147,14 @@ impl DisplayListBuilder {
|
|||
tile_spacing: LayoutSize,
|
||||
image_rendering: ImageRendering,
|
||||
key: ImageKey) {
|
||||
let item = ImageDisplayItem {
|
||||
let item = SpecificDisplayItem::Image(ImageDisplayItem {
|
||||
image_key: key,
|
||||
stretch_size: stretch_size,
|
||||
tile_spacing: tile_spacing,
|
||||
image_rendering: image_rendering,
|
||||
};
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::Image(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_yuv_image(&mut self,
|
||||
|
@ -117,33 +164,23 @@ impl DisplayListBuilder {
|
|||
u_key: ImageKey,
|
||||
v_key: ImageKey,
|
||||
color_space: YuvColorSpace) {
|
||||
self.list.push(DisplayItem {
|
||||
item: SpecificDisplayItem::YuvImage(YuvImageDisplayItem {
|
||||
let item = SpecificDisplayItem::YuvImage(YuvImageDisplayItem {
|
||||
y_image_key: y_key,
|
||||
u_image_key: u_key,
|
||||
v_image_key: v_key,
|
||||
color_space: color_space,
|
||||
}),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
});
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_webgl_canvas(&mut self,
|
||||
rect: LayoutRect,
|
||||
clip: ClipRegion,
|
||||
context_id: WebGLContextId) {
|
||||
let item = WebGLDisplayItem {
|
||||
let item = SpecificDisplayItem::WebGL(WebGLDisplayItem {
|
||||
context_id: context_id,
|
||||
};
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::WebGL(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
});
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_text(&mut self,
|
||||
|
@ -162,22 +199,46 @@ impl DisplayListBuilder {
|
|||
// font as a crash test - the rendering is also ignored
|
||||
// by the azure renderer.
|
||||
if size < Au::from_px(4096) {
|
||||
let item = TextDisplayItem {
|
||||
let item = SpecificDisplayItem::Text(TextDisplayItem {
|
||||
color: color,
|
||||
glyphs: self.auxiliary_lists_builder.add_glyph_instances(&glyphs),
|
||||
font_key: font_key,
|
||||
size: size,
|
||||
blur_radius: blur_radius,
|
||||
glyph_options: glyph_options,
|
||||
};
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::Text(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
}
|
||||
|
||||
self.list.push(display_item);
|
||||
pub fn create_gradient(&mut self,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode) -> Gradient {
|
||||
Gradient {
|
||||
start_point: start_point,
|
||||
end_point: end_point,
|
||||
stops: self.auxiliary_lists_builder.add_gradient_stops(&stops),
|
||||
extend_mode: extend_mode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_radial_gradient(&mut self,
|
||||
start_center: LayoutPoint,
|
||||
start_radius: f32,
|
||||
end_center: LayoutPoint,
|
||||
end_radius: f32,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode) -> RadialGradient {
|
||||
RadialGradient {
|
||||
start_center: start_center,
|
||||
start_radius: start_radius,
|
||||
end_center: end_center,
|
||||
end_radius: end_radius,
|
||||
stops: self.auxiliary_lists_builder.add_gradient_stops(&stops),
|
||||
extend_mode: extend_mode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,18 +247,12 @@ impl DisplayListBuilder {
|
|||
clip: ClipRegion,
|
||||
widths: BorderWidths,
|
||||
details: BorderDetails) {
|
||||
let item = BorderDisplayItem {
|
||||
let item = SpecificDisplayItem::Border(BorderDisplayItem {
|
||||
details: details,
|
||||
widths: widths,
|
||||
};
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::Border(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_box_shadow(&mut self,
|
||||
|
@ -210,7 +265,7 @@ impl DisplayListBuilder {
|
|||
spread_radius: f32,
|
||||
border_radius: f32,
|
||||
clip_mode: BoxShadowClipMode) {
|
||||
let item = BoxShadowDisplayItem {
|
||||
let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {
|
||||
box_bounds: box_bounds,
|
||||
offset: offset,
|
||||
color: color,
|
||||
|
@ -218,15 +273,9 @@ impl DisplayListBuilder {
|
|||
spread_radius: spread_radius,
|
||||
border_radius: border_radius,
|
||||
clip_mode: clip_mode,
|
||||
};
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::BoxShadow(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_gradient(&mut self,
|
||||
|
@ -236,20 +285,11 @@ impl DisplayListBuilder {
|
|||
end_point: LayoutPoint,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode) {
|
||||
let item = GradientDisplayItem {
|
||||
start_point: start_point,
|
||||
end_point: end_point,
|
||||
stops: self.auxiliary_lists_builder.add_gradient_stops(&stops),
|
||||
extend_mode: extend_mode,
|
||||
};
|
||||
let item = SpecificDisplayItem::Gradient(GradientDisplayItem {
|
||||
gradient: self.create_gradient(start_point, end_point, stops, extend_mode),
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::Gradient(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_radial_gradient(&mut self,
|
||||
|
@ -261,22 +301,13 @@ impl DisplayListBuilder {
|
|||
end_radius: f32,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode) {
|
||||
let item = RadialGradientDisplayItem {
|
||||
start_center: start_center,
|
||||
start_radius: start_radius,
|
||||
end_center: end_center,
|
||||
end_radius: end_radius,
|
||||
stops: self.auxiliary_lists_builder.add_gradient_stops(&stops),
|
||||
extend_mode: extend_mode,
|
||||
};
|
||||
let item = SpecificDisplayItem::RadialGradient(RadialGradientDisplayItem {
|
||||
gradient: self.create_radial_gradient(start_center, start_radius,
|
||||
end_center, end_radius,
|
||||
stops, extend_mode),
|
||||
});
|
||||
|
||||
let display_item = DisplayItem {
|
||||
item: SpecificDisplayItem::RadialGradient(item),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
|
||||
self.list.push(display_item);
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
pub fn push_stacking_context(&mut self,
|
||||
|
@ -284,75 +315,107 @@ impl DisplayListBuilder {
|
|||
bounds: LayoutRect,
|
||||
clip: ClipRegion,
|
||||
z_index: i32,
|
||||
transform: PropertyBinding<LayoutTransform>,
|
||||
perspective: LayoutTransform,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: Vec<FilterOp>) {
|
||||
let stacking_context = StackingContext {
|
||||
scroll_policy: scroll_policy,
|
||||
bounds: bounds,
|
||||
z_index: z_index,
|
||||
transform: transform,
|
||||
perspective: perspective,
|
||||
mix_blend_mode: mix_blend_mode,
|
||||
filters: self.auxiliary_lists_builder.add_filters(&filters),
|
||||
};
|
||||
let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
|
||||
stacking_context: StackingContext {
|
||||
scroll_policy: scroll_policy,
|
||||
bounds: bounds,
|
||||
z_index: z_index,
|
||||
transform: transform,
|
||||
perspective: perspective,
|
||||
mix_blend_mode: mix_blend_mode,
|
||||
filters: self.auxiliary_lists_builder.add_filters(&filters),
|
||||
}
|
||||
});
|
||||
|
||||
let item = DisplayItem {
|
||||
item: SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
|
||||
stacking_context: stacking_context
|
||||
}),
|
||||
rect: LayoutRect::zero(),
|
||||
clip: clip,
|
||||
};
|
||||
self.list.push(item);
|
||||
self.push_item(item, LayoutRect::zero(), clip);
|
||||
}
|
||||
|
||||
pub fn pop_stacking_context(&mut self) {
|
||||
let item = DisplayItem {
|
||||
item: SpecificDisplayItem::PopStackingContext,
|
||||
rect: LayoutRect::zero(),
|
||||
clip: ClipRegion::simple(&LayoutRect::zero()),
|
||||
};
|
||||
self.list.push(item);
|
||||
self.push_new_empty_item(SpecificDisplayItem::PopStackingContext);
|
||||
}
|
||||
|
||||
pub fn define_clip(&mut self,
|
||||
clip: ClipRegion,
|
||||
content_size: LayoutSize,
|
||||
scroll_root_id: Option<ServoScrollRootId>)
|
||||
-> ScrollLayerId {
|
||||
let scroll_layer_id = self.next_scroll_layer_id;
|
||||
self.next_scroll_layer_id += 1;
|
||||
|
||||
let id = ScrollLayerId::new(self.pipeline_id, scroll_layer_id);
|
||||
let item = SpecificDisplayItem::Clip(ClipDisplayItem {
|
||||
content_size: content_size,
|
||||
id: id,
|
||||
parent_id: *self.clip_stack.last().unwrap(),
|
||||
scroll_root_id: scroll_root_id,
|
||||
});
|
||||
|
||||
self.push_item(item, clip.main, clip);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn push_scroll_layer(&mut self,
|
||||
clip: ClipRegion,
|
||||
content_size: LayoutSize,
|
||||
scroll_root_id: ServoScrollRootId) {
|
||||
let scroll_layer_id = self.next_scroll_layer_id;
|
||||
self.next_scroll_layer_id += 1;
|
||||
scroll_root_id: Option<ServoScrollRootId>) {
|
||||
let id = self.define_clip(clip, content_size, scroll_root_id);
|
||||
self.clip_stack.push(id);
|
||||
}
|
||||
|
||||
let item = PushScrollLayerItem {
|
||||
content_size: content_size,
|
||||
id: ScrollLayerId::new(self.pipeline_id, scroll_layer_id, scroll_root_id),
|
||||
};
|
||||
pub fn push_clip_id(&mut self, id: ScrollLayerId) {
|
||||
self.clip_stack.push(id);
|
||||
}
|
||||
|
||||
let item = DisplayItem {
|
||||
item: SpecificDisplayItem::PushScrollLayer(item),
|
||||
rect: clip.main,
|
||||
clip: clip,
|
||||
};
|
||||
self.list.push(item);
|
||||
pub fn pop_clip_id(&mut self) {
|
||||
self.clip_stack.pop();
|
||||
assert!(self.clip_stack.len() > 0);
|
||||
}
|
||||
|
||||
pub fn pop_scroll_layer(&mut self) {
|
||||
let item = DisplayItem {
|
||||
item: SpecificDisplayItem::PopScrollLayer,
|
||||
rect: LayoutRect::zero(),
|
||||
clip: ClipRegion::simple(&LayoutRect::zero()),
|
||||
};
|
||||
self.list.push(item);
|
||||
self.pop_clip_id();
|
||||
}
|
||||
|
||||
pub fn push_iframe(&mut self, rect: LayoutRect, clip: ClipRegion, pipeline_id: PipelineId) {
|
||||
let item = DisplayItem {
|
||||
item: SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id }),
|
||||
rect: rect,
|
||||
clip: clip,
|
||||
};
|
||||
self.list.push(item);
|
||||
let item = SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id });
|
||||
self.push_item(item, rect, clip);
|
||||
}
|
||||
|
||||
// Don't use this function. It will go away.
|
||||
// We're using it as a hack in Gecko to retain parts sub-parts of display lists so that
|
||||
// we can regenerate them without building Gecko display items.
|
||||
pub fn push_built_display_list(&mut self, dl: BuiltDisplayList, aux: AuxiliaryLists) {
|
||||
use SpecificDisplayItem::*;
|
||||
// It's important for us to make sure that all of ItemRange structures are relocated
|
||||
// when copying from one list to another. To avoid this problem we could use a custom
|
||||
// derive implementation that would let ItemRanges relocate themselves.
|
||||
for i in dl.all_display_items() {
|
||||
let mut i = *i;
|
||||
match i.item {
|
||||
Text(ref mut item) => {
|
||||
item.glyphs = self.auxiliary_lists_builder.add_glyph_instances(aux.glyph_instances(&item.glyphs));
|
||||
}
|
||||
Gradient(ref mut item) => {
|
||||
item.gradient.stops = self.auxiliary_lists_builder.add_gradient_stops(aux.gradient_stops(&item.gradient.stops));
|
||||
}
|
||||
RadialGradient(ref mut item) => {
|
||||
item.gradient.stops = self.auxiliary_lists_builder.add_gradient_stops(aux.gradient_stops(&item.gradient.stops));
|
||||
}
|
||||
PushStackingContext(ref mut item) => {
|
||||
item.stacking_context.filters = self.auxiliary_lists_builder.add_filters(aux.filters(&item.stacking_context.filters));
|
||||
}
|
||||
Iframe(_) | Clip(_) => {
|
||||
// We don't support relocating these
|
||||
panic!();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
i.clip.complex = self.auxiliary_lists_builder.add_complex_clip_regions(aux.complex_clip_regions(&i.clip.complex));
|
||||
self.list.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_clip_region(&mut self,
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::Point2D;
|
||||
use {ColorU, ColorF};
|
||||
|
||||
#[cfg(target_os = "macos")] use core_graphics::font::CGFont;
|
||||
#[cfg(target_os = "windows")] use dwrote::FontDescriptor;
|
||||
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub type NativeFontHandle = CGFont;
|
||||
|
||||
/// Native fonts are not used on Linux; all fonts are raw.
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
#[cfg_attr(not(any(target_os = "macos", target_os = "windows")), derive(Clone, Serialize, Deserialize))]
|
||||
pub struct NativeFontHandle;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub type NativeFontHandle = FontDescriptor;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Deserialize, Serialize, Debug)]
|
||||
pub struct GlyphDimensions {
|
||||
pub left: i32,
|
||||
pub top: i32,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)]
|
||||
pub struct FontKey(pub u32, pub u32);
|
||||
|
||||
impl FontKey {
|
||||
pub fn new(key0: u32, key1: u32) -> FontKey {
|
||||
FontKey(key0, key1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub enum FontRenderMode {
|
||||
Mono,
|
||||
Alpha,
|
||||
Subpixel,
|
||||
}
|
||||
|
||||
impl FontRenderMode {
|
||||
// Skia quantizes subpixel offets into 1/4 increments.
|
||||
// Given the absolute position, return the quantized increment
|
||||
fn subpixel_quantize_offset(&self, pos: f32) -> SubpixelOffset {
|
||||
if *self != FontRenderMode::Subpixel {
|
||||
return SubpixelOffset::Zero;
|
||||
}
|
||||
|
||||
const SUBPIXEL_ROUNDING :f32 = 0.125; // Skia chosen value.
|
||||
let fraction = (pos + SUBPIXEL_ROUNDING).fract();
|
||||
|
||||
match fraction {
|
||||
0.0...0.25 => SubpixelOffset::Zero,
|
||||
0.25...0.5 => SubpixelOffset::Quarter,
|
||||
0.5...0.75 => SubpixelOffset::Half,
|
||||
0.75...1.0 => SubpixelOffset::ThreeQuarters,
|
||||
_ => panic!("Should only be given the fractional part"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub enum SubpixelOffset {
|
||||
Zero = 0,
|
||||
Quarter = 1,
|
||||
Half = 2,
|
||||
ThreeQuarters = 3,
|
||||
}
|
||||
|
||||
impl Into<f64> for SubpixelOffset {
|
||||
fn into(self) -> f64 {
|
||||
match self {
|
||||
SubpixelOffset::Zero => 0.0,
|
||||
SubpixelOffset::Quarter => 0.25,
|
||||
SubpixelOffset::Half => 0.5,
|
||||
SubpixelOffset::ThreeQuarters => 0.75,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug, Deserialize, Serialize, Ord, PartialOrd)]
|
||||
pub struct SubpixelPoint {
|
||||
pub x: SubpixelOffset,
|
||||
pub y: SubpixelOffset,
|
||||
}
|
||||
|
||||
impl SubpixelPoint {
|
||||
pub fn new(point: Point2D<f32>,
|
||||
render_mode: FontRenderMode) -> SubpixelPoint {
|
||||
SubpixelPoint {
|
||||
x: render_mode.subpixel_quantize_offset(point.x),
|
||||
y: render_mode.subpixel_quantize_offset(point.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_f64(&self) -> (f64, f64) {
|
||||
return (self.x.into(), self.y.into());
|
||||
}
|
||||
|
||||
pub fn set_offset(&mut self, point: Point2D<f32>, render_mode: FontRenderMode) {
|
||||
self.x = render_mode.subpixel_quantize_offset(point.x);
|
||||
self.y = render_mode.subpixel_quantize_offset(point.y);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug, Deserialize, Serialize, Ord, PartialOrd)]
|
||||
pub struct GlyphKey {
|
||||
pub font_key: FontKey,
|
||||
// The font size is in *device* pixels, not logical pixels.
|
||||
// It is stored as an Au since we need sub-pixel sizes, but
|
||||
// can't store as a f32 due to use of this type as a hash key.
|
||||
// TODO(gw): Perhaps consider having LogicalAu and DeviceAu
|
||||
// or something similar to that.
|
||||
pub size: Au,
|
||||
pub index: u32,
|
||||
pub color: ColorU,
|
||||
pub subpixel_point: SubpixelPoint,
|
||||
}
|
||||
|
||||
impl GlyphKey {
|
||||
pub fn new(font_key: FontKey,
|
||||
size: Au,
|
||||
color: ColorF,
|
||||
index: u32,
|
||||
point: Point2D<f32>,
|
||||
render_mode: FontRenderMode) -> GlyphKey {
|
||||
GlyphKey {
|
||||
font_key: font_key,
|
||||
size: size,
|
||||
color: ColorU::from(color),
|
||||
index: index,
|
||||
subpixel_point: SubpixelPoint::new(point, render_mode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GlyphInstance {
|
||||
pub index: u32,
|
||||
pub point: Point2D<f32>,
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче