tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lib.rs (14442B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 use crate::command::{RecordedComputePass, RecordedRenderPass};
      6 use wgc::id;
      7 
      8 pub mod client;
      9 pub mod command;
     10 pub mod error;
     11 pub mod server;
     12 
     13 pub use wgc::command::ffi::Command as CommandEncoderAction;
     14 
     15 use std::marker::PhantomData;
     16 use std::{borrow::Cow, mem, slice};
     17 
     18 use nsstring::nsACString;
     19 
     20 type RawString = *const std::os::raw::c_char;
     21 
     22 fn cow_label(raw: &RawString) -> Option<Cow<'_, str>> {
     23    if raw.is_null() {
     24        None
     25    } else {
     26        let cstr = unsafe { std::ffi::CStr::from_ptr(*raw) };
     27        cstr.to_str().ok().map(Cow::Borrowed)
     28    }
     29 }
     30 
     31 // Hides the repeated boilerplate of turning a `Option<&nsACString>` into a `Option<Cow<str>`.
     32 pub fn wgpu_string(gecko_string: Option<&nsACString>) -> Option<Cow<'_, str>> {
     33    gecko_string.map(|s| s.to_utf8())
     34 }
     35 
     36 /// An equivalent of `&[T]` for ffi structures and function parameters.
     37 #[repr(C)]
     38 pub struct FfiSlice<'a, T> {
     39    // `data` may be null.
     40    pub data: *const T,
     41    pub length: usize,
     42    pub _marker: PhantomData<&'a T>,
     43 }
     44 
     45 impl<'a, T> FfiSlice<'a, T> {
     46    pub fn from_slice(slice: &'a [T]) -> FfiSlice<'a, T> {
     47        Self {
     48            data: slice.as_ptr(),
     49            length: slice.len(),
     50            _marker: PhantomData,
     51        }
     52    }
     53 
     54    pub unsafe fn as_slice(&self) -> &'a [T] {
     55        if self.data.is_null() {
     56            // It is invalid to construct a rust slice with a null pointer.
     57            return &[];
     58        }
     59 
     60        std::slice::from_raw_parts(self.data, self.length)
     61    }
     62 }
     63 
     64 impl<'a, T> Copy for FfiSlice<'a, T> {}
     65 impl<'a, T> Clone for FfiSlice<'a, T> {
     66    fn clone(&self) -> Self {
     67        *self
     68    }
     69 }
     70 
     71 #[repr(C)]
     72 pub struct ByteBuf {
     73    data: *mut u8,
     74    len: usize,
     75    capacity: usize,
     76 }
     77 
     78 impl ByteBuf {
     79    fn new() -> Self {
     80        Self {
     81            data: std::ptr::null_mut(),
     82            len: 0,
     83            capacity: 0,
     84        }
     85    }
     86 
     87    fn is_empty(&self) -> bool {
     88        self.len == 0
     89    }
     90 
     91    fn from_vec(mut vec: Vec<u8>) -> Self {
     92        if vec.is_empty() {
     93            ByteBuf::new()
     94        } else {
     95            let bb = ByteBuf {
     96                data: vec.as_mut_ptr(),
     97                len: vec.len(),
     98                capacity: vec.capacity(),
     99            };
    100            mem::forget(vec);
    101            bb
    102        }
    103    }
    104 
    105    unsafe fn as_slice(&self) -> &[u8] {
    106        slice::from_raw_parts(self.data, self.len)
    107    }
    108 }
    109 
    110 fn make_byte_buf<T: serde::Serialize>(data: &T) -> ByteBuf {
    111    let vec = bincode::serialize(data).unwrap();
    112    ByteBuf::from_vec(vec)
    113 }
    114 
    115 #[repr(C)]
    116 #[derive(serde::Serialize, serde::Deserialize)]
    117 pub struct AdapterInformation<S> {
    118    id: id::AdapterId,
    119    limits: wgt::Limits,
    120    features: wgt::FeaturesWebGPU,
    121    name: S,
    122    vendor: u32,
    123    device: u32,
    124    device_type: wgt::DeviceType,
    125    driver: S,
    126    driver_info: S,
    127    backend: wgt::Backend,
    128    support_use_shared_texture_in_swap_chain: bool,
    129    transient_saves_memory: bool,
    130    subgroup_min_size: u32,
    131    subgroup_max_size: u32,
    132 }
    133 
    134 #[repr(C)]
    135 pub struct TextureViewDescriptor<'a> {
    136    label: Option<&'a nsACString>,
    137    format: Option<&'a wgt::TextureFormat>,
    138    dimension: Option<&'a wgt::TextureViewDimension>,
    139    aspect: wgt::TextureAspect,
    140    base_mip_level: u32,
    141    mip_level_count: Option<&'a u32>,
    142    base_array_layer: u32,
    143    array_layer_count: Option<&'a u32>,
    144 }
    145 
    146 // Declare an ID type for referring to external texture sources, and allow
    147 // them to be managed by IdentityHub just like built-in wgpu resource types.
    148 #[derive(Debug)]
    149 pub enum ExternalTextureSource {}
    150 impl id::Marker for ExternalTextureSource {}
    151 pub type ExternalTextureSourceId = id::Id<ExternalTextureSource>;
    152 
    153 #[repr(C)]
    154 #[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
    155 pub enum PredefinedColorSpace {
    156    Srgb,
    157    DisplayP3,
    158 }
    159 
    160 // Descriptor for creating an external texture as used by the client side.
    161 // Contains the fields of dom::GPUExternalTextureDescriptor, but with the
    162 // source encoded as an ID.
    163 #[repr(C)]
    164 #[derive(serde::Serialize, serde::Deserialize)]
    165 pub struct ExternalTextureDescriptor<L> {
    166    label: L,
    167    source: Option<crate::ExternalTextureSourceId>,
    168    color_space: PredefinedColorSpace,
    169 }
    170 
    171 impl<L> ExternalTextureDescriptor<L> {
    172    #[must_use]
    173    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> ExternalTextureDescriptor<K> {
    174        ExternalTextureDescriptor {
    175            label: fun(&self.label),
    176            source: self.source,
    177            color_space: self.color_space,
    178        }
    179    }
    180 }
    181 
    182 // Descriptor for creating an external texture as used by the server side. This
    183 // contains information that can only be provided from the server side via the
    184 // `ExternalTextureSourceHost`. It will be combined with the
    185 // `ExternalTextureDescriptor` provided by the client in order to create the
    186 // descriptor that will be passed to wgpu.
    187 #[repr(C)]
    188 struct ExternalTextureDescriptorFromSource<'a> {
    189    planes: FfiSlice<'a, id::TextureViewId>,
    190    width: u32,
    191    height: u32,
    192    format: wgt::ExternalTextureFormat,
    193    yuv_conversion_matrix: [f32; 16],
    194    gamut_conversion_matrix: [f32; 9],
    195    src_transfer_function: wgt::ExternalTextureTransferFunction,
    196    dst_transfer_function: wgt::ExternalTextureTransferFunction,
    197    sample_transform: [f32; 6],
    198    load_transform: [f32; 6],
    199 }
    200 
    201 #[derive(serde::Serialize, serde::Deserialize)]
    202 #[repr(transparent)]
    203 pub struct SurfaceFormat(i8);
    204 #[derive(serde::Serialize, serde::Deserialize)]
    205 #[repr(transparent)]
    206 pub struct RemoteTextureOwnerId(u64);
    207 #[derive(serde::Serialize, serde::Deserialize)]
    208 #[repr(transparent)]
    209 pub struct RemoteTextureId(u64);
    210 #[derive(serde::Serialize, serde::Deserialize)]
    211 #[repr(transparent)]
    212 pub struct RemoteTextureTxnType(u32);
    213 #[derive(serde::Serialize, serde::Deserialize)]
    214 #[repr(transparent)]
    215 pub struct RemoteTextureTxnId(u64);
    216 
    217 #[derive(serde::Serialize, serde::Deserialize)]
    218 #[repr(C)]
    219 #[derive(Copy, Clone, Debug)]
    220 #[cfg(target_os = "windows")]
    221 pub struct FfiLUID {
    222    low_part: core::ffi::c_ulong,
    223    high_part: core::ffi::c_long,
    224 }
    225 
    226 #[derive(serde::Serialize, serde::Deserialize)]
    227 pub enum QueueWriteDataSource {
    228    DataBuffer(usize),
    229    Shmem(usize),
    230 }
    231 
    232 const MAX_SWAPCHAIN_BUFFER_COUNT: usize = 10;
    233 
    234 #[derive(serde::Serialize, serde::Deserialize)]
    235 enum Message<'a> {
    236    RequestAdapter {
    237        adapter_id: id::AdapterId,
    238        power_preference: wgt::PowerPreference,
    239        force_fallback_adapter: bool,
    240    },
    241    RequestDevice {
    242        adapter_id: id::AdapterId,
    243        device_id: id::DeviceId,
    244        queue_id: id::QueueId,
    245        desc: wgc::device::DeviceDescriptor<'a>,
    246    },
    247    Device(id::DeviceId, DeviceAction<'a>),
    248    Texture(id::DeviceId, id::TextureId, TextureAction<'a>),
    249    CommandEncoder(id::DeviceId, id::CommandEncoderId, CommandEncoderAction),
    250    CommandEncoderFinish(
    251        id::DeviceId,
    252        id::CommandEncoderId,
    253        id::CommandBufferId,
    254        wgt::CommandBufferDescriptor<wgc::Label<'a>>,
    255    ),
    256    ReplayRenderPass(id::DeviceId, id::CommandEncoderId, RecordedRenderPass),
    257    ReplayComputePass(id::DeviceId, id::CommandEncoderId, RecordedComputePass),
    258    QueueWrite {
    259        device_id: id::DeviceId,
    260        queue_id: id::QueueId,
    261        data_source: QueueWriteDataSource,
    262        action: QueueWriteAction,
    263    },
    264    BufferMap {
    265        device_id: id::DeviceId,
    266        buffer_id: id::BufferId,
    267        mode: u32,
    268        offset: u64,
    269        size: u64,
    270    },
    271    BufferUnmap(id::DeviceId, id::BufferId, bool),
    272    QueueSubmit(
    273        id::DeviceId,
    274        id::QueueId,
    275        Cow<'a, [id::CommandBufferId]>,
    276        Cow<'a, [id::TextureId]>,
    277        Cow<'a, [crate::ExternalTextureSourceId]>,
    278    ),
    279    QueueOnSubmittedWorkDone(id::QueueId),
    280 
    281    CreateSwapChain {
    282        device_id: id::DeviceId,
    283        queue_id: id::QueueId,
    284        width: i32,
    285        height: i32,
    286        format: SurfaceFormat,
    287        buffer_ids: [id::BufferId; MAX_SWAPCHAIN_BUFFER_COUNT],
    288        remote_texture_owner_id: RemoteTextureOwnerId,
    289        use_shared_texture_in_swap_chain: bool,
    290    },
    291    SwapChainPresent {
    292        texture_id: id::TextureId,
    293        command_encoder_id: id::CommandEncoderId,
    294        command_buffer_id: id::CommandBufferId,
    295        remote_texture_id: RemoteTextureId,
    296        remote_texture_owner_id: RemoteTextureOwnerId,
    297    },
    298    SwapChainDrop {
    299        remote_texture_owner_id: RemoteTextureOwnerId,
    300        txn_type: RemoteTextureTxnType,
    301        txn_id: RemoteTextureTxnId,
    302    },
    303 
    304    DestroyBuffer(id::BufferId),
    305    DestroyTexture(id::TextureId),
    306    DestroyExternalTexture(id::ExternalTextureId),
    307    DestroyExternalTextureSource(crate::ExternalTextureSourceId),
    308    DestroyDevice(id::DeviceId),
    309 
    310    DropAdapter(id::AdapterId),
    311    DropDevice(id::DeviceId),
    312    DropQueue(id::QueueId),
    313    DropBuffer(id::BufferId),
    314    DropCommandEncoder(id::CommandEncoderId),
    315    DropRenderPassEncoder(id::RenderPassEncoderId),
    316    DropComputePassEncoder(id::ComputePassEncoderId),
    317    DropRenderBundleEncoder(id::RenderBundleEncoderId),
    318    DropCommandBuffer(id::CommandBufferId),
    319    DropRenderBundle(id::RenderBundleId),
    320    DropBindGroupLayout(id::BindGroupLayoutId),
    321    DropPipelineLayout(id::PipelineLayoutId),
    322    DropBindGroup(id::BindGroupId),
    323    DropShaderModule(id::ShaderModuleId),
    324    DropComputePipeline(id::ComputePipelineId),
    325    DropRenderPipeline(id::RenderPipelineId),
    326    DropTexture(id::TextureId),
    327    DropTextureView(id::TextureViewId),
    328    DropExternalTexture(id::ExternalTextureId),
    329    DropExternalTextureSource(crate::ExternalTextureSourceId),
    330    DropSampler(id::SamplerId),
    331    DropQuerySet(id::QuerySetId),
    332 }
    333 
    334 #[derive(serde::Serialize, serde::Deserialize)]
    335 enum DeviceAction<'a> {
    336    CreateBuffer {
    337        buffer_id: id::BufferId,
    338        desc: wgc::resource::BufferDescriptor<'a>,
    339        shmem_handle_index: usize,
    340    },
    341    CreateTexture(
    342        id::TextureId,
    343        wgc::resource::TextureDescriptor<'a>,
    344        Option<SwapChainId>,
    345    ),
    346    CreateExternalTexture(
    347        id::ExternalTextureId,
    348        crate::ExternalTextureDescriptor<wgc::Label<'a>>,
    349    ),
    350    CreateSampler(id::SamplerId, wgc::resource::SamplerDescriptor<'a>),
    351    CreateBindGroupLayout(
    352        id::BindGroupLayoutId,
    353        wgc::binding_model::BindGroupLayoutDescriptor<'a>,
    354    ),
    355    RenderPipelineGetBindGroupLayout(id::RenderPipelineId, u32, id::BindGroupLayoutId),
    356    ComputePipelineGetBindGroupLayout(id::ComputePipelineId, u32, id::BindGroupLayoutId),
    357    CreatePipelineLayout(
    358        id::PipelineLayoutId,
    359        wgc::binding_model::PipelineLayoutDescriptor<'a>,
    360    ),
    361    CreateBindGroup(id::BindGroupId, wgc::binding_model::BindGroupDescriptor<'a>),
    362    CreateShaderModule(id::ShaderModuleId, wgc::Label<'a>, Cow<'a, str>),
    363    CreateComputePipeline(
    364        id::ComputePipelineId,
    365        wgc::pipeline::ComputePipelineDescriptor<'a>,
    366        bool,
    367    ),
    368    CreateRenderPipeline(
    369        id::RenderPipelineId,
    370        wgc::pipeline::RenderPipelineDescriptor<'a>,
    371        bool,
    372    ),
    373    CreateRenderBundle(
    374        id::RenderBundleId,
    375        wgc::command::RenderBundleEncoder,
    376        wgc::command::RenderBundleDescriptor<'a>,
    377    ),
    378    CreateRenderBundleError(id::RenderBundleId, wgc::Label<'a>),
    379    CreateQuerySet(id::QuerySetId, wgc::resource::QuerySetDescriptor<'a>),
    380    CreateCommandEncoder(
    381        id::CommandEncoderId,
    382        wgt::CommandEncoderDescriptor<wgc::Label<'a>>,
    383    ),
    384    Error {
    385        message: String,
    386        r#type: wgt::error::ErrorType,
    387    },
    388    PushErrorScope(u8 /* dom::GPUErrorFilter */),
    389    PopErrorScope,
    390 }
    391 
    392 #[derive(serde::Serialize, serde::Deserialize)]
    393 enum QueueWriteAction {
    394    Buffer {
    395        dst: id::BufferId,
    396        offset: wgt::BufferAddress,
    397    },
    398    Texture {
    399        dst: wgt::TexelCopyTextureInfo<id::TextureId>,
    400        layout: wgt::TexelCopyBufferLayout,
    401        size: wgt::Extent3d,
    402    },
    403 }
    404 
    405 #[derive(serde::Serialize, serde::Deserialize)]
    406 enum TextureAction<'a> {
    407    CreateView(id::TextureViewId, wgc::resource::TextureViewDescriptor<'a>),
    408 }
    409 
    410 #[derive(serde::Serialize, serde::Deserialize)]
    411 struct PipelineError {
    412    is_validation_error: bool,
    413    error: String,
    414 }
    415 
    416 #[derive(serde::Serialize, serde::Deserialize)]
    417 pub struct ShaderModuleCompilationMessage {
    418    pub line_number: u64,
    419    pub line_pos: u64,
    420    pub utf16_offset: u64,
    421    pub utf16_length: u64,
    422    pub message: String,
    423 }
    424 
    425 #[derive(serde::Serialize, serde::Deserialize)]
    426 pub enum BufferMapResult<'a> {
    427    Success {
    428        is_writable: bool,
    429        offset: u64,
    430        size: u64,
    431    },
    432    Error(Cow<'a, str>),
    433 }
    434 
    435 #[derive(serde::Serialize, serde::Deserialize)]
    436 enum ServerMessage<'a> {
    437    RequestAdapterResponse(id::AdapterId, Option<AdapterInformation<Cow<'a, str>>>),
    438    RequestDeviceResponse(id::DeviceId, id::QueueId, Option<String>),
    439    PopErrorScopeResponse(
    440        id::DeviceId,
    441        u8, /* PopErrorScopeResultType */
    442        Cow<'a, str>,
    443    ),
    444    CreateRenderPipelineResponse {
    445        pipeline_id: id::RenderPipelineId,
    446        error: Option<PipelineError>,
    447    },
    448    CreateComputePipelineResponse {
    449        pipeline_id: id::ComputePipelineId,
    450        error: Option<PipelineError>,
    451    },
    452    CreateShaderModuleResponse(id::ShaderModuleId, Vec<ShaderModuleCompilationMessage>),
    453    BufferMapResponse(id::BufferId, BufferMapResult<'a>),
    454    QueueOnSubmittedWorkDoneResponse(id::QueueId),
    455 
    456    /// This message tells the client when we are done with swapchain readback buffers.
    457    /// Freeing a swapchain buffer too early may result in an ID resolution panic or
    458    /// an error submitting swapchain-related commands to the GPU.
    459    FreeSwapChainBufferIds([id::BufferId; MAX_SWAPCHAIN_BUFFER_COUNT]),
    460 }
    461 
    462 #[repr(C)]
    463 pub struct TexelCopyBufferLayout<'a> {
    464    pub offset: wgt::BufferAddress,
    465    pub bytes_per_row: Option<&'a u32>,
    466    pub rows_per_image: Option<&'a u32>,
    467 }
    468 
    469 impl<'a> TexelCopyBufferLayout<'a> {
    470    fn into_wgt(&self) -> wgt::TexelCopyBufferLayout {
    471        wgt::TexelCopyBufferLayout {
    472            offset: self.offset,
    473            bytes_per_row: self.bytes_per_row.map(|bpr| *bpr),
    474            rows_per_image: self.rows_per_image.map(|rpi| *rpi),
    475        }
    476    }
    477 }
    478 
    479 #[repr(C)]
    480 #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
    481 pub struct SwapChainId(pub u64);