Expand description
C FFI bindings for skia-rs.
This crate provides C-compatible bindings for use from other languages. It exposes a C API that mirrors the Skia C API for drop-in compatibility.
§Safety
All FFI functions are inherently unsafe. Callers must ensure:
- Pointers are valid and non-null (unless explicitly documented otherwise)
- Proper lifetime management (using the appropriate
_unreffunctions) - Thread safety requirements are followed (see below)
§Reference Counting
Objects follow Skia’s reference counting model:
- Objects are created with a reference count of 1
sk_*_ref()increments the reference countsk_*_unref()decrements the reference count and frees when it reaches 0- Use
sk_refcnt_get_count()to query the current count
Reference counting operations (ref/unref) are thread-safe and use
atomic operations internally.
§Thread Safety
skia-rs follows Skia’s threading model. Understanding thread safety is critical for correct usage in multi-threaded applications.
§Thread Safety Categories
| Category | Description | Examples |
|---|---|---|
| Thread-Safe | Can be accessed from any thread concurrently | sk_*_ref(), sk_*_unref(), sk_refcnt_*() |
| Thread-Compatible | Safe if each instance accessed by one thread | Most objects |
| Main-Thread-Only | Must only be used from main/UI thread | GPU contexts |
§Object-Specific Thread Safety
§Reference Counting (Thread-Safe)
// These operations are always thread-safe:
sk_surface_ref(surface); // Atomic increment
sk_surface_unref(surface); // Atomic decrement
sk_refcnt_get_count(ptr); // Atomic read
sk_refcnt_is_unique(ptr); // Atomic read§Immutable Objects (Thread-Safe after creation)
Once created, these objects are safe to read from multiple threads:
sk_path_t(after building is complete)sk_matrix_t(value type, copied on use)
§Mutable Objects (Thread-Compatible)
These must not be accessed concurrently from multiple threads:
sk_surface_t- Drawing operations are not thread-safesk_paint_t- Setters/getters must be externally synchronizedsk_pathbuilder_t- Building operations must be single-threaded
§GPU Objects (Special Restrictions)
GPU-related objects have additional constraints:
- Must be created/destroyed on the same thread as the GPU context
- Drawing to GPU surfaces must occur on the GPU context thread
- Flush operations must be called from the same thread
§Safe Patterns
§Pattern 1: Object-per-Thread
// Each thread creates its own objects
void* thread_func(void* arg) {
sk_surface_t* surface = sk_surface_new_raster(800, 600);
sk_paint_t* paint = sk_paint_new();
// ... use exclusively in this thread ...
sk_paint_unref(paint);
sk_surface_unref(surface);
return NULL;
}§Pattern 2: Shared Immutable Data
// Build path on one thread, share read-only
sk_path_t* shared_path; // Global
void init() {
sk_pathbuilder_t* builder = sk_pathbuilder_new();
sk_pathbuilder_add_circle(builder, 100, 100, 50);
shared_path = sk_pathbuilder_detach(builder);
sk_pathbuilder_unref(builder);
}
void* render_thread(void* arg) {
// Safe: path is immutable after creation
sk_rect_t bounds;
sk_path_get_bounds(shared_path, &bounds);
sk_path_contains(shared_path, 100, 100);
return NULL;
}§Pattern 3: Reference Counted Sharing
// Safe: ref counting is atomic
sk_paint_t* paint = sk_paint_new();
void share_to_thread(sk_paint_t* p) {
sk_paint_ref(p); // Thread-safe increment
// Pass to another thread...
}
void* other_thread(void* paint_ptr) {
sk_paint_t* p = (sk_paint_t*)paint_ptr;
// Clone for thread-local modifications
sk_paint_t* local = sk_paint_clone(p);
sk_paint_unref(p); // Thread-safe decrement
// ... use local exclusively ...
sk_paint_unref(local);
return NULL;
}§Unsafe Patterns (AVOID)
// UNSAFE: Concurrent mutation
sk_paint_t* shared_paint;
void* thread1(void* arg) {
sk_paint_set_color(shared_paint, 0xFFFF0000); // DATA RACE!
return NULL;
}
void* thread2(void* arg) {
sk_paint_set_color(shared_paint, 0xFF0000FF); // DATA RACE!
return NULL;
}
// UNSAFE: Drawing while modifying
void* draw_thread(void* arg) {
sk_surface_draw_rect(surface, &rect, paint); // DATA RACE with modifier!
return NULL;
}
void* modify_thread(void* arg) {
sk_paint_set_stroke_width(paint, 5.0); // DATA RACE with drawer!
return NULL;
}§Error Checking
After any FFI call, check for panics:
sk_surface_t* surface = sk_surface_new_raster(800, 600);
if (sk_last_call_panicked()) {
// Handle error - surface may be NULL
fprintf(stderr, "Surface creation panicked\n");
}§Summary Table
| Operation | Thread-Safe | Notes |
|---|---|---|
sk_*_new() | Yes | Returns unique object |
sk_*_ref() | Yes | Atomic increment |
sk_*_unref() | Yes | Atomic decrement |
sk_*_clone() | Yes* | Input must not be concurrently modified |
sk_*_get_*() | No | Requires external synchronization |
sk_*_set_*() | No | Requires external synchronization |
sk_surface_draw_*() | No | Single-threaded drawing only |
sk_path_contains() | Yes* | After path is immutable |
sk_pathbuilder_*() | No | Single-threaded building |
§Panic Safety
All FFI functions catch panics at the boundary to prevent unwinding
into C code. Functions that panic will return a default/null value
and set an error flag. Use sk_last_call_panicked() to check.
Modules§
- abi
- Binary ABI Compatibility Layer
Structs§
- RefCounted
- Reference counted wrapper for FFI objects.
- sk_
imageinfo_ t - C-compatible image info structure.
- sk_
ipoint_ t - C-compatible integer point structure.
- sk_
irect_ t - C-compatible integer rectangle structure.
- sk_
isize_ t - C-compatible integer size structure.
- sk_
matrix_ t - C-compatible matrix structure.
- sk_
point_ t - C-compatible point structure.
- sk_
rect_ t - C-compatible rectangle structure.
- sk_
size_ t - C-compatible size structure.
Functions§
- sk_
is_ ⚠available - Check if the library is available.
- sk_
last_ call_ panicked - Check if the last FFI call panicked.
- sk_
matrix_ ⚠concat - Concatenate two matrices.
- sk_
matrix_ ⚠map_ point - Map a point through a matrix.
- sk_
matrix_ ⚠set_ identity - Set matrix to identity.
- sk_
matrix_ ⚠set_ rotate - Set matrix to rotate (degrees).
- sk_
matrix_ ⚠set_ scale - Set matrix to scale.
- sk_
matrix_ ⚠set_ translate - Set matrix to translate.
- sk_
paint_ ⚠clone - Clone a paint.
- sk_
paint_ ⚠delete - Decrement the reference count of a paint (alias for unref).
- sk_
paint_ ⚠get_ color - Get the paint color.
- sk_
paint_ ⚠get_ refcnt - Get the reference count of a paint.
- sk_
paint_ ⚠get_ stroke_ width - Get the stroke width.
- sk_
paint_ ⚠is_ antialias - Check if anti-alias is enabled.
- sk_
paint_ ⚠new - Create a new paint.
- sk_
paint_ ⚠ref - Increment the reference count of a paint.
- sk_
paint_ ⚠set_ antialias - Set anti-alias.
- sk_
paint_ ⚠set_ color - Set the paint color.
- sk_
paint_ ⚠set_ stroke_ width - Set the stroke width.
- sk_
paint_ ⚠set_ style - Set the paint style.
- sk_
paint_ ⚠unref - Decrement the reference count of a paint.
- sk_
path_ ⚠clone - Clone a path.
- sk_
path_ ⚠contains - Check if path contains a point.
- sk_
path_ ⚠delete - Decrement the reference count of a path (alias for unref).
- sk_
path_ ⚠get_ bounds - Get the path bounds.
- sk_
path_ ⚠get_ filltype - Get the fill type.
- sk_
path_ ⚠get_ refcnt - Get the reference count of a path.
- sk_
path_ ⚠is_ empty - Check if path is empty.
- sk_
path_ ⚠new - Create a new path.
- sk_
path_ ⚠ref - Increment the reference count of a path.
- sk_
path_ ⚠set_ filltype - Set the fill type.
- sk_
path_ ⚠unref - Decrement the reference count of a path.
- sk_
pathbuilder_ ⚠add_ circle - Add a circle.
- sk_
pathbuilder_ ⚠add_ oval - Add an oval.
- sk_
pathbuilder_ ⚠add_ rect - Add a rectangle.
- sk_
pathbuilder_ ⚠close - Close the path.
- sk_
pathbuilder_ ⚠cubic_ to - Cubic bezier to a point.
- sk_
pathbuilder_ ⚠delete - Decrement the reference count of a path builder (alias for unref).
- sk_
pathbuilder_ ⚠detach - Build the path and reset the builder.
- sk_
pathbuilder_ ⚠line_ to - Line to a point.
- sk_
pathbuilder_ ⚠move_ to - Move to a point.
- sk_
pathbuilder_ ⚠new - Create a new path builder.
- sk_
pathbuilder_ ⚠quad_ to - Quadratic bezier to a point.
- sk_
pathbuilder_ ⚠ref - Increment the reference count of a path builder.
- sk_
pathbuilder_ ⚠snapshot - Build the path without resetting the builder.
- sk_
pathbuilder_ ⚠unref - Decrement the reference count of a path builder.
- sk_
refcnt_ ⚠get_ count - Get the reference count of an object.
- sk_
refcnt_ ⚠is_ unique - Check if an object has only one reference (is unique).
- sk_
surface_ ⚠clear - Clear a surface with a color.
- sk_
surface_ ⚠draw_ circle - Draw a circle on a surface.
- sk_
surface_ ⚠draw_ line - Draw a line on a surface.
- sk_
surface_ ⚠draw_ path - Draw a path on a surface.
- sk_
surface_ ⚠draw_ rect - Draw a rect on a surface.
- sk_
surface_ ⚠get_ height - Get the height of a surface.
- sk_
surface_ ⚠get_ refcnt - Get the reference count of a surface.
- sk_
surface_ ⚠get_ width - Get the width of a surface.
- sk_
surface_ ⚠is_ unique - Check if the surface has only one reference.
- sk_
surface_ ⚠new_ raster - Create a new raster surface.
- sk_
surface_ ⚠new_ raster_ with_ info - Create a raster surface with specific image info.
- sk_
surface_ ⚠peek_ pixels - Get the pixel data from a surface.
- sk_
surface_ ⚠ref - Increment the reference count of a surface.
- sk_
surface_ ⚠unref - Decrement the reference count of a surface.
- sk_
version ⚠ - Get the library version.
Type Aliases§
- sk_
color_ t - C-compatible color (ARGB).
- sk_
paint_ t - Reference counted paint type.
- sk_
path_ t - Reference counted path type.
- sk_
pathbuilder_ t - Reference counted path builder type.
- sk_
refcnt_ t - Opaque reference counted object type.
- sk_
surface_ t - Reference counted surface type.