Skip to documentation
SLOP

tiny.gui.paint.cpu.pixel

Reference tiny.gui paint cpu pixel

Defined in paint.cpu.

API (23)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callspaint.cpupixel
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callerspaint.cpu.pixelwritePackedpaint.cpu.pixel.ByteStorefill
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.cpu.pixelreadPackedpaint.cpu.pixel.ByteStoreload
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.cpu.pixelreadPackedpaint.cpu.pixel.ByteStoreloadVector
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.cpu.pixelwritePackedpaint.cpu.pixel.ByteStorestore
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerspaint.cpu.pixelwritePackedpaint.cpu.pixel.ByteStorestoreVector
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallspaint.cpu.pixelblendPackedpaint.cpu.pixeldiv255paint.cpu.pixelblendChannel
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.gui.src.paint.cpu.coveragerasterRunprivate sourcelib.gui.src.paint.cpu.coveragetexturedRunpaint.cpu.pixelblendSpanScalartest sourcelib.gui.src.paint.cpu.pixeltest: blendPacked with opaque source ...private sourcelib.gui.src.paint.cpu.spangradientRowsprivate sourcelib.gui.src.paint.cpu.spantexturedRowspaint.cpu.pixelblendChannelpaint.cpu.pixeldiv255paint.cpu.pixelblendPacked
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.gui.src.paint.cpu.pixeltest: selected packed spans match sca...private sourcelib.gui.src.paint.cpu.spanfillRowsprivate sourcelib.gui.src.paint.cpu.pixelblendPackedVectorpaint.cpu.pixelblendSpanScalarpaint.cpu.pixelblendSpan
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallspaint.cpu.pixelblendSpantest sourcelib.gui.src.paint.cpu.pixeltest: selected packed spans match sca...paint.cpu.pixelblendPackedpaint.cpu.pixelblendSpanScalar
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsprivate sourcelib.gui.src.paint.cpu.coveragecommandColorAtpaint.cpu.pixelcoverageAlphapaint.cpu.pixelcolorWithCoverage
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.gui.src.paint.cpu.coverageglyphColorAtprivate sourcelib.gui.src.paint.cpu.coverageimageColorAtprivate sourcelib.gui.src.paint.cpu.coverageshadowColorAtprivate sourcelib.gui.src.paint.cpu.coveragetexturedRunpaint.cpu.pixelcolorWithCoverage+2 morepaint.cpu.pixelcoverageAlpha
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.gui.src.paint.cpu.coverageglyphColorAtprivate sourcelib.gui.src.paint.cpu.coverageimageColorAtprivate sourcelib.gui.src.paint.cpu.coveragetexturedRunpaint.cpu.pixelblendChannelpaint.cpu.pixelblendPacked+2 morepaint.cpu.pixeldiv255
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.gui.src.paint.cpu.pixeltest: blendPacked with opaque source ...test sourcelib.gui.src.paint.cpu.pixeltest: packed byte layout round-trips ...private sourcelib.gui.src.paint.cpu.spanfillRowsprivate sourcelib.gui.src.paint.cpu.spangradientRowsprivate sourcelib.gui.src.paint.cpu.spanrenderRegion+5 morepaint.cpu.pixelpackRgba
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callspaint.cpu.pixel.ByteStoreloadpaint.cpu.pixel.ByteStoreloadVectortest sourcelib.gui.src.paint.cpu.pixeltest: selected packed spans match sca...test sourcelib.gui.src.paint.cpu.rendertest: renderCommandsRegionWithImages ...test sourcelib.gui.src.paint.cpu.rendertest: renderCommands paints clipped a...paint.cpu.pixelreadPacked
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.gui.src.paint.cpu.coveragetexturedRuntest sourcelib.gui.src.paint.cpu.pixeltest: packed byte layout round-trips ...private sourcelib.gui.src.paint.cpu.sampleimageSampleKnownprivate sourcelib.gui.src.paint.executorexpectShadowPixelsTintedtest sourcelib.gui.src.paint.imagetest: paint image processor shadow im...paint.cpu.pixelunpackRgba
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callspaint.cpu.pixel.ByteStorefillpaint.cpu.pixel.ByteStorestorepaint.cpu.pixel.ByteStorestoreVectortest sourcelib.gui.src.paint.cpu.pixeltest: selected packed spans match sca...paintrgba8FromPackedpaint.cpu.pixelwritePacked
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/gui/src/paint/cpu/pixel.zig

