Files
libretro-atari800/atari800/src/atari_rpi.c
T
2015-12-14 14:00:35 +01:00

210 lines
5.7 KiB
C

/*
* atari_rpi.c - Raspberry Pi support by djdron
*
* Copyright (c) 2013 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* This file is based on Portable ZX-Spectrum emulator.
* Copyright (C) 2001-2012 SMT, Dexus, Alone Coder, deathsoft, djdron, scor
*
* Atari800 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <bcm_host.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <SDL.h>
#include <assert.h>
#include "config.h"
#include "atari.h"
#include "atari_ntsc/atari_ntsc.h"
#include "util.h"
void gles2_create();
void gles2_destroy();
void gles2_draw(int width, int height);
void gles2_palette_changed();
static uint32_t screen_width = 0;
static uint32_t screen_height = 0;
static EGLDisplay display = NULL;
static EGLSurface surface = NULL;
static EGLContext context = NULL;
static EGL_DISPMANX_WINDOW_T nativewindow;
static SDL_Surface* screen = NULL;
extern int op_filtering;
extern float op_zoom;
int SDL_VIDEO_ReadConfig(char *option, char *parameters)
{
if(strcmp(option, "VIDEO_FILTERING") == 0)
{
int v = Util_sscanbool(parameters);
if(v >= 0)
{
op_filtering = v;
return TRUE;
}
}
else if(strcmp(option, "VIDEO_ZOOM") == 0)
{
double z = 1.0f;
if(Util_sscandouble(parameters, &z))
{
op_zoom = z;
return TRUE;
}
}
return FALSE;
}
void SDL_VIDEO_WriteConfig(FILE *fp)
{
fprintf(fp, "VIDEO_FILTERING=%d\n", op_filtering);
fprintf(fp, "VIDEO_ZOOM=%.2f\n", op_zoom);
}
// some dummies (unresolved externals from sdl/video.c, sdl/input.c)
int VIDEOMODE_Update() { return TRUE; }
int VIDEOMODE_SetWindowSize(unsigned int width, unsigned int height) { return TRUE; }
int VIDEOMODE_ToggleWindowed() { return TRUE; }
int VIDEOMODE_ToggleHorizontalArea() { return TRUE; }
int VIDEOMODE_Toggle80Column() { return TRUE; }
void SDL_VIDEO_SetScanlinesPercentage(int value) {}
int SDL_VIDEO_scanlines_percentage = 5;
int SDL_VIDEO_width = 1;
int SDL_VIDEO_height = 1;
atari_ntsc_t *FILTER_NTSC_emu = NULL;
atari_ntsc_setup_t FILTER_NTSC_setup;
void FILTER_NTSC_Update(atari_ntsc_t *filter) {}
void FILTER_NTSC_NextPreset() {}
void PLATFORM_PaletteUpdate() { gles2_palette_changed(); }
void SDL_VIDEO_InitSDL();
int SDL_VIDEO_Initialise(int *argc, char *argv[])
{
bcm_host_init();
SDL_VIDEO_InitSDL();
return 1;
}
void SDL_VIDEO_InitSDL()
{
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_WM_SetCaption(Atari800_TITLE, "Atari800");
SDL_EnableUNICODE(1);
SDL_ShowCursor(SDL_DISABLE); /* hide mouse cursor */
screen = SDL_SetVideoMode(0,0, 32, SDL_SWSURFACE); // hack to make keyboard events work
// get an EGL display connection
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(display != EGL_NO_DISPLAY);
// initialize the EGL display connection
EGLBoolean result = eglInitialize(display, NULL, NULL);
assert(EGL_FALSE != result);
// get an appropriate EGL frame buffer configuration
EGLint num_config;
EGLConfig config;
static const EGLint attribute_list[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
assert(EGL_FALSE != result);
result = eglBindAPI(EGL_OPENGL_ES_API);
assert(EGL_FALSE != result);
// create an EGL rendering context
static const EGLint context_attributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
assert(context != EGL_NO_CONTEXT);
// create an EGL window surface
int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
assert(success >= 0);
VC_RECT_T dst_rect;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = screen_width;
dst_rect.height = screen_height;
VC_RECT_T src_rect;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = screen_width << 16;
src_rect.height = screen_height << 16;
DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
nativewindow.element = dispman_element;
nativewindow.width = screen_width;
nativewindow.height = screen_height;
vc_dispmanx_update_submit_sync(dispman_update);
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
assert(surface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(display, surface, surface, context);
assert(EGL_FALSE != result);
gles2_create();
}
void SDL_VIDEO_Exit()
{
if(screen)
{
SDL_FreeSurface(screen);
screen = NULL;
}
SDL_QuitSubSystem(SDL_INIT_VIDEO);
gles2_destroy();
// Release OpenGL resources
eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
eglDestroySurface( display, surface );
eglDestroyContext( display, context );
eglTerminate( display );
bcm_host_deinit();
}
void PLATFORM_DisplayScreen()
{
gles2_draw(screen_width, screen_height);
eglSwapBuffers(display, surface);
}