summaryrefslogtreecommitdiff
path: root/detile/viv-demultitile.c
diff options
context:
space:
mode:
Diffstat (limited to 'detile/viv-demultitile.c')
-rw-r--r--detile/viv-demultitile.c162
1 files changed, 148 insertions, 14 deletions
diff --git a/detile/viv-demultitile.c b/detile/viv-demultitile.c
index 1162bef..5968cae 100644
--- a/detile/viv-demultitile.c
+++ b/detile/viv-demultitile.c
@@ -1,10 +1,62 @@
+#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
+static int safe_write(int fd, void *buf, size_t size)
+{
+ size_t written = 0;
+ ssize_t ret = 0;
+
+ while (size) {
+ ret = write(fd, buf, size);
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ } else if (ret > 0) {
+ written += ret;
+ buf += ret;
+ size -= ret;
+ } else if (written) {
+ ret = written;
+ break;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int safe_read(int fd, void *buf, size_t size)
+{
+ size_t rd = 0;
+ ssize_t ret = 0;
+
+ while (size) {
+ ret = read(fd, buf, size);
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ } else if (ret > 0) {
+ rd += ret;
+ buf += ret;
+ size -= ret;
+ } else if (rd) {
+ ret = rd;
+ break;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
static void detile_gen(void *dst, void *src, unsigned int unit_size,
unsigned int tile_width, unsigned int tile_height,
unsigned int blocks_x, unsigned int blocks_y)
@@ -44,8 +96,9 @@ static void demultitile(void *dst, void *src, unsigned ps, unsigned w, unsigned
int x, y;
/*
- * u1 u2 l1 l2 u5 u6 l5 l6
- * l3 l4 u3 u4 l7 l8 u7 u8
+ * 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64
+ * u1 u2 l1 l2 u5 u6 l5 l6 u9 u10 l9 l10 u13 u14 l13 l14
+ * l3 l4 u3 u4 l7 l8 u7 u8 l11 l12 u11 u12 l15 l16 u15 u16
*/
tile_bytes = ps * 4 * 4; /* each 4x4 tile */
@@ -54,9 +107,11 @@ static void demultitile(void *dst, void *src, unsigned ps, unsigned w, unsigned
src_u = src;
src_l = src + tile_stride * tile_h / 2;
- fprintf(stderr, "tile bytes = 0x%x\n", tile_bytes);
- fprintf(stderr, "tile stride = 0x%x\n", tile_stride);
- fprintf(stderr, "u -> l = 0x%x\n", src_l - src_u);
+ if (0) {
+ fprintf(stderr, "tile bytes = 0x%x\n", tile_bytes);
+ fprintf(stderr, "tile stride = 0x%x\n", tile_stride);
+ fprintf(stderr, "u -> l = 0x%x\n", src_l - src_u);
+ }
for (y = 0; y < tile_h / 2; y++) {
void *dpyu = tmp + y * 2 * tile_stride;
@@ -89,22 +144,101 @@ int main(int argc, char *argv[])
{
struct stat st;
void *ptr, *out;
+ int fd = 0;
+ int opt, ret, cpp = 4, width = 0, height = -1, multitile = 0;
+ size_t size;
+
+ while ((opt = getopt(argc, argv, "w:h:m")) != -1) {
+ switch (opt) {
+ case 'w':
+ width = strtoul(optarg, NULL, 10);
+ break;
+ case 'h':
+ height = strtoul(optarg, NULL, 10);
+ break;
+ case 'm':
+ multitile = 1;
+ break;
+ default:
+ fprintf(stderr, "Usage: %s [-w WIDTH] [-h HEIGHT] [FILE]\n",
+ argv[0]);
+ return 1;
+ }
+ }
- if (fstat(0, &st) == -1) {
- perror("failed to stat");
- return 1;
+ if (optind < argc) {
+ fd = open(argv[optind], O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "%s: %s: %m\n", argv[0], argv[optind]);
+ return 1;
+ }
+ } else {
+ fd = dup(0);
}
- ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, 0, 0);
- if (ptr == (void *)-1) {
- perror("failed to mmap");
+ if (fstat(fd, &st) == -1) {
+ fprintf(stderr, "%s: failed to stat: %m\n", argv[0]);
+ close(fd);
return 1;
}
- out = malloc(st.st_size);
+ if (height == -1)
+ height = st.st_size / (width * cpp);
+
+ size = cpp * width * height;
+ if (st.st_size) {
+ if (size > st.st_size) {
+ fprintf(stderr, "%s: width/height exceeds file size\n",
+ argv[0]);
+ close(fd);
+ return 1;
+ }
+
+ ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (ptr == (void *)-1) {
+ fprintf(stderr, "%s: failed to mmap: %m", argv[0]);
+ close(fd);
+ return 1;
+ }
+ } else {
+ ptr = malloc(size);
+ if (!ptr) {
+ fprintf(stderr, "%s: out of memory\n", argv[0]);
+ close(fd);
+ return 1;
+ }
+ ret = safe_read(fd, ptr, size);
+ if (ret < 0) {
+ fprintf(stderr, "%s: %m\n", argv[0]);
+ free(ptr);
+ close(fd);
+ return 1;
+ } else if (ret != size) {
+ fprintf(stderr, "%s: short read\n", argv[0]);
+ free(ptr);
+ close(fd);
+ return 1;
+ }
+ }
+
+ out = malloc(size);
+
+ if (multitile)
+ demultitile(out, ptr, cpp, width, height);
+ else
+ detile(out, ptr, cpp, width, height);
+
+ ret = safe_write(1, out, size);
- demultitile(out, ptr, 4, 256, 256);
+ free(out);
+
+ if (ret < 0) {
+ fprintf(stderr, "%s: write: %m\n", argv[0]);
+ return 1;
+ } else if (ret != size) {
+ fprintf(stderr, "%s: short write\n", argv[0]);
+ return 1;
+ }
- write(1, out, st.st_size);
return 0;
}