src/platform/sdl/sw-sdl1.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 <mgba/core/core.h>
9#include <mgba/core/thread.h>
10#include <mgba/core/version.h>
11#include <mgba-util/arm-algo.h>
12
13static bool mSDLSWInit(struct mSDLRenderer* renderer);
14static void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user);
15static void mSDLSWDeinit(struct mSDLRenderer* renderer);
16
17void mSDLSWCreate(struct mSDLRenderer* renderer) {
18 renderer->init = mSDLSWInit;
19 renderer->deinit = mSDLSWDeinit;
20 renderer->runloop = mSDLSWRunloop;
21}
22
23bool mSDLSWInit(struct mSDLRenderer* renderer) {
24#ifdef COLOR_16_BIT
25 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
26#else
27 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->player.fullscreen));
28#endif
29 SDL_WM_SetCaption(projectName, "");
30
31 unsigned width, height;
32 renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
33 SDL_Surface* surface = SDL_GetVideoSurface();
34 SDL_LockSurface(surface);
35
36 if (renderer->ratio == 1) {
37 renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
38 } else {
39#ifdef USE_PIXMAN
40 renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
41 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
42#ifdef COLOR_16_BIT
43#ifdef COLOR_5_6_5
44 pixman_format_code_t format = PIXMAN_r5g6b5;
45#else
46 pixman_format_code_t format = PIXMAN_x1b5g5r5;
47#endif
48#else
49 pixman_format_code_t format = PIXMAN_x8b8g8r8;
50#endif
51 renderer->pix = pixman_image_create_bits(format, width, height,
52 renderer->outputBuffer, width * BYTES_PER_PIXEL);
53 renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
54
55 pixman_transform_t transform;
56 pixman_transform_init_identity(&transform);
57 pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
58 pixman_image_set_transform(renderer->pix, &transform);
59 pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
60#else
61 return false;
62#endif
63 }
64
65 return true;
66}
67
68void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user) {
69 struct mCoreThread* context = user;
70 SDL_Event event;
71 SDL_Surface* surface = SDL_GetVideoSurface();
72
73 while (mCoreThreadIsActive(context)) {
74 while (SDL_PollEvent(&event)) {
75 mSDLHandleEvent(context, &renderer->player, &event);
76 }
77
78 if (mCoreSyncWaitFrameStart(&context->impl->sync)) {
79#ifdef USE_PIXMAN
80 if (renderer->ratio > 1) {
81 pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
82 0, 0, 0, 0, 0, 0,
83 renderer->viewportWidth, renderer->viewportHeight);
84 }
85#else
86 switch (renderer->ratio) {
87#if defined(__ARM_NEON) && COLOR_16_BIT
88 case 2:
89 _neon2x(surface->pixels, renderer->outputBuffer, width, height);
90 break;
91 case 4:
92 _neon4x(surface->pixels, renderer->outputBuffer, width, height);
93 break;
94#endif
95 case 1:
96 break;
97 default:
98 abort();
99 }
100#endif
101 SDL_UnlockSurface(surface);
102 SDL_Flip(surface);
103 SDL_LockSurface(surface);
104 }
105 mCoreSyncWaitFrameEnd(&context->impl->sync);
106 }
107}
108
109void mSDLSWDeinit(struct mSDLRenderer* renderer) {
110 if (renderer->ratio > 1) {
111 free(renderer->outputBuffer);
112#ifdef USE_PIXMAN
113 pixman_image_unref(renderer->pix);
114 pixman_image_unref(renderer->screenpix);
115#endif
116 }
117 SDL_Surface* surface = SDL_GetVideoSurface();
118 SDL_UnlockSurface(surface);
119}