Get things basically working
This commit is contained in:
parent
50ad78db2a
commit
d5b61e382e
|
@ -13,7 +13,7 @@ use compute_shader::buffer;
|
||||||
use compute_shader::instance::Instance;
|
use compute_shader::instance::Instance;
|
||||||
use compute_shader::texture::{ExternalTexture, Format};
|
use compute_shader::texture::{ExternalTexture, Format};
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Point2D, Rect, Size2D};
|
||||||
use gl::types::GLint;
|
use gl::types::{GLint, GLuint};
|
||||||
use glfw::{Action, Context, Key, OpenGlProfileHint, WindowEvent, WindowHint, WindowMode};
|
use glfw::{Action, Context, Key, OpenGlProfileHint, WindowEvent, WindowHint, WindowMode};
|
||||||
use memmap::{Mmap, Protection};
|
use memmap::{Mmap, Protection};
|
||||||
use pathfinder::batch::{BatchBuilder, GlyphRange};
|
use pathfinder::batch::{BatchBuilder, GlyphRange};
|
||||||
|
@ -32,7 +32,7 @@ const SHELF_HEIGHT: u32 = 32;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut glfw = glfw::init(glfw::LOG_ERRORS).unwrap();
|
let mut glfw = glfw::init(glfw::LOG_ERRORS).unwrap();
|
||||||
glfw.window_hint(WindowHint::ContextVersion(3, 3));
|
glfw.window_hint(WindowHint::ContextVersion(4, 1));
|
||||||
glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
|
glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
|
||||||
glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
|
glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
|
||||||
let context = glfw.create_window(WIDTH, HEIGHT, "generate-atlas", WindowMode::Windowed);
|
let context = glfw.create_window(WIDTH, HEIGHT, "generate-atlas", WindowMode::Windowed);
|
||||||
|
@ -40,6 +40,7 @@ fn main() {
|
||||||
let (mut window, events) = context.expect("Couldn't create a window!");
|
let (mut window, events) = context.expect("Couldn't create a window!");
|
||||||
window.make_current();
|
window.make_current();
|
||||||
gl::load_with(|symbol| window.get_proc_address(symbol) as *const c_void);
|
gl::load_with(|symbol| window.get_proc_address(symbol) as *const c_void);
|
||||||
|
let (device_pixel_width, device_pixel_height) = window.get_framebuffer_size();
|
||||||
|
|
||||||
let instance = Instance::new().unwrap();
|
let instance = Instance::new().unwrap();
|
||||||
let device = instance.create_device().unwrap();
|
let device = instance.create_device().unwrap();
|
||||||
|
@ -48,7 +49,7 @@ fn main() {
|
||||||
let rasterizer = Rasterizer::new(device, queue).unwrap();
|
let rasterizer = Rasterizer::new(device, queue).unwrap();
|
||||||
|
|
||||||
let mut glyph_buffer_builder = GlyphBufferBuilder::new();
|
let mut glyph_buffer_builder = GlyphBufferBuilder::new();
|
||||||
let mut batch_builder = BatchBuilder::new(WIDTH, SHELF_HEIGHT);
|
let mut batch_builder = BatchBuilder::new(device_pixel_width as GLuint, SHELF_HEIGHT);
|
||||||
|
|
||||||
let file = Mmap::open_path(env::args().nth(1).unwrap(), Protection::Read).unwrap();
|
let file = Mmap::open_path(env::args().nth(1).unwrap(), Protection::Read).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -69,7 +70,7 @@ fn main() {
|
||||||
let glyph_buffers = glyph_buffer_builder.finish().unwrap();
|
let glyph_buffers = glyph_buffer_builder.finish().unwrap();
|
||||||
let batch = batch_builder.finish(&glyph_buffer_builder).unwrap();
|
let batch = batch_builder.finish(&glyph_buffer_builder).unwrap();
|
||||||
|
|
||||||
let atlas_size = Size2D::new(WIDTH, HEIGHT);
|
let atlas_size = Size2D::new(device_pixel_width as GLuint, device_pixel_height as GLuint);
|
||||||
let coverage_buffer = CoverageBuffer::new(&rasterizer.device, &atlas_size).unwrap();
|
let coverage_buffer = CoverageBuffer::new(&rasterizer.device, &atlas_size).unwrap();
|
||||||
|
|
||||||
let texture = rasterizer.device
|
let texture = rasterizer.device
|
||||||
|
@ -98,6 +99,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
gl::Viewport(0, 0, device_pixel_width, device_pixel_height);
|
||||||
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
|
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ __kernel void accum(__write_only image2d_t gTexture,
|
||||||
int2 coord = (int2)((int)column, (int)row);
|
int2 coord = (int2)((int)column, (int)row);
|
||||||
coverage += read_imagef(gCoverage, SAMPLER, coord).r;
|
coverage += read_imagef(gCoverage, SAMPLER, coord).r;
|
||||||
|
|
||||||
uint gray = 255 - convert_uint(clamp(coverage, 0.0f, 1.0f) * 255.0f);
|
uint gray = convert_uint(clamp(coverage, 0.0f, 1.0f) * 255.0f);
|
||||||
write_imageui(gTexture, coord + (int2)kAtlasRect.xy, (uint4)(gray, 255, 255, 255));
|
write_imageui(gTexture, coord + (int2)kAtlasRect.xy, (uint4)(gray, 255, 255, 255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ out vec4 oFragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Compute the X boundaries of this pixel.
|
// Compute the X boundaries of this pixel.
|
||||||
float xMin = floor(gl_FragCoord.x), xMax = ceil(gl_FragCoord.x);
|
float xMin = floor(gl_FragCoord.x);
|
||||||
|
float xMax = xMin + 1.0f;
|
||||||
|
|
||||||
// Compute the horizontal span that the line segment covers across this pixel.
|
// Compute the horizontal span that the line segment covers across this pixel.
|
||||||
float dX = min(xMax, vP1.x) - max(xMin, vP0.x);
|
float dX = min(xMax, vP1.x) - max(xMin, vP0.x);
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
|
|
||||||
layout(vertices = 1) out;
|
layout(vertices = 1) out;
|
||||||
|
|
||||||
// The size of the atlas in pixels.
|
|
||||||
uniform uvec2 uAtlasSize;
|
|
||||||
|
|
||||||
// The vertex ID, passed into this shader.
|
// The vertex ID, passed into this shader.
|
||||||
flat in uint vVertexID[];
|
flat in uint vVertexID[];
|
||||||
|
|
||||||
|
@ -31,25 +28,26 @@ patch out vec2 vpP2;
|
||||||
patch out float vpDirection;
|
patch out float vpDirection;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vpP0 = gl_in[0].gl_Position.xy;
|
vec2 p0 = gl_in[0].gl_Position.xy;
|
||||||
vpP1 = gl_in[1].gl_Position.xy;
|
vec2 p1 = gl_in[1].gl_Position.xy;
|
||||||
vpP2 = gl_in[2].gl_Position.xy;
|
vec2 p2 = gl_in[2].gl_Position.xy;
|
||||||
|
|
||||||
// Compute direction. Flip around if necessary so that p0 is to the left of p2.
|
// Compute direction. Flip around if necessary so that p0 is to the left of p2.
|
||||||
if (vpP0.x < vpP2.x) {
|
float direction;
|
||||||
vpDirection = 1.0f;
|
if (p0.x < p2.x) {
|
||||||
|
direction = 1.0f;
|
||||||
} else {
|
} else {
|
||||||
vpDirection = -1.0f;
|
direction = -1.0f;
|
||||||
vec2 tmp = vpP0;
|
vec2 tmp = p0;
|
||||||
vpP0 = vpP2;
|
p0 = p2;
|
||||||
vpP2 = tmp;
|
p2 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Divide into lines.
|
// Divide into lines.
|
||||||
float lineCount = 1.0f;
|
float lineCount = 1.0f;
|
||||||
if (vVertexID[1] > 0) {
|
if (vVertexID[1] > 0) {
|
||||||
// Quadratic curve.
|
// Quadratic curve.
|
||||||
vec2 dev = vpP0 - 2.0f * vpP1 + vpP2;
|
vec2 dev = p0 - 2.0f * p1 + p2;
|
||||||
float devSq = dot(dev, dev);
|
float devSq = dot(dev, dev);
|
||||||
if (devSq >= CURVE_THRESHOLD) {
|
if (devSq >= CURVE_THRESHOLD) {
|
||||||
// Inverse square root is likely no slower and may be faster than regular square root
|
// Inverse square root is likely no slower and may be faster than regular square root
|
||||||
|
@ -100,10 +98,19 @@ void main() {
|
||||||
// so we're in the clear: the rasterizer will always discard the unshaded areas and render only
|
// so we're in the clear: the rasterizer will always discard the unshaded areas and render only
|
||||||
// the shaded ones.
|
// the shaded ones.
|
||||||
|
|
||||||
gl_TessLevelInner[0] = vpP0.x == vpP2.x ? 0.0f : lineCount * 2.0f - 1.0f;
|
float tessLevel = p0.x == p2.x ? 0.0f : (lineCount * 2.0f - 1.0f);
|
||||||
gl_TessLevelOuter[1] = gl_TessLevelOuter[3] = gl_TessLevelInner[0];
|
gl_TessLevelInner[0] = tessLevel;
|
||||||
|
gl_TessLevelInner[1] = 1.0f;
|
||||||
|
gl_TessLevelOuter[0] = 1.0f;
|
||||||
|
gl_TessLevelOuter[1] = tessLevel;
|
||||||
|
gl_TessLevelOuter[2] = 1.0f;
|
||||||
|
gl_TessLevelOuter[3] = tessLevel;
|
||||||
|
|
||||||
// Don't split vertically at all. We only tessellate horizontally.
|
// NB: These per-patch outputs must be assigned in this order, or Apple's compiler will
|
||||||
gl_TessLevelInner[1] = gl_TessLevelOuter[0] = gl_TessLevelOuter[2] = 1.0f;
|
// miscompile us.
|
||||||
|
vpP0 = p0;
|
||||||
|
vpP1 = p1;
|
||||||
|
vpP2 = p2;
|
||||||
|
vpDirection = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ void main() {
|
||||||
float t0 = float(lineIndex + 0) / float(lineCount);
|
float t0 = float(lineIndex + 0) / float(lineCount);
|
||||||
float t1 = float(lineIndex + 1) / float(lineCount);
|
float t1 = float(lineIndex + 1) / float(lineCount);
|
||||||
vP0 = mix(mix(vpP0, vpP1, t0), mix(vpP1, vpP2, t0), t0);
|
vP0 = mix(mix(vpP0, vpP1, t0), mix(vpP1, vpP2, t0), t0);
|
||||||
vP1 = mix(mix(vpP0, vpP1, t1), mix(vpP1, vpP2, t0), t1);
|
vP1 = mix(mix(vpP0, vpP1, t1), mix(vpP1, vpP2, t1), t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute Y extents and slope.
|
// Compute Y extents and slope.
|
||||||
|
|
|
@ -10,29 +10,19 @@
|
||||||
|
|
||||||
#version 410
|
#version 410
|
||||||
|
|
||||||
// FIXME(pcwalton): This should be higher. Dynamically query its maximum possible size, perhaps?
|
#define MAX_GLYPHS 2048
|
||||||
#define MAX_GLYPHS 256
|
|
||||||
|
// Accessors to work around Apple driver bugs.
|
||||||
|
#define GLYPH_DESCRIPTOR_UNITS_PER_EM(d) (d).misc.x
|
||||||
|
#define IMAGE_DESCRIPTOR_ATLAS_POS(d) (d).xy
|
||||||
|
#define IMAGE_DESCRIPTOR_POINT_SIZE(d) (d).z
|
||||||
|
|
||||||
// Information about the metrics of each glyph.
|
// Information about the metrics of each glyph.
|
||||||
layout(std140) struct GlyphDescriptor {
|
layout(std140) struct GlyphDescriptor {
|
||||||
// The left/top/right/bottom offsets of the glyph from point (0, 0) in glyph space.
|
// The left/bottom/right/top offsets of the glyph from point (0, 0) in glyph space.
|
||||||
ivec4 extents;
|
ivec4 extents;
|
||||||
// The number of units per em in this glyph.
|
// x: Units per em.
|
||||||
uint unitsPerEm;
|
uvec4 misc;
|
||||||
// The index of the first point in the VBO.
|
|
||||||
uint startPoint;
|
|
||||||
// The index of the first element in the IBO.
|
|
||||||
uint startIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Information about the position of each glyph in the atlas.
|
|
||||||
layout(std140) struct ImageDescriptor {
|
|
||||||
// The left/top/right/bottom positions of the glyph in the atlas.
|
|
||||||
uvec4 atlasRect;
|
|
||||||
// The font size in pixels.
|
|
||||||
float pointSize;
|
|
||||||
// The index of the glyph.
|
|
||||||
uint glyphIndex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The size of the atlas in pixels.
|
// The size of the atlas in pixels.
|
||||||
|
@ -43,7 +33,7 @@ layout(std140) uniform ubGlyphDescriptors {
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140) uniform ubImageDescriptors {
|
layout(std140) uniform ubImageDescriptors {
|
||||||
ImageDescriptor uImages[MAX_GLYPHS];
|
uvec4 uImages[MAX_GLYPHS];
|
||||||
};
|
};
|
||||||
|
|
||||||
// The position of each vertex in glyph space.
|
// The position of each vertex in glyph space.
|
||||||
|
@ -60,13 +50,13 @@ flat out uint vVertexID;
|
||||||
void main() {
|
void main() {
|
||||||
vVertexID = gl_VertexID;
|
vVertexID = gl_VertexID;
|
||||||
|
|
||||||
ImageDescriptor image = uImages[aGlyphIndex];
|
uvec4 image = uImages[aGlyphIndex];
|
||||||
GlyphDescriptor glyph = uGlyphs[aGlyphIndex];
|
GlyphDescriptor glyph = uGlyphs[aGlyphIndex];
|
||||||
|
|
||||||
float emsPerUnit = 1.0f / float(glyph.unitsPerEm);
|
|
||||||
|
|
||||||
vec2 glyphPos = vec2(aPosition.x - glyph.extents.x, glyph.extents.w - aPosition.y);
|
vec2 glyphPos = vec2(aPosition.x - glyph.extents.x, glyph.extents.w - aPosition.y);
|
||||||
vec2 atlasPos = glyphPos * emsPerUnit * image.pointSize + vec2(image.atlasRect.xy);
|
float pointSize = float(IMAGE_DESCRIPTOR_POINT_SIZE(image)) / 65536.0f;
|
||||||
|
vec2 glyphPxPos = glyphPos * pointSize / GLYPH_DESCRIPTOR_UNITS_PER_EM(glyph);
|
||||||
|
vec2 atlasPos = glyphPxPos + vec2(IMAGE_DESCRIPTOR_ATLAS_POS(image));
|
||||||
|
|
||||||
gl_Position = vec4(atlasPos, 0.0f, 1.0f);
|
gl_Position = vec4(atlasPos, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl BatchBuilder {
|
||||||
self.images[glyph_index as usize] = ImageDescriptor {
|
self.images[glyph_index as usize] = ImageDescriptor {
|
||||||
atlas_x: atlas_origin.x,
|
atlas_x: atlas_origin.x,
|
||||||
atlas_y: atlas_origin.y,
|
atlas_y: atlas_origin.y,
|
||||||
point_size: point_size,
|
point_size: (point_size * 65536.0) as u32,
|
||||||
glyph_index: glyph_index,
|
glyph_index: glyph_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ impl Iterator for GlyphRangeIter {
|
||||||
pub struct ImageDescriptor {
|
pub struct ImageDescriptor {
|
||||||
atlas_x: u32,
|
atlas_x: u32,
|
||||||
atlas_y: u32,
|
atlas_y: u32,
|
||||||
point_size: f32,
|
point_size: u32,
|
||||||
glyph_index: u32,
|
glyph_index: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ impl CoverageBuffer {
|
||||||
gl::TEXTURE_RECTANGLE,
|
gl::TEXTURE_RECTANGLE,
|
||||||
gl_texture,
|
gl_texture,
|
||||||
0);
|
0);
|
||||||
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CoverageBuffer {
|
Ok(CoverageBuffer {
|
||||||
|
|
|
@ -61,9 +61,9 @@ impl GlyphBufferBuilder {
|
||||||
|
|
||||||
if !point.first_point_in_contour && point.on_curve {
|
if !point.first_point_in_contour && point.on_curve {
|
||||||
let indices = if last_point_on_curve {
|
let indices = if last_point_on_curve {
|
||||||
[point_index - 2, 0, point_index - 1]
|
[point_index - 1, 0, point_index]
|
||||||
} else {
|
} else {
|
||||||
[point_index - 3, point_index - 2, point_index - 1]
|
[point_index - 2, point_index - 1, point_index]
|
||||||
};
|
};
|
||||||
self.indices.extend(indices.iter().cloned());
|
self.indices.extend(indices.iter().cloned());
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ pub struct GlyphBuffers {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct GlyphDescriptor {
|
pub struct GlyphDescriptor {
|
||||||
pub left: i32,
|
pub left: i32,
|
||||||
pub bottom: i32,
|
pub bottom: i32,
|
||||||
|
@ -154,7 +154,7 @@ impl GlyphDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Vertex {
|
pub struct Vertex {
|
||||||
x: i16,
|
x: i16,
|
||||||
|
|
|
@ -39,16 +39,17 @@ pub struct Rasterizer {
|
||||||
accum_program: Program,
|
accum_program: Program,
|
||||||
draw_vertex_array: GLuint,
|
draw_vertex_array: GLuint,
|
||||||
draw_position_attribute: GLint,
|
draw_position_attribute: GLint,
|
||||||
draw_image_index_attribute: GLint,
|
draw_glyph_index_attribute: GLint,
|
||||||
draw_atlas_size_uniform: GLint,
|
draw_atlas_size_uniform: GLint,
|
||||||
draw_glyph_descriptors_uniform: GLuint,
|
draw_glyph_descriptors_uniform: GLuint,
|
||||||
draw_image_info_uniform: GLuint,
|
draw_image_descriptors_uniform: GLuint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rasterizer {
|
impl Rasterizer {
|
||||||
pub fn new(device: Device, queue: Queue) -> Result<Rasterizer, ()> {
|
pub fn new(device: Device, queue: Queue) -> Result<Rasterizer, ()> {
|
||||||
let (draw_program, draw_position_attribute, draw_image_index_attribute);
|
let (draw_program, draw_position_attribute, draw_glyph_index_attribute);
|
||||||
let (draw_atlas_size_uniform, draw_glyph_descriptors_uniform, draw_image_info_uniform);
|
let (draw_glyph_descriptors_uniform, draw_image_descriptors_uniform);
|
||||||
|
let draw_atlas_size_uniform;
|
||||||
let mut draw_vertex_array = 0;
|
let mut draw_vertex_array = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
let shaders = [
|
let shaders = [
|
||||||
|
@ -83,16 +84,17 @@ impl Rasterizer {
|
||||||
|
|
||||||
draw_position_attribute =
|
draw_position_attribute =
|
||||||
gl::GetAttribLocation(draw_program, b"aPosition\0".as_ptr() as *const GLchar);
|
gl::GetAttribLocation(draw_program, b"aPosition\0".as_ptr() as *const GLchar);
|
||||||
draw_image_index_attribute =
|
draw_glyph_index_attribute =
|
||||||
gl::GetAttribLocation(draw_program, b"aImageIndex\0".as_ptr() as *const GLchar);
|
gl::GetAttribLocation(draw_program, b"aGlyphIndex\0".as_ptr() as *const GLchar);
|
||||||
|
|
||||||
draw_atlas_size_uniform =
|
draw_atlas_size_uniform =
|
||||||
gl::GetUniformLocation(draw_program, b"uAtlasSize\0".as_ptr() as *const GLchar);
|
gl::GetUniformLocation(draw_program, b"uAtlasSize\0".as_ptr() as *const GLchar);
|
||||||
draw_glyph_descriptors_uniform =
|
draw_glyph_descriptors_uniform =
|
||||||
gl::GetUniformBlockIndex(draw_program,
|
gl::GetUniformBlockIndex(draw_program,
|
||||||
b"ubGlyphDescriptors\0".as_ptr() as *const GLchar);
|
b"ubGlyphDescriptors\0".as_ptr() as *const GLchar);
|
||||||
draw_image_info_uniform =
|
draw_image_descriptors_uniform =
|
||||||
gl::GetUniformBlockIndex(draw_program, b"ubImageInfo\0".as_ptr() as *const GLchar);
|
gl::GetUniformBlockIndex(draw_program,
|
||||||
|
b"ubImageDescriptors\0".as_ptr() as *const GLchar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Don't panic if this fails to compile; just return an error.
|
// FIXME(pcwalton): Don't panic if this fails to compile; just return an error.
|
||||||
|
@ -105,10 +107,10 @@ impl Rasterizer {
|
||||||
accum_program: accum_program,
|
accum_program: accum_program,
|
||||||
draw_vertex_array: draw_vertex_array,
|
draw_vertex_array: draw_vertex_array,
|
||||||
draw_position_attribute: draw_position_attribute,
|
draw_position_attribute: draw_position_attribute,
|
||||||
draw_image_index_attribute: draw_image_index_attribute,
|
draw_glyph_index_attribute: draw_glyph_index_attribute,
|
||||||
draw_atlas_size_uniform: draw_atlas_size_uniform,
|
draw_atlas_size_uniform: draw_atlas_size_uniform,
|
||||||
draw_glyph_descriptors_uniform: draw_glyph_descriptors_uniform,
|
draw_glyph_descriptors_uniform: draw_glyph_descriptors_uniform,
|
||||||
draw_image_info_uniform: draw_image_info_uniform,
|
draw_image_descriptors_uniform: draw_image_descriptors_uniform,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +123,15 @@ impl Rasterizer {
|
||||||
texture: &Texture)
|
texture: &Texture)
|
||||||
-> Result<Event, ()> {
|
-> Result<Event, ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::UseProgram(self.draw_program);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, coverage_buffer.framebuffer);
|
||||||
|
gl::Viewport(0, 0, atlas_rect.size.width as GLint, atlas_rect.size.height as GLint);
|
||||||
|
|
||||||
|
// TODO(pcwalton): Scissor to the atlas rect to clear faster?
|
||||||
|
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
gl::BindVertexArray(self.draw_vertex_array);
|
gl::BindVertexArray(self.draw_vertex_array);
|
||||||
|
gl::UseProgram(self.draw_program);
|
||||||
|
|
||||||
// Set up the buffer layout.
|
// Set up the buffer layout.
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, glyph_buffers.vertices);
|
gl::BindBuffer(gl::ARRAY_BUFFER, glyph_buffers.vertices);
|
||||||
|
@ -131,20 +140,20 @@ impl Rasterizer {
|
||||||
gl::SHORT,
|
gl::SHORT,
|
||||||
mem::size_of::<Vertex>() as GLint,
|
mem::size_of::<Vertex>() as GLint,
|
||||||
0 as *const GLvoid);
|
0 as *const GLvoid);
|
||||||
gl::VertexAttribIPointer(self.draw_image_index_attribute as GLuint,
|
gl::VertexAttribIPointer(self.draw_glyph_index_attribute as GLuint,
|
||||||
1,
|
1,
|
||||||
gl::UNSIGNED_SHORT,
|
gl::UNSIGNED_SHORT,
|
||||||
mem::size_of::<Vertex>() as GLint,
|
mem::size_of::<Vertex>() as GLint,
|
||||||
mem::size_of::<(i16, i16)>() as *const GLvoid);
|
mem::size_of::<(i16, i16)>() as *const GLvoid);
|
||||||
gl::EnableVertexAttribArray(self.draw_position_attribute as GLuint);
|
gl::EnableVertexAttribArray(self.draw_position_attribute as GLuint);
|
||||||
gl::EnableVertexAttribArray(self.draw_image_index_attribute as GLuint);
|
gl::EnableVertexAttribArray(self.draw_glyph_index_attribute as GLuint);
|
||||||
|
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, glyph_buffers.indices);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, glyph_buffers.indices);
|
||||||
|
|
||||||
gl::BindBufferBase(gl::UNIFORM_BUFFER, 1, glyph_buffers.descriptors);
|
gl::BindBufferBase(gl::UNIFORM_BUFFER, 1, glyph_buffers.descriptors);
|
||||||
gl::BindBufferBase(gl::UNIFORM_BUFFER, 2, batch.images);
|
gl::BindBufferBase(gl::UNIFORM_BUFFER, 2, batch.images);
|
||||||
gl::UniformBlockBinding(self.draw_program, self.draw_glyph_descriptors_uniform, 1);
|
gl::UniformBlockBinding(self.draw_program, self.draw_glyph_descriptors_uniform, 1);
|
||||||
gl::UniformBlockBinding(self.draw_program, self.draw_image_info_uniform, 2);
|
gl::UniformBlockBinding(self.draw_program, self.draw_image_descriptors_uniform, 2);
|
||||||
|
|
||||||
gl::Uniform2ui(self.draw_atlas_size_uniform,
|
gl::Uniform2ui(self.draw_atlas_size_uniform,
|
||||||
atlas_rect.size.width,
|
atlas_rect.size.width,
|
||||||
|
@ -170,6 +179,16 @@ impl Rasterizer {
|
||||||
gl::UNSIGNED_INT,
|
gl::UNSIGNED_INT,
|
||||||
batch.start_indices.as_ptr() as *const *const GLvoid,
|
batch.start_indices.as_ptr() as *const *const GLvoid,
|
||||||
batch.counts.len() as GLsizei);
|
batch.counts.len() as GLsizei);
|
||||||
|
|
||||||
|
gl::Disable(gl::CULL_FACE);
|
||||||
|
gl::Disable(gl::BLEND);
|
||||||
|
|
||||||
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
// FIXME(pcwalton): We should have some better synchronization here if we're using
|
||||||
|
// OpenCL, but I don't know how to do that portably (i.e. on Mac…) Just using
|
||||||
|
// `glFlush()` seems to work in practice.
|
||||||
|
gl::Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
let atlas_rect_uniform = [
|
let atlas_rect_uniform = [
|
||||||
|
|
Loading…
Reference in New Issue