From 3a618a8b6f621b0b6d444027e8ccf76ebeb14125 Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Thu, 28 Nov 2013 20:43:02 +0900 Subject: [PATCH 1/7] Update latest Rust --- layers.rs | 30 +++++++++++++++--------------- util.rs | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/layers.rs b/layers.rs index 1a67168..e2e54ac 100644 --- a/layers.rs +++ b/layers.rs @@ -25,7 +25,7 @@ pub enum Layer { } impl Layer { - pub fn with_common(&self, f: &fn(&mut CommonLayer) -> T) -> T { + pub fn with_common(&self, f: |&mut CommonLayer| -> T) -> T { match *self { ContainerLayerKind(container_layer) => f(&mut container_layer.common), TextureLayerKind(texture_layer) => f(&mut texture_layer.common), @@ -99,7 +99,7 @@ impl ContainerLayer { /// Adds a child to the beginning of the list. /// Only works when the child is disconnected from the layer tree. pub fn add_child_start(@mut self, new_child: Layer) { - do new_child.with_common |new_child_common| { + new_child.with_common(|new_child_common| { assert!(new_child_common.parent.is_none()); assert!(new_child_common.prev_sibling.is_none()); assert!(new_child_common.next_sibling.is_none()); @@ -109,11 +109,11 @@ impl ContainerLayer { match self.first_child { None => {} Some(first_child) => { - do first_child.with_common |first_child_common| { + first_child.with_common(|first_child_common| { assert!(first_child_common.prev_sibling.is_none()); first_child_common.prev_sibling = Some(new_child); new_child_common.next_sibling = Some(first_child); - } + }) } } @@ -123,13 +123,13 @@ impl ContainerLayer { None => self.last_child = Some(new_child), Some(_) => {} } - } + }) } /// Adds a child to the end of the list. /// Only works when the child is disconnected from the layer tree. pub fn add_child_end(@mut self, new_child: Layer) { - do new_child.with_common |new_child_common| { + new_child.with_common(|new_child_common| { assert!(new_child_common.parent.is_none()); assert!(new_child_common.prev_sibling.is_none()); assert!(new_child_common.next_sibling.is_none()); @@ -139,11 +139,11 @@ impl ContainerLayer { match self.last_child { None => {} Some(last_child) => { - do last_child.with_common |last_child_common| { + last_child.with_common(|last_child_common| { assert!(last_child_common.next_sibling.is_none()); last_child_common.next_sibling = Some(new_child); new_child_common.prev_sibling = Some(last_child); - } + }) } } @@ -153,11 +153,11 @@ impl ContainerLayer { None => self.first_child = Some(new_child), Some(_) => {} } - } + }) } pub fn remove_child(@mut self, child: Layer) { - do child.with_common |child_common| { + child.with_common(|child_common| { assert!(child_common.parent.is_some()); match child_common.parent.unwrap() { ContainerLayerKind(ref container) => { @@ -171,9 +171,9 @@ impl ContainerLayer { self.last_child = child_common.prev_sibling; }, Some(ref sibling) => { - do sibling.with_common |sibling_common| { + sibling.with_common(|sibling_common| { sibling_common.prev_sibling = child_common.prev_sibling; - } + }) } } match child_common.prev_sibling { @@ -181,12 +181,12 @@ impl ContainerLayer { self.first_child = child_common.next_sibling; }, Some(ref sibling) => { - do sibling.with_common |sibling_common| { + sibling.with_common(|sibling_common| { sibling_common.next_sibling = child_common.next_sibling; - } + }) } } - } + }) } } diff --git a/util.rs b/util.rs index 47acd63..74bf688 100644 --- a/util.rs +++ b/util.rs @@ -13,7 +13,7 @@ use std::vec::from_fn; pub fn convert_rgb32_to_rgb24(buffer: ~[u8]) -> ~[u8] { let mut i = 0; - do from_fn(buffer.len() * 3 / 4) |j| { + from_fn(buffer.len() * 3 / 4, |j| { match j % 3 { 0 => { buffer[i + 2] @@ -30,6 +30,6 @@ pub fn convert_rgb32_to_rgb24(buffer: ~[u8]) -> ~[u8] { fail!() } } - } + }) } From 924e5799328080d69074c971d7827889c869f884 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Thu, 26 Dec 2013 20:00:56 -0700 Subject: [PATCH 2/7] Build with make instead of rustpkg. --- Makefile.in | 24 ++++++++++++++++++++++++ configure | 4 ++++ lib.rs | 12 +++++++----- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 Makefile.in create mode 100755 configure diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..ad2f528 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,24 @@ +VPATH=%VPATH% + +RUSTC ?= rustc +RUSTFLAGS ?= + +RUST_SRC=$(shell find $(VPATH)/. -type f -name '*.rs') + +.PHONY: all +all: librust-layers.dummy + +librust-layers.dummy: lib.rs $(RUST_SRC) + $(RUSTC) $(RUSTFLAGS) $< --lib --out-dir . + touch $@ + +rust-layers-test: lib.rs $(RUST_SRC) + $(RUSTC) $(RUSTFLAGS) $< -o $@ --test + +.PHONY: check +check: rust-layers-test + ./rust-layers-test $(TEST) + +.PHONY: clean +clean: + rm -f *.o *.a *.so *.dylib *.dll *.dummy *-test diff --git a/configure b/configure new file mode 100755 index 0000000..62a0f4c --- /dev/null +++ b/configure @@ -0,0 +1,4 @@ +#!/bin/bash + +SRCDIR="$(cd $(dirname $0) && pwd)" +sed "s#%VPATH%#${SRCDIR}#" ${SRCDIR}/Makefile.in > Makefile diff --git a/lib.rs b/lib.rs index e450d4d..01b45f3 100755 --- a/lib.rs +++ b/lib.rs @@ -7,20 +7,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[link(name = "layers", vers = "0.1")]; + #[feature(managed_boxes)]; extern mod extra; -extern mod geom = "rust-geom"; -extern mod opengles = "rust-opengles"; +extern mod geom; +extern mod opengles; extern mod std; #[cfg(target_os="macos")] -extern mod core_foundation = "rust-core-foundation"; +extern mod core_foundation; #[cfg(target_os="macos")] -extern mod io_surface = "rust-io-surface"; +extern mod io_surface; #[cfg(target_os="linux")] -extern mod xlib = "rust-xlib"; +extern mod xlib; pub mod layers; pub mod color; From 985790fe16d10d50391675d00df832fc2b8e1048 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Thu, 26 Dec 2013 22:32:20 -0700 Subject: [PATCH 3/7] Partial revert of rust upgrade. --- layers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layers.rs b/layers.rs index e2e54ac..9d90163 100644 --- a/layers.rs +++ b/layers.rs @@ -25,7 +25,7 @@ pub enum Layer { } impl Layer { - pub fn with_common(&self, f: |&mut CommonLayer| -> T) -> T { + pub fn with_common(&self, f: &fn(&mut CommonLayer) -> T) -> T { match *self { ContainerLayerKind(container_layer) => f(&mut container_layer.common), TextureLayerKind(texture_layer) => f(&mut texture_layer.common), From 9dcecfe1105b06ee2077213b49e5159713e1d742 Mon Sep 17 00:00:00 2001 From: "aydin.kim" Date: Wed, 20 Nov 2013 15:58:35 +0900 Subject: [PATCH 4/7] works for android rendering by using EGLImage --- lib.rs | 7 ++ platform/android/surface.rs | 165 ++++++++++++++++++++++++++++++++++++ platform/surface.rs | 8 ++ rendergl.rs | 113 ++++++++++++++++-------- 4 files changed, 256 insertions(+), 37 deletions(-) create mode 100644 platform/android/surface.rs diff --git a/lib.rs b/lib.rs index 01b45f3..ab67bb3 100755 --- a/lib.rs +++ b/lib.rs @@ -24,6 +24,9 @@ extern mod io_surface; #[cfg(target_os="linux")] extern mod xlib; +#[cfg(target_os="android")] +extern mod egl; + pub mod layers; pub mod color; pub mod rendergl; @@ -40,6 +43,10 @@ pub mod platform { pub mod macos { pub mod surface; } + #[cfg(target_os="android")] + pub mod android { + pub mod surface; + } pub mod surface; } diff --git a/platform/android/surface.rs b/platform/android/surface.rs new file mode 100644 index 0000000..a7f8916 --- /dev/null +++ b/platform/android/surface.rs @@ -0,0 +1,165 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Implementation of cross-process surfaces for Android. This uses EGL surface. + +use platform::surface::NativeSurfaceMethods; +use texturegl::Texture; + +use geom::size::Size2D; +use opengles::gl2::{egl_image_target_texture2d_oes, TEXTURE_2D, GLsizei, GLint, glTexImage2D, BGRA, UNSIGNED_BYTE}; +use egl::egl::EGLDisplay; +use egl::eglext::{EGLImageKHR, CreateImageKHR, DestroyImageKHR}; +use std::cast; +use std::ptr; +use std::util; +use std::vec; +use std::libc::c_void; +use std::vec::bytes; + +/// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them. + +pub struct NativeGraphicsMetadata { + display : EGLDisplay, +} + +pub struct NativePaintingGraphicsContext{ + display : EGLDisplay, +} + +impl NativePaintingGraphicsContext { + #[fixed_stack_segment] + pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext { + unsafe { + NativePaintingGraphicsContext { + display : metadata.display, + } + } + } +} + +impl Drop for NativePaintingGraphicsContext { + #[fixed_stack_segment] + fn drop(&mut self) {} +} + +pub struct NativeCompositingGraphicsContext { + contents: (), +} + +impl NativeCompositingGraphicsContext { + pub fn new() -> NativeCompositingGraphicsContext { + NativeCompositingGraphicsContext { + contents: (), + } + } +} + +pub struct NativeSurface { + image: Option, + bitmap: *c_void, + will_leak: bool, +} + +impl NativeSurface { + #[fixed_stack_segment] + pub fn from_image_khr(image_khr: EGLImageKHR) -> NativeSurface { + let mut _image: Option = None; + if image_khr != ptr::null() { + _image = Some(image_khr); + } + NativeSurface { + image : _image, + bitmap : ptr::null(), + will_leak: true, + } + } +} + +impl NativeSurfaceMethods for NativeSurface { + /// This may only be called on the case of CPU rendering. + #[fixed_stack_segment] + fn new(native_context: &NativePaintingGraphicsContext, size: Size2D, stride: i32) -> NativeSurface { + unsafe { + let len = size.width * size.height * 4; + let bitmap = vec::from_elem::(len as uint, 0); + + NativeSurface { + image: None, + bitmap: cast::transmute(bitmap), + will_leak : true, + } + } + } + + /// This may only be called on the compositor side. + #[fixed_stack_segment] + fn bind_to_texture(&self, + native_context: &NativeCompositingGraphicsContext, + texture: &Texture, + _size: Size2D) { + let _bound = texture.bind(); + + unsafe { + match self.image { + None => { + if self.bitmap != ptr::null() { + glTexImage2D(TEXTURE_2D, 0, BGRA as i32, _size.width as i32, _size.height as i32, 0, BGRA as u32, UNSIGNED_BYTE, self.bitmap); + } + else { + debug!("Cannot bind the buffer(CPU rendering), there is no bitmap"); + } + }, + Some(image_khr) => { + egl_image_target_texture2d_oes(TEXTURE_2D, image_khr); + } + } + } + } + + /// This may only be called on the painting side. + #[fixed_stack_segment] + fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) { + unsafe { + if self.bitmap != ptr::null() { + let dest:&mut [u8] = cast::transmute((self.bitmap, data.len())); + bytes::copy_memory(dest, data, data.len()); + } + else { + debug!("Cannot upload the buffer(CPU rendering), there is no bitmap"); + } + } + } + + fn get_id(&self) -> int { + match self.image { + None => 0, + Some(image_khr) => image_khr as int, + } + } + +#[fixed_stack_segment] + fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) { + match self.image { + None => {}, + Some(image_khr) => { + DestroyImageKHR(graphics_context.display, image_khr); + util::replace(&mut self.image, None); + } + } + self.mark_wont_leak() + } + + fn mark_will_leak(&mut self) { + self.will_leak = true + } + fn mark_wont_leak(&mut self) { + self.will_leak = false + } +} diff --git a/platform/surface.rs b/platform/surface.rs index a7e6820..0397a77 100644 --- a/platform/surface.rs +++ b/platform/surface.rs @@ -34,6 +34,14 @@ pub use platform::linux::surface::NativeGraphicsMetadata; pub use platform::linux::surface::NativeGraphicsMetadataDescriptor; #[cfg(target_os="linux")] pub use platform::linux::surface::NativeSurface; +#[cfg(target_os="android")] +pub use platform::android::surface::NativePaintingGraphicsContext; +#[cfg(target_os="android")] +pub use platform::android::surface::NativeCompositingGraphicsContext; +#[cfg(target_os="android")] +pub use platform::android::surface::NativeGraphicsMetadata; +#[cfg(target_os="android")] +pub use platform::android::surface::NativeSurface; pub trait NativeSurfaceMethods { /// Creates a new native surface with uninitialized data. diff --git a/rendergl.rs b/rendergl.rs index af8dfea..c6ecd16 100755 --- a/rendergl.rs +++ b/rendergl.rs @@ -138,39 +138,59 @@ struct ProgramRectangle { } pub struct RenderContext { - program_2d: Program2D, - program_rectangle: ProgramRectangle, + program_2d: Option, + program_rectangle: Option, buffers: Buffers, } impl RenderContext { - fn new(program_2d: GLuint, program_rectangle: GLuint) -> RenderContext { + fn new(program_2d: Option, program_rectangle: Option) -> RenderContext { let render_context = RenderContext { - program_2d: Program2D { - id: program_2d, - vertex_position_attr: get_attrib_location(program_2d, "aVertexPosition"), - texture_coord_attr: get_attrib_location(program_2d, "aTextureCoord"), - modelview_uniform: get_uniform_location(program_2d, "uMVMatrix"), - projection_uniform: get_uniform_location(program_2d, "uPMatrix"), - sampler_uniform: get_uniform_location(program_2d, "uSampler"), + program_2d: match program_2d { + Some(program) => { + Some(Program2D { + id: program, + vertex_position_attr: get_attrib_location(program, "aVertexPosition"), + texture_coord_attr: get_attrib_location(program, "aTextureCoord"), + modelview_uniform: get_uniform_location(program, "uMVMatrix"), + projection_uniform: get_uniform_location(program, "uPMatrix"), + sampler_uniform: get_uniform_location(program, "uSampler"), + }) + }, + None => None, }, - program_rectangle: ProgramRectangle { - id: program_rectangle, - vertex_position_attr: get_attrib_location(program_rectangle, "aVertexPosition"), - texture_coord_attr: get_attrib_location(program_rectangle, "aTextureCoord"), - modelview_uniform: get_uniform_location(program_rectangle, "uMVMatrix"), - projection_uniform: get_uniform_location(program_rectangle, "uPMatrix"), - sampler_uniform: get_uniform_location(program_rectangle, "uSampler"), - size_uniform: get_uniform_location(program_rectangle, "uSize"), + program_rectangle: match program_rectangle { + Some(program) => { + Some(ProgramRectangle { + id: program, + vertex_position_attr: get_attrib_location(program, "aVertexPosition"), + texture_coord_attr: get_attrib_location(program, "aTextureCoord"), + modelview_uniform: get_uniform_location(program, "uMVMatrix"), + projection_uniform: get_uniform_location(program, "uPMatrix"), + sampler_uniform: get_uniform_location(program, "uSampler"), + size_uniform: get_uniform_location(program, "uSize"), + }) + }, + None => None, }, buffers: RenderContext::init_buffers(), }; - enable_vertex_attrib_array(render_context.program_2d.vertex_position_attr as GLuint); - enable_vertex_attrib_array(render_context.program_2d.texture_coord_attr as GLuint); - enable_vertex_attrib_array(render_context.program_rectangle.vertex_position_attr as - GLuint); - enable_vertex_attrib_array(render_context.program_rectangle.texture_coord_attr as GLuint); + match render_context.program_2d { + Some(program) => { + enable_vertex_attrib_array(program.vertex_position_attr as GLuint); + enable_vertex_attrib_array(program.texture_coord_attr as GLuint); + }, + None => {} + } + + match render_context.program_rectangle { + Some(program) => { + enable_vertex_attrib_array(program.vertex_position_attr as GLuint); + enable_vertex_attrib_array(program.texture_coord_attr as GLuint); + }, + None=> {} + } render_context } @@ -208,6 +228,8 @@ pub fn init_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint { program } +#[cfg(target_os="linux")] +#[cfg(target_os="macos")] pub fn init_render_context() -> RenderContext { let vertex_2d_shader = load_shader(VERTEX_SHADER_SOURCE, VERTEX_SHADER); let fragment_2d_shader = load_shader(FRAGMENT_2D_SHADER_SOURCE, FRAGMENT_SHADER); @@ -220,7 +242,18 @@ pub fn init_render_context() -> RenderContext { enable(TEXTURE_2D); enable(TEXTURE_RECTANGLE_ARB); - RenderContext::new(program_2d, program_rectangle) + RenderContext::new(Some(program_2d), Some(program_rectangle)) +} + +#[cfg(target_os="android")] +pub fn init_render_context() -> RenderContext { + let vertex_2d_shader = load_shader(VERTEX_SHADER_SOURCE, VERTEX_SHADER); + let fragment_2d_shader = load_shader(FRAGMENT_2D_SHADER_SOURCE, FRAGMENT_SHADER); + let program_2d = init_program(vertex_2d_shader, fragment_2d_shader); + + enable(TEXTURE_2D); + + RenderContext::new(Some(program_2d), None) } fn bind_texture_coordinate_buffer(render_context: RenderContext, flip: Flip) { @@ -238,8 +271,14 @@ pub fn bind_and_render_quad(render_context: RenderContext, transform: &Matrix4, scene_size: Size2D) { let program_id = match texture.target { - TextureTarget2D => render_context.program_2d.id, - TextureTargetRectangle(*) => render_context.program_rectangle.id, + TextureTarget2D => match render_context.program_2d { + Some(program) => {program.id}, + None => {fail!("There is no shader program for texture 2D");} + }, + TextureTargetRectangle(*) => match render_context.program_rectangle { + Some(program) => {program.id}, + None => {fail!("There is no shader program for texture rectangle");} + }, }; use_program(program_id); @@ -252,42 +291,42 @@ pub fn bind_and_render_quad(render_context: RenderContext, // Set uniforms and vertex attribute pointers. match texture.target { TextureTarget2D => { - uniform_1i(render_context.program_2d.sampler_uniform, 0); - uniform_matrix_4fv(render_context.program_2d.modelview_uniform, + uniform_1i(render_context.program_2d.unwrap().sampler_uniform, 0); + uniform_matrix_4fv(render_context.program_2d.unwrap().modelview_uniform, false, transform.to_array()); - uniform_matrix_4fv(render_context.program_2d.projection_uniform, + uniform_matrix_4fv(render_context.program_2d.unwrap().projection_uniform, false, projection_matrix.to_array()); bind_buffer(ARRAY_BUFFER, render_context.buffers.vertex_buffer); - vertex_attrib_pointer_f32(render_context.program_2d.vertex_position_attr as GLuint, + vertex_attrib_pointer_f32(render_context.program_2d.unwrap().vertex_position_attr as GLuint, 3, false, 0, 0); bind_texture_coordinate_buffer(render_context, flip); - vertex_attrib_pointer_f32(render_context.program_2d.texture_coord_attr as GLuint, + vertex_attrib_pointer_f32(render_context.program_2d.unwrap().texture_coord_attr as GLuint, 2, false, 0, 0); } TextureTargetRectangle(size) => { - uniform_1i(render_context.program_rectangle.sampler_uniform, 0); - uniform_2f(render_context.program_rectangle.size_uniform, + uniform_1i(render_context.program_rectangle.unwrap().sampler_uniform, 0); + uniform_2f(render_context.program_rectangle.unwrap().size_uniform, size.width as GLfloat, size.height as GLfloat); - uniform_matrix_4fv(render_context.program_rectangle.modelview_uniform, + uniform_matrix_4fv(render_context.program_rectangle.unwrap().modelview_uniform, false, transform.to_array()); - uniform_matrix_4fv(render_context.program_rectangle.projection_uniform, + uniform_matrix_4fv(render_context.program_rectangle.unwrap().projection_uniform, false, projection_matrix.to_array()); bind_buffer(ARRAY_BUFFER, render_context.buffers.vertex_buffer); - vertex_attrib_pointer_f32(render_context.program_rectangle.vertex_position_attr as + vertex_attrib_pointer_f32(render_context.program_rectangle.unwrap().vertex_position_attr as GLuint, 3, false, @@ -295,7 +334,7 @@ pub fn bind_and_render_quad(render_context: RenderContext, 0); bind_texture_coordinate_buffer(render_context, flip); - vertex_attrib_pointer_f32(render_context.program_rectangle.texture_coord_attr as + vertex_attrib_pointer_f32(render_context.program_rectangle.unwrap().texture_coord_attr as GLuint, 2, false, From 73c96cf34ce2a52e0b8ff5a60d1d4fe52ba89402 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Fri, 20 Dec 2013 21:57:48 -0700 Subject: [PATCH 5/7] Upgrade to latest Rust. --- layers.rs | 16 ++++++++-------- lib.rs | 2 +- platform/android/surface.rs | 28 +++++++++------------------- platform/linux/surface.rs | 15 ++------------- platform/macos/surface.rs | 8 ++------ rendergl.rs | 2 +- scene.rs | 2 +- texturegl.rs | 6 +++--- util.rs | 4 ++-- 9 files changed, 29 insertions(+), 54 deletions(-) diff --git a/layers.rs b/layers.rs index 9d90163..2d5ec23 100644 --- a/layers.rs +++ b/layers.rs @@ -25,7 +25,7 @@ pub enum Layer { } impl Layer { - pub fn with_common(&self, f: &fn(&mut CommonLayer) -> T) -> T { + pub fn with_common(&self, f: |&mut CommonLayer| -> T) -> T { match *self { ContainerLayerKind(container_layer) => f(&mut container_layer.common), TextureLayerKind(texture_layer) => f(&mut texture_layer.common), @@ -113,7 +113,7 @@ impl ContainerLayer { assert!(first_child_common.prev_sibling.is_none()); first_child_common.prev_sibling = Some(new_child); new_child_common.next_sibling = Some(first_child); - }) + }); } } @@ -123,7 +123,7 @@ impl ContainerLayer { None => self.last_child = Some(new_child), Some(_) => {} } - }) + }); } /// Adds a child to the end of the list. @@ -143,7 +143,7 @@ impl ContainerLayer { assert!(last_child_common.next_sibling.is_none()); last_child_common.next_sibling = Some(new_child); new_child_common.prev_sibling = Some(last_child); - }) + }); } } @@ -153,7 +153,7 @@ impl ContainerLayer { None => self.first_child = Some(new_child), Some(_) => {} } - }) + }); } pub fn remove_child(@mut self, child: Layer) { @@ -173,7 +173,7 @@ impl ContainerLayer { Some(ref sibling) => { sibling.with_common(|sibling_common| { sibling_common.prev_sibling = child_common.prev_sibling; - }) + }); } } match child_common.prev_sibling { @@ -183,10 +183,10 @@ impl ContainerLayer { Some(ref sibling) => { sibling.with_common(|sibling_common| { sibling_common.next_sibling = child_common.next_sibling; - }) + }); } } - }) + }); } } diff --git a/lib.rs b/lib.rs index ab67bb3..f7cffb7 100755 --- a/lib.rs +++ b/lib.rs @@ -7,7 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[link(name = "layers", vers = "0.1")]; +#[crate_id = "github.com/mozilla-servo/rust-layers#layers:0.1"]; #[feature(managed_boxes)]; diff --git a/platform/android/surface.rs b/platform/android/surface.rs index a7f8916..17c3d39 100644 --- a/platform/android/surface.rs +++ b/platform/android/surface.rs @@ -13,15 +13,14 @@ use platform::surface::NativeSurfaceMethods; use texturegl::Texture; use geom::size::Size2D; -use opengles::gl2::{egl_image_target_texture2d_oes, TEXTURE_2D, GLsizei, GLint, glTexImage2D, BGRA, UNSIGNED_BYTE}; +use opengles::gl2::{egl_image_target_texture2d_oes, TEXTURE_2D, glTexImage2D, BGRA, UNSIGNED_BYTE}; use egl::egl::EGLDisplay; -use egl::eglext::{EGLImageKHR, CreateImageKHR, DestroyImageKHR}; +use egl::eglext::{EGLImageKHR, DestroyImageKHR}; use std::cast; use std::ptr; use std::util; use std::vec; use std::libc::c_void; -use std::vec::bytes; /// FIXME(Aydin Kim) :Currently, native surface is consist of 2 types of hybrid image buffer. EGLImageKHR is used to GPU rendering and vector is used to CPU rendering. EGL extension seems not provide simple way to accessing its bitmap directly. In the future, we need to find out the way to integrate them. @@ -34,18 +33,14 @@ pub struct NativePaintingGraphicsContext{ } impl NativePaintingGraphicsContext { - #[fixed_stack_segment] pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext { - unsafe { - NativePaintingGraphicsContext { - display : metadata.display, - } - } + NativePaintingGraphicsContext { + display : metadata.display, + } } } impl Drop for NativePaintingGraphicsContext { - #[fixed_stack_segment] fn drop(&mut self) {} } @@ -68,7 +63,6 @@ pub struct NativeSurface { } impl NativeSurface { - #[fixed_stack_segment] pub fn from_image_khr(image_khr: EGLImageKHR) -> NativeSurface { let mut _image: Option = None; if image_khr != ptr::null() { @@ -84,8 +78,7 @@ impl NativeSurface { impl NativeSurfaceMethods for NativeSurface { /// This may only be called on the case of CPU rendering. - #[fixed_stack_segment] - fn new(native_context: &NativePaintingGraphicsContext, size: Size2D, stride: i32) -> NativeSurface { + fn new(_native_context: &NativePaintingGraphicsContext, size: Size2D, _stride: i32) -> NativeSurface { unsafe { let len = size.width * size.height * 4; let bitmap = vec::from_elem::(len as uint, 0); @@ -99,9 +92,8 @@ impl NativeSurfaceMethods for NativeSurface { } /// This may only be called on the compositor side. - #[fixed_stack_segment] fn bind_to_texture(&self, - native_context: &NativeCompositingGraphicsContext, + _native_context: &NativeCompositingGraphicsContext, texture: &Texture, _size: Size2D) { let _bound = texture.bind(); @@ -124,12 +116,11 @@ impl NativeSurfaceMethods for NativeSurface { } /// This may only be called on the painting side. - #[fixed_stack_segment] - fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) { + fn upload(&self, _graphics_context: &NativePaintingGraphicsContext, data: &[u8]) { unsafe { if self.bitmap != ptr::null() { let dest:&mut [u8] = cast::transmute((self.bitmap, data.len())); - bytes::copy_memory(dest, data, data.len()); + dest.copy_memory(data); } else { debug!("Cannot upload the buffer(CPU rendering), there is no bitmap"); @@ -144,7 +135,6 @@ impl NativeSurfaceMethods for NativeSurface { } } -#[fixed_stack_segment] fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) { match self.image { None => {}, diff --git a/platform/linux/surface.rs b/platform/linux/surface.rs index 8881f88..231625a 100644 --- a/platform/linux/surface.rs +++ b/platform/linux/surface.rs @@ -39,12 +39,11 @@ pub struct NativePaintingGraphicsContext { } impl NativePaintingGraphicsContext { - #[fixed_stack_segment] pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext { unsafe { - let display = do metadata.display.with_c_str |c_str| { + let display = metadata.display.with_c_str(|c_str| { XOpenDisplay(c_str) - }; + }); if display.is_null() { fail!("XOpenDisplay() failed!"); @@ -64,7 +63,6 @@ impl NativePaintingGraphicsContext { } impl Drop for NativePaintingGraphicsContext { - #[fixed_stack_segment] fn drop(&mut self) { unsafe { let _ = XCloseDisplay(self.display); @@ -91,7 +89,6 @@ impl NativeCompositingGraphicsContext { /// Chooses the compositor visual info using the same algorithm that the compositor uses. /// /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual. - #[fixed_stack_segment] fn compositor_visual_info(display: *Display) -> *XVisualInfo { unsafe { let glx_display: *glx::Display = cast::transmute(display); @@ -104,7 +101,6 @@ impl NativeCompositingGraphicsContext { /// Creates a native graphics context from the given X display connection. This uses GLX. Only /// the compositor is allowed to call this. - #[fixed_stack_segment] pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext { unsafe { // FIXME(pcwalton): It would be more robust to actually have the compositor pass the @@ -167,7 +163,6 @@ pub struct NativeGraphicsMetadata { impl NativeGraphicsMetadata { /// Creates graphics metadata from a metadata descriptor. - #[fixed_stack_segment] pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor) -> NativeGraphicsMetadata { NativeGraphicsMetadata { @@ -184,7 +179,6 @@ pub struct NativeGraphicsMetadataDescriptor { impl NativeGraphicsMetadataDescriptor { /// Creates a metadata descriptor from metadata. - #[fixed_stack_segment] pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor { NativeGraphicsMetadataDescriptor { display: metadata.display.to_str() @@ -217,7 +211,6 @@ impl Drop for NativeSurface { } impl NativeSurface { - #[fixed_stack_segment] pub fn from_pixmap(pixmap: Pixmap) -> NativeSurface { NativeSurface { pixmap: pixmap, @@ -227,7 +220,6 @@ impl NativeSurface { } impl NativeSurfaceMethods for NativeSurface { - #[fixed_stack_segment] fn new(native_context: &NativePaintingGraphicsContext, size: Size2D, stride: i32) -> NativeSurface { unsafe { @@ -246,7 +238,6 @@ impl NativeSurfaceMethods for NativeSurface { } /// This may only be called on the compositor side. - #[fixed_stack_segment] fn bind_to_texture(&self, native_context: &NativeCompositingGraphicsContext, texture: &Texture, @@ -282,7 +273,6 @@ impl NativeSurfaceMethods for NativeSurface { } /// This may only be called on the painting side. - #[fixed_stack_segment] fn upload(&self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) { unsafe { // Ensure that we're running on the render task. Take the display. @@ -339,7 +329,6 @@ impl NativeSurfaceMethods for NativeSurface { self.pixmap as int } - #[fixed_stack_segment] fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) { unsafe { assert!(self.pixmap != 0); diff --git a/platform/macos/surface.rs b/platform/macos/surface.rs index d7f7991..671bf9f 100644 --- a/platform/macos/surface.rs +++ b/platform/macos/surface.rs @@ -24,7 +24,6 @@ use opengles::cgl::{CGLChoosePixelFormat, CGLDescribePixelFormat, CGLPixelFormat use opengles::cgl::{CGLPixelFormatObj, CORE_BOOLEAN_ATTRIBUTES, CORE_INTEGER_ATTRIBUTES}; use opengles::cgl::{kCGLNoError}; use opengles::gl2::GLint; -use std::cell::Cell; use std::hashmap::HashMap; use std::local_data; use std::ptr; @@ -48,7 +47,6 @@ impl NativeGraphicsMetadata { } } - #[fixed_stack_segment] pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor) -> NativeGraphicsMetadata { unsafe { @@ -86,7 +84,6 @@ pub struct NativeGraphicsMetadataDescriptor { } impl NativeGraphicsMetadataDescriptor { - #[fixed_stack_segment] pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor { unsafe { let mut descriptor = NativeGraphicsMetadataDescriptor { @@ -148,18 +145,17 @@ pub struct NativeSurface { } impl NativeSurface { - #[fixed_stack_segment] pub fn from_io_surface(io_surface: IOSurface) -> NativeSurface { // Take the surface by ID (so that we can send it cross-process) and consume its reference. let id = io_surface.get_id(); - let io_surface_cell = Cell::new(io_surface); + let mut io_surface = Some(io_surface); local_data::modify(io_surface_repository, |opt_repository| { let mut repository = match opt_repository { None => HashMap::new(), Some(repository) => repository, }; - repository.insert(id, io_surface_cell.take()); + repository.insert(id, io_surface.take().unwrap()); Some(repository) }); diff --git a/rendergl.rs b/rendergl.rs index c6ecd16..9db6269 100755 --- a/rendergl.rs +++ b/rendergl.rs @@ -275,7 +275,7 @@ pub fn bind_and_render_quad(render_context: RenderContext, Some(program) => {program.id}, None => {fail!("There is no shader program for texture 2D");} }, - TextureTargetRectangle(*) => match render_context.program_rectangle { + TextureTargetRectangle(..) => match render_context.program_rectangle { Some(program) => {program.id}, None => {fail!("There is no shader program for texture rectangle");} }, diff --git a/scene.rs b/scene.rs index a900070..772d464 100755 --- a/scene.rs +++ b/scene.rs @@ -35,7 +35,7 @@ pub fn Scene(root: Layer, size: Size2D, transform: Matrix4) -> Scene { impl Scene { // FIXME: Workaround for cross-crate bug regarding mutability of class fields - fn set_transform(&mut self, new_transform: Matrix4) { + pub fn set_transform(&mut self, new_transform: Matrix4) { self.transform = new_transform; } } diff --git a/texturegl.rs b/texturegl.rs index 4eeb7cb..8326711 100644 --- a/texturegl.rs +++ b/texturegl.rs @@ -19,11 +19,11 @@ use opengles::gl2; use std::num::Zero; /// Image data used when uploading to a texture. -pub struct TextureImageData<'self> { +pub struct TextureImageData<'a> { size: Size2D, stride: uint, format: Format, - data: &'self [u8], + data: &'a [u8], } /// The texture target. @@ -38,7 +38,7 @@ impl TextureTarget { fn as_gl_target(self) -> GLenum { match self { TextureTarget2D => TEXTURE_2D, - TextureTargetRectangle(*) => TEXTURE_RECTANGLE_ARB, + TextureTargetRectangle(_) => TEXTURE_RECTANGLE_ARB, } } } diff --git a/util.rs b/util.rs index 74bf688..62e2b89 100644 --- a/util.rs +++ b/util.rs @@ -9,11 +9,11 @@ // Miscellaneous utilities. -use std::vec::from_fn; +use std::vec; pub fn convert_rgb32_to_rgb24(buffer: ~[u8]) -> ~[u8] { let mut i = 0; - from_fn(buffer.len() * 3 / 4, |j| { + vec::from_fn(buffer.len() * 3 / 4, |j| { match j % 3 { 0 => { buffer[i + 2] From 952852a7ad8c5fd6da12a5ac6f834cd8a91880ff Mon Sep 17 00:00:00 2001 From: Lars Bergstrom Date: Sat, 30 Nov 2013 18:11:07 -0600 Subject: [PATCH 6/7] Distinguish 1.3+ from pre-1.3 GLX. On 1.3+, ensure we pick a visual and fbconfig that support RGBA. --- platform/linux/surface.rs | 135 +++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/platform/linux/surface.rs b/platform/linux/surface.rs index 231625a..5821682 100644 --- a/platform/linux/surface.rs +++ b/platform/linux/surface.rs @@ -13,13 +13,15 @@ use platform::surface::NativeSurfaceMethods; use texturegl::Texture; use geom::size::Size2D; -use opengles::glx::{GLXFBConfig, GLXDrawable, GLX_BIND_TO_TEXTURE_RGBA_EXT}; +use opengles::glx::{GLXFBConfig, GLXDrawable}; +use opengles::glx::{GLX_BIND_TO_TEXTURE_RGBA_EXT}; use opengles::glx::{GLX_DEPTH_SIZE, GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT, GLX_RGBA}; use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT}; use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXChooseVisual, glXCreatePixmap, glXDestroyPixmap}; -use opengles::glx::{glXGetProcAddress, glXGetFBConfigAttrib, glXGetFBConfigs}; -use opengles::glx::{glXGetVisualFromFBConfig}; -use opengles::glx; +use opengles::glx::{glXCreateGLXPixmap, glXDestroyGLXPixmap}; +use opengles::glx::{glXGetProcAddress, glXChooseFBConfig}; +use opengles::glx::{glXGetVisualFromFBConfig, glXQueryVersion, get_version}; +use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_ALPHA_SIZE, GLX_DOUBLEBUFFER}; use opengles::gl2::NO_ERROR; use opengles::gl2; use std::cast; @@ -51,7 +53,7 @@ impl NativePaintingGraphicsContext { // FIXME(pcwalton): It would be more robust to actually have the compositor pass the // visual. - let compositor_visual_info = + let (compositor_visual_info, _) = NativeCompositingGraphicsContext::compositor_visual_info(display); NativePaintingGraphicsContext { @@ -82,20 +84,50 @@ impl Drop for NativePaintingGraphicsContext { pub struct NativeCompositingGraphicsContext { display: *Display, visual_info: *XVisualInfo, - framebuffer_configuration: GLXFBConfig, + framebuffer_configuration: Option, + major: int, + minor: int, } impl NativeCompositingGraphicsContext { /// Chooses the compositor visual info using the same algorithm that the compositor uses. /// /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual. - fn compositor_visual_info(display: *Display) -> *XVisualInfo { + fn compositor_visual_info(display: *Display) -> (*XVisualInfo, Option) { unsafe { - let glx_display: *glx::Display = cast::transmute(display); - let screen = XDefaultScreen(display); - let attributes = [ GLX_RGBA, GLX_DEPTH_SIZE, 24, 0 ]; - let compositor_visual_info = glXChooseVisual(glx_display, screen, &attributes[0]); - cast::transmute(compositor_visual_info) + let glx_display = cast::transmute(display); + let (major, minor) = get_version(glx_display); + + if (major >= 1 && minor >= 3) { + // CONSIDER: + // In skia, they compute the GLX_ALPHA_SIZE minimum and request + // that as well. + + let fbconfig_attributes = [ + GLX_DOUBLEBUFFER, 0, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT, + GLX_BIND_TO_TEXTURE_RGBA_EXT, 1, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + 0 + ]; + + let screen = XDefaultScreen(display); + let mut configs = 0; + let fbconfigs = glXChooseFBConfig(glx_display, screen, + &fbconfig_attributes[0], &mut configs); + if (configs == 0) { + fail!("Unable to locate a GLX FB configuration that supports RGBA."); + } + + let fbconfig = *ptr::offset(fbconfigs, 0); + let vi = glXGetVisualFromFBConfig(glx_display, fbconfig); + (cast::transmute(vi), Some(fbconfig)) + } else { + let screen = XDefaultScreen(display); + let attributes = [ GLX_RGBA, GLX_DEPTH_SIZE, 24, 0 ]; + let vi = glXChooseVisual(glx_display, screen, &attributes[0]); + (cast::transmute(vi), None) + } } } @@ -103,53 +135,19 @@ impl NativeCompositingGraphicsContext { /// the compositor is allowed to call this. pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext { unsafe { - // FIXME(pcwalton): It would be more robust to actually have the compositor pass the - // visual. - let compositor_visual_info = - NativeCompositingGraphicsContext::compositor_visual_info(display); - let compositor_visual_id = (*compositor_visual_info).visualid; - // Choose an FB config. + let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display); let glx_display = cast::transmute(display); - let screen = XDefaultScreen(display); - let mut fbconfig_count = 0; - let fbconfigs = glXGetFBConfigs(glx_display, screen, &mut fbconfig_count); - let mut fbconfig_index = None; - for i in range(0, fbconfig_count) { - let fbconfig = *ptr::offset(fbconfigs, i as int); - let visual_info = glXGetVisualFromFBConfig(glx_display, fbconfig); - let visual_info: *XVisualInfo = cast::transmute(visual_info); - if visual_info == ptr::null() || (*visual_info).visualid != compositor_visual_id { - continue - } - - let mut value = 0; - glXGetFBConfigAttrib(glx_display, fbconfig, GLX_DRAWABLE_TYPE, &mut value); - if (value & GLX_PIXMAP_BIT) == 0 { - continue - } - - glXGetFBConfigAttrib(glx_display, - fbconfig, - GLX_BIND_TO_TEXTURE_RGBA_EXT, - &mut value); - if value == 0 { - continue - } - - fbconfig_index = Some(i); - break - } - - let framebuffer_configuration = match fbconfig_index { - None => fail!("No appropriate framebuffer config found!"), - Some(index) => *ptr::offset(fbconfigs, index as int), - }; - + let mut major = 0; + let mut minor = 0; + glXQueryVersion(glx_display, &mut major, &mut minor); + NativeCompositingGraphicsContext { display: display, - visual_info: compositor_visual_info, - framebuffer_configuration: framebuffer_configuration, + visual_info: visual_info, + framebuffer_configuration: fbconfig, + major: major as int, + minor: minor as int, } } } @@ -226,13 +224,11 @@ impl NativeSurfaceMethods for NativeSurface { // Create the pixmap. let screen = XDefaultScreen(native_context.display); let window = XRootWindow(native_context.display, screen); - let pixmap = XCreatePixmap(native_context.display, window, size.width as c_uint, size.height as c_uint, ((stride / size.width) * 8) as c_uint); - NativeSurface::from_pixmap(pixmap) } } @@ -251,11 +247,22 @@ impl NativeSurfaceMethods for NativeSurface { GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, 0 ]; + let glx_display = cast::transmute(native_context.display); - let glx_pixmap = glXCreatePixmap(glx_display, - native_context.framebuffer_configuration, - self.pixmap, - &pixmap_attributes[0]); + let (major, minor) = get_version(glx_display); + + let glx_pixmap = if (major == 1 && minor < 3) { + let glx_visual_info = cast::transmute(native_context.visual_info); + glXCreateGLXPixmap(glx_display, + glx_visual_info, + self.pixmap) + } else { + glXCreatePixmap(glx_display, + native_context.framebuffer_configuration.expect( + "GLX 1.3 should have a framebuffer_configuration"), + self.pixmap, + &pixmap_attributes[0]) + }; let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) = cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0]))); @@ -268,7 +275,11 @@ impl NativeSurfaceMethods for NativeSurface { assert_eq!(gl2::get_error(), NO_ERROR); // FIXME(pcwalton): Recycle these for speed? - glXDestroyPixmap(glx_display, glx_pixmap); + if (major == 1 && minor < 3) { + glXDestroyGLXPixmap(glx_display, glx_pixmap); + } else { + glXDestroyPixmap(glx_display, glx_pixmap); + } } } From 811807c4e9e19848a6dab84e76d7e2ea26671146 Mon Sep 17 00:00:00 2001 From: Lars Bergstrom Date: Sun, 15 Dec 2013 19:01:32 -0600 Subject: [PATCH 7/7] Always use the same display connection --- platform/linux/surface.rs | 180 ++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 106 deletions(-) diff --git a/platform/linux/surface.rs b/platform/linux/surface.rs index 5821682..8295ff2 100644 --- a/platform/linux/surface.rs +++ b/platform/linux/surface.rs @@ -15,24 +15,24 @@ use texturegl::Texture; use geom::size::Size2D; use opengles::glx::{GLXFBConfig, GLXDrawable}; use opengles::glx::{GLX_BIND_TO_TEXTURE_RGBA_EXT}; -use opengles::glx::{GLX_DEPTH_SIZE, GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT, GLX_RGBA}; +use opengles::glx::{GLX_DRAWABLE_TYPE, GLX_FRONT_EXT, GLX_PIXMAP_BIT}; use opengles::glx::{GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT}; -use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXChooseVisual, glXCreatePixmap, glXDestroyPixmap}; -use opengles::glx::{glXCreateGLXPixmap, glXDestroyGLXPixmap}; +use opengles::glx::{GLX_TEXTURE_TARGET_EXT, glXCreatePixmap, glXDestroyPixmap}; use opengles::glx::{glXGetProcAddress, glXChooseFBConfig}; -use opengles::glx::{glXGetVisualFromFBConfig, glXQueryVersion, get_version}; -use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_ALPHA_SIZE, GLX_DOUBLEBUFFER}; +use opengles::glx::{glXGetVisualFromFBConfig}; +use opengles::glx::{GLX_RGBA_BIT, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_DOUBLEBUFFER}; use opengles::gl2::NO_ERROR; use opengles::gl2; use std::cast; +use std::c_str::CString; use std::libc::{c_int, c_uint, c_void}; use std::ptr; -use xlib::xlib::{Display, Pixmap, XCloseDisplay, XCreateGC, XCreateImage, XCreatePixmap}; -use xlib::xlib::{XDefaultScreen, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow}; +use xlib::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen}; +use xlib::xlib::{XDisplayString, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage, XRootWindow}; use xlib::xlib::{XVisualInfo, ZPixmap}; -/// The display and visual info. This is needed in order to upload on the painting side. This holds -/// a *strong* reference to the display and will close it when done. +/// The display and visual info. This is needed in order to upload on the painting side. This +/// holds a weak reference to the display and will not close it when done. /// /// FIXME(pcwalton): Mark nonsendable and noncopyable. pub struct NativePaintingGraphicsContext { @@ -42,32 +42,14 @@ pub struct NativePaintingGraphicsContext { impl NativePaintingGraphicsContext { pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext { - unsafe { - let display = metadata.display.with_c_str(|c_str| { - XOpenDisplay(c_str) - }); - - if display.is_null() { - fail!("XOpenDisplay() failed!"); - } - - // FIXME(pcwalton): It would be more robust to actually have the compositor pass the - // visual. - let (compositor_visual_info, _) = - NativeCompositingGraphicsContext::compositor_visual_info(display); - - NativePaintingGraphicsContext { - display: display, - visual_info: compositor_visual_info, - } - } - } -} - -impl Drop for NativePaintingGraphicsContext { - fn drop(&mut self) { - unsafe { - let _ = XCloseDisplay(self.display); + // FIXME(pcwalton): It would be more robust to actually have the compositor pass the + // visual. + let (compositor_visual_info, _) = + NativeCompositingGraphicsContext::compositor_visual_info(metadata.display); + + NativePaintingGraphicsContext { + display: metadata.display, + visual_info: compositor_visual_info, } } } @@ -85,8 +67,6 @@ pub struct NativeCompositingGraphicsContext { display: *Display, visual_info: *XVisualInfo, framebuffer_configuration: Option, - major: int, - minor: int, } impl NativeCompositingGraphicsContext { @@ -96,75 +76,72 @@ impl NativeCompositingGraphicsContext { fn compositor_visual_info(display: *Display) -> (*XVisualInfo, Option) { unsafe { let glx_display = cast::transmute(display); - let (major, minor) = get_version(glx_display); - - if (major >= 1 && minor >= 3) { - // CONSIDER: - // In skia, they compute the GLX_ALPHA_SIZE minimum and request - // that as well. - - let fbconfig_attributes = [ - GLX_DOUBLEBUFFER, 0, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT, - GLX_BIND_TO_TEXTURE_RGBA_EXT, 1, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - 0 - ]; - - let screen = XDefaultScreen(display); - let mut configs = 0; - let fbconfigs = glXChooseFBConfig(glx_display, screen, - &fbconfig_attributes[0], &mut configs); - if (configs == 0) { - fail!("Unable to locate a GLX FB configuration that supports RGBA."); - } - - let fbconfig = *ptr::offset(fbconfigs, 0); - let vi = glXGetVisualFromFBConfig(glx_display, fbconfig); - (cast::transmute(vi), Some(fbconfig)) - } else { - let screen = XDefaultScreen(display); - let attributes = [ GLX_RGBA, GLX_DEPTH_SIZE, 24, 0 ]; - let vi = glXChooseVisual(glx_display, screen, &attributes[0]); - (cast::transmute(vi), None) + + // CONSIDER: + // In skia, they compute the GLX_ALPHA_SIZE minimum and request + // that as well. + + let fbconfig_attributes = [ + GLX_DOUBLEBUFFER, 0, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT, + GLX_BIND_TO_TEXTURE_RGBA_EXT, 1, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + 0 + ]; + + let screen = XDefaultScreen(display); + let mut configs = 0; + let fbconfigs = glXChooseFBConfig(glx_display, screen, + &fbconfig_attributes[0], &mut configs); + if (configs == 0) { + fail!("Unable to locate a GLX FB configuration that supports RGBA."); } + + let fbconfig = *ptr::offset(fbconfigs, 0); + let vi = glXGetVisualFromFBConfig(glx_display, fbconfig); + (cast::transmute(vi), Some(fbconfig)) } } /// Creates a native graphics context from the given X display connection. This uses GLX. Only /// the compositor is allowed to call this. pub fn from_display(display: *Display) -> NativeCompositingGraphicsContext { - unsafe { + let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display); - let (visual_info, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display); - let glx_display = cast::transmute(display); - let mut major = 0; - let mut minor = 0; - glXQueryVersion(glx_display, &mut major, &mut minor); - - NativeCompositingGraphicsContext { - display: display, - visual_info: visual_info, - framebuffer_configuration: fbconfig, - major: major as int, - minor: minor as int, - } + NativeCompositingGraphicsContext { + display: display, + visual_info: visual_info, + framebuffer_configuration: fbconfig, } } } -/// The X display string. +/// The X display. #[deriving(Clone)] pub struct NativeGraphicsMetadata { - display: ~str, + display: *Display, } impl NativeGraphicsMetadata { /// Creates graphics metadata from a metadata descriptor. pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor) -> NativeGraphicsMetadata { - NativeGraphicsMetadata { - display: descriptor.display.to_str(), + // WARNING: We currently rely on the X display connection being the + // same in both the Painting and Compositing contexts, as otherwise + // the X Pixmap will not be sharable across them. Using this + // method breaks that assumption. + unsafe { + let display = do descriptor.display.with_c_str |c_str| { + XOpenDisplay(c_str) + }; + + if display.is_null() { + fail!("XOpenDisplay() failed!"); + } + + NativeGraphicsMetadata { + display: display, + } } } } @@ -178,8 +155,11 @@ pub struct NativeGraphicsMetadataDescriptor { impl NativeGraphicsMetadataDescriptor { /// Creates a metadata descriptor from metadata. pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor { - NativeGraphicsMetadataDescriptor { - display: metadata.display.to_str() + unsafe { + let c_str = CString::new(XDisplayString(metadata.display), false); + NativeGraphicsMetadataDescriptor { + display: c_str.as_str().unwrap().to_str(), + } } } } @@ -249,20 +229,12 @@ impl NativeSurfaceMethods for NativeSurface { ]; let glx_display = cast::transmute(native_context.display); - let (major, minor) = get_version(glx_display); - let glx_pixmap = if (major == 1 && minor < 3) { - let glx_visual_info = cast::transmute(native_context.visual_info); - glXCreateGLXPixmap(glx_display, - glx_visual_info, - self.pixmap) - } else { - glXCreatePixmap(glx_display, - native_context.framebuffer_configuration.expect( - "GLX 1.3 should have a framebuffer_configuration"), - self.pixmap, - &pixmap_attributes[0]) - }; + let glx_pixmap = glXCreatePixmap(glx_display, + native_context.framebuffer_configuration.expect( + "GLX 1.3 should have a framebuffer_configuration"), + self.pixmap, + &pixmap_attributes[0]); let glXBindTexImageEXT: extern "C" fn(*Display, GLXDrawable, c_int, *c_int) = cast::transmute(glXGetProcAddress(cast::transmute(&"glXBindTexImageEXT\x00"[0]))); @@ -275,11 +247,7 @@ impl NativeSurfaceMethods for NativeSurface { assert_eq!(gl2::get_error(), NO_ERROR); // FIXME(pcwalton): Recycle these for speed? - if (major == 1 && minor < 3) { - glXDestroyGLXPixmap(glx_display, glx_pixmap); - } else { - glXDestroyPixmap(glx_display, glx_pixmap); - } + glXDestroyPixmap(glx_display, glx_pixmap); } }