aboutsummaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
authorneonloop2023-01-28 17:36:08 +0000
committerneonloop2023-01-28 17:36:08 +0000
commitacf64246dfbcb2cd9bd1e4c65fc11c409f892863 (patch)
tree074b18261d893e8fbe161ba88138e62637fb65df /video.c
parentb54c30613e5a4ade90aa81e832c90f9ab5307cb7 (diff)
downloadpicoarch-acf64246dfbcb2cd9bd1e4c65fc11c409f892863.tar.gz
picoarch-acf64246dfbcb2cd9bd1e4c65fc11c409f892863.tar.bz2
picoarch-acf64246dfbcb2cd9bd1e4c65fc11c409f892863.zip
Adds XRGB8888 core support
Simple version, conversion can still be optimized
Diffstat (limited to 'video.c')
-rw-r--r--video.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/video.c b/video.c
new file mode 100644
index 0000000..99ac2a6
--- /dev/null
+++ b/video.c
@@ -0,0 +1,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;
+}
+