src/platform/sdl/sw-sdl.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "main.h"
7
8#include "gba/supervisor/thread.h"
9#include "util/arm-algo.h"
10
11bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
12#if !SDL_VERSION_ATLEAST(2, 0, 0)
13#ifdef COLOR_16_BIT
14 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
15#else
16 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
17#endif
18#endif
19
20#if SDL_VERSION_ATLEAST(2, 0, 0)
21 renderer->window = SDL_CreateWindow(PROJECT_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen));
22 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
23 renderer->player.window = renderer->window;
24 renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
25#ifdef COLOR_16_BIT
26#ifdef COLOR_5_6_5
27 renderer->tex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
28#else
29 renderer->tex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR1555, SDL_TEXTUREACCESS_STREAMING, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
30#endif
31#else
32 renderer->tex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
33#endif
34
35 SDL_LockTexture(renderer->tex, 0, (void**) &renderer->d.outputBuffer, &renderer->d.outputBufferStride);
36 renderer->d.outputBufferStride /= BYTES_PER_PIXEL;
37#else
38 SDL_Surface* surface = SDL_GetVideoSurface();
39 SDL_LockSurface(surface);
40
41 if (renderer->ratio == 1) {
42 renderer->d.outputBuffer = surface->pixels;
43 renderer->d.outputBufferStride = surface->pitch / BYTES_PER_PIXEL;
44 } else {
45#ifdef USE_PIXMAN
46 renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
47 renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
48#ifdef COLOR_16_BIT
49#ifdef COLOR_5_6_5
50 pixman_format_code_t format = PIXMAN_r5g6b5;
51#else
52 pixman_format_code_t format = PIXMAN_x1b5g5r5;
53#endif
54#else
55 pixman_format_code_t format = PIXMAN_x8b8g8r8;
56#endif
57 renderer->pix = pixman_image_create_bits(format, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS,
58 renderer->d.outputBuffer, renderer->d.outputBufferStride * BYTES_PER_PIXEL);
59 renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
60
61 pixman_transform_t transform;
62 pixman_transform_init_identity(&transform);
63 pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
64 pixman_image_set_transform(renderer->pix, &transform);
65 pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
66#else
67 return false;
68#endif
69 }
70#endif
71
72 return true;
73}
74
75void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
76 SDL_Event event;
77#if !SDL_VERSION_ATLEAST(2, 0, 0)
78 SDL_Surface* surface = SDL_GetVideoSurface();
79#endif
80
81 while (context->state < THREAD_EXITING) {
82 while (SDL_PollEvent(&event)) {
83 GBASDLHandleEvent(context, &renderer->player, &event);
84 }
85
86 if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
87#if SDL_VERSION_ATLEAST(2, 0, 0)
88 SDL_UnlockTexture(renderer->tex);
89 SDL_RenderCopy(renderer->sdlRenderer, renderer->tex, 0, 0);
90 SDL_RenderPresent(renderer->sdlRenderer);
91 SDL_LockTexture(renderer->tex, 0, (void**) &renderer->d.outputBuffer, &renderer->d.outputBufferStride);
92 renderer->d.outputBufferStride /= BYTES_PER_PIXEL;
93#else
94#ifdef USE_PIXMAN
95 if (renderer->ratio > 1) {
96 pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
97 0, 0, 0, 0, 0, 0,
98 renderer->viewportWidth, renderer->viewportHeight);
99 }
100#else
101 switch (renderer->ratio) {
102#if defined(__ARM_NEON) && COLOR_16_BIT
103 case 2:
104 _neon2x(surface->pixels, renderer->d.outputBuffer, 240, 160);
105 break;
106 case 4:
107 _neon4x(surface->pixels, renderer->d.outputBuffer, 240, 160);
108 break;
109#endif
110 case 1:
111 break;
112 default:
113 abort();
114 }
115#endif
116 SDL_UnlockSurface(surface);
117 SDL_Flip(surface);
118 SDL_LockSurface(surface);
119#endif
120 }
121 GBASyncWaitFrameEnd(&context->sync);
122 }
123}
124
125void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
126 if (renderer->ratio > 1) {
127 free(renderer->d.outputBuffer);
128 }
129#if !SDL_VERSION_ATLEAST(2, 0, 0)
130 SDL_Surface* surface = SDL_GetVideoSurface();
131 SDL_UnlockSurface(surface);
132#ifdef USE_PIXMAN
133 pixman_image_unref(renderer->pix);
134 pixman_image_unref(renderer->screenpix);
135#endif
136#endif
137}