static void signal_handler(int sig) { if (g_xrefresh) xrefresh(); #ifdef BCMHOST if (g_bcm_active) { g_bcm_active = false; bcm_host_deinit(); } #endif if (g_stacktrace) { switch (sig) { case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: { void *array[10]; size_t size = backtrace(array, 10); if (! size) { printf("No stacktrace. Compile with -funwind-tables.\n"); } else { printf("Stacktrace: %i\n", size); backtrace_symbols_fd(array, size, 2); } break; } } } signal(sig, SIG_DFL); raise(sig); }
void piDestroyVideo() { if (sdlScreen) { SDL_FreeSurface(sdlScreen); } if (msxScreen) { free(msxScreen); } // Destroy shader resources if (shader.program) { glDeleteProgram(shader.program); glDeleteBuffers(3, buffers); glDeleteTextures(1, textures); } // Release OpenGL resources if (display) { eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(display, surface); eglDestroyContext(display, context); eglTerminate(display); } bcm_host_deinit(); }
void graphics_leave (void) { graphics_subshutdown (); SDL_FreeSurface(Dummy_prSDLScreen); bcm_host_deinit(); SDL_VideoQuit(); }
static void dispmanx_gfx_free(void *data) { int i; struct dispmanx_video *_dispvars = data; if (!_dispvars) return; dispmanx_free_main_resources(_dispvars); /* Close display and deinitialize. */ vc_dispmanx_display_close(_dispvars->display); bcm_host_deinit(); /* Destroy mutexes and conditions. */ slock_free(_dispvars->pending_mutex); scond_free(_dispvars->vsync_condition); for (i = 0; i < NUMPAGES; i++) slock_free(_dispvars->pages[i].page_used_mutex); if (_dispvars->pages) free (_dispvars->pages); _dispvars->pages = NULL; dispmanx_unblank_console(_dispvars); }
// Release OpenGL resources void closeGL() { #ifdef PLATFORM_RPI eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (surface != EGL_NO_SURFACE && eglDestroySurface(display, surface)) { printf("Surface destroyed ok\n"); } if (context != EGL_NO_CONTEXT && eglDestroyContext(display, context)) { printf("Main context destroyed ok\n"); } if (display != EGL_NO_DISPLAY && eglTerminate(display)) { printf("Display terminated ok\n"); } if (eglReleaseThread()) { printf("EGL thread resources released ok\n"); } if (vc_dispmanx_display_close(dispman_display) == 0) { printf("Dispmanx display rleased ok\n"); } bcm_host_deinit(); #else // ---------------------------------------- using GLFW // glfwTerminate(); #endif }
void testApp::exit(){ cam.close(); #ifdef TARGET_RASPBERRY_PI bcm_host_deinit(); #endif }
void Window::close() { if (m_pSDLWindow != NULL) { SDL_DestroyWindow(m_pSDLWindow); m_pSDLWindow = NULL; } if (m_pDisplay != EGL_NO_DISPLAY) { eglMakeCurrent(m_pDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (m_pContext != EGL_NO_CONTEXT) { eglDestroyContext(m_pContext, m_pContext); m_pContext = EGL_NO_CONTEXT; } if (m_pSurface != EGL_NO_SURFACE) { eglDestroySurface(m_pDisplay, m_pSurface); m_pSurface = EGL_NO_SURFACE; } eglTerminate(m_pDisplay); m_pDisplay = EGL_NO_DISPLAY; } bcm_host_deinit(); }
//called on exit, assuming we get far enough to have the log initialized void onExit() { Log::close(); #ifdef _RPI_ bcm_host_deinit(); #endif }
PlatformRPI::~PlatformRPI() { // de-initialize components before de-initalizing core m_jpeg.reset(); m_core.reset(); bcm_host_deinit(); }
void deinit_SDL(void) { if (sdlscreen) { SDL_DestroyWindow(sdlscreen); sdlscreen = NULL; } SDL_Quit(); bcm_host_deinit(); }
static void CloseDecoder(decoder_t *dec) { decoder_sys_t *sys = dec->p_sys; MMAL_BUFFER_HEADER_T *buffer; if (!sys) return; if (sys->component && sys->component->control->is_enabled) mmal_port_disable(sys->component->control); if (sys->input && sys->input->is_enabled) mmal_port_disable(sys->input); if (sys->output && sys->output->is_enabled) mmal_port_disable(sys->output); if (sys->component && sys->component->is_enabled) mmal_component_disable(sys->component); if (sys->input_pool) mmal_pool_destroy(sys->input_pool); if (sys->output_format) mmal_format_free(sys->output_format); /* Free pictures which are decoded but have not yet been sent * out to the core */ while ((buffer = mmal_queue_get(sys->decoded_pictures))) { picture_t *pic = (picture_t *)buffer->user_data; picture_Release(pic); if (sys->output_pool) { buffer->user_data = NULL; buffer->alloc_size = 0; buffer->data = NULL; mmal_buffer_header_release(buffer); } } if (sys->decoded_pictures) mmal_queue_destroy(sys->decoded_pictures); if (sys->output_pool) mmal_pool_destroy(sys->output_pool); if (sys->component) mmal_component_release(sys->component); vlc_mutex_destroy(&sys->mutex); vlc_sem_destroy(&sys->sem); free(sys); bcm_host_deinit(); }
void deinit_SDL(void) { if(sdlscreen) { SDL_FreeSurface(sdlscreen); sdlscreen = NULL; } SDL_Quit(); bcm_host_deinit(); }
static void frontend_deinit(void) { fe_update = vc_dispmanx_update_start( 0 ); vc_dispmanx_element_remove( fe_update, fe_element ); vc_dispmanx_update_submit_sync( fe_update ); vc_dispmanx_resource_delete( fe_resource ); vc_dispmanx_display_close( fe_display ); if(fe_screen) free(fe_screen); fe_screen=0; bcm_host_deinit(); }
ViewBackend::~ViewBackend() { ipcHost.deinitialize(); WPE::LibinputServer::singleton().setClient(nullptr); if (updateSource) g_source_destroy(updateSource); if (updateFd != -1) close(updateFd); vc_dispmanx_display_close(displayHandle); bcm_host_deinit(); }
static void Close(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys = vd->sys; char response[20]; /* answer is hvs_update_fields=%1d */ unsigned i; vc_tv_unregister_callback_full(tvservice_cb, vd); if (sys->dmx_handle) close_dmx(vd); if (sys->component && sys->component->control->is_enabled) mmal_port_disable(sys->component->control); if (sys->input && sys->input->is_enabled) mmal_port_disable(sys->input); if (sys->component && sys->component->is_enabled) mmal_component_disable(sys->component); if (sys->pool) mmal_pool_destroy(sys->pool); if (sys->component) mmal_component_release(sys->component); if (sys->picture_pool) picture_pool_Release(sys->picture_pool); else for (i = 0; i < sys->num_buffers; ++i) if (sys->pictures[i]) picture_Release(sys->pictures[i]); vlc_mutex_destroy(&sys->buffer_mutex); vlc_cond_destroy(&sys->buffer_cond); vlc_mutex_destroy(&sys->manage_mutex); if (sys->native_interlaced) { if (vc_gencmd(response, sizeof(response), "hvs_update_fields 0") < 0 || response[18] != '0') msg_Warn(vd, "Could not reset hvs field mode"); } free(sys->pictures); free(sys); bcm_host_deinit(); }
void GlContext::destroy() { if (NULL != m_display) { eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(m_display, m_context); eglDestroySurface(m_display, m_surface); eglTerminate(m_display); m_context = NULL; } eglClose(m_eglLibrary); # if BX_PLATFORM_RPI bcm_host_deinit(); # endif // BX_PLATFORM_RPI }
int main() { bcm_host_init(); initscr(); keypad(stdscr, TRUE); cbreak(); noecho(); nodelay(stdscr, TRUE); Game game; game.setWindowProvider(new EGLWindowProvider()); game.setGameContext(new GameContextDemo()); std::cout << "Finish setting up Game loop, starting ..." << std::endl; game.init(); endwin(); bcm_host_deinit(); }
GLUSvoid _glusDestroyNativeWindow() { if (_nativeWindowCreated) { DISPMANX_UPDATE_HANDLE_T dispmanUpdate; dispmanUpdate = vc_dispmanx_update_start(0); vc_dispmanx_element_remove(dispmanUpdate, _nativeWindow.element); vc_dispmanx_update_submit_sync(dispmanUpdate); _nativeWindowCreated = GLUS_FALSE; } memset(&_nativeWindow, 0, sizeof(_nativeWindow)); if (_nativeDisplay) { vc_dispmanx_display_close(_nativeDisplay); _nativeDisplay = 0; } if (_fullscreen) { vc_tv_register_callback(resizeDone, 0); if (vc_tv_hdmi_power_on_preferred() == 0) { waitResizeDone(); } vc_tv_unregister_callback(resizeDone); _fullscreen = GLUS_FALSE; } SDL_ShowCursor(SDL_ENABLE); SDL_Quit(); bcm_host_deinit(); }
int deinit_gl(EGLDisplay display, EGLContext context, EGLSurface surface) { if(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_FALSE) return 0; check(); if(eglDestroySurface(display, surface) == EGL_FALSE) return 0; check(); if(eglDestroyContext(display, context) == EGL_FALSE) return 0; check(); if(eglTerminate(display) == EGL_FALSE) return 0; check(); bcm_host_deinit(); return 1; }
static void DISPMANX_VideoQuit(_THIS) { /* Clear the lock mutex */ if ( hw_lock ) { SDL_DestroyMutex(hw_lock); hw_lock = NULL; } if (dispvars->pixmem != NULL){ int i; for (i=0; i < NUM_MODELISTS; ++i){ free(SDL_modelist[i]); SDL_modelist[i] = NULL; SDL_nummodes[i] = 0; } DISPMANX_FreeResources(); DISPMANX_FreeBackground(); vc_dispmanx_display_close( dispvars->display ); bcm_host_deinit(); } DISPMANX_CloseMouse(this); DISPMANX_CloseKeyboard(this); //MAC Set custom video mode block 2 //Reestablecemos el modo de video original /*if (dispvars->isResChanged){ int ret = vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, dispvars->original_tv_state->display.hdmi.group, dispvars->original_tv_state->display.hdmi.mode); printf ("\nRestaurando modo original...%s\n", ret == 0 ? "OK " : "FALLO"); }*/ #ifdef debug_mode fclose (fp); #endif exit (0); }
static void dispmanx_gfx_free(void *data) { struct dispmanx_video *_dispvars = data; int i; for (i = MAIN_SURFACE; i <= BACK_SURFACE; i++) { if (_dispvars->surfaces[i].setup) { dispmanx_surface_free(_dispvars, &_dispvars->surfaces[i]); } } /* Close display and deinitialize. */ vc_dispmanx_display_close(_dispvars->display); bcm_host_deinit(); /* Destroy mutexes and conditions. */ slock_free(_dispvars->pending_mutex); slock_free(_dispvars->vsync_cond_mutex); scond_free(_dispvars->vsync_condition); free(_dispvars); }
static void Close(filter_t *filter) { filter_sys_t *sys = filter->p_sys; MMAL_BUFFER_HEADER_T *buffer; if (!sys) return; if (sys->component && sys->component->control->is_enabled) mmal_port_disable(sys->component->control); if (sys->input && sys->input->is_enabled) mmal_port_disable(sys->input); if (sys->output && sys->output->is_enabled) mmal_port_disable(sys->output); if (sys->component && sys->component->is_enabled) mmal_component_disable(sys->component); while ((buffer = mmal_queue_get(sys->filtered_pictures))) { picture_t *pic = (picture_t *)buffer->user_data; picture_Release(pic); } if (sys->filtered_pictures) mmal_queue_destroy(sys->filtered_pictures); if (sys->component) mmal_component_release(sys->component); vlc_mutex_destroy(&sys->mutex); vlc_mutex_destroy(&sys->buffer_cond_mutex); vlc_cond_destroy(&sys->buffer_cond); free(sys); bcm_host_deinit(); }
static void *display_thread (void *unused) { VC_DISPMANX_ALPHA_T alpha = { (DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 255 /*alpha 0->255*/ , 0 }; uint32_t vc_image_ptr; SDL_Surface *Dummy_prSDLScreen; int width, height; bool callback_registered = false; for(;;) { display_thread_busy = false; uae_u32 signal = read_comm_pipe_u32_blocking(display_pipe); display_thread_busy = true; switch(signal) { case DISPLAY_SIGNAL_SETUP: if(!callback_registered) { bcm_host_init(); dispmanxdisplay = vc_dispmanx_display_open(0); vc_dispmanx_vsync_callback(dispmanxdisplay, vsync_callback, NULL); callback_registered = true; } break; case DISPLAY_SIGNAL_SUBSHUTDOWN: if (DispManXElementpresent == 1) { DispManXElementpresent = 0; dispmanxupdate = vc_dispmanx_update_start(0); vc_dispmanx_element_remove(dispmanxupdate, dispmanxelement); vc_dispmanx_update_submit_sync(dispmanxupdate); } if (dispmanxresource_amigafb_1 != 0) { vc_dispmanx_resource_delete(dispmanxresource_amigafb_1); dispmanxresource_amigafb_1 = 0; } if (dispmanxresource_amigafb_2 != 0) { vc_dispmanx_resource_delete(dispmanxresource_amigafb_2); dispmanxresource_amigafb_2 = 0; } if(prSDLScreen != NULL) { SDL_FreeSurface(prSDLScreen); prSDLScreen = NULL; } uae_sem_post (&display_sem); break; case DISPLAY_SIGNAL_OPEN: width = display_width; height = display_height; Dummy_prSDLScreen = SDL_SetVideoMode(width, height, 16, SDL_SWSURFACE | SDL_FULLSCREEN); prSDLScreen = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height, 16, Dummy_prSDLScreen->format->Rmask, Dummy_prSDLScreen->format->Gmask, Dummy_prSDLScreen->format->Bmask, Dummy_prSDLScreen->format->Amask); SDL_FreeSurface(Dummy_prSDLScreen); vc_dispmanx_display_get_info(dispmanxdisplay, &dispmanxdinfo); dispmanxresource_amigafb_1 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, width, height, &vc_image_ptr); dispmanxresource_amigafb_2 = vc_dispmanx_resource_create(VC_IMAGE_RGB565, width, height, &vc_image_ptr); vc_dispmanx_rect_set(&blit_rect, 0, 0, width, height); vc_dispmanx_resource_write_data(dispmanxresource_amigafb_1, VC_IMAGE_RGB565, prSDLScreen->pitch, prSDLScreen->pixels, &blit_rect); vc_dispmanx_rect_set(&src_rect, 0, 0, width << 16, height << 16); // 16/9 to 4/3 ratio adaptation. if (currprefs.gfx_correct_aspect == 0 || screen_is_picasso) { // Fullscreen. int scaled_width = dispmanxdinfo.width * currprefs.gfx_fullscreen_ratio / 100; int scaled_height = dispmanxdinfo.height * currprefs.gfx_fullscreen_ratio / 100; vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width - scaled_width)/2, (dispmanxdinfo.height - scaled_height)/2, scaled_width, scaled_height); } else { // 4/3 shrink. int scaled_width = dispmanxdinfo.width * currprefs.gfx_fullscreen_ratio / 100; int scaled_height = dispmanxdinfo.height * currprefs.gfx_fullscreen_ratio / 100; vc_dispmanx_rect_set( &dst_rect, (dispmanxdinfo.width - scaled_width / 16 * 12)/2, (dispmanxdinfo.height - scaled_height)/2, scaled_width/16*12, scaled_height); } if (DispManXElementpresent == 0) { DispManXElementpresent = 1; dispmanxupdate = vc_dispmanx_update_start(0); dispmanxelement = vc_dispmanx_element_add(dispmanxupdate, dispmanxdisplay, 2, // layer &dst_rect, dispmanxresource_amigafb_1, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, NULL, DISPMANX_NO_ROTATE); vc_dispmanx_update_submit(dispmanxupdate, NULL, NULL); } uae_sem_post (&display_sem); break; case DISPLAY_SIGNAL_SHOW: if (current_resource_amigafb == 1) { current_resource_amigafb = 0; vc_dispmanx_resource_write_data(dispmanxresource_amigafb_1, VC_IMAGE_RGB565, adisplays.gfxvidinfo.drawbuffer.rowbytes, adisplays.gfxvidinfo.drawbuffer.bufmem, &blit_rect); dispmanxupdate = vc_dispmanx_update_start(0); vc_dispmanx_element_change_source(dispmanxupdate, dispmanxelement, dispmanxresource_amigafb_1); } else { current_resource_amigafb = 1; vc_dispmanx_resource_write_data(dispmanxresource_amigafb_2, VC_IMAGE_RGB565, adisplays.gfxvidinfo.drawbuffer.rowbytes, adisplays.gfxvidinfo.drawbuffer.bufmem, &blit_rect); dispmanxupdate = vc_dispmanx_update_start(0); vc_dispmanx_element_change_source(dispmanxupdate, dispmanxelement, dispmanxresource_amigafb_2); } vc_dispmanx_update_submit(dispmanxupdate, NULL, NULL); break; case DISPLAY_SIGNAL_QUIT: callback_registered = false; vc_dispmanx_vsync_callback(dispmanxdisplay, NULL, NULL); vc_dispmanx_display_close(dispmanxdisplay); bcm_host_deinit(); SDL_VideoQuit(); display_tid = 0; return 0; } } }
int main(int argc, char *argv[]) { glslang::InitializeProcess(); #if PPSSPP_PLATFORM(RPI) bcm_host_init(); #endif putenv((char*)"SDL_VIDEO_CENTERED=1"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); if (VulkanMayBeAvailable()) { printf("Vulkan might be available.\n"); } else { printf("Vulkan is not available.\n"); } int set_xres = -1; int set_yres = -1; bool portrait = false; bool set_ipad = false; float set_dpi = 1.0f; float set_scale = 1.0f; // Produce a new set of arguments with the ones we skip. int remain_argc = 1; const char *remain_argv[256] = { argv[0] }; Uint32 mode = 0; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; else if (set_xres == -2) set_xres = parseInt(argv[i]); else if (set_yres == -2) set_yres = parseInt(argv[i]); else if (set_dpi == -2) set_dpi = parseFloat(argv[i]); else if (set_scale == -2) set_scale = parseFloat(argv[i]); else if (!strcmp(argv[i],"--xres")) set_xres = -2; else if (!strcmp(argv[i],"--yres")) set_yres = -2; else if (!strcmp(argv[i],"--dpi")) set_dpi = -2; else if (!strcmp(argv[i],"--scale")) set_scale = -2; else if (!strcmp(argv[i],"--ipad")) set_ipad = true; else if (!strcmp(argv[i],"--portrait")) portrait = true; else { remain_argv[remain_argc++] = argv[i]; } } std::string app_name; std::string app_name_nice; std::string version; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version); bool joystick_enabled = true; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n"); joystick_enabled = false; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } } // TODO: How do we get this into the GraphicsContext? #ifdef USING_EGL if (EGL_Open()) return 1; #endif // Get the video info before doing anything else, so we don't get skewed resolution results. // TODO: support multiple displays correctly SDL_DisplayMode displayMode; int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode); if (should_be_zero != 0) { fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError()); return 1; } g_DesktopWidth = displayMode.w; g_DesktopHeight = displayMode.h; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetSwapInterval(1); // Is resolution is too low to run windowed if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; } if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { pixel_xres = g_DesktopWidth; pixel_yres = g_DesktopHeight; g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2 * set_scale; pixel_yres = 272 * 2 * set_scale; if (portrait) { std::swap(pixel_xres, pixel_yres); } g_Config.bFullScreen = false; } set_dpi = 1.0f / set_dpi; if (set_ipad) { pixel_xres = 1024; pixel_yres = 768; } if (!landscape) { std::swap(pixel_xres, pixel_yres); } if (set_xres > 0) { pixel_xres = set_xres; } if (set_yres > 0) { pixel_yres = set_yres; } float dpi_scale = 1.0f; if (set_dpi > 0) { dpi_scale = set_dpi; } dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; // Mac / Linux char path[2048]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); // Use the setting from the config when initing the window. if (g_Config.bFullScreen) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; int x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()); int y = SDL_WINDOWPOS_UNDEFINED; pixel_in_dps_x = (float)pixel_xres / dp_xres; pixel_in_dps_y = (float)pixel_yres / dp_yres; g_dpi_scale_x = dp_xres / (float)pixel_xres; g_dpi_scale_y = dp_yres / (float)pixel_yres; g_dpi_scale_real_x = g_dpi_scale_x; g_dpi_scale_real_y = g_dpi_scale_y; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; std::string error_message; if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); if (ctx->Init(window, x, y, mode, &error_message) != 0) { printf("GL init error '%s'\n", error_message.c_str()); } graphicsContext = ctx; } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); if (!ctx->Init(window, x, y, mode, &error_message)) { printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = (int)GPUBackend::OPENGL; SetGPUBackend((GPUBackend)g_Config.iGPUBackend); delete ctx; SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); glctx->Init(window, x, y, mode, &error_message); graphicsContext = glctx; } else { graphicsContext = ctx; } } bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. if (!graphicsContext->InitFromRenderThread(&error_message)) { printf("Init from thread error: '%s'\n", error_message.c_str()); } #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif if (!useEmuThread) { NativeInitGraphics(graphicsContext); NativeResized(); } SDL_AudioSpec fmt, ret_fmt; memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { if (ret_fmt.samples != fmt.samples) // Notify, but still use it ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); } } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); if (joystick_enabled) { joystick = new SDLJoystick(); } else { joystick = nullptr; } EnableFZ(); int framecount = 0; bool mouseDown = false; if (useEmuThread) { EmuThreadStart(graphicsContext); } graphicsContext->ThreadStart(); while (true) { SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * g_dpi_scale_x; float my = event.motion.y * g_dpi_scale_y; switch (event.type) { case SDL_QUIT: g_QuitRequested = 1; break; #if !defined(MOBILE_DEVICE) case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: { Uint32 window_flags = SDL_GetWindowFlags(window); bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); pixel_xres = event.window.data1; pixel_yres = event.window.data2; dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; NativeResized(); // Set variable here in case fullscreen was toggled by hotkey g_Config.bFullScreen = fullscreen; // Hide/Show cursor correctly toggling fullscreen if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { SDL_ShowCursor(SDL_DISABLE); } else if (lastUIState != UISTATE_INGAME || !fullscreen) { SDL_ShowCursor(SDL_ENABLE); } break; } default: break; } break; #endif case SDL_KEYDOWN: { if (event.key.repeat > 0) { break;} int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; auto mapped = KeyMapRawSDLtoNative.find(k); if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { break; } key.keyCode = mapped->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_KEYUP: { if (event.key.repeat > 0) { break;} int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; auto mapped = KeyMapRawSDLtoNative.find(k); if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { break; } key.keyCode = mapped->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_TEXTINPUT: { int pos = 0; int c = u8_nextchar(event.text.text, &pos); KeyInput key; key.flags = KEY_CHAR; key.keyCode = c; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { mouseDown = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_DOWN | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; } break; case SDL_MOUSEWHEEL: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; if (event.wheel.y > 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; } key.flags = KEY_DOWN; NativeKey(key); // SDL2 doesn't consider the mousewheel a button anymore // so let's send the KEY_UP right away. // Maybe KEY_UP alone will suffice? key.flags = KEY_UP; NativeKey(key); } case SDL_MOUSEMOTION: if (mouseDown) { TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_MOVE | TOUCH_MOUSE; input.id = 0; NativeTouch(input); } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { mouseDown = false; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_UP | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; } break; default: if (joystick) { joystick->ProcessInput(event); } break; } } if (g_QuitRequested) break; const uint8_t *keys = SDL_GetKeyboardState(NULL); if (emuThreadState == (int)EmuThreadState::DISABLED) { UpdateRunLoop(); } if (g_QuitRequested) break; #if !defined(MOBILE_DEVICE) if (lastUIState != GetUIState()) { lastUIState = GetUIState(); if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) SDL_ShowCursor(SDL_ENABLE); } #endif if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } if (emuThreadState != (int)EmuThreadState::DISABLED) { if (!graphicsContext->ThreadFrame()) break; } graphicsContext->SwapBuffers(); ToggleFullScreenIfFlagSet(window); time_update(); framecount++; } if (useEmuThread) { EmuThreadStop(); while (emuThreadState != (int)EmuThreadState::STOPPED) { // Need to keep eating frames to allow the EmuThread to exit correctly. graphicsContext->ThreadFrame(); } EmuThreadJoin(); } delete joystick; if (!useEmuThread) { NativeShutdownGraphics(); } graphicsContext->Shutdown(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); NativeShutdown(); delete graphicsContext; SDL_PauseAudio(1); SDL_CloseAudio(); SDL_Quit(); #if PPSSPP_PLATFORM(RPI) bcm_host_deinit(); #endif glslang::FinalizeProcess(); ILOG("Leaving main"); return 0; }
int main(int argc, char* argv[]) { bcm_host_init(); // get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!display) { printf("Failed to get display\n"); return 1; } // initialize the EGL display connection //EGLBoolean result; if (!eglInitialize(display, NULL, NULL)) { printf("Failed to initialize EGL\n"); return 1; } // get an appropriate EGL frame buffer configuration static const EGLint attributeList[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; EGLConfig config; EGLint numConfig; if (!eglChooseConfig(display, attributeList, &config, 1, &numConfig)) { printf("Failed to choose EGL config\n"); return 1; } // get an appropriate EGL frame buffer configuration if (!eglBindAPI(EGL_OPENGL_ES_API)) { printf("Failed to bind OpenGL ES API\n"); return 1; } // create an EGL rendering context static const EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes); if (context == EGL_NO_CONTEXT) { printf("Failed to create EGL context\n"); return 1; } // create an EGL window surface uint32_t screenWidth; uint32_t screenHeight; int32_t success = graphics_get_display_size(0, &screenWidth, &screenHeight); if (success == -1) { printf("Failed to get display size\n"); return 1; } VC_RECT_T dstRect; dstRect.x = 0; dstRect.y = 0; dstRect.width = screenWidth; dstRect.height = screenHeight; VC_RECT_T srcRect; srcRect.x = 0; srcRect.y = 0; srcRect.width = screenWidth; srcRect.height = screenHeight; DISPMANX_DISPLAY_HANDLE_T dispmanDisplay = vc_dispmanx_display_open(0); DISPMANX_UPDATE_HANDLE_T dispmanUpdate = vc_dispmanx_update_start(0); DISPMANX_ELEMENT_HANDLE_T dispmanElement = vc_dispmanx_element_add(dispmanUpdate, dispmanDisplay, 0, &dstRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE); static EGL_DISPMANX_WINDOW_T nativewindow; nativewindow.element = dispmanElement; nativewindow.width = screenWidth; nativewindow.height = screenHeight; vc_dispmanx_update_submit_sync(dispmanUpdate); surface = eglCreateWindowSurface(display, config, &nativewindow, NULL); if (surface == EGL_NO_SURFACE) { printf("Failed to create EGL window surface\n"); return 1; } // connect the context to the surface if (!eglMakeCurrent(display, surface, surface, context)) { printf("Failed to set current EGL context\n"); return 1; } // input struct InputDeviceRPI { enum DeviceClass { CLASS_KEYBOARD = 1, CLASS_MOUSE = 2, CLASS_TOUCHPAD = 4, CLASS_GAMEPAD = 8 }; uint32_t deviceClass = 0; int fd = 0; }; int maxFd = 0; std::vector<InputDeviceRPI> inputDevices; uint32_t mouseX = 0; uint32_t mouseY = 0; char TEMP[256]; glob_t g; int result = glob("/dev/input/event*", GLOB_NOSORT, NULL, &g); if (result == GLOB_NOMATCH) { printf("No event devices found\n"); return 1; } else if (result) { printf("Could not read /dev/input/event*\n"); return 1; } for (size_t i = 0; i < g.gl_pathc; i++) { InputDeviceRPI inputDevice; inputDevice.fd = open(g.gl_pathv[i], O_RDONLY); if (inputDevice.fd == -1) { printf("Failed to open device file descriptor\n"); continue; } if (ioctl(inputDevice.fd, EVIOCGRAB, (void *)1) == -1) { printf("Failed to get grab device\n"); } memset(TEMP, 0, sizeof(TEMP)); if (ioctl(inputDevice.fd, EVIOCGNAME(sizeof(TEMP) - 1), TEMP) == -1) { printf("Failed to get device name\n"); } else { printf("Got device: %s\n", TEMP); } unsigned long eventBits[BITS_TO_LONGS(EV_CNT)]; unsigned long absBits[BITS_TO_LONGS(ABS_CNT)]; unsigned long relBits[BITS_TO_LONGS(REL_CNT)]; unsigned long keyBits[BITS_TO_LONGS(KEY_CNT)]; if (ioctl(inputDevice.fd, EVIOCGBIT(0, sizeof(eventBits)), eventBits) == -1 || ioctl(inputDevice.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) == -1 || ioctl(inputDevice.fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits) == -1 || ioctl(inputDevice.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) == -1) { printf("Failed to get device event bits\n"); } if (bit_is_set(eventBits, EV_KEY) && ( bit_is_set(keyBits, KEY_1) || bit_is_set(keyBits, KEY_2) || bit_is_set(keyBits, KEY_3) || bit_is_set(keyBits, KEY_4) || bit_is_set(keyBits, KEY_5) || bit_is_set(keyBits, KEY_6) || bit_is_set(keyBits, KEY_7) || bit_is_set(keyBits, KEY_8) || bit_is_set(keyBits, KEY_9) || bit_is_set(keyBits, KEY_0) )) { printf("Keyboard\n"); inputDevice.deviceClass = InputDeviceRPI::CLASS_KEYBOARD; } if (bit_is_set(eventBits, EV_ABS) && bit_is_set(absBits, ABS_X) && bit_is_set(absBits, ABS_Y)) { if (bit_is_set(keyBits, BTN_STYLUS) || bit_is_set(keyBits, BTN_TOOL_PEN)) { printf("Tablet\n"); inputDevice.deviceClass |= InputDeviceRPI::CLASS_TOUCHPAD; } else if (bit_is_set(keyBits, BTN_TOOL_FINGER) && !bit_is_set(keyBits, BTN_TOOL_PEN)) { printf("Touchpad\n"); inputDevice.deviceClass |= InputDeviceRPI::CLASS_TOUCHPAD; } else if (bit_is_set(keyBits, BTN_MOUSE)) { printf("Mouse\n"); inputDevice.deviceClass |= InputDeviceRPI::CLASS_MOUSE; } else if (bit_is_set(keyBits, BTN_TOUCH)) { printf("Touchscreen\n"); inputDevice.deviceClass |= InputDeviceRPI::CLASS_TOUCHPAD; } } else if (bit_is_set(eventBits, EV_REL) && bit_is_set(relBits, REL_X) && bit_is_set(relBits, REL_Y)) { if (bit_is_set(keyBits, BTN_MOUSE)) { printf("Mouse\n"); inputDevice.deviceClass |= InputDeviceRPI::CLASS_MOUSE; } } if (bit_is_set(keyBits, BTN_JOYSTICK)) { printf("Joystick\n"); inputDevice.deviceClass = InputDeviceRPI::CLASS_GAMEPAD; } if (bit_is_set(keyBits, BTN_GAMEPAD)) { printf("Gamepad\n"); inputDevice.deviceClass = InputDeviceRPI::CLASS_GAMEPAD; } if (inputDevice.fd > maxFd) { maxFd = inputDevice.fd; } inputDevices.push_back(inputDevice); } globfree(&g); fd_set rfds; struct timeval tv; for(;;) { FD_ZERO(&rfds); for (const InputDeviceRPI& inputDevice : inputDevices) { FD_SET(inputDevice.fd, &rfds); } tv.tv_sec = 0; tv.tv_usec = 0; int retval = select(maxFd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { printf("Select failed\n"); return 1; } else if (retval > 0) { for (const InputDeviceRPI& inputDevice : inputDevices) { if (FD_ISSET(inputDevice.fd, &rfds)) { ssize_t bytesRead = read(inputDevice.fd, TEMP, sizeof(TEMP)); if (bytesRead == -1) { printf("Failed to read input"); } printf("Got input, read %d bytes\n", bytesRead); for (ssize_t i = 0; i < bytesRead - static_cast<ssize_t>(sizeof(input_event)) + 1; i += sizeof(input_event)) { input_event* event = reinterpret_cast<input_event*>(TEMP + i); if (inputDevice.deviceClass & InputDeviceRPI::CLASS_KEYBOARD) { printf("Timestamp: %d.%d, type: %d", (uint32_t)event->time.tv_sec, (uint32_t)event->time.tv_usec, event->type); switch (event->type) { case EV_SYN: printf(", EV_SYN"); break; case EV_KEY: printf(", EV_KEY"); break; case EV_MSC: printf(", EV_MSC"); break; case EV_REP: printf(", EV_REP"); break; } printf(", value: %d, key: %d\n", event->value, event->code); if (event->type == EV_KEY && event->code == KEY_ESC) { return 0; } } if (inputDevice.deviceClass & InputDeviceRPI::CLASS_MOUSE) { printf("Timestamp: %d.%d, type: %d", (uint32_t)event->time.tv_sec, (uint32_t)event->time.tv_usec, event->type); switch (event->type) { case EV_SYN: printf(", EV_SYN"); break; case EV_KEY: printf(", EV_KEY"); break; case EV_MSC: printf(", EV_MSC"); break; case EV_REL: printf(", EV_REL"); break; } printf(", value: %d, key: %d\n", event->value, event->code); } } } } } glClearColor(1.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); eglSwapBuffers(display, surface); } for (const InputDeviceRPI& inputDevice : inputDevices) { if (ioctl(inputDevice.fd, EVIOCGRAB, (void*)0) == -1) { printf("Failed to release device\n"); } if (close(inputDevice.fd) == -1) { printf("Failed to close file descriptor\n"); } } if (!eglDestroySurface(display, surface)) { printf("Failed to destroy EGL surface\n"); } if (!eglDestroyContext(display, context)) { printf("Failed to destroy EGL context\n"); } if (!eglTerminate(display)) { printf("Failed to terminate EGL\n"); } bcm_host_deinit(); return 0; }
~CBroadcomHost() { bcm_host_deinit(); }
~InitBcmHost() { bcm_host_deinit(); }
void moduleTerm( WstCompositor *ctx ) { bcm_host_deinit(); compositor= 0; }
bool GBASDLGLES2Init(struct SDLSoftwareRenderer* renderer) { #ifdef BUILD_RASPI bcm_host_init(); renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); int major, minor; if (EGL_FALSE == eglInitialize(renderer->display, &major, &minor)) { printf("Failed to initialize EGL"); return false; } if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) { printf("Failed to get GLES API"); return false; } const EGLint requestConfig[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 1, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; EGLConfig config; EGLint numConfigs; if (EGL_FALSE == eglChooseConfig(renderer->display, requestConfig, &config, 1, &numConfigs)) { printf("Failed to choose EGL config\n"); return false; } const EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; int dispWidth = 240, dispHeight = 160, adjWidth; renderer->context = eglCreateContext(renderer->display, config, EGL_NO_CONTEXT, contextAttributes); graphics_get_display_size(0, &dispWidth, &dispHeight); adjWidth = dispHeight / 2 * 3; DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0); DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); VC_RECT_T destRect = { .x = (dispWidth - adjWidth) / 2, .y = 0, .width = adjWidth, .height = dispHeight }; VC_RECT_T srcRect = { .x = 0, .y = 0, .width = 240 << 16, .height = 160 << 16 }; DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, 0); vc_dispmanx_update_submit_sync(update); renderer->window.element = element; renderer->window.width = dispWidth; renderer->window.height = dispHeight; renderer->surface = eglCreateWindowSurface(renderer->display, config, &renderer->window, 0); if (EGL_FALSE == eglMakeCurrent(renderer->display, renderer->surface, renderer->surface, renderer->context)) { return false; } #else GBASDLGLCommonInit(renderer); #endif renderer->d.outputBuffer = memalign(16, 256 * 256 * 4); renderer->d.outputBufferStride = 256; GBAGLES2ContextCreate(&renderer->gl2); renderer->gl2.d.user = renderer; renderer->gl2.d.lockAspectRatio = renderer->lockAspectRatio; renderer->gl2.d.filter = renderer->filter; renderer->gl2.d.swap = GBASDLGLCommonSwap; renderer->gl2.d.init(&renderer->gl2.d, 0); return true; } void GBASDLGLES2Runloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) { SDL_Event event; struct VideoBackend* v = &renderer->gl2.d; while (context->state < THREAD_EXITING) { while (SDL_PollEvent(&event)) { GBASDLHandleEvent(context, &renderer->player, &event); } if (GBASyncWaitFrameStart(&context->sync)) { v->postFrame(v, renderer->d.outputBuffer); } GBASyncWaitFrameEnd(&context->sync); v->drawFrame(v); #ifdef BUILD_RASPI eglSwapBuffers(renderer->display, renderer->surface); #else v->swap(v); #endif } } void GBASDLGLES2Deinit(struct SDLSoftwareRenderer* renderer) { if (renderer->gl2.d.deinit) { renderer->gl2.d.deinit(&renderer->gl2.d); } #ifdef BUILD_RASPI eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(renderer->display, renderer->surface); eglDestroyContext(renderer->display, renderer->context); eglTerminate(renderer->display); bcm_host_deinit(); #elif SDL_VERSION_ATLEAST(2, 0, 0) SDL_GL_DeleteContext(renderer->glCtx); #endif free(renderer->d.outputBuffer); }
void exitfunc() { SDL_Quit(); bcm_host_deinit(); }