aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbors-servo <release+servo@mozilla.com>2013-06-14 16:06:33 -0700
committerbors-servo <release+servo@mozilla.com>2013-06-14 16:06:33 -0700
commit93eea6b2e87adedf833790d045bf69417ca9b7e3 (patch)
treec2a79b0689be6e704f183b6dd6177c93d487401e /src
parent96731e9714e08773521c0f54e0f0a852e5029252 (diff)
parent282288d8c560c99a8a966a44e7c0d4ca4979ebba (diff)
downloadservo-93eea6b2e87adedf833790d045bf69417ca9b7e3.tar.gz
servo-93eea6b2e87adedf833790d045bf69417ca9b7e3.zip
auto merge of #518 : metajack/servo/gpu-rendering, r=pcwalton
This uses Skia GL to render to offscreen FBOs and then passes the resulting textures directly to the compositor. It depends on https://github.com/mozilla-servo/rust-azure/pull/26 and https://github.com/mozilla-servo/skia/pull/14 r? @pcwalton
Diffstat (limited to 'src')
-rw-r--r--src/components/gfx/compositor.rs4
-rw-r--r--src/components/gfx/render_context.rs4
-rw-r--r--src/components/gfx/render_layers.rs53
-rw-r--r--src/components/gfx/render_task.rs12
-rw-r--r--src/components/main/compositing/mod.rs62
-rw-r--r--src/components/main/platform/common/glut_windowing.rs2
m---------src/support/azure/rust-azure0
m---------src/support/layers/rust-layers0
m---------src/support/opengles/rust-opengles0
m---------src/support/skia/skia0
m---------src/support/spidermonkey/rust-mozjs0
11 files changed, 54 insertions, 83 deletions
diff --git a/src/components/gfx/compositor.rs b/src/components/gfx/compositor.rs
index ea87d548661..91b03989da6 100644
--- a/src/components/gfx/compositor.rs
+++ b/src/components/gfx/compositor.rs
@@ -2,7 +2,8 @@
* 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 azure::azure_hl::{DrawTarget};
+use azure::azure_hl::DrawTarget;
+use azure::azure::AzGLContext;
use geom::rect::Rect;
use geom::size::Size2D;
@@ -34,6 +35,7 @@ pub enum RenderState {
/// The interface used to by the renderer to acquire draw targets for each rendered frame and
/// submit them to be drawn to the display.
pub trait Compositor {
+ fn get_gl_context(&self) -> AzGLContext;
fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>);
fn set_render_state(&self, render_state: RenderState);
}
diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs
index 17fb40d825c..aef6e85c9ec 100644
--- a/src/components/gfx/render_context.rs
+++ b/src/components/gfx/render_context.rs
@@ -30,6 +30,7 @@ pub impl<'self> RenderContext<'self> {
}
pub fn draw_solid_color(&self, bounds: &Rect<Au>, color: Color) {
+ self.canvas.draw_target.make_current();
self.canvas.draw_target.fill_rect(&bounds.to_azure_rect(), &ColorPattern(color));
}
@@ -46,6 +47,7 @@ pub impl<'self> RenderContext<'self> {
let stroke_opts = StrokeOptions(width_px as AzFloat, 10 as AzFloat, stroke_fields);
let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t);
+ self.canvas.draw_target.make_current();
self.canvas.draw_target.stroke_rect(&rect, &pattern, &stroke_opts, &draw_opts);
}
@@ -54,6 +56,7 @@ pub impl<'self> RenderContext<'self> {
let size = Size2D(image.width as i32, image.height as i32);
let stride = image.width * 4;
+ self.canvas.draw_target.make_current();
let draw_target_ref = &self.canvas.draw_target;
let azure_surface = draw_target_ref.create_source_surface_from_data(image.data, size,
stride as i32, B8G8R8A8);
@@ -75,6 +78,7 @@ pub impl<'self> RenderContext<'self> {
self.canvas.rect.origin.y as AzFloat),
Size2D(self.canvas.rect.size.width as AzFloat,
self.canvas.rect.size.height as AzFloat));
+ self.canvas.draw_target.make_current();
self.canvas.draw_target.fill_rect(&rect, &pattern);
}
}
diff --git a/src/components/gfx/render_layers.rs b/src/components/gfx/render_layers.rs
index a0741480dd7..fd8bdb03e86 100644
--- a/src/components/gfx/render_layers.rs
+++ b/src/components/gfx/render_layers.rs
@@ -9,6 +9,7 @@ use servo_util::time;
use servo_util::time::ProfilerChan;
use azure::azure_hl::{B8G8R8A8, DrawTarget};
+use azure::azure::{AzGLContext};
use core::comm::Chan;
use geom::point::Point2D;
use geom::rect::Rect;
@@ -34,6 +35,7 @@ type RenderFn<'self> = &'self fn(layer: *RenderLayer,
pub fn render_layers(layer_ref: *RenderLayer,
opts: &Opts,
prof_chan: ProfilerChan,
+ share_gl_context: AzGLContext,
f: RenderFn)
-> LayerBufferSet {
let tile_size = opts.tile_size;
@@ -55,19 +57,8 @@ pub fn render_layers(layer_ref: *RenderLayer,
let width = right - x;
let height = bottom - y;
- // Round the width up the nearest 32 pixels for DMA on the Mac.
- let aligned_width = if width % 32 == 0 {
- width
- } else {
- (width & !(32 - 1)) + 32
- };
- assert!(aligned_width % 32 == 0);
- assert!(aligned_width >= width);
-
- debug!("tile aligned_width %u", aligned_width);
-
- let tile_rect = Rect(Point2D(x / scale, y / scale), Size2D(aligned_width, height)); //change this
- let screen_rect = Rect(Point2D(x, y), Size2D(aligned_width, height)); //change this
+ let tile_rect = Rect(Point2D(x / scale, y / scale), Size2D(width, height)); //change this
+ let screen_rect = Rect(Point2D(x, y), Size2D(width, height)); //change this
let buffer;
// FIXME: Try harder to search for a matching tile.
@@ -79,40 +70,14 @@ pub fn render_layers(layer_ref: *RenderLayer,
// Create a new buffer.
debug!("creating tile, (%u, %u)", x, y);
- let size = Size2D(aligned_width as i32, height as i32);
// FIXME: This may not be always true.
- let stride = (aligned_width as i32) * 4;
-
- let mut data: ~[u8] = ~[0];
- let offset;
- unsafe {
- // FIXME: Evil black magic to ensure that we don't perform a slow memzero
- // of this buffer. This should be made safe.
-
- let align = 256;
-
- let len = ((stride * size.height) as uint) + align;
- vec::reserve(&mut data, len);
- vec::raw::set_len(&mut data, len);
-
- // Round up to the nearest 32-byte-aligned address for DMA on the Mac.
- let addr: uint = cast::transmute(ptr::to_unsafe_ptr(&data[0]));
- if addr % align == 0 {
- offset = 0;
- } else {
- offset = align - addr % align;
- }
-
- debug!("tile offset is %u, expected addr is %x", offset, addr + offset);
- }
+ let stride = width * 4;
buffer = LayerBuffer {
- draw_target: DrawTarget::new_with_data(opts.render_backend,
- data,
- offset,
- size,
- stride,
- B8G8R8A8),
+ draw_target: DrawTarget::new_with_fbo(opts.render_backend,
+ share_gl_context,
+ Size2D(width as i32, height as i32),
+ B8G8R8A8),
rect: tile_rect,
screen_pos: screen_rect,
stride: stride as uint
diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs
index 4b76e2ac0f6..1b5aa289f53 100644
--- a/src/components/gfx/render_task.rs
+++ b/src/components/gfx/render_task.rs
@@ -4,7 +4,7 @@
// The task that handles all rendering/painting.
-use azure::AzFloat;
+use azure::{AzFloat, AzGLContext};
use compositor::{Compositor, IdleRenderState, RenderingRenderState};
use font_context::FontContext;
use geom::matrix2d::Matrix2D;
@@ -16,6 +16,7 @@ use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan};
use core::task::SingleThreaded;
use std::task_pool::TaskPool;
+
use servo_net::util::spawn_listener;
use servo_util::time::{ProfilerChan, profile};
@@ -43,6 +44,7 @@ impl RenderTask {
do spawn {
let compositor = compositor_cell.take();
+ let share_gl_context = compositor.get_gl_context();
// FIXME: Annoying three-cell dance here. We need one-shot closures.
let opts = opts_cell.with_ref(|o| copy *o);
@@ -77,6 +79,7 @@ impl RenderTask {
thread_pool: thread_pool,
opts: opts_cell.take(),
profiler_chan: profiler_chan_copy,
+ share_gl_context: share_gl_context,
};
renderer.start();
@@ -103,6 +106,8 @@ priv struct Renderer<C> {
/// A channel to the profiler.
profiler_chan: ProfilerChan,
+
+ share_gl_context: AzGLContext,
}
impl<C: Compositor + Owned> Renderer<C> {
@@ -126,7 +131,8 @@ impl<C: Compositor + Owned> Renderer<C> {
do profile(time::RenderingCategory, self.profiler_chan.clone()) {
let layer_buffer_set = do render_layers(&render_layer,
&self.opts,
- self.profiler_chan.clone()) |render_layer_ref,
+ self.profiler_chan.clone(),
+ self.share_gl_context) |render_layer_ref,
layer_buffer,
buffer_chan| {
let layer_buffer_cell = Cell(layer_buffer);
@@ -147,7 +153,6 @@ impl<C: Compositor + Owned> Renderer<C> {
let matrix = matrix.translate(-(layer_buffer.rect.origin.x as f32) as AzFloat,
-(layer_buffer.rect.origin.y as f32) as AzFloat);
-
layer_buffer.draw_target.set_transform(&matrix);
// Clear the buffer.
@@ -160,6 +165,7 @@ impl<C: Compositor + Owned> Renderer<C> {
};
render_layer.display_list.draw_into_context(&ctx);
+ ctx.canvas.draw_target.flush();
}
// Send back the buffer.
diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs
index 452f4bbb06d..f7049f2d131 100644
--- a/src/components/main/compositing/mod.rs
+++ b/src/components/main/compositing/mod.rs
@@ -13,7 +13,8 @@ use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
use script::compositor_interface::{ReadyState, CompositorInterface};
use script::compositor_interface;
-use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
+use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
+use azure::azure::AzGLContext;
use core::cell::Cell;
use core::comm::{Chan, SharedChan, Port};
use core::num::Orderable;
@@ -22,8 +23,9 @@ use geom::matrix::identity;
use geom::point::Point2D;
use geom::size::Size2D;
use gfx::compositor::{Compositor, LayerBufferSet, RenderState};
-use layers::layers::{ARGB32Format, BasicImageData, ContainerLayer, ContainerLayerKind, Format};
-use layers::layers::{Image, ImageData, ImageLayer, ImageLayerKind, RGB24Format, WithDataFn};
+use layers::layers::{ARGB32Format, ContainerLayer, ContainerLayerKind, Format};
+use layers::layers::{ImageData, WithDataFn};
+use layers::layers::{TextureLayerKind, TextureLayer, TextureManager};
use layers::rendergl;
use layers::scene::Scene;
use servo_util::{time, url};
@@ -74,6 +76,8 @@ impl CompositorTask {
pub enum Msg {
/// Requests that the compositor shut down.
Exit,
+ /// Requests the compositors GL context.
+ GetGLContext(Chan<AzGLContext>),
/// Requests that the compositor paint the given layer buffer set for the given page size.
Paint(LayerBufferSet, Size2D<uint>),
/// Alerts the compositor to the current status of page loading.
@@ -86,7 +90,7 @@ pub enum Msg {
struct AzureDrawTargetImageData {
draw_target: DrawTarget,
data_source_surface: DataSourceSurface,
- size: Size2D<uint>
+ size: Size2D<uint>,
}
impl ImageData for AzureDrawTargetImageData {
@@ -121,16 +125,6 @@ fn run_main_loop(port: Port<Msg>,
// list. This is only here because we don't have that logic in the renderer yet.
let context = rendergl::init_render_context();
let root_layer = @mut ContainerLayer();
- let original_layer_transform;
- {
- let image_data = @BasicImageData::new(Size2D(0, 0), 0, RGB24Format, ~[]);
- let image = @mut Image::new(image_data as @ImageData);
- let image_layer = @mut ImageLayer(image);
- original_layer_transform = image_layer.common.transform;
- image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
- root_layer.add_child(ImageLayerKind(image_layer));
- }
-
let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0, 600.0), identity());
let done = @mut false;
@@ -155,6 +149,8 @@ fn run_main_loop(port: Port<Msg>,
ChangeReadyState(ready_state) => window.set_ready_state(ready_state),
ChangeRenderState(render_state) => window.set_render_state(render_state),
+ GetGLContext(chan) => chan.send(current_gl_context()),
+
Paint(new_layer_buffer_set, new_size) => {
debug!("osmain: received new frame");
@@ -175,25 +171,19 @@ fn run_main_loop(port: Port<Msg>,
debug!("osmain: compositing buffer rect %?", &buffer.rect);
- let image_data = @AzureDrawTargetImageData {
- draw_target: buffer.draw_target.clone(),
- data_source_surface: buffer.draw_target.snapshot().get_data_surface(),
- size: Size2D(width, height)
- };
- let image = @mut Image::new(image_data as @ImageData);
-
- // Find or create an image layer.
- let image_layer;
+ // Find or create a texture layer.
+ let texture_layer;
current_layer_child = match current_layer_child {
None => {
- debug!("osmain: adding new image layer");
- image_layer = @mut ImageLayer(image);
- root_layer.add_child(ImageLayerKind(image_layer));
+ debug!("osmain: adding new texture layer");
+ texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
+ buffer.rect.size);
+ root_layer.add_child(TextureLayerKind(texture_layer));
None
}
- Some(ImageLayerKind(existing_image_layer)) => {
- image_layer = existing_image_layer;
- image_layer.set_image(image);
+ Some(TextureLayerKind(existing_texture_layer)) => {
+ texture_layer = existing_texture_layer;
+ texture_layer.manager = @buffer.draw_target.clone() as @TextureManager;
// Move on to the next sibling.
do current_layer_child.get().with_common |common| {
@@ -207,17 +197,15 @@ fn run_main_loop(port: Port<Msg>,
let origin = Point2D(origin.x as f32, origin.y as f32);
// Set the layer's transform.
- let transform = original_layer_transform.translate(origin.x,
- origin.y,
- 0.0);
+ let transform = identity().translate(origin.x, origin.y, 0.0);
let transform = transform.scale(width as f32, height as f32, 1.0);
- image_layer.common.set_transform(transform)
+ texture_layer.common.set_transform(transform);
}
// TODO: Recycle the old buffers; send them back to the renderer to reuse if
// it wishes.
- window.set_needs_display()
+ window.set_needs_display();
}
}
}
@@ -356,6 +344,12 @@ fn run_main_loop(port: Port<Msg>,
/// Implementation of the abstract `Compositor` interface.
impl Compositor for CompositorTask {
+ fn get_gl_context(&self) -> AzGLContext {
+ let (port, chan) = comm::stream();
+ self.chan.send(GetGLContext(chan));
+ port.recv()
+ }
+
fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>) {
self.chan.send(Paint(layer_buffer_set, new_size))
}
diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs
index 0b35f24ae7c..a6ee264437c 100644
--- a/src/components/main/platform/common/glut_windowing.rs
+++ b/src/components/main/platform/common/glut_windowing.rs
@@ -60,8 +60,8 @@ impl WindowMethods<Application> for Window {
/// Creates a new window.
pub fn new(_: &Application) -> @mut Window {
// Create the GLUT window.
+ unsafe { glut::bindgen::glutInitWindowSize(800, 600); }
let glut_window = glut::create_window(~"Servo");
- glut::reshape_window(glut_window, 800, 600);
// Create our window object.
let window = @mut Window {
diff --git a/src/support/azure/rust-azure b/src/support/azure/rust-azure
-Subproject 9ee743c1badb904adcfdf6ff3ebd100797b68ab
+Subproject 04976e3fae0ef0332036082ab8770fb1ad2c10c
diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers
-Subproject f4ec5a4590a39804ef38faaab4b6749e5c7eb4c
+Subproject e0898b8555261dc01485883486df13afbcbd4dd
diff --git a/src/support/opengles/rust-opengles b/src/support/opengles/rust-opengles
-Subproject f0a5718827f7f2436cb0a9d0b2463efdea26361
+Subproject bb97c51065f8658911e9b16da4ec99d26099d9a
diff --git a/src/support/skia/skia b/src/support/skia/skia
-Subproject 4af440519885bc45ed51349e9b501b1550f75d9
+Subproject 7415c2829e77812411a2ae9cf448c0e28803546
diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs
-Subproject dc25b92b3f8777b3599455cee190d1a07348b71
+Subproject 4f966f005b0dab9e26264667fb9df1249235487