From 0c3dad974f32c92db3559fbcb75501e635e7ceb3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 20 Feb 2020 15:28:37 -0800 Subject: [PATCH] Expose individual blend factors in `pathfinder_gpu` --- gl/src/lib.rs | 74 ++++++++++++++++---------------- gpu/src/lib.rs | 36 ++++++++++------ metal/src/lib.rs | 81 +++++++++++++++++++----------------- renderer/src/gpu/renderer.rs | 39 +++++++++-------- ui/src/lib.rs | 24 ++++++----- 5 files changed, 141 insertions(+), 113 deletions(-) diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 34684887..46eda09a 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -19,7 +19,7 @@ use half::f16; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::resources::ResourceLoader; -use pathfinder_gpu::{BlendFunc, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps}; +use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps}; use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderOptions, RenderState, RenderTarget}; use pathfinder_gpu::{ShaderKind, StencilFunc, TextureData, TextureDataRef, TextureFormat}; use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; @@ -92,40 +92,11 @@ impl GLDevice { gl::Disable(gl::BLEND); ck(); } Some(ref blend) => { - match blend.func { - BlendFunc::RGBOneAlphaOne => { - gl::BlendFunc(gl::ONE, gl::ONE); ck(); - } - BlendFunc::RGBOneAlphaOneMinusSrcAlpha => { - gl::BlendFuncSeparate(gl::ONE, - gl::ONE_MINUS_SRC_ALPHA, - gl::ONE, - gl::ONE); ck(); - } - BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha => { - gl::BlendFuncSeparate(gl::SRC_ALPHA, - gl::ONE_MINUS_SRC_ALPHA, - gl::ONE, - gl::ONE); ck(); - } - } - match blend.op { - BlendOp::Add => { - gl::BlendEquation(gl::FUNC_ADD); ck(); - } - BlendOp::Subtract => { - gl::BlendEquation(gl::FUNC_SUBTRACT); ck(); - } - BlendOp::ReverseSubtract => { - gl::BlendEquation(gl::FUNC_REVERSE_SUBTRACT); ck(); - } - BlendOp::Min => { - gl::BlendEquation(gl::MIN); ck(); - } - BlendOp::Max => { - gl::BlendEquation(gl::MAX); ck(); - } - } + gl::BlendFuncSeparate(blend.src_rgb_factor.to_gl_blend_factor(), + blend.dest_rgb_factor.to_gl_blend_factor(), + blend.src_alpha_factor.to_gl_blend_factor(), + blend.dest_alpha_factor.to_gl_blend_factor()); ck(); + gl::BlendEquation(blend.op.to_gl_blend_op()); ck(); gl::Enable(gl::BLEND); ck(); } } @@ -982,6 +953,39 @@ impl Drop for GLTimerQuery { } } +trait BlendFactorExt { + fn to_gl_blend_factor(self) -> GLenum; +} + +impl BlendFactorExt for BlendFactor { + #[inline] + fn to_gl_blend_factor(self) -> GLenum { + match self { + BlendFactor::Zero => gl::ZERO, + BlendFactor::One => gl::ONE, + BlendFactor::SrcAlpha => gl::SRC_ALPHA, + BlendFactor::OneMinusSrcAlpha => gl::ONE_MINUS_SRC_ALPHA, + } + } +} + +trait BlendOpExt { + fn to_gl_blend_op(self) -> GLenum; +} + +impl BlendOpExt for BlendOp { + #[inline] + fn to_gl_blend_op(self) -> GLenum { + match self { + BlendOp::Add => gl::FUNC_ADD, + BlendOp::Subtract => gl::FUNC_SUBTRACT, + BlendOp::ReverseSubtract => gl::FUNC_REVERSE_SUBTRACT, + BlendOp::Min => gl::MIN, + BlendOp::Max => gl::MAX, + } + } +} + trait BufferTargetExt { fn to_gl_target(self) -> GLuint; } diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index c86b814b..34069d78 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -211,17 +211,21 @@ pub enum RenderTarget<'a, D> where D: Device { Framebuffer(&'a D::Framebuffer), } -#[derive(Clone, Copy, Debug, PartialEq, Default)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct BlendState { - pub func: BlendFunc, + pub dest_rgb_factor: BlendFactor, + pub dest_alpha_factor: BlendFactor, + pub src_rgb_factor: BlendFactor, + pub src_alpha_factor: BlendFactor, pub op: BlendOp, } #[derive(Clone, Copy, Debug, PartialEq)] -pub enum BlendFunc { - RGBOneAlphaOne, - RGBOneAlphaOneMinusSrcAlpha, - RGBSrcAlphaAlphaOneMinusSrcAlpha, +pub enum BlendFactor { + Zero, + One, + SrcAlpha, + OneMinusSrcAlpha, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -272,13 +276,6 @@ impl Default for RenderOptions { } } -impl Default for BlendFunc { - #[inline] - fn default() -> BlendFunc { - BlendFunc::RGBOneAlphaOneMinusSrcAlpha - } -} - impl Default for BlendOp { #[inline] fn default() -> BlendOp { @@ -380,6 +377,19 @@ impl ClearOps { } } +impl Default for BlendState { + #[inline] + fn default() -> BlendState { + BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, + op: BlendOp::Add, + } + } +} + impl<'a> TextureDataRef<'a> { #[doc(hidden)] pub fn check_and_extract_data_ptr(self, minimum_size: Vector2I, format: TextureFormat) diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 01050d7e..b998a725 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -44,7 +44,7 @@ use objc::runtime::{Class, Object}; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::Vector2I; use pathfinder_gpu::resources::ResourceLoader; -use pathfinder_gpu::{BlendFunc, BlendOp, BufferData, BufferTarget, BufferUploadMode, DepthFunc}; +use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, DepthFunc}; use pathfinder_gpu::{Device, Primitive, RenderState, RenderTarget, ShaderKind, StencilFunc}; use pathfinder_gpu::{TextureData, TextureDataRef, TextureFormat, UniformData, VertexAttrClass}; use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; @@ -993,45 +993,17 @@ impl MetalDevice { None => pipeline_color_attachment.set_blending_enabled(false), Some(ref blend) => { pipeline_color_attachment.set_blending_enabled(true); - match blend.func { - BlendFunc::RGBOneAlphaOne => { - pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One); - pipeline_color_attachment.set_destination_rgb_blend_factor( - MTLBlendFactor::One); - pipeline_color_attachment.set_source_alpha_blend_factor( - MTLBlendFactor::One); - pipeline_color_attachment.set_destination_alpha_blend_factor( - MTLBlendFactor::One); - } - BlendFunc::RGBOneAlphaOneMinusSrcAlpha => { - pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One); - pipeline_color_attachment.set_destination_rgb_blend_factor( - MTLBlendFactor::OneMinusSourceAlpha); - pipeline_color_attachment.set_source_alpha_blend_factor( - MTLBlendFactor::One); - pipeline_color_attachment.set_destination_alpha_blend_factor( - MTLBlendFactor::One); - } - BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha => { - pipeline_color_attachment.set_source_rgb_blend_factor( - MTLBlendFactor::SourceAlpha); - pipeline_color_attachment.set_destination_rgb_blend_factor( - MTLBlendFactor::OneMinusSourceAlpha); - pipeline_color_attachment.set_source_alpha_blend_factor( - MTLBlendFactor::One); - pipeline_color_attachment.set_destination_alpha_blend_factor( - MTLBlendFactor::One); - } - } - let blend_op = match blend.op { - BlendOp::Add => MTLBlendOperation::Add, - BlendOp::Subtract => MTLBlendOperation::Subtract, - BlendOp::ReverseSubtract => MTLBlendOperation::ReverseSubtract, - BlendOp::Min => MTLBlendOperation::Min, - BlendOp::Max => MTLBlendOperation::Max, - }; + pipeline_color_attachment.set_source_rgb_blend_factor( + blend.src_rgb_factor.to_metal_blend_factor()); + pipeline_color_attachment.set_destination_rgb_blend_factor( + blend.dest_rgb_factor.to_metal_blend_factor()); + pipeline_color_attachment.set_source_alpha_blend_factor( + blend.src_alpha_factor.to_metal_blend_factor()); + pipeline_color_attachment.set_destination_alpha_blend_factor( + blend.dest_alpha_factor.to_metal_blend_factor()); + let blend_op = blend.op.to_metal_blend_op(); pipeline_color_attachment.set_rgb_blend_operation(blend_op); pipeline_color_attachment.set_alpha_blend_operation(blend_op); } @@ -1186,6 +1158,39 @@ impl DeviceExtra for metal::Device { // Conversion helpers +trait BlendFactorExt { + fn to_metal_blend_factor(self) -> MTLBlendFactor; +} + +impl BlendFactorExt for BlendFactor { + #[inline] + fn to_metal_blend_factor(self) -> MTLBlendFactor { + match self { + BlendFactor::Zero => MTLBlendFactor::Zero, + BlendFactor::One => MTLBlendFactor::One, + BlendFactor::SrcAlpha => MTLBlendFactor::SourceAlpha, + BlendFactor::OneMinusSrcAlpha => MTLBlendFactor::OneMinusSourceAlpha, + } + } +} + +trait BlendOpExt { + fn to_metal_blend_op(self) -> MTLBlendOperation; +} + +impl BlendOpExt for BlendOp { + #[inline] + fn to_metal_blend_op(self) -> MTLBlendOperation { + match self { + BlendOp::Add => MTLBlendOperation::Add, + BlendOp::Subtract => MTLBlendOperation::Subtract, + BlendOp::ReverseSubtract => MTLBlendOperation::ReverseSubtract, + BlendOp::Min => MTLBlendOperation::Min, + BlendOp::Max => MTLBlendOperation::Max, + } + } +} + trait DepthFuncExt { fn to_metal_compare_function(self) -> MTLCompareFunction; } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 41ae72d1..9204a372 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -26,7 +26,7 @@ use pathfinder_geometry::vector::{Vector2I, Vector4F}; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::transform3d::Transform4F; use pathfinder_gpu::resources::ResourceLoader; -use pathfinder_gpu::{BlendFunc, BlendOp, BlendState, BufferData, BufferTarget, BufferUploadMode}; +use pathfinder_gpu::{BlendFactor, BlendOp, BlendState, BufferData, BufferTarget, BufferUploadMode}; use pathfinder_gpu::{ClearOps, DepthFunc, DepthState, Device, Primitive, RenderOptions}; use pathfinder_gpu::{RenderState, RenderTarget, StencilFunc, StencilState, TextureDataRef}; use pathfinder_gpu::{TextureFormat, UniformData}; @@ -525,7 +525,10 @@ where viewport: self.mask_viewport(), options: RenderOptions { blend: Some(BlendState { - func: BlendFunc::RGBOneAlphaOne, + src_rgb_factor: BlendFactor::One, + src_alpha_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, ..BlendState::default() }), clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, @@ -577,7 +580,10 @@ where viewport: self.mask_viewport(), options: RenderOptions { blend: Some(BlendState { - func: BlendFunc::RGBOneAlphaOne, + src_rgb_factor: BlendFactor::One, + src_alpha_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, op: BlendOp::Min, ..BlendState::default() }), @@ -623,10 +629,7 @@ where uniforms: &uniforms, viewport: self.draw_viewport(), options: RenderOptions { - blend: Some(BlendState { - func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha, - ..BlendState::default() - }), + blend: Some(alpha_blend_state()), stencil: self.stencil_state(), clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, ..RenderOptions::default() @@ -740,10 +743,7 @@ where ], viewport: self.draw_viewport(), options: RenderOptions { - blend: Some(BlendState { - func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha, - ..BlendState::default() - }), + blend: Some(alpha_blend_state()), depth: Some(DepthState { func: DepthFunc::Less, write: false, }), clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, ..RenderOptions::default() @@ -829,12 +829,7 @@ where ]; let blend_state = match composite_op { - CompositeOp::SourceOver => { - BlendState { - func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha, - ..BlendState::default() - } - } + CompositeOp::SourceOver => alpha_blend_state(), }; self.device.draw_elements(6, &RenderState { @@ -1111,3 +1106,13 @@ struct LayerFramebufferInfo where D: Device { effects: Effects, must_preserve_contents: bool, } + +fn alpha_blend_state() -> BlendState { + BlendState { + src_rgb_factor: BlendFactor::SrcAlpha, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, + ..BlendState::default() + } +} diff --git a/ui/src/lib.rs b/ui/src/lib.rs index c69cf6fc..cdc2ee43 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,6 +1,6 @@ // pathfinder/ui/src/lib.rs // -// Copyright © 2019 The Pathfinder Project Developers. +// Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -21,7 +21,7 @@ use pathfinder_color::ColorU; use pathfinder_geometry::rect::RectI; use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_gpu::resources::ResourceLoader; -use pathfinder_gpu::{BlendFunc, BlendState, BufferData, BufferTarget, BufferUploadMode, Device}; +use pathfinder_gpu::{BlendFactor, BlendState, BufferData, BufferTarget, BufferUploadMode, Device}; use pathfinder_gpu::{Primitive, RenderOptions, RenderState, RenderTarget, UniformData}; use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_simd::default::F32x4; @@ -187,10 +187,7 @@ impl UIPresenter where D: Device { textures: &[], viewport: RectI::new(Vector2I::default(), self.framebuffer_size), options: RenderOptions { - blend: Some(BlendState { - func: BlendFunc::RGBOneAlphaOneMinusSrcAlpha, - ..BlendState::default() - }), + blend: Some(alpha_blend_state()), ..RenderOptions::default() }, }); @@ -425,10 +422,7 @@ impl UIPresenter where D: Device { ], viewport: RectI::new(Vector2I::default(), self.framebuffer_size), options: RenderOptions { - blend: Some(BlendState { - func: BlendFunc::RGBOneAlphaOneMinusSrcAlpha, - ..BlendState::default() - }), + blend: Some(alpha_blend_state()), ..RenderOptions::default() }, }); @@ -830,3 +824,13 @@ impl DebugFont { serde_json::from_slice(&resources.slurp(FONT_JSON_VIRTUAL_PATH).unwrap()).unwrap() } } + +fn alpha_blend_state() -> BlendState { + BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::One, + ..BlendState::default() + } +}