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