font/sprite: replace pixman with z2d, extend Box coverage

More complete coverage of the Symbols For Legacy Computing block,
including characters from Unicode 16.0.

Pixman and the web canvas impl for Canvas have been removed in favor of
z2d for drawing, since it has a nicer API with more powerful methods,
and is in Zig with no specific platform optimizations so should compile
to wasm no problem.
This commit is contained in:
Qwerasd
2024-10-09 19:31:13 -04:00
parent c86b5f44ce
commit d38d0f30c4
115 changed files with 1029 additions and 68180 deletions

View File

@ -1007,10 +1007,6 @@ fn addDeps(
.optimize = optimize,
});
const opengl_dep = b.dependency("opengl", .{});
const pixman_dep = b.dependency("pixman", .{
.target = target,
.optimize = optimize,
});
const sentry_dep = b.dependency("sentry", .{
.target = target,
.optimize = optimize,
@ -1044,6 +1040,7 @@ fn addDeps(
.target = target,
.optimize = optimize,
});
const z2d_dep = b.dependency("z2d", .{});
// Wasm we do manually since it is such a different build.
if (step.rootModuleTarget().cpu.arch == .wasm32) {
@ -1125,12 +1122,16 @@ fn addDeps(
step.root_module.addImport("spirv_cross", spirv_cross_dep.module("spirv_cross"));
step.root_module.addImport("xev", libxev_dep.module("xev"));
step.root_module.addImport("opengl", opengl_dep.module("opengl"));
step.root_module.addImport("pixman", pixman_dep.module("pixman"));
step.root_module.addImport("sentry", sentry_dep.module("sentry"));
step.root_module.addImport("ziglyph", ziglyph_dep.module("ziglyph"));
step.root_module.addImport("vaxis", vaxis_dep.module("vaxis"));
step.root_module.addImport("wuffs", wuffs_dep.module("wuffs"));
step.root_module.addImport("zf", zf_dep.module("zf"));
step.root_module.addImport("z2d", b.addModule("z2d", .{
.root_source_file = z2d_dep.path("src/z2d.zig"),
.target = target,
.optimize = optimize,
}));
// Mac Stuff
if (step.rootModuleTarget().isDarwin()) {
@ -1196,7 +1197,6 @@ fn addDeps(
step.linkSystemLibrary2("freetype2", dynamic_link_opts);
step.linkSystemLibrary2("libpng", dynamic_link_opts);
step.linkSystemLibrary2("oniguruma", dynamic_link_opts);
step.linkSystemLibrary2("pixman-1", dynamic_link_opts);
step.linkSystemLibrary2("zlib", dynamic_link_opts);
if (config.font_backend.hasFontconfig()) {
@ -1222,10 +1222,6 @@ fn addDeps(
step.linkLibrary(freetype_dep.artifact("freetype"));
try static_libs.append(freetype_dep.artifact("freetype").getEmittedBin());
// Pixman
step.linkLibrary(pixman_dep.artifact("pixman"));
try static_libs.append(pixman_dep.artifact("pixman").getEmittedBin());
// Harfbuzz
if (config.font_backend.hasHarfbuzz()) {
step.linkLibrary(harfbuzz_dep.artifact("harfbuzz"));

View File

@ -36,7 +36,6 @@
.macos = .{ .path = "./pkg/macos" },
.oniguruma = .{ .path = "./pkg/oniguruma" },
.opengl = .{ .path = "./pkg/opengl" },
.pixman = .{ .path = "./pkg/pixman" },
.sentry = .{ .path = "./pkg/sentry" },
.simdutf = .{ .path = "./pkg/simdutf" },
.utfcpp = .{ .path = "./pkg/utfcpp" },
@ -61,5 +60,9 @@
.url = "git+https://github.com/natecraddock/zf.git?ref=main#bb27a917c3513785c6a91f0b1c10002a5029cacc",
.hash = "1220a74107c7f153a2f809e41c7fa7e8dbf75c91043e39fad998247804e5edac2cc8",
},
.z2d = .{
.url = "git+https://github.com/vancluever/z2d?ref=main#285a796eb9c25a2389f087d008f0e60faf0b8eda",
.hash = "12206445aa45bcf0170ace371905f705aec1d8d4f61e7dd77839c6621b8c407680a5",
},
},
}

View File

@ -41,7 +41,6 @@
libXi,
libXinerama,
libXrandr,
pixman,
zlib,
alejandra,
pandoc,
@ -61,7 +60,6 @@
harfbuzz
libpng
oniguruma
pixman
zlib
libX11
@ -126,7 +124,6 @@ in
harfbuzz
libpng
oniguruma
pixman
zlib
libX11

View File

@ -7,7 +7,6 @@
freetype,
harfbuzz,
libpng,
pixman,
zlib,
libGL,
libX11,
@ -133,7 +132,6 @@ in
freetype
harfbuzz
libpng
pixman
zlib
libX11

View File

@ -1,122 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const module = b.addModule("pixman", .{ .root_source_file = b.path("main.zig") });
const upstream = b.dependency("pixman", .{});
const lib = b.addStaticLibrary(.{
.name = "pixman",
.target = target,
.optimize = optimize,
});
lib.linkLibC();
if (target.result.os.tag != .windows) {
lib.linkSystemLibrary("pthread");
}
if (target.result.isDarwin()) {
const apple_sdk = @import("apple_sdk");
try apple_sdk.addPaths(b, &lib.root_module);
}
lib.addIncludePath(upstream.path(""));
lib.addIncludePath(b.path(""));
module.addIncludePath(upstream.path("pixman"));
module.addIncludePath(b.path(""));
var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit();
try flags.appendSlice(&.{
"-DHAVE_SIGACTION=1",
"-DHAVE_ALARM=1",
"-DHAVE_MPROTECT=1",
"-DHAVE_GETPAGESIZE=1",
"-DHAVE_MMAP=1",
"-DHAVE_GETISAX=1",
"-DHAVE_GETTIMEOFDAY=1",
"-DHAVE_FENV_H=1",
"-DHAVE_SYS_MMAN_H=1",
"-DHAVE_UNISTD_H=1",
"-DSIZEOF_LONG=8",
"-DPACKAGE=foo",
// There is ubsan
"-fno-sanitize=undefined",
"-fno-sanitize-trap=undefined",
});
if (!(target.result.os.tag == .windows)) {
try flags.appendSlice(&.{
"-DHAVE_PTHREADS=1",
"-DHAVE_POSIX_MEMALIGN=1",
});
}
lib.addCSourceFiles(.{
.root = upstream.path(""),
.files = srcs,
.flags = flags.items,
});
lib.installHeader(b.path("pixman-version.h"), "pixman-version.h");
lib.installHeadersDirectory(
upstream.path("pixman"),
"",
.{ .include_extensions = &.{".h"} },
);
b.installArtifact(lib);
if (target.query.isNative()) {
const test_exe = b.addTest(.{
.name = "test",
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
});
test_exe.linkLibrary(lib);
var it = module.import_table.iterator();
while (it.next()) |entry| test_exe.root_module.addImport(entry.key_ptr.*, entry.value_ptr.*);
const tests_run = b.addRunArtifact(test_exe);
const test_step = b.step("test", "Run tests");
test_step.dependOn(&tests_run.step);
}
}
const srcs: []const []const u8 = &.{
"pixman/pixman.c",
"pixman/pixman-access.c",
"pixman/pixman-access-accessors.c",
"pixman/pixman-bits-image.c",
"pixman/pixman-combine32.c",
"pixman/pixman-combine-float.c",
"pixman/pixman-conical-gradient.c",
"pixman/pixman-filter.c",
"pixman/pixman-x86.c",
"pixman/pixman-mips.c",
"pixman/pixman-arm.c",
"pixman/pixman-ppc.c",
"pixman/pixman-edge.c",
"pixman/pixman-edge-accessors.c",
"pixman/pixman-fast-path.c",
"pixman/pixman-glyph.c",
"pixman/pixman-general.c",
"pixman/pixman-gradient-walker.c",
"pixman/pixman-image.c",
"pixman/pixman-implementation.c",
"pixman/pixman-linear-gradient.c",
"pixman/pixman-matrix.c",
"pixman/pixman-noop.c",
"pixman/pixman-radial-gradient.c",
"pixman/pixman-region16.c",
"pixman/pixman-region32.c",
"pixman/pixman-solid-fill.c",
//"pixman/pixman-timer.c",
"pixman/pixman-trap.c",
"pixman/pixman-utils.c",
};

View File

@ -1,13 +0,0 @@
.{
.name = "pixman",
.version = "0.42.2",
.paths = .{""},
.dependencies = .{
.pixman = .{
.url = "https://deps.files.ghostty.dev/pixman-pixman-0.42.2.tar.gz",
.hash = "12209b9206f9a5d31ccd9a2312cc72cb9dfc3e034aee1883c549dc1d753fae457230",
},
.apple_sdk = .{ .path = "../apple-sdk" },
},
}

View File

@ -1,3 +0,0 @@
pub const c = @cImport({
@cInclude("pixman.h");
});

View File

@ -1,4 +0,0 @@
pub const Error = error{
// Pixman doesn't really have errors so we just have a single error.
PixmanFailure,
};

View File

@ -1,118 +0,0 @@
const std = @import("std");
const c = @import("c.zig").c;
const pixman = @import("main.zig");
pub const FormatCode = enum(c_uint) {
// 128bpp formats
rgba_float = c.PIXMAN_FORMAT_BYTE(128, c.PIXMAN_TYPE_RGBA_FLOAT, 32, 32, 32, 32),
// 96bpp formats
rgb_float = c.PIXMAN_FORMAT_BYTE(96, c.PIXMAN_TYPE_RGBA_FLOAT, 0, 32, 32, 32),
// 32bpp formats
a8r8g8b8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB, 8, 8, 8, 8),
x8r8g8b8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
a8b8g8r8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ABGR, 8, 8, 8, 8),
x8b8g8r8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
b8g8r8a8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_BGRA, 8, 8, 8, 8),
b8g8r8x8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_BGRA, 0, 8, 8, 8),
r8g8b8a8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_RGBA, 8, 8, 8, 8),
r8g8b8x8 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_RGBA, 0, 8, 8, 8),
x14r6g6b6 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB, 0, 6, 6, 6),
x2r10g10b10 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB, 0, 10, 10, 10),
a2r10g10b10 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB, 2, 10, 10, 10),
x2b10g10r10 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ABGR, 0, 10, 10, 10),
a2b10g10r10 = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ABGR, 2, 10, 10, 10),
// sRGB formats
a8r8g8b8_sRGB = c.PIXMAN_FORMAT(32, c.PIXMAN_TYPE_ARGB_SRGB, 8, 8, 8, 8),
r8g8b8_sRGB = c.PIXMAN_FORMAT(24, c.PIXMAN_TYPE_ARGB_SRGB, 0, 8, 8, 8),
// 24bpp formats
r8g8b8 = c.PIXMAN_FORMAT(24, c.PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
b8g8r8 = c.PIXMAN_FORMAT(24, c.PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
// 16bpp formats
r5g6b5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ARGB, 0, 5, 6, 5),
b5g6r5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ABGR, 0, 5, 6, 5),
a1r5g5b5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ARGB, 1, 5, 5, 5),
x1r5g5b5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ARGB, 0, 5, 5, 5),
a1b5g5r5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ABGR, 1, 5, 5, 5),
x1b5g5r5 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ABGR, 0, 5, 5, 5),
a4r4g4b4 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ARGB, 4, 4, 4, 4),
x4r4g4b4 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ARGB, 0, 4, 4, 4),
a4b4g4r4 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ABGR, 4, 4, 4, 4),
x4b4g4r4 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_ABGR, 0, 4, 4, 4),
// 8bpp formats
a8 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_A, 8, 0, 0, 0),
r3g3b2 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_ARGB, 0, 3, 3, 2),
b2g3r3 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_ABGR, 0, 3, 3, 2),
a2r2g2b2 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_ARGB, 2, 2, 2, 2),
a2b2g2r2 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_ABGR, 2, 2, 2, 2),
c8 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_COLOR, 0, 0, 0, 0),
g8 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_GRAY, 0, 0, 0, 0),
x4a4 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_A, 4, 0, 0, 0),
// c8/g8 equivalent
// x4c4 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_COLOR, 0, 0, 0, 0),
// x4g4 = c.PIXMAN_FORMAT(8, c.PIXMAN_TYPE_GRAY, 0, 0, 0, 0),
// 4bpp formats
a4 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_A, 4, 0, 0, 0),
r1g2b1 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_ARGB, 0, 1, 2, 1),
b1g2r1 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_ABGR, 0, 1, 2, 1),
a1r1g1b1 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_ARGB, 1, 1, 1, 1),
a1b1g1r1 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_ABGR, 1, 1, 1, 1),
c4 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_COLOR, 0, 0, 0, 0),
g4 = c.PIXMAN_FORMAT(4, c.PIXMAN_TYPE_GRAY, 0, 0, 0, 0),
// 1bpp formats
a1 = c.PIXMAN_FORMAT(1, c.PIXMAN_TYPE_A, 1, 0, 0, 0),
g1 = c.PIXMAN_FORMAT(1, c.PIXMAN_TYPE_GRAY, 0, 0, 0, 0),
// YUV formats
yuy2 = c.PIXMAN_FORMAT(16, c.PIXMAN_TYPE_YUY2, 0, 0, 0, 0),
yv12 = c.PIXMAN_FORMAT(12, c.PIXMAN_TYPE_YV12, 0, 0, 0, 0),
pub inline fn bpp(self: FormatCode) u32 {
return self.reshift(24, 8);
}
/// Calculates a valid stride for the bpp and width. Based on Cairo.
pub fn strideForWidth(self: FormatCode, width: u32) c_int {
const alignment = @sizeOf(u32);
const val = @as(c_int, @intCast((self.bpp() * width + 7) / 8));
return val + (alignment - 1) & -alignment;
}
// Converted from pixman.h
fn reshift(self: FormatCode, ofs: u5, num: u5) u32 {
const val = @intFromEnum(self);
const v1 = val >> ofs;
const v2 = @as(c_uint, 1) << num;
const v3 = @as(u5, @intCast((val >> 22) & 3));
return ((v1 & (v2 - 1)) << v3);
}
};
test "bpp" {
const testing = std.testing;
try testing.expectEqual(@as(u32, 1), FormatCode.g1.bpp());
try testing.expectEqual(@as(u32, 4), FormatCode.g4.bpp());
try testing.expectEqual(@as(u32, 8), FormatCode.g8.bpp());
}
test "stride" {
const testing = std.testing;
try testing.expectEqual(@as(c_int, 4), FormatCode.g1.strideForWidth(10));
try testing.expectEqual(@as(c_int, 8), FormatCode.g4.strideForWidth(10));
try testing.expectEqual(@as(c_int, 12), FormatCode.g8.strideForWidth(10));
}

View File

@ -1,211 +0,0 @@
const std = @import("std");
const c = @import("c.zig").c;
const pixman = @import("main.zig");
pub const Image = opaque {
pub fn createBitsNoClear(
format: pixman.FormatCode,
width: c_int,
height: c_int,
bits: [*]u32,
stride: c_int,
) pixman.Error!*Image {
return @as(?*Image, @ptrCast(c.pixman_image_create_bits_no_clear(
@intFromEnum(format),
width,
height,
bits,
stride,
))) orelse return pixman.Error.PixmanFailure;
}
pub fn createSolidFill(
color: pixman.Color,
) pixman.Error!*Image {
return @as(?*Image, @ptrCast(c.pixman_image_create_solid_fill(
@ptrCast(&color),
))) orelse return pixman.Error.PixmanFailure;
}
pub fn unref(self: *Image) bool {
return c.pixman_image_unref(@ptrCast(self)) == 1;
}
/// A variant of getDataUnsafe that sets the length of the slice to
/// height * stride. Its possible the buffer is larger but this is the
/// known safe values. If you KNOW the buffer is larger you can use the
/// unsafe variant.
pub fn getData(self: *Image) []u32 {
const height = self.getHeight();
const stride = self.getStride();
const ptr = self.getDataUnsafe();
const len = @as(usize, @intCast(height * stride));
return ptr[0..len];
}
pub fn getDataUnsafe(self: *Image) [*]u32 {
return c.pixman_image_get_data(@ptrCast(self));
}
pub fn getHeight(self: *Image) c_int {
return c.pixman_image_get_height(@ptrCast(self));
}
pub fn getWidth(self: *Image) c_int {
return c.pixman_image_get_width(@ptrCast(self));
}
pub fn getStride(self: *Image) c_int {
return c.pixman_image_get_stride(@ptrCast(self));
}
pub fn fillBoxes(
self: *Image,
op: pixman.Op,
color: pixman.Color,
boxes: []const pixman.Box32,
) pixman.Error!void {
if (c.pixman_image_fill_boxes(
@intFromEnum(op),
@ptrCast(self),
@ptrCast(&color),
@intCast(boxes.len),
@ptrCast(boxes.ptr),
) == 0) return pixman.Error.PixmanFailure;
}
pub fn fillRectangles(
self: *Image,
op: pixman.Op,
color: pixman.Color,
rects: []const pixman.Rectangle16,
) pixman.Error!void {
if (c.pixman_image_fill_rectangles(
@intFromEnum(op),
@ptrCast(self),
@ptrCast(&color),
@intCast(rects.len),
@ptrCast(rects.ptr),
) == 0) return pixman.Error.PixmanFailure;
}
pub fn rasterizeTrapezoid(
self: *Image,
trap: pixman.Trapezoid,
x_off: c_int,
y_off: c_int,
) void {
c.pixman_rasterize_trapezoid(
@ptrCast(self),
@ptrCast(&trap),
x_off,
y_off,
);
}
pub fn composite(
self: *Image,
op: pixman.Op,
src: *Image,
mask: ?*Image,
src_x: i16,
src_y: i16,
mask_x: i16,
mask_y: i16,
dest_x: i16,
dest_y: i16,
width: u16,
height: u16,
) void {
c.pixman_image_composite(
@intFromEnum(op),
@ptrCast(src),
@ptrCast(mask),
@ptrCast(self),
src_x,
src_y,
mask_x,
mask_y,
dest_x,
dest_y,
width,
height,
);
}
pub fn compositeTriangles(
self: *Image,
op: pixman.Op,
src: *Image,
mask_format: pixman.FormatCode,
x_src: c_int,
y_src: c_int,
x_dst: c_int,
y_dst: c_int,
tris: []const pixman.Triangle,
) void {
c.pixman_composite_triangles(
@intFromEnum(op),
@ptrCast(src),
@ptrCast(self),
@intFromEnum(mask_format),
x_src,
y_src,
x_dst,
y_dst,
@intCast(tris.len),
@ptrCast(tris.ptr),
);
}
};
test "create and destroy" {
const testing = std.testing;
const alloc = testing.allocator;
const width = 10;
const height = 10;
const format: pixman.FormatCode = .g1;
const stride = format.strideForWidth(width);
const len = height * @as(usize, @intCast(stride));
const data = try alloc.alloc(u32, len);
defer alloc.free(data);
@memset(data, 0);
const img = try Image.createBitsNoClear(.g1, width, height, data.ptr, stride);
try testing.expectEqual(@as(c_int, height), img.getHeight());
try testing.expectEqual(@as(c_int, stride), img.getStride());
try testing.expect(img.getData().len == height * stride);
try testing.expect(img.unref());
}
test "fill boxes a1" {
const testing = std.testing;
const alloc = testing.allocator;
// Dimensions
const width = 100;
const height = 100;
const format: pixman.FormatCode = .a1;
const stride = format.strideForWidth(width);
// Image
const len = height * @as(usize, @intCast(stride));
const data = try alloc.alloc(u32, len);
defer alloc.free(data);
@memset(data, 0);
const img = try Image.createBitsNoClear(format, width, height, data.ptr, stride);
defer _ = img.unref();
// Fill
const color: pixman.Color = .{ .red = 0xFFFF, .green = 0xFFFF, .blue = 0xFFFF, .alpha = 0xFFFF };
const boxes = &[_]pixman.Box32{
.{
.x1 = 0,
.y1 = 0,
.x2 = width,
.y2 = height,
},
};
try img.fillBoxes(.src, color, boxes);
}

View File

@ -1,23 +0,0 @@
const std = @import("std");
const format = @import("format.zig");
const image = @import("image.zig");
const types = @import("types.zig");
pub const c = @import("c.zig").c;
pub const Color = types.Color;
pub const Error = @import("error.zig").Error;
pub const Fixed = types.Fixed;
pub const FormatCode = format.FormatCode;
pub const Image = image.Image;
pub const Op = types.Op;
pub const PointFixed = types.PointFixed;
pub const LineFixed = types.LineFixed;
pub const Triangle = types.Triangle;
pub const Trapezoid = types.Trapezoid;
pub const Rectangle16 = types.Rectangle16;
pub const Box32 = types.Box32;
pub const Indexed = types.Indexed;
test {
std.testing.refAllDecls(@This());
}

View File

@ -1,54 +0,0 @@
/*
* Copyright © 2008 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#ifndef PIXMAN_VERSION_H__
#define PIXMAN_VERSION_H__
#ifndef PIXMAN_H__
# error pixman-version.h should only be included by pixman.h
#endif
#define PIXMAN_VERSION_MAJOR 999
#define PIXMAN_VERSION_MINOR 999
#define PIXMAN_VERSION_MICRO 999
#define PIXMAN_VERSION_STRING "999.999.999"
#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
((major) * 10000) \
+ ((minor) * 100) \
+ ((micro) * 1))
#define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \
PIXMAN_VERSION_MAJOR, \
PIXMAN_VERSION_MINOR, \
PIXMAN_VERSION_MICRO)
#ifndef PIXMAN_API
# define PIXMAN_API
#endif
#endif /* PIXMAN_VERSION_H__ */

View File

@ -1,131 +0,0 @@
const std = @import("std");
const c = @import("c.zig").c;
const pixman = @import("main.zig");
pub const Op = enum(c_uint) {
clear = 0x00,
src = 0x01,
dst = 0x02,
over = 0x03,
over_reverse = 0x04,
in = 0x05,
in_reverse = 0x06,
out = 0x07,
out_reverse = 0x08,
atop = 0x09,
atop_reverse = 0x0a,
xor = 0x0b,
add = 0x0c,
saturate = 0x0d,
disjoint_clear = 0x10,
disjoint_src = 0x11,
disjoint_dst = 0x12,
disjoint_over = 0x13,
disjoint_over_reverse = 0x14,
disjoint_in = 0x15,
disjoint_in_reverse = 0x16,
disjoint_out = 0x17,
disjoint_out_reverse = 0x18,
disjoint_atop = 0x19,
disjoint_atop_reverse = 0x1a,
disjoint_xor = 0x1b,
conjoint_clear = 0x20,
conjoint_src = 0x21,
conjoint_dst = 0x22,
conjoint_over = 0x23,
conjoint_over_reverse = 0x24,
conjoint_in = 0x25,
conjoint_in_reverse = 0x26,
conjoint_out = 0x27,
conjoint_out_reverse = 0x28,
conjoint_atop = 0x29,
conjoint_atop_reverse = 0x2a,
conjoint_xor = 0x2b,
multiply = 0x30,
screen = 0x31,
overlay = 0x32,
darken = 0x33,
lighten = 0x34,
color_dodge = 0x35,
color_burn = 0x36,
hard_light = 0x37,
soft_light = 0x38,
difference = 0x39,
exclusion = 0x3a,
hsl_hue = 0x3b,
hsl_saturation = 0x3c,
hsl_color = 0x3d,
hsl_luminosity = 0x3e,
};
pub const Color = extern struct {
red: u16,
green: u16,
blue: u16,
alpha: u16,
};
pub const Fixed = enum(i32) {
_,
pub fn init(v: anytype) Fixed {
return switch (@TypeOf(v)) {
comptime_int, i32, u32 => @enumFromInt(v << 16),
f64 => @enumFromInt(@as(i32, @intFromFloat(v * 65536))),
else => {
@compileLog(@TypeOf(v));
@compileError("unsupported type");
},
};
}
};
pub const PointFixed = extern struct {
x: Fixed,
y: Fixed,
};
pub const LineFixed = extern struct {
p1: PointFixed,
p2: PointFixed,
};
pub const Triangle = extern struct {
p1: PointFixed,
p2: PointFixed,
p3: PointFixed,
};
pub const Trapezoid = extern struct {
top: Fixed,
bottom: Fixed,
left: LineFixed,
right: LineFixed,
};
pub const Rectangle16 = extern struct {
x: i16,
y: i16,
width: u16,
height: u16,
};
pub const Box32 = extern struct {
x1: i32,
y1: i32,
x2: i32,
y2: i32,
};
pub const Indexed = extern struct {
color: bool,
rgba: [256]u32,
ent: [32768]u8,
};
test {
std.testing.refAllDecls(@This());
}

View File

@ -3,6 +3,7 @@ const canvas = @import("sprite/canvas.zig");
pub const Face = @import("sprite/Face.zig");
pub const Box = canvas.Box;
pub const Point = canvas.Point;
pub const Canvas = canvas.Canvas;
pub const Color = canvas.Color;

File diff suppressed because it is too large Load Diff

View File

@ -188,29 +188,65 @@ const Kind = enum {
=> .box,
},
// Box fonts
0x2500...0x257F, // "Box Drawing" block
0x2580...0x259F, // "Block Elements" block
0x2800...0x28FF, // "Braille" block
// == Box fonts ==
0x1FB00...0x1FB3B, // "Symbols for Legacy Computing" block
0x1FB3C...0x1FB40,
0x1FB47...0x1FB4B,
0x1FB57...0x1FB5B,
0x1FB62...0x1FB66,
0x1FB6C...0x1FB6F,
0x1FB41...0x1FB45,
0x1FB4C...0x1FB50,
0x1FB52...0x1FB56,
0x1FB5D...0x1FB61,
0x1FB68...0x1FB6B,
0x1FB70...0x1FB8B,
0x1FB46,
0x1FB51,
0x1FB5C,
0x1FB67,
0x1FB9A,
0x1FB9B,
// "Box Drawing" block
//
//
//
//
0x2500...0x257F,
// "Block Elements" block
//
0x2580...0x259F,
// "Braille" block
0x2800...0x28FF,
// "Symbols for Legacy Computing" block
// (Block Mosaics / "Sextants")
// 🬀 🬁 🬂 🬃 🬄 🬅 🬆 🬇 🬈 🬉 🬊 🬋 🬌 🬍 🬎 🬏 🬐 🬑 🬒 🬓 🬔 🬕 🬖 🬗 🬘 🬙 🬚 🬛 🬜 🬝 🬞 🬟 🬠
// 🬡 🬢 🬣 🬤 🬥 🬦 🬧 🬨 🬩 🬪 🬫 🬬 🬭 🬮 🬯 🬰 🬱 🬲 🬳 🬴 🬵 🬶 🬷 🬸 🬹 🬺 🬻
// (Smooth Mosaics)
// 🬼 🬽 🬾 🬿 🭀 🭁 🭂 🭃 🭄 🭅 🭆
// 🭇 🭈 🭉 🭊 🭋 🭌 🭍 🭎 🭏 🭐 🭑
// 🭒 🭓 🭔 🭕 🭖 🭗 🭘 🭙 🭚 🭛 🭜
// 🭝 🭞 🭟 🭠 🭡 🭢 🭣 🭤 🭥 🭦 🭧
// 🭨 🭩 🭪 🭫 🭬 🭭 🭮 🭯
// (Block Elements)
// 🭰 🭱 🭲 🭳 🭴 🭵 🭶 🭷 🭸 🭹 🭺 🭻
// 🭼 🭽 🭾 🭿 🮀 🮁
// 🮂 🮃 🮄 🮅 🮆
// 🮇 🮈 🮉 🮊 🮋
// (Rectangular Shade Characters)
// 🮌 🮍 🮎 🮏 🮐 🮑 🮒
0x1FB00...0x1FB92,
// (Rectangular Shade Characters)
// 🮔
// (Fill Characters)
// 🮕 🮖 🮗
// (Diagonal Fill Characters)
// 🮘 🮙
// (Smooth Mosaics)
// 🮚 🮛
// (Triangular Shade Characters)
// 🮜 🮝 🮞 🮟
// (Character Cell Diagonals)
// 🮠 🮡 🮢 🮣 🮤 🮥 🮦 🮧 🮨 🮩 🮪 🮫 🮬 🮭 🮮
// (Light Solid Line With Stroke)
// 🮯
0x1FB94...0x1FBAF,
// (Negative Terminal Characters)
// 🮽 🮾 🮿
0x1FBBD...0x1FBBF,
// (Block Elements)
// 🯎 🯏
// (Character Cell Diagonals)
// 🯐 🯑 🯒 🯓 🯔 🯕 🯖 🯗 🯘 🯙 🯚 🯛 🯜 🯝 🯞 🯟
// (Geometric Shapes)
// 🯠 🯡 🯢 🯣 🯤 🯥 🯦 🯧 🯨 🯩 🯪 🯫 🯬 🯭 🯮 🯯
0x1FBCE...0x1FBEF,
=> .box,
// Powerline fonts

View File

@ -11,7 +11,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const font = @import("../main.zig");
const Trapezoid = @import("canvas.zig").Trapezoid;
const Quad = @import("canvas.zig").Quad;
const log = std.log.scoped(.powerline_font);
@ -176,10 +176,10 @@ fn draw_wedge_triangle(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !v
else => unreachable,
}
canvas.triangle(.{
.p1 = .{ .x = @as(i32, @intCast(p1_x)), .y = @as(i32, @intCast(p1_y)) },
.p2 = .{ .x = @as(i32, @intCast(p2_x)), .y = @as(i32, @intCast(p2_y)) },
.p3 = .{ .x = @as(i32, @intCast(p3_x)), .y = @as(i32, @intCast(p3_y)) },
try canvas.triangle(.{
.p0 = .{ .x = @floatFromInt(p1_x), .y = @floatFromInt(p1_y) },
.p1 = .{ .x = @floatFromInt(p2_x), .y = @floatFromInt(p2_y) },
.p2 = .{ .x = @floatFromInt(p3_x), .y = @floatFromInt(p3_y) },
}, .on);
}
@ -391,8 +391,8 @@ fn draw_half_circle(self: Powerline, alloc: Allocator, canvas: *font.sprite.Canv
const average = @as(u8, @intCast(@min(total / (supersample * supersample), 0xFF)));
canvas.rect(
.{
.x = @intCast(c),
.y = @intCast(r),
.x = @floatFromInt(c),
.y = @floatFromInt(r),
.width = 1,
.height = 1,
},
@ -404,110 +404,86 @@ fn draw_half_circle(self: Powerline, alloc: Allocator, canvas: *font.sprite.Canv
}
fn draw_trapezoid_top_bottom(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !void {
const t_top: Trapezoid = if (cp == 0xE0D4)
const t_top: Quad = if (cp == 0xE0D4)
.{
.top = 0,
.bottom = @intCast(self.height / 2 - self.height / 20),
.left = .{
.p1 = .{
.x = 0,
.y = 0,
},
.p2 = .{
.x = @intCast(self.width - self.width / 3),
.y = @intCast(self.height / 2 - self.height / 20),
},
.p0 = .{
.x = 0,
.y = 0,
},
.right = .{
.p1 = .{
.x = @intCast(self.width),
.y = 0,
},
.p2 = .{
.x = @intCast(self.width),
.y = @intCast(self.height / 2 - self.height / 20),
},
.p1 = .{
.x = @floatFromInt(self.width - self.width / 3),
.y = @floatFromInt(self.height / 2 - self.height / 20),
},
.p2 = .{
.x = @floatFromInt(self.width),
.y = @floatFromInt(self.height / 2 - self.height / 20),
},
.p3 = .{
.x = @floatFromInt(self.width),
.y = 0,
},
}
else
.{
.top = 0,
.bottom = @intCast(self.height / 2 - self.height / 20),
.left = .{
.p1 = .{
.x = 0,
.y = 0,
},
.p2 = .{
.x = 0,
.y = @intCast(self.height / 2 - self.height / 20),
},
.p0 = .{
.x = 0,
.y = 0,
},
.right = .{
.p1 = .{
.x = @intCast(self.width),
.y = 0,
},
.p2 = .{
.x = @intCast(self.width / 3),
.y = @intCast(self.height / 2 - self.height / 20),
},
.p1 = .{
.x = 0,
.y = @floatFromInt(self.height / 2 - self.height / 20),
},
.p2 = .{
.x = @floatFromInt(self.width / 3),
.y = @floatFromInt(self.height / 2 - self.height / 20),
},
.p3 = .{
.x = @floatFromInt(self.width),
.y = 0,
},
};
const t_bottom: Trapezoid = if (cp == 0xE0D4)
const t_bottom: Quad = if (cp == 0xE0D4)
.{
.top = @intCast(self.height / 2 + self.height / 20),
.bottom = @intCast(self.height),
.left = .{
.p1 = .{
.x = @intCast(self.width - self.width / 3),
.y = @intCast(self.height / 2 + self.height / 20),
},
.p2 = .{
.x = 0,
.y = @intCast(self.height),
},
.p0 = .{
.x = @floatFromInt(self.width - self.width / 3),
.y = @floatFromInt(self.height / 2 + self.height / 20),
},
.right = .{
.p1 = .{
.x = @intCast(self.width),
.y = @intCast(self.height / 2 + self.height / 20),
},
.p2 = .{
.x = @intCast(self.width),
.y = @intCast(self.height),
},
.p1 = .{
.x = 0,
.y = @floatFromInt(self.height),
},
.p2 = .{
.x = @floatFromInt(self.width),
.y = @floatFromInt(self.height),
},
.p3 = .{
.x = @floatFromInt(self.width),
.y = @floatFromInt(self.height / 2 + self.height / 20),
},
}
else
.{
.top = @intCast(self.height / 2 + self.height / 20),
.bottom = @intCast(self.height),
.left = .{
.p1 = .{
.x = 0,
.y = @intCast(self.height / 2 + self.height / 20),
},
.p2 = .{
.x = 0,
.y = @intCast(self.height),
},
.p0 = .{
.x = 0,
.y = @floatFromInt(self.height / 2 + self.height / 20),
},
.right = .{
.p1 = .{
.x = @intCast(self.width / 3),
.y = @intCast(self.height / 2 + self.height / 20),
},
.p2 = .{
.x = @intCast(self.width),
.y = @intCast(self.height),
},
.p1 = .{
.x = 0,
.y = @floatFromInt(self.height),
},
.p2 = .{
.x = @floatFromInt(self.width),
.y = @floatFromInt(self.height),
},
.p3 = .{
.x = @floatFromInt(self.width / 3),
.y = @floatFromInt(self.height / 2 + self.height / 20),
},
};
canvas.trapezoid(t_top);
canvas.trapezoid(t_bottom);
try canvas.quad(t_top, .on);
try canvas.quad(t_bottom, .on);
}
test "all" {

View File

@ -3,340 +3,88 @@
const std = @import("std");
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const js = @import("zig-js");
const pixman = @import("pixman");
const z2d = @import("z2d");
const font = @import("../main.zig");
pub const Point = struct {
x: i32,
y: i32,
x: f64,
y: f64,
};
pub const Line = struct {
p0: Point,
p1: Point,
p2: Point,
};
pub const Box = struct {
x1: i32,
y1: i32,
x2: i32,
y2: i32,
p0: Point,
p1: Point,
pub fn rect(self: Box) Rect {
const tl_x = @min(self.x1, self.x2);
const tl_y = @min(self.y1, self.y2);
const br_x = @max(self.x1, self.x2);
const br_y = @max(self.y1, self.y2);
const tl_x = @min(self.p0.x, self.p1.x);
const tl_y = @min(self.p0.y, self.p1.y);
const br_x = @max(self.p0.x, self.p1.x);
const br_y = @max(self.p0.y, self.p1.y);
return .{
.x = tl_x,
.y = tl_y,
.width = @intCast(br_x - tl_x),
.height = @intCast(br_y - tl_y),
.width = br_x - tl_x,
.height = br_y - tl_y,
};
}
};
pub const Rect = struct {
x: i32,
y: i32,
width: u32,
height: u32,
x: f64,
y: f64,
width: f64,
height: f64,
};
pub const Triangle = struct {
p0: Point,
p1: Point,
p2: Point,
};
pub const Quad = struct {
p0: Point,
p1: Point,
p2: Point,
p3: Point,
};
pub const Trapezoid = struct {
top: i32,
bottom: i32,
left: Line,
right: Line,
};
/// We only use alpha-channel so a pixel can only be "on" or "off".
pub const Color = enum(u8) {
const CSS_BUF_MAX = 24;
on = 255,
off = 0,
_,
fn pixmanColor(self: Color) pixman.Color {
// pixman uses u16 for color while our color value is u8 so we
// scale it up proportionally.
const max = @as(f32, @floatFromInt(std.math.maxInt(u8)));
const max_u16 = @as(f32, @floatFromInt(std.math.maxInt(u16)));
const unscaled = @as(f32, @floatFromInt(@intFromEnum(self)));
const scaled = @as(u16, @intFromFloat((unscaled * max_u16) / max));
return .{ .red = 0, .green = 0, .blue = 0, .alpha = scaled };
}
fn cssColor(self: Color, buf: []u8) ![]u8 {
return try std.fmt.bufPrint(buf, "rgba(0, 0, 0, {:.2})", .{
@as(f32, @floatFromInt(@intFromEnum(self))) / 255,
});
}
};
/// Composition operations that are supported.
pub const CompositionOp = enum {
// Note: more can be added here as needed.
pub const Canvas = struct {
/// The underlying z2d surface.
sfc: z2d.Surface,
source_out,
fn pixmanOp(self: CompositionOp) pixman.Op {
return switch (self) {
.source_out => .out,
};
}
fn jsOp(self: CompositionOp) js.String {
return switch (self) {
.source_out => js.string("source-out"),
};
}
};
pub const Canvas = switch (font.options.backend) {
.web_canvas => WebCanvasImpl,
else => PixmanImpl,
};
const WebCanvasImpl = struct {
/// The canvas element that is our final image.
canvas: js.Object,
/// Store the dimensions for easy access later.
width: u32,
height: u32,
pub fn init(alloc: Allocator, width: u32, height: u32) !WebCanvasImpl {
_ = alloc;
// Create our canvas that we're going to continue to reuse.
const doc = try js.global.get(js.Object, "document");
defer doc.deinit();
const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")});
errdefer canvas.deinit();
// Set our dimensions.
try canvas.set("width", width);
try canvas.set("height", height);
return WebCanvasImpl{
.canvas = canvas,
.width = width,
.height = height,
};
}
pub fn deinit(self: *WebCanvasImpl, alloc: Allocator) void {
_ = alloc;
self.canvas.deinit();
self.* = undefined;
}
pub fn pixel(self: *WebCanvasImpl, x: u32, y: u32, color: Color) void {
const ctx = self.context(color) catch return;
defer ctx.deinit();
ctx.call(void, "fillRect", .{ x, y, 1, 1 }) catch return;
}
pub fn rect(self: *WebCanvasImpl, v: Rect, color: Color) void {
const ctx = self.context(color) catch return;
defer ctx.deinit();
ctx.call(void, "fillRect", .{
@as(u32, @intCast(v.x)),
@as(u32, @intCast(v.y)),
v.width,
v.height,
}) catch return;
}
pub fn trapezoid(self: *WebCanvasImpl, t: Trapezoid) void {
const ctx = self.context(.on) catch return;
defer ctx.deinit();
ctx.call(void, "beginPath", .{}) catch return;
ctx.call(void, "moveTo", .{ t.left.p1.x, t.left.p1.y }) catch return;
ctx.call(void, "lineTo", .{ t.right.p1.x, t.right.p1.y }) catch return;
ctx.call(void, "lineTo", .{ t.right.p2.x, t.right.p2.y }) catch return;
ctx.call(void, "lineTo", .{ t.left.p2.x, t.left.p2.y }) catch return;
ctx.call(void, "fill", .{}) catch return;
}
pub fn triangle(self: *WebCanvasImpl, t: Triangle, color: Color) void {
const ctx = self.context(color) catch return;
defer ctx.deinit();
ctx.call(void, "beginPath", .{}) catch return;
ctx.call(void, "moveTo", .{ t.p1.x, t.p1.y }) catch return;
ctx.call(void, "lineTo", .{ t.p2.x, t.p2.y }) catch return;
ctx.call(void, "lineTo", .{ t.p3.x, t.p3.y }) catch return;
ctx.call(void, "fill", .{}) catch return;
}
pub fn composite(
self: *WebCanvasImpl,
op: CompositionOp,
src: *const WebCanvasImpl,
dest: Rect,
) void {
const ctx = self.context(Color.on) catch return;
defer ctx.deinit();
// Set our compositing operation
ctx.set("globalCompositeOperation", op.jsOp()) catch return;
// Composite
ctx.call(void, "drawImage", .{
src.canvas,
dest.x,
dest.y,
dest.width,
dest.height,
}) catch return;
}
fn context(self: WebCanvasImpl, fill: ?Color) !js.Object {
const ctx = try self.canvas.call(js.Object, "getContext", .{js.string("2d")});
errdefer ctx.deinit();
// Reset our composite operation
try ctx.set("globalCompositeOperation", js.string("source-over"));
// Set our fill color
if (fill) |c| {
var buf: [Color.CSS_BUF_MAX]u8 = undefined;
const color = try c.cssColor(&buf);
try ctx.set("fillStyle", js.string(color));
}
return ctx;
}
pub fn writeAtlas(self: *WebCanvasImpl, alloc: Allocator, atlas: *font.Atlas) !font.Atlas.Region {
assert(atlas.format == .grayscale);
// Reload our context since we resized the canvas
const ctx = try self.context(null);
defer ctx.deinit();
// Set our width/height. Set to vars in case we just query the canvas later.
const width = self.width;
const height = self.height;
// Read the image data and get it into a []u8 on our side
const bitmap: []u8 = bitmap: {
// Read the raw bitmap data and get the "data" value which is a
// Uint8ClampedArray.
const data = try ctx.call(js.Object, "getImageData", .{ 0, 0, width, height });
defer data.deinit();
const src_array = try data.get(js.Object, "data");
defer src_array.deinit();
// Allocate our local memory to copy the data to.
const len = try src_array.get(u32, "length");
const bitmap = try alloc.alloc(u8, @intCast(len));
errdefer alloc.free(bitmap);
// Create our target Uint8Array that we can use to copy from src.
const mem_array = mem_array: {
// Get our runtime memory
const mem = try js.runtime.get(js.Object, "memory");
defer mem.deinit();
const buf = try mem.get(js.Object, "buffer");
defer buf.deinit();
// Construct our array to peer into our memory
const Uint8Array = try js.global.get(js.Object, "Uint8Array");
defer Uint8Array.deinit();
const mem_array = try Uint8Array.new(.{ buf, bitmap.ptr });
errdefer mem_array.deinit();
break :mem_array mem_array;
};
defer mem_array.deinit();
// Copy
try mem_array.call(void, "set", .{src_array});
break :bitmap bitmap;
};
errdefer alloc.free(bitmap);
// Convert the format of the bitmap to A8 since the raw canvas data
// is in RGBA.
// NOTE(mitchellh): do we need a 1px buffer to avoid artifacts?
const bitmap_a8: []u8 = a8: {
assert(@mod(bitmap.len, 4) == 0);
assert(bitmap.len == width * height * 4);
var bitmap_a8 = try alloc.alloc(u8, bitmap.len / 4);
errdefer alloc.free(bitmap_a8);
var i: usize = 0;
while (i < bitmap_a8.len) : (i += 1) {
bitmap_a8[i] = bitmap[(i * 4) + 3];
}
break :a8 bitmap_a8;
};
defer alloc.free(bitmap_a8);
// Write the glyph information into the atlas
const region = try atlas.reserve(alloc, width, height);
if (region.width > 0 and region.height > 0) {
assert(region.width == width);
assert(region.height == height);
atlas.set(region, bitmap_a8);
}
return region;
}
};
const PixmanImpl = struct {
/// The underlying image.
image: *pixman.Image,
/// The raw data buffer.
data: []u32,
alloc: Allocator,
pub fn init(alloc: Allocator, width: u32, height: u32) !Canvas {
// Determine the config for our image buffer. The images we draw
// for boxes are always 8bpp
const format: pixman.FormatCode = .a8;
const stride = format.strideForWidth(width);
const len = @as(usize, @intCast(stride * @as(c_int, @intCast(height))));
// Allocate our buffer. pixman uses []u32 so we divide our length
// by 4 since u32 / u8 = 4.
const data = try alloc.alloc(u32, len / 4);
errdefer alloc.free(data);
@memset(data, 0);
// Create the image we'll draw to
const img = try pixman.Image.createBitsNoClear(
format,
// Create the surface we'll be using.
const sfc = try z2d.Surface.initPixel(
.{ .alpha8 = .{ .a = 0 } },
alloc,
@intCast(width),
@intCast(height),
data.ptr,
stride,
);
errdefer _ = img.unref();
return Canvas{
.image = img,
.data = data,
return .{
.sfc = sfc,
.alloc = alloc,
};
}
pub fn deinit(self: *Canvas, alloc: Allocator) void {
alloc.free(self.data);
_ = self.image.unref();
_ = alloc;
self.sfc.deinit();
self.* = undefined;
}
@ -344,8 +92,8 @@ const PixmanImpl = struct {
pub fn writeAtlas(self: *Canvas, alloc: Allocator, atlas: *font.Atlas) !font.Atlas.Region {
assert(atlas.format == .grayscale);
const width = @as(u32, @intCast(self.image.getWidth()));
const height = @as(u32, @intCast(self.image.getHeight()));
const width = @as(u32, @intCast(self.sfc.getWidth()));
const height = @as(u32, @intCast(self.sfc.getHeight()));
// Allocate our texture atlas region
const region = region: {
@ -372,31 +120,7 @@ const PixmanImpl = struct {
};
if (region.width > 0 and region.height > 0) {
const depth = atlas.format.depth();
// Convert our []u32 to []u8 since we use 8bpp formats
const stride = self.image.getStride();
const data = @as([*]u8, @ptrCast(self.data.ptr))[0 .. self.data.len * 4];
// We can avoid a buffer copy if our atlas width and bitmap
// width match and the bitmap pitch is just the width (meaning
// the data is tightly packed).
const needs_copy = !(width * depth == stride);
// If we need to copy the data, we copy it into a temporary buffer.
const buffer = if (needs_copy) buffer: {
const temp = try alloc.alloc(u8, width * height * depth);
var dst_ptr = temp;
var src_ptr = data.ptr;
var i: usize = 0;
while (i < height) : (i += 1) {
@memcpy(dst_ptr[0 .. width * depth], src_ptr[0 .. width * depth]);
dst_ptr = dst_ptr[width * depth ..];
src_ptr += @as(usize, @intCast(stride));
}
break :buffer temp;
} else data[0..(width * height * depth)];
defer if (buffer.ptr != data.ptr) alloc.free(buffer);
const buffer: []u8 = @ptrCast(self.sfc.image_surface_alpha8.buf);
// Write the glyph information into the atlas
assert(region.width == width);
@ -409,102 +133,105 @@ const PixmanImpl = struct {
/// Draw and fill a single pixel
pub fn pixel(self: *Canvas, x: u32, y: u32, color: Color) void {
if (comptime std.debug.runtime_safety) {
assert(x < self.image.getWidth());
assert(y < self.image.getHeight());
}
const boxes = &[_]pixman.Box32{
.{
.x1 = @intCast(x),
.y1 = @intCast(y),
.x2 = @intCast(x + 1),
.y2 = @intCast(y + 1),
},
self.sfc.putPixel(
@intCast(x),
@intCast(y),
.{ .alpha8 = .{ .a = @intFromEnum(color) } },
) catch {
// If we try to set out of range this will fail.
// We just silently ignore that.
};
self.image.fillBoxes(.src, color.pixmanColor(), boxes) catch {};
}
/// Draw and fill a rectangle. This is the main primitive for drawing
/// lines as well (which are just generally skinny rectangles...)
pub fn rect(self: *Canvas, v: Rect, color: Color) void {
const boxes = &[_]pixman.Box32{
.{
.x1 = @intCast(v.x),
.y1 = @intCast(v.y),
.x2 = @intCast(v.x + @as(i32, @intCast(v.width))),
.y2 = @intCast(v.y + @as(i32, @intCast(v.height))),
const x0: usize = @intFromFloat(v.x);
const x1: usize = @intFromFloat(v.x + v.width);
const y0: usize = @intFromFloat(v.y);
const y1: usize = @intFromFloat(v.y + v.height);
for (y0..y1) |y| {
for (x0..x1) |x| {
self.pixel(
@intCast(x),
@intCast(y),
color,
);
}
}
}
/// Draw and fill a quad.
pub fn quad(self: *Canvas, q: Quad, color: Color) !void {
var ctx: z2d.Context = .{
.surface = self.sfc,
.pattern = .{
.opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
},
},
};
if (comptime std.debug.runtime_safety) {
assert(boxes[0].x1 >= 0);
assert(boxes[0].y1 >= 0);
assert(boxes[0].x2 <= @as(i32, @intCast(self.image.getWidth())));
assert(boxes[0].y2 <= @as(i32, @intCast(self.image.getHeight())));
}
var path = z2d.Path.init(self.alloc);
defer path.deinit();
self.image.fillBoxes(.src, color.pixmanColor(), boxes) catch {};
}
try path.moveTo(q.p0.x, q.p0.y);
try path.lineTo(q.p1.x, q.p1.y);
try path.lineTo(q.p2.x, q.p2.y);
try path.lineTo(q.p3.x, q.p3.y);
try path.close();
/// Draw and fill a trapezoid.
pub fn trapezoid(self: *Canvas, t: Trapezoid) void {
self.image.rasterizeTrapezoid(.{
.top = pixman.Fixed.init(t.top),
.bottom = pixman.Fixed.init(t.bottom),
.left = .{
.p1 = .{
.x = pixman.Fixed.init(t.left.p1.x),
.y = pixman.Fixed.init(t.left.p1.y),
},
.p2 = .{
.x = pixman.Fixed.init(t.left.p2.x),
.y = pixman.Fixed.init(t.left.p2.y),
},
},
.right = .{
.p1 = .{
.x = pixman.Fixed.init(t.right.p1.x),
.y = pixman.Fixed.init(t.right.p1.y),
},
.p2 = .{
.x = pixman.Fixed.init(t.right.p2.x),
.y = pixman.Fixed.init(t.right.p2.y),
},
},
}, 0, 0);
try ctx.fill(self.alloc, path);
}
/// Draw and fill a triangle.
pub fn triangle(self: *Canvas, t: Triangle, color: Color) void {
const tris = &[_]pixman.Triangle{
.{
.p1 = .{ .x = pixman.Fixed.init(t.p1.x), .y = pixman.Fixed.init(t.p1.y) },
.p2 = .{ .x = pixman.Fixed.init(t.p2.x), .y = pixman.Fixed.init(t.p2.y) },
.p3 = .{ .x = pixman.Fixed.init(t.p3.x), .y = pixman.Fixed.init(t.p3.y) },
pub fn triangle(self: *Canvas, t: Triangle, color: Color) !void {
var ctx: z2d.Context = .{
.surface = self.sfc,
.pattern = .{
.opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
},
},
};
const src = pixman.Image.createSolidFill(color.pixmanColor()) catch return;
defer _ = src.unref();
self.image.compositeTriangles(.over, src, .a8, 0, 0, 0, 0, tris);
var path = z2d.Path.init(self.alloc);
defer path.deinit();
try path.moveTo(t.p0.x, t.p0.y);
try path.lineTo(t.p1.x, t.p1.y);
try path.lineTo(t.p2.x, t.p2.y);
try path.close();
try ctx.fill(self.alloc, path);
}
/// Composite one image on another.
pub fn composite(self: *Canvas, op: CompositionOp, src: *const Canvas, dest: Rect) void {
self.image.composite(
op.pixmanOp(),
src.image,
null,
0,
0,
0,
0,
@intCast(dest.x),
@intCast(dest.y),
@intCast(dest.width),
@intCast(dest.height),
);
/// Stroke a line.
pub fn line(self: *Canvas, l: Line, thickness: f64, color: Color) !void {
var ctx: z2d.Context = .{
.surface = self.sfc,
.pattern = .{
.opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
},
},
.line_width = thickness,
.line_cap_mode = .round,
};
var path = z2d.Path.init(self.alloc);
defer path.deinit();
try path.moveTo(l.p0.x, l.p0.y);
try path.lineTo(l.p1.x, l.p1.y);
try ctx.stroke(self.alloc, path);
}
pub fn invert(self: *Canvas) void {
for (std.mem.sliceAsBytes(self.sfc.image_surface_alpha8.buf)) |*v| {
v.* = 255 - v.*;
}
}
};

Binary file not shown.

View File

@ -70,8 +70,8 @@ fn drawSingle(alloc: Allocator, width: u32, thickness: u32) !CanvasAndOffset {
canvas.rect(.{
.x = 0,
.y = 0,
.width = width,
.height = thickness,
.width = @floatFromInt(width),
.height = @floatFromInt(thickness),
}, .on);
const offset_y: i32 = 0;
@ -91,15 +91,15 @@ fn drawDouble(alloc: Allocator, width: u32, thickness: u32) !CanvasAndOffset {
canvas.rect(.{
.x = 0,
.y = 0,
.width = width,
.height = thickness,
.width = @floatFromInt(width),
.height = @floatFromInt(thickness),
}, .on);
canvas.rect(.{
.x = 0,
.y = @intCast(thickness + gap),
.width = width,
.height = thickness,
.y = @floatFromInt(thickness * 2),
.width = @floatFromInt(width),
.height = @floatFromInt(thickness),
}, .on);
const offset_y: i32 = -@as(i32, @intCast(thickness));
@ -121,10 +121,10 @@ fn drawDotted(alloc: Allocator, width: u32, thickness: u32) !CanvasAndOffset {
const x = @min(i * (dot_width + gap_width), width - 1);
const rect_width = @min(width - x, dot_width);
canvas.rect(.{
.x = @intCast(x),
.x = @floatFromInt(x),
.y = 0,
.width = rect_width,
.height = thickness,
.width = @floatFromInt(rect_width),
.height = @floatFromInt(thickness),
}, .on);
}
@ -146,10 +146,10 @@ fn drawDashed(alloc: Allocator, width: u32, thickness: u32) !CanvasAndOffset {
const x = @min(i * dash_width, width - 1);
const rect_width = @min(width - x, dash_width);
canvas.rect(.{
.x = @intCast(x),
.x = @floatFromInt(x),
.y = 0,
.width = rect_width,
.height = thickness,
.width = @floatFromInt(rect_width),
.height = @floatFromInt(thickness),
}, .on);
}

View File

@ -1,14 +0,0 @@
# To use this config on you editor, follow the instructions at:
# http://editorconfig.org
root = true
[*]
tab_width = 8
[Makefile.*]
indent_style = tab
[meson.build,meson_options.txt]
indent_style = space
indent_size = 2

View File

@ -1,56 +0,0 @@
Makefile
Makefile.in
.deps
.libs
.msg
*.pc
*.lo
*.la
*.a
*.o
*~
aclocal.m4
autom4te.cache
compile
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h?
config.h
config.h.in
.*.swp
demos/*-test
demos/checkerboard
demos/clip-in
demos/linear-gradient
demos/quad2quad
demos/scale
demos/dither
pixman/pixman-srgb.c
pixman/pixman-version.h
test/*-test
test/affine-bench
test/alpha-loop
test/alphamap
test/check-formats
test/clip-in
test/composite
test/infinite-loop
test/lowlevel-blt-bench
test/radial-invalid
test/region-translate
test/scaling-bench
test/trap-crasher
*.pdb
*.dll
*.lib
*.ilk
*.obj
*.exe

View File

@ -1,19 +0,0 @@
image: fedora:28
autotools-build:
script:
- dnf -y install dnf-plugins-core
- dnf -y groupinstall buildsys-build
- dnf -y builddep pixman
- ./autogen.sh
- make -sj4 check
meson-build:
script:
- dnf -y install dnf-plugins-core
- dnf -y groupinstall buildsys-build
- dnf -y builddep pixman
- dnf -y install ninja-build
- python3 -m pip install meson>=0.52.1
- meson build
- ninja -C build test

View File

View File

@ -1,199 +0,0 @@
Pixman coding style.
====================
The pixman coding style is close to cairo's with one exception: braces
go on their own line, rather than on the line of the if/while/for:
if (condition)
{
do_something();
do_something_else();
}
not
if (condition) {
do_something();
do_something_else();
}
Indentation
===========
Each new level is indented four spaces:
if (condition)
do_something();
This may be achieved with space characters or with a combination of
tab characters and space characters. Tab characters are interpreted as
Advance to the next column which is a multiple of 8.
Names
=====
In all names, words are separated with underscores. Do not use
CamelCase for any names.
Macros have ALL_CAPITAL_NAMES
Type names are in lower case and end with "_t". For example
pixman_image_t.
Labels, functions and variables have lower case names.
Braces
======
Braces always go on their own line:
if (condition)
{
do_this ();
do_that ();
}
else
{
do_the_other ();
}
Rules for braces and substatements of if/while/for/do:
* If a substatement spans multiple lines, then there must be braces
around it.
* If the condition of an if/while/for spans multiple lines, then
braces must be used for the substatements.
* If one substatement of an if statement has braces, then the other
must too.
* Otherwise, don't add braces.
Comments
========
For comments either like this:
/* One line comment */
or like this:
/* This is a multi-line comment
*
* It extends over multiple lines
*/
Generally comments should say things that aren't clear from the code
itself. If too many comments say obvious things, then people will just
stop reading all comments, including the good ones.
Whitespace
==========
* Put a single space after commas
* Put spaces around arithmetic operators such a +, -, *, /:
y * stride + x
x / unit_x
* Do not put spaces after the address-of operator, the * when used as
a pointer derefernce or the ! and ~ operators:
&foo;
~0x00000000
!condition
*result = 100
* Break up long lines (> ~80 characters) and use whitespace to align
things nicely. This is one way:
some_very_long_function name (
implementation, op, src, mask, dest,
src_x, src_y, mask_x, mask_y, dest_x, dest_y,
width, height);
This is another:
some_very_long_function_name (implementation, op,
src, mask, dest,
src_x, src_y,
mask_x, mask_y,
dest_x, dest_y,
width, height);
* Separate logically distinct chunks with a single newline. This
obviously applies between functions, but also applies within a
function or block or structure definition.
* Use a newline after a block of variable declarations.
* Use a single space before a left parenthesis, except where the
standard will not allow it, (eg. when defining a parameterized macro).
* Don't eliminate newlines just because things would still fit on one
line. This breaks the expected visual structure of the code making
it much harder to read and understand:
if (condition) foo (); else bar (); /* Yuck! */
Function Definitions
====================
Function definitions should take the following form:
void
my_function (int argument)
{
do_my_things ();
}
If all the parameters to a function fit naturally on one line, format
them that way. Otherwise, put one argument on each line, adding
whitespace so that the parameter names are aligned with each other.
I.e., do either this:
void
short_arguments (const char *str, int x, int y, int z)
{
}
or this:
void
long_arguments (const char *char_star_arg,
int int_arg,
double *double_star_arg,
double double_arg)
{
}
Mode lines
==========
Given the rules above, what is the best way to simplify one's life as
a code monkey? Get your editor to do most of the tedious work of
beautifying your code!
As a reward for reading this far, here are some mode lines for the more
popular editors:
/*
* vim:sw=4:sts=4:ts=8:tw=78:fo=tcroq:cindent:cino=\:0,(0
* vim:isk=a-z,A-Z,48-57,_,.,-,>
*/

42
vendor/pixman/COPYING vendored
View File

@ -1,42 +0,0 @@
The following is the MIT license, agreed upon by most contributors.
Copyright holders of new code should use this license statement where
possible. They may also add themselves to the list below.
/*
* Copyright 1987, 1988, 1989, 1998 The Open Group
* Copyright 1987, 1988, 1989 Digital Equipment Corporation
* Copyright 1999, 2004, 2008 Keith Packard
* Copyright 2000 SuSE, Inc.
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
* Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc.
* Copyright 2004 Nicholas Miell
* Copyright 2005 Lars Knoll & Zack Rusin, Trolltech
* Copyright 2005 Trolltech AS
* Copyright 2007 Luca Barbato
* Copyright 2008 Aaron Plattner, NVIDIA Corporation
* Copyright 2008 Rodrigo Kumpera
* Copyright 2008 André Tupinambá
* Copyright 2008 Mozilla Corporation
* Copyright 2008 Frederic Plourde
* Copyright 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009, 2010 Nokia Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

View File

234
vendor/pixman/INSTALL vendored
View File

@ -1,234 +0,0 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -1,143 +0,0 @@
SUBDIRS = pixman demos test
pkgconfigdir=$(libdir)/pkgconfig
pkgconfig_DATA=pixman-1.pc
$(pkgconfig_DATA): pixman-1.pc.in
snapshot:
distdir="$(distdir)-`date '+%Y%m%d'`"; \
test -d "$(srcdir)/.git" && distdir=$$distdir-`cd "$(srcdir)" && git rev-parse HEAD | cut -c 1-6`; \
$(MAKE) $(AM_MAKEFLAGS) distdir="$$distdir" dist
GPGKEY=3892336E
USERNAME=$$USER
RELEASE_OR_SNAPSHOT = $$(if test "x$(PIXMAN_VERSION_MINOR)" = "x$$(echo "$(PIXMAN_VERSION_MINOR)/2*2" | bc)" ; then echo release; else echo snapshot; fi)
RELEASE_CAIRO_HOST = $(USERNAME)@cairographics.org
RELEASE_CAIRO_DIR = /srv/cairo.freedesktop.org/www/$(RELEASE_OR_SNAPSHOT)s
RELEASE_CAIRO_URL = https://cairographics.org/$(RELEASE_OR_SNAPSHOT)s
RELEASE_XORG_URL = https://www.x.org/releases/individual/lib
RELEASE_XORG_HOST = $(USERNAME)@xorg.freedesktop.org
RELEASE_XORG_DIR = /srv/xorg.freedesktop.org/archive/individual/lib
RELEASE_ANNOUNCE_LIST = cairo-announce@cairographics.org, xorg-announce@lists.freedesktop.org, pixman@lists.freedesktop.org
EXTRA_DIST = \
Makefile.win32 \
Makefile.win32.common \
meson.build \
meson_options.txt \
neon-test.S \
a64-neon-test.S \
arm-simd-test.S \
$(NULL)
tar_gz = $(PACKAGE)-$(VERSION).tar.gz
tar_xz = $(PACKAGE)-$(VERSION).tar.xz
sha512_tgz = $(tar_gz).sha512
sha256_tgz = $(tar_gz).sha256
sha512_txz = $(tar_xz).sha512
sha256_txz = $(tar_xz).sha256
gpg_file = $(sha512_tgz).asc
$(sha512_tgz): $(tar_gz)
sha512sum $^ > $@
$(sha256_tgz): $(tar_gz)
sha256sum $^ > $@
$(sha512_txz): $(tar_xz)
sha512sum $^ > $@
$(sha256_txz): $(tar_xz)
sha256sum $^ > $@
$(gpg_file): $(sha512_tgz)
@echo "Please enter your GPG password to sign the checksum."
gpg --armor --sign $^
HASHFILES = $(sha512_tgz) $(sha512_txz) $(sha256_tgz) $(sha256_txz)
release-verify-newer:
@echo -n "Checking that no $(VERSION) release already exists at $(RELEASE_XORG_HOST)..."
@ssh $(RELEASE_XORG_HOST) test ! -e $(RELEASE_XORG_DIR)/$(tar_gz) \
|| (echo "Ouch." && echo "Found: $(RELEASE_XORG_HOST):$(RELEASE_XORG_DIR)/$(tar_gz)" \
&& echo "Refusing to try to generate a new release of the same name." \
&& false)
@ssh $(RELEASE_CAIRO_HOST) test ! -e $(RELEASE_CAIRO_DIR)/$(tar_gz) \
|| (echo "Ouch." && echo "Found: $(RELEASE_CAIRO_HOST):$(RELEASE_CAIRO_DIR)/$(tar_gz)" \
&& echo "Refusing to try to generate a new release of the same name." \
&& false)
@echo "Good."
release-remove-old:
$(RM) $(tar_gz) $(tar_xz) $(HASHFILES) $(gpg_file)
ensure-prev:
@if [ "$(PREV)" = "" ]; then \
echo "" && \
echo "You must set the PREV variable on the make command line to" && \
echo "the last version." && \
echo "" && \
echo "For example:" && \
echo " make PREV=0.7.3" && \
echo "" && \
false; \
fi
release-check: ensure-prev release-verify-newer release-remove-old distcheck
release-tag:
git tag -u $(GPGKEY) -m "$(PACKAGE) $(VERSION) release" $(PACKAGE)-$(VERSION)
release-upload: release-check $(tar_gz) $(tar_xz) $(sha512_tgz) $(sha512_txz) $(sha256_tgz) $(gpg_file)
scp $(tar_gz) $(sha512_tgz) $(gpg_file) $(RELEASE_CAIRO_HOST):$(RELEASE_CAIRO_DIR)
scp $(tar_gz) $(tar_xz) $(RELEASE_XORG_HOST):$(RELEASE_XORG_DIR)
ssh $(RELEASE_CAIRO_HOST) "rm -f $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_gz) $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
RELEASE_TYPE = $$(if test "x$(PIXMAN_VERSION_MINOR)" = "x$$(echo "$(PIXMAN_VERSION_MINOR)/2*2" | bc)" ; then echo "stable release in the" ; else echo "development snapshot leading up to a stable"; fi)
release-publish-message: $(HASHFILES) ensure-prev
@echo "Please follow the instructions in RELEASING to push stuff out and"
@echo "send out the announcement mails. Here is the excerpt you need:"
@echo ""
@echo "Lists: $(RELEASE_ANNOUNCE_LIST)"
@echo "Subject: [ANNOUNCE] $(PACKAGE) release $(VERSION) now available"
@echo "============================== CUT HERE =============================="
@echo "A new $(PACKAGE) release $(VERSION) is now available. This is a $(RELEASE_TYPE)"
@echo ""
@echo "tar.gz:"
@echo " $(RELEASE_CAIRO_URL)/$(tar_gz)"
@echo " $(RELEASE_XORG_URL)/$(tar_gz)"
@echo ""
@echo "tar.xz:"
@echo " $(RELEASE_XORG_URL)/$(tar_xz)"
@echo ""
@echo "Hashes:"
@echo -n " SHA256: "
@cat $(sha256_tgz)
@echo -n " SHA256: "
@cat $(sha256_txz)
@echo -n " SHA512: "
@cat $(sha512_tgz)
@echo -n " SHA512: "
@cat $(sha512_txz)
@echo ""
@echo "GPG signature:"
@echo " $(RELEASE_CAIRO_URL)/$(gpg_file)"
@echo " (signed by`gpg --list-keys $(GPGKEY) | grep uid | cut -b4- | tr -s " "`)"
@echo ""
@echo "Git:"
@echo " https://gitlab.freedesktop.org/pixman/pixman.git"
@echo " tag: $(PACKAGE)-$(VERSION)"
@echo ""
@echo "Log:"
@git log --no-merges "$(PACKAGE)-$(PREV)".."$(PACKAGE)-$(VERSION)" | git shortlog | awk '{ printf "\t"; print ; }' | cut -b1-80
@echo "============================== CUT HERE =============================="
@echo ""
release-publish: release-upload release-tag release-publish-message
.PHONY: release-upload release-publish release-publish-message release-tag

View File

@ -1,25 +0,0 @@
default: all
top_srcdir = .
include $(top_srcdir)/Makefile.win32.common
all: pixman test
pixman:
@$(MAKE) -C pixman -f Makefile.win32
test:
@$(MAKE) -C test -f Makefile.win32
clean_r:
@$(MAKE) -C pixman -f Makefile.win32 clean
@$(MAKE) -C test -f Makefile.win32 clean
check:
@$(MAKE) -C test -f Makefile.win32 check
clean: clean_r
.PHONY: all pixman test clean check

View File

@ -1,73 +0,0 @@
LIBRARY = pixman-1
ifeq ($(shell echo ""),)
# POSIX style shell
mkdir_p = mkdir -p $1
rm = $(RM) $1
echo = echo "$1"
else
# DOS/Windows style shell
mkdir_p = if not exist $(subst /,\,$1) md $(subst /,\,$1)
echo = echo $1
rm = del $(subst /,\,$1)
endif
CC = cl
LD = link
AR = lib
PERL = perl
ifneq ($(shell echo ""),)
RM = del
endif
ifeq ($(top_builddir),)
top_builddir = $(top_srcdir)
endif
CFG_VAR = $(CFG)
ifeq ($(CFG_VAR),)
CFG_VAR = release
endif
ifeq ($(CFG_VAR),debug)
CFG_CFLAGS = -MDd -Od -Zi
CFG_LDFLAGS = -DEBUG
else
CFG_CFLAGS = -MD -O2
CFG_LDFLAGS =
endif
# Package definitions, to be used instead of those provided in config.h
PKG_CFLAGS = -DPACKAGE=$(LIBRARY) -DPACKAGE_VERSION="" -DPACKAGE_BUGREPORT=""
BASE_CFLAGS = -nologo -I. -I$(top_srcdir) -I$(top_srcdir)/pixman
PIXMAN_CFLAGS = $(BASE_CFLAGS) $(PKG_CFLAGS) $(CFG_CFLAGS) $(CFLAGS)
PIXMAN_LDFLAGS = -nologo $(CFG_LDFLAGS) $(LDFLAGS)
PIXMAN_ARFLAGS = -nologo $(LDFLAGS)
inform:
ifneq ($(CFG),release)
ifneq ($(CFG),debug)
ifneq ($(CFG),)
@echo "Invalid specified configuration option: "$(CFG)"."
@echo
@echo "Possible choices for configuration are 'release' and 'debug'"
@exit 1
endif
@echo "Using default RELEASE configuration... (use CFG=release or CFG=debug)"
endif
endif
$(CFG_VAR):
@$(call mkdir_p,$@)
$(CFG_VAR)/%.obj: %.c $(libpixman_headers) | $(CFG_VAR)
$(CC) -c $(PIXMAN_CFLAGS) -Fo"$@" $<
clean: inform $(CFG_VAR)
-$(call rm,$(CFG_VAR)/*.exe $(CFG_VAR)/*.ilk $(CFG_VAR)/*.lib $(CFG_VAR)/*.obj $(CFG_VAR)/*.pdb)
.PHONY: inform clean

0
vendor/pixman/NEWS vendored
View File

140
vendor/pixman/README vendored
View File

@ -1,140 +0,0 @@
Pixman
======
Pixman is a library that provides low-level pixel manipulation
features such as image compositing and trapezoid rasterization.
Questions should be directed to the pixman mailing list:
https://lists.freedesktop.org/mailman/listinfo/pixman
You can also file bugs at
https://gitlab.freedesktop.org/pixman/pixman/-/issues/new
or submit improvements in form of a Merge Request via
https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests
For real time discussions about pixman, feel free to join the IRC
channels #cairo and #xorg-devel on the FreeNode IRC network.
Contributing
------------
In order to contribute to pixman, you will need a working knowledge of
the git version control system. For a quick getting started guide,
there is the "Everyday Git With 20 Commands Or So guide"
https://www.kernel.org/pub/software/scm/git/docs/everyday.html
from the Git homepage. For more in depth git documentation, see the
resources on the Git community documentation page:
https://git-scm.com/documentation
Pixman uses the infrastructure from the freedesktop.org umbrella
project. For instructions about how to use the git service on
freedesktop.org, see:
https://www.freedesktop.org/wiki/Infrastructure/git/Developers
The Pixman master repository can be found at:
https://gitlab.freedesktop.org/pixman/pixman
Sending patches
---------------
Patches should be submitted in form of Merge Requests via Gitlab.
You will first need to create a fork of the main pixman repository at
https://gitlab.freedesktop.org/pixman/pixman
via the Fork button on the top right. Once that is done you can add your
personal repository as a remote to your local pixman development git checkout:
git remote add my-gitlab git@gitlab.freedesktop.org:YOURUSERNAME/pixman.git
git fetch my-gitlab
Make sure to have added ssh keys to your gitlab profile at
https://gitlab.freedesktop.org/profile/keys
Once that is set up, the general workflow for sending patches is to create a
new local branch with your improvements and once it's ready push it to your
personal pixman fork:
git checkout -b fix-some-bug
...
git push my-gitlab
The output of the `git push` command will include a link that allows you to
create a Merge Request against the official pixman repository.
Whenever you make changes to your branch (add new commits or fix up commits)
you push them back to your personal pixman fork:
git push -f my-gitlab
If there is an open Merge Request Gitlab will automatically pick up the
changes from your branch and pixman developers can review them anew.
In order for your patches to be accepted, please consider the
following guidelines:
- At each point in the series, pixman should compile and the test
suite should pass.
The exception here is if you are changing the test suite to
demonstrate a bug. In this case, make one commit that makes the
test suite fail due to the bug, and then another commit that fixes
the bug.
You can run the test suite with
make check
if you built pixman with autotools or
meson test -C builddir
if you built pixman with meson.
It will take around two minutes to run on a modern PC.
- Follow the coding style described in the CODING_STYLE file
- For bug fixes, include an update to the test suite to make sure
the bug doesn't reappear.
- For new features, add tests of the feature to the test
suite. Also, add a program demonstrating the new feature to the
demos/ directory.
- Write descriptive commit messages. Useful information to include:
- Benchmark results, before and after
- Description of the bug that was fixed
- Detailed rationale for any new API
- Alternative approaches that were rejected (and why they
don't work)
- If review comments were incorporated, a brief version
history describing what those changes were.
- For big patch series, write an introductory post with an overall
description of the patch series, including benchmarks and
motivation. Each commit message should still be descriptive and
include enough information to understand why this particular commit
was necessary.
Pixman has high standards for code quality and so almost everybody
should expect to have the first versions of their patches rejected.
If you think that the reviewers are wrong about something, or that the
guidelines above are wrong, feel free to discuss the issue. The purpose
of the guidelines and code review is to ensure high code quality; it is
not an exercise in compliance.

View File

@ -1,59 +0,0 @@
Here are the steps to follow to create a new pixman release:
1) Ensure that there are no uncommitted changes or unpushed commits,
and that you are up to date with the latest commits in the central
repository. Here are a couple of useful commands:
git diff (no output)
git status (should report "nothing to commit")
git log master...origin (no output; note: *3* dots)
2) Increment pixman_(major|minor|micro) in configure.ac and meson.build
according to the directions in those files.
3) Make sure that new version works, including
- make distcheck passes
- the X server still works with the new pixman version
installed
- the cairo test suite hasn't gained any new failures compared
to last pixman version.
4) Use "git commit" to record the changes made in step 2 and 3.
5) Generate and publish the tar files by running
make PREV=<last version> GPGKEY=<your gpg key id> release-publish
If your freedesktop user name is different from your local one,
then also set the variable USER to your freedesktop user name.
6) Run
make release-publish-message
to generate a draft release announcement. Edit it as appropriate and
send it to
cairo-announce@cairographics.org
pixman@lists.freedesktop.org
xorg-announce@lists.freedesktop.org
7) Increment pixman_micro to the next larger (odd) number in
configure.ac. Commit this change, and push all commits created
during this process using
git push
git push --tags
You must use "--tags" here; otherwise the new tag will not
be pushed out.
8) Change the topic of the #cairo IRC channel on freenode to advertise
the new version.

View File

@ -1,5 +0,0 @@
.text
.arch armv8-a
.altmacro
prfm pldl2strm, [x0]
xtn v0.8b, v0.8h

View File

@ -1,10 +0,0 @@
.text
.arch armv6
.object_arch armv4
.arm
.altmacro
#ifndef __ARM_EABI__
#error EABI is required (to be sure that calling conventions are compatible)
#endif
pld [r0]
uqadd8 r0, r0, r0

View File

@ -1,14 +0,0 @@
#! /bin/sh
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
autoreconf -v --install || exit 1
cd $ORIGDIR || exit $?
if test -z "$NOCONFIGURE"; then
$srcdir/configure "$@"
fi

File diff suppressed because it is too large Load Diff

View File

@ -1,581 +0,0 @@
# Copyright © 2018 Intel Corporation
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
project(
'pixman',
['c'],
version : '0.42.3',
license : 'MIT',
meson_version : '>= 0.52.0',
default_options : ['c_std=gnu99', 'buildtype=debugoptimized'],
)
config = configuration_data()
cc = meson.get_compiler('c')
null_dep = dependency('', required : false)
add_project_arguments(
cc.get_supported_arguments([
'-Wdeclaration-after-statement',
'-fno-strict-aliasing',
'-fvisibility=hidden',
'-Wundef',
# -ftrapping-math is the default for gcc, but -fno-trapping-math is the
# default for clang. The FLOAT_IS_ZERO macro is used to guard against
# floating-point exceptions, however with -fno-trapping-math, the compiler
# can reorder floating-point operations so that they occur before the guard.
# Note, this function is ignored in clang < 10.0.0.
'-ftrapping-math'
]),
language : ['c']
)
# GCC and Clang both ignore -Wno options that they don't recognize, so test for
# -W<opt>, then add -Wno-<opt> if it's ignored
foreach opt : ['unused-local-typedefs']
if cc.has_argument('-W' + opt)
add_project_arguments(['-Wno-' + opt], language : ['c'])
endif
endforeach
use_loongson_mmi = get_option('loongson-mmi')
have_loongson_mmi = false
loongson_mmi_flags = ['-mloongson-mmi']
if not use_loongson_mmi.disabled()
if host_machine.cpu_family() == 'mips64' and cc.compiles('''
#ifndef __mips_loongson_vector_rev
#error "Loongson Multimedia Instructions are only available on Loongson"
#endif
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
#error "Need GCC >= 4.4 for Loongson MMI compilation"
#endif
#include "pixman/loongson-mmintrin.h"
int main () {
union {
__m64 v;
char c[8];
} a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
int b = 4;
__m64 c = _mm_srli_pi16 (a.v, b);
return 0;
}''',
args : loongson_mmi_flags,
include_directories : include_directories('.'),
name : 'Loongson MMI Intrinsic Support')
have_loongson_mmi = true
endif
endif
if have_loongson_mmi
config.set10('USE_LOONGSON_MMI', true)
elif use_loongson_mmi.enabled()
error('Loongson MMI Support unavailable, but required')
endif
use_mmx = get_option('mmx')
have_mmx = false
mmx_flags = []
if cc.get_id() == 'msvc'
mmx_flags = ['/w14710', '/w14714', '/wd4244']
elif cc.get_id() == 'sun'
mmx_flags = ['-xarch=sse']
else
mmx_flags = ['-mmmx', '-Winline']
endif
if not use_mmx.disabled()
if host_machine.cpu_family() == 'x86_64' or cc.get_id() == 'msvc'
have_mmx = true
elif host_machine.cpu_family() == 'x86' and cc.compiles('''
#include <mmintrin.h>
#include <stdint.h>
/* Check support for block expressions */
#define _mm_shuffle_pi16(A, N) \
({ \
__m64 ret; \
\
/* Some versions of clang will choke on K */ \
asm ("pshufw %2, %1, %0\n\t" \
: "=y" (ret) \
: "y" (A), "K" ((const int8_t)N) \
); \
\
ret; \
})
int main () {
__m64 v = _mm_cvtsi32_si64 (1);
__m64 w;
w = _mm_shuffle_pi16(v, 5);
/* Some versions of clang will choke on this */
asm ("pmulhuw %1, %0\n\t"
: "+y" (w)
: "y" (v)
);
return _mm_cvtsi64_si32 (v);
}''',
args : mmx_flags,
name : 'MMX Intrinsic Support')
have_mmx = true
endif
endif
if have_mmx
# Inline assembly do not work on X64 MSVC, so we use
# compatibility intrinsics there
if cc.get_id() != 'msvc' or host_machine.cpu_family() != 'x86_64'
config.set10('USE_X86_MMX', true)
endif
elif use_mmx.enabled()
error('MMX Support unavailable, but required')
endif
use_sse2 = get_option('sse2')
have_sse2 = false
sse2_flags = []
if cc.get_id() == 'sun'
sse2_flags = ['-xarch=sse2']
elif cc.get_id() != 'msvc'
sse2_flags = ['-msse2', '-Winline']
endif
if not use_sse2.disabled()
if host_machine.cpu_family() == 'x86'
if cc.compiles('''
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
# if !defined(__amd64__) && !defined(__x86_64__)
# error "Need GCC >= 4.2 for SSE2 intrinsics on x86"
# endif
#endif
#include <mmintrin.h>
#include <xmmintrin.h>
#include <emmintrin.h>
int param;
int main () {
__m128i a = _mm_set1_epi32 (param), b = _mm_set1_epi32 (param + 1), c;
c = _mm_xor_si128 (a, b);
return _mm_cvtsi128_si32(c);
}''',
args : sse2_flags,
name : 'SSE2 Intrinsic Support')
have_sse2 = true
endif
elif host_machine.cpu_family() == 'x86_64'
have_sse2 = true
endif
endif
if have_sse2
config.set10('USE_SSE2', true)
elif use_sse2.enabled()
error('sse2 Support unavailable, but required')
endif
use_ssse3 = get_option('ssse3')
have_ssse3 = false
ssse3_flags = []
if cc.get_id() != 'msvc'
ssse3_flags = ['-mssse3', '-Winline']
endif
# x64 pre-2010 MSVC compilers crashes when building the ssse3 code
if not use_ssse3.disabled() and not (cc.get_id() == 'msvc' and cc.version().version_compare('<16') and host_machine.cpu_family() == 'x86_64')
if host_machine.cpu_family().startswith('x86')
if cc.compiles('''
#include <mmintrin.h>
#include <xmmintrin.h>
#include <emmintrin.h>
int param;
int main () {
__m128i a = _mm_set1_epi32 (param), b = _mm_set1_epi32 (param + 1), c;
c = _mm_xor_si128 (a, b);
return _mm_cvtsi128_si32(c);
}''',
args : ssse3_flags,
name : 'SSSE3 Intrinsic Support')
have_ssse3 = true
endif
endif
endif
if have_ssse3
config.set10('USE_SSSE3', true)
elif use_ssse3.enabled()
error('ssse3 Support unavailable, but required')
endif
use_vmx = get_option('vmx')
have_vmx = false
vmx_flags = ['-maltivec', '-mabi=altivec']
if not use_vmx.disabled()
if host_machine.cpu_family().startswith('ppc')
if cc.compiles('''
#include <altivec.h>
int main () {
vector unsigned int v = vec_splat_u32 (1);
v = vec_sub (v, v);
return 0;
}''',
args : vmx_flags,
name : 'VMX/Altivec Intrinsic Support')
have_vmx = true
endif
endif
endif
if have_vmx
config.set10('USE_VMX', true)
elif use_vmx.enabled()
error('vmx Support unavailable, but required')
endif
use_armv6_simd = get_option('arm-simd')
have_armv6_simd = false
if not use_armv6_simd.disabled()
if host_machine.cpu_family() == 'arm'
if cc.compiles(files('arm-simd-test.S'), name : 'ARMv6 SIMD Intrinsic Support')
have_armv6_simd = true
endif
endif
endif
if have_armv6_simd
config.set10('USE_ARM_SIMD', true)
elif use_armv6_simd.enabled()
error('ARMv6 SIMD Support unavailable, but required')
endif
use_neon = get_option('neon')
have_neon = false
if not use_neon.disabled()
if host_machine.cpu_family() == 'arm'
if cc.compiles(files('neon-test.S'), name : 'NEON Intrinsic Support')
have_neon = true
endif
endif
endif
if have_neon
config.set10('USE_ARM_NEON', true)
elif use_neon.enabled()
error('NEON Support unavailable, but required')
endif
use_a64neon = get_option('a64-neon')
have_a64neon = false
if not use_a64neon.disabled()
if host_machine.cpu_family() == 'aarch64'
if cc.compiles(files('a64-neon-test.S'), name : 'NEON A64 Intrinsic Support')
have_a64neon = true
endif
endif
endif
if have_a64neon
config.set10('USE_ARM_A64_NEON', true)
elif use_a64neon.enabled()
error('A64 NEON Support unavailable, but required')
endif
use_iwmmxt = get_option('iwmmxt')
have_iwmmxt = false
iwmmxt_flags = ['-flax-vector-conversions', '-Winline']
if not use_iwmmxt.disabled()
if get_option('iwmmxt2')
iwmmxt_flags += '-march=iwmmxt2'
else
iwmmxt_flags += '-march=iwmmxt'
endif
if host_machine.cpu_family() == 'arm'
if cc.compiles('''
#ifndef __IWMMXT__
#error "IWMMXT not enabled (with -march=iwmmxt)"
#endif
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
#error "Need GCC >= 4.8 for IWMMXT intrinsics"
#endif
#include <mmintrin.h>
int main () {
union {
__m64 v;
char c[8];
} a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
int b = 4;
__m64 c = _mm_srli_si64 (a.v, b);
}
''',
args : iwmmxt_flags,
name : 'IWMMXT Intrinsic Support')
have_iwmmxt = true
endif
endif
endif
if have_iwmmxt
config.set10('USE_ARM_IWMMXT', true)
elif use_iwmmxt.enabled()
error('IWMMXT Support unavailable, but required')
endif
use_mips_dspr2 = get_option('mips-dspr2')
have_mips_dspr2 = false
mips_dspr2_flags = ['-mdspr2']
if not use_mips_dspr2.disabled()
if host_machine.cpu_family() == 'mips32'
if cc.compiles('''
#if !(defined(__mips__) && __mips_isa_rev >= 2)
#error MIPS DSPr2 is currently only available on MIPS32r2 platforms.
#endif
int
main ()
{
int c = 0, a = 0, b = 0;
__asm__ __volatile__ (
"precr.qb.ph %[c], %[a], %[b] \n\t"
: [c] "=r" (c)
: [a] "r" (a), [b] "r" (b)
);
return c;
}''',
args : mipds_dspr2_flags,
name : 'DSPr2 Intrinsic Support')
have_mips_dspr2 = true
endif
endif
endif
if have_mips_dspr2
config.set10('USE_MIPS_DSPR2', true)
elif use_mips_dspr2.enabled()
error('MIPS DSPr2 Support unavailable, but required')
endif
use_gnu_asm = get_option('gnu-inline-asm')
if not use_gnu_asm.disabled()
if cc.compiles('''
int main () {
/* Most modern architectures have a NOP instruction, so this is a fairly generic test. */
asm volatile ( "\tnop\n" : : : "cc", "memory" );
return 0;
}
''',
name : 'GNU Inline ASM support.')
config.set10('USE_GCC_INLINE_ASM', true)
elif use_gnu_asm.enabled()
error('GNU inline assembly support missing but required.')
endif
endif
if get_option('timers')
config.set('PIXMAN_TIMERS', 1)
endif
if get_option('gnuplot')
config.set('PIXMAN_GNUPLOT', 1)
endif
if cc.get_id() != 'msvc'
dep_openmp = dependency('openmp', required : get_option('openmp'))
if dep_openmp.found()
config.set10('USE_OPENMP', true)
elif meson.version().version_compare('<0.51.0')
# In versions of meson before 0.51 the openmp dependency can still
# inject arguments in the the auto case when it is not found, the
# detection does work correctly in that case however, so we just
# replace dep_openmp with null_dep to work around this.
dep_openmp = null_dep
endif
else
# the MSVC implementation of openmp is not compliant enough for our
# uses here, so we disable it here.
# Please see: https://stackoverflow.com/questions/12560243/using-threadprivate-directive-in-visual-studio
dep_openmp = null_dep
endif
dep_gtk = dependency('gtk+-3.0', required : get_option('gtk'), required: get_option('demos'))
dep_glib = dependency('glib-2.0', required : get_option('gtk'), required: get_option('demos'))
dep_png = null_dep
if not get_option('libpng').disabled()
dep_png = dependency('libpng', required : false)
# We need to look for the right library to link to for libpng,
# when looking for libpng manually
foreach png_ver : [ '16', '15', '14', '13', '12', '10' ]
if not dep_png.found()
dep_png = cc.find_library('libpng@0@'.format(png_ver), has_headers : ['png.h'], required : false)
endif
endforeach
if get_option('libpng').enabled() and not dep_png.found()
error('libpng support requested but libpng library not found')
endif
endif
if dep_png.found()
config.set('HAVE_LIBPNG', 1)
endif
dep_m = cc.find_library('m', required : false)
dep_threads = dependency('threads')
# MSVC-style compilers do not come with pthreads, so we must link
# to it explicitly, currently pthreads-win32 is supported
pthreads_found = false
if dep_threads.found() and cc.has_header('pthread.h')
if cc.get_argument_syntax() == 'msvc'
pthread_lib = null_dep
foreach pthread_type : ['VC3', 'VSE3', 'VCE3', 'VC2', 'VSE2', 'VCE2']
if not pthread_lib.found()
pthread_lib = cc.find_library('pthread@0@'.format(pthread_type), required : false)
endif
endforeach
if pthread_lib.found()
pthreads_found = true
dep_threads = pthread_lib
endif
else
pthreads_found = true
endif
endif
if pthreads_found
config.set('HAVE_PTHREADS', 1)
endif
funcs = ['sigaction', 'alarm', 'mprotect', 'getpagesize', 'mmap', 'getisax', 'gettimeofday']
# mingw claimes to have posix_memalign, but it doesn't
if host_machine.system() != 'windows'
funcs += 'posix_memalign'
endif
foreach f : funcs
if cc.has_function(f)
config.set('HAVE_@0@'.format(f.to_upper()), 1)
endif
endforeach
# This is only used in one test, that defines _GNU_SOURCE
if cc.has_function('feenableexcept',
prefix : '#define _GNU_SOURCE\n#include <fenv.h>',
dependencies : dep_m)
config.set('HAVE_FEENABLEEXCEPT', 1)
endif
if cc.has_header_symbol('fenv.h', 'FE_DIVBYZERO')
config.set('HAVE_FEDIVBYZERO', 1)
endif
foreach h : ['sys/mman.h', 'fenv.h', 'unistd.h']
if cc.check_header(h)
config.set('HAVE_@0@'.format(h.underscorify().to_upper()), 1)
endif
endforeach
use_tls = get_option('tls')
have_tls = ''
if not use_tls.disabled()
# gcc on Windows only warns that __declspec(thread) isn't supported,
# passing -Werror=attributes makes it fail.
if (host_machine.system() == 'windows' and
cc.compiles('int __declspec(thread) foo;',
args : cc.get_supported_arguments(['-Werror=attributes']),
name : 'TLS via __declspec(thread)'))
have_tls = '__declspec(thread)'
elif cc.compiles('int __thread foo;', name : 'TLS via __thread')
have_tls = '__thread'
endif
endif
if have_tls != ''
config.set('TLS', have_tls)
elif use_tls.enabled()
error('Compiler TLS Support unavailable, but required')
endif
if cc.links('''
static int x = 1;
static void __attribute__((constructor)) constructor_function () { x = 0; }
int main (void) { return x; }
''',
name : '__attribute__((constructor))')
config.set('TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR', 1)
endif
if cc.links(
' __float128 a = 1.0Q, b = 2.0Q; int main (void) { return a + b; }',
name : 'Has float128 support')
config.set('HAVE_FLOAT128', 1)
endif
if cc.has_function('clz')
config.set('HAVE_BUILTIN_CLZ', 1)
endif
if cc.links('''
unsigned int __attribute__ ((vector_size(16))) e, a, b;
int main (void) { e = a - ((b << 27) + (b >> (32 - 27))) + 1; return e[0]; }
''',
name : 'Support for GCC vector extensions')
config.set('HAVE_GCC_VECTOR_EXTENSIONS', 1)
endif
if host_machine.endian() == 'big'
config.set('WORDS_BIGENDIAN', 1)
endif
config.set('SIZEOF_LONG', cc.sizeof('long'))
# Required to make pixman-private.h
config.set('PACKAGE', 'foo')
version_conf = configuration_data()
split = meson.project_version().split('.')
version_conf.set('PIXMAN_VERSION_MAJOR', split[0])
version_conf.set('PIXMAN_VERSION_MINOR', split[1])
version_conf.set('PIXMAN_VERSION_MICRO', split[2])
add_project_arguments('-DHAVE_CONFIG_H', language : ['c'])
subdir('pixman')
if not get_option('tests').disabled() or not get_option('demos').disabled()
subdir(join_paths('test', 'utils'))
endif
if not get_option('demos').disabled()
subdir('demos')
endif
if not get_option('tests').disabled()
subdir('test')
endif
pkg = import('pkgconfig')
pkg.generate(libpixman,
name : 'Pixman',
filebase : 'pixman-1',
description : 'The pixman library (version 1)',
subdirs: 'pixman-1',
version : meson.project_version(),
)

View File

@ -1,128 +0,0 @@
# Copyright © 2018 Intel Corporation
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
option(
'loongson-mmi',
type : 'feature',
description : 'Use Loongson MMI intrinsic optimized paths',
)
option(
'mmx',
type : 'feature',
description : 'Use X86 MMX intrinsic optimized paths',
)
option(
'sse2',
type : 'feature',
description : 'Use X86 SSE2 intrinsic optimized paths',
)
option(
'ssse3',
type : 'feature',
description : 'Use X86 SSSE3 intrinsic optimized paths',
)
option(
'vmx',
type : 'feature',
description : 'Use PPC VMX/Altivec intrinsic optimized paths',
)
option(
'arm-simd',
type : 'feature',
description : 'Use ARMv6 SIMD intrinsic optimized paths',
)
option(
'neon',
type : 'feature',
description : 'Use ARM NEON intrinsic optimized paths',
)
option(
'a64-neon',
type : 'feature',
description : 'Use ARM A64 NEON intrinsic optimized paths',
)
option(
'iwmmxt',
type : 'feature',
description : 'Use ARM IWMMXT intrinsic optimized paths',
)
option(
'iwmmxt2',
type : 'boolean',
value : true,
description : 'Use ARM IWMMXT2 intrinsic instead of IWMMXT',
)
option(
'mips-dspr2',
type : 'feature',
description : 'Use MIPS32 DSPr2 intrinsic optimized paths',
)
option(
'gnu-inline-asm',
type : 'feature',
description : 'Use GNU style inline assembler',
)
option(
'tls',
type : 'feature',
description : 'Use compiler support for thread-local storage',
)
option(
'cpu-features-path',
type : 'string',
description : 'Path to platform-specific cpu-features.[ch] for systems that do not provide it (e.g. Android)',
)
option(
'openmp',
type : 'feature',
description : 'Enable OpenMP for tests',
)
option(
'timers',
type : 'boolean',
value : false,
description : 'Enable TIMER_* macros',
)
option(
'gnuplot',
type : 'boolean',
value : false,
description : 'Enable output of filters that can be piped to gnuplot',
)
option(
'gtk',
type : 'feature',
description : 'Enable demos using GTK',
)
option(
'libpng',
type : 'feature',
description : 'Use libpng in tests'
)
option(
'tests',
type : 'feature',
description : 'Build tests'
)
option(
'demos',
type : 'feature',
description : 'Build demos'
)

View File

@ -1,12 +0,0 @@
.text
.fpu neon
.arch armv7a
.object_arch armv4
.eabi_attribute 10, 0
.arm
.altmacro
#ifndef __ARM_EABI__
#error EABI is required (to be sure that calling conventions are compatible)
#endif
pld [r0]
vmovn.u16 d0, q0

View File

@ -1,5 +0,0 @@
Name: Pixman
Description: The pixman library (version 1)
Version: @PACKAGE_VERSION@
Cflags: -I${pc_top_builddir}/${pcfiledir}/pixman
Libs: ${pc_top_builddir}/${pcfiledir}/pixman/libpixman-1.la

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Pixman
Description: The pixman library (version 1)
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}/pixman-1
Libs: -L${libdir} -lpixman-1

View File

@ -1,158 +0,0 @@
include $(top_srcdir)/pixman/Makefile.sources
lib_LTLIBRARIES = libpixman-1.la
libpixman_1_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined @PTHREAD_LDFLAGS@
libpixman_1_la_LIBADD = @PTHREAD_LIBS@ -lm
libpixman_1_la_SOURCES = $(libpixman_sources) $(libpixman_headers)
libpixmanincludedir = $(includedir)/pixman-1
libpixmaninclude_HEADERS = pixman.h pixman-version.h
noinst_LTLIBRARIES =
EXTRA_DIST = \
Makefile.win32 \
dither/make-blue-noise.c \
pixman-region.c \
solaris-hwcap.mapfile \
meson.build \
$(NULL)
# mmx code
if USE_X86_MMX
noinst_LTLIBRARIES += libpixman-mmx.la
libpixman_mmx_la_SOURCES = \
pixman-mmx.c
libpixman_mmx_la_CFLAGS = $(MMX_CFLAGS)
libpixman_1_la_LDFLAGS += $(MMX_LDFLAGS)
libpixman_1_la_LIBADD += libpixman-mmx.la
ASM_CFLAGS_mmx=$(MMX_CFLAGS)
endif
# vmx code
if USE_VMX
noinst_LTLIBRARIES += libpixman-vmx.la
libpixman_vmx_la_SOURCES = \
pixman-vmx.c \
pixman-combine32.h
libpixman_vmx_la_CFLAGS = $(VMX_CFLAGS)
libpixman_1_la_LIBADD += libpixman-vmx.la
ASM_CFLAGS_vmx=$(VMX_CFLAGS)
endif
# sse2 code
if USE_SSE2
noinst_LTLIBRARIES += libpixman-sse2.la
libpixman_sse2_la_SOURCES = \
pixman-sse2.c
libpixman_sse2_la_CFLAGS = $(SSE2_CFLAGS)
libpixman_1_la_LDFLAGS += $(SSE2_LDFLAGS)
libpixman_1_la_LIBADD += libpixman-sse2.la
ASM_CFLAGS_sse2=$(SSE2_CFLAGS)
endif
# ssse3 code
if USE_SSSE3
noinst_LTLIBRARIES += libpixman-ssse3.la
libpixman_ssse3_la_SOURCES = \
pixman-ssse3.c
libpixman_ssse3_la_CFLAGS = $(SSSE3_CFLAGS)
libpixman_1_la_LDFLAGS += $(SSSE3_LDFLAGS)
libpixman_1_la_LIBADD += libpixman-ssse3.la
ASM_CFLAGS_ssse3=$(SSSE3_CFLAGS)
endif
# arm simd code
if USE_ARM_SIMD
noinst_LTLIBRARIES += libpixman-arm-simd.la
libpixman_arm_simd_la_SOURCES = \
pixman-arm-simd.c \
pixman-arm-common.h \
pixman-arm-simd-asm.S \
pixman-arm-simd-asm-scaled.S \
pixman-arm-asm.h \
pixman-arm-simd-asm.h
libpixman_1_la_LIBADD += libpixman-arm-simd.la
ASM_CFLAGS_arm_simd=
endif
# arm neon code
if USE_ARM_NEON
noinst_LTLIBRARIES += libpixman-arm-neon.la
libpixman_arm_neon_la_SOURCES = \
pixman-arm-neon.c \
pixman-arm-common.h \
pixman-arm-neon-asm.S \
pixman-arm-neon-asm-bilinear.S \
pixman-arm-asm.h \
pixman-arm-neon-asm.h
libpixman_1_la_LIBADD += libpixman-arm-neon.la
ASM_CFLAGS_arm_neon=
endif
# arm a64 neon code
if USE_ARM_A64_NEON
noinst_LTLIBRARIES += libpixman-arma64-neon.la
libpixman_arma64_neon_la_SOURCES = \
pixman-arm-neon.c \
pixman-arm-common.h \
pixman-arma64-neon-asm.S \
pixman-arma64-neon-asm-bilinear.S \
pixman-arm-asm.h \
pixman-arma64-neon-asm.h
libpixman_1_la_LIBADD += libpixman-arma64-neon.la
ASM_CFLAGS_arm_neon=
endif
# iwmmxt code
if USE_ARM_IWMMXT
libpixman_iwmmxt_la_SOURCES = pixman-mmx.c
noinst_LTLIBRARIES += libpixman-iwmmxt.la
libpixman_1_la_LIBADD += libpixman-iwmmxt.la
libpixman_iwmmxt_la-pixman-mmx.lo: pixman-mmx.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(IWMMXT_CFLAGS) -MT libpixman_iwmmxt_la-pixman-mmx.lo -MD -MP -MF $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Tpo -c -o libpixman_iwmmxt_la-pixman-mmx.lo `test -f 'pixman-mmx.c' || echo '$(srcdir)/'`pixman-mmx.c
$(AM_V_at)$(am__mv) $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Tpo $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Plo
libpixman_iwmmxt_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
libpixman_iwmmxt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(CFLAGS) $(IWMMXT_CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
libpixman-iwmmxt.la: libpixman_iwmmxt_la-pixman-mmx.lo $(libpixman_iwmmxt_la_DEPENDENCIES)
$(AM_V_CCLD)$(libpixman_iwmmxt_la_LINK) libpixman_iwmmxt_la-pixman-mmx.lo $(libpixman_iwmmxt_la_LIBADD) $(LIBS)
endif
# mips dspr2 code
if USE_MIPS_DSPR2
noinst_LTLIBRARIES += libpixman-mips-dspr2.la
libpixman_mips_dspr2_la_SOURCES = \
pixman-mips-dspr2.c \
pixman-mips-dspr2.h \
pixman-mips-dspr2-asm.S \
pixman-mips-dspr2-asm.h \
pixman-mips-memcpy-asm.S
libpixman_1_la_LIBADD += libpixman-mips-dspr2.la
ASM_CFLAGS_mips_dspr2=
endif
# loongson code
if USE_LOONGSON_MMI
noinst_LTLIBRARIES += libpixman-loongson-mmi.la
libpixman_loongson_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h
libpixman_loongson_mmi_la_CFLAGS = $(LS_CFLAGS)
libpixman_1_la_LDFLAGS += $(LS_LDFLAGS)
libpixman_1_la_LIBADD += libpixman-loongson-mmi.la
endif
.c.s : $(libpixmaninclude_HEADERS)
$(CC) $(CFLAGS) $(ASM_CFLAGS_$(@:pixman-%.s=%)) $(ASM_CFLAGS_$(@:pixman-arm-%.s=arm_%)) -DHAVE_CONFIG_H -I$(srcdir) -I$(builddir) -I$(top_builddir) -S -o $@ $<

View File

@ -1,43 +0,0 @@
libpixman_sources = \
pixman.c \
pixman-access.c \
pixman-access-accessors.c \
pixman-bits-image.c \
pixman-combine32.c \
pixman-combine-float.c \
pixman-conical-gradient.c \
pixman-filter.c \
pixman-x86.c \
pixman-mips.c \
pixman-arm.c \
pixman-ppc.c \
pixman-edge.c \
pixman-edge-accessors.c \
pixman-fast-path.c \
pixman-glyph.c \
pixman-general.c \
pixman-gradient-walker.c \
pixman-image.c \
pixman-implementation.c \
pixman-linear-gradient.c \
pixman-matrix.c \
pixman-noop.c \
pixman-radial-gradient.c \
pixman-region16.c \
pixman-region32.c \
pixman-solid-fill.c \
pixman-timer.c \
pixman-trap.c \
pixman-utils.c \
$(NULL)
libpixman_headers = \
dither/blue-noise-64x64.h \
pixman.h \
pixman-accessor.h \
pixman-combine32.h \
pixman-compiler.h \
pixman-edge-imp.h \
pixman-inlines.h \
pixman-private.h \
$(NULL)

View File

@ -1,93 +0,0 @@
default: all
top_srcdir = ..
include $(top_srcdir)/pixman/Makefile.sources
include $(top_srcdir)/Makefile.win32.common
MMX_VAR = $(MMX)
ifeq ($(MMX_VAR),)
MMX_VAR=on
endif
SSE2_VAR = $(SSE2)
ifeq ($(SSE2_VAR),)
SSE2_VAR=on
endif
SSSE3_VAR = $(SSSE3)
ifeq ($(SSSE3_VAR),)
SSSE3_VAR=on
endif
MMX_CFLAGS = -DUSE_X86_MMX -w14710 -w14714
SSE2_CFLAGS = -DUSE_SSE2
SSSE3_CFLAGS = -DUSE_SSSE3
# MMX compilation flags
ifeq ($(MMX_VAR),on)
PIXMAN_CFLAGS += $(MMX_CFLAGS)
libpixman_sources += pixman-mmx.c
endif
# SSE2 compilation flags
ifeq ($(SSE2_VAR),on)
PIXMAN_CFLAGS += $(SSE2_CFLAGS)
libpixman_sources += pixman-sse2.c
endif
# SSSE3 compilation flags
ifeq ($(SSSE3_VAR),on)
PIXMAN_CFLAGS += $(SSSE3_CFLAGS)
libpixman_sources += pixman-ssse3.c
endif
OBJECTS = $(patsubst %.c, $(CFG_VAR)/%.obj, $(libpixman_sources))
# targets
all: inform informMMX informSSE2 informSSSE3 $(CFG_VAR)/$(LIBRARY).lib
informMMX:
ifneq ($(MMX),off)
ifneq ($(MMX),on)
ifneq ($(MMX),)
@echo "Invalid specified MMX option : "$(MMX_VAR)"."
@echo
@echo "Possible choices for MMX are 'on' or 'off'"
@exit 1
endif
@echo "Setting MMX flag to default value 'on'... (use MMX=on or MMX=off)"
endif
endif
informSSE2:
ifneq ($(SSE2),off)
ifneq ($(SSE2),on)
ifneq ($(SSE2),)
@echo "Invalid specified SSE option : "$(SSE2)"."
@echo
@echo "Possible choices for SSE2 are 'on' or 'off'"
@exit 1
endif
@echo "Setting SSE2 flag to default value 'on'... (use SSE2=on or SSE2=off)"
endif
endif
informSSSE3:
ifneq ($(SSSE3),off)
ifneq ($(SSSE3),on)
ifneq ($(SSSE3),)
@echo "Invalid specified SSE option : "$(SSSE3)"."
@echo
@echo "Possible choices for SSSE3 are 'on' or 'off'"
@exit 1
endif
@echo "Setting SSSE3 flag to default value 'on'... (use SSSE3=on or SSSE3=off)"
endif
endif
# pixman linking
$(CFG_VAR)/$(LIBRARY).lib: $(OBJECTS)
@$(AR) $(PIXMAN_ARFLAGS) -OUT:$@ $^
.PHONY: all informMMX informSSE2 informSSSE3

View File

@ -1,77 +0,0 @@
/* WARNING: This file is generated by make-blue-noise.c
* Please edit that file instead of this one.
*/
#ifndef BLUE_NOISE_64X64_H
#define BLUE_NOISE_64X64_H
#include <stdint.h>
static const uint16_t dither_blue_noise_64x64[4096] = {
3039, 1368, 3169, 103, 2211, 1248, 2981, 668, 2633, 37, 3963, 2903, 384, 2564, 3115, 1973, 3348, 830, 2505, 1293, 3054, 1060, 1505, 3268, 400, 1341, 593, 3802, 3384, 429, 4082, 1411, 2503, 3863, 126, 1292, 1887, 2855, 205, 2094, 2977, 1899, 3924, 356, 3088, 2500, 3942, 1409, 2293, 1734, 3732, 1291, 3227, 277, 2054, 786, 2871, 411, 2425, 1678, 3986, 455, 2879, 2288,
388, 1972, 3851, 778, 2768, 3697, 944, 2123, 1501, 3533, 937, 1713, 1381, 3888, 156, 1242, 516, 2888, 1607, 3676, 632, 2397, 3804, 2673, 1898, 3534, 2593, 1777, 1170, 2299, 3013, 1838, 523, 3053, 1647, 3601, 3197, 959, 1520, 3633, 893, 2437, 3367, 2187, 1258, 137, 1965, 401, 3546, 643, 3087, 2498, 733, 2786, 3371, 4053, 1266, 1977, 3663, 183, 2570, 2107, 1183, 3708,
907, 2473, 1151, 3363, 1527, 1902, 232, 3903, 3060, 496, 2486, 3206, 2165, 861, 2387, 3653, 2101, 3972, 132, 2162, 3437, 1827, 215, 895, 3114, 271, 969, 2932, 197, 1598, 878, 3696, 1140, 2120, 904, 2431, 302, 3846, 2675, 481, 3187, 66, 1440, 650, 3833, 2826, 3435, 901, 2936, 2111, 250, 1875, 3609, 1174, 1747, 162, 2346, 3420, 913, 3172, 1383, 752, 3298, 1735,
3540, 2938, 249, 2324, 526, 3099, 2561, 1324, 2347, 1861, 1200, 3702, 257, 3442, 1514, 2999, 992, 1766, 2735, 1163, 478, 2943, 1279, 3635, 2177, 1464, 3672, 2386, 3871, 3340, 2690, 64, 3489, 2811, 3999, 633, 1948, 1243, 2269, 1807, 1143, 2750, 3729, 1790, 2363, 1053, 1537, 2636, 4065, 1076, 1476, 3869, 450, 2200, 2676, 658, 2979, 1548, 544, 1913, 2838, 3911, 116, 2698,
517, 1295, 3997, 1739, 3665, 1083, 3509, 599, 3400, 118, 2956, 720, 2689, 1907, 567, 2523, 284, 3397, 711, 3219, 2450, 3985, 1665, 2549, 562, 3011, 1855, 729, 1355, 528, 1908, 2456, 1384, 337, 1540, 2654, 3138, 3513, 703, 4080, 3314, 2047, 855, 3037, 209, 3317, 577, 1828, 17, 2336, 3193, 2748, 962, 3441, 1450, 3246, 1075, 3878, 2615, 3497, 1033, 2310, 1442, 2183,
1654, 3254, 2061, 738, 2832, 148, 2030, 1670, 909, 3850, 2109, 1533, 4046, 1085, 3098, 3897, 1378, 2248, 3829, 1495, 1966, 23, 797, 3427, 1124, 4057, 95, 2787, 2190, 3074, 3950, 742, 3194, 1999, 3386, 1113, 16, 1657, 2804, 201, 1543, 383, 2559, 1325, 3604, 2068, 2493, 3771, 1284, 3460, 710, 1716, 2447, 80, 3811, 2032, 347, 2227, 15, 1689, 397, 3084, 662, 3798,
973, 43, 2608, 3143, 1459, 2423, 4066, 2770, 3191, 1283, 2630, 314, 3235, 2289, 72, 1822, 2840, 924, 350, 2653, 1057, 3715, 2235, 2775, 346, 2083, 1553, 3292, 1081, 274, 1686, 1188, 2327, 3743, 578, 2234, 3916, 2519, 1011, 3056, 2207, 3438, 3890, 537, 1617, 837, 3094, 373, 2795, 1980, 276, 3951, 1353, 3015, 844, 1724, 3651, 2923, 1316, 4092, 2504, 3627, 1936, 2854,
2461, 3929, 1193, 421, 3746, 820, 1180, 286, 2261, 532, 3625, 1812, 802, 1327, 3527, 670, 3730, 2025, 3124, 3565, 529, 2960, 1769, 1390, 3196, 2494, 3756, 796, 3618, 2602, 3463, 2847, 166, 953, 1745, 2900, 438, 2070, 1418, 3741, 639, 1205, 1891, 2882, 2282, 4012, 1182, 1696, 3630, 951, 2904, 2170, 3530, 375, 2320, 2742, 1132, 701, 3216, 2023, 847, 1230, 310, 3431,
770, 1961, 3531, 1702, 2181, 3370, 1877, 3072, 1571, 3389, 1071, 2415, 3782, 2803, 1610, 2454, 1211, 182, 1655, 2322, 1282, 3372, 287, 3935, 704, 1232, 415, 1910, 2286, 1399, 556, 1964, 4068, 2444, 3605, 1272, 3345, 816, 3526, 256, 2402, 2777, 955, 345, 3289, 111, 2727, 635, 2396, 1488, 3331, 600, 1032, 1575, 4026, 515, 3507, 2433, 1605, 460, 3364, 2783, 1810, 1397,
2334, 223, 2945, 688, 2533, 99, 2705, 624, 3944, 2073, 46, 2978, 508, 2132, 269, 3173, 3453, 2631, 4076, 694, 1892, 2586, 972, 2178, 3470, 1695, 2849, 3141, 77, 3884, 994, 3029, 1536, 673, 3083, 124, 2583, 1722, 2821, 1944, 4027, 1661, 3176, 3728, 1337, 1813, 3503, 2035, 3930, 157, 2537, 1865, 3096, 2646, 1941, 3252, 1449, 135, 2836, 3758, 2139, 84, 3678, 3106,
3862, 1545, 3307, 1320, 3955, 1031, 3664, 1306, 2460, 776, 1487, 3294, 1187, 3990, 1903, 1021, 549, 1484, 943, 3027, 97, 3853, 1499, 2880, 198, 2575, 3995, 1089, 1587, 2475, 3282, 339, 2657, 1158, 2105, 1493, 3943, 580, 3232, 1287, 846, 48, 2480, 2112, 771, 2534, 459, 3134, 850, 1298, 3790, 325, 3652, 1249, 193, 940, 2202, 3895, 1829, 911, 1366, 2577, 1069, 534,
2104, 1009, 2667, 392, 1983, 2917, 1645, 324, 3439, 2869, 3705, 1767, 2592, 756, 2916, 3683, 2276, 2850, 2053, 3594, 2403, 3181, 634, 3699, 1933, 906, 519, 2150, 3673, 764, 1770, 2220, 3795, 3336, 502, 3547, 2339, 1110, 301, 2210, 3354, 3643, 569, 1518, 2940, 3973, 1138, 1613, 2773, 2127, 2983, 1671, 769, 2161, 3800, 2730, 3127, 1179, 533, 3259, 2284, 4014, 1651, 2820,
3566, 653, 1839, 3455, 2399, 789, 3149, 2244, 1863, 1099, 474, 2307, 158, 3541, 1312, 1711, 0, 3902, 360, 1629, 1091, 395, 1781, 1191, 2374, 3353, 1419, 3225, 206, 2931, 3553, 1046, 54, 1646, 2470, 910, 1860, 3137, 3770, 2635, 1562, 2809, 1215, 3788, 222, 2199, 3335, 67, 3606, 524, 1001, 3309, 2410, 3473, 591, 1619, 291, 2502, 3629, 2891, 335, 741, 3378, 168,
2384, 3129, 4051, 22, 1444, 3613, 543, 3893, 186, 2665, 4062, 933, 3058, 2142, 449, 2711, 3224, 849, 1330, 3349, 2195, 2670, 3484, 2993, 32, 3774, 2722, 1859, 2548, 1268, 583, 2027, 3165, 2807, 4029, 227, 2897, 1434, 721, 1816, 195, 905, 2066, 3258, 1754, 970, 2674, 1880, 2338, 3915, 1485, 2660, 14, 1313, 2914, 2046, 4074, 791, 1917, 1301, 1725, 2687, 2019, 1443,
418, 1186, 1664, 2859, 1049, 2056, 2741, 1226, 1589, 3186, 2042, 1377, 3449, 1574, 3941, 1063, 1930, 2501, 3751, 2930, 671, 4031, 888, 2081, 1544, 684, 1117, 351, 4052, 1698, 2393, 3881, 1439, 785, 1277, 2013, 3488, 441, 2459, 3980, 3061, 3481, 2543, 419, 3020, 609, 3515, 1350, 799, 2878, 348, 2034, 3966, 1824, 950, 3281, 1394, 2239, 3452, 55, 3922, 3119, 892, 3785,
3023, 2140, 782, 2492, 3817, 241, 3355, 2424, 856, 3639, 612, 2556, 245, 2858, 705, 2316, 3562, 495, 1748, 128, 1912, 1454, 280, 2552, 3905, 3130, 2274, 3472, 834, 3055, 240, 2692, 471, 2272, 3301, 2632, 1080, 3693, 2136, 1029, 1364, 590, 1611, 4067, 1190, 2360, 3827, 261, 3180, 1768, 3471, 1103, 3003, 520, 3674, 151, 2571, 555, 3033, 982, 2353, 504, 1259, 2555,
149, 3889, 3380, 493, 3178, 1681, 663, 1924, 2990, 49, 1792, 3861, 1192, 1987, 3273, 297, 1457, 3043, 1177, 2292, 3249, 2829, 3682, 1154, 1758, 428, 2872, 1993, 1500, 3703, 1129, 3421, 1840, 3754, 163, 659, 1733, 3182, 38, 2875, 1957, 3614, 2237, 78, 1873, 2801, 1513, 2121, 1074, 2516, 667, 3710, 1429, 2430, 2088, 2830, 1072, 3557, 1531, 2733, 1955, 3286, 3590, 1826,
2778, 1068, 1932, 1452, 2279, 1185, 3564, 3952, 1391, 2726, 3313, 2331, 870, 3709, 1674, 2772, 4085, 808, 2596, 3848, 927, 538, 2335, 3334, 773, 3597, 1347, 109, 2663, 608, 2108, 2994, 936, 1524, 2922, 3968, 2422, 1467, 845, 3870, 321, 2704, 1073, 3308, 3680, 823, 430, 3375, 4030, 112, 2171, 2695, 267, 3374, 731, 1627, 3919, 1871, 352, 3839, 1370, 234, 794, 1532,
3245, 647, 3575, 74, 3045, 2766, 285, 2174, 498, 1059, 1551, 385, 3125, 2598, 143, 1128, 2095, 3395, 318, 1590, 3524, 1345, 1969, 242, 2759, 2092, 947, 3926, 3244, 2356, 1658, 6, 3593, 2554, 1172, 1995, 371, 2755, 3417, 2294, 1570, 3164, 748, 2517, 1401, 3111, 2420, 1662, 2910, 1276, 3276, 854, 1804, 4000, 1253, 2987, 229, 2344, 3184, 649, 2196, 2921, 4095, 2389,
1289, 2193, 2579, 4023, 757, 1858, 986, 3199, 2514, 3475, 4021, 2154, 651, 1432, 3468, 2404, 574, 1799, 3105, 2145, 86, 2614, 3218, 1565, 4088, 2481, 3079, 1815, 323, 1212, 3837, 759, 2159, 435, 3223, 784, 3659, 1114, 1888, 550, 1221, 3786, 1803, 499, 2117, 185, 3763, 942, 589, 2001, 3838, 1483, 3154, 2256, 468, 2544, 3403, 898, 1208, 2610, 3622, 967, 1929, 378,
3781, 220, 1656, 1115, 3347, 2428, 3822, 1577, 712, 1959, 110, 2765, 1762, 3854, 979, 2928, 3714, 1371, 746, 3969, 2884, 975, 3779, 641, 1142, 159, 1460, 702, 3485, 2866, 2495, 3330, 1305, 3937, 1635, 2229, 2962, 146, 4055, 3091, 2417, 100, 3508, 2933, 4006, 1167, 1920, 2760, 3552, 2545, 433, 2845, 142, 1056, 1886, 3616, 1435, 2099, 3803, 1749, 27, 1446, 3350, 2843,
884, 3310, 2948, 2103, 447, 1351, 187, 2895, 3655, 1256, 3036, 932, 3325, 2257, 451, 1915, 40, 2780, 2438, 1112, 1814, 423, 2290, 1905, 2898, 3419, 2306, 3760, 1938, 486, 1019, 1791, 3010, 2628, 203, 3408, 1269, 2507, 1606, 862, 2779, 2078, 952, 1529, 2638, 708, 3332, 1413, 2, 1726, 1156, 3500, 2392, 3791, 3076, 812, 107, 2861, 501, 3050, 3487, 2455, 594, 1731,
2685, 1498, 680, 3908, 2621, 3529, 1786, 2236, 342, 2569, 1526, 3722, 230, 1290, 3203, 3947, 1609, 3516, 467, 3267, 3685, 1461, 3140, 3569, 367, 1759, 928, 2754, 1332, 2219, 4034, 260, 655, 1984, 978, 3814, 617, 2086, 3525, 279, 3841, 1373, 3361, 319, 2251, 3066, 407, 2382, 3918, 3133, 2168, 762, 1523, 507, 2641, 1677, 4025, 2413, 1584, 793, 2049, 1109, 3962, 2218,
1194, 3692, 266, 1687, 981, 3103, 740, 3983, 1005, 3434, 570, 2383, 1942, 2718, 676, 2462, 1007, 2089, 1308, 2222, 233, 2568, 829, 1241, 2669, 3987, 514, 3303, 69, 3142, 1603, 3560, 2295, 3288, 1497, 2696, 1764, 2865, 1058, 3271, 1914, 477, 2529, 3927, 1736, 1273, 3752, 2029, 1012, 565, 2798, 4078, 1949, 3305, 1175, 2179, 380, 3366, 1195, 3849, 2637, 416, 2959, 125,
3396, 2467, 2036, 3234, 2340, 68, 2819, 1436, 2011, 3139, 1704, 4073, 860, 3582, 1468, 2969, 211, 3157, 4056, 866, 2935, 2000, 3923, 31, 2157, 1477, 2429, 1147, 3792, 2557, 774, 2802, 1153, 3747, 464, 3192, 42, 3904, 539, 1474, 2283, 803, 2876, 1061, 75, 3477, 747, 2893, 1538, 3626, 251, 1322, 2506, 189, 2791, 3667, 939, 2991, 1971, 175, 3195, 1416, 3648, 1857,
3052, 454, 851, 3789, 1271, 1906, 3694, 2484, 406, 2757, 26, 1189, 2909, 296, 2215, 3784, 1864, 637, 2715, 1673, 3445, 581, 1572, 3059, 3469, 761, 2984, 1737, 2058, 440, 1414, 1921, 121, 2527, 894, 2223, 1302, 2377, 3077, 2666, 3759, 3198, 1811, 3661, 2166, 2731, 1883, 359, 3285, 2458, 1805, 3459, 926, 3834, 675, 1893, 1496, 2612, 657, 3523, 1763, 2354, 564, 961,
1367, 3977, 1588, 2714, 322, 3446, 1088, 625, 3887, 1354, 3535, 2090, 3316, 1760, 1127, 483, 3491, 1421, 2301, 94, 1202, 3740, 2311, 1014, 1878, 3836, 180, 3412, 991, 2868, 3953, 3450, 3081, 1632, 4071, 1882, 3543, 726, 1719, 179, 1171, 364, 1420, 622, 3090, 1490, 946, 4007, 2212, 1102, 619, 2739, 2189, 1669, 2937, 3426, 39, 3940, 2191, 1264, 887, 4091, 2792, 2135,
4, 2883, 2281, 631, 3044, 1641, 2232, 3243, 1773, 2319, 827, 2591, 629, 3938, 2426, 3222, 2629, 1044, 3879, 3293, 1952, 2749, 275, 2590, 472, 1372, 2496, 660, 3669, 2264, 208, 915, 2167, 561, 2828, 307, 3265, 1104, 3964, 2155, 3425, 1951, 4077, 2391, 283, 3387, 2581, 115, 1415, 3069, 3896, 141, 3158, 1214, 442, 2405, 1349, 3085, 425, 2528, 3002, 312, 1602, 3588,
1137, 3323, 1963, 1002, 3578, 2521, 127, 925, 2970, 273, 3737, 1573, 167, 2863, 1509, 800, 147, 2059, 2942, 409, 921, 3151, 1451, 3909, 3333, 2844, 2096, 1512, 3136, 1210, 1798, 2709, 1331, 3586, 1034, 1521, 2441, 2926, 488, 2585, 775, 3031, 2693, 879, 3602, 1173, 2028, 3654, 2781, 841, 1975, 1507, 3646, 768, 3991, 2012, 996, 3544, 1666, 3810, 1990, 3360, 753, 2597,
3736, 304, 1473, 3828, 485, 1334, 4008, 2072, 3495, 1136, 2806, 2004, 3236, 1010, 2130, 3819, 1750, 3567, 644, 2515, 1794, 3636, 698, 2137, 1162, 832, 3761, 326, 2613, 513, 3302, 3820, 357, 3163, 2259, 3733, 101, 1922, 1386, 3587, 1640, 28, 1286, 2141, 1761, 2918, 693, 1639, 457, 3250, 2434, 365, 2599, 1729, 3284, 2643, 306, 2793, 689, 1090, 104, 1309, 2305, 1831,
2776, 859, 2446, 2915, 1778, 3337, 2677, 614, 1508, 2409, 469, 4033, 1321, 3563, 402, 3131, 2720, 1093, 1569, 4042, 1229, 2277, 216, 3046, 1817, 57, 3006, 1684, 4059, 2016, 795, 2440, 1652, 1960, 610, 2763, 920, 3864, 3110, 1026, 2326, 3762, 3233, 521, 3856, 173, 2457, 3939, 2138, 1262, 3572, 989, 3021, 2238, 119, 1445, 3832, 1809, 2297, 3467, 2700, 3684, 3102, 394,
4036, 2050, 3256, 89, 2198, 1079, 248, 1845, 3805, 3104, 880, 1779, 2688, 717, 2373, 1375, 262, 2249, 3071, 13, 2813, 3429, 1600, 3984, 2416, 3603, 1299, 2298, 998, 3492, 1393, 2951, 10, 4009, 1247, 3462, 1679, 2204, 414, 2736, 316, 1894, 2816, 1050, 3373, 1462, 3107, 817, 3464, 21, 1835, 4070, 568, 1178, 3718, 875, 3168, 466, 2974, 1458, 2084, 616, 1564, 1018,
1693, 546, 1244, 3899, 716, 3160, 3608, 2877, 1220, 334, 3443, 2270, 44, 3000, 1843, 3928, 3405, 766, 3686, 2040, 587, 993, 2647, 387, 930, 2753, 630, 3274, 150, 2808, 453, 3638, 1092, 2352, 3030, 239, 2562, 700, 3240, 1257, 4016, 730, 1515, 2203, 2551, 417, 1866, 1123, 2348, 2902, 1550, 2678, 2075, 3238, 1630, 2531, 2115, 1255, 4054, 840, 290, 3874, 2477, 3399,
2250, 3577, 2817, 1626, 2576, 1356, 2315, 792, 2087, 2618, 1612, 3855, 1263, 3637, 1036, 494, 1535, 2553, 1198, 1715, 3867, 3170, 1359, 1954, 3483, 1539, 2069, 3886, 1772, 2487, 1534, 2045, 3242, 806, 1578, 2018, 3948, 1423, 3596, 2076, 2466, 3424, 139, 3688, 871, 4049, 2852, 3342, 547, 3719, 327, 852, 3505, 207, 2794, 542, 3600, 45, 2411, 3324, 1788, 3012, 1235, 61,
2655, 917, 253, 1986, 3738, 313, 1706, 4072, 120, 3229, 957, 597, 2024, 3262, 2453, 2857, 2002, 3190, 210, 2784, 2206, 300, 2400, 3766, 553, 3152, 218, 1150, 2988, 883, 3753, 627, 2664, 3831, 437, 3385, 1008, 2957, 60, 1636, 891, 2899, 1776, 3062, 1315, 2026, 194, 1643, 2079, 1296, 3201, 2465, 1379, 1927, 3898, 1125, 1847, 2846, 1552, 1028, 2725, 2169, 787, 3202,
1441, 3982, 3032, 1052, 3251, 605, 2639, 3073, 1431, 3642, 2329, 2949, 341, 1634, 833, 129, 4020, 916, 3571, 669, 1506, 3411, 821, 2856, 1207, 2337, 2683, 3448, 340, 2214, 3128, 235, 1738, 1288, 2833, 2419, 606, 1884, 2668, 552, 3765, 1176, 399, 2302, 596, 3591, 2634, 767, 3845, 2767, 995, 3967, 491, 3057, 814, 2300, 3422, 691, 3797, 254, 3645, 509, 3478, 1836,
2119, 475, 2445, 1525, 2175, 3539, 914, 1926, 473, 1157, 1800, 3971, 2701, 3739, 2129, 3486, 1333, 1784, 2366, 2982, 1070, 4089, 1802, 73, 1642, 3958, 835, 1837, 1480, 4043, 1217, 2469, 3416, 2113, 88, 3668, 1240, 3255, 3920, 2355, 3167, 2003, 2645, 3936, 3228, 1592, 1144, 3474, 2394, 79, 1820, 2241, 1594, 3656, 2584, 153, 1448, 3034, 2005, 2511, 1692, 1335, 3913, 217,
2822, 3391, 745, 3813, 192, 1274, 2941, 3847, 2489, 3440, 744, 161, 1422, 1086, 572, 3004, 2617, 338, 3807, 2031, 236, 2472, 3065, 2098, 3358, 362, 2163, 3574, 497, 2788, 1970, 948, 3885, 685, 3100, 1712, 2228, 292, 1408, 1016, 164, 3537, 1417, 941, 34, 2172, 3001, 358, 1491, 3147, 699, 3356, 258, 1149, 2946, 1787, 3931, 382, 1146, 3291, 818, 2890, 2379, 1096,
3679, 1328, 1901, 3162, 2747, 1730, 2253, 5, 1556, 2818, 2093, 3166, 2522, 3410, 2287, 1701, 956, 3237, 620, 1596, 3300, 1307, 511, 3701, 1020, 2939, 1362, 2532, 3208, 749, 3641, 160, 1522, 2624, 1095, 4086, 826, 2841, 3583, 2173, 1727, 723, 2925, 1911, 2482, 3726, 863, 1962, 4028, 1111, 2835, 3773, 2449, 2022, 582, 3278, 923, 2619, 2152, 4039, 92, 1934, 3145, 677,
2530, 53, 2303, 1003, 458, 3989, 739, 3321, 1064, 369, 3556, 877, 1900, 426, 3876, 1, 3617, 2106, 1197, 2805, 3634, 857, 2706, 1504, 2418, 682, 3868, 20, 1139, 1688, 2333, 3311, 2907, 1945, 265, 2385, 3433, 1601, 636, 2620, 3095, 4044, 386, 3382, 1184, 527, 2814, 3414, 2342, 465, 1889, 1343, 874, 3479, 1502, 2233, 3689, 1385, 559, 2745, 1463, 3465, 376, 1718,
3217, 4045, 1580, 3612, 2525, 1228, 3018, 1958, 3725, 2358, 1361, 3996, 1581, 3063, 1224, 2737, 1475, 2442, 3946, 191, 1796, 2128, 3975, 134, 1916, 3318, 1597, 2071, 3749, 2672, 403, 1278, 602, 3745, 3220, 1374, 445, 2064, 3830, 243, 1252, 2390, 1563, 2724, 3875, 1818, 1346, 165, 1650, 3264, 2680, 117, 2998, 4081, 343, 2799, 9, 3122, 1743, 3724, 1040, 2231, 3842, 1209,
900, 398, 2851, 697, 1797, 3482, 293, 2679, 1649, 566, 2954, 91, 2697, 714, 2060, 3211, 781, 480, 3040, 1038, 2611, 666, 2989, 3458, 1201, 2796, 548, 2975, 839, 3121, 1850, 4001, 2208, 1631, 790, 2558, 2972, 1148, 3213, 1849, 3624, 971, 2102, 108, 772, 3101, 2589, 3777, 1042, 656, 3907, 2097, 1615, 2540, 805, 1935, 1231, 3494, 2451, 268, 2995, 750, 2682, 2020,
3024, 1392, 2124, 3279, 106, 2217, 1387, 822, 3214, 3825, 2160, 1000, 2395, 3691, 228, 4038, 1872, 3413, 1608, 2225, 3536, 303, 1653, 886, 2541, 224, 4037, 2252, 1428, 172, 3504, 958, 2848, 113, 3628, 1834, 3979, 19, 2317, 779, 2797, 518, 3174, 3549, 1482, 2266, 444, 2014, 3555, 2439, 1213, 3113, 535, 1135, 3204, 3858, 2309, 931, 623, 2009, 3359, 1566, 140, 3550,
1808, 3872, 2488, 1152, 3764, 2892, 3960, 2412, 353, 1223, 1825, 3444, 3116, 1717, 1082, 2313, 1280, 2661, 82, 3852, 1389, 3200, 2330, 3812, 2038, 3581, 1728, 1039, 3339, 2427, 586, 2580, 1238, 3328, 2280, 1047, 595, 2662, 1363, 3338, 1620, 3934, 2497, 1881, 1054, 3954, 3215, 864, 2887, 1801, 320, 3519, 2378, 3704, 1753, 424, 2958, 1660, 4005, 2601, 1116, 3912, 2381, 573,
2740, 200, 828, 1667, 432, 1931, 1035, 1616, 3598, 2640, 728, 264, 1437, 557, 3501, 2966, 372, 3734, 974, 1978, 758, 2719, 1145, 452, 1433, 725, 2681, 408, 3843, 1918, 1547, 3906, 1996, 503, 1456, 3019, 3493, 1700, 3742, 355, 2134, 176, 1311, 615, 2867, 315, 1680, 1314, 8, 3297, 1494, 783, 1950, 83, 2656, 1382, 3561, 138, 2834, 1404, 330, 1904, 3156, 1027,
1357, 3381, 3041, 3666, 2729, 734, 3415, 177, 3051, 2021, 4079, 2823, 3775, 2186, 2616, 869, 1668, 3148, 2367, 3315, 393, 4075, 1870, 2920, 3343, 2362, 3188, 1303, 2782, 825, 3171, 259, 2905, 3717, 2538, 184, 2074, 838, 2860, 2407, 1024, 3496, 3008, 3706, 1985, 2349, 3623, 2582, 4058, 2184, 2694, 3873, 2964, 990, 3346, 690, 2033, 1066, 2201, 3490, 2971, 718, 3700, 2188,
4061, 391, 1989, 2325, 1430, 3150, 2125, 2526, 592, 1403, 976, 2351, 1165, 1851, 114, 3921, 2063, 613, 1358, 2785, 1623, 2254, 25, 3542, 1045, 246, 1852, 3554, 87, 2243, 3615, 1169, 727, 1705, 968, 3957, 3185, 1251, 500, 4063, 1751, 2622, 842, 1519, 90, 3393, 819, 490, 1874, 999, 571, 1275, 2271, 1586, 4040, 2448, 3126, 3731, 436, 885, 1708, 2421, 24, 1599,
889, 2563, 1199, 645, 70, 4013, 1237, 3723, 1694, 3499, 3, 3266, 484, 2997, 3390, 1233, 2842, 3687, 152, 3480, 1084, 3698, 881, 2490, 1542, 3992, 2209, 692, 1690, 3022, 1470, 2625, 2114, 3512, 2359, 381, 2684, 1897, 3368, 1395, 3080, 289, 2065, 3981, 2758, 1141, 3097, 1472, 2870, 3352, 3707, 225, 3159, 505, 1895, 214, 1222, 1774, 2686, 3978, 3275, 1196, 3518, 2825,
3270, 1720, 3796, 3466, 2650, 1841, 298, 899, 2862, 2091, 2671, 1744, 3735, 801, 1560, 349, 2262, 903, 1833, 2524, 512, 3117, 1793, 2827, 476, 3038, 1216, 2550, 3826, 980, 431, 4048, 35, 2992, 1265, 1595, 765, 3675, 76, 2247, 696, 3456, 1254, 2452, 664, 1757, 2133, 3750, 145, 2332, 1554, 1981, 3580, 2712, 868, 3640, 2919, 638, 2275, 1427, 309, 2595, 2006, 492,
2226, 178, 2911, 836, 1528, 3028, 2240, 3327, 404, 3970, 707, 1294, 2464, 2131, 4032, 2600, 3319, 1406, 2913, 3974, 2156, 1425, 221, 3877, 2017, 811, 3662, 272, 3287, 1988, 2408, 3357, 1746, 598, 3239, 3823, 2182, 2934, 1078, 2604, 3840, 1697, 2906, 413, 3210, 3880, 331, 2644, 1260, 848, 3042, 2535, 1077, 1438, 3261, 2365, 1561, 3799, 85, 3082, 1876, 674, 3932, 1101,
3644, 1344, 1943, 2401, 390, 3835, 1048, 2572, 1541, 1133, 3075, 3584, 308, 2889, 1065, 1869, 601, 3783, 282, 1181, 736, 3312, 2368, 1126, 3383, 1675, 2734, 1426, 628, 2873, 1317, 843, 2717, 2048, 1004, 2536, 333, 1782, 3295, 1517, 219, 2153, 815, 3502, 1579, 2268, 987, 3409, 1780, 4018, 354, 665, 3914, 47, 1956, 456, 1006, 2010, 3406, 1130, 3621, 2894, 1549, 3092,
2485, 640, 3993, 3179, 1270, 3436, 585, 1925, 3757, 2304, 136, 1976, 1486, 646, 3520, 50, 3155, 1637, 2435, 3522, 1937, 2756, 3748, 661, 2224, 58, 3230, 2357, 1830, 3892, 170, 3607, 1447, 3949, 190, 3392, 1336, 584, 4010, 918, 3016, 3670, 1155, 2406, 52, 1304, 3009, 607, 2085, 2699, 3205, 1848, 2291, 3402, 2764, 3865, 3048, 2508, 735, 2710, 443, 2341, 897, 263,
1785, 2769, 983, 56, 2197, 1685, 2703, 202, 2944, 810, 3377, 2626, 3787, 3047, 2055, 1236, 2752, 2122, 945, 3093, 96, 1624, 439, 3014, 1388, 4015, 977, 448, 3506, 1098, 2242, 3026, 506, 2361, 2952, 1862, 3619, 2790, 1992, 2483, 525, 1868, 2652, 4093, 1998, 3595, 2478, 3816, 122, 1412, 929, 3716, 1166, 1648, 813, 1300, 199, 1489, 3998, 1771, 1310, 3808, 2052, 3423,
434, 3712, 1625, 3558, 2955, 853, 4019, 1348, 3511, 1732, 1246, 487, 934, 1672, 2510, 3965, 788, 3711, 396, 1369, 4090, 1055, 2603, 1879, 3528, 2518, 2067, 3005, 1516, 2588, 751, 1740, 3418, 1131, 1576, 686, 2296, 1118, 18, 3263, 1365, 3401, 294, 737, 3177, 410, 867, 1633, 2963, 3579, 2375, 252, 2881, 479, 2471, 3576, 2180, 3306, 332, 2255, 3035, 41, 2648, 1396,
2929, 2230, 1219, 2512, 446, 2008, 3189, 2388, 626, 2164, 2831, 4047, 2376, 174, 3272, 368, 1469, 3226, 2578, 1991, 2874, 2263, 3681, 876, 188, 1239, 683, 3776, 226, 3183, 4083, 2148, 63, 2649, 3859, 299, 3086, 3933, 1585, 2185, 3767, 988, 1707, 2908, 1407, 1844, 2771, 2245, 1161, 560, 1755, 3376, 2051, 4064, 3135, 1832, 652, 2853, 1051, 3649, 760, 3290, 1105, 3945,
872, 154, 3207, 713, 3780, 1453, 281, 1087, 3695, 30, 3299, 1919, 1400, 3551, 1119, 1890, 2314, 618, 1703, 3428, 724, 295, 3146, 1557, 3341, 2896, 1683, 2723, 1974, 1017, 541, 1380, 3720, 804, 3280, 2082, 997, 2567, 777, 2961, 213, 2707, 2328, 3632, 1025, 3891, 3304, 255, 4003, 3108, 2587, 1323, 743, 1479, 105, 1013, 3901, 1618, 2044, 2627, 1465, 1846, 576, 1994,
2560, 3521, 1742, 2118, 2800, 3404, 1783, 2609, 2968, 1582, 1022, 412, 2713, 687, 2976, 3857, 2761, 3620, 62, 1108, 3844, 1340, 2100, 540, 2345, 3925, 405, 3457, 1319, 2468, 3362, 2815, 1867, 2372, 1281, 1714, 3690, 482, 3498, 1842, 1285, 3994, 558, 2039, 81, 2499, 678, 1481, 1923, 964, 12, 3824, 2980, 2205, 2762, 3432, 2398, 181, 3247, 462, 4094, 2350, 3589, 3089,
1555, 1094, 4041, 247, 1267, 908, 3959, 2041, 732, 3860, 2343, 3132, 3769, 2144, 1621, 237, 912, 1329, 3025, 2146, 2642, 1775, 3721, 2746, 1121, 1953, 902, 2285, 130, 3671, 1659, 278, 3153, 522, 2721, 123, 2996, 1466, 2380, 377, 3231, 873, 1510, 3476, 3123, 1250, 2147, 3650, 2839, 3451, 2323, 1122, 3545, 379, 1765, 1218, 603, 3768, 1360, 938, 2885, 133, 1245, 363,
2364, 554, 2743, 3344, 2474, 530, 3112, 169, 1297, 3430, 536, 1741, 98, 1043, 2574, 3253, 2246, 1854, 4022, 510, 3283, 204, 858, 3398, 36, 3118, 1478, 3794, 2986, 706, 2176, 922, 3559, 1097, 3976, 3322, 2149, 1160, 2810, 3883, 2007, 2513, 2953, 328, 1721, 3793, 422, 2566, 807, 329, 1638, 1967, 648, 2520, 3727, 3109, 2116, 2927, 2491, 1939, 3365, 1709, 2728, 3815,
2037, 3120, 831, 1405, 1896, 3592, 1622, 2369, 2864, 2151, 1107, 2542, 3532, 1410, 3917, 427, 3568, 709, 2509, 1503, 1037, 2973, 2436, 1604, 4035, 2594, 563, 1819, 2659, 1234, 4004, 2565, 1511, 2273, 1823, 336, 882, 3772, 575, 1628, 171, 3570, 1120, 2260, 2716, 935, 3064, 1806, 1342, 3144, 3900, 2744, 3296, 985, 1546, 238, 896, 1663, 305, 3660, 695, 2213, 960, 3407,
144, 1795, 3894, 2267, 51, 2708, 1023, 3818, 366, 1821, 4087, 2985, 755, 2057, 2912, 949, 1583, 2774, 231, 3447, 2258, 3866, 1982, 672, 1225, 2077, 3320, 1062, 370, 3241, 1968, 7, 3068, 681, 3631, 2573, 1567, 3175, 2321, 1067, 3070, 722, 1856, 3744, 642, 1471, 4084, 131, 3514, 2443, 531, 1227, 155, 2265, 4024, 2658, 3326, 3910, 1168, 3078, 1530, 3956, 489, 1424,
3647, 1203, 420, 2924, 3755, 719, 3248, 1376, 3067, 890, 196, 1559, 3269, 270, 2432, 1885, 3212, 1164, 3778, 1752, 579, 1338, 344, 3585, 3017, 288, 3658, 2371, 3882, 1691, 611, 2789, 3809, 1339, 389, 2950, 2015, 59, 3548, 2751, 2158, 4011, 1352, 29, 3388, 2370, 2812, 1946, 954, 2110, 1558, 2947, 3573, 1909, 1326, 679, 1853, 2312, 551, 2702, 33, 2414, 3209, 2824,
2547, 2143, 3379, 966, 1492, 1979, 2479, 463, 2194, 3657, 2738, 2318, 1261, 3713, 604, 4002, 11, 2192, 2967, 919, 2607, 3369, 2837, 1676, 2539, 984, 1568, 93, 2901, 1318, 3538, 1041, 2216, 1756, 3454, 1030, 4050, 1402, 798, 1723, 311, 3277, 2546, 2886, 2043, 461, 1206, 3677, 361, 3260, 3988, 809, 2605, 470, 3007, 3517, 102, 3221, 1398, 2062, 3611, 1134, 1928, 865,
4060, 621, 1710, 2606, 3510, 317, 4017, 1682, 3329, 1159, 1940, 654, 3461, 1789, 1015, 2691, 1455, 3599, 374, 1947, 4069, 71, 2126, 763, 3961, 2278, 3161, 1997, 824, 2623, 2080, 244, 3257, 780, 2732, 2308, 545, 3351, 2476, 3806, 1204, 588, 1591, 963, 3610, 1699, 754, 3049, 2651, 1106, 65, 2221, 1644, 3821, 1100, 2463, 1614, 3801, 965, 2965, 715, 3394, 1593, 212,
};
#endif /* BLUE_NOISE_64X64_H */

View File

@ -1,679 +0,0 @@
/* Blue noise generation using the void-and-cluster method as described in
*
* The void-and-cluster method for dither array generation
* Ulichney, Robert A (1993)
*
* http://cv.ulichney.com/papers/1993-void-cluster.pdf
*
* Note that running with openmp (-DUSE_OPENMP) will trigger additional
* randomness due to computing reductions in parallel, and is not recommended
* unless generating very large dither arrays.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <stdio.h>
/* Booleans and utility functions */
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
typedef int bool_t;
int
imin (int x, int y)
{
return x < y ? x : y;
}
/* Memory allocation */
void *
malloc_abc (unsigned int a, unsigned int b, unsigned int c)
{
if (a >= INT32_MAX / b)
return NULL;
else if (a * b >= INT32_MAX / c)
return NULL;
else
return malloc (a * b * c);
}
/* Random number generation */
typedef uint32_t xorwow_state_t[5];
uint32_t
xorwow_next (xorwow_state_t *state)
{
uint32_t s = (*state)[0],
t = (*state)[3];
(*state)[3] = (*state)[2];
(*state)[2] = (*state)[1];
(*state)[1] = s;
t ^= t >> 2;
t ^= t << 1;
t ^= s ^ (s << 4);
(*state)[0] = t;
(*state)[4] += 362437;
return t + (*state)[4];
}
float
xorwow_float (xorwow_state_t *s)
{
return (xorwow_next (s) >> 9) / (float)((1 << 23) - 1);
}
/* Floating point matrices
*
* Used to cache the cluster sizes.
*/
typedef struct matrix_t {
int width;
int height;
float *buffer;
} matrix_t;
bool_t
matrix_init (matrix_t *matrix, int width, int height)
{
float *buffer;
if (!matrix)
return FALSE;
buffer = malloc_abc (width, height, sizeof (float));
if (!buffer)
return FALSE;
matrix->buffer = buffer;
matrix->width = width;
matrix->height = height;
return TRUE;
}
bool_t
matrix_copy (matrix_t *dst, matrix_t const *src)
{
float *srcbuf = src->buffer,
*srcend = src->buffer + src->width * src->height,
*dstbuf = dst->buffer;
if (dst->width != src->width || dst->height != src->height)
return FALSE;
while (srcbuf < srcend)
*dstbuf++ = *srcbuf++;
return TRUE;
}
float *
matrix_get (matrix_t *matrix, int x, int y)
{
return &matrix->buffer[y * matrix->width + x];
}
void
matrix_destroy (matrix_t *matrix)
{
free (matrix->buffer);
}
/* Binary patterns */
typedef struct pattern_t {
int width;
int height;
bool_t *buffer;
} pattern_t;
bool_t
pattern_init (pattern_t *pattern, int width, int height)
{
bool_t *buffer;
if (!pattern)
return FALSE;
buffer = malloc_abc (width, height, sizeof (bool_t));
if (!buffer)
return FALSE;
pattern->buffer = buffer;
pattern->width = width;
pattern->height = height;
return TRUE;
}
bool_t
pattern_copy (pattern_t *dst, pattern_t const *src)
{
bool_t *srcbuf = src->buffer,
*srcend = src->buffer + src->width * src->height,
*dstbuf = dst->buffer;
if (dst->width != src->width || dst->height != src->height)
return FALSE;
while (srcbuf < srcend)
*dstbuf++ = *srcbuf++;
return TRUE;
}
bool_t *
pattern_get (pattern_t *pattern, int x, int y)
{
return &pattern->buffer[y * pattern->width + x];
}
void
pattern_fill_white_noise (pattern_t *pattern, float fraction,
xorwow_state_t *s)
{
bool_t *buffer = pattern->buffer;
bool_t *end = buffer + (pattern->width * pattern->height);
while (buffer < end)
*buffer++ = xorwow_float (s) < fraction;
}
void
pattern_destroy (pattern_t *pattern)
{
free (pattern->buffer);
}
/* Dither arrays */
typedef struct array_t {
int width;
int height;
uint32_t *buffer;
} array_t;
bool_t
array_init (array_t *array, int width, int height)
{
uint32_t *buffer;
if (!array)
return FALSE;
buffer = malloc_abc (width, height, sizeof (uint32_t));
if (!buffer)
return FALSE;
array->buffer = buffer;
array->width = width;
array->height = height;
return TRUE;
}
uint32_t *
array_get (array_t *array, int x, int y)
{
return &array->buffer[y * array->width + x];
}
bool_t
array_save_ppm (array_t *array, const char *filename)
{
FILE *f = fopen(filename, "wb");
int i = 0;
int bpp = 2;
uint8_t buffer[1024];
if (!f)
return FALSE;
if (array->width * array->height - 1 < 256)
bpp = 1;
fprintf(f, "P5 %d %d %d\n", array->width, array->height,
array->width * array->height - 1);
while (i < array->width * array->height)
{
int j = 0;
for (; j < 1024 / bpp && j < array->width * array->height; ++j)
{
uint32_t v = array->buffer[i + j];
if (bpp == 2)
{
buffer[2 * j] = v & 0xff;
buffer[2 * j + 1] = (v & 0xff00) >> 8;
} else {
buffer[j] = v;
}
}
fwrite((void *)buffer, bpp, j, f);
i += j;
}
if (fclose(f) != 0)
return FALSE;
return TRUE;
}
bool_t
array_save (array_t *array, const char *filename)
{
int x, y;
FILE *f = fopen(filename, "wb");
if (!f)
return FALSE;
fprintf (f,
"/* WARNING: This file is generated by make-blue-noise.c\n"
" * Please edit that file instead of this one.\n"
" */\n"
"\n"
"#ifndef BLUE_NOISE_%dX%d_H\n"
"#define BLUE_NOISE_%dX%d_H\n"
"\n"
"#include <stdint.h>\n"
"\n", array->width, array->height, array->width, array->height);
fprintf (f, "static const uint16_t dither_blue_noise_%dx%d[%d] = {\n",
array->width, array->height, array->width * array->height);
for (y = 0; y < array->height; ++y)
{
fprintf (f, " ");
for (x = 0; x < array->width; ++x)
{
if (x != 0)
fprintf (f, ", ");
fprintf (f, "%d", *array_get (array, x, y));
}
fprintf (f, ",\n");
}
fprintf (f, "};\n");
fprintf (f, "\n#endif /* BLUE_NOISE_%dX%d_H */\n",
array->width, array->height);
if (fclose(f) != 0)
return FALSE;
return TRUE;
}
void
array_destroy (array_t *array)
{
free (array->buffer);
}
/* Dither array generation */
bool_t
compute_cluster_sizes (pattern_t *pattern, matrix_t *matrix)
{
int width = pattern->width,
height = pattern->height;
if (matrix->width != width || matrix->height != height)
return FALSE;
int px, py, qx, qy, dx, dy;
float tsqsi = 2.f * 1.5f * 1.5f;
#ifdef USE_OPENMP
#pragma omp parallel for default (none) \
private (py, px, qy, qx, dx, dy) \
shared (height, width, pattern, matrix, tsqsi)
#endif
for (py = 0; py < height; ++py)
{
for (px = 0; px < width; ++px)
{
bool_t pixel = *pattern_get (pattern, px, py);
float dist = 0.f;
for (qx = 0; qx < width; ++qx)
{
dx = imin (abs (qx - px), width - abs (qx - px));
dx = dx * dx;
for (qy = 0; qy < height; ++qy)
{
dy = imin (abs (qy - py), height - abs (qy - py));
dy = dy * dy;
dist += (pixel == *pattern_get (pattern, qx, qy))
* expf (- (dx + dy) / tsqsi);
}
}
*matrix_get (matrix, px, py) = dist;
}
}
return TRUE;
}
bool_t
swap_pixel (pattern_t *pattern, matrix_t *matrix, int x, int y)
{
int width = pattern->width,
height = pattern->height;
bool_t new;
float f,
dist = 0.f,
tsqsi = 2.f * 1.5f * 1.5f;
int px, py, dx, dy;
bool_t b;
new = !*pattern_get (pattern, x, y);
*pattern_get (pattern, x, y) = new;
if (matrix->width != width || matrix->height != height)
return FALSE;
#ifdef USE_OPENMP
#pragma omp parallel for reduction (+:dist) default (none) \
private (px, py, dx, dy, b, f) \
shared (x, y, width, height, pattern, matrix, new, tsqsi)
#endif
for (py = 0; py < height; ++py)
{
dy = imin (abs (py - y), height - abs (py - y));
dy = dy * dy;
for (px = 0; px < width; ++px)
{
dx = imin (abs (px - x), width - abs (px - x));
dx = dx * dx;
b = (*pattern_get (pattern, px, py) == new);
f = expf (- (dx + dy) / tsqsi);
*matrix_get (matrix, px, py) += (2 * b - 1) * f;
dist += b * f;
}
}
*matrix_get (matrix, x, y) = dist;
return TRUE;
}
void
largest_cluster (pattern_t *pattern, matrix_t *matrix,
bool_t pixel, int *xmax, int *ymax)
{
int width = pattern->width,
height = pattern->height;
int x, y;
float vmax = -INFINITY;
#ifdef USE_OPENMP
#pragma omp parallel default (none) \
private (x, y) \
shared (height, width, pattern, matrix, pixel, xmax, ymax, vmax)
#endif
{
int xbest = -1,
ybest = -1;
#ifdef USE_OPENMP
float vbest = -INFINITY;
#pragma omp for reduction (max: vmax) collapse (2)
#endif
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x)
{
if (*pattern_get (pattern, x, y) != pixel)
continue;
if (*matrix_get (matrix, x, y) > vmax)
{
vmax = *matrix_get (matrix, x, y);
#ifdef USE_OPENMP
vbest = vmax;
#endif
xbest = x;
ybest = y;
}
}
}
#ifdef USE_OPENMP
#pragma omp barrier
#pragma omp critical
{
if (vmax == vbest)
{
*xmax = xbest;
*ymax = ybest;
}
}
#else
*xmax = xbest;
*ymax = ybest;
#endif
}
assert (vmax > -INFINITY);
}
void
generate_initial_binary_pattern (pattern_t *pattern, matrix_t *matrix)
{
int xcluster = 0,
ycluster = 0,
xvoid = 0,
yvoid = 0;
for (;;)
{
largest_cluster (pattern, matrix, TRUE, &xcluster, &ycluster);
assert (*pattern_get (pattern, xcluster, ycluster) == TRUE);
swap_pixel (pattern, matrix, xcluster, ycluster);
largest_cluster (pattern, matrix, FALSE, &xvoid, &yvoid);
assert (*pattern_get (pattern, xvoid, yvoid) == FALSE);
swap_pixel (pattern, matrix, xvoid, yvoid);
if (xcluster == xvoid && ycluster == yvoid)
return;
}
}
bool_t
generate_dither_array (array_t *array,
pattern_t const *prototype, matrix_t const *matrix,
pattern_t *temp_pattern, matrix_t *temp_matrix)
{
int width = prototype->width,
height = prototype->height;
int x, y, rank;
int initial_rank = 0;
if (array->width != width || array->height != height)
return FALSE;
// Make copies of the prototype and associated sizes matrix since we will
// trash them
if (!pattern_copy (temp_pattern, prototype))
return FALSE;
if (!matrix_copy (temp_matrix, matrix))
return FALSE;
// Compute initial rank
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x)
{
if (*pattern_get (temp_pattern, x, y))
initial_rank += 1;
*array_get (array, x, y) = 0;
}
}
// Phase 1
for (rank = initial_rank; rank > 0; --rank)
{
largest_cluster (temp_pattern, temp_matrix, TRUE, &x, &y);
swap_pixel (temp_pattern, temp_matrix, x, y);
*array_get (array, x, y) = rank - 1;
}
// Make copies again for phases 2 & 3
if (!pattern_copy (temp_pattern, prototype))
return FALSE;
if (!matrix_copy (temp_matrix, matrix))
return FALSE;
// Phase 2 & 3
for (rank = initial_rank; rank < width * height; ++rank)
{
largest_cluster (temp_pattern, temp_matrix, FALSE, &x, &y);
swap_pixel (temp_pattern, temp_matrix, x, y);
*array_get (array, x, y) = rank;
}
return TRUE;
}
bool_t
generate (int size, xorwow_state_t *s,
char const *c_filename, char const *ppm_filename)
{
bool_t ok = TRUE;
pattern_t prototype, temp_pattern;
array_t array;
matrix_t matrix, temp_matrix;
printf ("Generating %dx%d blue noise...\n", size, size);
if (!pattern_init (&prototype, size, size))
return FALSE;
if (!pattern_init (&temp_pattern, size, size))
{
pattern_destroy (&prototype);
return FALSE;
}
if (!matrix_init (&matrix, size, size))
{
pattern_destroy (&temp_pattern);
pattern_destroy (&prototype);
return FALSE;
}
if (!matrix_init (&temp_matrix, size, size))
{
matrix_destroy (&matrix);
pattern_destroy (&temp_pattern);
pattern_destroy (&prototype);
return FALSE;
}
if (!array_init (&array, size, size))
{
matrix_destroy (&temp_matrix);
matrix_destroy (&matrix);
pattern_destroy (&temp_pattern);
pattern_destroy (&prototype);
return FALSE;
}
printf("Filling initial binary pattern with white noise...\n");
pattern_fill_white_noise (&prototype, .1, s);
printf("Initializing cluster sizes...\n");
if (!compute_cluster_sizes (&prototype, &matrix))
{
fprintf (stderr, "Error while computing cluster sizes\n");
ok = FALSE;
goto out;
}
printf("Generating initial binary pattern...\n");
generate_initial_binary_pattern (&prototype, &matrix);
printf("Generating dither array...\n");
if (!generate_dither_array (&array, &prototype, &matrix,
&temp_pattern, &temp_matrix))
{
fprintf (stderr, "Error while generating dither array\n");
ok = FALSE;
goto out;
}
printf("Saving dither array...\n");
if (!array_save (&array, c_filename))
{
fprintf (stderr, "Error saving dither array\n");
ok = FALSE;
goto out;
}
#if SAVE_PPM
if (!array_save_ppm (&array, ppm_filename))
{
fprintf (stderr, "Error saving dither array PPM\n");
ok = FALSE;
goto out;
}
#else
(void)ppm_filename;
#endif
printf("All done!\n");
out:
array_destroy (&array);
matrix_destroy (&temp_matrix);
matrix_destroy (&matrix);
pattern_destroy (&temp_pattern);
pattern_destroy (&prototype);
return ok;
}
int
main (void)
{
xorwow_state_t s = {1185956906, 12385940, 983948, 349208051, 901842};
if (!generate (64, &s, "blue-noise-64x64.h", "blue-noise-64x64.ppm"))
return -1;
return 0;
}

View File

@ -1,412 +0,0 @@
/* The gcc-provided loongson intrinsic functions are way too fucking broken
* to be of any use, otherwise I'd use them.
*
* - The hardware instructions are very similar to MMX or iwMMXt. Certainly
* close enough that they could have implemented the _mm_*-style intrinsic
* interface and had a ton of optimized code available to them. Instead they
* implemented something much, much worse.
*
* - pshuf takes a dead first argument, causing extra instructions to be
* generated.
*
* - There are no 64-bit shift or logical intrinsics, which means you have
* to implement them with inline assembly, but this is a nightmare because
* gcc doesn't understand that the integer vector datatypes are actually in
* floating-point registers, so you end up with braindead code like
*
* punpcklwd $f9,$f9,$f5
* dmtc1 v0,$f8
* punpcklwd $f19,$f19,$f5
* dmfc1 t9,$f9
* dmtc1 v0,$f9
* dmtc1 t9,$f20
* dmfc1 s0,$f19
* punpcklbh $f20,$f20,$f2
*
* where crap just gets copied back and forth between integer and floating-
* point registers ad nauseum.
*
* Instead of trying to workaround the problems from these crap intrinsics, I
* just implement the _mm_* intrinsics needed for pixman-mmx.c using inline
* assembly.
*/
#include <stdint.h>
/* vectors are stored in 64-bit floating-point registers */
typedef double __m64;
/* having a 32-bit datatype allows us to use 32-bit loads in places like load8888 */
typedef float __m32;
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_setzero_si64 (void)
{
return 0.0;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_add_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("paddh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_add_pi32 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("paddw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_adds_pu16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("paddush %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_adds_pu8 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("paddusb %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_and_si64 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("and %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("pcmpeqw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_empty (void)
{
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_madd_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("pmaddhw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_mulhi_pu16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("pmulhuh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_mullo_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("pmullh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_or_si64 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("or %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_packs_pu16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("packushb %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_packs_pi32 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("packsswh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
(((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_set_pi16 (uint16_t __w3, uint16_t __w2, uint16_t __w1, uint16_t __w0)
{
if (__builtin_constant_p (__w3) &&
__builtin_constant_p (__w2) &&
__builtin_constant_p (__w1) &&
__builtin_constant_p (__w0))
{
uint64_t val = ((uint64_t)__w3 << 48)
| ((uint64_t)__w2 << 32)
| ((uint64_t)__w1 << 16)
| ((uint64_t)__w0 << 0);
return *(__m64 *)&val;
}
else if (__w3 == __w2 && __w2 == __w1 && __w1 == __w0)
{
/* TODO: handle other cases */
uint64_t val = __w3;
uint64_t imm = _MM_SHUFFLE (0, 0, 0, 0);
__m64 ret;
asm("pshufh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (*(__m64 *)&val), "f" (*(__m64 *)&imm)
);
return ret;
} else {
uint64_t val = ((uint64_t)__w3 << 48)
| ((uint64_t)__w2 << 32)
| ((uint64_t)__w1 << 16)
| ((uint64_t)__w0 << 0);
return *(__m64 *)&val;
}
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_set_pi32 (unsigned __i1, unsigned __i0)
{
if (__builtin_constant_p (__i1) &&
__builtin_constant_p (__i0))
{
uint64_t val = ((uint64_t)__i1 << 32)
| ((uint64_t)__i0 << 0);
return *(__m64 *)&val;
}
else if (__i1 == __i0)
{
uint64_t imm = _MM_SHUFFLE (1, 0, 1, 0);
__m64 ret;
asm("pshufh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (*(__m32 *)&__i1), "f" (*(__m64 *)&imm)
);
return ret;
} else {
uint64_t val = ((uint64_t)__i1 << 32)
| ((uint64_t)__i0 << 0);
return *(__m64 *)&val;
}
}
#undef _MM_SHUFFLE
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_shuffle_pi16 (__m64 __m, int64_t __n)
{
__m64 ret;
asm("pshufh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__n)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_slli_pi16 (__m64 __m, int64_t __count)
{
__m64 ret;
asm("psllh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__count)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_slli_si64 (__m64 __m, int64_t __count)
{
__m64 ret;
asm("dsll %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__count)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_srli_pi16 (__m64 __m, int64_t __count)
{
__m64 ret;
asm("psrlh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__count)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_srli_pi32 (__m64 __m, int64_t __count)
{
__m64 ret;
asm("psrlw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__count)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_srli_si64 (__m64 __m, int64_t __count)
{
__m64 ret;
asm("dsrl %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__count)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_sub_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("psubh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("punpckhbh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("punpckhhw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("punpcklbh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
/* Since punpcklbh doesn't care about the high 32-bits, we use the __m32 datatype which
* allows load8888 to use 32-bit loads */
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_unpacklo_pi8_f (__m32 __m1, __m64 __m2)
{
__m64 ret;
asm("punpcklbh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("punpcklhw %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_xor_si64 (__m64 __m1, __m64 __m2)
{
__m64 ret;
asm("xor %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
loongson_extract_pi16 (__m64 __m, int64_t __pos)
{
__m64 ret;
asm("pextrh %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m), "f" (*(__m64 *)&__pos)
);
return ret;
}
extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
loongson_insert_pi16 (__m64 __m1, __m64 __m2, int64_t __pos)
{
__m64 ret;
asm("pinsrh_%3 %0, %1, %2\n\t"
: "=f" (ret)
: "f" (__m1), "f" (__m2), "i" (__pos)
);
return ret;
}

View File

@ -1,115 +0,0 @@
#!/usr/bin/perl -w
use strict;
sub linear_to_srgb
{
my ($c) = @_;
if ($c < 0.0031308)
{
return $c * 12.92;
}
else
{
return 1.055 * $c ** (1.0/2.4) - 0.055;
}
}
sub srgb_to_linear
{
my ($c) = @_;
if ($c < 0.04045)
{
return $c / 12.92;
}
else
{
return (($c + 0.055) / 1.055) ** 2.4
}
}
my @linear_to_srgb;
for my $linear (0 .. 4095)
{
my $srgb = int(linear_to_srgb($linear / 4095.0) * 255.0 + 0.5);
push @linear_to_srgb, $srgb;
}
my @srgb_to_linear;
for my $srgb (0 .. 255)
{
my $linear = int(srgb_to_linear($srgb / 255.0) * 65535.0 + 0.5);
push @srgb_to_linear, $linear;
}
# Ensure that we have a lossless sRGB and back conversion loop.
# some of the darkest shades need a little bias -- maximum is just
# 5 increments out of 16. This gives us useful property with
# least amount of error in the sRGB-to-linear table, and keeps the actual
# table lookup in the other direction as simple as possible.
for my $srgb (0 .. $#srgb_to_linear)
{
my $add = 0;
while (1)
{
my $linear = $srgb_to_linear[$srgb];
my $srgb_lossy = $linear_to_srgb[$linear >> 4];
last if $srgb == $srgb_lossy;
# Add slight bias to this component until it rounds correctly
$srgb_to_linear[$srgb] ++;
$add ++;
}
die "Too many adds at $srgb" if $add > 5;
}
print <<"PROLOG";
/* WARNING: This file is generated by $0.
* Please edit that file instead of this one.
*/
#include <stdint.h>
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
PROLOG
print "const uint8_t linear_to_srgb[" . @linear_to_srgb . "] =\n";
print "{\n";
for my $linear (0 .. $#linear_to_srgb)
{
if (($linear % 10) == 0)
{
print "\t";
}
print sprintf("%d, ", $linear_to_srgb[$linear]);
if (($linear % 10) == 9)
{
print "\n";
}
}
print "\n};\n";
print "\n";
print "const uint16_t srgb_to_linear[" . @srgb_to_linear . "] =\n";
print "{\n";
for my $srgb (0 .. $#srgb_to_linear)
{
if (($srgb % 10) == 0)
{
print "\t";
}
print sprintf("%d, ", $srgb_to_linear[$srgb]);
if (($srgb % 10) == 9)
{
print "\n";
}
}
print "\n};\n";

View File

@ -1,143 +0,0 @@
# Copyright © 2018 Intel Corporation
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
config_h = configure_file(
configuration : config,
output : 'pixman-config.h'
)
version_h = configure_file(
configuration : version_conf,
input : 'pixman-version.h.in',
output : 'pixman-version.h',
install_dir : join_paths(get_option('prefix'), get_option('includedir'), 'pixman-1')
)
libpixman_extra_cargs = []
default_library = get_option('default_library')
if default_library != 'static' and cc.has_function_attribute('dllexport')
libpixman_extra_cargs = ['-DPIXMAN_API=__declspec(dllexport)']
endif
pixman_simd_libs = []
simds = [
# the mmx library can be compiled with mmx on x86/x86_64, iwmmxt on
# some arm cores, or loongson mmi on loongson mips systems. The
# libraries will all have the same name, "pixman-mmx", but there is
# no chance of more than one version being built in the same build
# because no system could have mmx, iwmmxt, and mmi, and it
# simplifies the build logic to give them the same name.
['mmx', have_mmx, mmx_flags, []],
['mmx', have_loongson_mmi, loongson_mmi_flags, []],
['mmx', have_iwmmxt, iwmmxt_flags, []],
['sse2', have_sse2, sse2_flags, []],
['ssse3', have_ssse3, ssse3_flags, []],
['vmx', have_vmx, vmx_flags, []],
['arm-simd', have_armv6_simd, [],
['pixman-arm-simd-asm.S', 'pixman-arm-simd-asm-scaled.S']],
['arm-neon', have_neon, [],
['pixman-arm-neon-asm.S', 'pixman-arm-neon-asm-bilinear.S']],
['arm-neon', have_a64neon, [],
['pixman-arma64-neon-asm.S', 'pixman-arma64-neon-asm-bilinear.S']],
['mips-dspr2', have_mips_dspr2, mips_dspr2_flags,
['pixman-mips-dspr2-asm.S', 'pixman-mips-memcpy-asm.S']],
]
foreach simd : simds
if simd[1]
name = 'pixman-' + simd[0]
pixman_simd_libs += static_library(
name,
[name + '.c', config_h, version_h, simd[3]],
c_args : simd[2]
)
endif
endforeach
pixman_files = files(
'pixman.c',
'pixman-access.c',
'pixman-access-accessors.c',
'pixman-bits-image.c',
'pixman-combine32.c',
'pixman-combine-float.c',
'pixman-conical-gradient.c',
'pixman-filter.c',
'pixman-x86.c',
'pixman-mips.c',
'pixman-arm.c',
'pixman-ppc.c',
'pixman-edge.c',
'pixman-edge-accessors.c',
'pixman-fast-path.c',
'pixman-glyph.c',
'pixman-general.c',
'pixman-gradient-walker.c',
'pixman-image.c',
'pixman-implementation.c',
'pixman-linear-gradient.c',
'pixman-matrix.c',
'pixman-noop.c',
'pixman-radial-gradient.c',
'pixman-region16.c',
'pixman-region32.c',
'pixman-solid-fill.c',
'pixman-timer.c',
'pixman-trap.c',
'pixman-utils.c',
)
# Android cpu-features
cpu_features_path = get_option('cpu-features-path')
cpu_features_sources = []
cpu_features_inc = []
if cpu_features_path != ''
message('Using cpu-features.[ch] from ' + cpu_features_path)
cpu_features_sources = files(
cpu_features_path / 'cpu-features.h',
cpu_features_path / 'cpu-features.c',
)
cpu_features_inc = include_directories(cpu_features_path)
endif
libpixman = library(
'pixman-1',
[pixman_files, config_h, version_h, cpu_features_sources],
link_with: pixman_simd_libs,
c_args : libpixman_extra_cargs,
dependencies : [dep_m, dep_threads],
include_directories : cpu_features_inc,
version : meson.project_version(),
install : true,
)
inc_pixman = include_directories('.')
idep_pixman = declare_dependency(
link_with: libpixman,
include_directories : inc_pixman,
)
if meson.version().version_compare('>= 0.54.0')
meson.override_dependency('pixman-1', idep_pixman)
endif
install_headers('pixman.h', subdir : 'pixman-1')

View File

@ -1,3 +0,0 @@
#define PIXMAN_FB_ACCESSORS
#include "pixman-access.c"

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
#ifdef PIXMAN_FB_ACCESSORS
#define READ(img, ptr) \
(((bits_image_t *)(img))->read_func ((ptr), sizeof(*(ptr))))
#define WRITE(img, ptr,val) \
(((bits_image_t *)(img))->write_func ((ptr), (val), sizeof (*(ptr))))
#define MEMSET_WRAPPED(img, dst, val, size) \
do { \
size_t _i; \
uint8_t *_dst = (uint8_t*)(dst); \
for(_i = 0; _i < (size_t) size; _i++) { \
WRITE((img), _dst +_i, (val)); \
} \
} while (0)
#else
#define READ(img, ptr) (*(ptr))
#define WRITE(img, ptr, val) (*(ptr) = (val))
#define MEMSET_WRAPPED(img, dst, val, size) \
memset(dst, val, size)
#endif

View File

@ -1,37 +0,0 @@
/*
* Copyright © 2008 Mozilla Corporation
* Copyright © 2010 Nokia Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Mozilla Corporation not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Mozilla Corporation makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Jeff Muizelaar (jeff@infidigm.net)
*
*/
/* Supplementary macro for setting function attributes */
.macro pixman_asm_function fname
.func fname
.global fname
#ifdef __ELF__
.hidden fname
.type fname, %function
#endif
fname:
.endm

View File

@ -1,419 +0,0 @@
/*
* Copyright © 2010 Nokia Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Siarhei Siamashka (siarhei.siamashka@nokia.com)
*/
#ifndef PIXMAN_ARM_COMMON_H
#define PIXMAN_ARM_COMMON_H
#include "pixman-inlines.h"
/* Define some macros which can expand into proxy functions between
* ARM assembly optimized functions and the rest of pixman fast path API.
*
* All the low level ARM assembly functions have to use ARM EABI
* calling convention and take up to 8 arguments:
* width, height, dst, dst_stride, src, src_stride, mask, mask_stride
*
* The arguments are ordered with the most important coming first (the
* first 4 arguments are passed to function in registers, the rest are
* on stack). The last arguments are optional, for example if the
* function is not using mask, then 'mask' and 'mask_stride' can be
* omitted when doing a function call.
*
* Arguments 'src' and 'mask' contain either a pointer to the top left
* pixel of the composited rectangle or a pixel color value depending
* on the function type. In the case of just a color value (solid source
* or mask), the corresponding stride argument is unused.
*/
#define SKIP_ZERO_SRC 1
#define SKIP_ZERO_MASK 2
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_DST(cputype, name, \
src_type, src_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_##cputype (int32_t w, \
int32_t h, \
dst_type *dst, \
int32_t dst_stride, \
src_type *src, \
int32_t src_stride); \
\
static void \
cputype##_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
int32_t dst_stride, src_stride; \
\
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
dst_line, dst_stride, \
src_line, src_stride); \
}
#define PIXMAN_ARM_BIND_FAST_PATH_N_DST(flags, cputype, name, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_##cputype (int32_t w, \
int32_t h, \
dst_type *dst, \
int32_t dst_stride, \
uint32_t src); \
\
static void \
cputype##_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
int32_t dst_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
dst_line, dst_stride, \
src); \
}
#define PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST(flags, cputype, name, \
mask_type, mask_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_##cputype (int32_t w, \
int32_t h, \
dst_type *dst, \
int32_t dst_stride, \
uint32_t src, \
int32_t unused, \
mask_type *mask, \
int32_t mask_stride); \
\
static void \
cputype##_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
mask_type *mask_line; \
int32_t dst_stride, mask_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
mask_stride, mask_line, mask_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
dst_line, dst_stride, \
src, 0, \
mask_line, mask_stride); \
}
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST(flags, cputype, name, \
src_type, src_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_##cputype (int32_t w, \
int32_t h, \
dst_type *dst, \
int32_t dst_stride, \
src_type *src, \
int32_t src_stride, \
uint32_t mask); \
\
static void \
cputype##_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
int32_t dst_stride, src_stride; \
uint32_t mask; \
\
mask = _pixman_image_get_solid ( \
imp, mask_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_MASK) && mask == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
dst_line, dst_stride, \
src_line, src_stride, \
mask); \
}
#define PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST(cputype, name, \
src_type, src_cnt, \
mask_type, mask_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_##cputype (int32_t w, \
int32_t h, \
dst_type *dst, \
int32_t dst_stride, \
src_type *src, \
int32_t src_stride, \
mask_type *mask, \
int32_t mask_stride); \
\
static void \
cputype##_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line; \
src_type *src_line; \
mask_type *mask_line; \
int32_t dst_stride, src_stride, mask_stride; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
mask_stride, mask_line, mask_cnt); \
\
pixman_composite_##name##_asm_##cputype (width, height, \
dst_line, dst_stride, \
src_line, src_stride, \
mask_line, mask_stride); \
}
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST(cputype, name, op, \
src_type, dst_type) \
void \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
int32_t w, \
dst_type * dst, \
const src_type * src, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx); \
\
static force_inline void \
scaled_nearest_scanline_##cputype##_##name##_##op (dst_type * pd, \
const src_type * ps, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
vx, unit_x, \
max_vx); \
} \
\
FAST_NEAREST_MAINLOOP (cputype##_##name##_cover_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op, \
src_type, dst_type, COVER) \
FAST_NEAREST_MAINLOOP (cputype##_##name##_none_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op, \
src_type, dst_type, NONE) \
FAST_NEAREST_MAINLOOP (cputype##_##name##_pad_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op, \
src_type, dst_type, PAD) \
FAST_NEAREST_MAINLOOP (cputype##_##name##_normal_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op, \
src_type, dst_type, NORMAL)
#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST(flags, cputype, name, op, \
src_type, dst_type) \
void \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype ( \
int32_t w, \
dst_type * dst, \
const src_type * src, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
const uint8_t * mask); \
\
static force_inline void \
scaled_nearest_scanline_##cputype##_##name##_##op (const uint8_t * mask, \
dst_type * pd, \
const src_type * ps, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps, \
vx, unit_x, \
max_vx, \
mask); \
} \
\
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op,\
src_type, uint8_t, dst_type, COVER, TRUE, FALSE)\
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op,\
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op,\
src_type, uint8_t, dst_type, PAD, TRUE, FALSE) \
FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
scaled_nearest_scanline_##cputype##_##name##_##op,\
src_type, uint8_t, dst_type, NORMAL, TRUE, FALSE)
/* Provide entries for the fast path table */
#define PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \
SIMPLE_NEAREST_A8_MASK_FAST_PATH (op,s,d,func), \
SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL (op,s,d,func)
/*****************************************************************************/
#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST(flags, cputype, name, op, \
src_type, dst_type) \
void \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
dst_type * dst, \
const src_type * top, \
const src_type * bottom, \
int wt, \
int wb, \
pixman_fixed_t x, \
pixman_fixed_t ux, \
int width); \
\
static force_inline void \
scaled_bilinear_scanline_##cputype##_##name##_##op ( \
dst_type * dst, \
const uint32_t * mask, \
const src_type * src_top, \
const src_type * src_bottom, \
int32_t w, \
int wt, \
int wb, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
dst, src_top, src_bottom, wt, wb, vx, unit_x, w); \
} \
\
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint32_t, dst_type, NORMAL, \
FLAG_NONE)
#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, cputype, name, op, \
src_type, dst_type) \
void \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
dst_type * dst, \
const uint8_t * mask, \
const src_type * top, \
const src_type * bottom, \
int wt, \
int wb, \
pixman_fixed_t x, \
pixman_fixed_t ux, \
int width); \
\
static force_inline void \
scaled_bilinear_scanline_##cputype##_##name##_##op ( \
dst_type * dst, \
const uint8_t * mask, \
const src_type * src_top, \
const src_type * src_bottom, \
int32_t w, \
int wt, \
int wb, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype ( \
dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
} \
\
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, COVER, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, NONE, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, PAD, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op, \
scaled_bilinear_scanline_##cputype##_##name##_##op, \
src_type, uint8_t, dst_type, NORMAL, \
FLAG_HAVE_NON_SOLID_MASK)
#endif

View File

@ -1,21 +0,0 @@
area pixman_msvc, code, readonly
export pixman_msvc_try_arm_simd_op
pixman_msvc_try_arm_simd_op
;; I don't think the msvc arm asm knows how to do SIMD insns
;; uqadd8 r3,r3,r3
dcd 0xe6633f93
mov pc,lr
endp
export pixman_msvc_try_arm_neon_op
pixman_msvc_try_arm_neon_op
;; I don't think the msvc arm asm knows how to do NEON insns
;; veor d0,d0,d0
dcd 0xf3000110
mov pc,lr
endp
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,493 +0,0 @@
/*
* Copyright © 2009 ARM Ltd, Movial Creative Technologies Oy
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of ARM Ltd not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. ARM Ltd makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Ian Rickards (ian.rickards@arm.com)
* Author: Jonathan Morton (jonathan.morton@movial.com)
* Author: Markku Vire (markku.vire@movial.com)
*
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <string.h>
#include "pixman-private.h"
#include "pixman-arm-common.h"
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_x888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_0565,
uint16_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0888,
uint8_t, 3, uint8_t, 3)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_8888_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0565_8888,
uint16_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_8888_rev,
uint8_t, 3, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_0888_0565_rev,
uint8_t, 3, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_pixbuf_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, src_rpixbuf_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, add_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, over_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_0565,
uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (neon, out_reverse_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_0565,
uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_n_8888,
uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, neon, over_reverse_n_8888,
uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, neon, in_n_8,
uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_0565,
uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_8888_ca,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8888_0565_ca,
uint32_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, over_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, neon, add_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (0, neon, src_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_8888_n_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, over_0565_n_0565,
uint16_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, neon, add_8888_n_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8_8_8,
uint8_t, 1, uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_0565_8_0565,
uint16_t, 1, uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8_8888,
uint32_t, 1, uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, add_8888_8888_8888,
uint32_t, 1, uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_8888,
uint32_t, 1, uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8888_8888,
uint32_t, 1, uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_8888_8_0565,
uint32_t, 1, uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST (neon, over_0565_8_0565,
uint16_t, 1, uint8_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_8888, OVER,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, OVER,
uint32_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 8888_0565, SRC,
uint32_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (neon, 0565_8888, SRC,
uint16_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_0565,
OVER, uint32_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, neon, 0565_8_0565,
OVER, uint16_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_8888, SRC,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 8888_0565, SRC,
uint32_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_x888, SRC,
uint16_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (0, neon, 0565_0565, SRC,
uint16_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, OVER,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, neon, 8888_8888, ADD,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 8888_8_8888, SRC,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 8888_8_0565, SRC,
uint32_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 0565_8_x888, SRC,
uint16_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (0, neon, 0565_8_0565, SRC,
uint16_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_8888, OVER,
uint32_t, uint32_t)
PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, neon, 8888_8_8888, ADD,
uint32_t, uint32_t)
void
pixman_composite_src_n_8_asm_neon (int32_t w,
int32_t h,
uint8_t *dst,
int32_t dst_stride,
uint8_t src);
void
pixman_composite_src_n_0565_asm_neon (int32_t w,
int32_t h,
uint16_t *dst,
int32_t dst_stride,
uint16_t src);
void
pixman_composite_src_n_8888_asm_neon (int32_t w,
int32_t h,
uint32_t *dst,
int32_t dst_stride,
uint32_t src);
static pixman_bool_t
arm_neon_fill (pixman_implementation_t *imp,
uint32_t * bits,
int stride,
int bpp,
int x,
int y,
int width,
int height,
uint32_t _xor)
{
/* stride is always multiple of 32bit units in pixman */
int32_t byte_stride = stride * sizeof(uint32_t);
switch (bpp)
{
case 8:
pixman_composite_src_n_8_asm_neon (
width,
height,
(uint8_t *)(((char *) bits) + y * byte_stride + x),
byte_stride,
_xor & 0xff);
return TRUE;
case 16:
pixman_composite_src_n_0565_asm_neon (
width,
height,
(uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
byte_stride / 2,
_xor & 0xffff);
return TRUE;
case 32:
pixman_composite_src_n_8888_asm_neon (
width,
height,
(uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
byte_stride / 4,
_xor);
return TRUE;
default:
return FALSE;
}
}
static pixman_bool_t
arm_neon_blt (pixman_implementation_t *imp,
uint32_t * src_bits,
uint32_t * dst_bits,
int src_stride,
int dst_stride,
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dest_x,
int dest_y,
int width,
int height)
{
if (src_bpp != dst_bpp)
return FALSE;
switch (src_bpp)
{
case 16:
pixman_composite_src_0565_0565_asm_neon (
width, height,
(uint16_t *)(((char *) dst_bits) +
dest_y * dst_stride * 4 + dest_x * 2), dst_stride * 2,
(uint16_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 2), src_stride * 2);
return TRUE;
case 32:
pixman_composite_src_8888_8888_asm_neon (
width, height,
(uint32_t *)(((char *) dst_bits) +
dest_y * dst_stride * 4 + dest_x * 4), dst_stride,
(uint32_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 4), src_stride);
return TRUE;
default:
return FALSE;
}
}
static const pixman_fast_path_t arm_neon_fast_paths[] =
{
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, neon_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, neon_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, neon_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, neon_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, neon_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, neon_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, neon_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, neon_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, neon_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, neon_composite_src_0888_0888),
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, neon_composite_src_0888_8888_rev),
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, neon_composite_src_0888_0565_rev),
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, neon_composite_src_pixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, neon_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, neon_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, neon_composite_src_pixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, neon_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8, neon_composite_src_n_8_8),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, neon_composite_over_n_8_8),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, neon_composite_over_n_8_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, neon_composite_over_n_8_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, neon_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, neon_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, neon_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, neon_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, neon_composite_over_n_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, neon_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, neon_composite_over_n_8888),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, neon_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, neon_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, neon_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, neon_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, neon_composite_over_n_8888_0565_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, neon_composite_over_n_8888_0565_ca),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, neon_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, neon_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, neon_composite_over_8888_n_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, neon_composite_over_8888_n_0565),
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, neon_composite_over_0565_n_0565),
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, neon_composite_over_0565_n_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, neon_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, neon_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, neon_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, neon_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, neon_composite_over_8888_8_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, neon_composite_over_8888_8_0565),
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, neon_composite_over_0565_8_0565),
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, neon_composite_over_0565_8_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, x8r8g8b8, neon_composite_over_8888_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_over_8888_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, neon_composite_over_8888_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, neon_composite_over_8888_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, neon_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, neon_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, neon_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, neon_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, x8r8g8b8, null, a8r8g8b8, neon_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (OVER, x8b8g8r8, null, a8b8g8r8, neon_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, neon_composite_add_n_8_8),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, x8r8g8b8, neon_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, neon_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, x8b8g8r8, neon_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, neon_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, neon_composite_add_8_8_8),
PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, neon_composite_add_0565_8_0565),
PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, neon_composite_add_0565_8_0565),
PIXMAN_STD_FAST_PATH (ADD, x8r8g8b8, a8, x8r8g8b8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, x8r8g8b8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, x8b8g8r8, a8, x8b8g8r8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, x8b8g8r8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, neon_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, x8r8g8b8, a8r8g8b8, x8r8g8b8, neon_composite_add_8888_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, x8r8g8b8, neon_composite_add_8888_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, neon_composite_add_8888_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, x8r8g8b8, solid, x8r8g8b8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, x8r8g8b8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, x8b8g8r8, solid, x8b8g8r8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, x8b8g8r8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, neon_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, neon_composite_add_8_8),
PIXMAN_STD_FAST_PATH (ADD, x8r8g8b8, null, x8r8g8b8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, x8r8g8b8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, x8b8g8r8, null, x8b8g8r8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, x8b8g8r8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, neon_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (IN, solid, null, a8, neon_composite_in_n_8),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, neon_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, neon_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, neon_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, neon_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, x8r8g8b8, neon_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, neon_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, x8b8g8r8, neon_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, neon_composite_out_reverse_8_8888),
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, neon_8888_8888),
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, neon_8888_8888),
SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, b5g6r5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, b5g6r5, neon_8888_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, neon_0565_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8888),
/* Note: NONE repeat is not supported yet */
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, neon_0565_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, neon_0565_8888),
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, neon_8888_8_0565),
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, neon_8888_8_0565),
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, neon_0565_8_0565),
PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, neon_0565_8_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_x888),
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_0565),
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (ADD, x8r8g8b8, x8r8g8b8, neon_8888_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, neon_8888_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, neon_8888_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, neon_0565_8_x888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, neon_0565_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, neon_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, x8r8g8b8, x8r8g8b8, neon_8888_8_8888),
{ PIXMAN_OP_NONE },
};
#define BIND_COMBINE_U(name) \
void \
pixman_composite_scanline_##name##_mask_asm_neon (int32_t w, \
const uint32_t *dst, \
const uint32_t *src, \
const uint32_t *mask); \
\
void \
pixman_composite_scanline_##name##_asm_neon (int32_t w, \
const uint32_t *dst, \
const uint32_t *src); \
\
static void \
neon_combine_##name##_u (pixman_implementation_t *imp, \
pixman_op_t op, \
uint32_t * dest, \
const uint32_t * src, \
const uint32_t * mask, \
int width) \
{ \
if (mask) \
pixman_composite_scanline_##name##_mask_asm_neon (width, dest, \
src, mask); \
else \
pixman_composite_scanline_##name##_asm_neon (width, dest, src); \
}
BIND_COMBINE_U (over)
BIND_COMBINE_U (add)
BIND_COMBINE_U (out_reverse)
pixman_implementation_t *
_pixman_implementation_create_arm_neon (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, arm_neon_fast_paths);
imp->combine_32[PIXMAN_OP_OVER] = neon_combine_over_u;
imp->combine_32[PIXMAN_OP_ADD] = neon_combine_add_u;
imp->combine_32[PIXMAN_OP_OUT_REVERSE] = neon_combine_out_reverse_u;
imp->blt = arm_neon_blt;
imp->fill = arm_neon_fill;
return imp;
}

View File

@ -1,156 +0,0 @@
/*
* Copyright © 2008 Mozilla Corporation
* Copyright © 2010 Nokia Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Mozilla Corporation not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Mozilla Corporation makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Jeff Muizelaar (jeff@infidigm.net)
*
*/
/* Prevent the stack from becoming executable */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
.text
.arch armv6
.object_arch armv4
.arm
.altmacro
.p2align 2
#include "pixman-arm-asm.h"
/*
* Note: This code is only using armv5te instructions (not even armv6),
* but is scheduled for ARM Cortex-A8 pipeline. So it might need to
* be split into a few variants, tuned for each microarchitecture.
*
* TODO: In order to get good performance on ARM9/ARM11 cores (which don't
* have efficient write combining), it needs to be changed to use 16-byte
* aligned writes using STM instruction.
*
* Nearest scanline scaler macro template uses the following arguments:
* fname - name of the function to generate
* bpp_shift - (1 << bpp_shift) is the size of pixel in bytes
* t - type suffix for LDR/STR instructions
* prefetch_distance - prefetch in the source image by that many
* pixels ahead
* prefetch_braking_distance - stop prefetching when that many pixels are
* remaining before the end of scanline
*/
.macro generate_nearest_scanline_func fname, bpp_shift, t, \
prefetch_distance, \
prefetch_braking_distance
pixman_asm_function fname
W .req r0
DST .req r1
SRC .req r2
VX .req r3
UNIT_X .req ip
TMP1 .req r4
TMP2 .req r5
VXMASK .req r6
PF_OFFS .req r7
SRC_WIDTH_FIXED .req r8
ldr UNIT_X, [sp]
push {r4, r5, r6, r7, r8, r10}
mvn VXMASK, #((1 << bpp_shift) - 1)
ldr SRC_WIDTH_FIXED, [sp, #28]
/* define helper macro */
.macro scale_2_pixels
ldr&t TMP1, [SRC, TMP1]
and TMP2, VXMASK, VX, asr #(16 - bpp_shift)
adds VX, VX, UNIT_X
str&t TMP1, [DST], #(1 << bpp_shift)
9: subpls VX, VX, SRC_WIDTH_FIXED
bpl 9b
ldr&t TMP2, [SRC, TMP2]
and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
adds VX, VX, UNIT_X
str&t TMP2, [DST], #(1 << bpp_shift)
9: subpls VX, VX, SRC_WIDTH_FIXED
bpl 9b
.endm
/* now do the scaling */
and TMP1, VXMASK, VX, asr #(16 - bpp_shift)
adds VX, VX, UNIT_X
9: subpls VX, VX, SRC_WIDTH_FIXED
bpl 9b
subs W, W, #(8 + prefetch_braking_distance)
blt 2f
/* calculate prefetch offset */
mov PF_OFFS, #prefetch_distance
mla PF_OFFS, UNIT_X, PF_OFFS, VX
1: /* main loop, process 8 pixels per iteration with prefetch */
pld [SRC, PF_OFFS, asr #(16 - bpp_shift)]
add PF_OFFS, UNIT_X, lsl #3
scale_2_pixels
scale_2_pixels
scale_2_pixels
scale_2_pixels
subs W, W, #8
bge 1b
2:
subs W, W, #(4 - 8 - prefetch_braking_distance)
blt 2f
1: /* process the remaining pixels */
scale_2_pixels
scale_2_pixels
subs W, W, #4
bge 1b
2:
tst W, #2
beq 2f
scale_2_pixels
2:
tst W, #1
ldrne&t TMP1, [SRC, TMP1]
strne&t TMP1, [DST]
/* cleanup helper macro */
.purgem scale_2_pixels
.unreq DST
.unreq SRC
.unreq W
.unreq VX
.unreq UNIT_X
.unreq TMP1
.unreq TMP2
.unreq VXMASK
.unreq PF_OFFS
.unreq SRC_WIDTH_FIXED
/* return */
pop {r4, r5, r6, r7, r8, r10}
bx lr
.endfunc
.endm
generate_nearest_scanline_func \
pixman_scaled_nearest_scanline_0565_0565_SRC_asm_armv6, 1, h, 80, 32
generate_nearest_scanline_func \
pixman_scaled_nearest_scanline_8888_8888_SRC_asm_armv6, 2, , 48, 32

File diff suppressed because it is too large Load Diff

View File

@ -1,966 +0,0 @@
/*
* Copyright © 2012 Raspberry Pi Foundation
* Copyright © 2012 RISC OS Open Ltd
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. The copyright holders make no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Ben Avison (bavison@riscosopen.org)
*
*/
/*
* Because the alignment of pixel data to cachelines, and even the number of
* cachelines per row can vary from row to row, and because of the need to
* preload each scanline once and only once, this prefetch strategy treats
* each row of pixels independently. When a pixel row is long enough, there
* are three distinct phases of prefetch:
* * an inner loop section, where each time a cacheline of data is
* processed, another cacheline is preloaded (the exact distance ahead is
* determined empirically using profiling results from lowlevel-blt-bench)
* * a leading section, where enough cachelines are preloaded to ensure no
* cachelines escape being preloaded when the inner loop starts
* * a trailing section, where a limited number (0 or more) of cachelines
* are preloaded to deal with data (if any) that hangs off the end of the
* last iteration of the inner loop, plus any trailing bytes that were not
* enough to make up one whole iteration of the inner loop
*
* There are (in general) three distinct code paths, selected between
* depending upon how long the pixel row is. If it is long enough that there
* is at least one iteration of the inner loop (as described above) then
* this is described as the "wide" case. If it is shorter than that, but
* there are still enough bytes output that there is at least one 16-byte-
* long, 16-byte-aligned write to the destination (the optimum type of
* write), then this is the "medium" case. If it is not even this long, then
* this is the "narrow" case, and there is no attempt to align writes to
* 16-byte boundaries. In the "medium" and "narrow" cases, all the
* cachelines containing data from the pixel row are prefetched up-front.
*/
/*
* Determine whether we put the arguments on the stack for debugging.
*/
#undef DEBUG_PARAMS
/*
* Bit flags for 'generate_composite_function' macro which are used
* to tune generated functions behavior.
*/
.set FLAG_DST_WRITEONLY, 0
.set FLAG_DST_READWRITE, 1
.set FLAG_COND_EXEC, 0
.set FLAG_BRANCH_OVER, 2
.set FLAG_PROCESS_PRESERVES_PSR, 0
.set FLAG_PROCESS_CORRUPTS_PSR, 4
.set FLAG_PROCESS_DOESNT_STORE, 0
.set FLAG_PROCESS_DOES_STORE, 8 /* usually because it needs to conditionally skip it */
.set FLAG_NO_SPILL_LINE_VARS, 0
.set FLAG_SPILL_LINE_VARS_WIDE, 16
.set FLAG_SPILL_LINE_VARS_NON_WIDE, 32
.set FLAG_SPILL_LINE_VARS, 48
.set FLAG_PROCESS_CORRUPTS_SCRATCH, 0
.set FLAG_PROCESS_PRESERVES_SCRATCH, 64
.set FLAG_PROCESS_PRESERVES_WK0, 0
.set FLAG_PROCESS_CORRUPTS_WK0, 128 /* if possible, use the specified register(s) instead so WK0 can hold number of leading pixels */
.set FLAG_PRELOAD_DST, 0
.set FLAG_NO_PRELOAD_DST, 256
/*
* Number of bytes by which to adjust preload offset of destination
* buffer (allows preload instruction to be moved before the load(s))
*/
.set DST_PRELOAD_BIAS, 0
/*
* Offset into stack where mask and source pointer/stride can be accessed.
*/
#ifdef DEBUG_PARAMS
.set ARGS_STACK_OFFSET, (9*4+9*4)
#else
.set ARGS_STACK_OFFSET, (9*4)
#endif
/*
* Offset into stack where space allocated during init macro can be accessed.
*/
.set LOCALS_STACK_OFFSET, 0
/*
* Constants for selecting preferable prefetch type.
*/
.set PREFETCH_TYPE_NONE, 0
.set PREFETCH_TYPE_STANDARD, 1
/*
* Definitions of macros for load/store of pixel data.
*/
.macro pixldst op, cond=al, numbytes, reg0, reg1, reg2, reg3, base, unaligned=0
.if numbytes == 16
.if unaligned == 1
op&r&cond WK&reg0, [base], #4
op&r&cond WK&reg1, [base], #4
op&r&cond WK&reg2, [base], #4
op&r&cond WK&reg3, [base], #4
.else
op&m&cond&ia base!, {WK&reg0,WK&reg1,WK&reg2,WK&reg3}
.endif
.elseif numbytes == 8
.if unaligned == 1
op&r&cond WK&reg0, [base], #4
op&r&cond WK&reg1, [base], #4
.else
op&m&cond&ia base!, {WK&reg0,WK&reg1}
.endif
.elseif numbytes == 4
op&r&cond WK&reg0, [base], #4
.elseif numbytes == 2
op&r&cond&h WK&reg0, [base], #2
.elseif numbytes == 1
op&r&cond&b WK&reg0, [base], #1
.else
.error "unsupported size: numbytes"
.endif
.endm
.macro pixst_baseupdated cond, numbytes, reg0, reg1, reg2, reg3, base
.if numbytes == 16
stm&cond&db base, {WK&reg0,WK&reg1,WK&reg2,WK&reg3}
.elseif numbytes == 8
stm&cond&db base, {WK&reg0,WK&reg1}
.elseif numbytes == 4
str&cond WK&reg0, [base, #-4]
.elseif numbytes == 2
str&cond&h WK&reg0, [base, #-2]
.elseif numbytes == 1
str&cond&b WK&reg0, [base, #-1]
.else
.error "unsupported size: numbytes"
.endif
.endm
.macro pixld cond, numbytes, firstreg, base, unaligned
pixldst ld, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base, unaligned
.endm
.macro pixst cond, numbytes, firstreg, base
.if (flags) & FLAG_DST_READWRITE
pixst_baseupdated cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base
.else
pixldst st, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base
.endif
.endm
.macro PF a, x:vararg
.if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_STANDARD)
a x
.endif
.endm
.macro preload_leading_step1 bpp, ptr, base
/* If the destination is already 16-byte aligned, then we need to preload
* between 0 and prefetch_distance (inclusive) cache lines ahead so there
* are no gaps when the inner loop starts.
*/
.if bpp > 0
PF bic, ptr, base, #31
.set OFFSET, 0
.rept prefetch_distance+1
PF pld, [ptr, #OFFSET]
.set OFFSET, OFFSET+32
.endr
.endif
.endm
.macro preload_leading_step2 bpp, bpp_shift, ptr, base
/* However, if the destination is not 16-byte aligned, we may need to
* preload more cache lines than that. The question we need to ask is:
* are the bytes corresponding to the leading pixels more than the amount
* by which the source pointer will be rounded down for preloading, and if
* so, by how many cache lines? Effectively, we want to calculate
* leading_bytes = ((-dst)&15)*src_bpp/dst_bpp
* inner_loop_offset = (src+leading_bytes)&31
* extra_needed = leading_bytes - inner_loop_offset
* and test if extra_needed is <= 0, <= 32, or > 32 (where > 32 is only
* possible when there are 4 src bytes for every 1 dst byte).
*/
.if bpp > 0
.ifc base,DST
/* The test can be simplified further when preloading the destination */
PF tst, base, #16
PF beq, 61f
.else
.if bpp/dst_w_bpp == 4
PF add, SCRATCH, base, WK0, lsl #bpp_shift-dst_bpp_shift
PF and, SCRATCH, SCRATCH, #31
PF rsb, SCRATCH, SCRATCH, WK0, lsl #bpp_shift-dst_bpp_shift
PF sub, SCRATCH, SCRATCH, #1 /* so now ranges are -16..-1 / 0..31 / 32..63 */
PF movs, SCRATCH, SCRATCH, lsl #32-6 /* so this sets NC / nc / Nc */
PF bcs, 61f
PF bpl, 60f
PF pld, [ptr, #32*(prefetch_distance+2)]
.else
PF mov, SCRATCH, base, lsl #32-5
PF add, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift
PF rsbs, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift
PF bls, 61f
.endif
.endif
60: PF pld, [ptr, #32*(prefetch_distance+1)]
61:
.endif
.endm
#define IS_END_OF_GROUP(INDEX,SIZE) ((SIZE) < 2 || ((INDEX) & ~((INDEX)+1)) & ((SIZE)/2))
.macro preload_middle bpp, base, scratch_holds_offset
.if bpp > 0
/* prefetch distance = 256/bpp, stm distance = 128/dst_w_bpp */
.if IS_END_OF_GROUP(SUBBLOCK,256/128*dst_w_bpp/bpp)
.if scratch_holds_offset
PF pld, [base, SCRATCH]
.else
PF bic, SCRATCH, base, #31
PF pld, [SCRATCH, #32*prefetch_distance]
.endif
.endif
.endif
.endm
.macro preload_trailing bpp, bpp_shift, base
.if bpp > 0
.if bpp*pix_per_block > 256
/* Calculations are more complex if more than one fetch per block */
PF and, WK1, base, #31
PF add, WK1, WK1, WK0, lsl #bpp_shift
PF add, WK1, WK1, #32*(bpp*pix_per_block/256-1)*(prefetch_distance+1)
PF bic, SCRATCH, base, #31
80: PF pld, [SCRATCH, #32*(prefetch_distance+1)]
PF add, SCRATCH, SCRATCH, #32
PF subs, WK1, WK1, #32
PF bhi, 80b
.else
/* If exactly one fetch per block, then we need either 0, 1 or 2 extra preloads */
PF mov, SCRATCH, base, lsl #32-5
PF adds, SCRATCH, SCRATCH, X, lsl #32-5+bpp_shift
PF adceqs, SCRATCH, SCRATCH, #0
/* The instruction above has two effects: ensures Z is only
* set if C was clear (so Z indicates that both shifted quantities
* were 0), and clears C if Z was set (so C indicates that the sum
* of the shifted quantities was greater and not equal to 32) */
PF beq, 82f
PF bic, SCRATCH, base, #31
PF bcc, 81f
PF pld, [SCRATCH, #32*(prefetch_distance+2)]
81: PF pld, [SCRATCH, #32*(prefetch_distance+1)]
82:
.endif
.endif
.endm
.macro preload_line narrow_case, bpp, bpp_shift, base
/* "narrow_case" - just means that the macro was invoked from the "narrow"
* code path rather than the "medium" one - because in the narrow case,
* the row of pixels is known to output no more than 30 bytes, then
* (assuming the source pixels are no wider than the the destination
* pixels) they cannot possibly straddle more than 2 32-byte cachelines,
* meaning there's no need for a loop.
* "bpp" - number of bits per pixel in the channel (source, mask or
* destination) that's being preloaded, or 0 if this channel is not used
* for reading
* "bpp_shift" - log2 of ("bpp"/8) (except if "bpp"=0 of course)
* "base" - base address register of channel to preload (SRC, MASK or DST)
*/
.if bpp > 0
.if narrow_case && (bpp <= dst_w_bpp)
/* In these cases, each line for each channel is in either 1 or 2 cache lines */
PF bic, WK0, base, #31
PF pld, [WK0]
PF add, WK1, base, X, LSL #bpp_shift
PF sub, WK1, WK1, #1
PF bic, WK1, WK1, #31
PF cmp, WK1, WK0
PF beq, 90f
PF pld, [WK1]
90:
.else
PF bic, WK0, base, #31
PF pld, [WK0]
PF add, WK1, base, X, lsl #bpp_shift
PF sub, WK1, WK1, #1
PF bic, WK1, WK1, #31
PF cmp, WK1, WK0
PF beq, 92f
91: PF add, WK0, WK0, #32
PF cmp, WK0, WK1
PF pld, [WK0]
PF bne, 91b
92:
.endif
.endif
.endm
.macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0
.if decrementx
sub&cond X, X, #8*numbytes/dst_w_bpp
.endif
process_tail cond, numbytes, firstreg
.if !((flags) & FLAG_PROCESS_DOES_STORE)
pixst cond, numbytes, firstreg, DST
.endif
.endm
.macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
.if (flags) & FLAG_BRANCH_OVER
.ifc cond,mi
bpl 100f
.endif
.ifc cond,cs
bcc 100f
.endif
.ifc cond,ne
beq 100f
.endif
conditional_process1_helper , process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
100:
.else
conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx
.endif
.endm
.macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx
.if (flags) & (FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE)
/* Can't interleave reads and writes */
test
conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx
.if (flags) & FLAG_PROCESS_CORRUPTS_PSR
test
.endif
conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx
.else
/* Can interleave reads and writes for better scheduling */
test
process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0
process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0
.if decrementx
sub&cond1 X, X, #8*numbytes1/dst_w_bpp
sub&cond2 X, X, #8*numbytes2/dst_w_bpp
.endif
process_tail cond1, numbytes1, firstreg1
process_tail cond2, numbytes2, firstreg2
pixst cond1, numbytes1, firstreg1, DST
pixst cond2, numbytes2, firstreg2, DST
.endif
.endm
.macro test_bits_1_0_ptr
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
movs SCRATCH, X, lsl #32-1 /* C,N = bits 1,0 of DST */
.else
movs SCRATCH, WK0, lsl #32-1 /* C,N = bits 1,0 of DST */
.endif
.endm
.macro test_bits_3_2_ptr
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
movs SCRATCH, X, lsl #32-3 /* C,N = bits 3, 2 of DST */
.else
movs SCRATCH, WK0, lsl #32-3 /* C,N = bits 3, 2 of DST */
.endif
.endm
.macro leading_15bytes process_head, process_tail
/* On entry, WK0 bits 0-3 = number of bytes until destination is 16-byte aligned */
.set DECREMENT_X, 1
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
.set DECREMENT_X, 0
sub X, X, WK0, lsr #dst_bpp_shift
str X, [sp, #LINE_SAVED_REG_COUNT*4]
mov X, WK0
.endif
/* Use unaligned loads in all cases for simplicity */
.if dst_w_bpp == 8
conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X
.elseif dst_w_bpp == 16
test_bits_1_0_ptr
conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X
.endif
conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
ldr X, [sp, #LINE_SAVED_REG_COUNT*4]
.endif
.endm
.macro test_bits_3_2_pix
movs SCRATCH, X, lsl #dst_bpp_shift+32-3
.endm
.macro test_bits_1_0_pix
.if dst_w_bpp == 8
movs SCRATCH, X, lsl #dst_bpp_shift+32-1
.else
movs SCRATCH, X, lsr #1
.endif
.endm
.macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0
.if dst_w_bpp == 16
test_bits_1_0_pix
conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0
.elseif dst_w_bpp == 8
conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0
.endif
.endm
.macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment
110:
.set SUBBLOCK, 0 /* this is a count of STMs; there can be up to 8 STMs per block */
.rept pix_per_block*dst_w_bpp/128
process_head , 16, 0, unaligned_src, unaligned_mask, 1
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
preload_middle src_bpp, SRC, 1
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
preload_middle mask_bpp, MASK, 1
.else
preload_middle src_bpp, SRC, 0
preload_middle mask_bpp, MASK, 0
.endif
.if (dst_r_bpp > 0) && ((SUBBLOCK % 2) == 0) && (((flags) & FLAG_NO_PRELOAD_DST) == 0)
/* Because we know that writes are 16-byte aligned, it's relatively easy to ensure that
* destination prefetches are 32-byte aligned. It's also the easiest channel to offset
* preloads for, to achieve staggered prefetches for multiple channels, because there are
* always two STMs per prefetch, so there is always an opposite STM on which to put the
* preload. Note, no need to BIC the base register here */
PF pld, [DST, #32*prefetch_distance - dst_alignment]
.endif
process_tail , 16, 0
.if !((flags) & FLAG_PROCESS_DOES_STORE)
pixst , 16, 0, DST
.endif
.set SUBBLOCK, SUBBLOCK+1
.endr
subs X, X, #pix_per_block
bhs 110b
.endm
.macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask
/* Destination now 16-byte aligned; we have at least one block before we have to stop preloading */
.if dst_r_bpp > 0
tst DST, #16
bne 111f
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 16 + DST_PRELOAD_BIAS
b 112f
111:
.endif
process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 0 + DST_PRELOAD_BIAS
112:
/* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */
.if (src_bpp*pix_per_block > 256) || (mask_bpp*pix_per_block > 256) || (dst_r_bpp*pix_per_block > 256)
PF and, WK0, X, #pix_per_block-1
.endif
preload_trailing src_bpp, src_bpp_shift, SRC
preload_trailing mask_bpp, mask_bpp_shift, MASK
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
preload_trailing dst_r_bpp, dst_bpp_shift, DST
.endif
add X, X, #(prefetch_distance+2)*pix_per_block - 128/dst_w_bpp
/* The remainder of the line is handled identically to the medium case */
medium_case_inner_loop_and_trailing_pixels process_head, process_tail,, exit_label, unaligned_src, unaligned_mask
.endm
.macro medium_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask
120:
process_head , 16, 0, unaligned_src, unaligned_mask, 0
process_tail , 16, 0
.if !((flags) & FLAG_PROCESS_DOES_STORE)
pixst , 16, 0, DST
.endif
subs X, X, #128/dst_w_bpp
bhs 120b
/* Trailing pixels */
tst X, #128/dst_w_bpp - 1
beq exit_label
trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
.endm
.macro narrow_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask
tst X, #16*8/dst_w_bpp
conditional_process1 ne, process_head, process_tail, 16, 0, unaligned_src, unaligned_mask, 0
/* Trailing pixels */
/* In narrow case, it's relatively unlikely to be aligned, so let's do without a branch here */
trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask
.endm
.macro switch_on_alignment action, process_head, process_tail, process_inner_loop, exit_label
/* Note that if we're reading the destination, it's already guaranteed to be aligned at this point */
.if mask_bpp == 8 || mask_bpp == 16
tst MASK, #3
bne 141f
.endif
.if src_bpp == 8 || src_bpp == 16
tst SRC, #3
bne 140f
.endif
action process_head, process_tail, process_inner_loop, exit_label, 0, 0
.if src_bpp == 8 || src_bpp == 16
b exit_label
140:
action process_head, process_tail, process_inner_loop, exit_label, 1, 0
.endif
.if mask_bpp == 8 || mask_bpp == 16
b exit_label
141:
.if src_bpp == 8 || src_bpp == 16
tst SRC, #3
bne 142f
.endif
action process_head, process_tail, process_inner_loop, exit_label, 0, 1
.if src_bpp == 8 || src_bpp == 16
b exit_label
142:
action process_head, process_tail, process_inner_loop, exit_label, 1, 1
.endif
.endif
.endm
.macro end_of_line restore_x, vars_spilled, loop_label, last_one
.if vars_spilled
/* Sadly, GAS doesn't seem have an equivalent of the DCI directive? */
/* This is ldmia sp,{} */
.word 0xE89D0000 | LINE_SAVED_REGS
.endif
subs Y, Y, #1
.if vars_spilled
.if (LINE_SAVED_REGS) & (1<<1)
str Y, [sp]
.endif
.endif
add DST, DST, STRIDE_D
.if src_bpp > 0
add SRC, SRC, STRIDE_S
.endif
.if mask_bpp > 0
add MASK, MASK, STRIDE_M
.endif
.if restore_x
mov X, ORIG_W
.endif
bhs loop_label
.ifc "last_one",""
.if vars_spilled
b 197f
.else
b 198f
.endif
.else
.if (!vars_spilled) && ((flags) & FLAG_SPILL_LINE_VARS)
b 198f
.endif
.endif
.endm
.macro generate_composite_function fname, \
src_bpp_, \
mask_bpp_, \
dst_w_bpp_, \
flags_, \
prefetch_distance_, \
init, \
newline, \
cleanup, \
process_head, \
process_tail, \
process_inner_loop
pixman_asm_function fname
/*
* Make some macro arguments globally visible and accessible
* from other macros
*/
.set src_bpp, src_bpp_
.set mask_bpp, mask_bpp_
.set dst_w_bpp, dst_w_bpp_
.set flags, flags_
.set prefetch_distance, prefetch_distance_
/*
* Select prefetch type for this function.
*/
.if prefetch_distance == 0
.set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE
.else
.set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_STANDARD
.endif
.if src_bpp == 32
.set src_bpp_shift, 2
.elseif src_bpp == 24
.set src_bpp_shift, 0
.elseif src_bpp == 16
.set src_bpp_shift, 1
.elseif src_bpp == 8
.set src_bpp_shift, 0
.elseif src_bpp == 0
.set src_bpp_shift, -1
.else
.error "requested src bpp (src_bpp) is not supported"
.endif
.if mask_bpp == 32
.set mask_bpp_shift, 2
.elseif mask_bpp == 24
.set mask_bpp_shift, 0
.elseif mask_bpp == 8
.set mask_bpp_shift, 0
.elseif mask_bpp == 0
.set mask_bpp_shift, -1
.else
.error "requested mask bpp (mask_bpp) is not supported"
.endif
.if dst_w_bpp == 32
.set dst_bpp_shift, 2
.elseif dst_w_bpp == 24
.set dst_bpp_shift, 0
.elseif dst_w_bpp == 16
.set dst_bpp_shift, 1
.elseif dst_w_bpp == 8
.set dst_bpp_shift, 0
.else
.error "requested dst bpp (dst_w_bpp) is not supported"
.endif
.if (((flags) & FLAG_DST_READWRITE) != 0)
.set dst_r_bpp, dst_w_bpp
.else
.set dst_r_bpp, 0
.endif
.set pix_per_block, 16*8/dst_w_bpp
.if src_bpp != 0
.if 32*8/src_bpp > pix_per_block
.set pix_per_block, 32*8/src_bpp
.endif
.endif
.if mask_bpp != 0
.if 32*8/mask_bpp > pix_per_block
.set pix_per_block, 32*8/mask_bpp
.endif
.endif
.if dst_r_bpp != 0
.if 32*8/dst_r_bpp > pix_per_block
.set pix_per_block, 32*8/dst_r_bpp
.endif
.endif
/* The standard entry conditions set up by pixman-arm-common.h are:
* r0 = width (pixels)
* r1 = height (rows)
* r2 = pointer to top-left pixel of destination
* r3 = destination stride (pixels)
* [sp] = source pixel value, or pointer to top-left pixel of source
* [sp,#4] = 0 or source stride (pixels)
* The following arguments are unused for non-mask operations
* [sp,#8] = mask pixel value, or pointer to top-left pixel of mask
* [sp,#12] = 0 or mask stride (pixels)
*/
/*
* Assign symbolic names to registers
*/
X .req r0 /* pixels to go on this line */
Y .req r1 /* lines to go */
DST .req r2 /* destination pixel pointer */
STRIDE_D .req r3 /* destination stride (bytes, minus width) */
SRC .req r4 /* source pixel pointer */
STRIDE_S .req r5 /* source stride (bytes, minus width) */
MASK .req r6 /* mask pixel pointer (if applicable) */
STRIDE_M .req r7 /* mask stride (bytes, minus width) */
WK0 .req r8 /* pixel data registers */
WK1 .req r9
WK2 .req r10
WK3 .req r11
SCRATCH .req r12
ORIG_W .req r14 /* width (pixels) */
push {r4-r11, lr} /* save all registers */
subs Y, Y, #1
blo 199f
#ifdef DEBUG_PARAMS
sub sp, sp, #9*4
#endif
.if src_bpp > 0
ldr SRC, [sp, #ARGS_STACK_OFFSET]
ldr STRIDE_S, [sp, #ARGS_STACK_OFFSET+4]
.endif
.if mask_bpp > 0
ldr MASK, [sp, #ARGS_STACK_OFFSET+8]
ldr STRIDE_M, [sp, #ARGS_STACK_OFFSET+12]
.endif
#ifdef DEBUG_PARAMS
add Y, Y, #1
stmia sp, {r0-r7,pc}
sub Y, Y, #1
#endif
init
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
/* Reserve a word in which to store X during leading pixels */
sub sp, sp, #4
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET+4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET+4
.endif
lsl STRIDE_D, #dst_bpp_shift /* stride in bytes */
sub STRIDE_D, STRIDE_D, X, lsl #dst_bpp_shift
.if src_bpp > 0
lsl STRIDE_S, #src_bpp_shift
sub STRIDE_S, STRIDE_S, X, lsl #src_bpp_shift
.endif
.if mask_bpp > 0
lsl STRIDE_M, #mask_bpp_shift
sub STRIDE_M, STRIDE_M, X, lsl #mask_bpp_shift
.endif
/* Are we not even wide enough to have one 16-byte aligned 16-byte block write? */
cmp X, #2*16*8/dst_w_bpp - 1
blo 170f
.if src_bpp || mask_bpp || dst_r_bpp /* Wide and medium cases are the same for fill */
/* To preload ahead on the current line, we need at least (prefetch_distance+2) 32-byte blocks on all prefetch channels */
cmp X, #(prefetch_distance+3)*pix_per_block - 1
blo 160f
/* Wide case */
/* Adjust X so that the decrement instruction can also test for
* inner loop termination. We want it to stop when there are
* (prefetch_distance+1) complete blocks to go. */
sub X, X, #(prefetch_distance+2)*pix_per_block
mov ORIG_W, X
.if (flags) & FLAG_SPILL_LINE_VARS_WIDE
/* This is stmdb sp!,{} */
.word 0xE92D0000 | LINE_SAVED_REGS
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
.endif
151: /* New line */
newline
preload_leading_step1 src_bpp, WK1, SRC
preload_leading_step1 mask_bpp, WK2, MASK
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
preload_leading_step1 dst_r_bpp, WK3, DST
.endif
ands WK0, DST, #15
beq 154f
rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */
preload_leading_step2 src_bpp, src_bpp_shift, WK1, SRC
preload_leading_step2 mask_bpp, mask_bpp_shift, WK2, MASK
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
preload_leading_step2 dst_r_bpp, dst_bpp_shift, WK3, DST
.endif
leading_15bytes process_head, process_tail
154: /* Destination now 16-byte aligned; we have at least one prefetch on each channel as well as at least one 16-byte output block */
.if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
and SCRATCH, SRC, #31
rsb SCRATCH, SCRATCH, #32*prefetch_distance
.elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH)
and SCRATCH, MASK, #31
rsb SCRATCH, SCRATCH, #32*prefetch_distance
.endif
.ifc "process_inner_loop",""
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, wide_case_inner_loop, 157f
.else
switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, process_inner_loop, 157f
.endif
157: /* Check for another line */
end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_WIDE), 151b
.if (flags) & FLAG_SPILL_LINE_VARS_WIDE
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
.endif
.endif
.ltorg
160: /* Medium case */
mov ORIG_W, X
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
/* This is stmdb sp!,{} */
.word 0xE92D0000 | LINE_SAVED_REGS
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4
.endif
161: /* New line */
newline
preload_line 0, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
preload_line 0, mask_bpp, mask_bpp_shift, MASK
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
preload_line 0, dst_r_bpp, dst_bpp_shift, DST
.endif
sub X, X, #128/dst_w_bpp /* simplifies inner loop termination */
ands WK0, DST, #15
beq 164f
rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */
leading_15bytes process_head, process_tail
164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */
switch_on_alignment medium_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 167f
167: /* Check for another line */
end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 161b
.ltorg
170: /* Narrow case, less than 31 bytes, so no guarantee of at least one 16-byte block */
.if dst_w_bpp < 32
mov ORIG_W, X
.endif
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
/* This is stmdb sp!,{} */
.word 0xE92D0000 | LINE_SAVED_REGS
.endif
171: /* New line */
newline
preload_line 1, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */
preload_line 1, mask_bpp, mask_bpp_shift, MASK
.if ((flags) & FLAG_NO_PRELOAD_DST) == 0
preload_line 1, dst_r_bpp, dst_bpp_shift, DST
.endif
.if dst_w_bpp == 8
tst DST, #3
beq 174f
172: subs X, X, #1
blo 177f
process_head , 1, 0, 1, 1, 0
process_tail , 1, 0
.if !((flags) & FLAG_PROCESS_DOES_STORE)
pixst , 1, 0, DST
.endif
tst DST, #3
bne 172b
.elseif dst_w_bpp == 16
tst DST, #2
beq 174f
subs X, X, #1
blo 177f
process_head , 2, 0, 1, 1, 0
process_tail , 2, 0
.if !((flags) & FLAG_PROCESS_DOES_STORE)
pixst , 2, 0, DST
.endif
.endif
174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */
switch_on_alignment narrow_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 177f
177: /* Check for another line */
end_of_line %(dst_w_bpp < 32), %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 171b, last_one
.if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4
.endif
197:
.if (flags) & FLAG_SPILL_LINE_VARS
add sp, sp, #LINE_SAVED_REG_COUNT*4
.endif
198:
.if (flags) & FLAG_PROCESS_CORRUPTS_WK0
.set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET-4
.set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET-4
add sp, sp, #4
.endif
cleanup
#ifdef DEBUG_PARAMS
add sp, sp, #9*4 /* junk the debug copy of arguments */
#endif
199:
pop {r4-r11, pc} /* exit */
.ltorg
.unreq X
.unreq Y
.unreq DST
.unreq STRIDE_D
.unreq SRC
.unreq STRIDE_S
.unreq MASK
.unreq STRIDE_M
.unreq WK0
.unreq WK1
.unreq WK2
.unreq WK3
.unreq SCRATCH
.unreq ORIG_W
.endfunc
.endm
.macro line_saved_regs x:vararg
.set LINE_SAVED_REGS, 0
.set LINE_SAVED_REG_COUNT, 0
.irp SAVED_REG,x
.ifc "SAVED_REG","Y"
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<1)
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
.endif
.ifc "SAVED_REG","STRIDE_D"
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<3)
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
.endif
.ifc "SAVED_REG","STRIDE_S"
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<5)
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
.endif
.ifc "SAVED_REG","STRIDE_M"
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<7)
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
.endif
.ifc "SAVED_REG","ORIG_W"
.set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<14)
.set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1
.endif
.endr
.endm
.macro nop_macro x:vararg
.endm

View File

@ -1,291 +0,0 @@
/*
* Copyright © 2008 Mozilla Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Mozilla Corporation not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Mozilla Corporation makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Jeff Muizelaar (jeff@infidigm.net)
*
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
#include "pixman-arm-common.h"
#include "pixman-inlines.h"
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_x888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_0565_0565,
uint16_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_0565_8888,
uint16_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, src_x888_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, add_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, over_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_DST (armv6, in_reverse_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, armv6, over_n_8888,
uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_DST (0, armv6, over_reverse_n_8888,
uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, armv6, over_8888_n_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, armv6, over_n_8888_8888_ca,
uint32_t, 1, uint32_t, 1)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 0565_0565, SRC,
uint16_t, uint16_t)
PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST (armv6, 8888_8888, SRC,
uint32_t, uint32_t)
void
pixman_composite_src_n_8888_asm_armv6 (int32_t w,
int32_t h,
uint32_t *dst,
int32_t dst_stride,
uint32_t src);
void
pixman_composite_src_n_0565_asm_armv6 (int32_t w,
int32_t h,
uint16_t *dst,
int32_t dst_stride,
uint16_t src);
void
pixman_composite_src_n_8_asm_armv6 (int32_t w,
int32_t h,
uint8_t *dst,
int32_t dst_stride,
uint8_t src);
static pixman_bool_t
arm_simd_fill (pixman_implementation_t *imp,
uint32_t * bits,
int stride, /* in 32-bit words */
int bpp,
int x,
int y,
int width,
int height,
uint32_t _xor)
{
/* stride is always multiple of 32bit units in pixman */
uint32_t byte_stride = stride * sizeof(uint32_t);
switch (bpp)
{
case 8:
pixman_composite_src_n_8_asm_armv6 (
width,
height,
(uint8_t *)(((char *) bits) + y * byte_stride + x),
byte_stride,
_xor & 0xff);
return TRUE;
case 16:
pixman_composite_src_n_0565_asm_armv6 (
width,
height,
(uint16_t *)(((char *) bits) + y * byte_stride + x * 2),
byte_stride / 2,
_xor & 0xffff);
return TRUE;
case 32:
pixman_composite_src_n_8888_asm_armv6 (
width,
height,
(uint32_t *)(((char *) bits) + y * byte_stride + x * 4),
byte_stride / 4,
_xor);
return TRUE;
default:
return FALSE;
}
}
static pixman_bool_t
arm_simd_blt (pixman_implementation_t *imp,
uint32_t * src_bits,
uint32_t * dst_bits,
int src_stride, /* in 32-bit words */
int dst_stride, /* in 32-bit words */
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dest_x,
int dest_y,
int width,
int height)
{
if (src_bpp != dst_bpp)
return FALSE;
switch (src_bpp)
{
case 8:
pixman_composite_src_8_8_asm_armv6 (
width, height,
(uint8_t *)(((char *) dst_bits) +
dest_y * dst_stride * 4 + dest_x * 1), dst_stride * 4,
(uint8_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 1), src_stride * 4);
return TRUE;
case 16:
pixman_composite_src_0565_0565_asm_armv6 (
width, height,
(uint16_t *)(((char *) dst_bits) +
dest_y * dst_stride * 4 + dest_x * 2), dst_stride * 2,
(uint16_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 2), src_stride * 2);
return TRUE;
case 32:
pixman_composite_src_8888_8888_asm_armv6 (
width, height,
(uint32_t *)(((char *) dst_bits) +
dest_y * dst_stride * 4 + dest_x * 4), dst_stride,
(uint32_t *)(((char *) src_bits) +
src_y * src_stride * 4 + src_x * 4), src_stride);
return TRUE;
default:
return FALSE;
}
}
static const pixman_fast_path_t arm_simd_fast_paths[] =
{
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, armv6_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, armv6_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, armv6_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, a1r5g5b5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a1b5g5r5, null, a1b5g5r5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a1r5g5b5, null, x1r5g5b5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a1b5g5r5, null, x1b5g5r5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, x1r5g5b5, null, x1r5g5b5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, x1b5g5r5, null, x1b5g5r5, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a4r4g4b4, null, a4r4g4b4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a4b4g4r4, null, a4b4g4r4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a4r4g4b4, null, x4r4g4b4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a4b4g4r4, null, x4b4g4r4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, x4r4g4b4, null, x4r4g4b4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, x4b4g4r4, null, x4b4g4r4, armv6_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a8, null, a8, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, r3g3b2, null, r3g3b2, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, b2g3r3, null, b2g3r3, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, a2r2g2b2, null, a2r2g2b2, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, a2b2g2r2, null, a2b2g2r2, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, c8, null, c8, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, g8, null, g8, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, x4a4, null, x4a4, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, x4c4, null, x4c4, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, x4g4, null, x4g4, armv6_composite_src_8_8),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, armv6_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, armv6_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, armv6_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, armv6_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, armv6_composite_src_x888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, armv6_composite_src_x888_0565),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, armv6_composite_src_x888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, armv6_composite_src_x888_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, armv6_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, armv6_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, armv6_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, armv6_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, armv6_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, armv6_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, a8b8g8r8, armv6_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, x8b8g8r8, armv6_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, armv6_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, armv6_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8b8g8r8, armv6_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8b8g8r8, armv6_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, armv6_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, armv6_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, armv6_composite_add_8_8),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, armv6_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, armv6_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, armv6_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, armv6_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8r8g8b8, null, a8r8g8b8, armv6_composite_in_reverse_8888_8888),
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8r8g8b8, null, x8r8g8b8, armv6_composite_in_reverse_8888_8888),
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8b8g8r8, null, a8b8g8r8, armv6_composite_in_reverse_8888_8888),
PIXMAN_STD_FAST_PATH (IN_REVERSE, a8b8g8r8, null, x8b8g8r8, armv6_composite_in_reverse_8888_8888),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, armv6_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, armv6_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, armv6_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, armv6_composite_over_n_8888_8888_ca),
SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, r5g6b5, armv6_0565_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, b5g6r5, armv6_0565_0565),
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, armv6_8888_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, armv6_8888_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, armv6_8888_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, armv6_8888_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, armv6_8888_8888),
SIMPLE_NEAREST_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, armv6_8888_8888),
{ PIXMAN_OP_NONE },
};
pixman_implementation_t *
_pixman_implementation_create_arm_simd (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp = _pixman_implementation_create (fallback, arm_simd_fast_paths);
imp->blt = arm_simd_blt;
imp->fill = arm_simd_fill;
return imp;
}

View File

@ -1,256 +0,0 @@
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
typedef enum
{
ARM_V7 = (1 << 0),
ARM_V6 = (1 << 1),
ARM_VFP = (1 << 2),
ARM_NEON = (1 << 3),
ARM_IWMMXT = (1 << 4)
} arm_cpu_features_t;
#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
#if defined(_MSC_VER)
/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
#include <windows.h>
extern int pixman_msvc_try_arm_neon_op ();
extern int pixman_msvc_try_arm_simd_op ();
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
__try
{
pixman_msvc_try_arm_simd_op ();
features |= ARM_V6;
}
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
{
}
__try
{
pixman_msvc_try_arm_neon_op ();
features |= ARM_NEON;
}
__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
{
}
return features;
}
#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */
#include "TargetConditionals.h"
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
features |= ARM_V6;
/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
* contain separate executable images for each processor architecture.
* So all we have to do is detect the armv7 architecture build. The
* operating system automatically runs the armv7 binary for armv7 devices
* and the armv6 binary for armv6 devices.
*/
#if defined(__ARM_NEON__)
features |= ARM_NEON;
#endif
return features;
}
#elif defined(__ANDROID__) || defined(ANDROID) /* Android */
#include <cpu-features.h>
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
AndroidCpuFamily cpu_family;
uint64_t cpu_features;
cpu_family = android_getCpuFamily();
cpu_features = android_getCpuFeatures();
if (cpu_family == ANDROID_CPU_FAMILY_ARM)
{
if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7)
features |= ARM_V7;
if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3)
features |= ARM_VFP;
if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)
features |= ARM_NEON;
}
return features;
}
#elif defined (__linux__) /* linux ELF */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <elf.h>
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
Elf32_auxv_t aux;
int fd;
fd = open ("/proc/self/auxv", O_RDONLY);
if (fd >= 0)
{
while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
{
if (aux.a_type == AT_HWCAP)
{
uint32_t hwcap = aux.a_un.a_val;
/* hardcode these values to avoid depending on specific
* versions of the hwcap header, e.g. HWCAP_NEON
*/
if ((hwcap & 64) != 0)
features |= ARM_VFP;
if ((hwcap & 512) != 0)
features |= ARM_IWMMXT;
/* this flag is only present on kernel 2.6.29 */
if ((hwcap & 4096) != 0)
features |= ARM_NEON;
}
else if (aux.a_type == AT_PLATFORM)
{
const char *plat = (const char*) aux.a_un.a_val;
if (strncmp (plat, "v7l", 3) == 0)
features |= (ARM_V7 | ARM_V6);
else if (strncmp (plat, "v6l", 3) == 0)
features |= ARM_V6;
}
}
close (fd);
}
return features;
}
#elif defined (_3DS) /* 3DS homebrew (devkitARM) */
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
features |= ARM_V6;
return features;
}
#elif defined (PSP2) || defined (__SWITCH__)
/* Vita (VitaSDK) or Switch (devkitA64) homebrew */
static arm_cpu_features_t
detect_cpu_features (void)
{
arm_cpu_features_t features = 0;
features |= ARM_NEON;
return features;
}
#else /* Unknown */
static arm_cpu_features_t
detect_cpu_features (void)
{
return 0;
}
#endif /* Linux elf */
static pixman_bool_t
have_feature (arm_cpu_features_t feature)
{
static pixman_bool_t initialized;
static arm_cpu_features_t features;
if (!initialized)
{
features = detect_cpu_features();
initialized = TRUE;
}
return (features & feature) == feature;
}
#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
pixman_implementation_t *
_pixman_arm_get_implementations (pixman_implementation_t *imp)
{
#ifdef USE_ARM_SIMD
if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6))
imp = _pixman_implementation_create_arm_simd (imp);
#endif
#ifdef USE_ARM_IWMMXT
if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT))
imp = _pixman_implementation_create_mmx (imp);
#endif
#ifdef USE_ARM_NEON
if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON))
imp = _pixman_implementation_create_arm_neon (imp);
#endif
#ifdef USE_ARM_A64_NEON
/* neon is a part of aarch64 */
if (!_pixman_disabled ("arm-neon"))
imp = _pixman_implementation_create_arm_neon (imp);
#endif
return imp;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,272 +0,0 @@
#define COMPONENT_SIZE 8
#define MASK 0xff
#define ONE_HALF 0x80
#define A_SHIFT 8 * 3
#define R_SHIFT 8 * 2
#define G_SHIFT 8
#define A_MASK 0xff000000
#define R_MASK 0xff0000
#define G_MASK 0xff00
#define RB_MASK 0xff00ff
#define AG_MASK 0xff00ff00
#define RB_ONE_HALF 0x800080
#define RB_MASK_PLUS_ONE 0x1000100
#define ALPHA_8(x) ((x) >> A_SHIFT)
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
#define BLUE_8(x) ((x) & MASK)
/*
* ARMv6 has UQADD8 instruction, which implements unsigned saturated
* addition for 8-bit values packed in 32-bit registers. It is very useful
* for UN8x4_ADD_UN8x4, UN8_rb_ADD_UN8_rb and ADD_UN8 macros (which would
* otherwise need a lot of arithmetic operations to simulate this operation).
* Since most of the major ARM linux distros are built for ARMv7, we are
* much less dependent on runtime CPU detection and can get practical
* benefits from conditional compilation here for a lot of users.
*/
#if defined(USE_GCC_INLINE_ASM) && defined(__arm__) && \
!defined(__aarch64__) && (!defined(__thumb__) || defined(__thumb2__))
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
static force_inline uint32_t
un8x4_add_un8x4 (uint32_t x, uint32_t y)
{
uint32_t t;
asm ("uqadd8 %0, %1, %2" : "=r" (t) : "%r" (x), "r" (y));
return t;
}
#define UN8x4_ADD_UN8x4(x, y) \
((x) = un8x4_add_un8x4 ((x), (y)))
#define UN8_rb_ADD_UN8_rb(x, y, t) \
((t) = un8x4_add_un8x4 ((x), (y)), (x) = (t))
#define ADD_UN8(x, y, t) \
((t) = (x), un8x4_add_un8x4 ((t), (y)))
#endif
#endif
/*****************************************************************************/
/*
* Helper macros.
*/
#define MUL_UN8(a, b, t) \
((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
#define DIV_UN8(a, b) \
(((uint16_t) (a) * MASK + ((b) / 2)) / (b))
#ifndef ADD_UN8
#define ADD_UN8(x, y, t) \
((t) = (x) + (y), \
(uint32_t) (uint8_t) ((t) | (0 - ((t) >> G_SHIFT))))
#endif
#define DIV_ONE_UN8(x) \
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
/*
* The methods below use some tricks to be able to do two color
* components at the same time.
*/
/*
* x_rb = (x_rb * a) / 255
*/
#define UN8_rb_MUL_UN8(x, a, t) \
do \
{ \
t = ((x) & RB_MASK) * (a); \
t += RB_ONE_HALF; \
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
x &= RB_MASK; \
} while (0)
/*
* x_rb = min (x_rb + y_rb, 255)
*/
#ifndef UN8_rb_ADD_UN8_rb
#define UN8_rb_ADD_UN8_rb(x, y, t) \
do \
{ \
t = ((x) + (y)); \
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
x = (t & RB_MASK); \
} while (0)
#endif
/*
* x_rb = (x_rb * a_rb) / 255
*/
#define UN8_rb_MUL_UN8_rb(x, a, t) \
do \
{ \
t = (x & MASK) * (a & MASK); \
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
t += RB_ONE_HALF; \
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
x = t & RB_MASK; \
} while (0)
/*
* x_c = (x_c * a) / 255
*/
#define UN8x4_MUL_UN8(x, a) \
do \
{ \
uint32_t r1__, r2__, t__; \
\
r1__ = (x); \
UN8_rb_MUL_UN8 (r1__, (a), t__); \
\
r2__ = (x) >> G_SHIFT; \
UN8_rb_MUL_UN8 (r2__, (a), t__); \
\
(x) = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
* x_c = (x_c * a) / 255 + y_c
*/
#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x); \
r2__ = (y) & RB_MASK; \
UN8_rb_MUL_UN8 (r1__, (a), t__); \
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
\
r2__ = (x) >> G_SHIFT; \
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
UN8_rb_MUL_UN8 (r2__, (a), t__); \
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
\
(x) = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
* x_c = (x_c * a + y_c * b) / 255
*/
#define UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8(x, a, y, b) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x); \
r2__ = (y); \
UN8_rb_MUL_UN8 (r1__, (a), t__); \
UN8_rb_MUL_UN8 (r2__, (b), t__); \
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
\
r2__ = ((x) >> G_SHIFT); \
r3__ = ((y) >> G_SHIFT); \
UN8_rb_MUL_UN8 (r2__, (a), t__); \
UN8_rb_MUL_UN8 (r3__, (b), t__); \
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
\
(x) = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
* x_c = (x_c * a_c) / 255
*/
#define UN8x4_MUL_UN8x4(x, a) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x); \
r2__ = (a); \
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
\
r2__ = (x) >> G_SHIFT; \
r3__ = (a) >> G_SHIFT; \
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
\
(x) = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
* x_c = (x_c * a_c) / 255 + y_c
*/
#define UN8x4_MUL_UN8x4_ADD_UN8x4(x, a, y) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x); \
r2__ = (a); \
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
r2__ = (y) & RB_MASK; \
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
\
r2__ = ((x) >> G_SHIFT); \
r3__ = ((a) >> G_SHIFT); \
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
\
(x) = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
* x_c = (x_c * a_c + y_c * b) / 255
*/
#define UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8(x, a, y, b) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x); \
r2__ = (a); \
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
r2__ = (y); \
UN8_rb_MUL_UN8 (r2__, (b), t__); \
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
\
r2__ = (x) >> G_SHIFT; \
r3__ = (a) >> G_SHIFT; \
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
r3__ = (y) >> G_SHIFT; \
UN8_rb_MUL_UN8 (r3__, (b), t__); \
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
\
x = r1__ | (r2__ << G_SHIFT); \
} while (0)
/*
x_c = min(x_c + y_c, 255)
*/
#ifndef UN8x4_ADD_UN8x4
#define UN8x4_ADD_UN8x4(x, y) \
do \
{ \
uint32_t r1__, r2__, r3__, t__; \
\
r1__ = (x) & RB_MASK; \
r2__ = (y) & RB_MASK; \
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
\
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
\
x = r1__ | (r2__ << G_SHIFT); \
} while (0)
#endif

View File

@ -1,234 +0,0 @@
/* Pixman uses some non-standard compiler features. This file ensures
* they exist
*
* The features are:
*
* FUNC must be defined to expand to the current function
* PIXMAN_EXPORT should be defined to whatever is required to
* export functions from a shared library
* limits limits for various types must be defined
* inline must be defined
* force_inline must be defined
*/
#if defined (__GNUC__)
# define FUNC ((const char*) (__PRETTY_FUNCTION__))
#elif defined (__sun) || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
# define FUNC ((const char*) (__func__))
#else
# define FUNC ((const char*) ("???"))
#endif
#if defined (__GNUC__)
# define unlikely(expr) __builtin_expect ((expr), 0)
#else
# define unlikely(expr) (expr)
#endif
#if defined (__GNUC__)
# define MAYBE_UNUSED __attribute__((unused))
#else
# define MAYBE_UNUSED
#endif
#ifndef INT16_MIN
# define INT16_MIN (-32767-1)
#endif
#ifndef INT16_MAX
# define INT16_MAX (32767)
#endif
#ifndef INT32_MIN
# define INT32_MIN (-2147483647-1)
#endif
#ifndef INT32_MAX
# define INT32_MAX (2147483647)
#endif
#ifndef UINT32_MIN
# define UINT32_MIN (0)
#endif
#ifndef UINT32_MAX
# define UINT32_MAX (4294967295U)
#endif
#ifndef INT64_MIN
# define INT64_MIN (-9223372036854775807-1)
#endif
#ifndef INT64_MAX
# define INT64_MAX (9223372036854775807)
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
#ifdef _MSC_VER
/* 'inline' is available only in C++ in MSVC */
# define inline __inline
# define force_inline __forceinline
# define noinline __declspec(noinline)
#elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define inline __inline__
# define force_inline __inline__ __attribute__ ((__always_inline__))
# define noinline __attribute__((noinline))
#else
# ifndef force_inline
# define force_inline inline
# endif
# ifndef noinline
# define noinline
# endif
#endif
/* GCC visibility */
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
# define PIXMAN_EXPORT __attribute__ ((visibility("default")))
/* Sun Studio 8 visibility */
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define PIXMAN_EXPORT __global
#elif defined (_MSC_VER) || defined(__MINGW32__)
# define PIXMAN_EXPORT PIXMAN_API
#else
# define PIXMAN_EXPORT
#endif
/* member offsets */
#define CONTAINER_OF(type, member, data) \
((type *)(((uint8_t *)data) - offsetof (type, member)))
/* TLS */
#if defined(PIXMAN_NO_TLS)
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static type name;
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)
#elif defined(TLS)
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static TLS type name;
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)
#elif defined(__MINGW32__)
# define _NO_W32_PSEUDO_MODIFIERS
# include <windows.h>
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static volatile int tls_ ## name ## _initialized = 0; \
static void *tls_ ## name ## _mutex = NULL; \
static unsigned tls_ ## name ## _index; \
\
static type * \
tls_ ## name ## _alloc (void) \
{ \
type *value = calloc (1, sizeof (type)); \
if (value) \
TlsSetValue (tls_ ## name ## _index, value); \
return value; \
} \
\
static force_inline type * \
tls_ ## name ## _get (void) \
{ \
type *value; \
if (!tls_ ## name ## _initialized) \
{ \
if (!tls_ ## name ## _mutex) \
{ \
void *mutex = CreateMutexA (NULL, 0, NULL); \
if (InterlockedCompareExchangePointer ( \
&tls_ ## name ## _mutex, mutex, NULL) != NULL) \
{ \
CloseHandle (mutex); \
} \
} \
WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \
if (!tls_ ## name ## _initialized) \
{ \
tls_ ## name ## _index = TlsAlloc (); \
tls_ ## name ## _initialized = 1; \
} \
ReleaseMutex (tls_ ## name ## _mutex); \
} \
if (tls_ ## name ## _index == 0xFFFFFFFF) \
return NULL; \
value = TlsGetValue (tls_ ## name ## _index); \
if (!value) \
value = tls_ ## name ## _alloc (); \
return value; \
}
# define PIXMAN_GET_THREAD_LOCAL(name) \
tls_ ## name ## _get ()
#elif defined(_MSC_VER)
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static __declspec(thread) type name;
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)
#elif defined(HAVE_PTHREADS)
#include <pthread.h>
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
static pthread_key_t tls_ ## name ## _key; \
\
static void \
tls_ ## name ## _destroy_value (void *value) \
{ \
free (value); \
} \
\
static void \
tls_ ## name ## _make_key (void) \
{ \
pthread_key_create (&tls_ ## name ## _key, \
tls_ ## name ## _destroy_value); \
} \
\
static type * \
tls_ ## name ## _alloc (void) \
{ \
type *value = calloc (1, sizeof (type)); \
if (value) \
pthread_setspecific (tls_ ## name ## _key, value); \
return value; \
} \
\
static force_inline type * \
tls_ ## name ## _get (void) \
{ \
type *value = NULL; \
if (pthread_once (&tls_ ## name ## _once_control, \
tls_ ## name ## _make_key) == 0) \
{ \
value = pthread_getspecific (tls_ ## name ## _key); \
if (!value) \
value = tls_ ## name ## _alloc (); \
} \
return value; \
}
# define PIXMAN_GET_THREAD_LOCAL(name) \
tls_ ## name ## _get ()
#else
# error "Unknown thread local support for this system. Pixman will not work with multiple threads. Define PIXMAN_NO_TLS to acknowledge and accept this limitation and compile pixman without thread-safety support."
#endif

View File

@ -1,220 +0,0 @@
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include <math.h>
#include "pixman-private.h"
static force_inline double
coordinates_to_parameter (double x, double y, double angle)
{
double t;
t = atan2 (y, x) + angle;
while (t < 0)
t += 2 * M_PI;
while (t >= 2 * M_PI)
t -= 2 * M_PI;
return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
* make rotation CCW
*/
}
static uint32_t *
conical_get_scanline (pixman_iter_t *iter,
const uint32_t *mask,
int Bpp,
pixman_gradient_walker_write_t write_pixel)
{
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t *buffer = iter->buffer;
gradient_t *gradient = (gradient_t *)image;
conical_gradient_t *conical = (conical_gradient_t *)image;
uint32_t *end = buffer + width * (Bpp / 4);
pixman_gradient_walker_t walker;
pixman_bool_t affine = TRUE;
double cx = 1.;
double cy = 0.;
double cz = 0.;
double rx = x + 0.5;
double ry = y + 0.5;
double rz = 1.;
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
if (image->common.transform)
{
pixman_vector_t v;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
if (!pixman_transform_point_3d (image->common.transform, &v))
return iter->buffer;
cx = image->common.transform->matrix[0][0] / 65536.;
cy = image->common.transform->matrix[1][0] / 65536.;
cz = image->common.transform->matrix[2][0] / 65536.;
rx = v.vector[0] / 65536.;
ry = v.vector[1] / 65536.;
rz = v.vector[2] / 65536.;
affine =
image->common.transform->matrix[2][0] == 0 &&
v.vector[2] == pixman_fixed_1;
}
if (affine)
{
rx -= conical->center.x / 65536.;
ry -= conical->center.y / 65536.;
while (buffer < end)
{
if (!mask || *mask++)
{
double t = coordinates_to_parameter (rx, ry, conical->angle);
write_pixel (&walker,
(pixman_fixed_48_16_t)pixman_double_to_fixed (t),
buffer);
}
buffer += (Bpp / 4);
rx += cx;
ry += cy;
}
}
else
{
while (buffer < end)
{
double x, y;
if (!mask || *mask++)
{
double t;
if (rz != 0)
{
x = rx / rz;
y = ry / rz;
}
else
{
x = y = 0.;
}
x -= conical->center.x / 65536.;
y -= conical->center.y / 65536.;
t = coordinates_to_parameter (x, y, conical->angle);
write_pixel (&walker,
(pixman_fixed_48_16_t)pixman_double_to_fixed (t),
buffer);
}
buffer += (Bpp / 4);
rx += cx;
ry += cy;
rz += cz;
}
}
iter->y++;
return iter->buffer;
}
static uint32_t *
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
return conical_get_scanline (iter, mask, 4,
_pixman_gradient_walker_write_narrow);
}
static uint32_t *
conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
return conical_get_scanline (iter, NULL, 16,
_pixman_gradient_walker_write_wide);
}
void
_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
if (iter->iter_flags & ITER_NARROW)
iter->get_scanline = conical_get_scanline_narrow;
else
iter->get_scanline = conical_get_scanline_wide;
}
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_conical_gradient (const pixman_point_fixed_t * center,
pixman_fixed_t angle,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_image_t *image = _pixman_image_allocate ();
conical_gradient_t *conical;
if (!image)
return NULL;
conical = &image->conical;
if (!_pixman_init_gradient (&conical->common, stops, n_stops))
{
free (image);
return NULL;
}
angle = MOD (angle, pixman_int_to_fixed (360));
image->type = CONICAL;
conical->center = *center;
conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
return image;
}

View File

@ -1,4 +0,0 @@
#define PIXMAN_FB_ACCESSORS
#include "pixman-edge.c"

View File

@ -1,182 +0,0 @@
/*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef rasterize_span
#endif
static void
RASTERIZE_EDGES (pixman_image_t *image,
pixman_edge_t *l,
pixman_edge_t *r,
pixman_fixed_t t,
pixman_fixed_t b)
{
pixman_fixed_t y = t;
uint32_t *line;
uint32_t *buf = (image)->bits.bits;
int stride = (image)->bits.rowstride;
int width = (image)->bits.width;
line = buf + pixman_fixed_to_int (y) * stride;
for (;;)
{
pixman_fixed_t lx;
pixman_fixed_t rx;
int lxi;
int rxi;
lx = l->x;
rx = r->x;
#if N_BITS == 1
/* For the non-antialiased case, round the coordinates up, in effect
* sampling just slightly to the left of the pixel. This is so that
* when the sample point lies exactly on the line, we round towards
* north-west.
*
* (The AA case does a similar adjustment in RENDER_SAMPLES_X)
*/
lx += X_FRAC_FIRST(1) - pixman_fixed_e;
rx += X_FRAC_FIRST(1) - pixman_fixed_e;
#endif
/* clip X */
if (lx < 0)
lx = 0;
if (pixman_fixed_to_int (rx) >= width)
#if N_BITS == 1
rx = pixman_int_to_fixed (width);
#else
/* Use the last pixel of the scanline, covered 100%.
* We can't use the first pixel following the scanline,
* because accessing it could result in a buffer overrun.
*/
rx = pixman_int_to_fixed (width) - 1;
#endif
/* Skip empty (or backwards) sections */
if (rx > lx)
{
/* Find pixel bounds for span */
lxi = pixman_fixed_to_int (lx);
rxi = pixman_fixed_to_int (rx);
#if N_BITS == 1
{
#define LEFT_MASK(x) \
(((x) & 0x1f) ? \
SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0)
#define RIGHT_MASK(x) \
(((32 - (x)) & 0x1f) ? \
SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0)
#define MASK_BITS(x,w,l,n,r) { \
n = (w); \
r = RIGHT_MASK ((x) + n); \
l = LEFT_MASK (x); \
if (l) { \
n -= 32 - ((x) & 0x1f); \
if (n < 0) { \
n = 0; \
l &= r; \
r = 0; \
} \
} \
n >>= 5; \
}
uint32_t *a = line;
uint32_t startmask;
uint32_t endmask;
int nmiddle;
int width = rxi - lxi;
int x = lxi;
a += x >> 5;
x &= 0x1f;
MASK_BITS (x, width, startmask, nmiddle, endmask);
if (startmask) {
WRITE(image, a, READ(image, a) | startmask);
a++;
}
while (nmiddle--)
WRITE(image, a++, 0xffffffff);
if (endmask)
WRITE(image, a, READ(image, a) | endmask);
}
#else
{
DEFINE_ALPHA(line,lxi);
int lxs;
int rxs;
/* Sample coverage for edge pixels */
lxs = RENDER_SAMPLES_X (lx, N_BITS);
rxs = RENDER_SAMPLES_X (rx, N_BITS);
/* Add coverage across row */
if (lxi == rxi)
{
ADD_ALPHA (rxs - lxs);
}
else
{
int xi;
ADD_ALPHA (N_X_FRAC(N_BITS) - lxs);
STEP_ALPHA;
for (xi = lxi + 1; xi < rxi; xi++)
{
ADD_ALPHA (N_X_FRAC(N_BITS));
STEP_ALPHA;
}
ADD_ALPHA (rxs);
}
}
#endif
}
if (y == b)
break;
#if N_BITS > 1
if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS))
{
RENDER_EDGE_STEP_SMALL (l);
RENDER_EDGE_STEP_SMALL (r);
y += STEP_Y_SMALL(N_BITS);
}
else
#endif
{
RENDER_EDGE_STEP_BIG (l);
RENDER_EDGE_STEP_BIG (r);
y += STEP_Y_BIG(N_BITS);
line += stride;
}
}
}
#undef rasterize_span

View File

@ -1,385 +0,0 @@
/*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <string.h>
#include "pixman-private.h"
#include "pixman-accessor.h"
/*
* Step across a small sample grid gap
*/
#define RENDER_EDGE_STEP_SMALL(edge) \
{ \
edge->x += edge->stepx_small; \
edge->e += edge->dx_small; \
if (edge->e > 0) \
{ \
edge->e -= edge->dy; \
edge->x += edge->signdx; \
} \
}
/*
* Step across a large sample grid gap
*/
#define RENDER_EDGE_STEP_BIG(edge) \
{ \
edge->x += edge->stepx_big; \
edge->e += edge->dx_big; \
if (edge->e > 0) \
{ \
edge->e -= edge->dy; \
edge->x += edge->signdx; \
} \
}
#ifdef PIXMAN_FB_ACCESSORS
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
#else
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
#endif
/*
* 4 bit alpha
*/
#define N_BITS 4
#define RASTERIZE_EDGES rasterize_edges_4
#ifndef WORDS_BIGENDIAN
#define SHIFT_4(o) ((o) << 2)
#else
#define SHIFT_4(o) ((1 - (o)) << 2)
#endif
#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
#define PUT_4(x, o, v) \
(((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
#define DEFINE_ALPHA(line, x) \
uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
int __ao = (x) & 1
#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
#define ADD_ALPHA(a) \
{ \
uint8_t __o = READ (image, __ap); \
uint8_t __a = (a) + GET_4 (__o, __ao); \
WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
}
#include "pixman-edge-imp.h"
#undef ADD_ALPHA
#undef STEP_ALPHA
#undef DEFINE_ALPHA
#undef RASTERIZE_EDGES
#undef N_BITS
/*
* 1 bit alpha
*/
#define N_BITS 1
#define RASTERIZE_EDGES rasterize_edges_1
#include "pixman-edge-imp.h"
#undef RASTERIZE_EDGES
#undef N_BITS
/*
* 8 bit alpha
*/
static force_inline uint8_t
clip255 (int x)
{
if (x > 255)
return 255;
return x;
}
#define ADD_SATURATE_8(buf, val, length) \
do \
{ \
int i__ = (length); \
uint8_t *buf__ = (buf); \
int val__ = (val); \
\
while (i__--) \
{ \
WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
(buf__)++; \
} \
} while (0)
/*
* We want to detect the case where we add the same value to a long
* span of pixels. The triangles on the end are filled in while we
* count how many sub-pixel scanlines contribute to the middle section.
*
* +--------------------------+
* fill_height =| \ /
* +------------------+
* |================|
* fill_start fill_end
*/
static void
rasterize_edges_8 (pixman_image_t *image,
pixman_edge_t * l,
pixman_edge_t * r,
pixman_fixed_t t,
pixman_fixed_t b)
{
pixman_fixed_t y = t;
uint32_t *line;
int fill_start = -1, fill_end = -1;
int fill_size = 0;
uint32_t *buf = (image)->bits.bits;
int stride = (image)->bits.rowstride;
int width = (image)->bits.width;
line = buf + pixman_fixed_to_int (y) * stride;
for (;;)
{
uint8_t *ap = (uint8_t *) line;
pixman_fixed_t lx, rx;
int lxi, rxi;
/* clip X */
lx = l->x;
if (lx < 0)
lx = 0;
rx = r->x;
if (pixman_fixed_to_int (rx) >= width)
{
/* Use the last pixel of the scanline, covered 100%.
* We can't use the first pixel following the scanline,
* because accessing it could result in a buffer overrun.
*/
rx = pixman_int_to_fixed (width) - 1;
}
/* Skip empty (or backwards) sections */
if (rx > lx)
{
int lxs, rxs;
/* Find pixel bounds for span. */
lxi = pixman_fixed_to_int (lx);
rxi = pixman_fixed_to_int (rx);
/* Sample coverage for edge pixels */
lxs = RENDER_SAMPLES_X (lx, 8);
rxs = RENDER_SAMPLES_X (rx, 8);
/* Add coverage across row */
if (lxi == rxi)
{
WRITE (image, ap + lxi,
clip255 (READ (image, ap + lxi) + rxs - lxs));
}
else
{
WRITE (image, ap + lxi,
clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
/* Move forward so that lxi/rxi is the pixel span */
lxi++;
/* Don't bother trying to optimize the fill unless
* the span is longer than 4 pixels. */
if (rxi - lxi > 4)
{
if (fill_start < 0)
{
fill_start = lxi;
fill_end = rxi;
fill_size++;
}
else
{
if (lxi >= fill_end || rxi < fill_start)
{
/* We're beyond what we saved, just fill it */
ADD_SATURATE_8 (ap + fill_start,
fill_size * N_X_FRAC (8),
fill_end - fill_start);
fill_start = lxi;
fill_end = rxi;
fill_size = 1;
}
else
{
/* Update fill_start */
if (lxi > fill_start)
{
ADD_SATURATE_8 (ap + fill_start,
fill_size * N_X_FRAC (8),
lxi - fill_start);
fill_start = lxi;
}
else if (lxi < fill_start)
{
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
fill_start - lxi);
}
/* Update fill_end */
if (rxi < fill_end)
{
ADD_SATURATE_8 (ap + rxi,
fill_size * N_X_FRAC (8),
fill_end - rxi);
fill_end = rxi;
}
else if (fill_end < rxi)
{
ADD_SATURATE_8 (ap + fill_end,
N_X_FRAC (8),
rxi - fill_end);
}
fill_size++;
}
}
}
else
{
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
}
WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
}
}
if (y == b)
{
/* We're done, make sure we clean up any remaining fill. */
if (fill_start != fill_end)
{
if (fill_size == N_Y_FRAC (8))
{
MEMSET_WRAPPED (image, ap + fill_start,
0xff, fill_end - fill_start);
}
else
{
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
fill_end - fill_start);
}
}
break;
}
if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
{
RENDER_EDGE_STEP_SMALL (l);
RENDER_EDGE_STEP_SMALL (r);
y += STEP_Y_SMALL (8);
}
else
{
RENDER_EDGE_STEP_BIG (l);
RENDER_EDGE_STEP_BIG (r);
y += STEP_Y_BIG (8);
if (fill_start != fill_end)
{
if (fill_size == N_Y_FRAC (8))
{
MEMSET_WRAPPED (image, ap + fill_start,
0xff, fill_end - fill_start);
}
else
{
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
fill_end - fill_start);
}
fill_start = fill_end = -1;
fill_size = 0;
}
line += stride;
}
}
}
#ifndef PIXMAN_FB_ACCESSORS
static
#endif
void
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
pixman_edge_t * l,
pixman_edge_t * r,
pixman_fixed_t t,
pixman_fixed_t b)
{
switch (PIXMAN_FORMAT_BPP (image->bits.format))
{
case 1:
rasterize_edges_1 (image, l, r, t, b);
break;
case 4:
rasterize_edges_4 (image, l, r, t, b);
break;
case 8:
rasterize_edges_8 (image, l, r, t, b);
break;
default:
break;
}
}
#ifndef PIXMAN_FB_ACCESSORS
PIXMAN_EXPORT void
pixman_rasterize_edges (pixman_image_t *image,
pixman_edge_t * l,
pixman_edge_t * r,
pixman_fixed_t t,
pixman_fixed_t b)
{
return_if_fail (image->type == BITS);
return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
if (image->bits.read_func || image->bits.write_func)
pixman_rasterize_edges_accessors (image, l, r, t, b);
else
pixman_rasterize_edges_no_accessors (image, l, r, t, b);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,491 +0,0 @@
/*
* Copyright 2012, Red Hat, Inc.
* Copyright 2012, Soren Sandmann
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Soren Sandmann <soren.sandmann@gmail.com>
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
typedef double (* kernel_func_t) (double x);
typedef struct
{
pixman_kernel_t kernel;
kernel_func_t func;
double width;
} filter_info_t;
static double
impulse_kernel (double x)
{
return (x == 0.0)? 1.0 : 0.0;
}
static double
box_kernel (double x)
{
return 1;
}
static double
linear_kernel (double x)
{
return 1 - fabs (x);
}
static double
gaussian_kernel (double x)
{
#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
#define SIGMA (SQRT2 / 2.0)
return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
}
static double
sinc (double x)
{
if (x == 0.0)
return 1.0;
else
return sin (M_PI * x) / (M_PI * x);
}
static double
lanczos (double x, int n)
{
return sinc (x) * sinc (x * (1.0 / n));
}
static double
lanczos2_kernel (double x)
{
return lanczos (x, 2);
}
static double
lanczos3_kernel (double x)
{
return lanczos (x, 3);
}
static double
nice_kernel (double x)
{
return lanczos3_kernel (x * 0.75);
}
static double
general_cubic (double x, double B, double C)
{
double ax = fabs(x);
if (ax < 1)
{
return (((12 - 9 * B - 6 * C) * ax +
(-18 + 12 * B + 6 * C)) * ax * ax +
(6 - 2 * B)) / 6;
}
else if (ax < 2)
{
return ((((-B - 6 * C) * ax +
(6 * B + 30 * C)) * ax +
(-12 * B - 48 * C)) * ax +
(8 * B + 24 * C)) / 6;
}
else
{
return 0;
}
}
static double
cubic_kernel (double x)
{
/* This is the Mitchell-Netravali filter.
*
* (0.0, 0.5) would give us the Catmull-Rom spline,
* but that one seems to be indistinguishable from Lanczos2.
*/
return general_cubic (x, 1/3.0, 1/3.0);
}
static const filter_info_t filters[] =
{
{ PIXMAN_KERNEL_IMPULSE, impulse_kernel, 0.0 },
{ PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
{ PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
{ PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 5.0 },
{ PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
{ PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
{ PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
};
/* This function scales @kernel2 by @scale, then
* aligns @x1 in @kernel1 with @x2 in @kernel2 and
* and integrates the product of the kernels across @width.
*
* This function assumes that the intervals are within
* the kernels in question. E.g., the caller must not
* try to integrate a linear kernel ouside of [-1:1]
*/
static double
integral (pixman_kernel_t kernel1, double x1,
pixman_kernel_t kernel2, double scale, double x2,
double width)
{
if (kernel1 == PIXMAN_KERNEL_BOX && kernel2 == PIXMAN_KERNEL_BOX)
{
return width;
}
/* The LINEAR filter is not differentiable at 0, so if the
* integration interval crosses zero, break it into two
* separate integrals.
*/
else if (kernel1 == PIXMAN_KERNEL_LINEAR && x1 < 0 && x1 + width > 0)
{
return
integral (kernel1, x1, kernel2, scale, x2, - x1) +
integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
}
else if (kernel2 == PIXMAN_KERNEL_LINEAR && x2 < 0 && x2 + width > 0)
{
return
integral (kernel1, x1, kernel2, scale, x2, - x2) +
integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
}
else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
{
assert (width == 0.0);
return filters[kernel2].func (x2 * scale);
}
else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
{
assert (width == 0.0);
return filters[kernel1].func (x1);
}
else
{
/* Integration via Simpson's rule
* See http://www.intmath.com/integration/6-simpsons-rule.php
* 12 segments (6 cubic approximations) seems to produce best
* result for lanczos3.linear, which was the combination that
* showed the most errors. This makes sense as the lanczos3
* filter is 6 wide.
*/
#define N_SEGMENTS 12
#define SAMPLE(a1, a2) \
(filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
double s = 0.0;
double h = width / N_SEGMENTS;
int i;
s = SAMPLE (x1, x2);
for (i = 1; i < N_SEGMENTS; i += 2)
{
double a1 = x1 + h * i;
double a2 = x2 + h * i;
s += 4 * SAMPLE (a1, a2);
}
for (i = 2; i < N_SEGMENTS; i += 2)
{
double a1 = x1 + h * i;
double a2 = x2 + h * i;
s += 2 * SAMPLE (a1, a2);
}
s += SAMPLE (x1 + width, x2 + width);
return h * s * (1.0 / 3.0);
}
}
static void
create_1d_filter (int width,
pixman_kernel_t reconstruct,
pixman_kernel_t sample,
double scale,
int n_phases,
pixman_fixed_t *pstart,
pixman_fixed_t *pend
)
{
pixman_fixed_t *p = pstart;
double step;
int i;
if(width <= 0) return;
step = 1.0 / n_phases;
for (i = 0; i < n_phases; ++i)
{
double frac = step / 2.0 + i * step;
pixman_fixed_t new_total;
int x, x1, x2;
double total, e;
/* Sample convolution of reconstruction and sampling
* filter. See rounding.txt regarding the rounding
* and sample positions.
*/
x1 = ceil (frac - width / 2.0 - 0.5);
x2 = x1 + width;
assert( p >= pstart && p + (x2 - x1) <= pend ); /* assert validity of the following loop */
total = 0;
for (x = x1; x < x2; ++x)
{
double pos = x + 0.5 - frac;
double rlow = - filters[reconstruct].width / 2.0;
double rhigh = rlow + filters[reconstruct].width;
double slow = pos - scale * filters[sample].width / 2.0;
double shigh = slow + scale * filters[sample].width;
double c = 0.0;
double ilow, ihigh;
if (rhigh >= slow && rlow <= shigh)
{
ilow = MAX (slow, rlow);
ihigh = MIN (shigh, rhigh);
c = integral (reconstruct, ilow,
sample, 1.0 / scale, ilow - pos,
ihigh - ilow);
}
*p = (pixman_fixed_t)floor (c * 65536.0 + 0.5);
total += *p;
p++;
}
/* Normalize, with error diffusion */
p -= width;
assert(p >= pstart && p + (x2 - x1) <= pend); /* assert validity of the following loop */
total = 65536.0 / total;
new_total = 0;
e = 0.0;
for (x = x1; x < x2; ++x)
{
double v = (*p) * total + e;
pixman_fixed_t t = floor (v + 0.5);
e = v - t;
new_total += t;
*p++ = t;
}
/* pixman_fixed_e's worth of error may remain; put it
* at the first sample, since that is the only one that
* hasn't had any error diffused into it.
*/
assert(p - width >= pstart && p - width < pend); /* assert... */
*(p - width) += pixman_fixed_1 - new_total;
}
}
static int
filter_width (pixman_kernel_t reconstruct, pixman_kernel_t sample, double size)
{
return ceil (filters[reconstruct].width + size * filters[sample].width);
}
#ifdef PIXMAN_GNUPLOT
/* If enable-gnuplot is configured, then you can pipe the output of a
* pixman-using program to gnuplot and get a continuously-updated plot
* of the horizontal filter. This works well with demos/scale to test
* the filter generation.
*
* The plot is all the different subposition filters shuffled
* together. This is misleading in a few cases:
*
* IMPULSE.BOX - goes up and down as the subfilters have different
* numbers of non-zero samples
* IMPULSE.TRIANGLE - somewhat crooked for the same reason
* 1-wide filters - looks triangular, but a 1-wide box would be more
* accurate
*/
static void
gnuplot_filter (int width, int n_phases, const pixman_fixed_t* p)
{
double step;
int i, j;
int first;
step = 1.0 / n_phases;
printf ("set style line 1 lc rgb '#0060ad' lt 1 lw 0.5 pt 7 pi 1 ps 0.5\n");
printf ("plot [x=%g:%g] '-' with linespoints ls 1\n", -width*0.5, width*0.5);
/* Print a point at the origin so that y==0 line is included: */
printf ("0 0\n\n");
/* The position of the first sample of the phase corresponding to
* frac is given by:
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
*
* We have to find the frac that minimizes this expression.
*
* For odd widths, we have
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
* = ceil (frac) + K - frac
* = 1 + K - frac
*
* for some K, so this is minimized when frac is maximized and
* strictly growing with frac. So for odd widths, we can simply
* start at the last phase and go backwards.
*
* For even widths, we have
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
* = ceil (frac - 0.5) + K - frac
*
* The graph for this function (ignoring K) looks like this:
*
* 0.5
* | |\
* | | \
* | | \
* 0 | | \
* |\ |
* | \ |
* | \ |
* -0.5 | \|
* ---------------------------------
* 0 0.5 1
*
* So in this case we need to start with the phase whose frac is
* less than, but as close as possible to 0.5, then go backwards
* until we hit the first phase, then wrap around to the last
* phase and continue backwards.
*
* Which phase is as close as possible 0.5? The locations of the
* sampling point corresponding to the kth phase is given by
* 1/(2 * n_phases) + k / n_phases:
*
* 1/(2 * n_phases) + k / n_phases = 0.5
*
* from which it follows that
*
* k = (n_phases - 1) / 2
*
* rounded down is the phase in question.
*/
if (width & 1)
first = n_phases - 1;
else
first = (n_phases - 1) / 2;
for (j = 0; j < width; ++j)
{
for (i = 0; i < n_phases; ++i)
{
int phase = first - i;
double frac, pos;
if (phase < 0)
phase = n_phases + phase;
frac = step / 2.0 + phase * step;
pos = ceil (frac - width / 2.0 - 0.5) + 0.5 - frac + j;
printf ("%g %g\n",
pos,
pixman_fixed_to_double (*(p + phase * width + j)));
}
}
printf ("e\n");
fflush (stdout);
}
#endif
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
* with the given kernels and scale parameters
*/
PIXMAN_EXPORT pixman_fixed_t *
pixman_filter_create_separable_convolution (int *n_values,
pixman_fixed_t scale_x,
pixman_fixed_t scale_y,
pixman_kernel_t reconstruct_x,
pixman_kernel_t reconstruct_y,
pixman_kernel_t sample_x,
pixman_kernel_t sample_y,
int subsample_bits_x,
int subsample_bits_y)
{
double sx = fabs (pixman_fixed_to_double (scale_x));
double sy = fabs (pixman_fixed_to_double (scale_y));
pixman_fixed_t *params;
int subsample_x, subsample_y;
int width, height;
width = filter_width (reconstruct_x, sample_x, sx);
subsample_x = (1 << subsample_bits_x);
height = filter_width (reconstruct_y, sample_y, sy);
subsample_y = (1 << subsample_bits_y);
*n_values = 4 + width * subsample_x + height * subsample_y;
params = malloc (*n_values * sizeof (pixman_fixed_t));
if (!params)
return NULL;
params[0] = pixman_int_to_fixed (width);
params[1] = pixman_int_to_fixed (height);
params[2] = pixman_int_to_fixed (subsample_bits_x);
params[3] = pixman_int_to_fixed (subsample_bits_y);
{
pixman_fixed_t
*xparams = params+4,
*yparams = xparams + width*subsample_x,
*endparams = params + *n_values;
create_1d_filter(width, reconstruct_x, sample_x, sx, subsample_x,
xparams, yparams);
create_1d_filter(height, reconstruct_y, sample_y, sy, subsample_y,
yparams, endparams);
}
#ifdef PIXMAN_GNUPLOT
gnuplot_filter(width, subsample_x, params + 4);
#endif
return params;
}

View File

@ -1,264 +0,0 @@
/*
* Copyright © 2009 Red Hat, Inc.
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
* 2008 Aaron Plattner, NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pixman-private.h"
static void
general_iter_init (pixman_iter_t *iter, const pixman_iter_info_t *info)
{
pixman_image_t *image = iter->image;
switch (image->type)
{
case BITS:
if ((iter->iter_flags & ITER_SRC) == ITER_SRC)
_pixman_bits_image_src_iter_init (image, iter);
else
_pixman_bits_image_dest_iter_init (image, iter);
break;
case LINEAR:
_pixman_linear_gradient_iter_init (image, iter);
break;
case RADIAL:
_pixman_radial_gradient_iter_init (image, iter);
break;
case CONICAL:
_pixman_conical_gradient_iter_init (image, iter);
break;
case SOLID:
_pixman_log_error (FUNC, "Solid image not handled by noop");
break;
default:
_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
break;
}
}
static const pixman_iter_info_t general_iters[] =
{
{ PIXMAN_any, 0, 0, general_iter_init, NULL, NULL },
{ PIXMAN_null },
};
typedef struct op_info_t op_info_t;
struct op_info_t
{
uint8_t src, dst;
};
#define ITER_IGNORE_BOTH \
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
{
/* Src Dst */
{ ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */
{ ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */
{ 0, ITER_LOCALIZED_ALPHA }, /* OVER */
{ ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */
{ 0, 0 }, /* ATOP */
{ 0, 0 }, /* ATOP_REVERSE */
{ 0, 0 }, /* XOR */
{ ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */
{ 0, 0 }, /* SATURATE */
};
#define SCANLINE_BUFFER_LENGTH 8192
static pixman_bool_t
operator_needs_division (pixman_op_t op)
{
static const uint8_t needs_division[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* SATURATE */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* DISJOINT */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* CONJOINT */
0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, /* blend ops */
};
return needs_division[op];
}
static void
general_composite_rect (pixman_implementation_t *imp,
pixman_composite_info_t *info)
{
PIXMAN_COMPOSITE_ARGS (info);
uint8_t stack_scanline_buffer[3 * SCANLINE_BUFFER_LENGTH];
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
uint8_t *src_buffer, *mask_buffer, *dest_buffer;
pixman_iter_t src_iter, mask_iter, dest_iter;
pixman_combine_32_func_t compose;
pixman_bool_t component_alpha;
iter_flags_t width_flag, src_iter_flags;
int Bpp;
int i;
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
!(operator_needs_division (op)) &&
(dest_image->bits.dither == PIXMAN_DITHER_NONE))
{
width_flag = ITER_NARROW;
Bpp = 4;
}
else
{
width_flag = ITER_WIDE;
Bpp = 16;
}
#define ALIGN(addr) \
((uint8_t *)((((uintptr_t)(addr)) + 15) & (~15)))
if (width <= 0 || _pixman_multiply_overflows_int (width, Bpp * 3))
return;
if (width * Bpp * 3 > sizeof (stack_scanline_buffer) - 15 * 3)
{
scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 15 * 3);
if (!scanline_buffer)
return;
memset (scanline_buffer, 0, width * Bpp * 3 + 15 * 3);
}
else
{
memset (stack_scanline_buffer, 0, sizeof (stack_scanline_buffer));
}
src_buffer = ALIGN (scanline_buffer);
mask_buffer = ALIGN (src_buffer + width * Bpp);
dest_buffer = ALIGN (mask_buffer + width * Bpp);
if (width_flag == ITER_WIDE)
{
/* To make sure there aren't any NANs in the buffers */
memset (src_buffer, 0, width * Bpp);
memset (mask_buffer, 0, width * Bpp);
memset (dest_buffer, 0, width * Bpp);
}
/* src iter */
src_iter_flags = width_flag | op_flags[op].src | ITER_SRC;
_pixman_implementation_iter_init (imp->toplevel, &src_iter, src_image,
src_x, src_y, width, height,
src_buffer, src_iter_flags,
info->src_flags);
/* mask iter */
if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
{
/* If it doesn't matter what the source is, then it doesn't matter
* what the mask is
*/
mask_image = NULL;
}
component_alpha = mask_image && mask_image->common.component_alpha;
_pixman_implementation_iter_init (
imp->toplevel, &mask_iter,
mask_image, mask_x, mask_y, width, height, mask_buffer,
ITER_SRC | width_flag | (component_alpha? 0 : ITER_IGNORE_RGB),
info->mask_flags);
/* dest iter */
_pixman_implementation_iter_init (
imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
dest_buffer, ITER_DEST | width_flag | op_flags[op].dst, info->dest_flags);
compose = _pixman_implementation_lookup_combiner (
imp->toplevel, op, component_alpha, width_flag != ITER_WIDE);
for (i = 0; i < height; ++i)
{
uint32_t *s, *m, *d;
m = mask_iter.get_scanline (&mask_iter, NULL);
s = src_iter.get_scanline (&src_iter, m);
d = dest_iter.get_scanline (&dest_iter, NULL);
compose (imp->toplevel, op, d, s, m, width);
dest_iter.write_back (&dest_iter);
}
if (src_iter.fini)
src_iter.fini (&src_iter);
if (mask_iter.fini)
mask_iter.fini (&mask_iter);
if (dest_iter.fini)
dest_iter.fini (&dest_iter);
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
free (scanline_buffer);
}
static const pixman_fast_path_t general_fast_path[] =
{
{ PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
{ PIXMAN_OP_NONE }
};
pixman_implementation_t *
_pixman_implementation_create_general (void)
{
pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
_pixman_setup_combiner_functions_32 (imp);
_pixman_setup_combiner_functions_float (imp);
imp->iter_info = general_iters;
return imp;
}

View File

@ -1,676 +0,0 @@
/*
* Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk>
* Copyright 2010, 2011, 2012, Red Hat, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Soren Sandmann <sandmann@cs.au.dk>
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
#include <stdlib.h>
typedef struct glyph_metrics_t glyph_metrics_t;
typedef struct glyph_t glyph_t;
#define TOMBSTONE ((glyph_t *)0x1)
/* XXX: These numbers are arbitrary---we've never done any measurements.
*/
#define N_GLYPHS_HIGH_WATER (16384)
#define N_GLYPHS_LOW_WATER (8192)
#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER)
#define HASH_MASK (HASH_SIZE - 1)
struct glyph_t
{
void * font_key;
void * glyph_key;
int origin_x;
int origin_y;
pixman_image_t * image;
pixman_link_t mru_link;
};
struct pixman_glyph_cache_t
{
int n_glyphs;
int n_tombstones;
int freeze_count;
pixman_list_t mru;
glyph_t * glyphs[HASH_SIZE];
};
static void
free_glyph (glyph_t *glyph)
{
pixman_list_unlink (&glyph->mru_link);
pixman_image_unref (glyph->image);
free (glyph);
}
static unsigned int
hash (const void *font_key, const void *glyph_key)
{
size_t key = (size_t)font_key + (size_t)glyph_key;
/* This hash function is based on one found on Thomas Wang's
* web page at
*
* http://www.concentric.net/~Ttwang/tech/inthash.htm
*
*/
key = (key << 15) - key - 1;
key = key ^ (key >> 12);
key = key + (key << 2);
key = key ^ (key >> 4);
key = key + (key << 3) + (key << 11);
key = key ^ (key >> 16);
return key;
}
static glyph_t *
lookup_glyph (pixman_glyph_cache_t *cache,
void *font_key,
void *glyph_key)
{
unsigned idx;
glyph_t *g;
idx = hash (font_key, glyph_key);
while ((g = cache->glyphs[idx++ & HASH_MASK]))
{
if (g != TOMBSTONE &&
g->font_key == font_key &&
g->glyph_key == glyph_key)
{
return g;
}
}
return NULL;
}
static void
insert_glyph (pixman_glyph_cache_t *cache,
glyph_t *glyph)
{
unsigned idx;
glyph_t **loc;
idx = hash (glyph->font_key, glyph->glyph_key);
/* Note: we assume that there is room in the table. If there isn't,
* this will be an infinite loop.
*/
do
{
loc = &cache->glyphs[idx++ & HASH_MASK];
} while (*loc && *loc != TOMBSTONE);
if (*loc == TOMBSTONE)
cache->n_tombstones--;
cache->n_glyphs++;
*loc = glyph;
}
static void
remove_glyph (pixman_glyph_cache_t *cache,
glyph_t *glyph)
{
unsigned idx;
idx = hash (glyph->font_key, glyph->glyph_key);
while (cache->glyphs[idx & HASH_MASK] != glyph)
idx++;
cache->glyphs[idx & HASH_MASK] = TOMBSTONE;
cache->n_tombstones++;
cache->n_glyphs--;
/* Eliminate tombstones if possible */
if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL)
{
while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE)
{
cache->glyphs[idx & HASH_MASK] = NULL;
cache->n_tombstones--;
idx--;
}
}
}
static void
clear_table (pixman_glyph_cache_t *cache)
{
int i;
for (i = 0; i < HASH_SIZE; ++i)
{
glyph_t *glyph = cache->glyphs[i];
if (glyph && glyph != TOMBSTONE)
free_glyph (glyph);
cache->glyphs[i] = NULL;
}
cache->n_glyphs = 0;
cache->n_tombstones = 0;
}
PIXMAN_EXPORT pixman_glyph_cache_t *
pixman_glyph_cache_create (void)
{
pixman_glyph_cache_t *cache;
if (!(cache = malloc (sizeof *cache)))
return NULL;
memset (cache->glyphs, 0, sizeof (cache->glyphs));
cache->n_glyphs = 0;
cache->n_tombstones = 0;
cache->freeze_count = 0;
pixman_list_init (&cache->mru);
return cache;
}
PIXMAN_EXPORT void
pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache)
{
return_if_fail (cache->freeze_count == 0);
clear_table (cache);
free (cache);
}
PIXMAN_EXPORT void
pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache)
{
cache->freeze_count++;
}
PIXMAN_EXPORT void
pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache)
{
if (--cache->freeze_count == 0 &&
cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER)
{
if (cache->n_tombstones > N_GLYPHS_HIGH_WATER)
{
/* More than half the entries are
* tombstones. Just dump the whole table.
*/
clear_table (cache);
}
while (cache->n_glyphs > N_GLYPHS_LOW_WATER)
{
glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail);
remove_glyph (cache, glyph);
free_glyph (glyph);
}
}
}
PIXMAN_EXPORT const void *
pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache,
void *font_key,
void *glyph_key)
{
return lookup_glyph (cache, font_key, glyph_key);
}
PIXMAN_EXPORT const void *
pixman_glyph_cache_insert (pixman_glyph_cache_t *cache,
void *font_key,
void *glyph_key,
int origin_x,
int origin_y,
pixman_image_t *image)
{
glyph_t *glyph;
int32_t width, height;
return_val_if_fail (cache->freeze_count > 0, NULL);
return_val_if_fail (image->type == BITS, NULL);
width = image->bits.width;
height = image->bits.height;
if (cache->n_glyphs >= HASH_SIZE)
return NULL;
if (!(glyph = malloc (sizeof *glyph)))
return NULL;
glyph->font_key = font_key;
glyph->glyph_key = glyph_key;
glyph->origin_x = origin_x;
glyph->origin_y = origin_y;
if (!(glyph->image = pixman_image_create_bits (
image->bits.format, width, height, NULL, -1)))
{
free (glyph);
return NULL;
}
pixman_image_composite32 (PIXMAN_OP_SRC,
image, NULL, glyph->image, 0, 0, 0, 0, 0, 0,
width, height);
if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 &&
PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0)
{
pixman_image_set_component_alpha (glyph->image, TRUE);
}
pixman_list_prepend (&cache->mru, &glyph->mru_link);
_pixman_image_validate (glyph->image);
insert_glyph (cache, glyph);
return glyph;
}
PIXMAN_EXPORT void
pixman_glyph_cache_remove (pixman_glyph_cache_t *cache,
void *font_key,
void *glyph_key)
{
glyph_t *glyph;
if ((glyph = lookup_glyph (cache, font_key, glyph_key)))
{
remove_glyph (cache, glyph);
free_glyph (glyph);
}
}
PIXMAN_EXPORT void
pixman_glyph_get_extents (pixman_glyph_cache_t *cache,
int n_glyphs,
pixman_glyph_t *glyphs,
pixman_box32_t *extents)
{
int i;
extents->x1 = extents->y1 = INT32_MAX;
extents->x2 = extents->y2 = INT32_MIN;
for (i = 0; i < n_glyphs; ++i)
{
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
int x1, y1, x2, y2;
x1 = glyphs[i].x - glyph->origin_x;
y1 = glyphs[i].y - glyph->origin_y;
x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width;
y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height;
if (x1 < extents->x1)
extents->x1 = x1;
if (y1 < extents->y1)
extents->y1 = y1;
if (x2 > extents->x2)
extents->x2 = x2;
if (y2 > extents->y2)
extents->y2 = y2;
}
}
/* This function returns a format that is suitable for use as a mask for the
* set of glyphs in question.
*/
PIXMAN_EXPORT pixman_format_code_t
pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
int n_glyphs,
const pixman_glyph_t *glyphs)
{
pixman_format_code_t format = PIXMAN_a1;
int i;
for (i = 0; i < n_glyphs; ++i)
{
const glyph_t *glyph = glyphs[i].glyph;
pixman_format_code_t glyph_format = glyph->image->bits.format;
if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A)
{
if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format))
format = glyph_format;
}
else
{
return PIXMAN_a8r8g8b8;
}
}
return format;
}
static pixman_bool_t
box32_intersect (pixman_box32_t *dest,
const pixman_box32_t *box1,
const pixman_box32_t *box2)
{
dest->x1 = MAX (box1->x1, box2->x1);
dest->y1 = MAX (box1->y1, box2->y1);
dest->x2 = MIN (box1->x2, box2->x2);
dest->y2 = MIN (box1->y2, box2->y2);
return dest->x2 > dest->x1 && dest->y2 > dest->y1;
}
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
__attribute__((__force_align_arg_pointer__))
#endif
PIXMAN_EXPORT void
pixman_composite_glyphs_no_mask (pixman_op_t op,
pixman_image_t *src,
pixman_image_t *dest,
int32_t src_x,
int32_t src_y,
int32_t dest_x,
int32_t dest_y,
pixman_glyph_cache_t *cache,
int n_glyphs,
const pixman_glyph_t *glyphs)
{
pixman_region32_t region;
pixman_format_code_t glyph_format = PIXMAN_null;
uint32_t glyph_flags = 0;
pixman_format_code_t dest_format;
uint32_t dest_flags;
pixman_composite_func_t func = NULL;
pixman_implementation_t *implementation = NULL;
pixman_composite_info_t info;
int i;
_pixman_image_validate (src);
_pixman_image_validate (dest);
dest_format = dest->common.extended_format_code;
dest_flags = dest->common.flags;
pixman_region32_init (&region);
if (!_pixman_compute_composite_region32 (
&region,
src, NULL, dest,
src_x - dest_x, src_y - dest_y, 0, 0, 0, 0,
dest->bits.width, dest->bits.height))
{
goto out;
}
info.op = op;
info.src_image = src;
info.dest_image = dest;
info.src_flags = src->common.flags;
info.dest_flags = dest->common.flags;
for (i = 0; i < n_glyphs; ++i)
{
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
pixman_image_t *glyph_img = glyph->image;
pixman_box32_t glyph_box;
pixman_box32_t *pbox;
uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
pixman_box32_t composite_box;
int n;
glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x;
glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y;
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
pbox = pixman_region32_rectangles (&region, &n);
info.mask_image = glyph_img;
while (n--)
{
if (box32_intersect (&composite_box, pbox, &glyph_box))
{
if (glyph_img->common.extended_format_code != glyph_format ||
glyph_img->common.flags != glyph_flags)
{
glyph_format = glyph_img->common.extended_format_code;
glyph_flags = glyph_img->common.flags;
_pixman_implementation_lookup_composite (
get_implementation(), op,
src->common.extended_format_code, src->common.flags,
glyph_format, glyph_flags | extra,
dest_format, dest_flags,
&implementation, &func);
}
info.src_x = src_x + composite_box.x1 - dest_x;
info.src_y = src_y + composite_box.y1 - dest_y;
info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x);
info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y);
info.dest_x = composite_box.x1;
info.dest_y = composite_box.y1;
info.width = composite_box.x2 - composite_box.x1;
info.height = composite_box.y2 - composite_box.y1;
info.mask_flags = glyph_flags;
func (implementation, &info);
}
pbox++;
}
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
}
out:
pixman_region32_fini (&region);
}
static void
add_glyphs (pixman_glyph_cache_t *cache,
pixman_image_t *dest,
int off_x, int off_y,
int n_glyphs, const pixman_glyph_t *glyphs)
{
pixman_format_code_t glyph_format = PIXMAN_null;
uint32_t glyph_flags = 0;
pixman_composite_func_t func = NULL;
pixman_implementation_t *implementation = NULL;
pixman_format_code_t dest_format;
uint32_t dest_flags;
pixman_box32_t dest_box;
pixman_composite_info_t info;
pixman_image_t *white_img = NULL;
pixman_bool_t white_src = FALSE;
int i;
_pixman_image_validate (dest);
dest_format = dest->common.extended_format_code;
dest_flags = dest->common.flags;
info.op = PIXMAN_OP_ADD;
info.dest_image = dest;
info.src_x = 0;
info.src_y = 0;
info.dest_flags = dest_flags;
dest_box.x1 = 0;
dest_box.y1 = 0;
dest_box.x2 = dest->bits.width;
dest_box.y2 = dest->bits.height;
for (i = 0; i < n_glyphs; ++i)
{
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
pixman_image_t *glyph_img = glyph->image;
pixman_box32_t glyph_box;
pixman_box32_t composite_box;
if (glyph_img->common.extended_format_code != glyph_format ||
glyph_img->common.flags != glyph_flags)
{
pixman_format_code_t src_format, mask_format;
glyph_format = glyph_img->common.extended_format_code;
glyph_flags = glyph_img->common.flags;
if (glyph_format == dest->bits.format)
{
src_format = glyph_format;
mask_format = PIXMAN_null;
info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
info.mask_flags = FAST_PATH_IS_OPAQUE;
info.mask_image = NULL;
white_src = FALSE;
}
else
{
if (!white_img)
{
static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
if (!(white_img = pixman_image_create_solid_fill (&white)))
goto out;
_pixman_image_validate (white_img);
}
src_format = PIXMAN_solid;
mask_format = glyph_format;
info.src_flags = white_img->common.flags;
info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
info.src_image = white_img;
white_src = TRUE;
}
_pixman_implementation_lookup_composite (
get_implementation(), PIXMAN_OP_ADD,
src_format, info.src_flags,
mask_format, info.mask_flags,
dest_format, dest_flags,
&implementation, &func);
}
glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x;
glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y;
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
if (box32_intersect (&composite_box, &glyph_box, &dest_box))
{
int src_x = composite_box.x1 - glyph_box.x1;
int src_y = composite_box.y1 - glyph_box.y1;
if (white_src)
info.mask_image = glyph_img;
else
info.src_image = glyph_img;
info.mask_x = info.src_x = src_x;
info.mask_y = info.src_y = src_y;
info.dest_x = composite_box.x1;
info.dest_y = composite_box.y1;
info.width = composite_box.x2 - composite_box.x1;
info.height = composite_box.y2 - composite_box.y1;
func (implementation, &info);
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
}
}
out:
if (white_img)
pixman_image_unref (white_img);
}
/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an
* infinitely big mask image at the position such that the glyph origin point
* is positioned at the (glyphs[i].x, glyphs[i].y) point.
*
* Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source
* image are both aligned with (dest_x, dest_y) in the destination image. Then
* these three images are composited within the
*
* (dest_x, dest_y, dst_x + width, dst_y + height)
*
* rectangle.
*
* TODO:
* - Trim the mask to the destination clip/image?
* - Trim composite region based on sources, when the op ignores 0s.
*/
#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
__attribute__((__force_align_arg_pointer__))
#endif
PIXMAN_EXPORT void
pixman_composite_glyphs (pixman_op_t op,
pixman_image_t *src,
pixman_image_t *dest,
pixman_format_code_t mask_format,
int32_t src_x,
int32_t src_y,
int32_t mask_x,
int32_t mask_y,
int32_t dest_x,
int32_t dest_y,
int32_t width,
int32_t height,
pixman_glyph_cache_t *cache,
int n_glyphs,
const pixman_glyph_t *glyphs)
{
pixman_image_t *mask;
if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1)))
return;
if (PIXMAN_FORMAT_A (mask_format) != 0 &&
PIXMAN_FORMAT_RGB (mask_format) != 0)
{
pixman_image_set_component_alpha (mask, TRUE);
}
add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs);
pixman_image_composite32 (op, src, mask, dest,
src_x, src_y,
0, 0,
dest_x, dest_y,
width, height);
pixman_image_unref (mask);
}

View File

@ -1,264 +0,0 @@
/*
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
void
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
gradient_t * gradient,
pixman_repeat_t repeat)
{
walker->num_stops = gradient->n_stops;
walker->stops = gradient->stops;
walker->left_x = 0;
walker->right_x = 0x10000;
walker->a_s = 0.0f;
walker->a_b = 0.0f;
walker->r_s = 0.0f;
walker->r_b = 0.0f;
walker->g_s = 0.0f;
walker->g_b = 0.0f;
walker->b_s = 0.0f;
walker->b_b = 0.0f;
walker->repeat = repeat;
walker->need_reset = TRUE;
}
static void
gradient_walker_reset (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t pos)
{
int64_t x, left_x, right_x;
pixman_color_t *left_c, *right_c;
int n, count = walker->num_stops;
pixman_gradient_stop_t *stops = walker->stops;
float la, lr, lg, lb;
float ra, rr, rg, rb;
float lx, rx;
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
{
x = (int32_t)pos & 0xffff;
}
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
{
x = (int32_t)pos & 0xffff;
if ((int32_t)pos & 0x10000)
x = 0x10000 - x;
}
else
{
x = pos;
}
for (n = 0; n < count; n++)
{
if (x < stops[n].x)
break;
}
left_x = stops[n - 1].x;
left_c = &stops[n - 1].color;
right_x = stops[n].x;
right_c = &stops[n].color;
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
{
left_x += (pos - x);
right_x += (pos - x);
}
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
{
if ((int32_t)pos & 0x10000)
{
pixman_color_t *tmp_c;
int32_t tmp_x;
tmp_x = 0x10000 - right_x;
right_x = 0x10000 - left_x;
left_x = tmp_x;
tmp_c = right_c;
right_c = left_c;
left_c = tmp_c;
x = 0x10000 - x;
}
left_x += (pos - x);
right_x += (pos - x);
}
else if (walker->repeat == PIXMAN_REPEAT_NONE)
{
if (n == 0)
right_c = left_c;
else if (n == count)
left_c = right_c;
}
/* The alpha/red/green/blue channels are scaled to be in [0, 1].
* This ensures that after premultiplication all channels will
* be in the [0, 1] interval.
*/
la = (left_c->alpha * (1.0f/257.0f));
lr = (left_c->red * (1.0f/257.0f));
lg = (left_c->green * (1.0f/257.0f));
lb = (left_c->blue * (1.0f/257.0f));
ra = (right_c->alpha * (1.0f/257.0f));
rr = (right_c->red * (1.0f/257.0f));
rg = (right_c->green * (1.0f/257.0f));
rb = (right_c->blue * (1.0f/257.0f));
lx = left_x * (1.0f/65536.0f);
rx = right_x * (1.0f/65536.0f);
if (FLOAT_IS_ZERO (rx - lx) || left_x == INT32_MIN || right_x == INT32_MAX)
{
walker->a_s = walker->r_s = walker->g_s = walker->b_s = 0.0f;
walker->a_b = (la + ra) / 510.0f;
walker->r_b = (lr + rr) / 510.0f;
walker->g_b = (lg + rg) / 510.0f;
walker->b_b = (lb + rb) / 510.0f;
}
else
{
float w_rec = 1.0f / (rx - lx);
walker->a_b = (la * rx - ra * lx) * w_rec * (1.0f/255.0f);
walker->r_b = (lr * rx - rr * lx) * w_rec * (1.0f/255.0f);
walker->g_b = (lg * rx - rg * lx) * w_rec * (1.0f/255.0f);
walker->b_b = (lb * rx - rb * lx) * w_rec * (1.0f/255.0f);
walker->a_s = (ra - la) * w_rec * (1.0f/255.0f);
walker->r_s = (rr - lr) * w_rec * (1.0f/255.0f);
walker->g_s = (rg - lg) * w_rec * (1.0f/255.0f);
walker->b_s = (rb - lb) * w_rec * (1.0f/255.0f);
}
walker->left_x = left_x;
walker->right_x = right_x;
walker->need_reset = FALSE;
}
static argb_t
pixman_gradient_walker_pixel_float (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x)
{
argb_t f;
float y;
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
gradient_walker_reset (walker, x);
y = x * (1.0f / 65536.0f);
f.a = walker->a_s * y + walker->a_b;
f.r = f.a * (walker->r_s * y + walker->r_b);
f.g = f.a * (walker->g_s * y + walker->g_b);
f.b = f.a * (walker->b_s * y + walker->b_b);
return f;
}
static uint32_t
pixman_gradient_walker_pixel_32 (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x)
{
argb_t f;
float y;
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
gradient_walker_reset (walker, x);
y = x * (1.0f / 65536.0f);
/* Instead of [0...1] for ARGB, we want [0...255],
* multiply alpha with 255 and the color channels
* also get multiplied by the alpha multiplier.
*
* We don't use pixman_contract_from_float because it causes a 2x
* slowdown to do so, and the values are already normalized,
* so we don't have to worry about values < 0.f or > 1.f
*/
f.a = 255.f * (walker->a_s * y + walker->a_b);
f.r = f.a * (walker->r_s * y + walker->r_b);
f.g = f.a * (walker->g_s * y + walker->g_b);
f.b = f.a * (walker->b_s * y + walker->b_b);
return (((uint32_t)(f.a + .5f) << 24) & 0xff000000) |
(((uint32_t)(f.r + .5f) << 16) & 0x00ff0000) |
(((uint32_t)(f.g + .5f) << 8) & 0x0000ff00) |
(((uint32_t)(f.b + .5f) >> 0) & 0x000000ff);
}
void
_pixman_gradient_walker_write_narrow (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x,
uint32_t *buffer)
{
*buffer = pixman_gradient_walker_pixel_32 (walker, x);
}
void
_pixman_gradient_walker_write_wide (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x,
uint32_t *buffer)
{
*(argb_t *)buffer = pixman_gradient_walker_pixel_float (walker, x);
}
void
_pixman_gradient_walker_fill_narrow (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x,
uint32_t *buffer,
uint32_t *end)
{
register uint32_t color;
color = pixman_gradient_walker_pixel_32 (walker, x);
while (buffer < end)
*buffer++ = color;
}
void
_pixman_gradient_walker_fill_wide (pixman_gradient_walker_t *walker,
pixman_fixed_48_16_t x,
uint32_t *buffer,
uint32_t *end)
{
register argb_t color;
argb_t *buffer_wide = (argb_t *)buffer;
argb_t *end_wide = (argb_t *)end;
color = pixman_gradient_walker_pixel_float (walker, x);
while (buffer_wide < end_wide)
*buffer_wide++ = color;
}

View File

@ -1,994 +0,0 @@
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "pixman-private.h"
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
static void
gradient_property_changed (pixman_image_t *image)
{
gradient_t *gradient = &image->gradient;
int n = gradient->n_stops;
pixman_gradient_stop_t *stops = gradient->stops;
pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
pixman_gradient_stop_t *end = &(gradient->stops[n]);
switch (gradient->common.repeat)
{
default:
case PIXMAN_REPEAT_NONE:
begin->x = INT32_MIN;
begin->color = transparent_black;
end->x = INT32_MAX;
end->color = transparent_black;
break;
case PIXMAN_REPEAT_NORMAL:
begin->x = stops[n - 1].x - pixman_fixed_1;
begin->color = stops[n - 1].color;
end->x = stops[0].x + pixman_fixed_1;
end->color = stops[0].color;
break;
case PIXMAN_REPEAT_REFLECT:
begin->x = - stops[0].x;
begin->color = stops[0].color;
end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
end->color = stops[n - 1].color;
break;
case PIXMAN_REPEAT_PAD:
begin->x = INT32_MIN;
begin->color = stops[0].color;
end->x = INT32_MAX;
end->color = stops[n - 1].color;
break;
}
}
pixman_bool_t
_pixman_init_gradient (gradient_t * gradient,
const pixman_gradient_stop_t *stops,
int n_stops)
{
return_val_if_fail (n_stops > 0, FALSE);
/* We allocate two extra stops, one before the beginning of the stop list,
* and one after the end. These stops are initialized to whatever color
* would be used for positions outside the range of the stop list.
*
* This saves a bit of computation in the gradient walker.
*
* The pointer we store in the gradient_t struct still points to the
* first user-supplied struct, so when freeing, we will have to
* subtract one.
*/
gradient->stops =
pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
if (!gradient->stops)
return FALSE;
gradient->stops += 1;
memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
gradient->n_stops = n_stops;
gradient->common.property_changed = gradient_property_changed;
return TRUE;
}
void
_pixman_image_init (pixman_image_t *image)
{
image_common_t *common = &image->common;
pixman_region32_init (&common->clip_region);
common->alpha_count = 0;
common->have_clip_region = FALSE;
common->clip_sources = FALSE;
common->transform = NULL;
common->repeat = PIXMAN_REPEAT_NONE;
common->filter = PIXMAN_FILTER_NEAREST;
common->filter_params = NULL;
common->n_filter_params = 0;
common->alpha_map = NULL;
common->component_alpha = FALSE;
common->ref_count = 1;
common->property_changed = NULL;
common->client_clip = FALSE;
common->destroy_func = NULL;
common->destroy_data = NULL;
common->dirty = TRUE;
}
pixman_bool_t
_pixman_image_fini (pixman_image_t *image)
{
image_common_t *common = (image_common_t *)image;
common->ref_count--;
if (common->ref_count == 0)
{
if (image->common.destroy_func)
image->common.destroy_func (image, image->common.destroy_data);
pixman_region32_fini (&common->clip_region);
free (common->transform);
free (common->filter_params);
if (common->alpha_map)
pixman_image_unref ((pixman_image_t *)common->alpha_map);
if (image->type == LINEAR ||
image->type == RADIAL ||
image->type == CONICAL)
{
if (image->gradient.stops)
{
/* See _pixman_init_gradient() for an explanation of the - 1 */
free (image->gradient.stops - 1);
}
/* This will trigger if someone adds a property_changed
* method to the linear/radial/conical gradient overwriting
* the general one.
*/
assert (
image->common.property_changed == gradient_property_changed);
}
if (image->type == BITS && image->bits.free_me)
free (image->bits.free_me);
return TRUE;
}
return FALSE;
}
pixman_image_t *
_pixman_image_allocate (void)
{
pixman_image_t *image = malloc (sizeof (pixman_image_t));
if (image)
_pixman_image_init (image);
return image;
}
static void
image_property_changed (pixman_image_t *image)
{
image->common.dirty = TRUE;
}
/* Ref Counting */
PIXMAN_EXPORT pixman_image_t *
pixman_image_ref (pixman_image_t *image)
{
image->common.ref_count++;
return image;
}
/* returns TRUE when the image is freed */
PIXMAN_EXPORT pixman_bool_t
pixman_image_unref (pixman_image_t *image)
{
if (_pixman_image_fini (image))
{
free (image);
return TRUE;
}
return FALSE;
}
PIXMAN_EXPORT void
pixman_image_set_destroy_function (pixman_image_t * image,
pixman_image_destroy_func_t func,
void * data)
{
image->common.destroy_func = func;
image->common.destroy_data = data;
}
PIXMAN_EXPORT void *
pixman_image_get_destroy_data (pixman_image_t *image)
{
return image->common.destroy_data;
}
void
_pixman_image_reset_clip_region (pixman_image_t *image)
{
image->common.have_clip_region = FALSE;
}
/* Executive Summary: This function is a no-op that only exists
* for historical reasons.
*
* There used to be a bug in the X server where it would rely on
* out-of-bounds accesses when it was asked to composite with a
* window as the source. It would create a pixman image pointing
* to some bogus position in memory, but then set a clip region
* to the position where the actual bits were.
*
* Due to a bug in old versions of pixman, where it would not clip
* against the image bounds when a clip region was set, this would
* actually work. So when the pixman bug was fixed, a workaround was
* added to allow certain out-of-bound accesses. This function disabled
* those workarounds.
*
* Since 0.21.2, pixman doesn't do these workarounds anymore, so now
* this function is a no-op.
*/
PIXMAN_EXPORT void
pixman_disable_out_of_bounds_workaround (void)
{
}
static void
compute_image_info (pixman_image_t *image)
{
pixman_format_code_t code;
uint32_t flags = 0;
/* Transform */
if (!image->common.transform)
{
flags |= (FAST_PATH_ID_TRANSFORM |
FAST_PATH_X_UNIT_POSITIVE |
FAST_PATH_Y_UNIT_ZERO |
FAST_PATH_AFFINE_TRANSFORM);
}
else
{
flags |= FAST_PATH_HAS_TRANSFORM;
if (image->common.transform->matrix[2][0] == 0 &&
image->common.transform->matrix[2][1] == 0 &&
image->common.transform->matrix[2][2] == pixman_fixed_1)
{
flags |= FAST_PATH_AFFINE_TRANSFORM;
if (image->common.transform->matrix[0][1] == 0 &&
image->common.transform->matrix[1][0] == 0)
{
if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
image->common.transform->matrix[1][1] == -pixman_fixed_1)
{
flags |= FAST_PATH_ROTATE_180_TRANSFORM;
}
flags |= FAST_PATH_SCALE_TRANSFORM;
}
else if (image->common.transform->matrix[0][0] == 0 &&
image->common.transform->matrix[1][1] == 0)
{
pixman_fixed_t m01 = image->common.transform->matrix[0][1];
pixman_fixed_t m10 = image->common.transform->matrix[1][0];
if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
flags |= FAST_PATH_ROTATE_90_TRANSFORM;
else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
flags |= FAST_PATH_ROTATE_270_TRANSFORM;
}
}
if (image->common.transform->matrix[0][0] > 0)
flags |= FAST_PATH_X_UNIT_POSITIVE;
if (image->common.transform->matrix[1][0] == 0)
flags |= FAST_PATH_Y_UNIT_ZERO;
}
/* Filter */
switch (image->common.filter)
{
case PIXMAN_FILTER_NEAREST:
case PIXMAN_FILTER_FAST:
flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
break;
case PIXMAN_FILTER_BILINEAR:
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
/* Here we have a chance to optimize BILINEAR filter to NEAREST if
* they are equivalent for the currently used transformation matrix.
*/
if (flags & FAST_PATH_ID_TRANSFORM)
{
flags |= FAST_PATH_NEAREST_FILTER;
}
else if (flags & FAST_PATH_AFFINE_TRANSFORM)
{
/* Suppose the transform is
*
* [ t00, t01, t02 ]
* [ t10, t11, t12 ]
* [ 0, 0, 1 ]
*
* and the destination coordinates are (n + 0.5, m + 0.5). Then
* the transformed x coordinate is:
*
* tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02
* = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5
*
* which implies that if t00, t01 and t02 are all integers
* and (t00 + t01) is odd, then tx will be an integer plus 0.5,
* which means a BILINEAR filter will reduce to NEAREST. The same
* applies in the y direction
*/
pixman_fixed_t (*t)[3] = image->common.transform->matrix;
if ((pixman_fixed_frac (
t[0][0] | t[0][1] | t[0][2] |
t[1][0] | t[1][1] | t[1][2]) == 0) &&
(pixman_fixed_to_int (
(t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1)
{
/* FIXME: there are some affine-test failures, showing that
* handling of BILINEAR and NEAREST filter is not quite
* equivalent when getting close to 32K for the translation
* components of the matrix. That's likely some bug, but for
* now just skip BILINEAR->NEAREST optimization in this case.
*/
pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
if (image->common.transform->matrix[0][2] <= magic_limit &&
image->common.transform->matrix[1][2] <= magic_limit &&
image->common.transform->matrix[0][2] >= -magic_limit &&
image->common.transform->matrix[1][2] >= -magic_limit)
{
flags |= FAST_PATH_NEAREST_FILTER;
}
}
}
break;
case PIXMAN_FILTER_CONVOLUTION:
break;
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
break;
default:
flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
break;
}
/* Repeat mode */
switch (image->common.repeat)
{
case PIXMAN_REPEAT_NONE:
flags |=
FAST_PATH_NO_REFLECT_REPEAT |
FAST_PATH_NO_PAD_REPEAT |
FAST_PATH_NO_NORMAL_REPEAT;
break;
case PIXMAN_REPEAT_REFLECT:
flags |=
FAST_PATH_NO_PAD_REPEAT |
FAST_PATH_NO_NONE_REPEAT |
FAST_PATH_NO_NORMAL_REPEAT;
break;
case PIXMAN_REPEAT_PAD:
flags |=
FAST_PATH_NO_REFLECT_REPEAT |
FAST_PATH_NO_NONE_REPEAT |
FAST_PATH_NO_NORMAL_REPEAT;
break;
default:
flags |=
FAST_PATH_NO_REFLECT_REPEAT |
FAST_PATH_NO_PAD_REPEAT |
FAST_PATH_NO_NONE_REPEAT;
break;
}
/* Component alpha */
if (image->common.component_alpha)
flags |= FAST_PATH_COMPONENT_ALPHA;
else
flags |= FAST_PATH_UNIFIED_ALPHA;
flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
/* Type specific checks */
switch (image->type)
{
case SOLID:
code = PIXMAN_solid;
if (image->solid.color.alpha == 0xffff)
flags |= FAST_PATH_IS_OPAQUE;
break;
case BITS:
if (image->bits.width == 1 &&
image->bits.height == 1 &&
image->common.repeat != PIXMAN_REPEAT_NONE)
{
code = PIXMAN_solid;
}
else
{
code = image->bits.format;
flags |= FAST_PATH_BITS_IMAGE;
}
if (!PIXMAN_FORMAT_A (image->bits.format) &&
PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY &&
PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
{
flags |= FAST_PATH_SAMPLES_OPAQUE;
if (image->common.repeat != PIXMAN_REPEAT_NONE)
flags |= FAST_PATH_IS_OPAQUE;
}
if (image->bits.read_func || image->bits.write_func)
flags &= ~FAST_PATH_NO_ACCESSORS;
if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
flags &= ~FAST_PATH_NARROW_FORMAT;
break;
case RADIAL:
code = PIXMAN_unknown;
/*
* As explained in pixman-radial-gradient.c, every point of
* the plane has a valid associated radius (and thus will be
* colored) if and only if a is negative (i.e. one of the two
* circles contains the other one).
*/
if (image->radial.a >= 0)
break;
/* Fall through */
case CONICAL:
case LINEAR:
code = PIXMAN_unknown;
if (image->common.repeat != PIXMAN_REPEAT_NONE)
{
int i;
flags |= FAST_PATH_IS_OPAQUE;
for (i = 0; i < image->gradient.n_stops; ++i)
{
if (image->gradient.stops[i].color.alpha != 0xffff)
{
flags &= ~FAST_PATH_IS_OPAQUE;
break;
}
}
}
break;
default:
code = PIXMAN_unknown;
break;
}
/* Alpha maps are only supported for BITS images, so it's always
* safe to ignore their presense for non-BITS images
*/
if (!image->common.alpha_map || image->type != BITS)
{
flags |= FAST_PATH_NO_ALPHA_MAP;
}
else
{
if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
flags &= ~FAST_PATH_NARROW_FORMAT;
}
/* Both alpha maps and convolution filters can introduce
* non-opaqueness in otherwise opaque images. Also
* an image with component alpha turned on is only opaque
* if all channels are opaque, so we simply turn it off
* unconditionally for those images.
*/
if (image->common.alpha_map ||
image->common.filter == PIXMAN_FILTER_CONVOLUTION ||
image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION ||
image->common.component_alpha)
{
flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
}
image->common.flags = flags;
image->common.extended_format_code = code;
}
void
_pixman_image_validate (pixman_image_t *image)
{
if (image->common.dirty)
{
compute_image_info (image);
/* It is important that property_changed is
* called *after* compute_image_info() because
* property_changed() can make use of the flags
* to set up accessors etc.
*/
if (image->common.property_changed)
image->common.property_changed (image);
image->common.dirty = FALSE;
}
if (image->common.alpha_map)
_pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
}
PIXMAN_EXPORT pixman_bool_t
pixman_image_set_clip_region32 (pixman_image_t * image,
const pixman_region32_t *region)
{
image_common_t *common = (image_common_t *)image;
pixman_bool_t result;
if (region)
{
if ((result = pixman_region32_copy (&common->clip_region, region)))
image->common.have_clip_region = TRUE;
}
else
{
_pixman_image_reset_clip_region (image);
result = TRUE;
}
image_property_changed (image);
return result;
}
PIXMAN_EXPORT pixman_bool_t
pixman_image_set_clip_region (pixman_image_t * image,
const pixman_region16_t *region)
{
image_common_t *common = (image_common_t *)image;
pixman_bool_t result;
if (region)
{
if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
image->common.have_clip_region = TRUE;
}
else
{
_pixman_image_reset_clip_region (image);
result = TRUE;
}
image_property_changed (image);
return result;
}
PIXMAN_EXPORT void
pixman_image_set_has_client_clip (pixman_image_t *image,
pixman_bool_t client_clip)
{
image->common.client_clip = client_clip;
}
PIXMAN_EXPORT pixman_bool_t
pixman_image_set_transform (pixman_image_t * image,
const pixman_transform_t *transform)
{
static const pixman_transform_t id =
{
{ { pixman_fixed_1, 0, 0 },
{ 0, pixman_fixed_1, 0 },
{ 0, 0, pixman_fixed_1 } }
};
image_common_t *common = (image_common_t *)image;
pixman_bool_t result;
if (common->transform == transform)
return TRUE;
if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
{
free (common->transform);
common->transform = NULL;
result = TRUE;
goto out;
}
if (common->transform &&
memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
{
return TRUE;
}
if (common->transform == NULL)
common->transform = malloc (sizeof (pixman_transform_t));
if (common->transform == NULL)
{
result = FALSE;
goto out;
}
memcpy (common->transform, transform, sizeof(pixman_transform_t));
result = TRUE;
out:
image_property_changed (image);
return result;
}
PIXMAN_EXPORT void
pixman_image_set_repeat (pixman_image_t *image,
pixman_repeat_t repeat)
{
if (image->common.repeat == repeat)
return;
image->common.repeat = repeat;
image_property_changed (image);
}
PIXMAN_EXPORT void
pixman_image_set_dither (pixman_image_t *image,
pixman_dither_t dither)
{
if (image->type == BITS)
{
if (image->bits.dither == dither)
return;
image->bits.dither = dither;
image_property_changed (image);
}
}
PIXMAN_EXPORT void
pixman_image_set_dither_offset (pixman_image_t *image,
int offset_x,
int offset_y)
{
if (image->type == BITS)
{
if (image->bits.dither_offset_x == offset_x &&
image->bits.dither_offset_y == offset_y)
{
return;
}
image->bits.dither_offset_x = offset_x;
image->bits.dither_offset_y = offset_y;
image_property_changed (image);
}
}
PIXMAN_EXPORT pixman_bool_t
pixman_image_set_filter (pixman_image_t * image,
pixman_filter_t filter,
const pixman_fixed_t *params,
int n_params)
{
image_common_t *common = (image_common_t *)image;
pixman_fixed_t *new_params;
if (params == common->filter_params && filter == common->filter)
return TRUE;
if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
{
int width = pixman_fixed_to_int (params[0]);
int height = pixman_fixed_to_int (params[1]);
int x_phase_bits = pixman_fixed_to_int (params[2]);
int y_phase_bits = pixman_fixed_to_int (params[3]);
int n_x_phases = (1 << x_phase_bits);
int n_y_phases = (1 << y_phase_bits);
return_val_if_fail (
n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
}
new_params = NULL;
if (params)
{
new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
if (!new_params)
return FALSE;
memcpy (new_params,
params, n_params * sizeof (pixman_fixed_t));
}
common->filter = filter;
if (common->filter_params)
free (common->filter_params);
common->filter_params = new_params;
common->n_filter_params = n_params;
image_property_changed (image);
return TRUE;
}
PIXMAN_EXPORT void
pixman_image_set_source_clipping (pixman_image_t *image,
pixman_bool_t clip_sources)
{
if (image->common.clip_sources == clip_sources)
return;
image->common.clip_sources = clip_sources;
image_property_changed (image);
}
/* Unlike all the other property setters, this function does not
* copy the content of indexed. Doing this copying is simply
* way, way too expensive.
*/
PIXMAN_EXPORT void
pixman_image_set_indexed (pixman_image_t * image,
const pixman_indexed_t *indexed)
{
bits_image_t *bits = (bits_image_t *)image;
if (bits->indexed == indexed)
return;
bits->indexed = indexed;
image_property_changed (image);
}
PIXMAN_EXPORT void
pixman_image_set_alpha_map (pixman_image_t *image,
pixman_image_t *alpha_map,
int16_t x,
int16_t y)
{
image_common_t *common = (image_common_t *)image;
return_if_fail (!alpha_map || alpha_map->type == BITS);
if (alpha_map && common->alpha_count > 0)
{
/* If this image is being used as an alpha map itself,
* then you can't give it an alpha map of its own.
*/
return;
}
if (alpha_map && alpha_map->common.alpha_map)
{
/* If the image has an alpha map of its own,
* then it can't be used as an alpha map itself
*/
return;
}
if (common->alpha_map != (bits_image_t *)alpha_map)
{
if (common->alpha_map)
{
common->alpha_map->common.alpha_count--;
pixman_image_unref ((pixman_image_t *)common->alpha_map);
}
if (alpha_map)
{
common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
common->alpha_map->common.alpha_count++;
}
else
{
common->alpha_map = NULL;
}
}
common->alpha_origin_x = x;
common->alpha_origin_y = y;
image_property_changed (image);
}
PIXMAN_EXPORT void
pixman_image_set_component_alpha (pixman_image_t *image,
pixman_bool_t component_alpha)
{
if (image->common.component_alpha == component_alpha)
return;
image->common.component_alpha = component_alpha;
image_property_changed (image);
}
PIXMAN_EXPORT pixman_bool_t
pixman_image_get_component_alpha (pixman_image_t *image)
{
return image->common.component_alpha;
}
PIXMAN_EXPORT void
pixman_image_set_accessors (pixman_image_t * image,
pixman_read_memory_func_t read_func,
pixman_write_memory_func_t write_func)
{
return_if_fail (image != NULL);
if (image->type == BITS)
{
/* Accessors only work for <= 32 bpp. */
if (PIXMAN_FORMAT_BPP(image->bits.format) > 32)
return_if_fail (!read_func && !write_func);
image->bits.read_func = read_func;
image->bits.write_func = write_func;
image_property_changed (image);
}
}
PIXMAN_EXPORT uint32_t *
pixman_image_get_data (pixman_image_t *image)
{
if (image->type == BITS)
return image->bits.bits;
return NULL;
}
PIXMAN_EXPORT int
pixman_image_get_width (pixman_image_t *image)
{
if (image->type == BITS)
return image->bits.width;
return 0;
}
PIXMAN_EXPORT int
pixman_image_get_height (pixman_image_t *image)
{
if (image->type == BITS)
return image->bits.height;
return 0;
}
PIXMAN_EXPORT int
pixman_image_get_stride (pixman_image_t *image)
{
if (image->type == BITS)
return image->bits.rowstride * (int) sizeof (uint32_t);
return 0;
}
PIXMAN_EXPORT int
pixman_image_get_depth (pixman_image_t *image)
{
if (image->type == BITS)
return PIXMAN_FORMAT_DEPTH (image->bits.format);
return 0;
}
PIXMAN_EXPORT pixman_format_code_t
pixman_image_get_format (pixman_image_t *image)
{
if (image->type == BITS)
return image->bits.format;
return PIXMAN_null;
}
uint32_t
_pixman_image_get_solid (pixman_implementation_t *imp,
pixman_image_t * image,
pixman_format_code_t format)
{
uint32_t result;
if (image->type == SOLID)
{
result = image->solid.color_32;
}
else if (image->type == BITS)
{
if (image->bits.format == PIXMAN_a8r8g8b8)
result = image->bits.bits[0];
else if (image->bits.format == PIXMAN_x8r8g8b8)
result = image->bits.bits[0] | 0xff000000;
else if (image->bits.format == PIXMAN_a8)
result = (uint32_t)(*(uint8_t *)image->bits.bits) << 24;
else
goto otherwise;
}
else
{
pixman_iter_t iter;
otherwise:
_pixman_implementation_iter_init (
imp, &iter, image, 0, 0, 1, 1,
(uint8_t *)&result,
ITER_NARROW | ITER_SRC, image->common.flags);
result = *iter.get_scanline (&iter, NULL);
if (iter.fini)
iter.fini (&iter);
}
/* If necessary, convert RGB <--> BGR. */
if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
{
result = (((result & 0xff000000) >> 0) |
((result & 0x00ff0000) >> 16) |
((result & 0x0000ff00) >> 0) |
((result & 0x000000ff) << 16));
}
return result;
}

View File

@ -1,417 +0,0 @@
/*
* Copyright © 2009 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include "pixman-private.h"
pixman_implementation_t *
_pixman_implementation_create (pixman_implementation_t *fallback,
const pixman_fast_path_t *fast_paths)
{
pixman_implementation_t *imp;
assert (fast_paths);
if ((imp = malloc (sizeof (pixman_implementation_t))))
{
pixman_implementation_t *d;
memset (imp, 0, sizeof *imp);
imp->fallback = fallback;
imp->fast_paths = fast_paths;
/* Make sure the whole fallback chain has the right toplevel */
for (d = imp; d != NULL; d = d->fallback)
d->toplevel = imp;
}
return imp;
}
#define N_CACHED_FAST_PATHS 8
typedef struct
{
struct
{
pixman_implementation_t * imp;
pixman_fast_path_t fast_path;
} cache [N_CACHED_FAST_PATHS];
} cache_t;
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache)
static void
dummy_composite_rect (pixman_implementation_t *imp,
pixman_composite_info_t *info)
{
}
void
_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
pixman_op_t op,
pixman_format_code_t src_format,
uint32_t src_flags,
pixman_format_code_t mask_format,
uint32_t mask_flags,
pixman_format_code_t dest_format,
uint32_t dest_flags,
pixman_implementation_t **out_imp,
pixman_composite_func_t *out_func)
{
pixman_implementation_t *imp;
cache_t *cache;
int i;
/* Check cache for fast paths */
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
{
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
/* Note that we check for equality here, not whether
* the cached fast path matches. This is to prevent
* us from selecting an overly general fast path
* when a more specific one would work.
*/
if (info->op == op &&
info->src_format == src_format &&
info->mask_format == mask_format &&
info->dest_format == dest_format &&
info->src_flags == src_flags &&
info->mask_flags == mask_flags &&
info->dest_flags == dest_flags &&
info->func)
{
*out_imp = cache->cache[i].imp;
*out_func = cache->cache[i].fast_path.func;
goto update_cache;
}
}
for (imp = toplevel; imp != NULL; imp = imp->fallback)
{
const pixman_fast_path_t *info = imp->fast_paths;
while (info->op != PIXMAN_OP_NONE)
{
if ((info->op == op || info->op == PIXMAN_OP_any) &&
/* Formats */
((info->src_format == src_format) ||
(info->src_format == PIXMAN_any)) &&
((info->mask_format == mask_format) ||
(info->mask_format == PIXMAN_any)) &&
((info->dest_format == dest_format) ||
(info->dest_format == PIXMAN_any)) &&
/* Flags */
(info->src_flags & src_flags) == info->src_flags &&
(info->mask_flags & mask_flags) == info->mask_flags &&
(info->dest_flags & dest_flags) == info->dest_flags)
{
*out_imp = imp;
*out_func = info->func;
/* Set i to the last spot in the cache so that the
* move-to-front code below will work
*/
i = N_CACHED_FAST_PATHS - 1;
goto update_cache;
}
++info;
}
}
/* We should never reach this point */
_pixman_log_error (
FUNC,
"No composite function found\n"
"\n"
"The most likely cause of this is that this system has issues with\n"
"thread local storage\n");
*out_imp = NULL;
*out_func = dummy_composite_rect;
return;
update_cache:
if (i)
{
while (i--)
cache->cache[i + 1] = cache->cache[i];
cache->cache[0].imp = *out_imp;
cache->cache[0].fast_path.op = op;
cache->cache[0].fast_path.src_format = src_format;
cache->cache[0].fast_path.src_flags = src_flags;
cache->cache[0].fast_path.mask_format = mask_format;
cache->cache[0].fast_path.mask_flags = mask_flags;
cache->cache[0].fast_path.dest_format = dest_format;
cache->cache[0].fast_path.dest_flags = dest_flags;
cache->cache[0].fast_path.func = *out_func;
}
}
static void
dummy_combine (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * pd,
const uint32_t * ps,
const uint32_t * pm,
int w)
{
}
pixman_combine_32_func_t
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
pixman_op_t op,
pixman_bool_t component_alpha,
pixman_bool_t narrow)
{
while (imp)
{
pixman_combine_32_func_t f = NULL;
switch ((narrow << 1) | component_alpha)
{
case 0: /* not narrow, not component alpha */
f = (pixman_combine_32_func_t)imp->combine_float[op];
break;
case 1: /* not narrow, component_alpha */
f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
break;
case 2: /* narrow, not component alpha */
f = imp->combine_32[op];
break;
case 3: /* narrow, component_alpha */
f = imp->combine_32_ca[op];
break;
}
if (f)
return f;
imp = imp->fallback;
}
/* We should never reach this point */
_pixman_log_error (FUNC, "No known combine function\n");
return dummy_combine;
}
pixman_bool_t
_pixman_implementation_blt (pixman_implementation_t * imp,
uint32_t * src_bits,
uint32_t * dst_bits,
int src_stride,
int dst_stride,
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dest_x,
int dest_y,
int width,
int height)
{
while (imp)
{
if (imp->blt &&
(*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
width, height))
{
return TRUE;
}
imp = imp->fallback;
}
return FALSE;
}
pixman_bool_t
_pixman_implementation_fill (pixman_implementation_t *imp,
uint32_t * bits,
int stride,
int bpp,
int x,
int y,
int width,
int height,
uint32_t filler)
{
while (imp)
{
if (imp->fill &&
((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
{
return TRUE;
}
imp = imp->fallback;
}
return FALSE;
}
static uint32_t *
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
{
return NULL;
}
void
_pixman_implementation_iter_init (pixman_implementation_t *imp,
pixman_iter_t *iter,
pixman_image_t *image,
int x,
int y,
int width,
int height,
uint8_t *buffer,
iter_flags_t iter_flags,
uint32_t image_flags)
{
pixman_format_code_t format;
iter->image = image;
iter->buffer = (uint32_t *)buffer;
iter->x = x;
iter->y = y;
iter->width = width;
iter->height = height;
iter->iter_flags = iter_flags;
iter->image_flags = image_flags;
iter->fini = NULL;
if (!iter->image)
{
iter->get_scanline = get_scanline_null;
return;
}
format = iter->image->common.extended_format_code;
while (imp)
{
if (imp->iter_info)
{
const pixman_iter_info_t *info;
for (info = imp->iter_info; info->format != PIXMAN_null; ++info)
{
if ((info->format == PIXMAN_any || info->format == format) &&
(info->image_flags & image_flags) == info->image_flags &&
(info->iter_flags & iter_flags) == info->iter_flags)
{
iter->get_scanline = info->get_scanline;
iter->write_back = info->write_back;
if (info->initializer)
info->initializer (iter, info);
return;
}
}
}
imp = imp->fallback;
}
}
pixman_bool_t
_pixman_disabled (const char *name)
{
const char *env;
if ((env = getenv ("PIXMAN_DISABLE")))
{
do
{
const char *end;
int len;
if ((end = strchr (env, ' ')))
len = end - env;
else
len = strlen (env);
if (strlen (name) == len && strncmp (name, env, len) == 0)
{
printf ("pixman: Disabled %s implementation\n", name);
return TRUE;
}
env += len;
}
while (*env++);
}
return FALSE;
}
static const pixman_fast_path_t empty_fast_path[] =
{
{ PIXMAN_OP_NONE }
};
pixman_implementation_t *
_pixman_choose_implementation (void)
{
pixman_implementation_t *imp;
imp = _pixman_implementation_create_general();
if (!_pixman_disabled ("fast"))
imp = _pixman_implementation_create_fast_path (imp);
imp = _pixman_x86_get_implementations (imp);
imp = _pixman_arm_get_implementations (imp);
imp = _pixman_ppc_get_implementations (imp);
imp = _pixman_mips_get_implementations (imp);
imp = _pixman_implementation_create_noop (imp);
if (_pixman_disabled ("wholeops"))
{
pixman_implementation_t *cur;
/* Disable all whole-operation paths except the general one,
* so that optimized iterators are used as much as possible.
*/
for (cur = imp; cur->fallback; cur = cur->fallback)
cur->fast_paths = empty_fast_path;
}
return imp;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,292 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include "pixman-private.h"
static pixman_bool_t
linear_gradient_is_horizontal (pixman_image_t *image,
int x,
int y,
int width,
int height)
{
linear_gradient_t *linear = (linear_gradient_t *)image;
pixman_vector_t v;
pixman_fixed_32_32_t l;
pixman_fixed_48_16_t dx, dy;
double inc;
if (image->common.transform)
{
/* projective transformation */
if (image->common.transform->matrix[2][0] != 0 ||
image->common.transform->matrix[2][1] != 0 ||
image->common.transform->matrix[2][2] == 0)
{
return FALSE;
}
v.vector[0] = image->common.transform->matrix[0][1];
v.vector[1] = image->common.transform->matrix[1][1];
v.vector[2] = image->common.transform->matrix[2][2];
}
else
{
v.vector[0] = 0;
v.vector[1] = pixman_fixed_1;
v.vector[2] = pixman_fixed_1;
}
dx = linear->p2.x - linear->p1.x;
dy = linear->p2.y - linear->p1.y;
l = dx * dx + dy * dy;
if (l == 0)
return FALSE;
/*
* compute how much the input of the gradient walked changes
* when moving vertically through the whole image
*/
inc = height * (double) pixman_fixed_1 * pixman_fixed_1 *
(dx * v.vector[0] + dy * v.vector[1]) /
(v.vector[2] * (double) l);
/* check that casting to integer would result in 0 */
if (-1 < inc && inc < 1)
return TRUE;
return FALSE;
}
static uint32_t *
linear_get_scanline (pixman_iter_t *iter,
const uint32_t *mask,
int Bpp,
pixman_gradient_walker_write_t write_pixel,
pixman_gradient_walker_fill_t fill_pixel)
{
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t * buffer = iter->buffer;
pixman_vector_t v, unit;
pixman_fixed_32_32_t l;
pixman_fixed_48_16_t dx, dy;
gradient_t *gradient = (gradient_t *)image;
linear_gradient_t *linear = (linear_gradient_t *)image;
uint32_t *end = buffer + width * (Bpp / 4);
pixman_gradient_walker_t walker;
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
if (image->common.transform)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
return iter->buffer;
unit.vector[0] = image->common.transform->matrix[0][0];
unit.vector[1] = image->common.transform->matrix[1][0];
unit.vector[2] = image->common.transform->matrix[2][0];
}
else
{
unit.vector[0] = pixman_fixed_1;
unit.vector[1] = 0;
unit.vector[2] = 0;
}
dx = linear->p2.x - linear->p1.x;
dy = linear->p2.y - linear->p1.y;
l = dx * dx + dy * dy;
if (l == 0 || unit.vector[2] == 0)
{
/* affine transformation only */
pixman_fixed_32_32_t t, next_inc;
double inc;
if (l == 0 || v.vector[2] == 0)
{
t = 0;
inc = 0;
}
else
{
double invden, v2;
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
(l * (double) v.vector[2]);
v2 = v.vector[2] * (1. / pixman_fixed_1);
t = ((dx * v.vector[0] + dy * v.vector[1]) -
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
}
next_inc = 0;
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
{
fill_pixel (&walker, t, buffer, end);
}
else
{
int i;
i = 0;
while (buffer < end)
{
if (!mask || *mask++)
{
write_pixel (&walker, t + next_inc, buffer);
}
i++;
next_inc = inc * i;
buffer += (Bpp / 4);
}
}
}
else
{
/* projective transformation */
double t;
t = 0;
while (buffer < end)
{
if (!mask || *mask++)
{
if (v.vector[2] != 0)
{
double invden, v2;
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
(l * (double) v.vector[2]);
v2 = v.vector[2] * (1. / pixman_fixed_1);
t = ((dx * v.vector[0] + dy * v.vector[1]) -
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
}
write_pixel (&walker, t, buffer);
}
buffer += (Bpp / 4);
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
}
iter->y++;
return iter->buffer;
}
static uint32_t *
linear_get_scanline_narrow (pixman_iter_t *iter,
const uint32_t *mask)
{
return linear_get_scanline (iter, mask, 4,
_pixman_gradient_walker_write_narrow,
_pixman_gradient_walker_fill_narrow);
}
static uint32_t *
linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
return linear_get_scanline (iter, NULL, 16,
_pixman_gradient_walker_write_wide,
_pixman_gradient_walker_fill_wide);
}
void
_pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
if (linear_gradient_is_horizontal (
iter->image, iter->x, iter->y, iter->width, iter->height))
{
if (iter->iter_flags & ITER_NARROW)
linear_get_scanline_narrow (iter, NULL);
else
linear_get_scanline_wide (iter, NULL);
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
else
{
if (iter->iter_flags & ITER_NARROW)
iter->get_scanline = linear_get_scanline_narrow;
else
iter->get_scanline = linear_get_scanline_wide;
}
}
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_linear_gradient (const pixman_point_fixed_t * p1,
const pixman_point_fixed_t * p2,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_image_t *image;
linear_gradient_t *linear;
image = _pixman_image_allocate ();
if (!image)
return NULL;
linear = &image->linear;
if (!_pixman_init_gradient (&linear->common, stops, n_stops))
{
free (image);
return NULL;
}
linear->p1 = *p1;
linear->p2 = *p2;
image->type = LINEAR;
return image;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,711 +0,0 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
*/
#ifndef PIXMAN_MIPS_DSPR2_ASM_H
#define PIXMAN_MIPS_DSPR2_ASM_H
#define zero $0
#define AT $1
#define v0 $2
#define v1 $3
#define a0 $4
#define a1 $5
#define a2 $6
#define a3 $7
#define t0 $8
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#define s0 $16
#define s1 $17
#define s2 $18
#define s3 $19
#define s4 $20
#define s5 $21
#define s6 $22
#define s7 $23
#define t8 $24
#define t9 $25
#define k0 $26
#define k1 $27
#define gp $28
#define sp $29
#define fp $30
#define s8 $30
#define ra $31
/*
* LEAF_MIPS32R2 - declare leaf routine for MIPS32r2
*/
#define LEAF_MIPS32R2(symbol) \
.globl symbol; \
.align 2; \
.hidden symbol; \
.type symbol, @function; \
.ent symbol, 0; \
symbol: .frame sp, 0, ra; \
.set push; \
.set arch=mips32r2; \
.set noreorder; \
.set noat;
/*
* LEAF_MIPS32R2 - declare leaf routine for MIPS DSPr2
*/
#define LEAF_MIPS_DSPR2(symbol) \
LEAF_MIPS32R2(symbol) \
.set dspr2;
/*
* END - mark end of function
*/
#define END(function) \
.set pop; \
.end function; \
.size function,.-function
/*
* Checks if stack offset is big enough for storing/restoring regs_num
* number of register to/from stack. Stack offset must be greater than
* or equal to the number of bytes needed for storing registers (regs_num*4).
* Since MIPS ABI allows usage of first 16 bytes of stack frame (this is
* preserved for input arguments of the functions, already stored in a0-a3),
* stack size can be further optimized by utilizing this space.
*/
.macro CHECK_STACK_OFFSET regs_num, stack_offset
.if \stack_offset < \regs_num * 4 - 16
.error "Stack offset too small."
.endif
.endm
/*
* Saves set of registers on stack. Maximum number of registers that
* can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
* Stack offset is number of bytes that are added to stack pointer (sp)
* before registers are pushed in order to provide enough space on stack
* (offset must be multiple of 4, and must be big enough, as described by
* CHECK_STACK_OFFSET macro). This macro is intended to be used in
* combination with RESTORE_REGS_FROM_STACK macro. Example:
* SAVE_REGS_ON_STACK 4, v0, v1, s0, s1
* RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1
*/
.macro SAVE_REGS_ON_STACK stack_offset = 0, r1, \
r2 = 0, r3 = 0, r4 = 0, \
r5 = 0, r6 = 0, r7 = 0, \
r8 = 0, r9 = 0, r10 = 0, \
r11 = 0, r12 = 0, r13 = 0, \
r14 = 0
.if (\stack_offset < 0) || (\stack_offset - (\stack_offset / 4) * 4)
.error "Stack offset must be pozitive and multiple of 4."
.endif
.if \stack_offset != 0
addiu sp, sp, -\stack_offset
.endif
sw \r1, 0(sp)
.if \r2 != 0
sw \r2, 4(sp)
.endif
.if \r3 != 0
sw \r3, 8(sp)
.endif
.if \r4 != 0
sw \r4, 12(sp)
.endif
.if \r5 != 0
CHECK_STACK_OFFSET 5, \stack_offset
sw \r5, 16(sp)
.endif
.if \r6 != 0
CHECK_STACK_OFFSET 6, \stack_offset
sw \r6, 20(sp)
.endif
.if \r7 != 0
CHECK_STACK_OFFSET 7, \stack_offset
sw \r7, 24(sp)
.endif
.if \r8 != 0
CHECK_STACK_OFFSET 8, \stack_offset
sw \r8, 28(sp)
.endif
.if \r9 != 0
CHECK_STACK_OFFSET 9, \stack_offset
sw \r9, 32(sp)
.endif
.if \r10 != 0
CHECK_STACK_OFFSET 10, \stack_offset
sw \r10, 36(sp)
.endif
.if \r11 != 0
CHECK_STACK_OFFSET 11, \stack_offset
sw \r11, 40(sp)
.endif
.if \r12 != 0
CHECK_STACK_OFFSET 12, \stack_offset
sw \r12, 44(sp)
.endif
.if \r13 != 0
CHECK_STACK_OFFSET 13, \stack_offset
sw \r13, 48(sp)
.endif
.if \r14 != 0
CHECK_STACK_OFFSET 14, \stack_offset
sw \r14, 52(sp)
.endif
.endm
/*
* Restores set of registers from stack. Maximum number of registers that
* can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
* Stack offset is number of bytes that are added to stack pointer (sp)
* after registers are restored (offset must be multiple of 4, and must
* be big enough, as described by CHECK_STACK_OFFSET macro). This macro is
* intended to be used in combination with RESTORE_REGS_FROM_STACK macro.
* Example:
* SAVE_REGS_ON_STACK 4, v0, v1, s0, s1
* RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1
*/
.macro RESTORE_REGS_FROM_STACK stack_offset = 0, r1, \
r2 = 0, r3 = 0, r4 = 0, \
r5 = 0, r6 = 0, r7 = 0, \
r8 = 0, r9 = 0, r10 = 0, \
r11 = 0, r12 = 0, r13 = 0, \
r14 = 0
.if (\stack_offset < 0) || (\stack_offset - (\stack_offset/4)*4)
.error "Stack offset must be pozitive and multiple of 4."
.endif
lw \r1, 0(sp)
.if \r2 != 0
lw \r2, 4(sp)
.endif
.if \r3 != 0
lw \r3, 8(sp)
.endif
.if \r4 != 0
lw \r4, 12(sp)
.endif
.if \r5 != 0
CHECK_STACK_OFFSET 5, \stack_offset
lw \r5, 16(sp)
.endif
.if \r6 != 0
CHECK_STACK_OFFSET 6, \stack_offset
lw \r6, 20(sp)
.endif
.if \r7 != 0
CHECK_STACK_OFFSET 7, \stack_offset
lw \r7, 24(sp)
.endif
.if \r8 != 0
CHECK_STACK_OFFSET 8, \stack_offset
lw \r8, 28(sp)
.endif
.if \r9 != 0
CHECK_STACK_OFFSET 9, \stack_offset
lw \r9, 32(sp)
.endif
.if \r10 != 0
CHECK_STACK_OFFSET 10, \stack_offset
lw \r10, 36(sp)
.endif
.if \r11 != 0
CHECK_STACK_OFFSET 11, \stack_offset
lw \r11, 40(sp)
.endif
.if \r12 != 0
CHECK_STACK_OFFSET 12, \stack_offset
lw \r12, 44(sp)
.endif
.if \r13 != 0
CHECK_STACK_OFFSET 13, \stack_offset
lw \r13, 48(sp)
.endif
.if \r14 != 0
CHECK_STACK_OFFSET 14, \stack_offset
lw \r14, 52(sp)
.endif
.if \stack_offset != 0
addiu sp, sp, \stack_offset
.endif
.endm
/*
* Conversion of single r5g6b5 pixel (in_565) to single a8r8g8b8 pixel
* returned in (out_8888) register. Requires two temporary registers
* (scratch1 and scratch2).
*/
.macro CONVERT_1x0565_TO_1x8888 in_565, \
out_8888, \
scratch1, scratch2
lui \out_8888, 0xff00
sll \scratch1, \in_565, 0x3
andi \scratch2, \scratch1, 0xff
ext \scratch1, \in_565, 0x2, 0x3
or \scratch1, \scratch2, \scratch1
or \out_8888, \out_8888, \scratch1
sll \scratch1, \in_565, 0x5
andi \scratch1, \scratch1, 0xfc00
srl \scratch2, \in_565, 0x1
andi \scratch2, \scratch2, 0x300
or \scratch2, \scratch1, \scratch2
or \out_8888, \out_8888, \scratch2
andi \scratch1, \in_565, 0xf800
srl \scratch2, \scratch1, 0x5
andi \scratch2, \scratch2, 0xff00
or \scratch1, \scratch1, \scratch2
sll \scratch1, \scratch1, 0x8
or \out_8888, \out_8888, \scratch1
.endm
/*
* Conversion of two r5g6b5 pixels (in1_565 and in2_565) to two a8r8g8b8 pixels
* returned in (out1_8888 and out2_8888) registers. Requires four scratch
* registers (scratch1 ... scratch4). It also requires maskG and maskB for
* color component extractions. These masks must have following values:
* li maskG, 0x07e007e0
* li maskB, 0x001F001F
*/
.macro CONVERT_2x0565_TO_2x8888 in1_565, in2_565, \
out1_8888, out2_8888, \
maskG, maskB, \
scratch1, scratch2, scratch3, scratch4
sll \scratch1, \in1_565, 16
or \scratch1, \scratch1, \in2_565
lui \out2_8888, 0xff00
ori \out2_8888, \out2_8888, 0xff00
shrl.ph \scratch2, \scratch1, 11
and \scratch3, \scratch1, \maskG
shra.ph \scratch4, \scratch2, 2
shll.ph \scratch2, \scratch2, 3
shll.ph \scratch3, \scratch3, 5
or \scratch2, \scratch2, \scratch4
shrl.qb \scratch4, \scratch3, 6
or \out2_8888, \out2_8888, \scratch2
or \scratch3, \scratch3, \scratch4
and \scratch1, \scratch1, \maskB
shll.ph \scratch2, \scratch1, 3
shra.ph \scratch4, \scratch1, 2
or \scratch2, \scratch2, \scratch4
or \scratch3, \scratch2, \scratch3
precrq.ph.w \out1_8888, \out2_8888, \scratch3
precr_sra.ph.w \out2_8888, \scratch3, 0
.endm
/*
* Conversion of single a8r8g8b8 pixel (in_8888) to single r5g6b5 pixel
* returned in (out_565) register. Requires two temporary registers
* (scratch1 and scratch2).
*/
.macro CONVERT_1x8888_TO_1x0565 in_8888, \
out_565, \
scratch1, scratch2
ext \out_565, \in_8888, 0x3, 0x5
srl \scratch1, \in_8888, 0x5
andi \scratch1, \scratch1, 0x07e0
srl \scratch2, \in_8888, 0x8
andi \scratch2, \scratch2, 0xf800
or \out_565, \out_565, \scratch1
or \out_565, \out_565, \scratch2
.endm
/*
* Conversion of two a8r8g8b8 pixels (in1_8888 and in2_8888) to two r5g6b5
* pixels returned in (out1_565 and out2_565) registers. Requires two temporary
* registers (scratch1 and scratch2). It also requires maskR, maskG and maskB
* for color component extractions. These masks must have following values:
* li maskR, 0xf800f800
* li maskG, 0x07e007e0
* li maskB, 0x001F001F
* Value of input register in2_8888 is lost.
*/
.macro CONVERT_2x8888_TO_2x0565 in1_8888, in2_8888, \
out1_565, out2_565, \
maskR, maskG, maskB, \
scratch1, scratch2
precr.qb.ph \scratch1, \in2_8888, \in1_8888
precrq.qb.ph \in2_8888, \in2_8888, \in1_8888
and \out1_565, \scratch1, \maskR
shrl.ph \scratch1, \scratch1, 3
shll.ph \in2_8888, \in2_8888, 3
and \scratch1, \scratch1, \maskB
or \out1_565, \out1_565, \scratch1
and \in2_8888, \in2_8888, \maskG
or \out1_565, \out1_565, \in2_8888
srl \out2_565, \out1_565, 16
.endm
/*
* Multiply pixel (a8) with single pixel (a8r8g8b8). It requires maskLSR needed
* for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro MIPS_UN8x4_MUL_UN8 s_8888, \
m_8, \
d_8888, \
maskLSR, \
scratch1, scratch2, scratch3
replv.ph \m_8, \m_8 /* 0 | M | 0 | M */
muleu_s.ph.qbl \scratch1, \s_8888, \m_8 /* A*M | R*M */
muleu_s.ph.qbr \scratch2, \s_8888, \m_8 /* G*M | B*M */
shra_r.ph \scratch3, \scratch1, 8
shra_r.ph \d_8888, \scratch2, 8
and \scratch3, \scratch3, \maskLSR /* 0 |A*M| 0 |R*M */
and \d_8888, \d_8888, \maskLSR /* 0 |G*M| 0 |B*M */
addq.ph \scratch1, \scratch1, \scratch3 /* A*M+A*M | R*M+R*M */
addq.ph \scratch2, \scratch2, \d_8888 /* G*M+G*M | B*M+B*M */
shra_r.ph \scratch1, \scratch1, 8
shra_r.ph \scratch2, \scratch2, 8
precr.qb.ph \d_8888, \scratch1, \scratch2
.endm
/*
* Multiply two pixels (a8) with two pixels (a8r8g8b8). It requires maskLSR
* needed for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro MIPS_2xUN8x4_MUL_2xUN8 s1_8888, \
s2_8888, \
m1_8, \
m2_8, \
d1_8888, \
d2_8888, \
maskLSR, \
scratch1, scratch2, scratch3, \
scratch4, scratch5, scratch6
replv.ph \m1_8, \m1_8 /* 0 | M1 | 0 | M1 */
replv.ph \m2_8, \m2_8 /* 0 | M2 | 0 | M2 */
muleu_s.ph.qbl \scratch1, \s1_8888, \m1_8 /* A1*M1 | R1*M1 */
muleu_s.ph.qbr \scratch2, \s1_8888, \m1_8 /* G1*M1 | B1*M1 */
muleu_s.ph.qbl \scratch3, \s2_8888, \m2_8 /* A2*M2 | R2*M2 */
muleu_s.ph.qbr \scratch4, \s2_8888, \m2_8 /* G2*M2 | B2*M2 */
shra_r.ph \scratch5, \scratch1, 8
shra_r.ph \d1_8888, \scratch2, 8
shra_r.ph \scratch6, \scratch3, 8
shra_r.ph \d2_8888, \scratch4, 8
and \scratch5, \scratch5, \maskLSR /* 0 |A1*M1| 0 |R1*M1 */
and \d1_8888, \d1_8888, \maskLSR /* 0 |G1*M1| 0 |B1*M1 */
and \scratch6, \scratch6, \maskLSR /* 0 |A2*M2| 0 |R2*M2 */
and \d2_8888, \d2_8888, \maskLSR /* 0 |G2*M2| 0 |B2*M2 */
addq.ph \scratch1, \scratch1, \scratch5
addq.ph \scratch2, \scratch2, \d1_8888
addq.ph \scratch3, \scratch3, \scratch6
addq.ph \scratch4, \scratch4, \d2_8888
shra_r.ph \scratch1, \scratch1, 8
shra_r.ph \scratch2, \scratch2, 8
shra_r.ph \scratch3, \scratch3, 8
shra_r.ph \scratch4, \scratch4, 8
precr.qb.ph \d1_8888, \scratch1, \scratch2
precr.qb.ph \d2_8888, \scratch3, \scratch4
.endm
/*
* Multiply pixel (a8r8g8b8) with single pixel (a8r8g8b8). It requires maskLSR
* needed for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro MIPS_UN8x4_MUL_UN8x4 s_8888, \
m_8888, \
d_8888, \
maskLSR, \
scratch1, scratch2, scratch3, scratch4
preceu.ph.qbl \scratch1, \m_8888 /* 0 | A | 0 | R */
preceu.ph.qbr \scratch2, \m_8888 /* 0 | G | 0 | B */
muleu_s.ph.qbl \scratch3, \s_8888, \scratch1 /* A*A | R*R */
muleu_s.ph.qbr \scratch4, \s_8888, \scratch2 /* G*G | B*B */
shra_r.ph \scratch1, \scratch3, 8
shra_r.ph \scratch2, \scratch4, 8
and \scratch1, \scratch1, \maskLSR /* 0 |A*A| 0 |R*R */
and \scratch2, \scratch2, \maskLSR /* 0 |G*G| 0 |B*B */
addq.ph \scratch1, \scratch1, \scratch3
addq.ph \scratch2, \scratch2, \scratch4
shra_r.ph \scratch1, \scratch1, 8
shra_r.ph \scratch2, \scratch2, 8
precr.qb.ph \d_8888, \scratch1, \scratch2
.endm
/*
* Multiply two pixels (a8r8g8b8) with two pixels (a8r8g8b8). It requires
* maskLSR needed for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro MIPS_2xUN8x4_MUL_2xUN8x4 s1_8888, \
s2_8888, \
m1_8888, \
m2_8888, \
d1_8888, \
d2_8888, \
maskLSR, \
scratch1, scratch2, scratch3, \
scratch4, scratch5, scratch6
preceu.ph.qbl \scratch1, \m1_8888 /* 0 | A | 0 | R */
preceu.ph.qbr \scratch2, \m1_8888 /* 0 | G | 0 | B */
preceu.ph.qbl \scratch3, \m2_8888 /* 0 | A | 0 | R */
preceu.ph.qbr \scratch4, \m2_8888 /* 0 | G | 0 | B */
muleu_s.ph.qbl \scratch5, \s1_8888, \scratch1 /* A*A | R*R */
muleu_s.ph.qbr \scratch6, \s1_8888, \scratch2 /* G*G | B*B */
muleu_s.ph.qbl \scratch1, \s2_8888, \scratch3 /* A*A | R*R */
muleu_s.ph.qbr \scratch2, \s2_8888, \scratch4 /* G*G | B*B */
shra_r.ph \scratch3, \scratch5, 8
shra_r.ph \scratch4, \scratch6, 8
shra_r.ph \d1_8888, \scratch1, 8
shra_r.ph \d2_8888, \scratch2, 8
and \scratch3, \scratch3, \maskLSR /* 0 |A*A| 0 |R*R */
and \scratch4, \scratch4, \maskLSR /* 0 |G*G| 0 |B*B */
and \d1_8888, \d1_8888, \maskLSR /* 0 |A*A| 0 |R*R */
and \d2_8888, \d2_8888, \maskLSR /* 0 |G*G| 0 |B*B */
addq.ph \scratch3, \scratch3, \scratch5
addq.ph \scratch4, \scratch4, \scratch6
addq.ph \d1_8888, \d1_8888, \scratch1
addq.ph \d2_8888, \d2_8888, \scratch2
shra_r.ph \scratch3, \scratch3, 8
shra_r.ph \scratch4, \scratch4, 8
shra_r.ph \scratch5, \d1_8888, 8
shra_r.ph \scratch6, \d2_8888, 8
precr.qb.ph \d1_8888, \scratch3, \scratch4
precr.qb.ph \d2_8888, \scratch5, \scratch6
.endm
/*
* OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8
* destination pixel (d_8888) using a8 mask (m_8). It also requires maskLSR
* needed for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro OVER_8888_8_8888 s_8888, \
m_8, \
d_8888, \
out_8888, \
maskLSR, \
scratch1, scratch2, scratch3, scratch4
MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \
\scratch1, \maskLSR, \
\scratch2, \scratch3, \scratch4
not \scratch2, \scratch1
srl \scratch2, \scratch2, 24
MIPS_UN8x4_MUL_UN8 \d_8888, \scratch2, \
\d_8888, \maskLSR, \
\scratch3, \scratch4, \out_8888
addu_s.qb \out_8888, \d_8888, \scratch1
.endm
/*
* OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two
* a8r8g8b8 destination pixels (d1_8888 and d2_8888) using a8 masks (m1_8 and
* m2_8). It also requires maskLSR needed for rounding process. maskLSR must
* have following value:
* li maskLSR, 0x00ff00ff
*/
.macro OVER_2x8888_2x8_2x8888 s1_8888, \
s2_8888, \
m1_8, \
m2_8, \
d1_8888, \
d2_8888, \
out1_8888, \
out2_8888, \
maskLSR, \
scratch1, scratch2, scratch3, \
scratch4, scratch5, scratch6
MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \
\m1_8, \m2_8, \
\scratch1, \scratch2, \
\maskLSR, \
\scratch3, \scratch4, \out1_8888, \
\out2_8888, \scratch5, \scratch6
not \scratch3, \scratch1
srl \scratch3, \scratch3, 24
not \scratch4, \scratch2
srl \scratch4, \scratch4, 24
MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \
\scratch3, \scratch4, \
\d1_8888, \d2_8888, \
\maskLSR, \
\scratch5, \scratch6, \out1_8888, \
\out2_8888, \scratch3, \scratch4
addu_s.qb \out1_8888, \d1_8888, \scratch1
addu_s.qb \out2_8888, \d2_8888, \scratch2
.endm
/*
* OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8
* destination pixel (d_8888). It also requires maskLSR needed for rounding
* process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro OVER_8888_8888 s_8888, \
d_8888, \
out_8888, \
maskLSR, \
scratch1, scratch2, scratch3, scratch4
not \scratch1, \s_8888
srl \scratch1, \scratch1, 24
MIPS_UN8x4_MUL_UN8 \d_8888, \scratch1, \
\out_8888, \maskLSR, \
\scratch2, \scratch3, \scratch4
addu_s.qb \out_8888, \out_8888, \s_8888
.endm
/*
* OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two
* a8r8g8b8 destination pixels (d1_8888 and d2_8888). It also requires maskLSR
* needed for rounding process. maskLSR must have following value:
* li maskLSR, 0x00ff00ff
*/
.macro OVER_2x8888_2x8888 s1_8888, \
s2_8888, \
d1_8888, \
d2_8888, \
out1_8888, \
out2_8888, \
maskLSR, \
scratch1, scratch2, scratch3, \
scratch4, scratch5, scratch6
not \scratch1, \s1_8888
srl \scratch1, \scratch1, 24
not \scratch2, \s2_8888
srl \scratch2, \scratch2, 24
MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \
\scratch1, \scratch2, \
\out1_8888, \out2_8888, \
\maskLSR, \
\scratch3, \scratch4, \scratch5, \
\scratch6, \d1_8888, \d2_8888
addu_s.qb \out1_8888, \out1_8888, \s1_8888
addu_s.qb \out2_8888, \out2_8888, \s2_8888
.endm
.macro MIPS_UN8x4_MUL_UN8_ADD_UN8x4 s_8888, \
m_8, \
d_8888, \
out_8888, \
maskLSR, \
scratch1, scratch2, scratch3
MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \
\out_8888, \maskLSR, \
\scratch1, \scratch2, \scratch3
addu_s.qb \out_8888, \out_8888, \d_8888
.endm
.macro MIPS_2xUN8x4_MUL_2xUN8_ADD_2xUN8x4 s1_8888, \
s2_8888, \
m1_8, \
m2_8, \
d1_8888, \
d2_8888, \
out1_8888, \
out2_8888, \
maskLSR, \
scratch1, scratch2, scratch3, \
scratch4, scratch5, scratch6
MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \
\m1_8, \m2_8, \
\out1_8888, \out2_8888, \
\maskLSR, \
\scratch1, \scratch2, \scratch3, \
\scratch4, \scratch5, \scratch6
addu_s.qb \out1_8888, \out1_8888, \d1_8888
addu_s.qb \out2_8888, \out2_8888, \d2_8888
.endm
.macro BILINEAR_INTERPOLATE_SINGLE_PIXEL tl, tr, bl, br, \
scratch1, scratch2, \
alpha, red, green, blue \
wt1, wt2, wb1, wb2
andi \scratch1, \tl, 0xff
andi \scratch2, \tr, 0xff
andi \alpha, \bl, 0xff
andi \red, \br, 0xff
multu $ac0, \wt1, \scratch1
maddu $ac0, \wt2, \scratch2
maddu $ac0, \wb1, \alpha
maddu $ac0, \wb2, \red
ext \scratch1, \tl, 8, 8
ext \scratch2, \tr, 8, 8
ext \alpha, \bl, 8, 8
ext \red, \br, 8, 8
multu $ac1, \wt1, \scratch1
maddu $ac1, \wt2, \scratch2
maddu $ac1, \wb1, \alpha
maddu $ac1, \wb2, \red
ext \scratch1, \tl, 16, 8
ext \scratch2, \tr, 16, 8
ext \alpha, \bl, 16, 8
ext \red, \br, 16, 8
mflo \blue, $ac0
multu $ac2, \wt1, \scratch1
maddu $ac2, \wt2, \scratch2
maddu $ac2, \wb1, \alpha
maddu $ac2, \wb2, \red
ext \scratch1, \tl, 24, 8
ext \scratch2, \tr, 24, 8
ext \alpha, \bl, 24, 8
ext \red, \br, 24, 8
mflo \green, $ac1
multu $ac3, \wt1, \scratch1
maddu $ac3, \wt2, \scratch2
maddu $ac3, \wb1, \alpha
maddu $ac3, \wb2, \red
mflo \red, $ac2
mflo \alpha, $ac3
precr.qb.ph \alpha, \alpha, \red
precr.qb.ph \scratch1, \green, \blue
precrq.qb.ph \tl, \alpha, \scratch1
.endm
#endif //PIXMAN_MIPS_DSPR2_ASM_H

View File

@ -1,459 +0,0 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
#include "pixman-mips-dspr2.h"
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_x888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_8888_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0565_8888,
uint16_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0565_0565,
uint16_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888,
uint8_t, 3, uint8_t, 3)
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0888_8888_rev,
uint8_t, 3, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0888_0565_rev,
uint8_t, 3, uint16_t, 1)
#endif
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_pixbuf_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_rpixbuf_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, over_8888_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, add_8888_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, out_reverse_8_0565,
uint8_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, out_reverse_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (0, src_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (0, src_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca,
uint32_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565,
uint8_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8,
uint8_t, 1, uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, add_n_8_8888,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_8888_n_0565,
uint32_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, over_0565_n_0565,
uint16_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST (SKIP_ZERO_MASK, add_8888_n_8888,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_n_0565,
uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_n_8888,
uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (SKIP_ZERO_SRC, over_reverse_n_8888,
uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_N_DST (0, in_n_8,
uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8_8_8, uint8_t, 1,
uint8_t, 1, uint8_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8_8888, uint32_t, 1,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_8888_8888_8888, uint32_t, 1,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (add_0565_8_0565, uint16_t, 1,
uint8_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_8888, uint32_t, 1,
uint8_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8_0565, uint32_t, 1,
uint8_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_0565_8_0565, uint16_t, 1,
uint8_t, 1, uint16_t, 1)
PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST (over_8888_8888_8888, uint32_t, 1,
uint32_t, 1, uint32_t, 1)
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (8888_8888, OVER,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (8888_0565, OVER,
uint32_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST (0565_8888, SRC,
uint16_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC,
uint32_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_8888, SRC,
uint16_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_0565, SRC,
uint16_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, OVER,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, ADD,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_0565,
OVER, uint32_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST (SKIP_ZERO_SRC, 0565_8_0565,
OVER, uint16_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_8888, SRC,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_0565, SRC,
uint32_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_x888, SRC,
uint16_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_0565, SRC,
uint16_t, uint16_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, OVER,
uint32_t, uint32_t)
PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD,
uint32_t, uint32_t)
static pixman_bool_t
mips_dspr2_fill (pixman_implementation_t *imp,
uint32_t * bits,
int stride,
int bpp,
int x,
int y,
int width,
int height,
uint32_t _xor)
{
uint8_t *byte_line;
uint32_t byte_width;
switch (bpp)
{
case 16:
stride = stride * (int) sizeof (uint32_t) / 2;
byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
byte_width = width * 2;
stride *= 2;
while (height--)
{
uint8_t *dst = byte_line;
byte_line += stride;
pixman_fill_buff16_mips (dst, byte_width, _xor & 0xffff);
}
return TRUE;
case 32:
stride = stride * (int) sizeof (uint32_t) / 4;
byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
byte_width = width * 4;
stride *= 4;
while (height--)
{
uint8_t *dst = byte_line;
byte_line += stride;
pixman_fill_buff32_mips (dst, byte_width, _xor);
}
return TRUE;
default:
return FALSE;
}
}
static pixman_bool_t
mips_dspr2_blt (pixman_implementation_t *imp,
uint32_t * src_bits,
uint32_t * dst_bits,
int src_stride,
int dst_stride,
int src_bpp,
int dst_bpp,
int src_x,
int src_y,
int dest_x,
int dest_y,
int width,
int height)
{
if (src_bpp != dst_bpp)
return FALSE;
uint8_t *src_bytes;
uint8_t *dst_bytes;
uint32_t byte_width;
switch (src_bpp)
{
case 16:
src_stride = src_stride * (int) sizeof (uint32_t) / 2;
dst_stride = dst_stride * (int) sizeof (uint32_t) / 2;
src_bytes =(uint8_t *)(((uint16_t *)src_bits)
+ src_stride * (src_y) + (src_x));
dst_bytes = (uint8_t *)(((uint16_t *)dst_bits)
+ dst_stride * (dest_y) + (dest_x));
byte_width = width * 2;
src_stride *= 2;
dst_stride *= 2;
while (height--)
{
uint8_t *src = src_bytes;
uint8_t *dst = dst_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
pixman_mips_fast_memcpy (dst, src, byte_width);
}
return TRUE;
case 32:
src_stride = src_stride * (int) sizeof (uint32_t) / 4;
dst_stride = dst_stride * (int) sizeof (uint32_t) / 4;
src_bytes = (uint8_t *)(((uint32_t *)src_bits)
+ src_stride * (src_y) + (src_x));
dst_bytes = (uint8_t *)(((uint32_t *)dst_bits)
+ dst_stride * (dest_y) + (dest_x));
byte_width = width * 4;
src_stride *= 4;
dst_stride *= 4;
while (height--)
{
uint8_t *src = src_bytes;
uint8_t *dst = dst_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
pixman_mips_fast_memcpy (dst, src, byte_width);
}
return TRUE;
default:
return FALSE;
}
}
static const pixman_fast_path_t mips_dspr2_fast_paths[] =
{
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, mips_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, mips_composite_src_0565_0565),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, mips_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, mips_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, mips_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, mips_composite_src_0565_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, mips_composite_src_8888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, mips_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, mips_composite_src_x888_8888),
PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, mips_composite_src_0888_0888),
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, x8r8g8b8, mips_composite_src_0888_8888_rev),
PIXMAN_STD_FAST_PATH (SRC, b8g8r8, null, r5g6b5, mips_composite_src_0888_0565_rev),
#endif
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8r8g8b8, mips_composite_src_pixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, pixbuf, pixbuf, a8b8g8r8, mips_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8r8g8b8, mips_composite_src_rpixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, rpixbuf, rpixbuf, a8b8g8r8, mips_composite_src_pixbuf_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mips_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mips_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mips_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, mips_composite_src_n_8_8888),
PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8, mips_composite_src_n_8_8),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, mips_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, mips_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, mips_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mips_composite_over_n_8888_8888_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mips_composite_over_n_8888_0565_ca),
PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mips_composite_over_n_8888_0565_ca),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8, mips_composite_over_n_8_8),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mips_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mips_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mips_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, mips_composite_over_n_8_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mips_composite_over_n_8_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mips_composite_over_n_8_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, mips_composite_over_n_0565),
PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, mips_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, mips_composite_over_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, a8r8g8b8, mips_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, x8r8g8b8, mips_composite_over_8888_n_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, solid, r5g6b5, mips_composite_over_8888_n_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, solid, b5g6r5, mips_composite_over_8888_n_0565),
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, solid, r5g6b5, mips_composite_over_0565_n_0565),
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, solid, b5g6r5, mips_composite_over_0565_n_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, a8r8g8b8, mips_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, x8r8g8b8, mips_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, a8b8g8r8, mips_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, x8b8g8r8, mips_composite_over_8888_8_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8, r5g6b5, mips_composite_over_8888_8_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, a8, b5g6r5, mips_composite_over_8888_8_0565),
PIXMAN_STD_FAST_PATH (OVER, r5g6b5, a8, r5g6b5, mips_composite_over_0565_8_0565),
PIXMAN_STD_FAST_PATH (OVER, b5g6r5, a8, b5g6r5, mips_composite_over_0565_8_0565),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_over_8888_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, mips_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, mips_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, mips_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mips_composite_over_8888_8888),
PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, r5g6b5, mips_composite_over_8888_0565),
PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, mips_composite_over_8888_0565),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mips_composite_add_n_8_8),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8r8g8b8, mips_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8b8g8r8, mips_composite_add_n_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8, a8, a8, mips_composite_add_8_8_8),
PIXMAN_STD_FAST_PATH (ADD, r5g6b5, a8, r5g6b5, mips_composite_add_0565_8_0565),
PIXMAN_STD_FAST_PATH (ADD, b5g6r5, a8, b5g6r5, mips_composite_add_0565_8_0565),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8, a8r8g8b8, mips_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, a8, a8b8g8r8, mips_composite_add_8888_8_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, a8r8g8b8, mips_composite_add_8888_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, solid, a8r8g8b8, mips_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, solid, a8b8g8r8, mips_composite_add_8888_n_8888),
PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mips_composite_add_8_8),
PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, mips_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, mips_composite_add_8888_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, r5g6b5, mips_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, b5g6r5, mips_composite_out_reverse_8_0565),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8r8g8b8, mips_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OUT_REVERSE, a8, null, a8b8g8r8, mips_composite_out_reverse_8_8888),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, mips_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, mips_composite_over_reverse_n_8888),
PIXMAN_STD_FAST_PATH (IN, solid, null, a8, mips_composite_in_n_8),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mips_8888_8888),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mips_8888_8888),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_0565),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_0565),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (SRC, b5g6r5, x8b8g8r8, mips_0565_8888),
PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888),
/* Note: NONE repeat is not supported yet */
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, r5g6b5, a8r8g8b8, mips_0565_8888),
SIMPLE_NEAREST_FAST_PATH_COVER (SRC, b5g6r5, a8b8g8r8, mips_0565_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, r5g6b5, a8r8g8b8, mips_0565_8888),
SIMPLE_NEAREST_FAST_PATH_PAD (SRC, b5g6r5, a8b8g8r8, mips_0565_8888),
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8r8g8b8, r5g6b5, mips_8888_8_0565),
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, a8b8g8r8, b5g6r5, mips_8888_8_0565),
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, r5g6b5, r5g6b5, mips_0565_8_0565),
SIMPLE_NEAREST_A8_MASK_FAST_PATH (OVER, b5g6r5, b5g6r5, mips_0565_8_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_0565),
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888),
SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_0565),
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8_x888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_8_0565),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8_8888),
SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8_8888),
{ PIXMAN_OP_NONE },
};
static void
mips_dspr2_combine_over_u (pixman_implementation_t *imp,
pixman_op_t op,
uint32_t * dest,
const uint32_t * src,
const uint32_t * mask,
int width)
{
if (mask)
pixman_composite_over_8888_8888_8888_asm_mips (
dest, (uint32_t *)src, (uint32_t *)mask, width);
else
pixman_composite_over_8888_8888_asm_mips (
dest, (uint32_t *)src, width);
}
pixman_implementation_t *
_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, mips_dspr2_fast_paths);
imp->combine_32[PIXMAN_OP_OVER] = mips_dspr2_combine_over_u;
imp->blt = mips_dspr2_blt;
imp->fill = mips_dspr2_fill;
return imp;
}

View File

@ -1,432 +0,0 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Nemanja Lukic (nemanja.lukic@rt-rk.com)
*/
#ifndef PIXMAN_MIPS_DSPR2_H
#define PIXMAN_MIPS_DSPR2_H
#include "pixman-private.h"
#include "pixman-inlines.h"
#define SKIP_ZERO_SRC 1
#define SKIP_ZERO_MASK 2
#define DO_FAST_MEMCPY 3
void
pixman_mips_fast_memcpy (void *dst, void *src, uint32_t n_bytes);
void
pixman_fill_buff16_mips (void *dst, uint32_t n_bytes, uint16_t value);
void
pixman_fill_buff32_mips (void *dst, uint32_t n_bytes, uint32_t value);
/****************************************************************/
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST(flags, name, \
src_type, src_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_mips (dst_type *dst, \
src_type *src, \
int32_t w); \
\
static void \
mips_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line, *dst; \
src_type *src_line, *src; \
int32_t dst_stride, src_stride; \
int bpp = PIXMAN_FORMAT_BPP (dest_image->bits.format) / 8; \
\
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
while (height--) \
{ \
dst = dst_line; \
dst_line += dst_stride; \
src = src_line; \
src_line += src_stride; \
\
if (flags == DO_FAST_MEMCPY) \
pixman_mips_fast_memcpy (dst, src, width * bpp); \
else \
pixman_composite_##name##_asm_mips (dst, src, width); \
} \
}
/****************************************************************/
#define PIXMAN_MIPS_BIND_FAST_PATH_N_DST(flags, name, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_mips (dst_type *dst, \
uint32_t src, \
int32_t w); \
\
static void \
mips_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line, *dst; \
int32_t dst_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
\
while (height--) \
{ \
dst = dst_line; \
dst_line += dst_stride; \
\
pixman_composite_##name##_asm_mips (dst, src, width); \
} \
}
/*******************************************************************/
#define PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST(flags, name, \
mask_type, mask_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_mips (dst_type *dst, \
uint32_t src, \
mask_type *mask, \
int32_t w); \
\
static void \
mips_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line, *dst; \
mask_type *mask_line, *mask; \
int32_t dst_stride, mask_stride; \
uint32_t src; \
\
src = _pixman_image_get_solid ( \
imp, src_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_SRC) && src == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
mask_stride, mask_line, mask_cnt); \
\
while (height--) \
{ \
dst = dst_line; \
dst_line += dst_stride; \
mask = mask_line; \
mask_line += mask_stride; \
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
} \
}
/*******************************************************************/
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_N_DST(flags, name, \
src_type, src_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_mips (dst_type *dst, \
src_type *src, \
uint32_t mask, \
int32_t w); \
\
static void \
mips_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line, *dst; \
src_type *src_line, *src; \
int32_t dst_stride, src_stride; \
uint32_t mask; \
\
mask = _pixman_image_get_solid ( \
imp, mask_image, dest_image->bits.format); \
\
if ((flags & SKIP_ZERO_MASK) && mask == 0) \
return; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
\
while (height--) \
{ \
dst = dst_line; \
dst_line += dst_stride; \
src = src_line; \
src_line += src_stride; \
\
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
} \
}
/************************************************************************/
#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_MASK_DST(name, src_type, src_cnt, \
mask_type, mask_cnt, \
dst_type, dst_cnt) \
void \
pixman_composite_##name##_asm_mips (dst_type *dst, \
src_type *src, \
mask_type *mask, \
int32_t w); \
\
static void \
mips_composite_##name (pixman_implementation_t *imp, \
pixman_composite_info_t *info) \
{ \
PIXMAN_COMPOSITE_ARGS (info); \
dst_type *dst_line, *dst; \
src_type *src_line, *src; \
mask_type *mask_line, *mask; \
int32_t dst_stride, src_stride, mask_stride; \
\
PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \
dst_stride, dst_line, dst_cnt); \
PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \
src_stride, src_line, src_cnt); \
PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \
mask_stride, mask_line, mask_cnt); \
\
while (height--) \
{ \
dst = dst_line; \
dst_line += dst_stride; \
mask = mask_line; \
mask_line += mask_stride; \
src = src_line; \
src_line += src_stride; \
pixman_composite_##name##_asm_mips (dst, src, mask, width); \
} \
}
/****************************************************************************/
#define PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_DST(name, op, \
src_type, dst_type) \
void \
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips ( \
dst_type * dst, \
const src_type * src, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x); \
\
static force_inline void \
scaled_nearest_scanline_mips_##name##_##op (dst_type * pd, \
const src_type * ps, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips (pd, ps, w, \
vx, unit_x); \
} \
\
FAST_NEAREST_MAINLOOP (mips_##name##_cover_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, dst_type, COVER) \
FAST_NEAREST_MAINLOOP (mips_##name##_none_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, dst_type, NONE) \
FAST_NEAREST_MAINLOOP (mips_##name##_pad_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, dst_type, PAD)
/* Provide entries for the fast path table */
#define PIXMAN_MIPS_SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \
SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \
SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func)
/*****************************************************************************/
#define PIXMAN_MIPS_BIND_SCALED_NEAREST_SRC_A8_DST(flags, name, op, \
src_type, dst_type) \
void \
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips ( \
dst_type * dst, \
const src_type * src, \
const uint8_t * mask, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x); \
\
static force_inline void \
scaled_nearest_scanline_mips_##name##_##op (const uint8_t * mask, \
dst_type * pd, \
const src_type * ps, \
int32_t w, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_nearest_scanline_##name##_##op##_asm_mips (pd, ps, \
mask, w, \
vx, unit_x); \
} \
\
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_cover_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, COVER, TRUE, FALSE)\
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_none_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
FAST_NEAREST_MAINLOOP_COMMON (mips_##name##_pad_##op, \
scaled_nearest_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, PAD, TRUE, FALSE)
/****************************************************************************/
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \
src_type, dst_type) \
void \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips( \
dst_type * dst, \
const src_type * src_top, \
const src_type * src_bottom, \
int32_t w, \
int wt, \
int wb, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x); \
static force_inline void \
scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \
const uint32_t * mask, \
const src_type * src_top, \
const src_type * src_bottom, \
int32_t w, \
int wt, \
int wb, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips (dst, src_top, \
src_bottom, w, \
wt, wb, \
vx, unit_x); \
} \
\
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint32_t, dst_type, COVER, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint32_t, dst_type, NONE, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint32_t, dst_type, PAD, FLAG_NONE) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint32_t, dst_type, NORMAL, \
FLAG_NONE)
/*****************************************************************************/
#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, name, op, \
src_type, dst_type) \
void \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \
dst_type * dst, \
const uint8_t * mask, \
const src_type * top, \
const src_type * bottom, \
int wt, \
int wb, \
pixman_fixed_t x, \
pixman_fixed_t ux, \
int width); \
\
static force_inline void \
scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \
const uint8_t * mask, \
const src_type * src_top, \
const src_type * src_bottom, \
int32_t w, \
int wt, \
int wb, \
pixman_fixed_t vx, \
pixman_fixed_t unit_x, \
pixman_fixed_t max_vx, \
pixman_bool_t zero_src) \
{ \
if ((flags & SKIP_ZERO_SRC) && zero_src) \
return; \
pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \
dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
} \
\
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, COVER, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, NONE, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, PAD, \
FLAG_HAVE_NON_SOLID_MASK) \
FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \
scaled_bilinear_scanline_mips_##name##_##op, \
src_type, uint8_t, dst_type, NORMAL, \
FLAG_HAVE_NON_SOLID_MASK)
#endif //PIXMAN_MIPS_DSPR2_H

View File

@ -1,382 +0,0 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "pixman-mips-dspr2-asm.h"
/*
* This routine could be optimized for MIPS64. The current code only
* uses MIPS32 instructions.
*/
#ifdef EB
# define LWHI lwl /* high part is left in big-endian */
# define SWHI swl /* high part is left in big-endian */
# define LWLO lwr /* low part is right in big-endian */
# define SWLO swr /* low part is right in big-endian */
#else
# define LWHI lwr /* high part is right in little-endian */
# define SWHI swr /* high part is right in little-endian */
# define LWLO lwl /* low part is left in big-endian */
# define SWLO swl /* low part is left in big-endian */
#endif
LEAF_MIPS32R2(pixman_mips_fast_memcpy)
slti AT, a2, 8
bne AT, zero, $last8
move v0, a0 /* memcpy returns the dst pointer */
/* Test if the src and dst are word-aligned, or can be made word-aligned */
xor t8, a1, a0
andi t8, t8, 0x3 /* t8 is a0/a1 word-displacement */
bne t8, zero, $unaligned
negu a3, a0
andi a3, a3, 0x3 /* we need to copy a3 bytes to make a0/a1 aligned */
beq a3, zero, $chk16w /* when a3=0 then the dst (a0) is word-aligned */
subu a2, a2, a3 /* now a2 is the remining bytes count */
LWHI t8, 0(a1)
addu a1, a1, a3
SWHI t8, 0(a0)
addu a0, a0, a3
/* Now the dst/src are mutually word-aligned with word-aligned addresses */
$chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */
/* t8 is the byte count after 64-byte chunks */
beq a2, t8, $chk8w /* if a2==t8, no 64-byte chunks */
/* There will be at most 1 32-byte chunk after it */
subu a3, a2, t8 /* subtract from a2 the reminder */
/* Here a3 counts bytes in 16w chunks */
addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */
addu t0, a0, a2 /* t0 is the "past the end" address */
/*
* When in the loop we exercise "pref 30, x(a0)", the a0+x should not be past
* the "t0-32" address
* This means: for x=128 the last "safe" a0 address is "t0-160"
* Alternatively, for x=64 the last "safe" a0 address is "t0-96"
* In the current version we use "pref 30, 128(a0)", so "t0-160" is the limit
*/
subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */
pref 0, 0(a1) /* bring the first line of src, addr 0 */
pref 0, 32(a1) /* bring the second line of src, addr 32 */
pref 0, 64(a1) /* bring the third line of src, addr 64 */
pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */
/* In case the a0 > t9 don't use "pref 30" at all */
sgtu v1, a0, t9
bgtz v1, $loop16w /* skip "pref 30, 64(a0)" for too short arrays */
nop
/* otherwise, start with using pref30 */
pref 30, 64(a0)
$loop16w:
pref 0, 96(a1)
lw t0, 0(a1)
bgtz v1, $skip_pref30_96 /* skip "pref 30, 96(a0)" */
lw t1, 4(a1)
pref 30, 96(a0) /* continue setting up the dest, addr 96 */
$skip_pref30_96:
lw t2, 8(a1)
lw t3, 12(a1)
lw t4, 16(a1)
lw t5, 20(a1)
lw t6, 24(a1)
lw t7, 28(a1)
pref 0, 128(a1) /* bring the next lines of src, addr 128 */
sw t0, 0(a0)
sw t1, 4(a0)
sw t2, 8(a0)
sw t3, 12(a0)
sw t4, 16(a0)
sw t5, 20(a0)
sw t6, 24(a0)
sw t7, 28(a0)
lw t0, 32(a1)
bgtz v1, $skip_pref30_128 /* skip "pref 30, 128(a0)" */
lw t1, 36(a1)
pref 30, 128(a0) /* continue setting up the dest, addr 128 */
$skip_pref30_128:
lw t2, 40(a1)
lw t3, 44(a1)
lw t4, 48(a1)
lw t5, 52(a1)
lw t6, 56(a1)
lw t7, 60(a1)
pref 0, 160(a1) /* bring the next lines of src, addr 160 */
sw t0, 32(a0)
sw t1, 36(a0)
sw t2, 40(a0)
sw t3, 44(a0)
sw t4, 48(a0)
sw t5, 52(a0)
sw t6, 56(a0)
sw t7, 60(a0)
addiu a0, a0, 64 /* adding 64 to dest */
sgtu v1, a0, t9
bne a0, a3, $loop16w
addiu a1, a1, 64 /* adding 64 to src */
move a2, t8
/* Here we have src and dest word-aligned but less than 64-bytes to go */
$chk8w:
pref 0, 0x0(a1)
andi t8, a2, 0x1f /* is there a 32-byte chunk? */
/* the t8 is the reminder count past 32-bytes */
beq a2, t8, $chk1w /* when a2=t8, no 32-byte chunk */
nop
lw t0, 0(a1)
lw t1, 4(a1)
lw t2, 8(a1)
lw t3, 12(a1)
lw t4, 16(a1)
lw t5, 20(a1)
lw t6, 24(a1)
lw t7, 28(a1)
addiu a1, a1, 32
sw t0, 0(a0)
sw t1, 4(a0)
sw t2, 8(a0)
sw t3, 12(a0)
sw t4, 16(a0)
sw t5, 20(a0)
sw t6, 24(a0)
sw t7, 28(a0)
addiu a0, a0, 32
$chk1w:
andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */
beq a2, t8, $last8
subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */
addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */
/* copying in words (4-byte chunks) */
$wordCopy_loop:
lw t3, 0(a1) /* the first t3 may be equal t0 ... optimize? */
addiu a1, a1, 4
addiu a0, a0, 4
bne a0, a3, $wordCopy_loop
sw t3, -4(a0)
/* For the last (<8) bytes */
$last8:
blez a2, leave
addu a3, a0, a2 /* a3 is the last dst address */
$last8loop:
lb v1, 0(a1)
addiu a1, a1, 1
addiu a0, a0, 1
bne a0, a3, $last8loop
sb v1, -1(a0)
leave: j ra
nop
/*
* UNALIGNED case
*/
$unaligned:
/* got here with a3="negu a0" */
andi a3, a3, 0x3 /* test if the a0 is word aligned */
beqz a3, $ua_chk16w
subu a2, a2, a3 /* bytes left after initial a3 bytes */
LWHI v1, 0(a1)
LWLO v1, 3(a1)
addu a1, a1, a3 /* a3 may be here 1, 2 or 3 */
SWHI v1, 0(a0)
addu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */
$ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */
/* t8 is the byte count after 64-byte chunks */
beq a2, t8, $ua_chk8w /* if a2==t8, no 64-byte chunks */
/* There will be at most 1 32-byte chunk after it */
subu a3, a2, t8 /* subtract from a2 the reminder */
/* Here a3 counts bytes in 16w chunks */
addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */
addu t0, a0, a2 /* t0 is the "past the end" address */
subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */
pref 0, 0(a1) /* bring the first line of src, addr 0 */
pref 0, 32(a1) /* bring the second line of src, addr 32 */
pref 0, 64(a1) /* bring the third line of src, addr 64 */
pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */
/* In case the a0 > t9 don't use "pref 30" at all */
sgtu v1, a0, t9
bgtz v1, $ua_loop16w /* skip "pref 30, 64(a0)" for too short arrays */
nop
/* otherwise, start with using pref30 */
pref 30, 64(a0)
$ua_loop16w:
pref 0, 96(a1)
LWHI t0, 0(a1)
LWLO t0, 3(a1)
LWHI t1, 4(a1)
bgtz v1, $ua_skip_pref30_96
LWLO t1, 7(a1)
pref 30, 96(a0) /* continue setting up the dest, addr 96 */
$ua_skip_pref30_96:
LWHI t2, 8(a1)
LWLO t2, 11(a1)
LWHI t3, 12(a1)
LWLO t3, 15(a1)
LWHI t4, 16(a1)
LWLO t4, 19(a1)
LWHI t5, 20(a1)
LWLO t5, 23(a1)
LWHI t6, 24(a1)
LWLO t6, 27(a1)
LWHI t7, 28(a1)
LWLO t7, 31(a1)
pref 0, 128(a1) /* bring the next lines of src, addr 128 */
sw t0, 0(a0)
sw t1, 4(a0)
sw t2, 8(a0)
sw t3, 12(a0)
sw t4, 16(a0)
sw t5, 20(a0)
sw t6, 24(a0)
sw t7, 28(a0)
LWHI t0, 32(a1)
LWLO t0, 35(a1)
LWHI t1, 36(a1)
bgtz v1, $ua_skip_pref30_128
LWLO t1, 39(a1)
pref 30, 128(a0) /* continue setting up the dest, addr 128 */
$ua_skip_pref30_128:
LWHI t2, 40(a1)
LWLO t2, 43(a1)
LWHI t3, 44(a1)
LWLO t3, 47(a1)
LWHI t4, 48(a1)
LWLO t4, 51(a1)
LWHI t5, 52(a1)
LWLO t5, 55(a1)
LWHI t6, 56(a1)
LWLO t6, 59(a1)
LWHI t7, 60(a1)
LWLO t7, 63(a1)
pref 0, 160(a1) /* bring the next lines of src, addr 160 */
sw t0, 32(a0)
sw t1, 36(a0)
sw t2, 40(a0)
sw t3, 44(a0)
sw t4, 48(a0)
sw t5, 52(a0)
sw t6, 56(a0)
sw t7, 60(a0)
addiu a0, a0, 64 /* adding 64 to dest */
sgtu v1, a0, t9
bne a0, a3, $ua_loop16w
addiu a1, a1, 64 /* adding 64 to src */
move a2, t8
/* Here we have src and dest word-aligned but less than 64-bytes to go */
$ua_chk8w:
pref 0, 0x0(a1)
andi t8, a2, 0x1f /* is there a 32-byte chunk? */
/* the t8 is the reminder count */
beq a2, t8, $ua_chk1w /* when a2=t8, no 32-byte chunk */
LWHI t0, 0(a1)
LWLO t0, 3(a1)
LWHI t1, 4(a1)
LWLO t1, 7(a1)
LWHI t2, 8(a1)
LWLO t2, 11(a1)
LWHI t3, 12(a1)
LWLO t3, 15(a1)
LWHI t4, 16(a1)
LWLO t4, 19(a1)
LWHI t5, 20(a1)
LWLO t5, 23(a1)
LWHI t6, 24(a1)
LWLO t6, 27(a1)
LWHI t7, 28(a1)
LWLO t7, 31(a1)
addiu a1, a1, 32
sw t0, 0(a0)
sw t1, 4(a0)
sw t2, 8(a0)
sw t3, 12(a0)
sw t4, 16(a0)
sw t5, 20(a0)
sw t6, 24(a0)
sw t7, 28(a0)
addiu a0, a0, 32
$ua_chk1w:
andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */
beq a2, t8, $ua_smallCopy
subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */
addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */
/* copying in words (4-byte chunks) */
$ua_wordCopy_loop:
LWHI v1, 0(a1)
LWLO v1, 3(a1)
addiu a1, a1, 4
addiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */
bne a0, a3, $ua_wordCopy_loop
sw v1, -4(a0)
/* Now less than 4 bytes (value in a2) left to copy */
$ua_smallCopy:
beqz a2, leave
addu a3, a0, a2 /* a3 is the last dst address */
$ua_smallCopy_loop:
lb v1, 0(a1)
addiu a1, a1, 1
addiu a0, a0, 1
bne a0, a3, $ua_smallCopy_loop
sb v1, -1(a0)
j ra
nop
END(pixman_mips_fast_memcpy)

View File

@ -1,94 +0,0 @@
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
#if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI)
#include <string.h>
#include <stdlib.h>
static pixman_bool_t
have_feature (const char *search_string)
{
#if defined (__linux__) /* linux ELF */
/* Simple detection of MIPS features at runtime for Linux.
* It is based on /proc/cpuinfo, which reveals hardware configuration
* to user-space applications. According to MIPS (early 2010), no similar
* facility is universally available on the MIPS architectures, so it's up
* to individual OSes to provide such.
*/
const char *file_name = "/proc/cpuinfo";
char cpuinfo_line[256];
FILE *f = NULL;
if ((f = fopen (file_name, "r")) == NULL)
return FALSE;
while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
{
if (strstr (cpuinfo_line, search_string) != NULL)
{
fclose (f);
return TRUE;
}
}
fclose (f);
#endif
/* Did not find string in the proc file, or not Linux ELF. */
return FALSE;
}
#endif
pixman_implementation_t *
_pixman_mips_get_implementations (pixman_implementation_t *imp)
{
#ifdef USE_LOONGSON_MMI
/* I really don't know if some Loongson CPUs don't have MMI. */
if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson"))
imp = _pixman_implementation_create_mmx (imp);
#endif
#ifdef USE_MIPS_DSPR2
if (!_pixman_disabled ("mips-dspr2"))
{
int already_compiling_everything_for_dspr2 = 0;
#if defined(__mips_dsp) && (__mips_dsp_rev >= 2)
already_compiling_everything_for_dspr2 = 1;
#endif
if (already_compiling_everything_for_dspr2 ||
/* Only currently available MIPS core that supports DSPr2 is 74K. */
have_feature ("MIPS 74K"))
{
imp = _pixman_implementation_create_mips_dspr2 (imp);
}
}
#endif
return imp;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,161 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
/*
* Copyright © 2011 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "pixman-private.h"
#include "pixman-combine32.h"
#include "pixman-inlines.h"
static void
noop_composite (pixman_implementation_t *imp,
pixman_composite_info_t *info)
{
return;
}
static uint32_t *
noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
{
uint32_t *result = iter->buffer;
iter->buffer += iter->image->bits.rowstride;
return result;
}
static void
noop_init_solid_narrow (pixman_iter_t *iter,
const pixman_iter_info_t *info)
{
pixman_image_t *image = iter->image;
uint32_t *buffer = iter->buffer;
uint32_t *end = buffer + iter->width;
uint32_t color;
if (iter->image->type == SOLID)
color = image->solid.color_32;
else
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
while (buffer < end)
*(buffer++) = color;
}
static void
noop_init_solid_wide (pixman_iter_t *iter,
const pixman_iter_info_t *info)
{
pixman_image_t *image = iter->image;
argb_t *buffer = (argb_t *)iter->buffer;
argb_t *end = buffer + iter->width;
argb_t color;
if (iter->image->type == SOLID)
color = image->solid.color_float;
else
color = image->bits.fetch_pixel_float (&image->bits, 0, 0);
while (buffer < end)
*(buffer++) = color;
}
static void
noop_init_direct_buffer (pixman_iter_t *iter, const pixman_iter_info_t *info)
{
pixman_image_t *image = iter->image;
iter->buffer =
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
}
static void
dest_write_back_direct (pixman_iter_t *iter)
{
iter->buffer += iter->image->bits.rowstride;
}
static const pixman_iter_info_t noop_iters[] =
{
/* Source iters */
{ PIXMAN_any,
0, ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_SRC,
NULL,
_pixman_iter_get_scanline_noop,
NULL
},
{ PIXMAN_solid,
FAST_PATH_NO_ALPHA_MAP, ITER_NARROW | ITER_SRC,
noop_init_solid_narrow,
_pixman_iter_get_scanline_noop,
NULL,
},
{ PIXMAN_solid,
FAST_PATH_NO_ALPHA_MAP, ITER_WIDE | ITER_SRC,
noop_init_solid_wide,
_pixman_iter_get_scanline_noop,
NULL
},
{ PIXMAN_a8r8g8b8,
FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |
FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST,
ITER_NARROW | ITER_SRC,
noop_init_direct_buffer,
noop_get_scanline,
NULL
},
/* Dest iters */
{ PIXMAN_a8r8g8b8,
FAST_PATH_STD_DEST_FLAGS, ITER_NARROW | ITER_DEST,
noop_init_direct_buffer,
_pixman_iter_get_scanline_noop,
dest_write_back_direct
},
{ PIXMAN_x8r8g8b8,
FAST_PATH_STD_DEST_FLAGS, ITER_NARROW | ITER_DEST | ITER_LOCALIZED_ALPHA,
noop_init_direct_buffer,
_pixman_iter_get_scanline_noop,
dest_write_back_direct
},
{ PIXMAN_null },
};
static const pixman_fast_path_t noop_fast_paths[] =
{
{ PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
{ PIXMAN_OP_NONE },
};
pixman_implementation_t *
_pixman_implementation_create_noop (pixman_implementation_t *fallback)
{
pixman_implementation_t *imp =
_pixman_implementation_create (fallback, noop_fast_paths);
imp->iter_info = noop_iters;
return imp;
}

View File

@ -1,173 +0,0 @@
/*
* Copyright © 2000 SuSE, Inc.
* Copyright © 2007 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include "pixman-private.h"
#ifdef USE_VMX
/* The CPU detection code needs to be in a file not compiled with
* "-maltivec -mabi=altivec", as gcc would try to save vector register
* across function calls causing SIGILL on cpus without Altivec/vmx.
*/
#ifdef __APPLE__
#include <sys/sysctl.h>
static pixman_bool_t
pixman_have_vmx (void)
{
int error, have_vmx;
size_t length = sizeof(have_vmx);
error = sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0);
if (error)
return FALSE;
return have_vmx;
}
#elif defined (__OpenBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
static pixman_bool_t
pixman_have_vmx (void)
{
int error, have_vmx;
int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
size_t length = sizeof(have_vmx);
error = sysctl (mib, 2, &have_vmx, &length, NULL, 0);
if (error != 0)
return FALSE;
return have_vmx;
}
#elif defined (__FreeBSD__)
#include <machine/cpu.h>
#include <sys/auxv.h>
static pixman_bool_t
pixman_have_vmx (void)
{
unsigned long cpufeatures;
int have_vmx;
if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)))
return FALSE;
have_vmx = cpufeatures & PPC_FEATURE_HAS_ALTIVEC;
return have_vmx;
}
#elif defined (__linux__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/auxvec.h>
#include <asm/cputable.h>
static pixman_bool_t
pixman_have_vmx (void)
{
int have_vmx = FALSE;
int fd;
struct
{
unsigned long type;
unsigned long value;
} aux;
fd = open ("/proc/self/auxv", O_RDONLY);
if (fd >= 0)
{
while (read (fd, &aux, sizeof (aux)) == sizeof (aux))
{
if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC))
{
have_vmx = TRUE;
break;
}
}
close (fd);
}
return have_vmx;
}
#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */
#include <signal.h>
#include <setjmp.h>
static jmp_buf jump_env;
static void
vmx_test (int sig,
siginfo_t *si,
void * unused)
{
longjmp (jump_env, 1);
}
static pixman_bool_t
pixman_have_vmx (void)
{
struct sigaction sa, osa;
int jmp_result;
sa.sa_flags = SA_SIGINFO;
sigemptyset (&sa.sa_mask);
sa.sa_sigaction = vmx_test;
sigaction (SIGILL, &sa, &osa);
jmp_result = setjmp (jump_env);
if (jmp_result == 0)
{
asm volatile ( "vor 0, 0, 0" );
}
sigaction (SIGILL, &osa, NULL);
return (jmp_result == 0);
}
#endif /* __APPLE__ */
#endif /* USE_VMX */
pixman_implementation_t *
_pixman_ppc_get_implementations (pixman_implementation_t *imp)
{
#ifdef USE_VMX
if (!_pixman_disabled ("vmx") && pixman_have_vmx ())
imp = _pixman_implementation_create_vmx (imp);
#endif
return imp;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,509 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
/*
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* Copyright © 2000 SuSE, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
* Copyright © 2007 Red Hat, Inc.
*
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif
#include <stdlib.h>
#include <math.h>
#include "pixman-private.h"
static inline pixman_fixed_32_32_t
dot (pixman_fixed_48_16_t x1,
pixman_fixed_48_16_t y1,
pixman_fixed_48_16_t z1,
pixman_fixed_48_16_t x2,
pixman_fixed_48_16_t y2,
pixman_fixed_48_16_t z2)
{
/*
* Exact computation, assuming that the input values can
* be represented as pixman_fixed_16_16_t
*/
return x1 * x2 + y1 * y2 + z1 * z2;
}
static inline double
fdot (double x1,
double y1,
double z1,
double x2,
double y2,
double z2)
{
/*
* Error can be unbound in some special cases.
* Using clever dot product algorithms (for example compensated
* dot product) would improve this but make the code much less
* obvious
*/
return x1 * x2 + y1 * y2 + z1 * z2;
}
static void
radial_write_color (double a,
double b,
double c,
double inva,
double dr,
double mindr,
pixman_gradient_walker_t *walker,
pixman_repeat_t repeat,
int Bpp,
pixman_gradient_walker_write_t write_pixel,
uint32_t *buffer)
{
/*
* In this function error propagation can lead to bad results:
* - discr can have an unbound error (if b*b-a*c is very small),
* potentially making it the opposite sign of what it should have been
* (thus clearing a pixel that would have been colored or vice-versa)
* or propagating the error to sqrtdiscr;
* if discr has the wrong sign or b is very small, this can lead to bad
* results
*
* - the algorithm used to compute the solutions of the quadratic
* equation is not numerically stable (but saves one division compared
* to the numerically stable one);
* this can be a problem if a*c is much smaller than b*b
*
* - the above problems are worse if a is small (as inva becomes bigger)
*/
double discr;
if (a == 0)
{
double t;
if (b == 0)
{
memset (buffer, 0, Bpp);
return;
}
t = pixman_fixed_1 / 2 * c / b;
if (repeat == PIXMAN_REPEAT_NONE)
{
if (0 <= t && t <= pixman_fixed_1)
{
write_pixel (walker, t, buffer);
return;
}
}
else
{
if (t * dr >= mindr)
{
write_pixel (walker, t, buffer);
return;
}
}
memset (buffer, 0, Bpp);
return;
}
discr = fdot (b, a, 0, b, -c, 0);
if (discr >= 0)
{
double sqrtdiscr, t0, t1;
sqrtdiscr = sqrt (discr);
t0 = (b + sqrtdiscr) * inva;
t1 = (b - sqrtdiscr) * inva;
/*
* The root that must be used is the biggest one that belongs
* to the valid range ([0,1] for PIXMAN_REPEAT_NONE, any
* solution that results in a positive radius otherwise).
*
* If a > 0, t0 is the biggest solution, so if it is valid, it
* is the correct result.
*
* If a < 0, only one of the solutions can be valid, so the
* order in which they are tested is not important.
*/
if (repeat == PIXMAN_REPEAT_NONE)
{
if (0 <= t0 && t0 <= pixman_fixed_1)
{
write_pixel (walker, t0, buffer);
return;
}
else if (0 <= t1 && t1 <= pixman_fixed_1)
{
write_pixel (walker, t1, buffer);
return;
}
}
else
{
if (t0 * dr >= mindr)
{
write_pixel (walker, t0, buffer);
return;
}
else if (t1 * dr >= mindr)
{
write_pixel (walker, t1, buffer);
return;
}
}
}
memset (buffer, 0, Bpp);
return;
}
static uint32_t *
radial_get_scanline (pixman_iter_t *iter,
const uint32_t *mask,
int Bpp,
pixman_gradient_walker_write_t write_pixel)
{
/*
* Implementation of radial gradients following the PDF specification.
* See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
* Manual (PDF 32000-1:2008 at the time of this writing).
*
* In the radial gradient problem we are given two circles (c,r) and
* (c,r) that define the gradient itself.
*
* Mathematically the gradient can be defined as the family of circles
*
* ((1-t)·c + t·(c), (1-t)·r + t·r)
*
* excluding those circles whose radius would be < 0. When a point
* belongs to more than one circle, the one with a bigger t is the only
* one that contributes to its color. When a point does not belong
* to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
* Further limitations on the range of values for t are imposed when
* the gradient is not repeated, namely t must belong to [0,1].
*
* The graphical result is the same as drawing the valid (radius > 0)
* circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
* is not repeated) using SOURCE operator composition.
*
* It looks like a cone pointing towards the viewer if the ending circle
* is smaller than the starting one, a cone pointing inside the page if
* the starting circle is the smaller one and like a cylinder if they
* have the same radius.
*
* What we actually do is, given the point whose color we are interested
* in, compute the t values for that point, solving for t in:
*
* length((1-t)·c + t·(c) - p) = (1-t)·r + t·r
*
* Let's rewrite it in a simpler way, by defining some auxiliary
* variables:
*
* cd = c - c
* pd = p - c
* dr = r - r
* length(t·cd - pd) = r + t·dr
*
* which actually means
*
* hypot(t·cdx - pdx, t·cdy - pdy) = r + t·dr
*
* or
*
* ((t·cdx - pdx)² + (t·cdy - pdy)²) = r + t·dr.
*
* If we impose (as stated earlier) that r + t·dr >= 0, it becomes:
*
* (t·cdx - pdx)² + (t·cdy - pdy)² = (r + t·dr)²
*
* where we can actually expand the squares and solve for t:
*
* t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
* = r² + 2·r·t·dr + t²·dr²
*
* (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r·dr)t +
* (pdx² + pdy² - r²) = 0
*
* A = cdx² + cdy² - dr²
* B = pdx·cdx + pdy·cdy + r·dr
* C = pdx² + pdy² - r²
* At² - 2Bt + C = 0
*
* The solutions (unless the equation degenerates because of A = 0) are:
*
* t = (B ± (B² - A·C)) / A
*
* The solution we are going to prefer is the bigger one, unless the
* radius associated to it is negative (or it falls outside the valid t
* range).
*
* Additional observations (useful for optimizations):
* A does not depend on p
*
* A < 0 <=> one of the two circles completely contains the other one
* <=> for every p, the radiuses associated with the two t solutions
* have opposite sign
*/
pixman_image_t *image = iter->image;
int x = iter->x;
int y = iter->y;
int width = iter->width;
uint32_t *buffer = iter->buffer;
gradient_t *gradient = (gradient_t *)image;
radial_gradient_t *radial = (radial_gradient_t *)image;
uint32_t *end = buffer + width * (Bpp / 4);
pixman_gradient_walker_t walker;
pixman_vector_t v, unit;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
if (image->common.transform)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
return iter->buffer;
unit.vector[0] = image->common.transform->matrix[0][0];
unit.vector[1] = image->common.transform->matrix[1][0];
unit.vector[2] = image->common.transform->matrix[2][0];
}
else
{
unit.vector[0] = pixman_fixed_1;
unit.vector[1] = 0;
unit.vector[2] = 0;
}
if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
{
/*
* Given:
*
* t = (B ± (B² - A·C)) / A
*
* where
*
* A = cdx² + cdy² - dr²
* B = pdx·cdx + pdy·cdy + r·dr
* C = pdx² + pdy² - r²
* det = B² - A·C
*
* Since we have an affine transformation, we know that (pdx, pdy)
* increase linearly with each pixel,
*
* pdx = pdx + n·ux,
* pdy = pdy + n·uy,
*
* we can then express B, C and det through multiple differentiation.
*/
pixman_fixed_32_32_t b, db, c, dc, ddc;
/* warning: this computation may overflow */
v.vector[0] -= radial->c1.x;
v.vector[1] -= radial->c1.y;
/*
* B and C are computed and updated exactly.
* If fdot was used instead of dot, in the worst case it would
* lose 11 bits of precision in each of the multiplication and
* summing up would zero out all the bit that were preserved,
* thus making the result 0 instead of the correct one.
* This would mean a worst case of unbound relative error or
* about 2^10 absolute error
*/
b = dot (v.vector[0], v.vector[1], radial->c1.radius,
radial->delta.x, radial->delta.y, radial->delta.radius);
db = dot (unit.vector[0], unit.vector[1], 0,
radial->delta.x, radial->delta.y, 0);
c = dot (v.vector[0], v.vector[1],
-((pixman_fixed_48_16_t) radial->c1.radius),
v.vector[0], v.vector[1], radial->c1.radius);
dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
0,
unit.vector[0], unit.vector[1], 0);
ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
unit.vector[0], unit.vector[1], 0);
while (buffer < end)
{
if (!mask || *mask++)
{
radial_write_color (radial->a, b, c,
radial->inva,
radial->delta.radius,
radial->mindr,
&walker,
image->common.repeat,
Bpp,
write_pixel,
buffer);
}
b += db;
c += dc;
dc += ddc;
buffer += (Bpp / 4);
}
}
else
{
/* projective */
/* Warning:
* error propagation guarantees are much looser than in the affine case
*/
while (buffer < end)
{
if (!mask || *mask++)
{
if (v.vector[2] != 0)
{
double pdx, pdy, invv2, b, c;
invv2 = 1. * pixman_fixed_1 / v.vector[2];
pdx = v.vector[0] * invv2 - radial->c1.x;
/* / pixman_fixed_1 */
pdy = v.vector[1] * invv2 - radial->c1.y;
/* / pixman_fixed_1 */
b = fdot (pdx, pdy, radial->c1.radius,
radial->delta.x, radial->delta.y,
radial->delta.radius);
/* / pixman_fixed_1 / pixman_fixed_1 */
c = fdot (pdx, pdy, -radial->c1.radius,
pdx, pdy, radial->c1.radius);
/* / pixman_fixed_1 / pixman_fixed_1 */
radial_write_color (radial->a, b, c,
radial->inva,
radial->delta.radius,
radial->mindr,
&walker,
image->common.repeat,
Bpp,
write_pixel,
buffer);
}
else
{
memset (buffer, 0, Bpp);
}
}
buffer += (Bpp / 4);
v.vector[0] += unit.vector[0];
v.vector[1] += unit.vector[1];
v.vector[2] += unit.vector[2];
}
}
iter->y++;
return iter->buffer;
}
static uint32_t *
radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
return radial_get_scanline (iter, mask, 4,
_pixman_gradient_walker_write_narrow);
}
static uint32_t *
radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
return radial_get_scanline (iter, NULL, 16,
_pixman_gradient_walker_write_wide);
}
void
_pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
{
if (iter->iter_flags & ITER_NARROW)
iter->get_scanline = radial_get_scanline_narrow;
else
iter->get_scanline = radial_get_scanline_wide;
}
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_radial_gradient (const pixman_point_fixed_t * inner,
const pixman_point_fixed_t * outer,
pixman_fixed_t inner_radius,
pixman_fixed_t outer_radius,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_image_t *image;
radial_gradient_t *radial;
image = _pixman_image_allocate ();
if (!image)
return NULL;
radial = &image->radial;
if (!_pixman_init_gradient (&radial->common, stops, n_stops))
{
free (image);
return NULL;
}
image->type = RADIAL;
radial->c1.x = inner->x;
radial->c1.y = inner->y;
radial->c1.radius = inner_radius;
radial->c2.x = outer->x;
radial->c2.y = outer->y;
radial->c2.radius = outer_radius;
/* warning: this computations may overflow */
radial->delta.x = radial->c2.x - radial->c1.x;
radial->delta.y = radial->c2.y - radial->c1.y;
radial->delta.radius = radial->c2.radius - radial->c1.radius;
/* computed exactly, then cast to double -> every bit of the double
representation is correct (53 bits) */
radial->a = dot (radial->delta.x, radial->delta.y, -radial->delta.radius,
radial->delta.x, radial->delta.y, radial->delta.radius);
if (radial->a != 0)
radial->inva = 1. * pixman_fixed_1 / radial->a;
radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius;
return image;
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More