Implementing secondary cairo interface.

This commit is contained in:
Matthew Budd 2020-06-07 13:58:09 -04:00
parent 5bbbd0e8e7
commit 79b796f790
3 changed files with 213 additions and 66 deletions

View File

@ -35,7 +35,7 @@ static XWindowAttributes gwa;
static XEvent xev;
static GLuint gltexture = 0;
static int spawn_new_window = 0;
static int spawn_new_window = 1;
glxwin_shm_t *glx_shm = NULL;

View File

@ -82,11 +82,9 @@ static char useCairoDraw = 0;
static int drawAreaGL = 0;
unsigned int gtk_draw_area_width = NES_WIDTH;
unsigned int gtk_draw_area_height = NES_HEIGHT;
static unsigned int gtk_win_width = 0;
static unsigned int gtk_win_height = 0;
static int gtk_win_menu_ysize = 30;
static GtkTreeStore *hotkey_store = NULL;
static cairo_surface_t *cairo_surface = NULL;
static int *cairo_pix_remapper = NULL;
static gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data);
@ -3097,6 +3095,53 @@ gint handleMouseClick (GtkWidget * widget, GdkEvent * event,
return 0;
}
union cairo_pixel_t
{
uint32_t u32;
uint8_t u8[4];
};
static void transferPix2CairoSurface(void)
{
union cairo_pixel_t *p;
int x, y, i,j, w, h;
if ( cairo_surface == NULL )
{
return;
}
cairo_surface_flush( cairo_surface );
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);
i=0;
for (y=0; y<h; y++)
{
for (x=0; x<w; x++)
{
j = cairo_pix_remapper[i];
if ( j < 0 )
{
p[i].u32 = 0;
}
else
{
p[i].u32 = glx_shm->pixbuf[j];
//p[i].u32 = 0xffffffff;
}
i++;
}
}
cairo_surface_mark_dirty( cairo_surface );
gtk_widget_queue_draw( evbox );
}
uint32_t *getGuiPixelBuffer( int *w, int *h, int *s )
{
if ( w ) *w = GLX_NES_WIDTH;
@ -3136,14 +3181,15 @@ int guiPixelBufferReDraw(void)
{
glx_shm->blit_count++;
gtk3_glx_render();
if ( cairo_surface != NULL )
if ( useCairoDraw )
{
cairo_surface_mark_dirty( cairo_surface );
gtk_widget_queue_draw( evbox );
transferPix2CairoSurface();
}
else
{
gtk3_glx_render();
}
return 0;
}
@ -3218,19 +3264,119 @@ static void loadPixelTestPattern(void)
}
static void cairo_recalc_mapper(void)
{
int w, h, s;
int i, j, x, y;
int sw, sh, rx, ry;
int llx, lly, urx, ury;
float sx, sy, nw, nh;
w = cairo_image_surface_get_width (cairo_surface);
h = cairo_image_surface_get_height (cairo_surface);
s = w * h * 4;
if ( cairo_pix_remapper != NULL )
{
::free( cairo_pix_remapper ); cairo_pix_remapper = NULL;
}
cairo_pix_remapper = (int*)malloc(s);
if ( cairo_pix_remapper == NULL )
{
printf("Error: Failed to allocate memory for Pixel Surface Remapper\n");
return;
}
memset( cairo_pix_remapper, 0, s );
sx = (float)w / (float)GLX_NES_WIDTH;
sy = (float)h / (float)GLX_NES_HEIGHT;
if (sx < sy )
{
sy = sx;
}
else
{
sx = sy;
}
sw = (int) ( (float)GLX_NES_WIDTH * sx );
sh = (int) ( (float)GLX_NES_HEIGHT * sy );
llx = (w - sw) / 2;
lly = (h - sh) / 2;
urx = llx + sw;
ury = lly + sh;
i=0;
for (y=0; y<h; y++)
{
if ( (y < lly) || (y > ury) )
{
for (x=0; x<w; x++)
{
cairo_pix_remapper[i] = -1; i++;
}
}
else
{
for (x=0; x<w; x++)
{
if ( (x < llx) || (x > urx) )
{
cairo_pix_remapper[i] = -1; i++;
}
else
{
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);
if ( rx < 0 )
{
rx = 0;
}
else if ( rx >= GLX_NES_WIDTH )
{
rx = GLX_NES_WIDTH-1;
}
if ( ry < 0 )
{
ry = 0;
}
else if ( ry >= GLX_NES_HEIGHT )
{
ry = GLX_NES_HEIGHT-1;
}
j = (ry * GLX_NES_WIDTH) + rx;
//j = (rx * GLX_NES_WIDTH) + ry;
cairo_pix_remapper[i] = j; i++;
//printf("Remap: (%i,%i)=%i (%i,%i)=%i \n", x,y,i, rx,ry,j );
}
}
}
}
}
static void cairo_handle_resize( int width, int height )
{
int w, h;
cairo_format_t cairo_format;
if (cairo_surface)
{
cairo_surface_destroy (cairo_surface); cairo_surface = NULL;
}
w = gtk_widget_get_allocated_width( evbox );
h = gtk_widget_get_allocated_height( evbox );
cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24,
gtk_widget_get_allocated_width (evbox),
gtk_widget_get_allocated_height (evbox) );
cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h );
printf("Cairo Surface: %p \n", cairo_surface );
@ -3242,9 +3388,13 @@ static void cairo_handle_resize( int width, int height )
{
printf("Cairo Format: ARGB32 \n" );
}
cairo_recalc_mapper();
guiClearSurface();
cairo_surface_mark_dirty( cairo_surface );
transferPix2CairoSurface();
//cairo_surface_mark_dirty( cairo_surface );
}
@ -3254,31 +3404,26 @@ gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data)
// of the GTK window as possible
// get new window width/height
int width, height, draw_width, draw_height, winsize_changed = 0;
int width, height, winsize_changed = 0;
width = event->configure.width;
height = event->configure.height;
//printf ("DEBUG: Configure new window size: %dx%d\n", width, height);
winsize_changed = (width != gtk_win_width) || (height != gtk_win_height);
gtk_win_width = width;
gtk_win_height = height;
winsize_changed = 0;
// get width/height multipliers
double xscale = width / (double) NES_WIDTH;
double yscale = height / (double) NES_HEIGHT;
draw_width = gtk_win_width;
draw_height = gtk_win_height - gtk_win_menu_ysize;
//printf("DRAW: %ix%i MenuY: %i \n", draw_width, draw_height, gtk_win_menu_ysize );
if ( (draw_width != gtk_draw_area_width) || (draw_height != gtk_draw_area_height) )
if ( (width != gtk_draw_area_width) || (height != gtk_draw_area_height) )
{
winsize_changed = 1;
}
gtk_draw_area_width = draw_width;
gtk_draw_area_height = draw_height;
gtk_draw_area_width = width;
gtk_draw_area_height = height;
if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH;
if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT;
@ -3292,7 +3437,7 @@ gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data)
if ( useCairoDraw )
{
cairo_handle_resize( draw_width, draw_height );
cairo_handle_resize( width, height );
}
//TODO if openGL make these integers
@ -3340,14 +3485,6 @@ static gboolean cairo_clear_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
static gboolean cairo_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
{
gtk_draw_area_width = gtk_widget_get_allocated_width (widget);
gtk_draw_area_height = gtk_widget_get_allocated_height (widget);
if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH;
if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT;
gtk_win_menu_ysize = gtk_win_height - gtk_draw_area_height;
cairo_set_source_surface (cr, cairo_surface, 0, 0);
cairo_paint (cr);
@ -3357,6 +3494,12 @@ static gboolean cairo_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
static gboolean draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
{
gtk_draw_area_width = gtk_widget_get_allocated_width (widget);
gtk_draw_area_height = gtk_widget_get_allocated_height (widget);
if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH;
if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT;
if ( useCairoDraw )
{
cairo_draw_cb( widget, cr, data );
@ -3419,7 +3562,8 @@ int InitGTKSubsystem (int argc, char **argv)
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
#endif
drawAreaGL = s_useOpenGL;
drawAreaGL = s_useOpenGL;
useCairoDraw = !drawAreaGL;
evbox = gtk_drawing_area_new ();

View File

@ -908,7 +908,8 @@ BlitScreen(uint8 *XBuf)
//}
// refresh the palette if required
if(s_paletterefresh) {
if (s_paletterefresh)
{
RedoPalette();
s_paletterefresh = 0;
}
@ -945,34 +946,36 @@ BlitScreen(uint8 *XBuf)
if ( dest == NULL ) return;
//if(s_fullscreen) { // Always do this calculation now. Screen resolution is always provided.
xo = (int)(((w - NWIDTH * s_exs)) / 2);
dest += xo * (s_curbpp >> 3);
if(h > (s_tlines * s_eys)) {
yo = (int)((h - s_tlines * s_eys) / 2);
dest += yo * pitch;
}
// xo = (int)(((w - NWIDTH * s_exs)) / 2);
// dest += xo * (s_curbpp >> 3);
// if(h > (s_tlines * s_eys)) {
// yo = (int)((h - s_tlines * s_eys) / 2);
// dest += yo * pitch;
// }
//}
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1);
// XXX soules - again, I'm surprised SDL can't handle this
// perform the blit, converting bpp if necessary
if(s_curbpp > 8) {
if(s_useOpenGL) {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
pitch, 1, 1);
} else {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
pitch, (int)s_exs, (int)s_eys);
}
} else {
if(s_BlitBuf) {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
pitch, 1, 1, 0, s_sponge);
} else {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
pitch, (int)s_exs, (int)s_eys,
s_eefx, s_sponge);
}
}
//if(s_curbpp > 8) {
// if(s_useOpenGL) {
// Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
// pitch, 1, 1);
// } else {
// Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
// pitch, (int)s_exs, (int)s_eys);
// }
//} else {
// if(s_BlitBuf) {
// Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
// pitch, 1, 1, 0, s_sponge);
// } else {
// Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
// pitch, (int)s_exs, (int)s_eys,
// s_eefx, s_sponge);
// }
//}
//print_pixels();
//
guiPixelBufferReDraw();
@ -982,12 +985,12 @@ BlitScreen(uint8 *XBuf)
// SDL_UnlockSurface(TmpScreen);
//}
int scrw;
if(s_sponge == 3) { // NTSC 2x
scrw = 301;
} else {
scrw = NWIDTH;
}
//int scrw;
//if(s_sponge == 3) { // NTSC 2x
// scrw = 301;
//} else {
// scrw = NWIDTH;
//}
// if we have a hardware video buffer, do a fast video->video copy
//if(s_BlitBuf) {