Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic subpixel AA text support on Linux. #527

Merged
merged 1 commit into from Nov 7, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -99,6 +99,7 @@ fn main() {
precache_shaders: false,
renderer_kind: webrender_traits::RendererKind::Native,
debug: false,
enable_subpixel_aa: false,
};

let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
@@ -140,6 +140,7 @@ fn main() {
debug: true,
precache_shaders: false,
renderer_kind: RendererKind::Native,
enable_subpixel_aa: false,
};

let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
@@ -3,11 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

void main(void) {
#ifdef WR_FEATURE_SUBPIXEL_AA
oFragColor = texture(sDiffuse, vUv);
#else
float a = texture(sDiffuse, vUv).a;
#ifdef WR_FEATURE_TRANSFORM
float alpha = 0.0;
init_transform_fs(vLocalPos, vLocalRect, alpha);
a *= alpha;
#endif
oFragColor = vec4(vColor.rgb, vColor.a * a);
#endif
}
@@ -17,7 +17,7 @@ use std::path::PathBuf;
use std::mem;
//use std::sync::mpsc::{channel, Sender};
//use std::thread;
use webrender_traits::ImageFormat;
use webrender_traits::{ColorF, ImageFormat};

#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
const GL_FORMAT_A: gl::GLuint = gl::RED;
@@ -1813,6 +1813,11 @@ impl Device {
gl::ONE, gl::ONE);
gl::blend_equation(gl::FUNC_ADD);
}

pub fn set_blend_mode_subpixel(&self, color: ColorF) {
gl::blend_color(color.r, color.g, color.b, color.a);
gl::blend_func(gl::CONSTANT_COLOR, gl::ONE_MINUS_SRC_COLOR);
}
}

