Added logic to allow for switching from openGL to cairo draw functions. There is still an issue with the GTK draw update stops getting called when switch from openGL to cairo.

This commit is contained in:
Matthew Budd 2020-06-08 09:14:01 -04:00
parent 79b796f790
commit 9db334275f
5 changed files with 266 additions and 112 deletions

View File

@ -30,7 +30,7 @@ static XVisualInfo *vi = NULL;
static Colormap cmap;
static XSetWindowAttributes swa;
static Window win;
static GLXContext glc;
static GLXContext glc = NULL;
static XWindowAttributes gwa;
static XEvent xev;
@ -77,6 +77,10 @@ static glxwin_shm_t *open_shm(void)
sem_init( &vaddr->sem, 1, 1 );
vaddr->ncol = 256;
vaddr->nrow = 256;
vaddr->pitch = 256 * 4;
return vaddr;
}
//************************************************************************
@ -84,6 +88,11 @@ static void genTextures(void)
{
int ipolate = 1;
if ( gltexture )
{
printf("GL Texture already exists\n");
return;
}
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &gltexture);
@ -131,11 +140,18 @@ static int open_window(void)
XStoreName(dpy, win, "FCEUX VIEWPORT");
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if ( glc == NULL )
{
printf("Error: glXCreateContext Failed\n");
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if ( glc == NULL )
{
printf("Error: glXCreateContext Failed\n");
}
}
else
{
printf("GLX Context Already Exists\n");
}
glXMakeCurrent(dpy, win, glc);
@ -166,11 +182,13 @@ static void print_pixbuf(void)
//************************************************************************
static void render_image(void)
{
int l=0, r=GLX_NES_WIDTH;
int t=0, b=GLX_NES_HEIGHT;
static int null_glc_error = 0;
int l=0, r=glx_shm->ncol;
int t=0, b=glx_shm->nrow;
float xscale = (float)screen_width / (float)glx_shm->ncol;
float yscale = (float)screen_height / (float)glx_shm->nrow;
float xscale = (float)screen_width / (float)GLX_NES_WIDTH;
float yscale = (float)screen_height / (float)GLX_NES_HEIGHT;
if (xscale < yscale )
{
yscale = xscale;
@ -184,6 +202,17 @@ static void render_image(void)
int sx=(screen_width-rw)/2;
int sy=(screen_height-rh)/2;
if ( glc == NULL )
{
if ( !null_glc_error )
{
printf("Error: GLX Render has NULL Context\n");
null_glc_error = 1;
}
return;
}
null_glc_error = 0;
glXMakeCurrent(dpy, win, glc);
//printf("Viewport: (%i,%i) %i %i %i %i \n",
// screen_width, screen_height, sx, sy, rw, rh );
@ -251,7 +280,7 @@ static int mainWindowLoop(void)
//glViewport(0, 0, gwa.width, gwa.height);
//DrawAQuad();
glXSwapBuffers(dpy, win);
printf("Expose\n");
//printf("Expose\n");
}
else if (xev.type == ConfigureNotify)
{
@ -267,7 +296,7 @@ static int mainWindowLoop(void)
//genTextures();
printf("Resize Request: (%i,%i)\n", screen_width, screen_height );
//printf("Resize Request: (%i,%i)\n", screen_width, screen_height );
render_image();
//glViewport(0, 0, gwa.width, gwa.height);
//DrawAQuad();
@ -350,6 +379,8 @@ int init_gtk3_GLXContext( void )
{
XWindowAttributes xattrb;
printf("Init GLX Context\n");
GdkWindow *gdkWin = gtk_widget_get_window(evbox);
if ( gdkWin == NULL )
@ -390,11 +421,14 @@ int init_gtk3_GLXContext( void )
printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
}
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if ( glc == NULL )
{
printf("Error: glXCreateContext Failed\n");
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if ( glc == NULL )
{
printf("Error: glXCreateContext Failed\n");
}
}
glXMakeCurrent(dpy, win, glc);
@ -412,6 +446,27 @@ int init_gtk3_GLXContext( void )
return 0;
}
//************************************************************************
int destroy_gtk3_GLXContext(void)
{
if ( dpy != NULL )
{
glXMakeCurrent(dpy, None, NULL);
}
if (gltexture)
{
printf("Destroying GLX Texture\n");
glDeleteTextures(1, &gltexture);
gltexture=0;
}
if ( glc != NULL )
{
printf("Destroying GLX Context\n");
glXDestroyContext(dpy, glc); glc = NULL;
}
return 0;
}
//************************************************************************
int gtk3_glx_render(void)
{
screen_width = gtk_draw_area_width;

View File

@ -11,6 +11,7 @@
int spawn_glxwin( int flags );
int init_gtk3_GLXContext( void );
int destroy_gtk3_GLXContext( void );
int gtk3_glx_render(void);
@ -25,6 +26,10 @@ struct glxwin_shm_t
uint32_t blit_count;
sem_t sem;
int ncol;
int nrow;
int pitch;
// Pass Key Events back to GTK Gui
struct
{
@ -56,6 +61,11 @@ struct glxwin_shm_t
} guiEvent;
uint32_t pixbuf[65536]; // 256 x 256
void clear_pixbuf(void)
{
memset( pixbuf, 0, sizeof(pixbuf) );
}
};
extern glxwin_shm_t *glx_shm;

View File

@ -85,6 +85,8 @@ unsigned int gtk_draw_area_height = NES_HEIGHT;
static GtkTreeStore *hotkey_store = NULL;
static cairo_surface_t *cairo_surface = NULL;
static int *cairo_pix_remapper = NULL;
static int numRendLines = 0;
static void cairo_recalc_mapper(void);
static gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data);
@ -3104,6 +3106,7 @@ union cairo_pixel_t
static void transferPix2CairoSurface(void)
{
union cairo_pixel_t *p;
union cairo_pixel_t *g;
int x, y, i,j, w, h;
if ( cairo_surface == NULL )
@ -3112,10 +3115,16 @@ static void transferPix2CairoSurface(void)
}
cairo_surface_flush( cairo_surface );
if ( numRendLines != glx_shm->nrow )
{
cairo_recalc_mapper();
}
w = cairo_image_surface_get_width (cairo_surface);
h = cairo_image_surface_get_height (cairo_surface);
p = (cairo_pixel_t*)cairo_image_surface_get_data (cairo_surface);
g = (cairo_pixel_t*)glx_shm->pixbuf;
i=0;
for (y=0; y<h; y++)
@ -3130,7 +3139,15 @@ static void transferPix2CairoSurface(void)
}
else
{
p[i].u32 = glx_shm->pixbuf[j];
// RGBA to ARGB
#ifdef LSB_FIRST
p[i].u8[2] = g[j].u8[0];
p[i].u8[1] = g[j].u8[1];
p[i].u8[0] = g[j].u8[2];
p[i].u8[3] = g[j].u8[3];
#else
p[i].u32 = g[j].u32;
#endif
//p[i].u32 = 0xffffffff;
}
i++;
@ -3268,7 +3285,7 @@ static void cairo_recalc_mapper(void)
{
int w, h, s;
int i, j, x, y;
int sw, sh, rx, ry;
int sw, sh, rx, ry, gw, gh;
int llx, lly, urx, ury;
float sx, sy, nw, nh;
@ -3276,6 +3293,9 @@ static void cairo_recalc_mapper(void)
h = cairo_image_surface_get_height (cairo_surface);
s = w * h * 4;
gw = glx_shm->ncol;
gh = glx_shm->nrow;
if ( cairo_pix_remapper != NULL )
{
::free( cairo_pix_remapper ); cairo_pix_remapper = NULL;
@ -3289,8 +3309,8 @@ static void cairo_recalc_mapper(void)
}
memset( cairo_pix_remapper, 0, s );
sx = (float)w / (float)GLX_NES_WIDTH;
sy = (float)h / (float)GLX_NES_HEIGHT;
sx = (float)w / (float)gw;
sy = (float)h / (float)gh;
if (sx < sy )
{
@ -3301,8 +3321,8 @@ static void cairo_recalc_mapper(void)
sx = sy;
}
sw = (int) ( (float)GLX_NES_WIDTH * sx );
sh = (int) ( (float)GLX_NES_HEIGHT * sy );
sw = (int) ( (float)gw * sx );
sh = (int) ( (float)gh * sy );
llx = (w - sw) / 2;
lly = (h - sh) / 2;
@ -3332,8 +3352,8 @@ static void cairo_recalc_mapper(void)
nw = (float)(x - llx) / (float)sw;
nh = (float)(y - lly) / (float)sh;
rx = (int)((float)GLX_NES_WIDTH * nw);
ry = (int)((float)GLX_NES_HEIGHT * nh);
rx = (int)((float)gw * nw);
ry = (int)((float)gh * nh);
if ( rx < 0 )
{
@ -3353,7 +3373,6 @@ static void cairo_recalc_mapper(void)
}
j = (ry * GLX_NES_WIDTH) + rx;
//j = (rx * GLX_NES_WIDTH) + ry;
cairo_pix_remapper[i] = j; i++;
@ -3362,9 +3381,10 @@ static void cairo_recalc_mapper(void)
}
}
}
numRendLines = gh;
}
static void cairo_handle_resize( int width, int height )
static void cairo_handle_resize(void)
{
int w, h;
cairo_format_t cairo_format;
@ -3376,18 +3396,15 @@ static void cairo_handle_resize( int width, int height )
w = gtk_widget_get_allocated_width( evbox );
h = gtk_widget_get_allocated_height( evbox );
//cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h );
printf("Cairo Surface: %p \n", cairo_surface );
cairo_format = cairo_image_surface_get_format( cairo_surface );
printf("Cairo Format: %i \n", cairo_format );
//printf("Cairo Format: %i \n", cairo_format );
if ( cairo_format == CAIRO_FORMAT_ARGB32 )
{
printf("Cairo Format: ARGB32 \n" );
}
cairo_recalc_mapper();
guiClearSurface();
@ -3397,6 +3414,54 @@ static void cairo_handle_resize( int width, int height )
//cairo_surface_mark_dirty( cairo_surface );
}
int destroy_gui_video( void )
{
printf("Destroy GUI Video\n");
destroy_cairo_screen();
destroy_gtk3_GLXContext();
return 0;
}
int init_gui_video( int use_openGL )
{
drawAreaGL = use_openGL;
useCairoDraw = !drawAreaGL;
if ( use_openGL )
{
destroy_cairo_screen();
init_gtk3_GLXContext();
}
else
{
destroy_gtk3_GLXContext();
init_cairo_screen();
}
return 0;
}
void init_cairo_screen(void)
{
cairo_handle_resize();
}
void destroy_cairo_screen(void)
{
if (cairo_surface)
{
printf("Destroying Cairo Surface\n");
cairo_surface_destroy (cairo_surface); cairo_surface = NULL;
}
if ( cairo_pix_remapper != NULL )
{
printf("Destroying Cairo Pixel Remapper\n");
::free( cairo_pix_remapper ); cairo_pix_remapper = NULL;
}
}
gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data)
{
@ -3435,9 +3500,9 @@ gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data)
if (yscale > xscale)
yscale = xscale;
if ( useCairoDraw )
if ( useCairoDraw && winsize_changed )
{
cairo_handle_resize( width, height );
cairo_handle_resize();
}
//TODO if openGL make these integers
@ -3518,7 +3583,10 @@ drawAreaRealizeCB (GtkWidget *widget,
{
printf("Draw Area Realize\n");
init_gtk3_GLXContext();
if ( drawAreaGL )
{
init_gtk3_GLXContext();
}
}

View File

@ -89,4 +89,9 @@ int InitGTKSubsystem(int argc, char** argv);
uint32_t *getGuiPixelBuffer( int *w, int *h, int *s );
int guiPixelBufferReDraw(void);
int init_gui_video( int use_openGL );
int destroy_gui_video( void );
void init_cairo_screen(void);
void destroy_cairo_screen(void);
#endif // ifndef FCEUX_GUI_H

View File

@ -23,6 +23,7 @@
#include "sdl.h"
#include "sdl-opengl.h"
#include "glxwin.h"
#include "../common/vidblit.h"
#include "../../fceu.h"
#include "../../version.h"
@ -80,6 +81,7 @@ static int s_fullscreen = 0;
static int noframe = 0;
static int s_nativeWidth = -1;
static int s_nativeHeight = -1;
static int initBlitToHighDone = 0;
#define NWIDTH (256 - (s_clipSides ? 16 : 0))
#define NOFFSET (s_clipSides ? 8 : 0)
@ -136,6 +138,13 @@ bool FCEUD_ShouldDrawInputAids()
int
KillVideo()
{
printf("Killing Video\n");
if ( glx_shm != NULL )
{
glx_shm->clear_pixbuf();
}
// if the IconSurface has been initialized, destroy it
if (s_IconSurface)
{
@ -143,51 +152,53 @@ KillVideo()
s_IconSurface=0;
}
//destroy_gui_video();
// return failure if the video system was not initialized
if(s_inited == 0)
if (s_inited == 0)
return -1;
// if the rest of the system has been initialized, shut it down
#ifdef OPENGL
// check for OpenGL and shut it down
if(s_useOpenGL)
{
KillOpenGL();
}
else
#endif
{
// shut down the system that converts from 8 to 16/32 bpp
if (s_curbpp > 8)
{
KillBlitToHigh();
}
}
//#ifdef OPENGL
// // check for OpenGL and shut it down
// if(s_useOpenGL)
// {
// KillOpenGL();
// }
// else
//#endif
// {
// // shut down the system that converts from 8 to 16/32 bpp
// if (s_curbpp > 8)
// {
// KillBlitToHigh();
// }
// }
#if SDL_VERSION_ATLEAST(2, 0, 0)
if ( s_screen != NULL )
{
SDL_FreeSurface( s_screen ); s_screen = NULL;
}
if ( s_texture != NULL )
{
SDL_DestroyTexture( s_texture ); s_texture = NULL;
}
if ( s_renderer != NULL )
{
SDL_DestroyRenderer( s_renderer ); s_renderer = NULL;
}
if ( s_window != NULL )
{
SDL_DestroyWindow( s_window );
s_window = NULL;
}
#endif
//#if SDL_VERSION_ATLEAST(2, 0, 0)
//
// if ( s_screen != NULL )
// {
// SDL_FreeSurface( s_screen ); s_screen = NULL;
// }
//
// if ( s_texture != NULL )
// {
// SDL_DestroyTexture( s_texture ); s_texture = NULL;
// }
//
// if ( s_renderer != NULL )
// {
// SDL_DestroyRenderer( s_renderer ); s_renderer = NULL;
// }
//
// if ( s_window != NULL )
// {
// SDL_DestroyWindow( s_window );
// s_window = NULL;
// }
//
//#endif
// shut down the SDL video sub-system
//SDL_QuitSubSystem(SDL_INIT_VIDEO);
@ -198,7 +209,7 @@ KillVideo()
// this variable contains information about the special scaling filters
static int s_sponge;
static int s_sponge = 0;
/**
* These functions determine an appropriate scale factor for fullscreen/
@ -240,7 +251,7 @@ int InitVideo(FCEUGI *gi)
#ifdef OPENGL
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
#endif
g_config->getOption("SDL.SpecialFilter", &s_sponge);
//g_config->getOption("SDL.SpecialFilter", &s_sponge);
g_config->getOption("SDL.XStretch", &xstretch);
g_config->getOption("SDL.YStretch", &ystretch);
//g_config->getOption("SDL.LastXRes", &xres);
@ -248,10 +259,11 @@ int InitVideo(FCEUGI *gi)
g_config->getOption("SDL.ClipSides", &s_clipSides);
g_config->getOption("SDL.NoFrame", &noframe);
g_config->getOption("SDL.ShowFPS", &show_fps);
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
//g_config->getOption("SDL.XScale", &s_exs);
//g_config->getOption("SDL.YScale", &s_eys);
uint32_t rmask, gmask, bmask;
s_sponge = 0;
s_exs = 1.0;
s_eys = 1.0;
xres = gtk_draw_area_width;
@ -271,6 +283,8 @@ int InitVideo(FCEUGI *gi)
//}
#endif
init_gui_video( s_useOpenGL );
s_inited = 1;
// check to see if we are showing FPS
@ -280,9 +294,6 @@ int InitVideo(FCEUGI *gi)
rmask = 0x000000FF;
gmask = 0x0000FF00;
bmask = 0x00FF0000;
//rmask = 0x00FF0000;
//gmask = 0x0000FF00;
//bmask = 0x000000FF;
#else
rmask = 0x00FF0000;
gmask = 0x0000FF00;
@ -356,36 +367,36 @@ int InitVideo(FCEUGI *gi)
//s_paletterefresh = 1;
// -Video Modes Tag-
if (s_sponge)
{
if (s_sponge <= 3 && s_sponge >= 1)
{
s_exs = s_eys = 2;
}
else if (s_sponge >=4 && s_sponge <= 5)
{
s_exs = s_eys = 3;
}
else if (s_sponge >= 6 && s_sponge <= 8)
{
s_exs = s_eys = s_sponge - 4;
}
else if(s_sponge == 9)
{
s_exs = s_eys = 3;
}
else
{
s_exs = s_eys = 1;
}
if(s_sponge == 3) {
xres = 301 * s_exs;
}
s_eefx = 0;
//if(s_sponge == 1 || s_sponge == 4) {
// desbpp = 32;
//}
}
//if (s_sponge)
//{
// if (s_sponge <= 3 && s_sponge >= 1)
// {
// s_exs = s_eys = 2;
// }
// else if (s_sponge >=4 && s_sponge <= 5)
// {
// s_exs = s_eys = 3;
// }
// else if (s_sponge >= 6 && s_sponge <= 8)
// {
// s_exs = s_eys = s_sponge - 4;
// }
// else if(s_sponge == 9)
// {
// s_exs = s_eys = 3;
// }
// else
// {
// s_exs = s_eys = 1;
// }
// if(s_sponge == 3) {
// xres = 301 * s_exs;
// }
// s_eefx = 0;
// //if(s_sponge == 1 || s_sponge == 4) {
// // desbpp = 32;
// //}
//}
//int scrw = NWIDTH * s_exs;
//if(s_sponge == 3) {
@ -414,13 +425,15 @@ int InitVideo(FCEUGI *gi)
}
#endif
if (s_curbpp > 8)
if ( !initBlitToHighDone )
{
InitBlitToHigh(s_curbpp >> 3,
rmask,
gmask,
bmask,
s_eefx, s_sponge, 0);
initBlitToHighDone = 1;
}
return 0;
@ -466,7 +479,7 @@ InitVideo(FCEUGI *gi)
// check for OpenGL and set the global flags
#ifdef OPENGL
if(s_useOpenGL && !s_sponge) {
if (s_useOpenGL && !s_sponge) {
flags = SDL_OPENGL;
}
#endif
@ -941,7 +954,9 @@ BlitScreen(uint8 *XBuf)
//dest = (uint8*)TmpScreen->pixels;
dest = (uint8*)getGuiPixelBuffer( &w, &h, &pitch );
pitch = w * 4;
glx_shm->ncol = NWIDTH;
glx_shm->nrow = s_tlines;
glx_shm->pitch = pitch;
if ( dest == NULL ) return;
@ -954,6 +969,7 @@ BlitScreen(uint8 *XBuf)
// }
//}
//Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1);
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1);
// XXX soules - again, I'm surprised SDL can't handle this