all repos — mgba @ 6ec99ce4e478878130b7a9449253a88c42ae00be

mGBA Game Boy Advance Emulator

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