impl Drop for Device {
@@ -24,14 +24,6 @@ use webrender_traits::{Epoch, ColorF, PipelineId};
use webrender_traits::{ImageFormat, MixBlendMode, NativeFontHandle, DisplayItem};
use webrender_traits::{ScrollLayerId, WebGLCommand};

#[allow(dead_code)] // TODO(gw): Make use of the subpixel render mode!
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub enum FontRenderMode {
Mono,
Alpha,
Subpixel,
}

pub enum GLContextHandleWrapper {
Native(NativeGLContextHandle),
OSMesa(OSMesaContextHandle),
@@ -12,10 +12,9 @@ use core_graphics::geometry::CGPoint;
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use internal_types::FontRenderMode;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::{FontKey, GlyphDimensions};
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions};

pub type NativeFontHandle = CGFont;

@@ -3,8 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use internal_types::FontRenderMode;
use webrender_traits::{FontKey, GlyphDimensions, NativeFontHandle};
use webrender_traits::{FontKey, FontRenderMode, GlyphDimensions, NativeFontHandle};

use freetype::freetype::{FTErrorMethods, FT_PIXEL_MODE_GRAY, FT_PIXEL_MODE_MONO, FT_PIXEL_MODE_LCD};
use freetype::freetype::{FT_Done_FreeType, FT_RENDER_MODE_LCD, FT_Library_SetLcdFilter};
@@ -49,7 +48,10 @@ impl FontContext {
if !result.succeeded() { panic!("Unable to initialize FreeType library {}", result); }

// TODO(gw): Check result of this to determine if freetype build supports subpixel.
FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
if !result.succeeded() {
println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
}
}

FontContext {
@@ -156,7 +158,7 @@ impl FontContext {
let bitmap_mode = bitmap.pixel_mode as u32;

let metrics = &(*slot).metrics;
let glyph_width = (metrics.width >> 6) as i32;
let mut glyph_width = (metrics.width >> 6) as i32;
let glyph_height = (metrics.height >> 6) as i32;
let mut final_buffer = Vec::with_capacity(glyph_width as usize *
glyph_height as usize *
@@ -215,6 +217,9 @@ impl FontContext {
}
}
FT_PIXEL_MODE_LCD => {
// Extra subpixel on each side of the glyph.
glyph_width += 2;

This comment has been minimized.

@pcwalton

pcwalton Nov 7, 2016

Collaborator

Ugly. :( Oh well, probably can't be helped.

for y in 0..bitmap.rows {
for x in 0..(bitmap.width / 3) {
let index = (y * bitmap.pitch) + (x * 3);
@@ -13,7 +13,8 @@ use std::mem;
use std::usize;
use texture_cache::TextureCacheItem;
use util::TransformedRect;
use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering, WebGLContextId};
use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering};
use webrender_traits::{FontRenderMode, WebGLContextId};
use webrender_traits::{ClipRegion, FontKey, ItemRange, ComplexClipRegion, GlyphKey};

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
@@ -186,6 +187,8 @@ pub struct TextRunPrimitiveCpu {
// TODO(gw): Maybe make this an Arc for sharing with resource cache
pub glyph_indices: Vec<u32>,
pub color_texture_id: TextureId,
pub color: ColorF,
pub render_mode: FontRenderMode,
}

#[derive(Debug, Clone)]
@@ -583,7 +586,8 @@ impl PrimitiveStore {
let texture_id = resource_cache.get_glyphs(text.font_key,
text.font_size,
text.blur_radius,
&text.glyph_indices, |index, uv0, uv1| {
&text.glyph_indices,
text.render_mode, |index, uv0, uv1| {
let dest_glyph = &mut dest_glyphs[index];
let dest: &mut GlyphPrimitive = unsafe {
mem::transmute(dest_glyph)
@@ -785,7 +789,8 @@ impl PrimitiveStore {
resource_cache.request_glyphs(text.font_key,
text.font_size,
text.blur_radius,
&text.glyph_indices);
&text.glyph_indices,
text.render_mode);
}
PrimitiveKind::Image => {
let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0];
@@ -92,6 +92,8 @@ const GPU_TAG_PRIM_BORDER: GpuProfileTag = GpuProfileTag { label: "Border", colo
pub enum BlendMode {
None,
Alpha,
// Use the color of the text itself as a constant color blend factor.
Subpixel(ColorF),
}

struct VertexDataTexture {
@@ -140,7 +142,8 @@ impl VertexDataTexture {
}
}

const TRANSFORM_FEATURE: &'static [&'static str] = &["TRANSFORM"];
const TRANSFORM_FEATURE: &'static str = "TRANSFORM";
const SUBPIXEL_AA_FEATURE: &'static str = "SUBPIXEL_AA";

enum ShaderKind {
Primitive,
@@ -153,22 +156,22 @@ struct LazilyCompiledShader {
name: &'static str,
kind: ShaderKind,
max_ubo_vectors: usize,
features: &'static [&'static str],
features: Vec<&'static str>,
}

impl LazilyCompiledShader {
fn new(kind: ShaderKind,
name: &'static str,
max_ubo_vectors: usize,
features: &'static [&'static str],
features: &[&'static str],
device: &mut Device,
precache: bool) -> LazilyCompiledShader {
let mut shader = LazilyCompiledShader {
id: None,
name: name,
kind: kind,
max_ubo_vectors: max_ubo_vectors,
features: features,
features: features.to_vec(),
};

if precache {
@@ -190,7 +193,7 @@ impl LazilyCompiledShader {
create_prim_shader(self.name,
device,
self.max_ubo_vectors,
self.features)
&self.features)
}
};
self.id = Some(id);
@@ -235,18 +238,22 @@ impl PrimitiveShader {
max_ubo_vectors: usize,
max_prim_items: usize,
device: &mut Device,
features: &[&'static str],
precache: bool) -> PrimitiveShader {
let simple = LazilyCompiledShader::new(ShaderKind::Primitive,
name,
max_ubo_vectors,
&[],
features,
device,
precache);

let mut transform_features = features.to_vec();
transform_features.push(TRANSFORM_FEATURE);

let transform = LazilyCompiledShader::new(ShaderKind::Primitive,
name,
max_ubo_vectors,
TRANSFORM_FEATURE,
&transform_features,
device,
precache);

@@ -335,6 +342,7 @@ pub struct Renderer {

ps_rectangle: PrimitiveShader,
ps_text_run: PrimitiveShader,
ps_text_run_subpixel: PrimitiveShader,
ps_image: PrimitiveShader,
ps_border: PrimitiveShader,
ps_gradient: PrimitiveShader,
@@ -443,53 +451,69 @@ impl Renderer {
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_text_run = PrimitiveShader::new("ps_text_run",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_text_run_subpixel = PrimitiveShader::new("ps_text_run",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[ SUBPIXEL_AA_FEATURE ],
options.precache_shaders);
let ps_image = PrimitiveShader::new("ps_image",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_border = PrimitiveShader::new("ps_border",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_rectangle_clip = PrimitiveShader::new("ps_rectangle_clip",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_image_clip = PrimitiveShader::new("ps_image_clip",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);

let ps_box_shadow = PrimitiveShader::new("ps_box_shadow",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);

let ps_gradient = PrimitiveShader::new("ps_gradient",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_gradient_clip = PrimitiveShader::new("ps_gradient_clip",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);
let ps_angle_gradient = PrimitiveShader::new("ps_angle_gradient",
max_ubo_vectors,
max_prim_instances,
&mut device,
&[],
options.precache_shaders);

let ps_blend = LazilyCompiledShader::new(ShaderKind::Primitive,
@@ -619,7 +643,8 @@ impl Renderer {
RendererKind::OSMesa => GLContextHandleWrapper::current_osmesa_handle(),
};

let config = FrameBuilderConfig::new(options.enable_scrollbars);
let config = FrameBuilderConfig::new(options.enable_scrollbars,
options.enable_subpixel_aa);

let debug = options.debug;
let (device_pixel_ratio, enable_aa) = (options.device_pixel_ratio, options.enable_aa);
@@ -657,6 +682,7 @@ impl Renderer {
cs_box_shadow: cs_box_shadow,
ps_rectangle: ps_rectangle,
ps_text_run: ps_text_run,
ps_text_run_subpixel: ps_text_run_subpixel,
ps_image: ps_image,
ps_border: ps_border,
ps_rectangle_clip: ps_rectangle_clip,
@@ -1405,9 +1431,13 @@ impl Renderer {

if batch.key.blend_mode != prev_blend_mode {
match batch.key.blend_mode {
// TODO(gw): More blend modes to come with subpixel aa work.
BlendMode::None | BlendMode::Alpha => {
self.device.set_blend(batch.key.blend_mode == BlendMode::Alpha);
self.device.set_blend_mode_alpha();
}
BlendMode::Subpixel(color) => {
self.device.set_blend(true);
self.device.set_blend_mode_subpixel(color);
}
}
prev_blend_mode = batch.key.blend_mode;
@@ -1502,7 +1532,10 @@ impl Renderer {
}
&PrimitiveBatchData::TextRun(ref ubo_data) => {
self.gpu_profile.add_marker(GPU_TAG_PRIM_TEXT_RUN);
let (shader, max_prim_items) = self.ps_text_run.get(&mut self.device, transform_kind);
let (shader, max_prim_items) = match batch.key.blend_mode {
BlendMode::Subpixel(..) => self.ps_text_run_subpixel.get(&mut self.device, transform_kind),
BlendMode::Alpha | BlendMode::None => self.ps_text_run.get(&mut self.device, transform_kind),
};
self.draw_ubo_batch(ubo_data,
shader,
1,
@@ -1686,4 +1719,5 @@ pub struct RendererOptions {
pub enable_scrollbars: bool,
pub precache_shaders: bool,
pub renderer_kind: RendererKind,
pub enable_subpixel_aa: bool,
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.