summaryrefslogtreecommitdiff
path: root/detile/viv-demultitile.c
blob: 1162beff297b641cd9c8674a222383166c5d20d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

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)
{
	unsigned int major_x, minor_x, major_y, minor_y;
	unsigned int tile_size = tile_width * tile_height;
	unsigned int tile_stride = tile_size * blocks_x;
	unsigned int src_p, dst_p;

	for (major_y = 0; major_y < blocks_y; major_y++) {
		for (minor_y = 0; minor_y < tile_height; minor_y++) {
			unsigned int dst_y = major_y * tile_height + minor_y;

			for (major_x = 0; major_x < blocks_x; major_x++) {
				for (minor_x = 0; minor_x < tile_width; minor_x++) {
					unsigned int dst_x = major_x * tile_width + minor_x;
					unsigned int src_maj = major_y * tile_stride + major_x * tile_size;
					unsigned int src_min = minor_y * tile_width + minor_x;

					dst_p = (dst_y * tile_width * blocks_x + dst_x) * unit_size;
					src_p = (src_maj + src_min) * unit_size;
					memcpy(dst + dst_p, src + src_p, unit_size);
				}
			}
		}
	}
}

static void demultitile(void *dst, void *src, unsigned ps, unsigned w, unsigned h)
{
	void *tmp = malloc(ps * w * h);
	void *src_u, *src_l;
	unsigned int tile_bytes;
	unsigned int tile_stride;
	unsigned int tile_w = w / 4;
	unsigned int tile_h = h / 4;
	int x, y;

	/*
	 * u1 u2 l1 l2 u5 u6 l5 l6
	 * l3 l4 u3 u4 l7 l8 u7 u8
	 */

	tile_bytes = ps * 4 * 4; /* each 4x4 tile */
	tile_stride = tile_bytes * tile_w; /* one full row of tiles */

	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);

	for (y = 0; y < tile_h / 2; y++) {
		void *dpyu = tmp + y * 2 * tile_stride;
		void *dpyl = dpyu + tile_stride;
		void *spyu = src_u + y * tile_stride; /* upper half */
		void *spyl = src_l + y * tile_stride; /* lower half */
		for (x = 0; x < tile_w / 4; x++) {
			void *dpu = dpyu + x * 4 * tile_bytes;
			void *dpl = dpyl + x * 4 * tile_bytes;
			void *spu = spyu + x * 4 * tile_bytes;
			void *spl = spyl + x * 4 * tile_bytes;

			memcpy(dpu, spu, 2 * tile_bytes);
			memcpy(dpu + 2 * tile_bytes, spl, 2 * tile_bytes);
			memcpy(dpl, spl + 2 * tile_bytes, 2 * tile_bytes);
			memcpy(dpl + 2 * tile_bytes, spu + 2 * tile_bytes, 2 * tile_bytes);
		}
	}

	detile_gen(dst, tmp, ps, 4, 4, tile_w, tile_h);
	free(tmp);
}

static void detile(void *dst, void *src, unsigned ps, unsigned w, unsigned h)
{
	detile_gen(dst, src, ps, 4, 4, w / 4, h / 4);
}

int main(int argc, char *argv[])
{
	struct stat st;
	void *ptr, *out;

	if (fstat(0, &st) == -1) {
		perror("failed to stat");
		return 1;
	}

	ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, 0, 0);
	if (ptr == (void *)-1) {
		perror("failed to mmap");
		return 1;
	}

	out = malloc(st.st_size);

	demultitile(out, ptr, 4, 256, 256);

	write(1, out, st.st_size);
	return 0;
}