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 "core/thread.h"
9#include "core/version.h"
10#include "util/arm-algo.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#if !SDL_VERSION_ATLEAST(2, 0, 0)
24#ifdef COLOR_16_BIT
25 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
26#else
27 SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
28#endif
29#endif
30
31 unsigned width, height;
32 renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
33#if SDL_VERSION_ATLEAST(2, 0, 0)
34 renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen));
35 SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
36 renderer->player.window = renderer->window;
37 renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
38#ifdef COLOR_16_BIT
39#ifdef COLOR_5_6_5
40 renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
41#else
42 renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR1555, SDL_TEXTUREACCESS_STREAMING, width, height);
43#endif
44#else
45 renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height);
46#endif
47
48 int stride;
49 SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride);
50 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL);
51#else
52 SDL_Surface* surface = SDL_GetVideoSurface();
53 SDL_LockSurface(surface);
54
55 if (renderer->ratio == 1) {
56 renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
57 } else {
58#ifdef USE_PIXMAN
59 renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
60 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
61#ifdef COLOR_16_BIT
62#ifdef COLOR_5_6_5
63 pixman_format_code_t format = PIXMAN_r5g6b5;
64#else
65 pixman_format_code_t format = PIXMAN_x1b5g5r5;
66#endif
67#else
68 pixman_format_code_t format = PIXMAN_x8b8g8r8;
69#endif
70 renderer->pix = pixman_image_create_bits(format, width, height,
71 renderer->outputBuffer, width * BYTES_PER_PIXEL);
72 renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);
73
74 pixman_transform_t transform;
75 pixman_transform_init_identity(&transform);
76 pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
77 pixman_image_set_transform(renderer->pix, &transform);
78 pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
79#else
80 return false;
81#endif
82 }
83#endif
84
85 return true;
86}
87
88void mSDLSWRunloop(struct mSDLRenderer* renderer, void* user) {
89 struct mCoreThread* context = user;
90 SDL_Event event;
91#if !SDL_VERSION_ATLEAST(2, 0, 0)
92 SDL_Surface* surface = SDL_GetVideoSurface();
93#endif
94
95 while (context->state < THREAD_EXITING) {
96 while (SDL_PollEvent(&event)) {
97 mSDLHandleEvent(context, &renderer->player, &event);
98 }
99
100 if (mCoreSyncWaitFrameStart(&context->sync)) {
101#if SDL_VERSION_ATLEAST(2, 0, 0)
102 SDL_UnlockTexture(renderer->sdlTex);
103 SDL_RenderCopy(renderer->sdlRenderer, renderer->sdlTex, 0, 0);
104 SDL_RenderPresent(renderer->sdlRenderer);
105 int stride;
106 SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride);
107 renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL);
108#else
109#ifdef USE_PIXMAN
110 if (renderer->ratio > 1) {
111 pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix,
112 0, 0, 0, 0, 0, 0,
113 renderer->viewportWidth, renderer->viewportHeight);
114 }
115#else
116 switch (renderer->ratio) {
117#if defined(__ARM_NEON) && COLOR_16_BIT
118 case 2:
119 _neon2x(surface->pixels, renderer->outputBuffer, width, height);
120 break;
121 case 4:
122 _neon4x(surface->pixels, renderer->outputBuffer, width, height);
123 break;
124#endif
125 case 1:
126 break;
127 default:
128 abort();
129 }
130#endif
131 SDL_UnlockSurface(surface);
132 SDL_Flip(surface);
133 SDL_LockSurface(surface);
134#endif
135 }
136 mCoreSyncWaitFrameEnd(&context->sync);
137 }
138}
139
140void mSDLSWDeinit(struct mSDLRenderer* renderer) {
141 if (renderer->ratio > 1) {
142 free(renderer->outputBuffer);
143 }
144#if !SDL_VERSION_ATLEAST(2, 0, 0)
145 SDL_Surface* surface = SDL_GetVideoSurface();
146 SDL_UnlockSurface(surface);
147#ifdef USE_PIXMAN
148 pixman_image_unref(renderer->pix);
149 pixman_image_unref(renderer->screenpix);
150#endif
151#endif
152}