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