pathfinder/pathfinder-classic/src/coverage.rs

134 lines
4.7 KiB
Rust
Raw Normal View History

// 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.
2017-02-07 23:20:14 -05:00
//! An intermediate surface on the GPU used during the rasterization process.
use compute_shader::buffer::Protection;
use compute_shader::device::Device;
2017-02-02 19:40:46 -05:00
use compute_shader::image::{ExternalImage, Format, Image};
2017-02-03 21:25:56 -05:00
use error::InitError;
use euclid::size::Size2D;
use gl::types::{GLint, GLuint};
use gl;
const DEFAULT_COVERAGE_BUFFER_SIZE: u32 = 1024;
2017-02-07 23:20:14 -05:00
/// An intermediate surface on the GPU used during the rasterization process.
///
/// You can reuse this surface from draw operation to draw operation. It only needs to be at least
/// as large as every atlas you will draw into it.
///
/// The GPU memory usage of this buffer is `4 * width * height` bytes.
pub struct CoverageBuffer {
2017-02-02 20:00:37 -05:00
image: Image,
framebuffer: GLuint,
}
impl CoverageBuffer {
/// Creates a new coverage buffer with the given options.
pub fn new(device: &Device, options: &CoverageBufferOptions)
-> Result<CoverageBuffer, InitError> {
let mut size = options.size;
if options.subpixel_antialiasing {
size.width *= 3
}
let image = try!(device.create_image(Format::R32F, Protection::ReadWrite, &size)
2017-02-03 21:25:56 -05:00
.map_err(InitError::ComputeError));
let mut framebuffer = 0;
unsafe {
let mut gl_texture = 0;
gl::GenTextures(1, &mut gl_texture);
2017-02-03 21:25:56 -05:00
try!(image.bind_to(&ExternalImage::GlTexture(gl_texture))
.map_err(InitError::ComputeError));
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_MAG_FILTER, gl::LINEAR as GLint);
gl::TexParameteri(gl::TEXTURE_RECTANGLE,
gl::TEXTURE_WRAP_S,
gl::CLAMP_TO_EDGE as GLint);
gl::TexParameteri(gl::TEXTURE_RECTANGLE,
gl::TEXTURE_WRAP_T,
gl::CLAMP_TO_EDGE as GLint);
gl::GenFramebuffers(1, &mut framebuffer);
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_RECTANGLE,
gl_texture,
0);
2017-01-25 14:52:18 -05:00
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
}
Ok(CoverageBuffer {
2017-02-02 19:40:46 -05:00
image: image,
framebuffer: framebuffer,
})
}
2017-02-02 20:00:37 -05:00
2017-02-07 23:20:14 -05:00
#[doc(hidden)]
2017-02-02 20:00:37 -05:00
#[inline]
pub fn image(&self) -> &Image {
&self.image
}
2017-02-07 23:20:14 -05:00
#[doc(hidden)]
2017-02-02 20:00:37 -05:00
#[inline]
pub fn framebuffer(&self) -> GLuint {
self.framebuffer
}
}
impl Drop for CoverageBuffer {
fn drop(&mut self) {
unsafe {
let mut gl_texture = 0;
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer);
gl::GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
&mut gl_texture as *mut GLuint as *mut GLint);
gl::DeleteTextures(1, &mut gl_texture);
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::DeleteFramebuffers(1, &mut self.framebuffer);
}
}
}
/// Options that control the format of the coverage buffer.
#[derive(Clone, Copy, Debug)]
pub struct CoverageBufferOptions {
/// The size of the coverage buffer.
///
/// The size must be at least as large as every atlas you will render with the buffer.
pub size: Size2D<u32>,
/// Whether this coverage buffer is intended for subpixel antialiasing.
///
/// If this buffer is intended for subpixel AA, all atlas rendered with it must use subpixel
/// AA, and vice versa.
pub subpixel_antialiasing: bool,
}
impl Default for CoverageBufferOptions {
#[inline]
fn default() -> CoverageBufferOptions {
CoverageBufferOptions {
size: Size2D::new(DEFAULT_COVERAGE_BUFFER_SIZE, DEFAULT_COVERAGE_BUFFER_SIZE),
subpixel_antialiasing: false,
}
}
}