src/platform/sdl/pandora-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
10#include <linux/omapfb.h>
11#include <linux/fb.h>
12#include <sys/ioctl.h>
13#include <sys/mman.h>
14
15bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
16 SDL_SetVideoMode(800, 480, 16, SDL_FULLSCREEN);
17
18 renderer->odd = 0;
19 renderer->fb = open("/dev/fb1", O_RDWR);
20 if (renderer->fb < 0) {
21 return false;
22 }
23
24 struct omapfb_plane_info plane;
25 struct omapfb_mem_info mem;
26 if (ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane) < 0) {
27 return false;
28 }
29 if (ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem) < 0) {
30 return false;
31 }
32
33 if (plane.enabled) {
34 plane.enabled = 0;
35 ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
36 }
37
38 mem.size = VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4;
39 ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem);
40
41 plane.enabled = 1;
42 plane.pos_x = 40;
43 plane.pos_y = 0;
44 plane.out_width = 720;
45 plane.out_height = 480;
46 ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
47
48 struct fb_var_screeninfo info;
49 ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info);
50 info.xres = VIDEO_HORIZONTAL_PIXELS;
51 info.yres = VIDEO_VERTICAL_PIXELS;
52 info.xres_virtual = VIDEO_HORIZONTAL_PIXELS;
53 info.yres_virtual = VIDEO_VERTICAL_PIXELS * 2;
54 info.bits_per_pixel = 16;
55 ioctl(renderer->fb, FBIOPUT_VSCREENINFO, &info);
56
57 renderer->odd = 0;
58 renderer->base[0] = mmap(0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4, PROT_READ | PROT_WRITE, MAP_SHARED, renderer->fb, 0);
59 renderer->base[1] = (uint16_t*) renderer->base[0] + VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS;
60
61 renderer->d.outputBuffer = renderer->base[0];
62 renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
63 return true;
64}
65
66void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
67 SDL_Event event;
68
69 while (context->state < THREAD_EXITING) {
70 while (SDL_PollEvent(&event)) {
71 GBASDLHandleEvent(context, &renderer->player, &event);
72 }
73
74 if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
75 int arg = 0;
76 ioctl(renderer->fb, FBIO_WAITFORVSYNC, &arg);
77
78 struct fb_var_screeninfo info;
79 ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info);
80 info.yoffset = VIDEO_VERTICAL_PIXELS * renderer->odd;
81 ioctl(renderer->fb, FBIOPAN_DISPLAY, &info);
82
83 renderer->odd = !renderer->odd;
84 renderer->d.outputBuffer = renderer->base[renderer->odd];
85 }
86 GBASyncWaitFrameEnd(&context->sync);
87 }
88}
89
90void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
91 munmap(renderer->base[0], VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4);
92
93 struct omapfb_plane_info plane;
94 struct omapfb_mem_info mem;
95 ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane);
96 ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem);
97
98 mem.size = 0;
99 ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem);
100
101 plane.enabled = 0;
102 plane.pos_x = 0;
103 plane.pos_y = 0;
104 plane.out_width = 0;
105 plane.out_height = 0;
106 ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
107
108 close(renderer->fb);
109}