aboutsummaryrefslogblamecommitdiffstats
path: root/libglitter_split_uint64_raster.c
blob: bdcd42731d005d539e44006f8cc96ffd097f9a33 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

                                                         
            







                                                                                         
                              












                                                      
                                                                                     





                                                                           







                                                 








                                                                       






















































































                                                                         
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifndef TEST


void
libglitter_split_uint64_raster(uint16_t *rasters[3], uint16_t **alphap, uint64_t *raster,
                               uint64_t red, uint64_t green, uint64_t blue)
{
	uint64_t alpha, map;
	size_t position;
	unsigned char channel;

	alpha = ~(red | green | blue);
	red   /= 0xFF;
	green /= 0xFF;
	blue  /= 0xFF;
	alpha /= 0xFF;
	red   *= 0;
	green *= 1;
	blue  *= 2;
	alpha *= 3;
	map = red | green | blue | alpha;

	for (position = 0; position < 4; position++) {
		channel = ((const unsigned char *)&map)[position * sizeof(uint16_t)];
		if (channel < 3)
			rasters[channel] = &((uint16_t *)raster)[position];
		else if (alphap)
			*alphap = &((uint16_t *)raster)[position];
	}
}


#else


static void
check(int with_alpha, int r, int g, int b, int a)
{
	int red_shift    = r * (int)sizeof(uint16_t) * 8;
	int green_shift  = g * (int)sizeof(uint16_t) * 8;
	int blue_shift   = b * (int)sizeof(uint16_t) * 8;
	int alpha_shift  = a * (int)sizeof(uint16_t) * 8;
	uint16_t full  = (uint16_t)~0U;
	uint16_t red   = (uint16_t)~0U / (uint16_t)0xF * (uint16_t)0x5;
	uint16_t green = (uint16_t)~0U / (uint16_t)0xF * (uint16_t)0x8;
	uint16_t blue  = (uint16_t)~0U / (uint16_t)0xF * (uint16_t)0xA;
	uint16_t alpha = (uint16_t)~0U / (uint16_t)0xF * (uint16_t)0x9;
	uint64_t red_mask   = (uint64_t)red   << red_shift;
	uint64_t green_mask = (uint64_t)green << green_shift;
	uint64_t blue_mask  = (uint64_t)blue  << blue_shift;
	uint64_t alpha_mask = (uint64_t)alpha << alpha_shift;
	uint64_t raster = red_mask | green_mask | blue_mask | alpha_mask;
	uint16_t *rasters[4] = {NULL, NULL, NULL, NULL};

	ASSERT(r != g && r != b && r != a);
	ASSERT(g != b && g != a);
	ASSERT(b != a);

	libglitter_split_uint64_raster(rasters,
	                               with_alpha ? &rasters[3] : NULL,
	                               &raster,
	                               (uint64_t)full << red_shift,
	                               (uint64_t)full << green_shift,
	                               (uint64_t)full << blue_shift);
	ASSERT(rasters[0]);
	ASSERT(rasters[1]);
	ASSERT(rasters[2]);
	ASSERT(*rasters[0] == red);
	ASSERT(*rasters[1] == green);
	ASSERT(*rasters[2] == blue);
	if (with_alpha) {
		ASSERT(rasters[3]);
		ASSERT(*rasters[3] == alpha);
	} else {
		ASSERT(!rasters[3]);
	}
}

int
main(void)
{
	check(0, 0, 1, 2, 3);
	check(0, 0, 1, 3, 2);
	check(0, 0, 2, 1, 3);
	check(0, 0, 2, 3, 1);
	check(0, 0, 3, 1, 2);
	check(0, 0, 3, 2, 1);
	check(0, 1, 0, 2, 3);
	check(0, 1, 0, 3, 2);
	check(0, 1, 2, 0, 3);
	check(0, 1, 2, 3, 0);
	check(0, 1, 3, 0, 2);
	check(0, 1, 3, 2, 0);
	check(0, 2, 0, 1, 3);
	check(0, 2, 0, 3, 1);
	check(0, 2, 1, 0, 3);
	check(0, 2, 1, 3, 0);
	check(0, 2, 3, 0, 1);
	check(0, 2, 3, 1, 0);
	check(0, 3, 0, 1, 2);
	check(0, 3, 0, 2, 1);
	check(0, 3, 1, 0, 2);
	check(0, 3, 1, 2, 0);
	check(0, 3, 2, 0, 1);
	check(0, 3, 2, 1, 0);
	check(1, 0, 1, 2, 3);
	check(1, 0, 1, 3, 2);
	check(1, 0, 2, 1, 3);
	check(1, 0, 2, 3, 1);
	check(1, 0, 3, 1, 2);
	check(1, 0, 3, 2, 1);
	check(1, 1, 0, 2, 3);
	check(1, 1, 0, 3, 2);
	check(1, 1, 2, 0, 3);
	check(1, 1, 2, 3, 0);
	check(1, 1, 3, 0, 2);
	check(1, 1, 3, 2, 0);
	check(1, 2, 0, 1, 3);
	check(1, 2, 0, 3, 1);
	check(1, 2, 1, 0, 3);
	check(1, 2, 1, 3, 0);
	check(1, 2, 3, 0, 1);
	check(1, 2, 3, 1, 0);
	check(1, 3, 0, 1, 2);
	check(1, 3, 0, 2, 1);
	check(1, 3, 1, 0, 2);
	check(1, 3, 1, 2, 0);
	check(1, 3, 2, 0, 1);
	check(1, 3, 2, 1, 0);
	return 0;
}


#endif