Added GLES target and updated Makefile
This commit is contained in:
parent
6db872bcd8
commit
9b0817b04b
8 changed files with 1738 additions and 2 deletions
16
Makefile
16
Makefile
|
@ -10,6 +10,10 @@ else ifeq ($(PLATFORM),rpi2)
|
|||
MORE_CFLAGS += -DARMV6T2 -DUSE_ARMNEON
|
||||
else ifeq ($(PLATFORM),rpi1)
|
||||
CPU_FLAGS += -march=armv6zk -mfpu=vfp -mfloat-abi=hard
|
||||
else ifeq ($(PLATFORM),gles)
|
||||
CPU_FLAGS += -march=armv8-a -mfpu=neon-fp-armv8 -mfloat-abi=hard
|
||||
MORE_CFLAGS += -DARMV6T2 -DUSE_ARMNEON -DHAVE_GLES
|
||||
LDFLAGS += -lEGL -lGLESv1_CM
|
||||
endif
|
||||
|
||||
NAME = uae4arm
|
||||
|
@ -193,8 +197,16 @@ OBJS = \
|
|||
src/od-pandora/gui/PanelSavestate.o \
|
||||
src/od-pandora/gui/main_window.o \
|
||||
src/od-pandora/gui/Navigation.o
|
||||
|
||||
OBJS += src/od-rasp/rasp_gfx.o
|
||||
|
||||
ifeq ($(PLATFORM),gles)
|
||||
OBJS += src/od-gles/gl.o
|
||||
OBJS += src/od-gles/shader_stuff.o
|
||||
OBJS += src/od-gles/gl_platform.o
|
||||
OBJS += src/od-gles/gles_gfx.o
|
||||
else
|
||||
OBJS += src/od-rasp/rasp_gfx.o
|
||||
endif
|
||||
|
||||
OBJS += src/od-pandora/gui/sdltruetypefont.o
|
||||
OBJS += src/od-pandora/picasso96.o
|
||||
|
||||
|
|
282
src/od-gles/gl.cpp
Normal file
282
src/od-gles/gl.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "gl_platform.h"
|
||||
#include "gl.h"
|
||||
|
||||
#include "shader_stuff.h"
|
||||
|
||||
|
||||
static EGLDisplay edpy;
|
||||
static EGLSurface esfc;
|
||||
static EGLContext ectxt;
|
||||
|
||||
/* for external flips */
|
||||
void *gl_es_display;
|
||||
void *gl_es_surface;
|
||||
|
||||
|
||||
static float vertex_coords[] = {
|
||||
-1.0f, 1.0f, 0.0f, // 0 0 1
|
||||
1.0f, 1.0f, 0.0f, // 1 ^
|
||||
-1.0f, -1.0f, 0.0f, // 2 | 2 3
|
||||
1.0f, -1.0f, 0.0f, // 3 +-->
|
||||
};
|
||||
|
||||
static float orig_texture_coords[] = {
|
||||
-0.5f, -0.5f,
|
||||
0.5f, -0.5f,
|
||||
-0.5f, 0.5f,
|
||||
0.5f, 0.5f,
|
||||
};
|
||||
|
||||
static float texture_coords[] = {
|
||||
0.0f, 0.0f, // we flip this:
|
||||
1.0f, 0.0f, // v^
|
||||
0.0f, 1.0f, // | u
|
||||
1.0f, 1.0f, // +-->
|
||||
};
|
||||
|
||||
|
||||
static int gl_have_error(const char *name)
|
||||
{
|
||||
GLenum e = glGetError();
|
||||
if (e != GL_NO_ERROR) {
|
||||
printf("GL error: %s %x\n", name, e);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gles_have_error(const char *name)
|
||||
{
|
||||
EGLint e = eglGetError();
|
||||
if (e != EGL_SUCCESS) {
|
||||
printf("%s %x\n", name, e);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gl_init(void *display, void *window, int *quirks)
|
||||
{
|
||||
EGLConfig ecfg = NULL;
|
||||
GLuint texture_name = 0;
|
||||
void *tmp_texture_mem = NULL;
|
||||
EGLint num_config;
|
||||
int retval = -1;
|
||||
int ret;
|
||||
|
||||
static const EGLint config_attributes[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
static const EGLint context_attributes[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
|
||||
// gl_platform_init() does Raspi-specific stuff like bcm_host_init()
|
||||
ret = gl_platform_init(&display, &window, quirks);
|
||||
if (ret != 0) {
|
||||
printf("gl_platform_init failed with %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp_texture_mem = calloc(1, 1024 * 512 * 2);
|
||||
if (tmp_texture_mem == NULL) {
|
||||
printf("OOM\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
edpy = eglGetDisplay((EGLNativeDisplayType)display);
|
||||
if (edpy == EGL_NO_DISPLAY) {
|
||||
printf("Failed to get EGL display\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!eglInitialize(edpy, NULL, NULL)) {
|
||||
printf("Failed to initialize EGL\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!eglChooseConfig(edpy, config_attributes, &ecfg, 1, &num_config)) {
|
||||
printf("Failed to choose config (%x)\n", eglGetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ecfg == NULL || num_config == 0) {
|
||||
printf("No EGL configs available\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
esfc = eglCreateWindowSurface(edpy, ecfg,
|
||||
(EGLNativeWindowType)window, NULL);
|
||||
if (esfc == EGL_NO_SURFACE) {
|
||||
printf("Unable to create EGL surface (%x)\n",
|
||||
eglGetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
// ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, NULL);
|
||||
ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, context_attributes);
|
||||
if (ectxt == EGL_NO_CONTEXT) {
|
||||
printf("Unable to create EGL context (%x)\n",
|
||||
eglGetError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
eglMakeCurrent(edpy, esfc, esfc, ectxt);
|
||||
|
||||
//glEnable(GL_TEXTURE_2D); // for old fixed-function pipeline
|
||||
//if (gl_have_error("glEnable(GL_TEXTURE_2D)")) goto out;
|
||||
|
||||
glGenTextures(1, &texture_name);
|
||||
if (gl_have_error("glGenTextures")) goto out;
|
||||
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_name);
|
||||
if (gl_have_error("glBindTexture")) goto out;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 512, 0, GL_RGB,
|
||||
GL_UNSIGNED_SHORT_5_6_5, tmp_texture_mem);
|
||||
if (gl_have_error("glTexImage2D")) goto out;
|
||||
|
||||
// no mipmaps
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
//glViewport(0, 0, 512, 512);
|
||||
glLoadIdentity();
|
||||
glFrontFace(GL_CW);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (gl_have_error("init"))
|
||||
goto out;
|
||||
|
||||
gl_es_display = (void *)edpy;
|
||||
gl_es_surface = (void *)esfc;
|
||||
retval = 0;
|
||||
|
||||
int shader_stuff_result;
|
||||
shader_stuff_result = shader_stuff_init();
|
||||
shader_stuff_result = shader_stuff_reload_shaders();
|
||||
shader_stuff_result = shader_stuff_set_data(vertex_coords, texture_coords, texture_name);
|
||||
|
||||
out:
|
||||
free(tmp_texture_mem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int framecount = 0;
|
||||
|
||||
int gl_flip(const void *fb, int w, int h)
|
||||
{
|
||||
static int old_w, old_h;
|
||||
|
||||
if (framecount % 60 == 0)
|
||||
{
|
||||
// printf("gl_flip() w: %d, h: %d\n", w, h);
|
||||
}
|
||||
|
||||
if (framecount % 30 == 0)
|
||||
{
|
||||
if (shader_stuff_shader_needs_reload()) {
|
||||
shader_stuff_reload_shaders();
|
||||
// shader_stuff_set_data(vertex_coords, texture_coords, texture_name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
framecount++;
|
||||
float floattime = (framecount * 0.04f);
|
||||
|
||||
if (fb != NULL) {
|
||||
if (w != old_w || h != old_h) {
|
||||
float f_w = (float)w / 1024.0f;
|
||||
float f_h = (float)h / 512.0f;
|
||||
texture_coords[1*2 + 0] = f_w;
|
||||
texture_coords[2*2 + 1] = f_h;
|
||||
texture_coords[3*2 + 0] = f_w;
|
||||
texture_coords[3*2 + 1] = f_h;
|
||||
old_w = w;
|
||||
old_h = h;
|
||||
}
|
||||
/*
|
||||
float rotmat[4]; // 2d rotation matrix
|
||||
rotmat[0] = cos(floattime);
|
||||
rotmat[1] = sin(floattime);
|
||||
rotmat[2] = -sin(floattime);
|
||||
rotmat[3] = cos(floattime);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
float f_w = (float)w / 1024.0f;
|
||||
float f_h = (float)h / 512.0f;
|
||||
float x = orig_texture_coords[i*2 + 0] * f_w;
|
||||
float y = orig_texture_coords[i*2 + 1] * f_h;
|
||||
texture_coords[i*2 + 0] =
|
||||
f_w * 0.5f + (x * rotmat[0] + y * rotmat[1]);
|
||||
texture_coords[i*2 + 1] =
|
||||
f_h * 0.5f + (x * rotmat[2] + y * rotmat[3]);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb);
|
||||
if (gl_have_error("glTexSubImage2D"))
|
||||
return -1;
|
||||
} // if (fb != NULL)
|
||||
|
||||
// glVertexPointer(3, GL_FLOAT, 0, vertex_coords);
|
||||
// if (gl_have_error("glVertexPointer")) return -1;
|
||||
|
||||
// glTexCoordPointer(2, GL_FLOAT, 0, texture_coords);
|
||||
// if (gl_have_error("glTexCoordPointer")) return -1;
|
||||
|
||||
shader_stuff_frame(framecount, w, h, 800, 480); // TODO! hard-coded output size
|
||||
if (gl_have_error("use program")) return -1;
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
// glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
if (gl_have_error("glDrawArrays")) return -1;
|
||||
|
||||
eglSwapBuffers(edpy, esfc);
|
||||
if (gles_have_error("eglSwapBuffers")) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gl_finish(void)
|
||||
{
|
||||
eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(edpy, ectxt);
|
||||
ectxt = EGL_NO_CONTEXT;
|
||||
eglDestroySurface(edpy, esfc);
|
||||
esfc = EGL_NO_SURFACE;
|
||||
eglTerminate(edpy);
|
||||
edpy = EGL_NO_DISPLAY;
|
||||
|
||||
gl_es_display = (void *)edpy;
|
||||
gl_es_surface = (void *)esfc;
|
||||
|
||||
gl_platform_finish();
|
||||
}
|
35
src/od-gles/gl.h
Normal file
35
src/od-gles/gl.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef LIBPICOFE_GL_H
|
||||
#define LIBPICOFE_GL_H
|
||||
|
||||
#ifdef HAVE_GLES
|
||||
|
||||
int gl_init(void *display, void *window, int *quirks);
|
||||
int gl_flip(const void *fb, int w, int h);
|
||||
void gl_finish(void);
|
||||
|
||||
/* for external flips */
|
||||
extern void *gl_es_display;
|
||||
extern void *gl_es_surface;
|
||||
|
||||
#else
|
||||
|
||||
static __inline int gl_init(void *display, void *window, int *quirks)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static __inline int gl_flip(const void *fb, int w, int h)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static __inline void gl_finish(void)
|
||||
{
|
||||
}
|
||||
|
||||
#define gl_es_display (void *)0
|
||||
#define gl_es_surface (void *)0
|
||||
|
||||
#endif
|
||||
|
||||
#define GL_QUIRK_ACTIVATE_RECREATE 1
|
||||
|
||||
#endif // LIBPICOFE_GL_H
|
156
src/od-gles/gl_platform.cpp
Normal file
156
src/od-gles/gl_platform.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "gl_platform.h"
|
||||
|
||||
#ifdef VCOS_VERSION
|
||||
|
||||
/*
|
||||
* hacks for Broadcom VideoCore / Raspberry Pi..
|
||||
* Why do I have to do this proprietary API stuff,
|
||||
* couldn't they implement EGL properly? D:
|
||||
*/
|
||||
#include <bcm_host.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static Display *x11display;
|
||||
static Window x11window;
|
||||
static DISPMANX_DISPLAY_HANDLE_T m_dispmanDisplay;
|
||||
static EGL_DISPMANX_WINDOW_T m_nativeWindow;
|
||||
|
||||
static void *x11lib;
|
||||
#define FPTR(f) typeof(f) * p##f
|
||||
static FPTR(XGetGeometry);
|
||||
static FPTR(XGetWindowAttributes);
|
||||
static FPTR(XTranslateCoordinates);
|
||||
|
||||
static void get_window_rect(VC_RECT_T *rect)
|
||||
{
|
||||
XWindowAttributes xattrs_root;
|
||||
uint32_t disp_w = 0, disp_h = 0;
|
||||
int dx = 0, dy = 0;
|
||||
unsigned int dw = 0, dh = 0, dummy;
|
||||
Window root, dummyw;
|
||||
|
||||
graphics_get_display_size(0, &disp_w, &disp_h);
|
||||
if (disp_w == 0 || disp_h == 0)
|
||||
fprintf(stderr, "ERROR: graphics_get_display_size is broken\n");
|
||||
|
||||
// default to fullscreen
|
||||
// Chips: rpi cut border when full screen...
|
||||
#if 1
|
||||
rect->x = (disp_w*2)/100;
|
||||
rect->y = 0;
|
||||
rect->width = disp_w - (disp_w*2)/100;
|
||||
rect->height = disp_h - (disp_h*2)/100;
|
||||
#else
|
||||
rect->x = rect->y = 0;
|
||||
rect->width = disp_w;
|
||||
rect->height = disp_h;
|
||||
#endif
|
||||
|
||||
if (x11display == NULL || x11window == 0)
|
||||
return; // use fullscreen
|
||||
|
||||
pXGetGeometry(x11display, x11window, &root, &dx, &dy, &dw, &dh,
|
||||
&dummy, &dummy);
|
||||
pXGetWindowAttributes(x11display, root, &xattrs_root);
|
||||
|
||||
if (dw == xattrs_root.width && dh == xattrs_root.height)
|
||||
return; // use fullscreen
|
||||
|
||||
pXTranslateCoordinates(x11display, x11window, root,
|
||||
dx, dy, &dx, &dy, &dummyw);
|
||||
|
||||
// how to deal with that weird centering thing?
|
||||
// this is not quite right..
|
||||
dx += (disp_w - xattrs_root.width) / 2;
|
||||
dy += (disp_h - xattrs_root.height) / 2;
|
||||
|
||||
rect->x = dx;
|
||||
rect->y = dy;
|
||||
rect->width = dw;
|
||||
rect->height = dh;
|
||||
}
|
||||
|
||||
static void submit_rect(void)
|
||||
{
|
||||
DISPMANX_UPDATE_HANDLE_T m_dispmanUpdate;
|
||||
DISPMANX_ELEMENT_HANDLE_T m_dispmanElement;
|
||||
VC_RECT_T srcRect = { 0, }; // unused, but we segfault without passing it??
|
||||
VC_RECT_T dstRect;
|
||||
|
||||
get_window_rect(&dstRect);
|
||||
|
||||
m_dispmanDisplay = vc_dispmanx_display_open(0);
|
||||
m_dispmanUpdate = vc_dispmanx_update_start(0);
|
||||
|
||||
m_dispmanElement = vc_dispmanx_element_add(m_dispmanUpdate,
|
||||
m_dispmanDisplay, 0, &dstRect, 0, &srcRect,
|
||||
DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE);
|
||||
|
||||
m_nativeWindow.element = m_dispmanElement;
|
||||
m_nativeWindow.width = dstRect.width;
|
||||
m_nativeWindow.height = dstRect.height;
|
||||
|
||||
vc_dispmanx_update_submit_sync(m_dispmanUpdate);
|
||||
}
|
||||
|
||||
int gl_platform_init(void **display, void **window, int *quirks)
|
||||
{
|
||||
x11display = NULL;
|
||||
x11window = 0;
|
||||
|
||||
x11lib = dlopen("libX11.so.6", RTLD_LAZY);
|
||||
if (x11lib != NULL) {
|
||||
pXGetGeometry = dlsym(x11lib, "XGetGeometry");
|
||||
pXGetWindowAttributes = dlsym(x11lib, "XGetWindowAttributes");
|
||||
pXTranslateCoordinates = dlsym(x11lib, "XTranslateCoordinates");
|
||||
if (pXGetGeometry != NULL && pXGetWindowAttributes != NULL
|
||||
&& pXTranslateCoordinates != NULL)
|
||||
{
|
||||
x11display = *display;
|
||||
x11window = (Window)*window;
|
||||
}
|
||||
}
|
||||
|
||||
bcm_host_init();
|
||||
submit_rect();
|
||||
|
||||
*display = EGL_DEFAULT_DISPLAY;
|
||||
*window = &m_nativeWindow;
|
||||
*quirks |= GL_QUIRK_ACTIVATE_RECREATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gl_platform_finish(void)
|
||||
{
|
||||
vc_dispmanx_display_close(m_dispmanDisplay);
|
||||
bcm_host_deinit();
|
||||
|
||||
if (x11lib) {
|
||||
dlclose(x11lib);
|
||||
x11lib = NULL;
|
||||
}
|
||||
|
||||
x11display = NULL;
|
||||
x11window = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int gl_platform_init(void **display, void **window, int *quirks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gl_platform_finish(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
2
src/od-gles/gl_platform.h
Normal file
2
src/od-gles/gl_platform.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
int gl_platform_init(void **display, void **window, int *quirks);
|
||||
void gl_platform_finish(void);
|
748
src/od-gles/gles_gfx.cpp
Normal file
748
src/od-gles/gles_gfx.cpp
Normal file
|
@ -0,0 +1,748 @@
|
|||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
#include "config.h"
|
||||
#include "uae.h"
|
||||
#include "options.h"
|
||||
#include "gui.h"
|
||||
#include "memory.h"
|
||||
#include "newcpu.h"
|
||||
#include "inputdevice.h"
|
||||
#include "custom.h"
|
||||
#include "xwin.h"
|
||||
#include "drawing.h"
|
||||
#include "savestate.h"
|
||||
#include "picasso96.h"
|
||||
|
||||
#include <png.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <SDL_gfxPrimitives.h>
|
||||
#ifdef ANDROIDSDL
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
#include "gl.h"
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
/* SDL surface variable for output of emulation */
|
||||
SDL_Surface *prSDLScreen = NULL;
|
||||
/* Dummy SDL variable for screen init */
|
||||
SDL_Surface *Dummy_prSDLScreen = NULL;
|
||||
static SDL_Surface *current_screenshot = NULL;
|
||||
/* Possible screen modes (x and y resolutions) */
|
||||
#define MAX_SCREEN_MODES 6
|
||||
static int x_size_table[MAX_SCREEN_MODES] = { 640, 640, 800, 1024, 1152, 1280 };
|
||||
static int y_size_table[MAX_SCREEN_MODES] = { 400, 480, 480, 768, 864, 960 };
|
||||
|
||||
static int red_bits, green_bits, blue_bits;
|
||||
static int red_shift, green_shift, blue_shift;
|
||||
|
||||
struct PicassoResolution *DisplayModes;
|
||||
struct MultiDisplay Displays[MAX_DISPLAYS];
|
||||
|
||||
int screen_is_picasso = 0;
|
||||
|
||||
static int curr_layer_width = 0;
|
||||
|
||||
static char vid_drv_name[32];
|
||||
static void *display, *window;
|
||||
static int gl_quirks;
|
||||
|
||||
static char screenshot_filename_default[255]={
|
||||
'/', 't', 'm', 'p', '/', 'n', 'u', 'l', 'l', '.', 'p', 'n', 'g', '\0'
|
||||
};
|
||||
char *screenshot_filename=(char *)&screenshot_filename_default[0];
|
||||
FILE *screenshot_file=NULL;
|
||||
static void CreateScreenshot(void);
|
||||
static int save_thumb(char *path);
|
||||
int delay_savestate_frame = 0;
|
||||
|
||||
int justClicked = 0;
|
||||
int mouseMoving = 0;
|
||||
int fcounter = 0;
|
||||
int doStylusRightClick = 0;
|
||||
|
||||
static long next_synctime = 0;
|
||||
|
||||
|
||||
unsigned char current_resource_amigafb = 0;
|
||||
|
||||
|
||||
int graphics_setup (void)
|
||||
{
|
||||
#ifdef PICASSO96
|
||||
picasso_InitResolutions();
|
||||
InitPicasso96();
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void InitAmigaVidMode(struct uae_prefs *p)
|
||||
{
|
||||
/* Initialize structure for Amiga video modes */
|
||||
gfxvidinfo.pixbytes = 2;
|
||||
gfxvidinfo.bufmem = (uae_u8 *)prSDLScreen->pixels;
|
||||
gfxvidinfo.outwidth = p->gfx_size.width;
|
||||
gfxvidinfo.outheight = p->gfx_size.height;
|
||||
#ifdef PICASSO96
|
||||
if(screen_is_picasso)
|
||||
{
|
||||
gfxvidinfo.outwidth = picasso_vidinfo.width;
|
||||
//gfxvidinfo.outheight = picasso_vidinfo.height;
|
||||
}
|
||||
#endif
|
||||
gfxvidinfo.rowbytes = prSDLScreen->pitch;
|
||||
//gfxvidinfo.rowbytes = blit_rect.width * 2;
|
||||
}
|
||||
|
||||
void graphics_dispmanshutdown (void)
|
||||
{
|
||||
printf("dispmanshutdown\n");
|
||||
}
|
||||
|
||||
|
||||
void graphics_subshutdown (void)
|
||||
{
|
||||
gl_finish();
|
||||
// Dunno if below lines are usefull for Rpi...
|
||||
//SDL_FreeSurface(prSDLScreen);
|
||||
//prSDLScreen = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void open_screen(struct uae_prefs *p)
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
SDL_SysWMinfo wminfo;
|
||||
int ret;
|
||||
int gl_works = 0;
|
||||
|
||||
|
||||
#ifdef PICASSO96
|
||||
if (screen_is_picasso)
|
||||
{
|
||||
width = picasso_vidinfo.width;
|
||||
height = picasso_vidinfo.height;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
p->gfx_resolution = p->gfx_size.width > 600 ? 1 : 0;
|
||||
width = p->gfx_size.width;
|
||||
height = p->gfx_size.height;
|
||||
}
|
||||
|
||||
|
||||
if(Dummy_prSDLScreen)
|
||||
{ // y.f. 2016-10-13 : free the previous screen surface every time,
|
||||
// so we can have fullscreen while running and windowed while in config window.
|
||||
// Apparently, something somewhere is resetting the screen.
|
||||
SDL_FreeSurface(Dummy_prSDLScreen);
|
||||
Dummy_prSDLScreen = NULL;
|
||||
}
|
||||
|
||||
if(Dummy_prSDLScreen == NULL )
|
||||
{
|
||||
const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo ();
|
||||
printf("Current resolution: %d x %d %d bpp\n",videoInfo->current_w, videoInfo->current_h, videoInfo->vfmt->BitsPerPixel);
|
||||
//Dummy_prSDLScreen = SDL_SetVideoMode(videoInfo->current_w,videoInfo->current_h,16,SDL_SWSURFACE |SDL_FULLSCREEN);
|
||||
Dummy_prSDLScreen = SDL_SetVideoMode(800,480,16,SDL_SWSURFACE );
|
||||
}
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
printf("Emulation resolution: Width %i Height: %i\n",width,height);
|
||||
prSDLScreen = SDL_CreateRGBSurface(SDL_SWSURFACE,width,height,16,
|
||||
Dummy_prSDLScreen->format->Rmask,
|
||||
Dummy_prSDLScreen->format->Gmask,
|
||||
Dummy_prSDLScreen->format->Bmask,
|
||||
Dummy_prSDLScreen->format->Amask);
|
||||
|
||||
|
||||
// get x11 display/window for GL
|
||||
SDL_VideoDriverName(vid_drv_name, sizeof(vid_drv_name));
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
if (strcmp(vid_drv_name, "x11") == 0) {
|
||||
SDL_VERSION(&wminfo.version);
|
||||
ret = SDL_GetWMInfo(&wminfo);
|
||||
if (ret > 0) {
|
||||
display = wminfo.info.x11.display;
|
||||
window = (void *)wminfo.info.x11.window;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)wminfo;
|
||||
#endif
|
||||
ret = gl_init(display, window, &gl_quirks);
|
||||
if (ret == 0) {
|
||||
gl_works = 1;
|
||||
}
|
||||
|
||||
|
||||
if(prSDLScreen != NULL)
|
||||
{
|
||||
InitAmigaVidMode(p);
|
||||
init_row_map();
|
||||
}
|
||||
//framecnt = 1; // Don't draw frame before reset done
|
||||
}
|
||||
|
||||
|
||||
void update_display(struct uae_prefs *p)
|
||||
{
|
||||
open_screen(p);
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
framecnt = 1; // Don't draw frame before reset done
|
||||
}
|
||||
|
||||
|
||||
int check_prefs_changed_gfx (void)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if(currprefs.gfx_size.height != changed_prefs.gfx_size.height ||
|
||||
currprefs.gfx_size.width != changed_prefs.gfx_size.width ||
|
||||
currprefs.gfx_size_fs.width != changed_prefs.gfx_size_fs.width ||
|
||||
currprefs.gfx_resolution != changed_prefs.gfx_resolution)
|
||||
{
|
||||
cfgfile_configuration_change(1);
|
||||
currprefs.gfx_size.height = changed_prefs.gfx_size.height;
|
||||
currprefs.gfx_size.width = changed_prefs.gfx_size.width;
|
||||
currprefs.gfx_size_fs.width = changed_prefs.gfx_size_fs.width;
|
||||
currprefs.gfx_resolution = changed_prefs.gfx_resolution;
|
||||
update_display(&currprefs);
|
||||
changed = 1;
|
||||
}
|
||||
if (currprefs.leds_on_screen != changed_prefs.leds_on_screen ||
|
||||
currprefs.pandora_hide_idle_led != changed_prefs.pandora_hide_idle_led ||
|
||||
currprefs.pandora_vertical_offset != changed_prefs.pandora_vertical_offset)
|
||||
{
|
||||
currprefs.leds_on_screen = changed_prefs.leds_on_screen;
|
||||
currprefs.pandora_hide_idle_led = changed_prefs.pandora_hide_idle_led;
|
||||
currprefs.pandora_vertical_offset = changed_prefs.pandora_vertical_offset;
|
||||
changed = 1;
|
||||
}
|
||||
if (currprefs.chipset_refreshrate != changed_prefs.chipset_refreshrate)
|
||||
{
|
||||
currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate;
|
||||
init_hz_full ();
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
int lockscr (void)
|
||||
{
|
||||
//SDL_LockSurface(prSDLScreen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void unlockscr (void)
|
||||
{
|
||||
//SDL_UnlockSurface(prSDLScreen);
|
||||
}
|
||||
|
||||
void wait_for_vsync(void)
|
||||
{
|
||||
// Temporary
|
||||
}
|
||||
|
||||
void flush_screen ()
|
||||
{
|
||||
//SDL_UnlockSurface (prSDLScreen);
|
||||
|
||||
|
||||
if (savestate_state == STATE_DOSAVE)
|
||||
{
|
||||
if(delay_savestate_frame > 0)
|
||||
--delay_savestate_frame;
|
||||
else
|
||||
{
|
||||
CreateScreenshot();
|
||||
save_thumb(screenshot_filename);
|
||||
savestate_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
long start = read_processor_time();
|
||||
//if(start < next_synctime && next_synctime - start > time_per_frame - 1000)
|
||||
// usleep((next_synctime - start) - 1000);
|
||||
|
||||
gl_flip(gfxvidinfo.bufmem, currprefs.gfx_size.width, currprefs.gfx_size.height);
|
||||
|
||||
|
||||
last_synctime = read_processor_time();
|
||||
|
||||
if(last_synctime - next_synctime > time_per_frame * (1 + currprefs.gfx_framerate) - (long)1000)
|
||||
adjust_idletime(-1);
|
||||
else
|
||||
adjust_idletime(last_synctime - start);
|
||||
|
||||
next_synctime = last_synctime + time_per_frame * (1 + currprefs.gfx_framerate);
|
||||
|
||||
init_row_map();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void black_screen_now(void)
|
||||
{
|
||||
SDL_FillRect(Dummy_prSDLScreen,NULL,0);
|
||||
SDL_Flip(Dummy_prSDLScreen);
|
||||
}
|
||||
|
||||
|
||||
static void graphics_subinit (void)
|
||||
{
|
||||
if (prSDLScreen == NULL)
|
||||
{
|
||||
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
InitAmigaVidMode(&currprefs);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_INLINE int bitsInMask (unsigned long mask)
|
||||
{
|
||||
/* count bits in mask */
|
||||
int n = 0;
|
||||
while (mask)
|
||||
{
|
||||
n += mask & 1;
|
||||
mask >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
STATIC_INLINE int maskShift (unsigned long mask)
|
||||
{
|
||||
/* determine how far mask is shifted */
|
||||
int n = 0;
|
||||
while (!(mask & 1))
|
||||
{
|
||||
n++;
|
||||
mask >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static int init_colors (void)
|
||||
{
|
||||
int i;
|
||||
int red_bits, green_bits, blue_bits;
|
||||
int red_shift, green_shift, blue_shift;
|
||||
|
||||
/* Truecolor: */
|
||||
red_bits = bitsInMask(prSDLScreen->format->Rmask);
|
||||
green_bits = bitsInMask(prSDLScreen->format->Gmask);
|
||||
blue_bits = bitsInMask(prSDLScreen->format->Bmask);
|
||||
red_shift = maskShift(prSDLScreen->format->Rmask);
|
||||
green_shift = maskShift(prSDLScreen->format->Gmask);
|
||||
blue_shift = maskShift(prSDLScreen->format->Bmask);
|
||||
alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift, 0);
|
||||
notice_new_xcolors();
|
||||
for (i = 0; i < 4096; i++)
|
||||
xcolors[i] = xcolors[i] * 0x00010001;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the colour depth of the display
|
||||
*/
|
||||
static int get_display_depth (void)
|
||||
{
|
||||
const SDL_VideoInfo *vid_info;
|
||||
int depth = 0;
|
||||
|
||||
if ((vid_info = SDL_GetVideoInfo())) {
|
||||
depth = vid_info->vfmt->BitsPerPixel;
|
||||
|
||||
/* Don't trust the answer if it's 16 bits; the display
|
||||
* could actually be 15 bits deep. We'll count the bits
|
||||
* ourselves */
|
||||
if (depth == 16)
|
||||
depth = bitsInMask (vid_info->vfmt->Rmask) + bitsInMask (vid_info->vfmt->Gmask) + bitsInMask (vid_info->vfmt->Bmask);
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
int GetSurfacePixelFormat(void)
|
||||
{
|
||||
int depth = get_display_depth();
|
||||
int unit = (depth + 1) & 0xF8;
|
||||
|
||||
return (unit == 8 ? RGBFB_CHUNKY
|
||||
: depth == 15 && unit == 16 ? RGBFB_R5G5B5
|
||||
: depth == 16 && unit == 16 ? RGBFB_R5G6B5
|
||||
: unit == 24 ? RGBFB_B8G8R8
|
||||
: unit == 32 ? RGBFB_R8G8B8A8
|
||||
: RGBFB_NONE);
|
||||
}
|
||||
|
||||
|
||||
int graphics_init (bool mousecapture)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
//uae_sem_init (&vsync_wait_sem, 0, 1);
|
||||
|
||||
graphics_subinit ();
|
||||
|
||||
|
||||
if (!init_colors ())
|
||||
return 0;
|
||||
|
||||
//buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
|
||||
//keyboard_init();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void graphics_leave (void)
|
||||
{
|
||||
graphics_subshutdown ();
|
||||
SDL_FreeSurface(Dummy_prSDLScreen);
|
||||
SDL_VideoQuit();
|
||||
}
|
||||
|
||||
|
||||
#define systemRedShift (prSDLScreen->format->Rshift)
|
||||
#define systemGreenShift (prSDLScreen->format->Gshift)
|
||||
#define systemBlueShift (prSDLScreen->format->Bshift)
|
||||
#define systemRedMask (prSDLScreen->format->Rmask)
|
||||
#define systemGreenMask (prSDLScreen->format->Gmask)
|
||||
#define systemBlueMask (prSDLScreen->format->Bmask)
|
||||
|
||||
static int save_png(SDL_Surface* surface, char *path)
|
||||
{
|
||||
int w = surface->w;
|
||||
int h = surface->h;
|
||||
unsigned char * pix = (unsigned char *)surface->pixels;
|
||||
unsigned char writeBuffer[1024 * 3];
|
||||
FILE *f = fopen(path,"wb");
|
||||
if(!f) return 0;
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
if(!png_ptr) {
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if(!info_ptr) {
|
||||
png_destroy_write_struct(&png_ptr,NULL);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr,f);
|
||||
|
||||
png_set_IHDR(png_ptr,
|
||||
info_ptr,
|
||||
w,
|
||||
h,
|
||||
8,
|
||||
PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info(png_ptr,info_ptr);
|
||||
|
||||
unsigned char *b = writeBuffer;
|
||||
|
||||
int sizeX = w;
|
||||
int sizeY = h;
|
||||
int y;
|
||||
int x;
|
||||
|
||||
unsigned short *p = (unsigned short *)pix;
|
||||
for(y = 0; y < sizeY; y++)
|
||||
{
|
||||
for(x = 0; x < sizeX; x++)
|
||||
{
|
||||
unsigned short v = p[x];
|
||||
|
||||
*b++ = ((v & systemRedMask ) >> systemRedShift ) << 3; // R
|
||||
*b++ = ((v & systemGreenMask) >> systemGreenShift) << 2; // G
|
||||
*b++ = ((v & systemBlueMask ) >> systemBlueShift ) << 3; // B
|
||||
}
|
||||
p += surface->pitch / 2;
|
||||
png_write_row(png_ptr,writeBuffer);
|
||||
b = writeBuffer;
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void CreateScreenshot(void)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
if(current_screenshot != NULL)
|
||||
{
|
||||
SDL_FreeSurface(current_screenshot);
|
||||
current_screenshot = NULL;
|
||||
}
|
||||
|
||||
w=prSDLScreen->w;
|
||||
h=prSDLScreen->h;
|
||||
|
||||
current_screenshot = SDL_CreateRGBSurface(prSDLScreen->flags,w,h,prSDLScreen->format->BitsPerPixel,prSDLScreen->format->Rmask,prSDLScreen->format->Gmask,prSDLScreen->format->Bmask,prSDLScreen->format->Amask);
|
||||
SDL_BlitSurface(prSDLScreen, NULL, current_screenshot, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int save_thumb(char *path)
|
||||
{
|
||||
int ret = 0;
|
||||
if(current_screenshot != NULL)
|
||||
{
|
||||
ret = save_png(current_screenshot, path);
|
||||
SDL_FreeSurface(current_screenshot);
|
||||
current_screenshot = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vsync_switchmode (int hz)
|
||||
{
|
||||
int changed_height = changed_prefs.gfx_size.height;
|
||||
|
||||
if (hz >= 55)
|
||||
hz = 60;
|
||||
else
|
||||
hz = 50;
|
||||
|
||||
if(hz == 50 && currVSyncRate == 60)
|
||||
{
|
||||
// Switch from NTSC -> PAL
|
||||
switch(changed_height) {
|
||||
case 200: changed_height = 240; break;
|
||||
case 216: changed_height = 262; break;
|
||||
case 240: changed_height = 270; break;
|
||||
case 256: changed_height = 270; break;
|
||||
case 262: changed_height = 270; break;
|
||||
case 270: changed_height = 270; break;
|
||||
}
|
||||
}
|
||||
else if(hz == 60 && currVSyncRate == 50)
|
||||
{
|
||||
// Switch from PAL -> NTSC
|
||||
switch(changed_height) {
|
||||
case 200: changed_height = 200; break;
|
||||
case 216: changed_height = 200; break;
|
||||
case 240: changed_height = 200; break;
|
||||
case 256: changed_height = 216; break;
|
||||
case 262: changed_height = 216; break;
|
||||
case 270: changed_height = 240; break;
|
||||
}
|
||||
}
|
||||
|
||||
if(changed_height == currprefs.gfx_size.height && hz == currprefs.chipset_refreshrate)
|
||||
return true;
|
||||
|
||||
changed_prefs.gfx_size.height = changed_height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool target_graphics_buffer_update (void)
|
||||
{
|
||||
bool rate_changed = 0;
|
||||
//bool rate_changed = SetVSyncRate(currprefs.chipset_refreshrate);
|
||||
|
||||
if(currprefs.gfx_size.height != changed_prefs.gfx_size.height)
|
||||
{
|
||||
update_display(&changed_prefs);
|
||||
rate_changed = true;
|
||||
}
|
||||
|
||||
if(rate_changed)
|
||||
{
|
||||
black_screen_now();
|
||||
fpscounter_reset();
|
||||
time_per_frame = 1000 * 1000 / (currprefs.chipset_refreshrate);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef PICASSO96
|
||||
|
||||
|
||||
static int resolution_compare (const void *a, const void *b)
|
||||
{
|
||||
struct PicassoResolution *ma = (struct PicassoResolution *)a;
|
||||
struct PicassoResolution *mb = (struct PicassoResolution *)b;
|
||||
if (ma->res.width < mb->res.width)
|
||||
return -1;
|
||||
if (ma->res.width > mb->res.width)
|
||||
return 1;
|
||||
if (ma->res.height < mb->res.height)
|
||||
return -1;
|
||||
if (ma->res.height > mb->res.height)
|
||||
return 1;
|
||||
return ma->depth - mb->depth;
|
||||
}
|
||||
static void sortmodes (void)
|
||||
{
|
||||
int i = 0, idx = -1;
|
||||
int pw = -1, ph = -1;
|
||||
while (DisplayModes[i].depth >= 0)
|
||||
i++;
|
||||
qsort (DisplayModes, i, sizeof (struct PicassoResolution), resolution_compare);
|
||||
for (i = 0; DisplayModes[i].depth >= 0; i++) {
|
||||
if (DisplayModes[i].res.height != ph || DisplayModes[i].res.width != pw) {
|
||||
ph = DisplayModes[i].res.height;
|
||||
pw = DisplayModes[i].res.width;
|
||||
idx++;
|
||||
}
|
||||
DisplayModes[i].residx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
static void modesList (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
i = 0;
|
||||
while (DisplayModes[i].depth >= 0) {
|
||||
write_log ("%d: %s (", i, DisplayModes[i].name);
|
||||
j = 0;
|
||||
while (DisplayModes[i].refresh[j] > 0) {
|
||||
if (j > 0)
|
||||
write_log (",");
|
||||
write_log ("%d", DisplayModes[i].refresh[j]);
|
||||
j++;
|
||||
}
|
||||
write_log (")\n");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void picasso_InitResolutions (void)
|
||||
{
|
||||
struct MultiDisplay *md1;
|
||||
int i, count = 0;
|
||||
char tmp[200];
|
||||
int bitdepth;
|
||||
|
||||
Displays[0].primary = 1;
|
||||
Displays[0].disabled = 0;
|
||||
Displays[0].rect.left = 0;
|
||||
Displays[0].rect.top = 0;
|
||||
Displays[0].rect.right = 800;
|
||||
Displays[0].rect.bottom = 640;
|
||||
sprintf (tmp, "%s (%d*%d)", "Display", Displays[0].rect.right, Displays[0].rect.bottom);
|
||||
Displays[0].name = my_strdup(tmp);
|
||||
Displays[0].name2 = my_strdup("Display");
|
||||
|
||||
md1 = Displays;
|
||||
DisplayModes = md1->DisplayModes = (struct PicassoResolution*) xmalloc (sizeof (struct PicassoResolution) * MAX_PICASSO_MODES);
|
||||
for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++) {
|
||||
for(bitdepth = 16; bitdepth <= 32; bitdepth += 16) {
|
||||
int bit_unit = (bitdepth + 1) & 0xF8;
|
||||
int rgbFormat = (bitdepth == 16 ? RGBFB_R5G6B5 : RGBFB_R8G8B8A8);
|
||||
int pixelFormat = 1 << rgbFormat;
|
||||
pixelFormat |= RGBFF_CHUNKY;
|
||||
|
||||
if (SDL_VideoModeOK (x_size_table[i], y_size_table[i], bitdepth, SDL_SWSURFACE))
|
||||
{
|
||||
DisplayModes[count].res.width = x_size_table[i];
|
||||
DisplayModes[count].res.height = y_size_table[i];
|
||||
DisplayModes[count].depth = bit_unit >> 3;
|
||||
DisplayModes[count].refresh[0] = 50;
|
||||
DisplayModes[count].refresh[1] = 60;
|
||||
DisplayModes[count].refresh[2] = 0;
|
||||
DisplayModes[count].colormodes = pixelFormat;
|
||||
sprintf(DisplayModes[count].name, "%dx%d, %d-bit",
|
||||
DisplayModes[count].res.width, DisplayModes[count].res.height, DisplayModes[count].depth * 8);
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
DisplayModes[count].depth = -1;
|
||||
sortmodes();
|
||||
modesList();
|
||||
DisplayModes = Displays[0].DisplayModes;
|
||||
}
|
||||
|
||||
|
||||
void gfx_set_picasso_modeinfo (uae_u32 w, uae_u32 h, uae_u32 depth, RGBFTYPE rgbfmt)
|
||||
{
|
||||
depth >>= 3;
|
||||
if( ((unsigned)picasso_vidinfo.width == w ) &&
|
||||
( (unsigned)picasso_vidinfo.height == h ) &&
|
||||
( (unsigned)picasso_vidinfo.depth == depth ) &&
|
||||
( picasso_vidinfo.selected_rgbformat == rgbfmt) )
|
||||
return;
|
||||
|
||||
picasso_vidinfo.selected_rgbformat = rgbfmt;
|
||||
picasso_vidinfo.width = w;
|
||||
picasso_vidinfo.height = h;
|
||||
picasso_vidinfo.depth = depth;
|
||||
picasso_vidinfo.extra_mem = 1;
|
||||
|
||||
picasso_vidinfo.pixbytes = depth;
|
||||
if (screen_is_picasso)
|
||||
{
|
||||
open_screen(&currprefs);
|
||||
picasso_vidinfo.rowbytes = prSDLScreen->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gfx_set_picasso_state (int on)
|
||||
{
|
||||
if (on == screen_is_picasso)
|
||||
return;
|
||||
|
||||
screen_is_picasso = on;
|
||||
open_screen(&currprefs);
|
||||
picasso_vidinfo.rowbytes = prSDLScreen->pitch;
|
||||
}
|
||||
|
||||
uae_u8 *gfx_lock_picasso (void)
|
||||
{
|
||||
// We lock the surface directly after create and flip
|
||||
picasso_vidinfo.rowbytes = prSDLScreen->pitch;
|
||||
return (uae_u8 *)prSDLScreen->pixels;
|
||||
}
|
||||
|
||||
void gfx_unlock_picasso (void)
|
||||
{
|
||||
// We lock the surface directly after create and flip, so no unlock here
|
||||
}
|
||||
|
||||
#endif // PICASSO96
|
489
src/od-gles/shader_stuff.cpp
Normal file
489
src/od-gles/shader_stuff.cpp
Normal file
|
@ -0,0 +1,489 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "shader_stuff.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Handle to a program object
|
||||
GLuint programObject;
|
||||
|
||||
// Attribute locations
|
||||
GLint positionLoc;
|
||||
GLint texCoordLoc;
|
||||
|
||||
// Sampler location
|
||||
GLint samplerLoc;
|
||||
|
||||
// Other locations
|
||||
GLint frameCountLoc;
|
||||
GLint emulatorFrameSizeLoc;
|
||||
GLint outputFrameSizeLoc;
|
||||
|
||||
// Texture handle
|
||||
GLuint textureId;
|
||||
|
||||
} UserData;
|
||||
|
||||
typedef struct STATE_T
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
EGL_DISPMANX_WINDOW_T nativewindow;
|
||||
UserData *user_data;
|
||||
void (*draw_func) (struct STATE_T* );
|
||||
} STATE_T;
|
||||
|
||||
|
||||
|
||||
// for checking if file has changed
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
time_t get_file_date(const char *path)
|
||||
{
|
||||
struct stat file_stat;
|
||||
int err = stat(path, &file_stat);
|
||||
if (err)
|
||||
return 0;
|
||||
else
|
||||
return file_stat.st_mtime;
|
||||
}
|
||||
|
||||
|
||||
void showlog(GLint shader)
|
||||
{
|
||||
char log[1024];
|
||||
|
||||
glGetShaderInfoLog(shader,sizeof log,NULL,log);
|
||||
printf("%d:shader:\n%s\n", shader, log);
|
||||
}
|
||||
|
||||
static void showprogramlog(GLint shader)
|
||||
{
|
||||
char log[1024];
|
||||
glGetProgramInfoLog(shader,sizeof log,NULL,log);
|
||||
printf("%d:program:\n%s\n", shader, log);
|
||||
}
|
||||
|
||||
//static char fshader_file_name[10000];
|
||||
static char fshader_file_name[] = "fshader.glsl";
|
||||
static time_t fshader_file_date=0;
|
||||
static GLchar *fshader_source = NULL;
|
||||
|
||||
|
||||
static GLchar default_vShaderStr[] =
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_texCoord; \n"
|
||||
"varying vec2 v_texCoord; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = a_position; \n"
|
||||
" v_texCoord = a_texCoord; \n"
|
||||
"} \n";
|
||||
|
||||
static GLchar default_fShaderStr[] =
|
||||
"precision mediump float;\n"
|
||||
"varying vec2 v_texCoord;\n"
|
||||
"uniform sampler2D s_texture;\n"
|
||||
"uniform float u_framecount;\n"
|
||||
"uniform vec2 u_emulator_frame_size;\n"
|
||||
"uniform vec2 u_output_frame_size;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
// " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
|
||||
" gl_FragColor = texture2D( s_texture, v_texCoord )\n"
|
||||
// " * (cos(gl_FragCoord.y * 3.14159) * 0.5 + 0.5); \n"
|
||||
// " * (cos(v_texCoord.y * 3.14159 * 262.0 * 2.0 * 2.0) * 0.45 + 0.55); \n"
|
||||
" * (cos(gl_FragCoord.y * 3.1415926) * 0.35 + 0.65); \n"
|
||||
"}\n";
|
||||
|
||||
|
||||
/*
|
||||
void set_fshader_file_name(char *shaderdir)
|
||||
{
|
||||
strcpy(fshader_file_name,shaderdir);
|
||||
if(shaderdir[strlen(shaderdir)-1]!='/')
|
||||
strcat(fshader_file_name,"/");
|
||||
strcat(fshader_file_name,"fshader.glsl");
|
||||
}
|
||||
*/
|
||||
|
||||
/* Returns non-zero, if the fragment shaders should be reloaded.
|
||||
* Because the file has been changed or deleted or something.
|
||||
* Returns zero, if the shader doesn't need to be reloaded.
|
||||
*/
|
||||
int shader_stuff_shader_needs_reload()
|
||||
{
|
||||
if ((fshader_file_name == NULL) || (fshader_source == default_fShaderStr))
|
||||
return 0;
|
||||
|
||||
return (get_file_date(fshader_file_name) != fshader_file_date);
|
||||
}
|
||||
|
||||
|
||||
/* Tries to load file named file_name.
|
||||
*
|
||||
* If opening the file succeeds:
|
||||
* Allocates memory for *file_data with malloc() and loads the file
|
||||
* contents in the allocated buffer. An extra terminator char is added.
|
||||
* Previous pointer value is overwritten.
|
||||
*
|
||||
* *file_date is set to the time/date stamp of the file.
|
||||
*
|
||||
* Returns 0.
|
||||
*
|
||||
* If opening the file fails:
|
||||
* *file_data and *file_date are left untouched.
|
||||
* Returns -1.
|
||||
*
|
||||
*/
|
||||
int load_file(char *file_name, GLchar **file_data, time_t *file_date)
|
||||
{
|
||||
GLchar *data = NULL;
|
||||
|
||||
FILE *f = fopen(file_name, "rb");
|
||||
if(f!=NULL)
|
||||
{
|
||||
fseek(f, 0, SEEK_END);
|
||||
int len = ftell(f);
|
||||
*file_data = (GLchar *)malloc(len+1);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(*file_data, 1, len, f);
|
||||
fclose(f);
|
||||
(*file_data)[len] = 0; // String terminator
|
||||
|
||||
*file_date = get_file_date(file_name);
|
||||
}
|
||||
else {
|
||||
printf("Fragment shader file %s won't open\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_fshader_source()
|
||||
{
|
||||
if ((fshader_source != NULL) && (fshader_source != default_fShaderStr)) {
|
||||
free(fshader_source);
|
||||
fshader_source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// Create a shader object, load the shader source, and
|
||||
// compile the shader.
|
||||
//
|
||||
GLuint LoadShader(GLenum type, const GLchar *shaderSrc)
|
||||
{
|
||||
GLuint shader;
|
||||
GLint compiled;
|
||||
// Create the shader object
|
||||
shader = glCreateShader(type);
|
||||
if(shader == 0)
|
||||
return 0;
|
||||
// Load the shader source
|
||||
glShaderSource(shader, 1, &shaderSrc, NULL);
|
||||
// Compile the shader
|
||||
glCompileShader(shader);
|
||||
// Check the compile status
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||
if(!compiled)
|
||||
{
|
||||
GLint infoLen = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
|
||||
if(infoLen > 1)
|
||||
{
|
||||
char* infoLog = (char *)malloc(sizeof(char) * infoLen);
|
||||
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
|
||||
fprintf(stderr, "Error compiling shader:\n%s\n", infoLog);
|
||||
free(infoLog);
|
||||
}
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint LoadProgram ( const GLchar *vertShaderSrc, const GLchar *fragShaderSrc )
|
||||
{
|
||||
GLuint vertexShader;
|
||||
GLuint fragmentShader;
|
||||
GLuint programObject;
|
||||
GLint linked;
|
||||
|
||||
// Load the vertex/fragment shaders
|
||||
vertexShader = LoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
|
||||
if ( vertexShader == 0 )
|
||||
return 0;
|
||||
|
||||
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
|
||||
// if it didn't compile, let's try the default shader
|
||||
if ((fragmentShader == 0) && (fshader_source != default_fShaderStr)) {
|
||||
fshader_source = default_fShaderStr;
|
||||
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, default_fShaderStr );
|
||||
}
|
||||
|
||||
if ( fragmentShader == 0 )
|
||||
{
|
||||
glDeleteShader( vertexShader );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create the program object
|
||||
programObject = glCreateProgram ( );
|
||||
|
||||
if ( programObject == 0 )
|
||||
return 0;
|
||||
|
||||
glAttachShader ( programObject, vertexShader );
|
||||
glAttachShader ( programObject, fragmentShader );
|
||||
|
||||
// Link the program
|
||||
glLinkProgram ( programObject );
|
||||
|
||||
// Check the link status
|
||||
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
|
||||
|
||||
if ( !linked )
|
||||
{
|
||||
GLint infoLen = 0;
|
||||
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
|
||||
|
||||
if ( infoLen > 1 )
|
||||
{
|
||||
char* infoLog = (char *)malloc (sizeof(char) * infoLen );
|
||||
|
||||
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
|
||||
fprintf (stderr, "Error linking program:\n%s\n", infoLog );
|
||||
|
||||
free ( infoLog );
|
||||
}
|
||||
|
||||
glDeleteProgram ( programObject );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free up no longer needed shader resources
|
||||
glDeleteShader ( vertexShader );
|
||||
glDeleteShader ( fragmentShader );
|
||||
|
||||
return programObject;
|
||||
}
|
||||
|
||||
static STATE_T shader_stuff_state;
|
||||
|
||||
int shader_stuff_init()
|
||||
{
|
||||
STATE_T *p_state = &shader_stuff_state;
|
||||
p_state->user_data = (UserData *)malloc(sizeof(UserData));
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
///
|
||||
// Initialize the shader and program object
|
||||
//
|
||||
int shader_stuff_reload_shaders()
|
||||
{
|
||||
STATE_T *p_state = &shader_stuff_state;
|
||||
UserData *userData = p_state->user_data;
|
||||
|
||||
// ----- these lines could be moved to a separate "delete program" routine
|
||||
|
||||
free_fshader_source();
|
||||
|
||||
// If there was an existing program object, delete it.
|
||||
if (userData->programObject != 0) {
|
||||
glDeleteProgram(userData->programObject);
|
||||
userData->programObject = 0;
|
||||
}
|
||||
// -----
|
||||
|
||||
|
||||
if (load_file(fshader_file_name, &fshader_source, &fshader_file_date) != 0) {
|
||||
printf("Cannot open %s. Using built-in default fragment shader.", fshader_file_name);
|
||||
fshader_source = default_fShaderStr;
|
||||
}
|
||||
|
||||
// Load the shaders and get a linked program object
|
||||
userData->programObject = LoadProgram ( default_vShaderStr, fshader_source );
|
||||
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
int shader_stuff_set_data(GLfloat *vertex_coords_3f, GLfloat *texture_coords_2f, GLuint texture_name)
|
||||
{
|
||||
STATE_T *p_state = &shader_stuff_state;
|
||||
UserData *userData = p_state->user_data;
|
||||
|
||||
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
|
||||
// Get the attribute locations
|
||||
userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
|
||||
userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
|
||||
|
||||
// Get the sampler location
|
||||
userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
|
||||
|
||||
// Get the sampler location
|
||||
userData->frameCountLoc = glGetUniformLocation ( userData->programObject, "u_framecount" );
|
||||
printf("frameCountLoc = %d\n", userData->frameCountLoc);
|
||||
userData->emulatorFrameSizeLoc = glGetUniformLocation ( userData->programObject, "u_emulator_frame_size" );
|
||||
printf("emulatorFrameSizeLoc = %d\n", userData->emulatorFrameSizeLoc);
|
||||
userData->outputFrameSizeLoc = glGetUniformLocation ( userData->programObject, "u_output_frame_size" );
|
||||
|
||||
// Load the texture
|
||||
userData->textureId = texture_name;
|
||||
|
||||
// Load the vertex position
|
||||
glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
|
||||
GL_FALSE, 3 * sizeof(GLfloat), vertex_coords_3f );
|
||||
// Load the texture coordinate
|
||||
glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
|
||||
GL_FALSE, 2 * sizeof(GLfloat), texture_coords_2f );
|
||||
|
||||
glEnableVertexAttribArray ( userData->positionLoc );
|
||||
glEnableVertexAttribArray ( userData->texCoordLoc );
|
||||
|
||||
// Bind the texture
|
||||
glActiveTexture ( GL_TEXTURE0 );
|
||||
glBindTexture ( GL_TEXTURE_2D, userData->textureId );
|
||||
|
||||
// Set the sampler texture unit to 0
|
||||
glUniform1i ( userData->samplerLoc, 0 );
|
||||
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// call this for every frame
|
||||
// todo: merge all this "stuff" properly to gl.cpp
|
||||
int shader_stuff_frame(int framecount, int emu_width, int emu_height, int out_width, int out_height)
|
||||
{
|
||||
STATE_T *p_state = &shader_stuff_state;
|
||||
UserData *userData = p_state->user_data;
|
||||
|
||||
glUseProgram ( userData->programObject );
|
||||
|
||||
glUniform1f ( userData->frameCountLoc, (GLfloat)(framecount) );
|
||||
glUniform2f( userData->emulatorFrameSizeLoc, (GLfloat)(emu_width), (GLfloat)(emu_height));
|
||||
glUniform2f ( userData->outputFrameSizeLoc, (GLfloat)(out_width), (GLfloat)(out_height));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// for checking if file has changed
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
void showlog(GLint shader)
|
||||
{
|
||||
char log[1024];
|
||||
|
||||
glGetShaderInfoLog(shader,sizeof log,NULL,log);
|
||||
printf("%d:shader:\n%s\n", shader, log);
|
||||
}
|
||||
|
||||
static void showprogramlog(GLint shader)
|
||||
{
|
||||
char log[1024];
|
||||
glGetProgramInfoLog(shader,sizeof log,NULL,log);
|
||||
printf("%d:program:\n%s\n", shader, log);
|
||||
}
|
||||
|
||||
static char fshader_file_name[10000];
|
||||
static time_t fshader_file_date=0;
|
||||
|
||||
void set_fshader_file_name(char *shaderdir)
|
||||
{
|
||||
strcpy(fshader_file_name,shaderdir);
|
||||
if(shaderdir[strlen(shaderdir)-1]!='/')
|
||||
strcat(fshader_file_name,"/");
|
||||
strcat(fshader_file_name,"fshader.glsl");
|
||||
}
|
||||
|
||||
static int init_shader()
|
||||
{
|
||||
FILE *f;
|
||||
int len;
|
||||
static GLchar *fsource=NULL,*vsource=
|
||||
"attribute vec2 vertex;"
|
||||
"void main(void) {"
|
||||
" gl_Position = vec4(vertex.x,vertex.y,0.0,1.0);"
|
||||
"}";
|
||||
|
||||
f=fopen(fshader_file_name,"rb");
|
||||
if(f==NULL)
|
||||
{
|
||||
printf("Fragment shader won't open\n");
|
||||
return -1;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
len=ftell(f);
|
||||
if(fsource!=NULL)
|
||||
free(fsource);
|
||||
fsource=malloc(len+1);
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(fsource,1,len,f);
|
||||
fclose(f);
|
||||
fsource[len]=0; // Need to terminate!
|
||||
|
||||
fshader_file_date = get_file_date(fshader_file_name);
|
||||
|
||||
vshader=glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vshader,1,(const GLchar **)&vsource,0);
|
||||
glCompileShader(vshader);
|
||||
showlog(vshader);
|
||||
|
||||
fshader=glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fshader,1,(const GLchar **)&fsource,0);
|
||||
glCompileShader(fshader);
|
||||
showlog(fshader);
|
||||
|
||||
program=glCreateProgram();
|
||||
glAttachShader(program,vshader);
|
||||
glAttachShader(program,fshader);
|
||||
glLinkProgram(program);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void delete_shader()
|
||||
{
|
||||
glDetachShader(program, fshader);
|
||||
glDetachShader(program, vshader);
|
||||
glDeleteShader(fshader);
|
||||
glDeleteShader(vshader);
|
||||
glUseProgram(0);
|
||||
glDeleteProgram(program);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void koelli_reload_shader()
|
||||
{
|
||||
delete_shader();
|
||||
init_shader();
|
||||
}
|
||||
*
|
||||
int koelli_fshader_file_changed(void)
|
||||
{
|
||||
return (get_file_date(fshader_file_name) != fshader_file_date);
|
||||
}
|
||||
*/
|
12
src/od-gles/shader_stuff.h
Normal file
12
src/od-gles/shader_stuff.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __SHADER_STUFF_H
|
||||
#define __SHADER_STUFF_H
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
extern int shader_stuff_init();
|
||||
extern int shader_stuff_shader_needs_reload();
|
||||
extern int shader_stuff_reload_shaders();
|
||||
extern int shader_stuff_set_data(GLfloat *vertex_coords_3f, GLfloat *texture_coords_2f, GLuint texture_name);
|
||||
extern int shader_stuff_frame(int framecount, int emu_width, int emu_height, int out_width, int out_height);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue