aboutsummaryrefslogtreecommitdiff
path: root/video.c
blob: 99ac2a6d84f63992c4fa966bc1739afa11a956e0 (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
#include "video.h"
#include "main.h"
#include "plat.h"

static struct {
	unsigned max_width;
	unsigned max_height;
	enum retro_pixel_format pixel_format;
	uint16_t *buffer;
} screen_def;

static void video_alloc_convert_buffer(
	unsigned new_width,
	unsigned new_height,
	enum retro_pixel_format new_format
) {
	if (new_width == screen_def.max_width &&
	    new_height == screen_def.max_height &&
	    new_format == screen_def.pixel_format)
		return;

	if (screen_def.buffer) {
		free(screen_def.buffer);
		screen_def.buffer = NULL;
	}

	if ((new_width > 0 || new_height > 0) && new_format == RETRO_PIXEL_FORMAT_XRGB8888) {
		screen_def.buffer = malloc(new_width * new_height * sizeof(uint16_t));
		if (!screen_def.buffer)
			PA_FATAL("Can't allocate buffer for color format conversion\n");
	}
}

void video_set_geometry(struct retro_game_geometry *geometry) {
	video_alloc_convert_buffer(geometry->max_width,
	                           geometry->max_height,
	                           screen_def.pixel_format);

	screen_def.max_width = geometry->max_width;
	screen_def.max_height = geometry->max_height;
}

void video_set_pixel_format(enum retro_pixel_format format) {
	video_alloc_convert_buffer(screen_def.max_width,
	                           screen_def.max_height,
	                           format);

	screen_def.pixel_format = format;
}

void video_process(const void *data, unsigned width, unsigned height, size_t pitch) {
	const uint32_t *input = data;
	uint16_t *output = screen_def.buffer;
	size_t extra = pitch / sizeof(uint32_t) - width;

	if (screen_def.pixel_format != RETRO_PIXEL_FORMAT_XRGB8888)
		return plat_video_process(data, width, height, pitch);

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			*output =  (*input & 0xF80000) >> 8;
			*output |= (*input & 0xFC00) >> 5;
			*output |= (*input & 0xF8) >> 3;
			input++;
			output++;
		}

		input += extra;
	}

	plat_video_process(screen_def.buffer, width, height, width * sizeof(uint16_t));
}

void video_deinit(void) {
	free(screen_def.buffer);
	screen_def.buffer = NULL;
}