all repos — mgba @ 92849dee1a9704a34f75b6cf0de0bb0443b5dfc2

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
 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}