zig
const std = @import("std");const simd = @import("simd");const gui = @import("../../root.zig");const Color = gui.model.UiColor;const PackedVector = simd.ScalableTag(u32);const span_vector_lanes = PackedVector.lane_count;const span_vector_threshold = span_vector_lanes * 2;pub fn packRgba(color: Color) u32 {    return @as(u32, color.r) |        (@as(u32, color.g) << 8) |        (@as(u32, color.b) << 16) |        (@as(u32, color.a) << 24);}pub fn unpackRgba(pixel: u32) Color {    return .{        .r = @truncate(pixel),        .g = @truncate(pixel >> 8),        .b = @truncate(pixel >> 16),        .a = @truncate(pixel >> 24),    };}pub fn readPacked(rgba8: []const u8, index: usize) u32 {    return std.mem.readInt(u32, rgba8[index * 4 ..][0..4], .little);}pub fn writePacked(rgba8: []u8, index: usize, pixel: u32) void {    std.mem.writeInt(u32, rgba8[index * 4 ..][0..4], pixel, .little);}pub fn blendPacked(dst: u32, src: Color) u32 {    if (src.a == 0) return dst;    const inv = 255 - @as(u32, src.a);    const dst_r = dst & 0xff;    const dst_g = (dst >> 8) & 0xff;    const dst_b = (dst >> 16) & 0xff;    const dst_a = (dst >> 24) & 0xff;    const r = blendChannel(src.r, src.a, dst_r, inv);    const g = blendChannel(src.g, src.a, dst_g, inv);    const b = blendChannel(src.b, src.a, dst_b, inv);    const a = @as(u32, src.a) + div255(dst_a * inv);    return r | (g << 8) | (b << 16) | (a << 24);}pub fn blendSpanScalar(    comptime Store: type,    store: Store,    start: usize,    count: usize,    src: Color,) void {    var index = start;    const end = start + count;    while (index < end) : (index += 1) {        store.store(index, blendPacked(store.load(index), src));    }}pub fn blendSpan(    comptime Store: type,    store: Store,    start: usize,    count: usize,    src: Color,) void {    if (src.a == 0) return;    var index = start;    const end = start + count;    if (comptime span_vector_lanes > 1) {        if (count >= span_vector_threshold) {            const vector_end = end - count % span_vector_lanes;            while (index < vector_end) : (index += span_vector_lanes) {                const dst = store.loadVector(PackedVector, index);                store.storeVector(                    PackedVector,                    index,                    blendPackedVector(PackedVector, dst, src),                );            }        }    }    blendSpanScalar(Store, store, index, end - index, src);}pub fn blendChannel(src_value: u8, src_alpha: u8, dst_value: u32, inv_alpha: u32) u32 {    return div255(@as(u32, src_value) * @as(u32, src_alpha) + dst_value * inv_alpha);}pub fn div255(value: u32) u32 {    return (value + 127) / 255;}fn blendPackedVector(    comptime D: type,    dst: D.Vector,    src: Color,) D.Vector {    const byte_mask = simd.set(D, 0xff);    const alpha = @as(u32, src.a);    const inv = simd.set(D, 255 - alpha);    const dst_r = simd.bitAnd(D, dst, byte_mask);    const dst_g = simd.bitAnd(D, shiftRight(D, dst, 8), byte_mask);    const dst_b = simd.bitAnd(D, shiftRight(D, dst, 16), byte_mask);    const dst_a = shiftRight(D, dst, 24);    const r = blendChannelVector(D, dst_r, src.r, alpha, inv);    const g = blendChannelVector(D, dst_g, src.g, alpha, inv);    const b = blendChannelVector(D, dst_b, src.b, alpha, inv);    const a = simd.add(        D,        simd.set(D, alpha),        div255Vector(D, simd.mul(D, dst_a, inv)),    );    return simd.bitOr(        D,        simd.or3(            D,            r,            shiftLeft(D, g, 8),            shiftLeft(D, b, 16),        ),        shiftLeft(D, a, 24),    );}fn blendChannelVector(    comptime D: type,    dst: D.Vector,    src: u8,    alpha: u32,    inv: D.Vector,) D.Vector {    return div255Vector(        D,        simd.add(            D,            simd.set(D, @as(u32, src) * alpha),            simd.mul(D, dst, inv),        ),    );}fn div255Vector(comptime D: type, value: D.Vector) D.Vector {    const rounded = simd.add(D, value, simd.set(D, 128));    return shiftRight(D, simd.add(D, rounded, shiftRight(D, rounded, 8)), 8);}fn shiftLeft(comptime D: type, value: D.Vector, comptime amount: u5) D.Vector {    const Shift = @Vector(D.lane_count, u5);    return value << @as(Shift, @splat(amount));}fn shiftRight(comptime D: type, value: D.Vector, comptime amount: u5) D.Vector {    const Shift = @Vector(D.lane_count, u5);    return value >> @as(Shift, @splat(amount));}pub fn coverageAlpha(alpha: u8, coverage: u32) u8 {    return @intCast((@as(u32, alpha) * coverage + 2) / 4);}pub fn colorWithCoverage(color: Color, coverage: u32) Color {    return .{        .r = color.r,        .g = color.g,        .b = color.b,        .a = coverageAlpha(color.a, coverage),    };}pub const ByteStore = struct {    bytes: []u8,    pub inline fn load(self: ByteStore, index: usize) u32 {        return readPacked(self.bytes, index);    }    pub inline fn store(self: ByteStore, index: usize, value: u32) void {        writePacked(self.bytes, index, value);    }    pub inline fn fill(self: ByteStore, start: usize, count: usize, value: u32) void {        var index = start;        const end = start + count;        while (index < end) : (index += 1) writePacked(self.bytes, index, value);    }    pub inline fn loadVector(self: ByteStore, comptime D: type, index: usize) D.Vector {        var result: D.Vector = undefined;        inline for (0..D.lane_count) |lane_index| {            result[lane_index] = readPacked(self.bytes, index + lane_index);        }        return result;    }    pub inline fn storeVector(        self: ByteStore,        comptime D: type,        index: usize,        value: D.Vector,    ) void {        inline for (0..D.lane_count) |lane_index| {            writePacked(self.bytes, index + lane_index, value[lane_index]);        }    }};pub const WordStore = struct {    words: []u32,    pub inline fn load(self: WordStore, index: usize) u32 {        return self.words[index];    }    pub inline fn store(self: WordStore, index: usize, value: u32) void {        self.words[index] = value;    }    pub inline fn fill(self: WordStore, start: usize, count: usize, value: u32) void {        @memset(self.words[start .. start + count], value);    }    pub inline fn loadVector(self: WordStore, comptime D: type, index: usize) D.Vector {        return simd.load(D, self.words[index..]);    }    pub inline fn storeVector(        self: WordStore,        comptime D: type,        index: usize,        value: D.Vector,    ) void {        simd.store(D, value, self.words[index..]);    }};test "packed byte layout round-trips through both stores" {    const color = Color{ .r = 12, .g = 34, .b = 56, .a = 78 };    const pixel = packRgba(color);    var bytes = @as([8]u8, @splat(0));    const byte_store = ByteStore{ .bytes = bytes[0..] };    byte_store.store(1, pixel);    try std.testing.expectEqual(pixel, byte_store.load(1));    try std.testing.expectEqual(@as(u8, 12), bytes[4]);    try std.testing.expectEqual(@as(u8, 78), bytes[7]);    var words = @as([2]u32, @splat(0));    const word_store = WordStore{ .words = words[0..] };    word_store.store(1, pixel);    try std.testing.expectEqual(pixel, word_store.load(1));    try std.testing.expectEqual(color, unpackRgba(word_store.load(1)));}test "coverageAlpha at full coverage preserves alpha exactly" {    var alpha: u32 = 0;    while (alpha <= 255) : (alpha += 1) {        try std.testing.expectEqual(@as(u8, @intCast(alpha)), coverageAlpha(@intCast(alpha), 4));    }}test "blendPacked with opaque source replaces destination" {    const src = Color{ .r = 10, .g = 20, .b = 30, .a = 255 };    try std.testing.expectEqual(packRgba(src), blendPacked(0xdead_beef, src));}test "vector div255 is bit-exact over packed blend range" {    var value: u32 = 0;    while (value <= 65_025) : (value += 1) {        const vector = div255Vector(PackedVector, simd.set(PackedVector, value));        const lanes: [PackedVector.lane_count]u32 = vector;        try std.testing.expectEqual(div255(value), lanes[0]);    }}test "selected packed spans match scalar words and unaligned bytes" {    const pixel_count = span_vector_lanes * 3 + 5;    var initial: [pixel_count]u32 = undefined;    var expected: [pixel_count]u32 = undefined;    var words: [pixel_count]u32 = undefined;    var byte_storage: [pixel_count * 4 + 1]u8 = undefined;    const bytes = byte_storage[1..];    for (&initial, 0..) |*value, index| {        value.* = @as(u32, @truncate(index *% 0x9e37_79b9)) ^ 0xa5c3_71e9;    }    var alpha: u16 = 0;    while (alpha <= 255) : (alpha += 1) {        const src = Color{            .r = @truncate(alpha *% 29 + 3),            .g = @truncate(alpha *% 73 + 5),            .b = @truncate(alpha *% 151 + 7),            .a = @intCast(alpha),        };        var offset: usize = 0;        while (offset < span_vector_lanes + 1) : (offset += 1) {            var count: usize = 0;            while (count <= pixel_count - offset) : (count += 1) {                @memcpy(&expected, &initial);                @memcpy(&words, &initial);                for (initial, 0..) |value, index| writePacked(bytes, index, value);                blendSpanScalar(                    WordStore,                    .{ .words = &expected },                    offset,                    count,                    src,                );                blendSpan(WordStore, .{ .words = &words }, offset, count, src);                blendSpan(ByteStore, .{ .bytes = bytes }, offset, count, src);                try std.testing.expectEqualSlices(u32, &expected, &words);                for (expected, 0..) |value, index| {                    try std.testing.expectEqual(value, readPacked(bytes, index));                }            }        }    }}

Source: lib/gui/src/paint/cpu/root.zig:4

zig
pub const pixel = render.pixel;

Complete caller list for paint.cpu.pixel.coverageAlpha

7 direct callers.

Complete caller list for paint.cpu.pixel.div255

7 direct callers.

Complete caller list for paint.cpu.pixel.packRgba

10 direct callers.

Audit

Definitions24
Public names26
Members2
Version26.7.0
Revisiondaab053ee433