static void opengl_swap_synchronous(void) { if (g_sync_method == SYNC_SWAP) { swap_opengl_buffers(); } else if (g_sync_method == SYNC_SWAP_FINISH) { swap_opengl_buffers(); gl_finish(); } else if (g_sync_method == SYNC_FINISH_SWAP_FINISH) { gl_finish(); swap_opengl_buffers(); gl_finish(); } else if (g_sync_method == SYNC_SLEEP_SWAP_FINISH) { sleep_until_vsync(); swap_opengl_buffers(); gl_finish(); } else if (g_sync_method == SYNC_FINISH_SLEEP_SWAP_FINISH) { gl_finish(); sleep_until_vsync(); swap_opengl_buffers(); gl_finish(); } else if (g_sync_method == SYNC_SWAP_FENCE) { swap_opengl_buffers(); opengl_fence(FENCE_SET); glFlush(); opengl_fence(FENCE_WAIT); } else if (g_sync_method == SYNC_SWAP_SLEEP_FENCE) { swap_opengl_buffers(); sleep_until_vsync(); opengl_fence(FENCE_SET); glFlush(); opengl_fence(FENCE_WAIT); } }
void plat_sdl_finish(void) { if (plat_sdl_overlay != NULL) { SDL_FreeYUVOverlay(plat_sdl_overlay); plat_sdl_overlay = NULL; } if (plat_sdl_gl_active) { gl_finish(); plat_sdl_gl_active = 0; } // restore back to initial resolution // resolves black screen issue on R-Pi if (strcmp(vid_drv_name, "x11") != 0) SDL_SetVideoMode(fs_w, fs_h, 16, SDL_SWSURFACE); SDL_Quit(); }
void plat_sdl_event_handler(void *event_) { static int was_active; SDL_Event *event = event_; switch (event->type) { case SDL_VIDEORESIZE: //printf("resize %dx%d\n", event->resize.w, event->resize.h); if (plat_target.vout_method != 0 && !plat_target.vout_fullscreen && !old_fullscreen) { window_w = event->resize.w; window_h = event->resize.h; plat_sdl_change_video_mode(0, 0, 1); } break; case SDL_ACTIVEEVENT: if (event->active.gain && !was_active) { if (plat_sdl_overlay != NULL) { SDL_Rect dstrect = { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); } else if (plat_sdl_gl_active) { if (gl_quirks & GL_QUIRK_ACTIVATE_RECREATE) { gl_finish(); plat_sdl_gl_active = (gl_init(display, window, &gl_quirks) == 0); } gl_flip(NULL, 0, 0); } // else SDL takes care of it } was_active = event->active.gain; break; case SDL_QUIT: if (plat_sdl_quit_cb != NULL) plat_sdl_quit_cb(); break; } }
/* w, h is layer resolution */ int plat_sdl_change_video_mode(int w, int h, int force) { static int prev_w, prev_h; if (w == 0) w = prev_w; else prev_w = w; if (h == 0) h = prev_h; else prev_h = h; plat_target.vout_method=vout_mode_overlay; // invalid method might come from config.. if (plat_target.vout_method != 0 && plat_target.vout_method != vout_mode_overlay && plat_target.vout_method != vout_mode_gl) { fprintf(stderr, "invalid vout_method: %d\n", plat_target.vout_method); plat_target.vout_method = 0; } // skip GL recreation if window doesn't change - avoids flicker if (plat_target.vout_method == vout_mode_gl && plat_sdl_gl_active && plat_target.vout_fullscreen == old_fullscreen && !force) { return 0; } if (plat_sdl_overlay != NULL) { SDL_FreeYUVOverlay(plat_sdl_overlay); plat_sdl_overlay = NULL; } if (plat_sdl_gl_active) { gl_finish(); plat_sdl_gl_active = 0; } if (plat_target.vout_method != 0) { Uint32 flags = SDL_RESIZABLE | SDL_SWSURFACE; int win_w = window_w; int win_h = window_h; if (plat_target.vout_fullscreen) { flags |= SDL_FULLSCREEN; win_w = fs_w; win_h = fs_h; } // XXX: workaround some occasional mysterious deadlock in SDL_SetVideoMode // (seen on r-pi) SDL_PumpEvents(); unsigned int user_width = 0; sscanf(getenv("PCSX_WIDTH"), "%d", &user_width); if(user_width == 0) user_width=win_h; plat_sdl_screen = SDL_SetVideoMode(/*win_w*/ /*win_h*4/3*/ /*640*/ user_width*4/3, /*win_h*/ /*512*/ user_width, 0, flags); if (plat_sdl_screen == NULL) { fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); plat_target.vout_method = 0; } } if (plat_target.vout_method == vout_mode_overlay) { plat_sdl_overlay = SDL_CreateYUVOverlay(w, h, SDL_UYVY_OVERLAY, plat_sdl_screen); if (plat_sdl_overlay != NULL) { if ((long)plat_sdl_overlay->pixels[0] & 3) fprintf(stderr, "warning: overlay pointer is unaligned\n"); plat_sdl_overlay_clear(); } else { fprintf(stderr, "warning: could not create overlay.\n"); plat_target.vout_method = 0; } } else if (plat_target.vout_method == vout_mode_gl) { plat_sdl_gl_active = (gl_init(display, window, &gl_quirks) == 0); if (!plat_sdl_gl_active) { fprintf(stderr, "warning: could not init GL.\n"); plat_target.vout_method = 0; } } if (plat_target.vout_method == 0) { SDL_PumpEvents(); plat_sdl_screen = SDL_SetVideoMode(w, h, 16, SDL_SWSURFACE); if (plat_sdl_screen == NULL) { fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); return -1; } } old_fullscreen = plat_target.vout_fullscreen; if (plat_sdl_resize_cb != NULL) plat_sdl_resize_cb(plat_sdl_screen->w, plat_sdl_screen->h); return 0; }
int plat_sdl_init(void) { static const char *vout_list[] = { NULL, NULL, NULL, NULL }; const SDL_VideoInfo *info; SDL_SysWMinfo wminfo; int overlay_works = 0; int gl_works = 0; int i, ret, h; ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); if (ret != 0) { fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); return -1; } info = SDL_GetVideoInfo(); if (info != NULL) { fs_w = info->current_w; fs_h = info->current_h; printf("plat_sdl: using %dx%d as fullscreen resolution\n", fs_w, fs_h); } g_menuscreen_w = 640; if (fs_w != 0 && g_menuscreen_w > fs_w) g_menuscreen_w = fs_w; g_menuscreen_h = 480; if (fs_h != 0) { h = fs_h; if (info && info->wm_available && h > WM_DECORATION_H) h -= WM_DECORATION_H; if (g_menuscreen_h > h) g_menuscreen_h = h; } ret = plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 1); if (ret != 0) { plat_sdl_screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE); if (plat_sdl_screen == NULL) { fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); goto fail; } if (plat_sdl_screen->w < 320 || plat_sdl_screen->h < 240) { fprintf(stderr, "resolution %dx%d is too small, sorry.\n", plat_sdl_screen->w, plat_sdl_screen->h); goto fail; } } g_menuscreen_w = window_w = plat_sdl_screen->w; g_menuscreen_h = window_h = plat_sdl_screen->h; // overlay/gl require native bpp in some cases.. plat_sdl_screen = SDL_SetVideoMode(g_menuscreen_w, g_menuscreen_h, 0, SDL_SWSURFACE); if (plat_sdl_screen == NULL) { fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); goto fail; } plat_sdl_overlay = SDL_CreateYUVOverlay(plat_sdl_screen->w, plat_sdl_screen->h, SDL_UYVY_OVERLAY, plat_sdl_screen); if (plat_sdl_overlay != NULL) { printf("plat_sdl: overlay: fmt %x, planes: %d, pitch: %d, hw: %d\n", plat_sdl_overlay->format, plat_sdl_overlay->planes, *plat_sdl_overlay->pitches, plat_sdl_overlay->hw_overlay); if (plat_sdl_overlay->hw_overlay) overlay_works = 1; else fprintf(stderr, "warning: video overlay is not hardware accelerated, " "not going to use it.\n"); SDL_FreeYUVOverlay(plat_sdl_overlay); plat_sdl_overlay = NULL; } else fprintf(stderr, "overlay is not available.\n"); // 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; } } #endif ret = gl_init(display, window, &gl_quirks); if (ret == 0) { gl_works = 1; gl_finish(); } i = 0; vout_list[i++] = "SDL Window"; if (overlay_works) { plat_target.vout_method = vout_mode_overlay = i; vout_list[i++] = "Video Overlay"; } if (gl_works) { plat_target.vout_method = vout_mode_gl = i; vout_list[i++] = "OpenGL"; } plat_target.vout_methods = vout_list; return 0; fail: SDL_Quit(); return -1; }
/*! To set a valid raster position outside the viewport, first set a valid raster position inside the viewport, then call glBitmap with NULL as the bitmap parameter and with xmove and ymove set to the offsets of the new raster position. This technique is useful when panning an image around the viewport. (see http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml and http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml) */ void ImageView::GLDraw() { #ifdef USE_OPEN_GL_WINDOW if (!valid()) GLViewSetup(); #else gl_start(); #endif // Invert image //glPixelZoom(1.0f, -1.0f); glPixelZoom((float) m_scaling, (float) -m_scaling); // Set image origin glRasterPos2i(0, h()); // Check that the raster position is valid GLboolean rasVal; glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &rasVal); if (!rasVal) { ShowError("Invalid raster position. No image will be shown"); } // If image is scaled down, the view needs to be fully erased //if (m_zoom < 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); m_mutex.Lock(); if (m_curByteImage.is_contiguous() && m_curByteImage.size() > 0) glDrawPixels(m_curByteImage.ni(), m_curByteImage.nj(), GL_LUMINANCE, GL_UNSIGNED_BYTE, m_curByteImage.top_left_ptr()); else if (m_curRGBImage.is_contiguous()) glDrawPixels(m_curRGBImage.ni(), m_curRGBImage.nj(), GL_RGB, GL_UNSIGNED_BYTE, m_curRGBImage.top_left_ptr()); else glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_mutex.Release(); // Call the current vision system component (if there is one) // to draw over the current image if (m_pPainter) { glPushMatrix(); glTranslated(m_offset.x, m_offset.y + h(), 0); glScaled(m_zoom, -m_zoom, 1); glColor4f(0, 0, 0, 1.0); m_pPainter->DrawWithMutex(m_painterInfo); glPopMatrix(); } #ifdef USE_OPEN_GL_WINDOW glFlush(); #else gl_finish(); #endif }