diff --git a/src/drivers/sdl/glxwin.cpp b/src/drivers/sdl/glxwin.cpp index 12a84801..6e496dfe 100644 --- a/src/drivers/sdl/glxwin.cpp +++ b/src/drivers/sdl/glxwin.cpp @@ -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; diff --git a/src/drivers/sdl/glxwin.h b/src/drivers/sdl/glxwin.h index ed1b64e5..2f2fad40 100644 --- a/src/drivers/sdl/glxwin.h +++ b/src/drivers/sdl/glxwin.h @@ -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; diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 796ca4be..90e006ac 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -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; ypixbuf[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(); + } } diff --git a/src/drivers/sdl/gui.h b/src/drivers/sdl/gui.h index 73147ee9..b3313bb6 100644 --- a/src/drivers/sdl/gui.h +++ b/src/drivers/sdl/gui.h @@ -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 diff --git a/src/drivers/sdl/sdl-video.cpp b/src/drivers/sdl/sdl-video.cpp index 7a42a3c2..bc555fcb 100644 --- a/src/drivers/sdl/sdl-video.cpp +++ b/src/drivers/sdl/sdl-video.cpp @@ -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