Add errors throughout
This commit is contained in:
parent
78c03a9594
commit
5453afa7a1
|
@ -8,6 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use error::GlError;
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
use gl::types::{GLenum, GLsizei, GLsizeiptr, GLuint, GLvoid};
|
use gl::types::{GLenum, GLsizei, GLsizeiptr, GLuint, GLvoid};
|
||||||
use gl;
|
use gl;
|
||||||
|
@ -34,6 +35,8 @@ impl AtlasBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an error if there is no space left for the glyph in the atlas.
|
||||||
|
///
|
||||||
/// FIXME(pcwalton): Support the same glyph drawn at multiple point sizes.
|
/// FIXME(pcwalton): Support the same glyph drawn at multiple point sizes.
|
||||||
pub fn pack_glyph(&mut self,
|
pub fn pack_glyph(&mut self,
|
||||||
outline_builder: &OutlineBuilder,
|
outline_builder: &OutlineBuilder,
|
||||||
|
@ -74,7 +77,7 @@ impl AtlasBuilder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_atlas(&mut self, outline_builder: &OutlineBuilder) -> Result<Atlas, ()> {
|
pub fn create_atlas(&mut self, outline_builder: &OutlineBuilder) -> Result<Atlas, GlError> {
|
||||||
self.image_metadata.sort_by(|a, b| a.glyph_index.cmp(&b.glyph_index));
|
self.image_metadata.sort_by(|a, b| a.glyph_index.cmp(&b.glyph_index));
|
||||||
|
|
||||||
let (mut current_range, mut counts, mut start_indices) = (None, vec![], vec![]);
|
let (mut current_range, mut counts, mut start_indices) = (None, vec![], vec![]);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use compute_shader::buffer::Protection;
|
use compute_shader::buffer::Protection;
|
||||||
use compute_shader::device::Device;
|
use compute_shader::device::Device;
|
||||||
use compute_shader::image::{ExternalImage, Format, Image};
|
use compute_shader::image::{ExternalImage, Format, Image};
|
||||||
|
use error::InitError;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use gl::types::{GLint, GLuint};
|
use gl::types::{GLint, GLuint};
|
||||||
use gl;
|
use gl;
|
||||||
|
@ -21,15 +22,16 @@ pub struct CoverageBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoverageBuffer {
|
impl CoverageBuffer {
|
||||||
pub fn new(device: &Device, size: &Size2D<u32>) -> Result<CoverageBuffer, ()> {
|
pub fn new(device: &Device, size: &Size2D<u32>) -> Result<CoverageBuffer, InitError> {
|
||||||
let image = try!(device.create_image(Format::R32F, Protection::ReadWrite, size)
|
let image = try!(device.create_image(Format::R32F, Protection::ReadWrite, size)
|
||||||
.map_err(drop));
|
.map_err(InitError::ComputeError));
|
||||||
|
|
||||||
let mut framebuffer = 0;
|
let mut framebuffer = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut gl_texture = 0;
|
let mut gl_texture = 0;
|
||||||
gl::GenTextures(1, &mut gl_texture);
|
gl::GenTextures(1, &mut gl_texture);
|
||||||
try!(image.bind_to(&ExternalImage::GlTexture(gl_texture)).map_err(drop));
|
try!(image.bind_to(&ExternalImage::GlTexture(gl_texture))
|
||||||
|
.map_err(InitError::ComputeError));
|
||||||
|
|
||||||
gl::BindTexture(gl::TEXTURE_RECTANGLE, gl_texture);
|
gl::BindTexture(gl::TEXTURE_RECTANGLE, gl_texture);
|
||||||
gl::TexParameteri(gl::TEXTURE_RECTANGLE, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
|
gl::TexParameteri(gl::TEXTURE_RECTANGLE, gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2017 The Servo Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Errors.
|
||||||
|
|
||||||
|
use compute_shader;
|
||||||
|
use gl::types::GLenum;
|
||||||
|
|
||||||
|
/// An OpenGL error with the given code.
|
||||||
|
///
|
||||||
|
/// You cannot depend on these being reliably returned. Pathfinder does not call `glGetError()`
|
||||||
|
/// unless necessary, to avoid driver stalls.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
|
pub struct GlError(pub GLenum);
|
||||||
|
|
||||||
|
/// An initialization error. This could be an OpenGL error or a shader compilation/link error.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InitError {
|
||||||
|
GlError(GlError),
|
||||||
|
CompileFailed(&'static str, String),
|
||||||
|
LinkFailed(String),
|
||||||
|
ComputeError(compute_shader::error::Error),
|
||||||
|
/// One of the rasterization options had an invalid syntax.
|
||||||
|
InvalidSetting,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A rasterization error. This could be an OpenGL error or a compute error.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RasterError {
|
||||||
|
GlError(GlError),
|
||||||
|
ComputeError(compute_shader::error::Error),
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern crate test;
|
||||||
pub mod atlas;
|
pub mod atlas;
|
||||||
pub mod charmap;
|
pub mod charmap;
|
||||||
pub mod coverage;
|
pub mod coverage;
|
||||||
|
pub mod error;
|
||||||
pub mod glyph_range;
|
pub mod glyph_range;
|
||||||
pub mod otf;
|
pub mod otf;
|
||||||
pub mod outline;
|
pub mod outline;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use error::GlError;
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
use gl::types::{GLsizeiptr, GLuint};
|
use gl::types::{GLsizeiptr, GLuint};
|
||||||
use gl;
|
use gl;
|
||||||
|
@ -95,7 +96,7 @@ impl OutlineBuilder {
|
||||||
self.descriptors[glyph_index as usize].glyph_id
|
self.descriptors[glyph_index as usize].glyph_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_buffers(&self) -> Result<OutlineBuffers, ()> {
|
pub fn create_buffers(&self) -> Result<OutlineBuffers, GlError> {
|
||||||
// TODO(pcwalton): Try using `glMapBuffer` here. Requires precomputing contour types and
|
// TODO(pcwalton): Try using `glMapBuffer` here. Requires precomputing contour types and
|
||||||
// counts.
|
// counts.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -16,6 +16,7 @@ use compute_shader::profile_event::ProfileEvent;
|
||||||
use compute_shader::program::Program;
|
use compute_shader::program::Program;
|
||||||
use compute_shader::queue::{Queue, Uniform};
|
use compute_shader::queue::{Queue, Uniform};
|
||||||
use coverage::CoverageBuffer;
|
use coverage::CoverageBuffer;
|
||||||
|
use error::{InitError, RasterError};
|
||||||
use euclid::rect::Rect;
|
use euclid::rect::Rect;
|
||||||
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint, GLvoid};
|
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint, GLvoid};
|
||||||
use gl;
|
use gl;
|
||||||
|
@ -58,7 +59,7 @@ pub struct DrawAtlasProfilingEvents {
|
||||||
|
|
||||||
impl Rasterizer {
|
impl Rasterizer {
|
||||||
pub fn new(instance: &Instance, device: Device, queue: Queue, options: RasterizerOptions)
|
pub fn new(instance: &Instance, device: Device, queue: Queue, options: RasterizerOptions)
|
||||||
-> Result<Rasterizer, ()> {
|
-> Result<Rasterizer, InitError> {
|
||||||
let (draw_program, draw_position_attribute, draw_glyph_index_attribute);
|
let (draw_program, draw_position_attribute, draw_glyph_index_attribute);
|
||||||
let (draw_glyph_descriptors_uniform, draw_image_descriptors_uniform);
|
let (draw_glyph_descriptors_uniform, draw_image_descriptors_uniform);
|
||||||
let draw_atlas_size_uniform;
|
let draw_atlas_size_uniform;
|
||||||
|
@ -96,9 +97,8 @@ impl Rasterizer {
|
||||||
|
|
||||||
try!(check_gl_object_status(draw_program,
|
try!(check_gl_object_status(draw_program,
|
||||||
gl::LINK_STATUS,
|
gl::LINK_STATUS,
|
||||||
"Program",
|
|
||||||
gl::GetProgramiv,
|
gl::GetProgramiv,
|
||||||
gl::GetProgramInfoLog));
|
gl::GetProgramInfoLog).map_err(InitError::LinkFailed));
|
||||||
|
|
||||||
gl::GenVertexArrays(1, &mut draw_vertex_array);
|
gl::GenVertexArrays(1, &mut draw_vertex_array);
|
||||||
|
|
||||||
|
@ -124,7 +124,9 @@ impl Rasterizer {
|
||||||
ShadingLanguage::Cl => ACCUM_CL_SHADER,
|
ShadingLanguage::Cl => ACCUM_CL_SHADER,
|
||||||
ShadingLanguage::Glsl => ACCUM_COMPUTE_SHADER,
|
ShadingLanguage::Glsl => ACCUM_COMPUTE_SHADER,
|
||||||
};
|
};
|
||||||
let accum_program = device.create_program(accum_source).unwrap();
|
|
||||||
|
let accum_program = try!(device.create_program(accum_source)
|
||||||
|
.map_err(InitError::ComputeError));
|
||||||
|
|
||||||
Ok(Rasterizer {
|
Ok(Rasterizer {
|
||||||
device: device,
|
device: device,
|
||||||
|
@ -148,7 +150,7 @@ impl Rasterizer {
|
||||||
atlas: &Atlas,
|
atlas: &Atlas,
|
||||||
outline_buffers: &OutlineBuffers,
|
outline_buffers: &OutlineBuffers,
|
||||||
coverage_buffer: &CoverageBuffer)
|
coverage_buffer: &CoverageBuffer)
|
||||||
-> Result<DrawAtlasProfilingEvents, ()> {
|
-> Result<DrawAtlasProfilingEvents, RasterError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, coverage_buffer.framebuffer());
|
gl::BindFramebuffer(gl::FRAMEBUFFER, coverage_buffer.framebuffer());
|
||||||
gl::Viewport(0, 0, rect.size.width as GLint, rect.size.height as GLint);
|
gl::Viewport(0, 0, rect.size.width as GLint, rect.size.height as GLint);
|
||||||
|
@ -230,7 +232,7 @@ impl Rasterizer {
|
||||||
let accum_event = try!(self.queue.submit_compute(&self.accum_program,
|
let accum_event = try!(self.queue.submit_compute(&self.accum_program,
|
||||||
&[atlas.shelf_columns],
|
&[atlas.shelf_columns],
|
||||||
&accum_uniforms,
|
&accum_uniforms,
|
||||||
&[]).map_err(drop));
|
&[]).map_err(RasterError::ComputeError));
|
||||||
|
|
||||||
Ok(DrawAtlasProfilingEvents {
|
Ok(DrawAtlasProfilingEvents {
|
||||||
draw: self.draw_query,
|
draw: self.draw_query,
|
||||||
|
@ -239,26 +241,27 @@ impl Rasterizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_gl_shader(shader_type: GLuint, description: &str, source: &str) -> Result<GLuint, ()> {
|
fn compile_gl_shader(shader_type: GLuint, description: &'static str, source: &str)
|
||||||
|
-> Result<GLuint, InitError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let shader = gl::CreateShader(shader_type);
|
let shader = gl::CreateShader(shader_type);
|
||||||
gl::ShaderSource(shader, 1, &(source.as_ptr() as *const GLchar), &(source.len() as GLint));
|
gl::ShaderSource(shader, 1, &(source.as_ptr() as *const GLchar), &(source.len() as GLint));
|
||||||
gl::CompileShader(shader);
|
gl::CompileShader(shader);
|
||||||
try!(check_gl_object_status(shader,
|
match check_gl_object_status(shader,
|
||||||
gl::COMPILE_STATUS,
|
gl::COMPILE_STATUS,
|
||||||
description,
|
gl::GetShaderiv,
|
||||||
gl::GetShaderiv,
|
gl::GetShaderInfoLog) {
|
||||||
gl::GetShaderInfoLog));
|
Ok(_) => Ok(shader),
|
||||||
Ok(shader)
|
Err(info_log) => Err(InitError::CompileFailed(description, info_log)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_gl_object_status(object: GLuint,
|
fn check_gl_object_status(object: GLuint,
|
||||||
parameter: GLenum,
|
parameter: GLenum,
|
||||||
description: &str,
|
|
||||||
get_status: unsafe fn(GLuint, GLenum, *mut GLint),
|
get_status: unsafe fn(GLuint, GLenum, *mut GLint),
|
||||||
get_log: unsafe fn(GLuint, GLsizei, *mut GLsizei, *mut GLchar))
|
get_log: unsafe fn(GLuint, GLsizei, *mut GLsizei, *mut GLchar))
|
||||||
-> Result<(), ()> {
|
-> Result<(), String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut status = 0;
|
let mut status = 0;
|
||||||
get_status(object, parameter, &mut status);
|
get_status(object, parameter, &mut status);
|
||||||
|
@ -271,10 +274,11 @@ fn check_gl_object_status(object: GLuint,
|
||||||
|
|
||||||
let mut info_log = vec![0; info_log_length as usize];
|
let mut info_log = vec![0; info_log_length as usize];
|
||||||
get_log(object, info_log_length, ptr::null_mut(), info_log.as_mut_ptr() as *mut GLchar);
|
get_log(object, info_log_length, ptr::null_mut(), info_log.as_mut_ptr() as *mut GLchar);
|
||||||
if let Ok(string) = String::from_utf8(info_log) {
|
|
||||||
println!("{} error:\n{}", description, string);
|
match String::from_utf8(info_log) {
|
||||||
|
Ok(string) => Err(string),
|
||||||
|
Err(_) => Err("(not UTF-8)".to_owned()),
|
||||||
}
|
}
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +296,7 @@ impl Default for RasterizerOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RasterizerOptions {
|
impl RasterizerOptions {
|
||||||
pub fn from_env() -> Result<RasterizerOptions, ()> {
|
pub fn from_env() -> Result<RasterizerOptions, InitError> {
|
||||||
let force_geometry_shader = match env::var("PATHFINDER_FORCE_GEOMETRY_SHADER") {
|
let force_geometry_shader = match env::var("PATHFINDER_FORCE_GEOMETRY_SHADER") {
|
||||||
Ok(ref string) if string.eq_ignore_ascii_case("on") ||
|
Ok(ref string) if string.eq_ignore_ascii_case("on") ||
|
||||||
string.eq_ignore_ascii_case("yes") ||
|
string.eq_ignore_ascii_case("yes") ||
|
||||||
|
@ -301,7 +305,7 @@ impl RasterizerOptions {
|
||||||
string.eq_ignore_ascii_case("no") ||
|
string.eq_ignore_ascii_case("no") ||
|
||||||
string.eq_ignore_ascii_case("0") => false,
|
string.eq_ignore_ascii_case("0") => false,
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
Ok(_) => return Err(()),
|
Ok(_) => return Err(InitError::InvalidSetting),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(RasterizerOptions {
|
Ok(RasterizerOptions {
|
||||||
|
|
|
@ -31,6 +31,9 @@ impl RectPacker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Packs a rectangle of the given size.
|
||||||
|
///
|
||||||
|
/// Returns the top-left position of the rectangle or an error if there is no space left.
|
||||||
pub fn pack(&mut self, size: &Size2D<u32>) -> Result<Point2D<u32>, ()> {
|
pub fn pack(&mut self, size: &Size2D<u32>) -> Result<Point2D<u32>, ()> {
|
||||||
// Add a one-pixel border to prevent bleed.
|
// Add a one-pixel border to prevent bleed.
|
||||||
let alloc_size = *size + Size2D::new(2, 2);
|
let alloc_size = *size + Size2D::new(2, 2);
|
||||||
|
|
Loading…
Reference in New Issue