Add some more features to blending, and expand texture upload features

This commit is contained in:
Patrick Walton 2019-12-19 08:58:02 -08:00
parent 9124d9856a
commit 7c655246ae
7 changed files with 225 additions and 93 deletions

34
Cargo.lock generated
View File

@ -333,6 +333,20 @@ dependencies = [
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "cocoa"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "color-backtrace" name = "color-backtrace"
version = "0.1.3" version = "0.1.3"
@ -1260,6 +1274,20 @@ dependencies = [
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "metal"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "nfd" name = "nfd"
version = "0.0.4" version = "0.0.4"
@ -1631,10 +1659,10 @@ dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)", "cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_geometry 0.3.0", "pathfinder_geometry 0.3.0",
"pathfinder_gpu 0.1.0", "pathfinder_gpu 0.1.0",
@ -2791,6 +2819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54" "checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
"checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
"checksum color-backtrace 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "90242aff9b6439332beb77ee416126367adcd6376b0dc80b39250e7debdd913d" "checksum color-backtrace 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "90242aff9b6439332beb77ee416126367adcd6376b0dc80b39250e7debdd913d"
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
"checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
@ -2891,6 +2920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
"checksum metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd3f21d259068945192293b7a98b1c6844af9eb7602e393c405198b229efc157" "checksum metal 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd3f21d259068945192293b7a98b1c6844af9eb7602e393c405198b229efc157"
"checksum metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f83c7dcc2038e12f68493fa3de44235df27b2497178e257185b4b5b5d028a1e4"
"checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98" "checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98"
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"

View File

@ -17,10 +17,10 @@ use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr,
use pathfinder_geometry::rect::RectI; use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::Vector2I; use pathfinder_geometry::vector::Vector2I;
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{RenderTarget, BlendState, BufferData, BufferTarget, BufferUploadMode}; use pathfinder_gpu::{RenderTarget, BlendFunc, BlendOp, BufferData, BufferTarget, BufferUploadMode};
use pathfinder_gpu::{ClearOps, DepthFunc, Device, Primitive, RenderOptions, RenderState}; use pathfinder_gpu::{ClearOps, DepthFunc, Device, Primitive, RenderOptions, RenderState};
use pathfinder_gpu::{ShaderKind, StencilFunc, TextureData, TextureFormat, UniformData}; use pathfinder_gpu::{ShaderKind, StencilFunc, TextureData, TextureDataRef, TextureFormat};
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::ffi::CString; use std::ffi::CString;
use std::mem; use std::mem;
@ -86,28 +86,35 @@ impl GLDevice {
unsafe { unsafe {
// Set blend. // Set blend.
match render_options.blend { match render_options.blend {
BlendState::Off => { None => {
gl::Disable(gl::BLEND); ck(); gl::Disable(gl::BLEND); ck();
} }
BlendState::RGBOneAlphaOne => { Some(ref blend) => {
gl::BlendEquation(gl::FUNC_ADD); ck(); match blend.func {
gl::BlendFunc(gl::ONE, gl::ONE); ck(); BlendFunc::RGBOneAlphaOne => {
gl::Enable(gl::BLEND); ck(); gl::BlendFunc(gl::ONE, gl::ONE); ck();
} }
BlendState::RGBOneAlphaOneMinusSrcAlpha => { BlendFunc::RGBOneAlphaOneMinusSrcAlpha => {
gl::BlendEquation(gl::FUNC_ADD); ck(); gl::BlendFuncSeparate(gl::ONE,
gl::BlendFuncSeparate(gl::ONE, gl::ONE_MINUS_SRC_ALPHA,
gl::ONE_MINUS_SRC_ALPHA, gl::ONE,
gl::ONE, gl::ONE); ck();
gl::ONE); ck(); }
gl::Enable(gl::BLEND); ck(); BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha => {
} gl::BlendFuncSeparate(gl::SRC_ALPHA,
BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha => { gl::ONE_MINUS_SRC_ALPHA,
gl::BlendEquation(gl::FUNC_ADD); ck(); gl::ONE,
gl::BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE); ck();
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();
}
}
gl::Enable(gl::BLEND); ck(); gl::Enable(gl::BLEND); ck();
} }
} }
@ -198,13 +205,8 @@ impl GLDevice {
fn reset_render_options(&self, render_options: &RenderOptions) { fn reset_render_options(&self, render_options: &RenderOptions) {
unsafe { unsafe {
match render_options.blend { if render_options.blend.is_some() {
BlendState::Off => {} gl::Disable(gl::BLEND); ck();
BlendState::RGBOneAlphaOneMinusSrcAlpha |
BlendState::RGBOneAlphaOne |
BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha => {
gl::Disable(gl::BLEND); ck();
}
} }
if render_options.depth.is_some() { if render_options.depth.is_some() {
@ -252,8 +254,26 @@ impl Device for GLDevice {
texture texture
} }
fn create_texture_from_data(&self, size: Vector2I, data: &[u8]) -> GLTexture { fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef)
assert!(data.len() >= size.x() as usize * size.y() as usize); -> GLTexture {
let channels = match (format, data) {
(TextureFormat::R8, TextureDataRef::U8(_)) => 1,
(TextureFormat::RGBA8, TextureDataRef::U8(_)) => 4,
(TextureFormat::RGBA32F, TextureDataRef::F32(_)) => 4,
_ => panic!("Unimplemented texture format in `create_texture_from_data`!"),
};
let area = size.x() as usize * size.y() as usize;
let data_ptr = match data {
TextureDataRef::U8(data) => {
assert!(data.len() >= area * channels);
data.as_ptr() as *const GLvoid
}
TextureDataRef::F32(data) => {
assert!(data.len() >= area * channels);
data.as_ptr() as *const GLvoid
}
};
let mut texture = GLTexture { gl_texture: 0, size, format: TextureFormat::R8 }; let mut texture = GLTexture { gl_texture: 0, size, format: TextureFormat::R8 };
unsafe { unsafe {
@ -261,13 +281,13 @@ impl Device for GLDevice {
self.bind_texture(&texture, 0); self.bind_texture(&texture, 0);
gl::TexImage2D(gl::TEXTURE_2D, gl::TexImage2D(gl::TEXTURE_2D,
0, 0,
gl::R8 as GLint, format.gl_internal_format(),
size.x() as GLsizei, size.x() as GLsizei,
size.y() as GLsizei, size.y() as GLsizei,
0, 0,
gl::RED, format.gl_format(),
gl::UNSIGNED_BYTE, format.gl_type(),
data.as_ptr() as *const GLvoid); ck(); data_ptr)
} }
self.set_texture_parameters(&texture); self.set_texture_parameters(&texture);

View File

@ -33,7 +33,8 @@ pub trait Device: Sized {
type VertexAttr; type VertexAttr;
fn create_texture(&self, format: TextureFormat, size: Vector2I) -> Self::Texture; fn create_texture(&self, format: TextureFormat, size: Vector2I) -> Self::Texture;
fn create_texture_from_data(&self, size: Vector2I, data: &[u8]) -> Self::Texture; fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef)
-> Self::Texture;
fn create_shader(&self, resources: &dyn ResourceLoader, name: &str, kind: ShaderKind) fn create_shader(&self, resources: &dyn ResourceLoader, name: &str, kind: ShaderKind)
-> Self::Shader; -> Self::Shader;
fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind) fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind)
@ -88,7 +89,7 @@ pub trait Device: Sized {
.unwrap() .unwrap()
.to_luma(); .to_luma();
let size = Vector2I::new(image.width() as i32, image.height() as i32); let size = Vector2I::new(image.width() as i32, image.height() as i32);
self.create_texture_from_data(size, &image) self.create_texture_from_data(TextureFormat::R8, size, TextureDataRef::U8(&image))
} }
fn create_program_from_shader_names( fn create_program_from_shader_names(
@ -181,7 +182,7 @@ pub struct RenderState<'a, D> where D: Device {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RenderOptions { pub struct RenderOptions {
pub blend: BlendState, pub blend: Option<BlendState>,
pub depth: Option<DepthState>, pub depth: Option<DepthState>,
pub stencil: Option<StencilState>, pub stencil: Option<StencilState>,
pub clear_ops: ClearOps, pub clear_ops: ClearOps,
@ -201,14 +202,25 @@ pub enum RenderTarget<'a, D> where D: Device {
Framebuffer(&'a D::Framebuffer), Framebuffer(&'a D::Framebuffer),
} }
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct BlendState {
pub func: BlendFunc,
pub op: BlendOp,
}
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum BlendState { pub enum BlendFunc {
Off,
RGBOneAlphaOne, RGBOneAlphaOne,
RGBOneAlphaOneMinusSrcAlpha, RGBOneAlphaOneMinusSrcAlpha,
RGBSrcAlphaAlphaOneMinusSrcAlpha, RGBSrcAlphaAlphaOneMinusSrcAlpha,
} }
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BlendOp {
Add,
Subtract,
}
#[derive(Clone, Copy, Default, Debug)] #[derive(Clone, Copy, Default, Debug)]
pub struct DepthState { pub struct DepthState {
pub func: DepthFunc, pub func: DepthFunc,
@ -239,7 +251,7 @@ impl Default for RenderOptions {
#[inline] #[inline]
fn default() -> RenderOptions { fn default() -> RenderOptions {
RenderOptions { RenderOptions {
blend: BlendState::default(), blend: None,
depth: None, depth: None,
stencil: None, stencil: None,
clear_ops: ClearOps::default(), clear_ops: ClearOps::default(),
@ -248,10 +260,17 @@ impl Default for RenderOptions {
} }
} }
impl Default for BlendState { impl Default for BlendFunc {
#[inline] #[inline]
fn default() -> BlendState { fn default() -> BlendFunc {
BlendState::Off BlendFunc::RGBOneAlphaOneMinusSrcAlpha
}
}
impl Default for BlendOp {
#[inline]
fn default() -> BlendOp {
BlendOp::Add
} }
} }
@ -288,6 +307,12 @@ pub enum TextureData {
F32(Vec<f32>), F32(Vec<f32>),
} }
#[derive(Clone, Copy, Debug)]
pub enum TextureDataRef<'a> {
U8(&'a [u8]),
F32(&'a [f32]),
}
impl UniformData { impl UniformData {
#[inline] #[inline]
pub fn from_transform_3d(transform: &Transform4F) -> UniformData { pub fn from_transform_3d(transform: &Transform4F) -> UniformData {

View File

@ -8,10 +8,10 @@ edition = "2018"
bitflags = "1.0" bitflags = "1.0"
byteorder = "1.3" byteorder = "1.3"
block = "0.1" block = "0.1"
cocoa = "0.18" cocoa = "0.19"
core-foundation = "0.6" core-foundation = "0.6"
foreign-types = "0.3" foreign-types = "0.3"
metal = "0.14" metal = "0.17"
objc = "0.2" objc = "0.2"
[dependencies.pathfinder_geometry] [dependencies.pathfinder_geometry]

View File

@ -26,9 +26,9 @@ use foreign_types::{ForeignType, ForeignTypeRef};
use metal::{self, Argument, ArgumentEncoder, Buffer, CommandBuffer, CommandBufferRef}; use metal::{self, Argument, ArgumentEncoder, Buffer, CommandBuffer, CommandBufferRef};
use metal::{CommandQueue, CompileOptions, CoreAnimationDrawable, CoreAnimationDrawableRef}; use metal::{CommandQueue, CompileOptions, CoreAnimationDrawable, CoreAnimationDrawableRef};
use metal::{CoreAnimationLayer, CoreAnimationLayerRef, DepthStencilDescriptor, Function, Library}; use metal::{CoreAnimationLayer, CoreAnimationLayerRef, DepthStencilDescriptor, Function, Library};
use metal::{MTLArgument, MTLArgumentEncoder, MTLBlendFactor, MTLClearColor, MTLColorWriteMask}; use metal::{MTLArgument, MTLArgumentEncoder, MTLBlendFactor, MTLBlendOperation, MTLClearColor};
use metal::{MTLCompareFunction, MTLDataType, MTLDevice, MTLFunctionType, MTLIndexType}; use metal::{MTLColorWriteMask, MTLCompareFunction, MTLDataType, MTLDevice, MTLFunctionType};
use metal::{MTLLoadAction, MTLOrigin, MTLPixelFormat, MTLPrimitiveType, MTLRegion}; use metal::{MTLIndexType, MTLLoadAction, MTLOrigin, MTLPixelFormat, MTLPrimitiveType, MTLRegion};
use metal::{MTLRenderPipelineReflection, MTLRenderPipelineState, MTLResourceOptions}; use metal::{MTLRenderPipelineReflection, MTLRenderPipelineState, MTLResourceOptions};
use metal::{MTLResourceUsage, MTLSamplerAddressMode, MTLSamplerMinMagFilter, MTLSize}; use metal::{MTLResourceUsage, MTLSamplerAddressMode, MTLSamplerMinMagFilter, MTLSize};
use metal::{MTLStencilOperation, MTLStorageMode, MTLStoreAction, MTLTextureType, MTLTextureUsage}; use metal::{MTLStencilOperation, MTLStorageMode, MTLStoreAction, MTLTextureType, MTLTextureUsage};
@ -43,9 +43,9 @@ use objc::runtime::{Class, Object};
use pathfinder_geometry::rect::RectI; use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::Vector2I; use pathfinder_geometry::vector::Vector2I;
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, DepthFunc, Device}; use pathfinder_gpu::{BlendFunc, BlendOp, BufferData, BufferTarget, BufferUploadMode, DepthFunc};
use pathfinder_gpu::{Primitive, RenderState, RenderTarget, ShaderKind, StencilFunc, TextureData}; use pathfinder_gpu::{Device, Primitive, RenderState, RenderTarget, ShaderKind, StencilFunc};
use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrClass}; use pathfinder_gpu::{TextureData, TextureDataRef, TextureFormat, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::{F32x2, F32x4}; use pathfinder_simd::default::{F32x2, F32x4};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -196,6 +196,7 @@ impl Device for MetalDevice {
TextureFormat::R8 => descriptor.set_pixel_format(MTLPixelFormat::R8Unorm), TextureFormat::R8 => descriptor.set_pixel_format(MTLPixelFormat::R8Unorm),
TextureFormat::R16F => descriptor.set_pixel_format(MTLPixelFormat::R16Float), TextureFormat::R16F => descriptor.set_pixel_format(MTLPixelFormat::R16Float),
TextureFormat::RGBA8 => descriptor.set_pixel_format(MTLPixelFormat::RGBA8Unorm), TextureFormat::RGBA8 => descriptor.set_pixel_format(MTLPixelFormat::RGBA8Unorm),
TextureFormat::RGBA32F => descriptor.set_pixel_format(MTLPixelFormat::RGBA32Float),
} }
descriptor.set_width(size.x() as u64); descriptor.set_width(size.x() as u64);
descriptor.set_height(size.y() as u64); descriptor.set_height(size.y() as u64);
@ -204,11 +205,18 @@ impl Device for MetalDevice {
MetalTexture { texture: self.device.new_texture(&descriptor), dirty: Cell::new(false) } MetalTexture { texture: self.device.new_texture(&descriptor), dirty: Cell::new(false) }
} }
fn create_texture_from_data(&self, size: Vector2I, data: &[u8]) -> MetalTexture { fn create_texture_from_data(&self, format: TextureFormat, size: Vector2I, data: TextureDataRef)
assert!(data.len() >= size.x() as usize * size.y() as usize); -> MetalTexture {
let texture = self.create_texture(TextureFormat::R8, size); match (format, data) {
self.upload_to_texture(&texture, size, data); (TextureFormat::R8, TextureDataRef::U8(data)) => {
texture assert!(data.len() >= size.x() as usize * size.y() as usize);
let texture = self.create_texture(TextureFormat::R8, size);
self.upload_to_texture(&texture, size, data);
texture
}
_ => panic!("Unimplemented texture format in `create_texture_from_data`!"),
}
} }
fn create_shader_from_source(&self, _: &str, source: &[u8], _: ShaderKind) -> MetalShader { fn create_shader_from_source(&self, _: &str, source: &[u8], _: ShaderKind) -> MetalShader {
@ -455,6 +463,16 @@ impl Device for MetalDevice {
stride as u64 * 2); stride as u64 * 2);
TextureData::U16(pixels) TextureData::U16(pixels)
} }
TextureFormat::RGBA32F => {
let channels = format.channels();
let stride = size.x() as usize * channels;
let mut pixels = vec![0.0; stride * size.y() as usize];
texture.get_bytes(pixels.as_mut_ptr() as *mut _,
metal_region,
0,
stride as u64 * 4);
TextureData::F32(pixels)
}
} }
} }
@ -922,29 +940,53 @@ impl MetalDevice {
let pixel_format = self.render_target_color_texture(&render_state.target).pixel_format(); let pixel_format = self.render_target_color_texture(&render_state.target).pixel_format();
pipeline_color_attachment.set_pixel_format(pixel_format); pipeline_color_attachment.set_pixel_format(pixel_format);
let blending_enabled = render_state.options.blend != BlendState::Off;
pipeline_color_attachment.set_blending_enabled(blending_enabled);
match render_state.options.blend { match render_state.options.blend {
BlendState::Off => {} None => pipeline_color_attachment.set_blending_enabled(false),
BlendState::RGBOneAlphaOne => { Some(ref blend) => {
pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One); pipeline_color_attachment.set_blending_enabled(true);
pipeline_color_attachment.set_destination_rgb_blend_factor(MTLBlendFactor::One); match blend.func {
pipeline_color_attachment.set_source_alpha_blend_factor(MTLBlendFactor::One); BlendFunc::RGBOneAlphaOne => {
pipeline_color_attachment.set_destination_alpha_blend_factor(MTLBlendFactor::One); pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One);
} pipeline_color_attachment.set_destination_rgb_blend_factor(
BlendState::RGBOneAlphaOneMinusSrcAlpha => { MTLBlendFactor::One);
pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One); pipeline_color_attachment.set_source_alpha_blend_factor(
pipeline_color_attachment.set_destination_rgb_blend_factor( MTLBlendFactor::One);
MTLBlendFactor::OneMinusSourceAlpha); pipeline_color_attachment.set_destination_alpha_blend_factor(
pipeline_color_attachment.set_source_alpha_blend_factor(MTLBlendFactor::One); MTLBlendFactor::One);
pipeline_color_attachment.set_destination_alpha_blend_factor(MTLBlendFactor::One); }
} BlendFunc::RGBOneAlphaOneMinusSrcAlpha => {
BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha => { pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::One);
pipeline_color_attachment.set_source_rgb_blend_factor(MTLBlendFactor::SourceAlpha); pipeline_color_attachment.set_destination_rgb_blend_factor(
pipeline_color_attachment.set_destination_rgb_blend_factor( MTLBlendFactor::OneMinusSourceAlpha);
MTLBlendFactor::OneMinusSourceAlpha); pipeline_color_attachment.set_source_alpha_blend_factor(
pipeline_color_attachment.set_source_alpha_blend_factor(MTLBlendFactor::One); MTLBlendFactor::One);
pipeline_color_attachment.set_destination_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);
}
}
match blend.op {
BlendOp::Add => {
pipeline_color_attachment.set_rgb_blend_operation(MTLBlendOperation::Add);
pipeline_color_attachment.set_alpha_blend_operation(
MTLBlendOperation::Add);
}
BlendOp::Subtract => {
pipeline_color_attachment.set_rgb_blend_operation(
MTLBlendOperation::Subtract);
pipeline_color_attachment.set_alpha_blend_operation(
MTLBlendOperation::Subtract);
}
}
} }
} }
@ -1228,7 +1270,7 @@ impl SharedEvent {
*mut BlockBase<(*mut Object, u64), ()>; *mut BlockBase<(*mut Object, u64), ()>;
(*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE; (*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE;
(*block).extra = &BLOCK_EXTRA; (*block).extra = &BLOCK_EXTRA;
msg_send![self.0, notifyListener:listener.0 atValue:value block:block]; let () = msg_send![self.0, notifyListener:listener.0 atValue:value block:block];
mem::forget(block); mem::forget(block);
} }
@ -1376,7 +1418,7 @@ impl FunctionExt for Function {
let encoder: *mut MTLArgumentEncoder = let encoder: *mut MTLArgumentEncoder =
msg_send![self.as_ptr(), newArgumentEncoderWithBufferIndex:buffer_index msg_send![self.as_ptr(), newArgumentEncoderWithBufferIndex:buffer_index
reflection:&mut reflection]; reflection:&mut reflection];
msg_send![reflection, retain]; let () = msg_send![reflection, retain];
(ArgumentEncoder::from_ptr(encoder), Argument::from_ptr(reflection)) (ArgumentEncoder::from_ptr(encoder), Argument::from_ptr(reflection))
} }
} }

View File

@ -19,7 +19,7 @@ use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::transform3d::Transform4F; use pathfinder_geometry::transform3d::Transform4F;
use pathfinder_content::color::ColorF; use pathfinder_content::color::ColorF;
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearOps}; use pathfinder_gpu::{BlendFunc, BlendState, BufferData, BufferTarget, BufferUploadMode, ClearOps};
use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderOptions, RenderState}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderOptions, RenderState};
use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureFormat, UniformData}; use pathfinder_gpu::{RenderTarget, StencilFunc, StencilState, TextureFormat, UniformData};
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
@ -455,7 +455,10 @@ where
], ],
viewport: self.mask_viewport(), viewport: self.mask_viewport(),
options: RenderOptions { options: RenderOptions {
blend: BlendState::RGBOneAlphaOne, blend: Some(BlendState {
func: BlendFunc::RGBOneAlphaOne,
..BlendState::default()
}),
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default() ..RenderOptions::default()
}, },
@ -523,7 +526,10 @@ where
uniforms: &uniforms, uniforms: &uniforms,
viewport: self.draw_viewport(), viewport: self.draw_viewport(),
options: RenderOptions { options: RenderOptions {
blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, blend: Some(BlendState {
func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha,
..BlendState::default()
}),
stencil: self.stencil_state(), stencil: self.stencil_state(),
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default() ..RenderOptions::default()
@ -754,7 +760,10 @@ where
], ],
viewport: self.draw_viewport(), viewport: self.draw_viewport(),
options: RenderOptions { options: RenderOptions {
blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, blend: Some(BlendState {
func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha,
..BlendState::default()
}),
depth: Some(DepthState { func: DepthFunc::Less, write: false, }), depth: Some(DepthState { func: DepthFunc::Less, write: false, }),
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default() ..RenderOptions::default()

View File

@ -21,9 +21,9 @@ use pathfinder_content::color::ColorU;
use pathfinder_geometry::rect::RectI; use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_geometry::vector::{Vector2F, Vector2I};
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, Device, Primitive}; use pathfinder_gpu::{BlendFunc, BlendState, BufferData, BufferTarget, BufferUploadMode, Device};
use pathfinder_gpu::{RenderOptions, RenderState, RenderTarget, UniformData, VertexAttrClass}; use pathfinder_gpu::{Primitive, RenderOptions, RenderState, RenderTarget, UniformData};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use serde_json; use serde_json;
use std::mem; use std::mem;
@ -187,7 +187,10 @@ impl<D> UIPresenter<D> where D: Device {
textures: &[], textures: &[],
viewport: RectI::new(Vector2I::default(), self.framebuffer_size), viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
options: RenderOptions { options: RenderOptions {
blend: BlendState::RGBOneAlphaOneMinusSrcAlpha, blend: Some(BlendState {
func: BlendFunc::RGBOneAlphaOneMinusSrcAlpha,
..BlendState::default()
}),
..RenderOptions::default() ..RenderOptions::default()
}, },
}); });
@ -422,7 +425,10 @@ impl<D> UIPresenter<D> where D: Device {
], ],
viewport: RectI::new(Vector2I::default(), self.framebuffer_size), viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
options: RenderOptions { options: RenderOptions {
blend: BlendState::RGBOneAlphaOneMinusSrcAlpha, blend: Some(BlendState {
func: BlendFunc::RGBOneAlphaOneMinusSrcAlpha,
..BlendState::default()
}),
..RenderOptions::default() ..RenderOptions::default()
}, },
}); });