int rgssThreadFun(void *userdata) { RGSSThreadData *threadData = static_cast<RGSSThreadData*>(userdata); SDL_Window *win = threadData->window; SDL_GLContext glCtx; /* Setup GL context */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (threadData->config.debugMode) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); glCtx = SDL_GL_CreateContext(win); if (!glCtx) { rgssThreadError(threadData, std::string("Error creating context: ") + SDL_GetError()); return 0; } try { initGLFunctions(); } catch (const Exception &exc) { rgssThreadError(threadData, exc.msg); SDL_GL_DeleteContext(glCtx); return 0; } gl.ClearColor(0, 0, 0, 1); gl.Clear(GL_COLOR_BUFFER_BIT); SDL_GL_SwapWindow(win); printGLInfo(); SDL_GL_SetSwapInterval(threadData->config.vsync ? 1 : 0); DebugLogger dLogger; /* Setup AL context */ ALCdevice *alcDev = alcOpenDevice(0); if (!alcDev) { rgssThreadError(threadData, "Error opening OpenAL device"); SDL_GL_DeleteContext(glCtx); return 0; } ALCcontext *alcCtx = alcCreateContext(alcDev, 0); if (!alcCtx) { rgssThreadError(threadData, "Error creating OpenAL context"); alcCloseDevice(alcDev); SDL_GL_DeleteContext(glCtx); return 0; } alcMakeContextCurrent(alcCtx); try { SharedState::initInstance(threadData); } catch (const Exception &exc) { rgssThreadError(threadData, exc.msg); alcDestroyContext(alcCtx); alcCloseDevice(alcDev); SDL_GL_DeleteContext(glCtx); return 0; } /* Start script execution */ scriptBinding->execute(); threadData->rqTermAck.set(); threadData->ethread->requestTerminate(); SharedState::finiInstance(); alcDestroyContext(alcCtx); alcCloseDevice(alcDev); SDL_GL_DeleteContext(glCtx); return 0; }
/* ** GLimp_SetSwapInterval */ void GLimp_SetSwapInterval( int swapInterval ) { SDL_GL_SetSwapInterval( swapInterval ); }
/****** Process hotkey input ******/ void AGB_core::handle_hotkey(SDL_Event& event) { //Disallow key repeats if(event.key.repeat) { return; } //Quit on Q or ESC if((event.type == SDL_KEYDOWN) && ((event.key.keysym.sym == SDLK_q) || (event.key.keysym.sym == SDLK_ESCAPE))) { running = false; SDL_Quit(); } //Mute or unmute sound on M else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == config::hotkey_mute) && (!config::use_external_interfaces)) { if(config::volume == 0) { update_volume(config::old_volume); } else { config::old_volume = config::volume; update_volume(0); } } //Quick save state on F1 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F1)) { save_state(0); } //Quick load save state on F2 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F2)) { load_state(0); } //Pause and wait for netplay connection on F5 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F5)) { start_netplay(); } //Disconnect netplay connection on F6 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F6)) { stop_netplay(); } //Start CLI debugger on F7 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F7) && (!config::use_external_interfaces)) { //Start a new CLI debugger session or interrupt an existing one in Continue Mode if((!db_unit.debug_mode) || ((db_unit.debug_mode) && (db_unit.last_command == "c"))) { db_unit.debug_mode = true; db_unit.last_command = "n"; db_unit.last_mnemonic = ""; } } //Screenshot on F9 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F9)) { std::stringstream save_stream; std::string save_name = config::ss_path; //Prefix SDL Ticks to screenshot name save_stream << SDL_GetTicks(); save_name += save_stream.str(); save_stream.str(std::string()); //Append random number to screenshot name srand(SDL_GetTicks()); save_stream << rand() % 1024 << rand() % 1024 << rand() % 1024; save_name += save_stream.str() + ".bmp"; SDL_SaveBMP(core_cpu.controllers.video.final_screen, save_name.c_str()); //OSD config::osd_message = "SAVED SCREENSHOT"; config::osd_count = 180; } //Toggle Fullscreen on F12 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F12)) { //Unset fullscreen if(config::flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { config::flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; config::scaling_factor = config::old_scaling_factor; } //Set fullscreen else { config::flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; config::old_scaling_factor = config::scaling_factor; } //Destroy old window SDL_DestroyWindow(core_cpu.controllers.video.window); //Initialize new window - SDL if(!config::use_opengl) { core_cpu.controllers.video.window = SDL_CreateWindow("GBE+", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, config::sys_width, config::sys_height, config::flags); core_cpu.controllers.video.final_screen = SDL_GetWindowSurface(core_cpu.controllers.video.window); SDL_GetWindowSize(core_cpu.controllers.video.window, &config::win_width, &config::win_height); //Find the maximum fullscreen dimensions that maintain the original aspect ratio if(config::flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { double max_width, max_height, ratio = 0.0; max_width = (double)config::win_width / config::sys_width; max_height = (double)config::win_height / config::sys_height; if(max_width <= max_height) { ratio = max_width; } else { ratio = max_height; } core_cpu.controllers.video.max_fullscreen_ratio = ratio; } } //Initialize new window - OpenGL else { core_cpu.controllers.video.opengl_init(); } } //Pause emulation else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_PAUSE)) { config::pause_emu = true; SDL_PauseAudio(1); std::cout<<"EMU::Paused\n"; //Delay until pause key is hit again while(config::pause_emu) { SDL_Delay(50); if((SDL_PollEvent(&event)) && (event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_PAUSE)) { config::pause_emu = false; SDL_PauseAudio(0); std::cout<<"EMU::Unpaused\n"; } } } //Toggle turbo on else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == config::hotkey_turbo)) { config::turbo = true; if((config::sdl_render) && (config::use_opengl)) { SDL_GL_SetSwapInterval(0); } } //Toggle turbo off else if((event.type == SDL_KEYUP) && (event.key.keysym.sym == config::hotkey_turbo)) { config::turbo = false; if((config::sdl_render) && (config::use_opengl)) { SDL_GL_SetSwapInterval(1); } } //Reset emulation on F8 else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F8)) { reset(); } //Initiate various communication functions //Soul Doll Adapter - Reset Soul Doll //Battle Chip Gate - Insert Battle Chip else if((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_F3)) { switch(core_cpu.controllers.serial_io.sio_stat.sio_type) { //Reset adapter case GBA_SOUL_DOLL_ADAPTER: core_cpu.controllers.serial_io.soul_doll_adapter_reset(); //OSD config::osd_message = "SOUL DOLL ADAPTER RESET"; config::osd_count = 180; break; } } }
int main(int argc, char* argv[]) { printf("press 'z' to toggle microprofile drawing\n"); printf("press 'right shift' to pause microprofile update\n"); printf("press 'x' to toggle profiling\n"); printf("press 'c' to toggle enable of all profiler groups\n"); MicroProfileOnThreadCreate("Main"); if(SDL_Init(SDL_INIT_VIDEO) < 0) { return 1; } 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_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetSwapInterval(1); SDL_Window * pWindow = SDL_CreateWindow("microprofiledemo", 10, 10, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); if(!pWindow) return 1; SDL_GLContext glcontext = SDL_GL_CreateContext(pWindow); glewExperimental=1; GLenum err=glewInit(); if(err!=GLEW_OK) { __BREAK(); } glGetError(); //glew generates an error #if MICROPROFILE_ENABLED MicroProfileQueryInitGL(); MicroProfileDrawInit(); MP_ASSERT(glGetError() == 0); #endif StartFakeWork(); while(!g_nQuit) { MICROPROFILE_SCOPE(MAIN); SDL_Event Evt; while(SDL_PollEvent(&Evt)) { HandleEvent(&Evt); } glClearColor(0.3f,0.4f,0.6f,0.f); glViewport(0, 0, WIDTH, HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #if 1||FAKE_WORK { MICROPROFILE_SCOPEI("Main", "Dummy", 0xff3399ff); for(uint32_t i = 0; i < 14; ++i) { MICROPROFILE_SCOPEI("Main", "1ms", 0xff3399ff); MICROPROFILE_META_CPU("Sleep",1); usleep(1000); } } #endif MicroProfileMouseButton(g_MouseDown0, g_MouseDown1); MicroProfileMousePosition(g_MouseX, g_MouseY, g_MouseDelta); g_MouseDelta = 0; MicroProfileFlip(); { MICROPROFILE_SCOPEGPUI("GPU", "MicroProfileDraw", 0x88dd44); float projection[16]; float left = 0.f; float right = WIDTH; float bottom = HEIGHT; float top = 0.f; float near = -1.f; float far = 1.f; memset(&projection[0], 0, sizeof(projection)); projection[0] = 2.0f / (right - left); projection[5] = 2.0f / (top - bottom); projection[10] = -2.0f / (far - near); projection[12] = - (right + left) / (right - left); projection[13] = - (top + bottom) / (top - bottom); projection[14] = - (far + near) / (far - near); projection[15] = 1.f; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); #if MICROPROFILE_ENABLED MicroProfileBeginDraw(WIDTH, HEIGHT, &projection[0]); MicroProfileDraw(WIDTH, HEIGHT); MicroProfileEndDraw(); #endif glDisable(GL_BLEND); } MICROPROFILE_SCOPEI("MAIN", "Flip", 0xffee00); SDL_GL_SwapWindow(pWindow); } StopFakeWork(); MicroProfileShutdown(); SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(pWindow); SDL_Quit(); return 0; }
/* inits sdl and creates an opengl window */ static void initSDL(VideoMode *video) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { LOGE("Failed to init SDL2: %s", SDL_GetError()); exit(1); } #ifdef _WIN32 float ddpi; if (!SDL_GetDisplayDPI(0, &ddpi, nullptr, nullptr)) { const float WINDOWS_DEFAULT_DPI = 96.0f; video->pixel_scale = ddpi / WINDOWS_DEFAULT_DPI; } #endif SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); #ifdef EMSCRIPTEN SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); #endif int window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; if (video->fullscreen) window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; sdl_window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, video->pixel_scale * video->width, video->pixel_scale * video->height, window_flags); if (!sdl_window) { LOGE("Failed to create an OpenGL window: %s", SDL_GetError()); exit(1); } sdl_gl_context = SDL_GL_CreateContext(sdl_window); if (!sdl_gl_context) { LOGE("Failed to create an OpenGL context: %s", SDL_GetError()); exit(1); } int drawable_width, drawable_height; SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height); if (drawable_width != video->width) { LOGI("Created high DPI window. (%dx%d)", drawable_width, drawable_height); video->pixel_scale = (float)drawable_width / (float)video->width; } else { video->pixel_scale = 1.0f; } if (SDL_GL_SetSwapInterval(1) == -1) { // sync with monitor refresh rate LOGW("Could not enable VSync."); } #ifndef __APPLE__ glewInit(); #endif }
Engine::Engine(util::Dir *data_dir, const char *windowtitle) : running(false), window_size{800, 600}, camgame_phys{10 * coord::settings::phys_per_tile, 10 * coord::settings::phys_per_tile, 0}, camgame_window{400, 300}, camhud_window{0, 600}, tile_halfsize{48, 24}, // TODO: get from convert script data_dir(data_dir), audio_manager{48000, AUDIO_S16LSB, 2, 4096} { // enqueue the engine's own input handler to the // execution list. this->register_input_action(&this->input_handler); this->input_handler.register_resize_action(this); if (SDL_Init(SDL_INIT_VIDEO) < 0) { throw util::Error("SDL video initialization: %s", SDL_GetError()); } else { log::msg("initialized SDL video subsystems."); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); int32_t window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED; this->window = SDL_CreateWindow( windowtitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->window_size.x, this->window_size.y, window_flags ); if (this->window == nullptr) { throw util::Error("Failed creating SDL window: %s", SDL_GetError()); } // load support for the PNG image formats, jpg bit: IMG_INIT_JPG int wanted_image_formats = IMG_INIT_PNG; int sdlimg_inited = IMG_Init(wanted_image_formats); if ((sdlimg_inited & wanted_image_formats) != wanted_image_formats) { throw util::Error("Failed to init PNG support: %s", IMG_GetError()); } this->glcontext = SDL_GL_CreateContext(this->window); if (this->glcontext == nullptr) { throw util::Error("Failed creating OpenGL context: %s", SDL_GetError()); } // initialize glew, for shaders n stuff GLenum glew_state = glewInit(); if (glew_state != GLEW_OK) { throw util::Error("GLEW initialization failed"); } if (!GLEW_VERSION_2_1) { throw util::Error("OpenGL 2.1 not available"); } // to quote the standard doc: // 'The value gives a rough estimate // of the largest texture that the GL can handle' // -> wat? // anyways, we need at least 1024x1024. int max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); log::dbg("Maximum supported texture size: %d", max_texture_size); if (max_texture_size < 1024) { throw util::Error("Maximum supported texture size too small: %d", max_texture_size); } int max_texture_units; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units); log::dbg("Maximum supported texture units: %d", max_texture_units); if (max_texture_size < 2) { throw util::Error("Your GPU has too less texture units: %d", max_texture_units); } // vsync on SDL_GL_SetSwapInterval(1); // enable alpha blending glEnable(GL_BLEND); // order of drawing relevant for depth // what gets drawn last is displayed on top. glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // initialize debug text font this->dejavuserif20 = new Font{"DejaVu Serif", "Book", 20}; // initialize job manager with cpucount-2 worker threads int number_of_worker_threads = SDL_GetCPUCount() - 2; if (number_of_worker_threads <= 0) { number_of_worker_threads = 1; } this->job_manager = new job::JobManager{number_of_worker_threads}; // initialize audio auto devices = audio::AudioManager::get_devices(); if (devices.empty()) { throw util::Error{"No audio devices found"}; } }
SDL_Renderer * GLES_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_Renderer *renderer; GLES_RenderData *data; GLint value; int doublebuffer; #if SDL_VERSION_ATLEAST(1,3,0) if (!(window->flags & SDL_WINDOW_OPENGL)) { if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) { return NULL; } } #endif renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { GLES_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } renderer->ActivateRenderer = GLES_ActivateRenderer; renderer->DisplayModeChanged = GLES_DisplayModeChanged; renderer->CreateTexture = GLES_CreateTexture; renderer->QueryTexturePixels = GLES_QueryTexturePixels; renderer->SetTexturePalette = GLES_SetTexturePalette; renderer->GetTexturePalette = GLES_GetTexturePalette; renderer->SetTextureColorMod = GLES_SetTextureColorMod; renderer->SetTextureAlphaMod = GLES_SetTextureAlphaMod; renderer->SetTextureBlendMode = GLES_SetTextureBlendMode; renderer->SetTextureScaleMode = GLES_SetTextureScaleMode; renderer->UpdateTexture = GLES_UpdateTexture; renderer->LockTexture = GLES_LockTexture; renderer->UnlockTexture = GLES_UnlockTexture; renderer->DirtyTexture = GLES_DirtyTexture; renderer->RenderDrawPoints = GLES_RenderDrawPoints; renderer->RenderDrawLines = GLES_RenderDrawLines; renderer->RenderDrawRects = GLES_RenderDrawRects; renderer->RenderFillRects = GLES_RenderFillRects; renderer->RenderCopy = GLES_RenderCopy; renderer->RenderPresent = GLES_RenderPresent; renderer->DestroyTexture = GLES_DestroyTexture; renderer->DestroyRenderer = GLES_DestroyRenderer; renderer->info = GL_ES_RenderDriver.info; renderer->window = window; renderer->driverdata = data; renderer->info.flags = (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED); #if defined(__QNXNTO__) #if _NTO_VERSION<=641 /* QNX's OpenGL ES implementation is broken regarding */ /* packed textures support, affected versions 6.3.2, 6.4.0, 6.4.1 */ renderer->info.num_texture_formats = 2; renderer->info.texture_formats[0] = SDL_PIXELFORMAT_ABGR8888; renderer->info.texture_formats[1] = SDL_PIXELFORMAT_BGR24; #endif /* _NTO_VERSION */ #endif /* __QNXNTO__ */ if (GLES_LoadFunctions(data) < 0) { GLES_DestroyRenderer(renderer); return NULL; } data->context = SDL_GL_CreateContext(window); if (!data->context) { GLES_DestroyRenderer(renderer); return NULL; } if (SDL_GL_MakeCurrent(window, data->context) < 0) { GLES_DestroyRenderer(renderer); return NULL; } if (flags & SDL_RENDERER_PRESENTVSYNC) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); } if (SDL_GL_GetSwapInterval() > 0) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } #if SDL_VERSION_ATLEAST(1,3,0) // Always double-buffered #else if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) { if (!doublebuffer) { renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER; } } #endif #if SDL_VIDEO_DRIVER_PANDORA data->GL_OES_draw_texture_supported = SDL_FALSE; data->useDrawTexture = SDL_FALSE; #else if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) { data->GL_OES_draw_texture_supported = SDL_TRUE; data->useDrawTexture = SDL_TRUE; } else { data->GL_OES_draw_texture_supported = SDL_FALSE; data->useDrawTexture = SDL_FALSE; } #ifdef ANDROID data->GL_OES_draw_texture_supported = SDL_TRUE; data->useDrawTexture = SDL_TRUE; #endif #endif data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_width = value; data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_height = value; /* Set up parameters for rendering */ data->blendMode = -1; data->glDisable(GL_DEPTH_TEST); data->glDisable(GL_CULL_FACE); data->updateSize = SDL_TRUE; return renderer; }
core::AppState Client::onInit() { eventBus()->subscribe<network::NewConnectionEvent>(*this); eventBus()->subscribe<network::DisconnectEvent>(*this); eventBus()->subscribe<voxel::WorldCreatedEvent>(*this); GLDebug::enable(GLDebug::Medium); core::AppState state = UIApp::onInit(); if (state != core::Running) return state; if (!_network->start()) return core::Cleanup; core::Var::get(cfg::ClientName, "noname"); core::Var::get(cfg::ClientPassword, "nopassword"); if (!_worldShader.init()) { return core::Cleanup; } if (!_meshShader->init()) { return core::Cleanup; } if (!_waterShader->init()) { return core::Cleanup; } _waterTexture = video::TexturePtr(new video::Texture("texture/water.png")); _waterTexture->load(); const glm::vec3 vertices[4] = { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f) }; const glm::ivec3 indices[2] = { glm::ivec3( 0, 1, 2 ), glm::ivec3( 1, 3, 2 ) }; glGenVertexArrays(1, &_waterData.vertexArrayObject); core_assert(_waterData.vertexArrayObject > 0); glBindVertexArray(_waterData.vertexArrayObject); glGenBuffers(1, &_waterData.vertexBuffer); core_assert(_waterData.vertexBuffer > 0); glBindBuffer(GL_ARRAY_BUFFER, _waterData.vertexBuffer); glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(glm::vec3), vertices, GL_STATIC_DRAW); glGenBuffers(1, &_waterData.indexBuffer); core_assert(_waterData.indexBuffer > 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _waterData.indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * sizeof(glm::ivec2), indices, GL_STATIC_DRAW); const int posLoc = _waterShader->enableVertexAttribute("a_pos"); glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(voxel::VoxelVertexDecoded), GL_OFFSET(offsetof(voxel::VoxelVertexDecoded, position))); glBindVertexArray(0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); _waterData.noOfIndices = 2; _waterData.scale = 1.0f; _waterData.indexType = GL_UNSIGNED_INT; GL_checkError(); _camera.init(_width, _height); registerMoveCmd("+move_right", MOVERIGHT); registerMoveCmd("+move_left", MOVELEFT); registerMoveCmd("+move_forward", MOVEFORWARD); registerMoveCmd("+move_backward", MOVEBACKWARD); const int ColorTextureSize = 256; uint8_t colorTexture[ColorTextureSize * ColorTextureSize * 3]; noise::Simplex::SeamlessNoise2DRGB(colorTexture, ColorTextureSize, 3, 0.3f, 0.7f); _colorTexture = video::TexturePtr(new video::Texture(colorTexture, ColorTextureSize, ColorTextureSize, 3)); _clearColor = glm::vec3(0.0, 0.6, 0.796); _root.SetSkinBg(TBIDC("background")); new frontend::LoginWindow(this); SDL_GL_SetSwapInterval(core::Var::get(cfg::ClientVSync, "false")->boolVal()); return state; }
SDL_Renderer * GLES_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_Renderer *renderer; GLES_RenderData *data; GLint value; Uint32 windowFlags; int profile_mask, major, minor; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); windowFlags = SDL_GetWindowFlags(window); if (!(windowFlags & SDL_WINDOW_OPENGL) || profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) { /* Uh oh, better try to put it back... */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); SDL_RecreateWindow(window, windowFlags); return NULL; } } renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { GLES_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } renderer->WindowEvent = GLES_WindowEvent; renderer->CreateTexture = GLES_CreateTexture; renderer->UpdateTexture = GLES_UpdateTexture; renderer->LockTexture = GLES_LockTexture; renderer->UnlockTexture = GLES_UnlockTexture; renderer->SetRenderTarget = GLES_SetRenderTarget; renderer->UpdateViewport = GLES_UpdateViewport; renderer->UpdateClipRect = GLES_UpdateClipRect; renderer->RenderClear = GLES_RenderClear; renderer->RenderDrawPoints = GLES_RenderDrawPoints; renderer->RenderDrawLines = GLES_RenderDrawLines; renderer->RenderFillRects = GLES_RenderFillRects; renderer->RenderCopy = GLES_RenderCopy; renderer->RenderCopyEx = GLES_RenderCopyEx; renderer->RenderReadPixels = GLES_RenderReadPixels; renderer->RenderPresent = GLES_RenderPresent; renderer->DestroyTexture = GLES_DestroyTexture; renderer->DestroyRenderer = GLES_DestroyRenderer; renderer->GL_BindTexture = GLES_BindTexture; renderer->GL_UnbindTexture = GLES_UnbindTexture; renderer->info = GLES_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; data->context = SDL_GL_CreateContext(window); if (!data->context) { GLES_DestroyRenderer(renderer); return NULL; } if (SDL_GL_MakeCurrent(window, data->context) < 0) { GLES_DestroyRenderer(renderer); return NULL; } if (GLES_LoadFunctions(data) < 0) { GLES_DestroyRenderer(renderer); return NULL; } if (flags & SDL_RENDERER_PRESENTVSYNC) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); } if (SDL_GL_GetSwapInterval() > 0) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } #if SDL_VIDEO_DRIVER_PANDORA data->GL_OES_draw_texture_supported = SDL_FALSE; data->useDrawTexture = SDL_FALSE; #else if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) { data->GL_OES_draw_texture_supported = SDL_TRUE; data->useDrawTexture = SDL_TRUE; } else { data->GL_OES_draw_texture_supported = SDL_FALSE; data->useDrawTexture = SDL_FALSE; } #endif value = 0; data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_width = value; value = 0; data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_height = value; /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */ if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) { data->GL_OES_framebuffer_object_supported = SDL_TRUE; renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; value = 0; data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value); data->window_framebuffer = (GLuint)value; } data->framebuffers = NULL; if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) { data->GL_OES_blend_func_separate_supported = SDL_TRUE; } /* Set up parameters for rendering */ GLES_ResetState(renderer); return renderer; }
static int lua_SDL_GL_SetSwapInterval(lutok::state& state){ state.push_boolean(SDL_GL_SetSwapInterval((state.to_boolean(1)) ? 1 : 0) == 0); return 1; }
int video_mode(int f, int w, int h) { int stereo = config_get_d(CONFIG_STEREO) ? 1 : 0; int stencil = config_get_d(CONFIG_REFLECTION) ? 1 : 0; int buffers = config_get_d(CONFIG_MULTISAMPLE) ? 1 : 0; int samples = config_get_d(CONFIG_MULTISAMPLE); int vsync = config_get_d(CONFIG_VSYNC) ? 1 : 0; int hmd = config_get_d(CONFIG_HMD) ? 1 : 0; int dpy = config_get_d(CONFIG_DISPLAY); int X = SDL_WINDOWPOS_CENTERED_DISPLAY(dpy); int Y = SDL_WINDOWPOS_CENTERED_DISPLAY(dpy); hmd_free(); if (window) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); } SDL_GL_SetAttribute(SDL_GL_STEREO, stereo); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); /* Require 16-bit double buffer with 16-bit depth buffer. */ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); /* Try to set the currently specified mode. */ window = SDL_CreateWindow("", X, Y, w, h, SDL_WINDOW_OPENGL | (f ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); if (window) { set_window_title(TITLE); set_window_icon(ICON); SDL_GetWindowSize(window, &w, &h); config_set_d(CONFIG_DISPLAY, video_display()); config_set_d(CONFIG_FULLSCREEN, f); config_set_d(CONFIG_WIDTH, w); config_set_d(CONFIG_HEIGHT, h); context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(vsync); if (!glext_init()) return 0; glViewport(0, 0, w, h); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glEnable(GL_NORMALIZE); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_BLEND); #if !ENABLE_OPENGLES glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); #endif glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthFunc(GL_LEQUAL); /* If GL supports multisample, and SDL got a multisample buffer... */ if (glext_check("ARB_multisample")) { SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers); if (buffers) glEnable(GL_MULTISAMPLE); } /* Set up HMD display if requested. */ if (hmd) hmd_init(); /* Initialize screen snapshotting. */ snapshot_init(); video_show_cursor(); /* Grab input immediately in HMD mode. */ if (hmd_stat()) SDL_SetWindowGrab(window, SDL_TRUE); return 1; } /* If the mode failed, try it without stereo. */ else if (stereo) { config_set_d(CONFIG_STEREO, 0); return video_mode(f, w, h); } /* If the mode failed, try decreasing the level of multisampling. */ else if (buffers) { config_set_d(CONFIG_MULTISAMPLE, samples / 2); return video_mode(f, w, h); } /* If that mode failed, try it without reflections. */ else if (stencil) { config_set_d(CONFIG_REFLECTION, 0); return video_mode(f, w, h); } /* If THAT mode failed, punt. */ return 0; }
bool DecafSDLOpenGL::initialise(int width, int height) { if (SDL_GL_LoadLibrary(NULL) != 0) { gCliLog->error("Failed to load OpenGL library: {}", SDL_GetError()); return false; } 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_DOUBLEBUFFER, 1); // Set to OpenGL 4.5 core profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Enable debug context if (decaf::config::gpu::debug) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); } // Create TV window mWindow = SDL_CreateWindow("Decaf", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE); if (!mWindow) { gCliLog->error("Failed to create GL SDL window"); return false; } SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); // Create OpenGL context mContext = SDL_GL_CreateContext(mWindow); if (!mContext) { gCliLog->error("Failed to create Main OpenGL context: {}", SDL_GetError()); return false; } mThreadContext = SDL_GL_CreateContext(mWindow); if (!mThreadContext) { gCliLog->error("Failed to create GPU OpenGL context: {}", SDL_GetError()); return false; } SDL_GL_MakeCurrent(mWindow, mContext); // Setup decaf driver auto glDriver = decaf::createGLDriver(); decaf_check(glDriver); mDecafDriver = reinterpret_cast<decaf::OpenGLDriver*>(glDriver); // Setup rendering initialiseContext(); initialiseDraw(); decaf::debugger::initialiseUiGL(); // Start graphics thread if (!config::gpu::force_sync) { SDL_GL_SetSwapInterval(1); mGraphicsThread = std::thread{ [this]() { SDL_GL_MakeCurrent(mWindow, mThreadContext); initialiseContext(); mDecafDriver->run(); } }; } else { // Set the swap interval to 0 so that we don't slow // down the GPU system when presenting... The game should // throttle our swapping automatically anyways. SDL_GL_SetSwapInterval(0); // Switch to the thread context, we automatically switch // back when presenting a frame. SDL_GL_MakeCurrent(mWindow, mThreadContext); // Initialise the context initialiseContext(); } return true; }
SDLContext::SDLContext(const rainbow::Config& config) : window_(nullptr), vsync_(false), fullscreen_(0), context_(nullptr) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) { LOGF("SDL: Unable to initialise video: %s", SDL_GetError()); return; } #ifdef RAINBOW_OS_MACOS // Prevent the full screen window from being minimized when losing focus. SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); #endif 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, 0); if (config.msaa() > 0) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config.msaa()); } const uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (config.high_dpi() ? SDL_WINDOW_ALLOW_HIGHDPI : 0); const Vec2i& size = ::window_size(config); window_ = SDL_CreateWindow(RAINBOW_BUILD, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, size.x, size.y, flags); if (!window_) { R_ABORT("SDL: Failed to create window: %s", SDL_GetError()); return; } context_ = SDL_GL_CreateContext(window_); if (!context_) { R_ABORT("SDL: Failed to create GL context: %s", SDL_GetError()); return; } #ifdef RAINBOW_JS vsync_ = true; #else SDL_GL_SetSwapInterval(1); vsync_ = SDL_GL_GetSwapInterval() == 1; #endif #ifndef NDEBUG const Vec2i& resolution = drawable_size(); LOGI("SDL: Resolution: %ix%i", resolution.x, resolution.y); int msaa = 0; SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa); if (msaa > 0) LOGI("SDL: Anti-aliasing: %ix MSAA", msaa); else LOGI("SDL: Anti-aliasing: Disabled"); LOGI("SDL: Vertical sync: %s", (vsync_ ? "Enabled" : "Disabled")); #endif }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode( int mode, qboolean fullscreen, qboolean noborder ) { const char *glstring; int perChannelColorBits; int alphaBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; SDL_DisplayMode desktopMode; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; int x, y; GLenum glewResult; ri.Printf( PRINT_ALL, "Initializing OpenGL display\n" ); if ( r_allowResize->integer ) { flags |= SDL_WINDOW_RESIZABLE; } if ( r_centerWindow->integer ) { // center window on specified display x = SDL_WINDOWPOS_CENTERED_DISPLAY( r_displayIndex->integer ); y = SDL_WINDOWPOS_CENTERED_DISPLAY( r_displayIndex->integer ); } else { x = SDL_WINDOWPOS_UNDEFINED_DISPLAY( r_displayIndex->integer ); y = SDL_WINDOWPOS_UNDEFINED_DISPLAY( r_displayIndex->integer ); } icon = SDL_CreateRGBSurfaceFrom( ( void * ) CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); if ( SDL_GetDesktopDisplayMode( r_displayIndex->integer, &desktopMode ) == 0 ) { displayAspect = ( float ) desktopMode.w / ( float ) desktopMode.h; ri.Printf( PRINT_ALL, "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); ri.Printf( PRINT_ALL, "Cannot determine display aspect (%s), assuming 1.333\n", SDL_GetError() ); } ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( mode == -2 ) { // use desktop video resolution if ( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; ri.Printf( PRINT_ALL, "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.windowAspect = ( float ) glConfig.vidWidth / ( float ) glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); do { if ( glContext != NULL ) { SDL_GL_DeleteContext( glContext ); glContext = NULL; } if ( window != NULL ) { SDL_GetWindowPosition( window, &x, &y ); ri.Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( window ); window = NULL; } // we come back here if we couldn't get a visual and there's // something we can switch off if ( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if ( noborder ) { flags |= SDL_WINDOW_BORDERLESS; } glConfig.isFullscreen = qfalse; } colorBits = r_colorbits->integer; if ( ( !colorBits ) || ( colorBits >= 32 ) ) { colorBits = 24; } alphaBits = r_alphabits->integer; if ( alphaBits < 0 ) { alphaBits = 0; } depthBits = r_depthbits->integer; if ( !depthBits ) { depthBits = 24; } stencilBits = r_stencilbits->integer; samples = r_ext_multisample->integer; for ( i = 0; i < 16; i++ ) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorBits == 24 ) { colorBits = 16; } break; case 1: if ( depthBits == 24 ) { depthBits = 16; } else if ( depthBits == 16 ) { depthBits = 8; } case 3: if ( stencilBits == 24 ) { stencilBits = 16; } else if ( stencilBits == 16 ) { stencilBits = 8; } } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( testColorBits == 24 ) { testColorBits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( testDepthBits == 24 ) { testDepthBits = 16; } else if ( testDepthBits == 16 ) { testDepthBits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( testStencilBits == 24 ) { testStencilBits = 16; } else if ( testStencilBits == 16 ) { testStencilBits = 8; } else { testStencilBits = 0; } } if ( testColorBits == 24 ) { perChannelColorBits = 8; } else { perChannelColorBits = 4; } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, alphaBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if !SDL_VERSION_ATLEAST( 2, 0, 0 ) SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ); #endif #if SDL_VERSION_ATLEAST( 2, 0, 0 ) if ( !r_glAllowSoftware->integer ) { SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); } if ( r_glCoreProfile->integer || r_glDebugProfile->integer ) { int major = r_glMajorVersion->integer; int minor = r_glMinorVersion->integer; SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, major ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, minor ); if ( r_glCoreProfile->integer ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); } else { SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); } if ( r_glDebugProfile->integer ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG ); } } #endif window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ); if ( !window ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError() ); continue; } SDL_SetWindowIcon( window, icon ); glContext = SDL_GL_CreateContext( window ); if ( !glContext ) { ri.Printf( PRINT_DEVELOPER, "SDL_GL_CreateContext failed: %s\n", SDL_GetError() ); continue; } #if SDL_VERSION_ATLEAST( 2, 0, 0 ) SDL_GL_SetSwapInterval( r_swapInterval->integer ); #endif SDL_ShowCursor( 0 ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; ri.Printf( PRINT_ALL, "Using %d Color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } if ( samples && ( !glContext || !window ) ) { r_ext_multisample->integer = 0; } } while ( ( !glContext || !window ) && samples ); SDL_FreeSurface( icon ); glewResult = glewInit(); if ( glewResult != GLEW_OK ) { // glewInit failed, something is seriously wrong ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem: %s", glewGetErrorString( glewResult ) ); } else { ri.Printf( PRINT_ALL, "Using GLEW %s\n", glewGetString( GLEW_VERSION ) ); } int GLmajor, GLminor; sscanf( ( const char * ) glGetString( GL_VERSION ), "%d.%d", &GLmajor, &GLminor ); if ( GLmajor < 2 || ( GLmajor == 2 && GLminor < 1 ) ) { // missing shader support, switch to 1.x renderer return RSERR_OLD_GL; } if ( GLmajor < 3 || ( GLmajor == 3 && GLminor < 2 ) ) { // shaders are supported, but not all GL3.x features ri.Printf( PRINT_ALL, "Using enhanced (GL3) Renderer in GL 2.x mode...\n" ); } else { ri.Printf( PRINT_ALL, "Using enhanced (GL3) Renderer in GL 3.x mode...\n" ); glConfig.driverType = GLDRV_OPENGL3; } #if defined( SMP ) && !SDL_VERSION_ATLEAST( 2, 0, 0 ) // setup context for SDL_GL_MakeCurrent SDL_GL_GetCurrentContext(); #endif GLimp_DetectAvailableModes(); glstring = ( char * ) glGetString( GL_RENDERER ); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }
bool GBASDLInit(struct SDLSoftwareRenderer* renderer) { #ifndef COLOR_16_BIT SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); #else SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); #ifdef COLOR_5_6_5 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); #else SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); #endif SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); #endif #if SDL_VERSION_ATLEAST(2, 0, 0) renderer->window = SDL_CreateWindow(PROJECT_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->events.fullscreen)); SDL_GL_CreateContext(renderer->window); SDL_GL_SetSwapInterval(1); SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight); renderer->events.window = renderer->window; #else SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); #ifdef COLOR_16_BIT SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_OPENGL); #else SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_OPENGL); #endif #endif renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS; glGenTextures(1, &renderer->tex); glBindTexture(GL_TEXTURE_2D, renderer->tex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); if (renderer->filter) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } #ifndef _WIN32 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #endif #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); #else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0); #endif #else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); #endif glViewport(0, 0, renderer->viewportWidth, renderer->viewportHeight); return true; }
int main( int argc, char* argv[] ) { GLboolean running; // Initialise SDL2 if( 0 != SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS ) ) { fprintf( stderr, "Failed to initialize SDL2: %s\n", SDL_GetError() ); exit( EXIT_FAILURE ); } // Open OpenGL window SDL_Window * window = SDL_CreateWindow( "SOIL2 Test",SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN ); if( NULL == window ) { fprintf( stderr, "Failed to open SDL2 window: %s\n", SDL_GetError() ); exit( EXIT_FAILURE ); } SDL_GLContext context = SDL_GL_CreateContext( window ); if ( NULL == context ) { fprintf( stderr, "Failed to create SDL2 OpenGL Context: %s\n", SDL_GetError() ); SDL_DestroyWindow( window ); exit( EXIT_FAILURE ); } SDL_GL_SetSwapInterval( 1 ); SDL_GL_MakeCurrent( window, context ); // log what the use is asking us to load std::string load_me; if ( argc >= 2 ) { load_me = std::string( argv[1] ); } else { load_me = ResourcePath( "img_test.png" ); } std::cout << "'" << load_me << "'" << std::endl; // 1st try to load it as a single-image-cubemap // (note, need DDS ordered faces: "EWUDNS") GLuint tex_ID; Uint64 time_me; std::cout << "Attempting to load as a cubemap" << std::endl; time_me = SDL_GetPerformanceCounter(); tex_ID = SOIL_load_OGL_single_cubemap( load_me.c_str(), SOIL_DDS_CUBEMAP_FACE_ORDER, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_DDS_LOAD_DIRECT | SOIL_FLAG_PVR_LOAD_DIRECT | SOIL_FLAG_ETC1_LOAD_DIRECT ); std::cout << "the load time was " << get_total_ms(time_me) << " milliseconds" << std::endl; if( tex_ID > 0 ) { glEnable( GL_TEXTURE_CUBE_MAP ); glEnable( GL_TEXTURE_GEN_S ); glEnable( GL_TEXTURE_GEN_T ); glEnable( GL_TEXTURE_GEN_R ); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP ); glBindTexture( GL_TEXTURE_CUBE_MAP, tex_ID ); std::cout << "the loaded single cube map ID was " << tex_ID << std::endl; } else { std::cout << "Attempting to load as a HDR texture" << std::endl; time_me = SDL_GetPerformanceCounter(); tex_ID = SOIL_load_OGL_HDR_texture( load_me.c_str(), SOIL_HDR_RGBdivA2, 0, SOIL_CREATE_NEW_ID, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_GL_MIPMAPS ); std::cout << "the load time was " << get_total_ms(time_me) << " milliseconds" << std::endl; // did I fail? if( tex_ID < 1 ) { // loading of the single-image-cubemap failed, try it as a simple texture std::cout << "Attempting to load as a simple 2D texture" << std::endl; // load the texture, if specified time_me = SDL_GetPerformanceCounter(); tex_ID = SOIL_load_OGL_texture( load_me.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_GL_MIPMAPS | SOIL_FLAG_DDS_LOAD_DIRECT | SOIL_FLAG_PVR_LOAD_DIRECT | SOIL_FLAG_ETC1_LOAD_DIRECT | SOIL_FLAG_COMPRESS_TO_DXT ); std::cout << "the load time was " << get_total_ms(time_me) << " milliseconds" << std::endl; } if( tex_ID > 0 ) { // enable texturing glEnable( GL_TEXTURE_2D ); // bind an OpenGL texture ID glBindTexture( GL_TEXTURE_2D, tex_ID ); // report std::cout << "the loaded texture ID was " << tex_ID << std::endl; } else { // loading of the texture failed...why? glDisable( GL_TEXTURE_2D ); std::cout << "Texture loading failed: '" << SOIL_last_result() << "'" << std::endl; } } running = GL_TRUE; const float ref_mag = 0.1f; float theta = 0.0f; float tex_u_max = 1.0f; float tex_v_max = 1.0f; Uint64 counterOld = SDL_GetPerformanceCounter(); while( running ) { float dt = (float)((double)(SDL_GetPerformanceCounter() - counterOld) / (double)SDL_GetPerformanceFrequency()); counterOld = SDL_GetPerformanceCounter(); SDL_Event evt; while (SDL_PollEvent(&evt)) { switch (evt.type) { case SDL_QUIT: { running = false; break; } case SDL_KEYUP: { if ( SDLK_ESCAPE == evt.key.keysym.sym ) { running = false; } break; } } } theta += dt * 40; glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // Draw our textured geometry (just a rectangle in this instance) glPushMatrix(); glScalef( 0.8f, 0.8f, 0.8f ); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glNormal3f( 0.0f, 0.0f, 1.0f ); glBegin(GL_QUADS); glNormal3f( -ref_mag, -ref_mag, 1.0f ); glTexCoord2f( 0.0f, tex_v_max ); glVertex3f( -1.0f, -1.0f, -0.1f ); glNormal3f( ref_mag, -ref_mag, 1.0f ); glTexCoord2f( tex_u_max, tex_v_max ); glVertex3f( 1.0f, -1.0f, -0.1f ); glNormal3f( ref_mag, ref_mag, 1.0f ); glTexCoord2f( tex_u_max, 0.0f ); glVertex3f( 1.0f, 1.0f, -0.1f ); glNormal3f( -ref_mag, ref_mag, 1.0f ); glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, 1.0f, -0.1f ); glEnd(); glPopMatrix(); glPushMatrix(); glScalef( 0.8f, 0.8f, 0.8f ); glRotatef(theta, 0.0f, 0.0f, 1.0f); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glNormal3f( 0.0f, 0.0f, 1.0f ); glBegin(GL_QUADS); glTexCoord2f( 0.0f, tex_v_max ); glVertex3f( 0.0f, 0.0f, 0.1f ); glTexCoord2f( tex_u_max, tex_v_max ); glVertex3f( 1.0f, 0.0f, 0.1f ); glTexCoord2f( tex_u_max, 0.0f ); glVertex3f( 1.0f, 1.0f, 0.1f ); glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 0.0f, 1.0f, 0.1f ); glEnd(); glPopMatrix(); // Swap buffers SDL_GL_SwapWindow( window ); } // Close OpenGL window and terminate SDL2 SDL_GL_DeleteContext( context ); SDL_DestroyWindow( window ); exit( EXIT_SUCCESS ); }
void rockpush_init_game(Rock_Screen *screen_data) { SDL_Event event; Rock_Sprite *object_rocco; Rock_Scroll_Map map; int16_t current_level; bool done = false; Uint32 init_ms; Uint32 move_ms; SDL_Joystick *joystick = NULL; Sint16 joy_event = 0; if (SDL_NumJoysticks() >= 1) { joystick = SDL_JoystickOpen(0); SDL_JoystickEventState(SDL_ENABLE); } map.view_height = VIEW_HEIGHT; map.view_width = VIEW_WIDTH; map.scroll_shift = SCROLL_SHIFT; map.diamonds = 0; map.level = 0; map.points = 0; map.lives = INIT_ROCCO_LIVE; map.update_score = false; map.refresh_rocco = false; map.rocco_death = false; current_level = map.level; screen_show_background(screen_data->screen); sprites_set_tiles_textures(); object_rocco = set_level_rocco(&map); set_score(&map, screen_data); if (sfx_get_active()) { sfx_set_level_music(&map); Mix_PlayMusic(map.level_music, -1); } SDL_GL_SetSwapInterval(0); distorsion_in(&map, screen_data); while (!done) { init_ms = SDL_GetTicks(); while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) done = true; if (SDL_JoystickGetAttached(joystick)) joy_event = SDL_JoystickGetAxis(joystick, 0) | SDL_JoystickGetAxis(joystick, 1); while (event.type == SDL_KEYDOWN || event.type == SDL_JOYBUTTONDOWN || joy_event) { move_ms = SDL_GetTicks(); if (SDL_JoystickGetAttached(joystick)) { joy_event = SDL_JoystickGetAxis(joystick, 0) | SDL_JoystickGetAxis(joystick, 1); if (SDL_JoystickGetButton(joystick, 0)) done = true; if (SDL_JoystickGetButton(joystick, 1)) map.rocco_death = true; } /*if (event.key.keysym.sym == SDLK_n) map.level ++;*/ // Reinicia el nivel if (event.key.keysym.sym == SDLK_r) map.rocco_death = true; set_position(object_rocco, event, joystick); sprites_update(&map); map_show(screen_data, &map, false); screen_dump_buffer(screen_data, map.view_width, map.view_height); SDL_PollEvent(&event); if (map.update_score) { set_score(&map, screen_data); map.update_score = false; } if (map.level > current_level && map.level < TOTAL_LEVELS) { sfx_play(SFX_LEVEL); if (sfx_get_active()) { Mix_HaltMusic(); Mix_FreeMusic(map.level_music); sfx_set_level_music(&map); Mix_PlayMusic(map.level_music, -1); } distorsion_out(&map, screen_data); free(sprites); object_rocco = set_level_rocco(&map); current_level = map.level; set_score(&map, screen_data); distorsion_in(&map, screen_data); } else if (map.level >= TOTAL_LEVELS) done = true; if (map.refresh_rocco) { object_rocco = sprite_get_object(map.rocco_index); map.refresh_rocco = false; } while ((SDL_GetTicks() - move_ms) < TICK_RATE); } if (event.type == SDL_KEYUP || !joy_event) { rocco_set_action(object_rocco, WAIT_LEFT); sprites_push_off(&map); } } sprites_update(&map); map_show(screen_data, &map, false); screen_dump_buffer(screen_data, map.view_width, map.view_height); if (map.update_score) { set_score(&map, screen_data); map.update_score = false; } // Si se añaden más elementos al mapa (realloc), hay que reasignar el puntero del personaje if (map.refresh_rocco) { object_rocco = sprite_get_object(map.rocco_index); map.refresh_rocco = false; } if (map.rocco_death) { map.lives --; if (map.lives <= 0) done = true; else { free(sprites); object_rocco = set_level_rocco(&map); current_level = map.level; set_score(&map, screen_data); map.rocco_death = false; } } while ((SDL_GetTicks() - init_ms) < TICK_RATE); } if (sfx_get_active()) { Mix_HaltMusic(); Mix_FreeMusic(map.level_music); } distorsion_out(&map, screen_data); SDL_GL_SetSwapInterval(0); if (SDL_JoystickGetAttached(joystick)) SDL_JoystickClose(joystick); }
bool initGL() { #ifdef DEBUG_DRIVERS /************ DEBUG DRIVERS ********************************/ // Identify video drivers (this is for debug) OUTSTREAM << "\nSDL found the following video drivers:\n"; int numdrivers = SDL_GetNumVideoDrivers(); const char* drivername; for (int i = 0; i < numdrivers; ++i) { drivername = SDL_GetVideoDriver(i); if (SDL_VideoInit(drivername) == 0) { SDL_VideoQuit(); OUTSTREAM << "\t\t Driver " << drivername << " works.\n"; } else { OUTSTREAM << "\t<!>\tDriver " << drivername << " DOES NOT WORK!\n"; } } // Identify render drivers (this is for debug) OUTSTREAM << "SDL found the following render drivers: "; numdrivers = SDL_GetNumRenderDrivers(); for (int i = 0; i < numdrivers; ++i) { SDL_RendererInfo info; SDL_GetRenderDriverInfo(i, &info); OUTSTREAM << info.name << ((i < numdrivers - 1)? ", " : "\n"); } #endif /************************** DEBUG DRIVERS ********************************/ // Initialize SDL overall. if (SDL_Init(SDL_INIT_VIDEO) < 0) { OUTSTREAM << "<!> SDL did not initialize! SDL Error: " << SDL_GetError() << std::endl; return false; } // SDL_GL_CONTEXT_CORE gives us only the newer version, deprecated functions are disabled SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Specify OpenGL version SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, GLVERSION_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, GLVERSION_MINOR); // Turn on double buffering with a 24bit Z buffer. // You may need to change this to 16 or 32 for your system SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Create the SDL window pWindow = SDL_CreateWindow("OpenGL Window", // name of window SDL_WINDOWPOS_CENTERED, // x position of window SDL_WINDOWPOS_CENTERED, // y position of window RESOLUTION_X, RESOLUTION_Y, // x and y width of window SCREENOPTIONS); // options (fullscreen, etc) // If the window couldn't be created for whatever reason if (pWindow == NULL) { OUTSTREAM << "<!> SDL window was not created! SDL Error: " << SDL_GetError() << std::endl; return false; } else { OUTSTREAM << "SDL window created.\n"; } //Create context context = SDL_GL_CreateContext(pWindow); //context is the place where openGL can draw if(context == NULL) { OUTSTREAM << "<!> OpenGL context was not created! SDL Error: " << SDL_GetError() << std::endl; return false; } else { OUTSTREAM << "GL context created.\n"; } checkGlError(__LINE__); //Initialize GLEW (openGL Extensions Wrangler) glewExperimental = GL_TRUE; // Sometimes things wont work without this line GLenum glewError = glewInit(); // GL enumerator error is thrown here when using openGL versions 3.2+ It's fine. // see https://www.opengl.org/wiki/OpenGL_Loading_Library if(glewError != GLEW_OK) { OUTSTREAM << "<!> Could not initialize GLEW! " << glewGetErrorString(glewError) << std::endl; return false; } else { OUTSTREAM << "GLEW initialized.\n"; } checkGlError(__LINE__); #ifdef USE_VSYNC /************ USE VSYNC ********************************/ if (SDL_GL_SetSwapInterval(1) < 0) { OUTSTREAM << "<!> Warning: Unable to set VSync! SDL Error: " << SDL_GetError() << std::endl; // Do not return. This is not an essential functionality. } else { OUTSTREAM << "VSync enabled.\n"; } #endif /********************** USE VSYNC ********************************/ // set openGL clear color glClearColor(CLEARCOLOR); #ifdef USE_DEPTHBUFFER // enable the occlusion of objects hidden behind other objects (using the depth buffer) glEnable(GL_DEPTH_TEST); // set the test for that occlusion to: "draw if distance of new fragment is less than or equal to old fragment" glDepthFunc(GL_LEQUAL); #endif #ifdef USE_BACKFACE_CULLING // enable the culling of back faces (back faces will not be drawn) glEnable(GL_CULL_FACE); #endif #ifdef USE_TRANSPARENCY // enable transparency glEnable (GL_BLEND); // set transparency function (this is standard transparency) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif checkGlError(__LINE__); checkSDLError(__LINE__); return true; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { const char *glstring; int perChannelColorBits; int colorBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; SDL_DisplayMode desktopMode; int display = 0; int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; ri.Printf( PRINT_ALL, "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_WINDOW_RESIZABLE; #ifdef USE_ICON icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); #endif // If a window exists, note its display index if( SDL_window != NULL ) display = SDL_GetWindowDisplayIndex( SDL_window ); if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; ri.Printf( PRINT_ALL, "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); ri.Printf( PRINT_ALL, "Cannot determine display aspect, assuming 1.333\n" ); } ri.Printf (PRINT_ALL, "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; ri.Printf( PRINT_ALL, "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); // Center window if( r_centerWindow->integer && !fullscreen ) { x = ( desktopMode.w / 2 ) - ( glConfig.vidWidth / 2 ); y = ( desktopMode.h / 2 ) - ( glConfig.vidHeight / 2 ); } // Destroy existing state if it exists if( SDL_glContext != NULL ) { SDL_GL_DeleteContext( SDL_glContext ); SDL_glContext = NULL; } if( SDL_window != NULL ) { SDL_GetWindowPosition( SDL_window, &x, &y ); ri.Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( SDL_window ); SDL_window = NULL; } if( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if( noborder ) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = qfalse; } colorBits = r_colorbits->value; if ((!colorBits) || (colorBits >= 32)) colorBits = 24; if (!r_depthbits->value) depthBits = 24; else depthBits = r_depthbits->value; stencilBits = r_stencilbits->value; samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorBits == 24) colorBits = 16; break; case 1 : if (depthBits == 24) depthBits = 16; else if (depthBits == 16) depthBits = 8; case 3 : if (stencilBits == 24) stencilBits = 16; else if (stencilBits == 16) stencilBits = 8; } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) { // reduce colorBits if (testColorBits == 24) testColorBits = 16; } if ((i % 4) == 2) { // reduce depthBits if (testDepthBits == 24) testDepthBits = 16; else if (testDepthBits == 16) testDepthBits = 8; } if ((i % 4) == 1) { // reduce stencilBits if (testStencilBits == 24) testStencilBits = 16; else if (testStencilBits == 16) testStencilBits = 8; else testStencilBits = 0; } if (testColorBits == 24) perChannelColorBits = 8; else perChannelColorBits = 4; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (perChannelColorBits == 4) perChannelColorBits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if(r_stereoEnabled->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if 0 // if multisampling is enabled on X11, this causes create window to fail. // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); #endif if( ( SDL_window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } if( fullscreen ) { SDL_DisplayMode mode; switch( testColorBits ) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: ri.Printf( PRINT_DEVELOPER, "testColorBits is %d, can't fullscreen\n", testColorBits ); continue; } mode.w = glConfig.vidWidth; mode.h = glConfig.vidHeight; mode.refresh_rate = glConfig.displayFrequency = ri.Cvar_VariableIntegerValue( "r_displayRefresh" ); mode.driverdata = NULL; if( SDL_SetWindowDisplayMode( SDL_window, &mode ) < 0 ) { ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } SDL_SetWindowIcon( SDL_window, icon ); if( ( SDL_glContext = SDL_GL_CreateContext( SDL_window ) ) == NULL ) { ri.Printf( PRINT_DEVELOPER, "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); continue; } qglClearColor( 0, 0, 0, 1 ); qglClear( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow( SDL_window ); SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; ri.Printf( PRINT_ALL, "Using %d color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } SDL_FreeSurface( icon ); if( !SDL_window ) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } GLimp_DetectAvailableModes(); glstring = (char *) qglGetString (GL_RENDERER); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }
int main(int, char**) { // Setup SDL if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { printf("Error: %s\n", SDL_GetError()); return -1; } // Setup window SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_DisplayMode current; SDL_GetCurrentDisplayMode(0, ¤t); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); // Enable vsync // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); // Setup Platform/Renderer bindings ImGui_ImplSDL2_InitForOpenGL(window, gl_context); ImGui_ImplOpenGL2_Init(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop bool done = false; while (!done) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_QUIT) done = true; } // Start the Dear ImGui frame ImGui_ImplOpenGL2_NewFrame(); ImGui_ImplSDL2_NewFrame(window); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). if (show_demo_window) ImGui::ShowDemoWindow(&show_demo_window); // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. { static float f = 0.0f; static int counter = 0; ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state ImGui::Checkbox("Another Window", &show_another_window); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::End(); } // 3. Show another simple window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) ImGui::Text("Hello from another window!"); if (ImGui::Button("Close Me")) show_another_window = false; ImGui::End(); } // Rendering ImGui::Render(); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(window); } // Cleanup ImGui_ImplOpenGL2_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); SDL_GL_DeleteContext(gl_context); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
Engine::Engine(util::Dir *data_dir, const char *windowtitle) : OptionNode{"Engine"}, running{false}, drawing_debug_overlay{this, "drawing_debug_overlay", true}, drawing_huds{this, "drawing_huds", true}, engine_coord_data{this->get_coord_data()}, current_player{this, "current_player", 1}, data_dir{data_dir}, audio_manager{} { for (uint32_t size : {12, 20}) { fonts[size] = std::unique_ptr<Font>{new Font{"DejaVu Serif", "Book", size}}; } this->logsink_file = std::make_unique<log::FileSink>("/tmp/openage-log", true); // enqueue the engine's own input handler to the // execution list. this->register_resize_action(this); // register the engines input manager this->register_input_action(&this->input_manager); if (SDL_Init(SDL_INIT_VIDEO) < 0) { throw Error(MSG(err) << "SDL video initialization: " << SDL_GetError()); } else { log::log(MSG(info) << "Initialized SDL video subsystems."); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); int32_t window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED; this->window = SDL_CreateWindow( windowtitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->engine_coord_data->window_size.x, this->engine_coord_data->window_size.y, window_flags ); if (this->window == nullptr) { throw Error(MSG(err) << "Failed to create SDL window: " << SDL_GetError()); } // load support for the PNG image formats, jpg bit: IMG_INIT_JPG int wanted_image_formats = IMG_INIT_PNG; int sdlimg_inited = IMG_Init(wanted_image_formats); if ((sdlimg_inited & wanted_image_formats) != wanted_image_formats) { throw Error(MSG(err) << "Failed to init PNG support: " << IMG_GetError()); } this->glcontext = SDL_GL_CreateContext(this->window); if (this->glcontext == nullptr) { throw Error(MSG(err) << "Failed creating OpenGL context: " << SDL_GetError()); } // check the OpenGL version, for shaders n stuff if (!epoxy_is_desktop_gl() || epoxy_gl_version() < 21) { throw Error(MSG(err) << "OpenGL 2.1 not available"); } // to quote the standard doc: // 'The value gives a rough estimate // of the largest texture that the GL can handle' // -> wat? // anyways, we need at least 1024x1024. int max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); log::log(MSG(dbg) << "Maximum supported texture size: " << max_texture_size); if (max_texture_size < 1024) { throw Error(MSG(err) << "Maximum supported texture size too small: " << max_texture_size); } int max_texture_units; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units); log::log(MSG(dbg) << "Maximum supported texture units: " << max_texture_units); if (max_texture_units < 2) { throw Error(MSG(err) << "Your GPU has too less texture units: " << max_texture_units); } // vsync on SDL_GL_SetSwapInterval(1); // enable alpha blending glEnable(GL_BLEND); // order of drawing relevant for depth // what gets drawn last is displayed on top. glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // initialize job manager with cpucount-2 worker threads int number_of_worker_threads = SDL_GetCPUCount() - 2; if (number_of_worker_threads <= 0) { number_of_worker_threads = 1; } this->job_manager = new job::JobManager{number_of_worker_threads}; // initialize audio auto devices = audio::AudioManager::get_devices(); if (devices.empty()) { throw Error{MSG(err) << "No audio devices found"}; } // initialize engine related global keybinds auto &global_input_context = this->get_input_manager().get_global_context(); global_input_context.bind(input::action_t::STOP_GAME, [this](const input::action_arg_t &) { this->stop(); }); global_input_context.bind(input::action_t::TOGGLE_HUD, [this](const input::action_arg_t &) { this->drawing_huds.value = !this->drawing_huds.value; }); global_input_context.bind(input::action_t::SCREENSHOT, [this](const input::action_arg_t &) { this->get_screenshot_manager().save_screenshot(); }); global_input_context.bind(input::action_t::TOGGLE_DEBUG_OVERLAY, [this](const input::action_arg_t &) { this->drawing_debug_overlay.value = !this->drawing_debug_overlay.value; }); global_input_context.bind(input::action_t::TOGGLE_PROFILER, [this](const input::action_arg_t &) { if (this->external_profiler.currently_profiling) { this->external_profiler.stop(); this->external_profiler.show_results(); } else { this->external_profiler.start(); } }); global_input_context.bind(input::event_class::MOUSE, [this](const input::action_arg_t &arg) { if (arg.e.cc.has_class(input::event_class::MOUSE_MOTION) && this->get_input_manager().is_down(input::event_class::MOUSE_BUTTON, 2)) { this->move_phys_camera(arg.motion.x, arg.motion.y); return true; } return false; }); // Switching between players with the 1-8 keys auto bind_player_switch = [this, &global_input_context](input::action_t action, int player) { global_input_context.bind(action, [this, player](const input::action_arg_t &) { this->current_player.value = player; }); }; bind_player_switch(input::action_t::SWITCH_TO_PLAYER_1, 1); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_2, 2); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_3, 3); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_4, 4); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_5, 5); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_6, 6); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_7, 7); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_8, 8); }
/* * Initializes the OpenGL window */ static qboolean GLimp_InitGraphics(qboolean fullscreen) { int flags; int msaa_samples; int stencil_bits; int width, height; char title[24]; if (GetWindowSize(&width, &height) && (width == vid.width) && (height == vid.height)) { /* If we want fullscreen, but aren't */ if (fullscreen != IsFullscreen()) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0); #else SDL_WM_ToggleFullScreen(window); #endif Cvar_SetValue("vid_fullscreen", fullscreen); } /* Are we now? */ if (fullscreen == IsFullscreen()) { return true; } } /* Is the surface used? */ if (window) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); #else SDL_FreeSurface(window); #endif } /* Create the window */ VID_NewWindow(vid.width, vid.height); 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_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); if ((int)Cvar_VariableValue("cl_stereo") == 1){ SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } if (gl_msaa_samples->value) { msaa_samples = gl_msaa_samples->value; if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) < 0) { Com_Printf("MSAA is unsupported: %s\n", SDL_GetError()); Cvar_SetValue ("gl_msaa_samples", 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } else if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_samples) < 0) { Com_Printf("MSAA %ix is unsupported: %s\n", msaa_samples, SDL_GetError()); Cvar_SetValue("gl_msaa_samples", 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } } /* Initiate the flags */ flags = SDL_OPENGL; if (fullscreen) { flags |= SDL_FULLSCREEN; } #if !SDL_VERSION_ATLEAST(2, 0, 0) /* For SDL1.2, these things must be done before creating the window */ /* Set the icon */ SetSDLIcon(); /* Set vsync */ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, gl_swapinterval->value ? 1 : 0); #endif while (1) { if (!CreateSDLWindow(flags)) { if (gl_msaa_samples->value) { VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n", SDL_GetError()); VID_Printf(PRINT_ALL, "Reverting to %s gl_mode %i (%ix%i) without MSAA.\n", (flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed", (int)Cvar_VariableValue("gl_mode"), vid.width, vid.height); /* Try to recover */ Cvar_SetValue("gl_msaa_samples", 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } else if ((int)Cvar_VariableValue("cl_stereo") == 1) { VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n", SDL_GetError()); Cvar_SetValue("cl_stereo", 0); SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } else if (vid.width != 640 || vid.height != 480 || (flags & SDL_FULLSCREEN)) { VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n", SDL_GetError()); VID_Printf(PRINT_ALL, "Reverting to windowed gl_mode 4 (640x480).\n"); /* Try to recover */ Cvar_SetValue("gl_mode", 4); Cvar_SetValue("vid_fullscreen", 0); vid.width = 640; vid.height = 480; flags &= ~SDL_FULLSCREEN; } else { VID_Error(ERR_FATAL, "Failed to revert to gl_mode 4. Exiting...\n"); return false; } } else { break; } } if (gl_msaa_samples->value) { if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0) { Cvar_SetValue("gl_msaa_samples", msaa_samples); } } #if SDL_VERSION_ATLEAST(2, 0, 0) /* For SDL2, these things must be done after creating the window */ /* Set the icon */ SetSDLIcon(); /* Set vsync - TODO: -1 could be set for "late swap tearing" */ SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0); #endif /* Initialize the stencil buffer */ if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits)) { VID_Printf(PRINT_ALL, "Got %d bits of stencil.\n", stencil_bits); if (stencil_bits >= 1) { have_stencil = true; } } /* Initialize hardware gamma */ InitGamma(); /* Window title */ snprintf(title, sizeof(title), "Yamagi Quake II %s", YQ2VERSION); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetWindowTitle(window, title); #else SDL_WM_SetCaption(title, title); #endif /* No cursor */ SDL_ShowCursor(0); return true; }
int main(int argc, char *argv[]) { #if PPSSPP_PLATFORM(RPI) bcm_host_init(); #endif putenv((char*)"SDL_VIDEO_CENTERED=1"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); 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) { 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; } } #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 // We really should upgrade to SDL 2.0 soon. //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); #endif #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); Uint32 mode; #ifdef USING_GLES2 mode = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; #else mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; #endif 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] }; 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]; } } // 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; #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else // 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, "/"); #endif #ifdef _WIN32 NativeInit(remain_argc, (const char **)remain_argv, path, "D:\\", nullptr); #else NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); #endif // Use the setting from the config when initing the window. if (g_Config.bFullScreen) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()),\ SDL_WINDOWPOS_UNDEFINED, pixel_xres, pixel_yres, mode); if (g_Screen == NULL) { NativeShutdown(); fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; } SDL_GLContext glContext = SDL_GL_CreateContext(g_Screen); if (glContext == NULL) { NativeShutdown(); fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; } #ifdef USING_EGL EGL_Init(); #endif SDL_SetWindowTitle(g_Screen, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif #ifndef USING_GLES2 // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. // glewExperimental allows us to force GLEW to search for the pointers anyway. if (gl_extensions.IsCoreContext) glewExperimental = true; if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; } // Unfortunately, glew will generate an invalid enum error, ignore. if (gl_extensions.IsCoreContext) glGetError(); if (GLEW_VERSION_2_0) { printf("OpenGL 2.0 or higher.\n"); } else { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } #endif 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 = new GLDummyGraphicsContext(); 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); #ifndef _WIN32 if (joystick_enabled) { joystick = new SDLJoystick(); } else { joystick = nullptr; } #endif EnableFZ(); int framecount = 0; float t = 0; float lastT = 0; bool mouseDown = false; 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(g_Screen); 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: #ifndef _WIN32 if (joystick) { joystick->ProcessInput(event); } #endif break; } } if (g_QuitRequested) break; const uint8_t *keys = SDL_GetKeyboardState(NULL); 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. } #ifdef USING_EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { SDL_GL_SwapWindow(g_Screen); lastT = t; } #endif ToggleFullScreenIfFlagSet(); time_update(); t = time_now(); framecount++; } #ifndef _WIN32 delete joystick; #endif NativeShutdownGraphics(); graphicsContext->Shutdown(); NativeShutdown(); delete graphicsContext; // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifndef MOBILE_DEVICE exit(0); #endif SDL_PauseAudio(1); SDL_CloseAudio(); #ifdef USING_EGL EGL_Close(); #endif SDL_GL_DeleteContext(glContext); SDL_Quit(); #if PPSSPP_PLATFORM(RPI) bcm_host_deinit(); #endif exit(0); return 0; }
int main() { int ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS // Window events etc // | SDL_INIT_HAPTIC // Force feedback // | SDL_INIT_GAMECONTROLLER // Gamepad, joystick etc | SDL_INIT_NOPARACHUTE // Disable catch fatal signals ); if (ret == 0) { /* Turn on double buffering with a 24bit Z buffer. * You may need to change this to 16 or 32 for your system */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); // Important!, Only for this demo SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); // 16 Max SDL_Window *mainWindow = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 768, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); if (mainWindow) { //SDL_SetWindowGrab(mainWindow, SDL_TRUE); /* Request opengl 4.3 context. */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); /* Create our opengl context and attach it to our window */ SDL_GLContext mainContext = SDL_GL_CreateContext(mainWindow); SDL_GL_SetSwapInterval(1); if (glewInit() == GLEW_OK) { RendererInstance = new RendererForward(mainWindow); if (RendererInstance && RendererInstance->initialize()) { int currWindowWidth = 0; int currWindowHeight = 0; SDL_GetWindowSize(mainWindow, &currWindowWidth, &currWindowHeight); RendererInstance->resize(currWindowWidth, currWindowHeight); CameraInstance = RendererInstance->camera(); clock_t logicTime = clock(); SDL_Event event; bool quit = false; while (!quit) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_WINDOWEVENT: RendererInstance->sdlWindowEvent(event); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEWHEEL: RendererInstance->sdlMouseKeyEvent(event.type, event); break; case SDL_QUIT: quit = true; break; } } if ((clock() - logicTime) >= 30) { RendererInstance->logicUpdate(); logicTime = clock(); } RendererInstance->render(); SDL_GL_SwapWindow(mainWindow); } RendererInstance->destroy(); delete RendererInstance; } } } } return 0; }
int main(int argc, char *argv[]) { #ifdef MSVC_DEBUG_HEAP // Get current flag int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); tmpFlag |= _CRTDBG_ALLOC_MEM_DF; tmpFlag |= _CRTDBG_LEAK_CHECK_DF; // Set flag to the new value. _CrtSetDbgFlag(tmpFlag); #endif #ifdef WIN32 // When on windows, do some workarounds so our console window // behaves properly. // put the program name into argv[0] char filename[_MAX_PATH]; GetModuleFileNameA(NULL, filename, _MAX_PATH); argv[0] = filename; bool fromRuby = false; for (int i = 1; i < argc; i++) { if (!stricmp(argv[i], "ProcessID") && i + 1 < argc) { fromRuby = true; char *pEnd; long int pid = strtol (argv[i + 1], &pEnd, 10); LS::Process::rubyProcessId = pid; memmove(argv + i, argv + i + 2, (argc - i - 2)*sizeof(char*)); argc -= 2; i--; break; } } LS::Process::consoleAttached = false; if (!fromRuby && AttachConsole(ATTACH_PARENT_PROCESS)) { HANDLE consoleHandleOut = GetStdHandle(STD_OUTPUT_HANDLE); int fdOut = _open_osfhandle((intptr_t)consoleHandleOut, _O_TEXT); FILE *fpOut = _fdopen(fdOut, "w"); *stdout = *fpOut; setvbuf(stdout, NULL, _IONBF, 0); //redirect unbuffered STDERR to the console HANDLE consoleHandleError = GetStdHandle(STD_ERROR_HANDLE); int fdError = _open_osfhandle((intptr_t)consoleHandleError, _O_TEXT); FILE *fpError = _fdopen(fdError, "w"); *stderr = *fpError; setvbuf(stderr, NULL, _IONBF, 0); LS::Process::consoleAttached = true; } #endif // Initialize logging. loom_log_initialize(); LSLuaState::initCommandLine(argc, (const char**) argv); /* Enable standard application logging */ SDL_LogSetAllPriority(SDL_LOG_PRIORITY_INFO); SDL_LogSetOutputFunction(sdlLogOutput, NULL); SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS ); int ret; #if LOOM_RENDERER_OPENGLES2 ret = SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); lmAssert(ret == 0, "SDL Error: %s", SDL_GetError()); ret = SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); lmAssert(ret == 0, "SDL Error: %s", SDL_GetError()); #endif int stencilSize = 1; ret = SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilSize); lmAssert(ret == 0, "SDL Error: %s", SDL_GetError()); // Set up SDL window. if ((gSDLWindow = SDL_CreateWindow( "Loom", 0, 0, 100, 100, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN #if LOOM_PLATFORM == LOOM_PLATFORM_IOS | SDL_WINDOW_BORDERLESS #endif | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI)) == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow(): %s\n", SDL_GetError()); exit(0); } gContext = SDL_GL_CreateContext(gSDLWindow); if (!gContext) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError()); exit(2); } ret = SDL_GL_SetSwapInterval(-1); if (ret != 0) { lmLog(coreLogGroup, "Late swap tearing not supported, using vsync"); SDL_GL_SetSwapInterval(1); } // And show the window with proper settings. SDL_SetWindowPosition(gSDLWindow, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_StopTextInput(); // Initialize Loom! loom_appSetup(); supplyEmbeddedAssets(); /* Main render loop */ gLoomExecutionDone = 0; /* Display SDL version */ SDL_version compiled; SDL_version linked; SDL_VERSION(&compiled); SDL_GetVersion(&linked); lmLogDebug(coreLogGroup, "Compiled with SDL version %d.%d.%d and linking against SDL version %d.%d.%d ...", compiled.major, compiled.minor, compiled.patch, linked.major, linked.minor, linked.patch); /* Game Controller */ // Enable controller events SDL_GameControllerEventState(SDL_ENABLE); //Open all connected game controllers LoomGameController::openAll(); #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(loop, 0, 1); #else while (!gLoomExecutionDone) loop(); #endif //Close all opened game controllers before closing application LoomGameController::closeAll(); loom_appShutdown(); #ifdef WIN32 LS::Process::cleanupConsole(); #endif exit(0); return 0; /* to prevent compiler warning */ }
/* =============== GLimp_SetMode =============== */ static rserr_t GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { const char *glstring; int perChannelColorBits; int colorBits, depthBits, stencilBits; //int samples; int i = 0; SDL_Surface *icon = NULL; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; SDL_DisplayMode desktopMode; int display = 0; int x = 0, y = 0; Com_Printf( "Initializing OpenGL display\n"); if ( r_allowResize->integer && !fullscreen ) flags |= SDL_WINDOW_RESIZABLE; /*icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif );*/ // If a window exists, note its display index if( screen != NULL ) display = SDL_GetWindowDisplayIndex( screen ); if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; Com_Printf( "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); Com_Printf( "Cannot determine display aspect, assuming 1.333\n" ); } Com_Printf( "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; Com_Printf( "Cannot determine display resolution, assuming 640x480\n" ); } //glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, /*&glConfig.windowAspect,*/ mode ) ) { Com_Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } Com_Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); // Center window if( r_centerWindow->integer && !fullscreen ) { x = ( desktopMode.w / 2 ) - ( glConfig.vidWidth / 2 ); y = ( desktopMode.h / 2 ) - ( glConfig.vidHeight / 2 ); } // Destroy existing state if it exists if( opengl_context != NULL ) { SDL_GL_DeleteContext( opengl_context ); opengl_context = NULL; } if( screen != NULL ) { SDL_GetWindowPosition( screen, &x, &y ); ri->Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( screen ); screen = NULL; } if( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if( noborder ) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = qfalse; } colorBits = r_colorbits->value; if ((!colorBits) || (colorBits >= 32)) colorBits = 24; if (!r_depthbits->value) depthBits = 24; else depthBits = r_depthbits->value; stencilBits = r_stencilbits->value; //samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorBits == 24) colorBits = 16; break; case 1 : if (depthBits == 24) depthBits = 16; else if (depthBits == 16) depthBits = 8; case 3 : if (stencilBits == 24) stencilBits = 16; else if (stencilBits == 16) stencilBits = 8; } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) { // reduce colorBits if (testColorBits == 24) testColorBits = 16; } if ((i % 4) == 2) { // reduce depthBits if (testDepthBits == 24) testDepthBits = 16; else if (testDepthBits == 16) testDepthBits = 8; } if ((i % 4) == 1) { // reduce stencilBits if (testStencilBits == 24) testStencilBits = 16; else if (testStencilBits == 16) testStencilBits = 8; else testStencilBits = 0; } if (testColorBits == 24) perChannelColorBits = 8; else perChannelColorBits = 4; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (perChannelColorBits == 4) perChannelColorBits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); /*SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples );*/ if(r_stereo->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); if( ( screen = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) { ri->Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } if( fullscreen ) { SDL_DisplayMode mode; switch( testColorBits ) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: ri->Printf( PRINT_DEVELOPER, "testColorBits is %d, can't fullscreen\n", testColorBits ); continue; } mode.w = glConfig.vidWidth; mode.h = glConfig.vidHeight; mode.refresh_rate = glConfig.displayFrequency = ri->Cvar_VariableIntegerValue( "r_displayRefresh" ); mode.driverdata = NULL; if( SDL_SetWindowDisplayMode( screen, &mode ) < 0 ) { ri->Printf( PRINT_DEVELOPER, "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } SDL_SetWindowTitle( screen, CLIENT_WINDOW_TITLE ); SDL_SetWindowIcon( screen, icon ); if( ( opengl_context = (QGLContext)SDL_GL_CreateContext( screen ) ) == NULL ) { Com_Printf( "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); continue; } if( SDL_GL_MakeCurrent( screen, opengl_context ) < 0 ) { Com_Printf( "SDL_GL_MakeCurrent failed: %s\n", SDL_GetError( ) ); continue; } SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; Com_Printf( "Using %d color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } /*SDL_FreeSurface( icon );*/ GLimp_DetectAvailableModes(); glstring = (char *) qglGetString (GL_RENDERER); Com_Printf( "GL_RENDERER: %s\n", glstring ); return RSERR_OK; #if 0 const char* glstring; int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int samples; int i = 0; Uint32 flags = SDL_WINDOW_OPENGL; Com_Printf( "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_WINDOW_RESIZABLE; if( videoInfo == NULL ) { static SDL_DisplayMode sVideoInfo; static SDL_PixelFormat sPixelFormat; if (SDL_GetCurrentDisplayMode( 0, &sVideoInfo ) < 0) Com_Error(ERR_FATAL, "SDL_GetCurrentDisplayMode failed : %s\n", SDL_GetError()); // Take a copy of the videoInfo sPixelFormat.format = sVideoInfo.format; sPixelFormat.palette = NULL; // Should already be the case //Com_Memcpy( &sVideoInfo, videoInfo, sizeof( SDL_DisplayMode ) ); sVideoInfo.format = sPixelFormat.format; videoInfo = &sVideoInfo; if( videoInfo->h > 0 ) { glConfig.displayWidth = videoInfo->w; glConfig.displayHeight = videoInfo->h; // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio glConfig.displayAspect = (float)videoInfo->w / (float)videoInfo->h; Com_Printf( "Estimated display aspect: %.3f\n", glConfig.displayAspect ); } else { glConfig.displayWidth = 480; glConfig.displayHeight = 640; glConfig.displayAspect = 1.333f; Com_Printf( "Cannot estimate display resolution/aspect, assuming 640x480/1.333\n" ); } } Com_Printf( "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( videoInfo->h > 0 ) { glConfig.vidWidth = videoInfo->w; glConfig.vidHeight = videoInfo->h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; Com_Printf( "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.displayAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, /*&glConfig.displayAspect,*/ mode ) ) { Com_Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } Com_Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if (fullscreen) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if (noborder) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = qfalse; } colorbits = r_colorbits->value; if ((!colorbits) || (colorbits >= 32)) colorbits = 24; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; //samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (sdlcolorbits == 4) sdlcolorbits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); /*if(r_stereoEnabled->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else {*/ glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); //} SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if 0 // See http://bugzilla.icculus.org/show_bug.cgi?id=3526 // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) { if( SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ) < 0 ) { Com_Printf( "Unable to guarantee accelerated " "visual with libSDL < 1.2.10\n" ); } } #endif if( SDL_GL_SetSwapInterval(r_swapInterval->integer ) < 0 ) Com_Printf( "SDL_GL_SetSwapInterval not supported\n" ); #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); SDL_WM_SetIcon( icon, NULL ); SDL_FreeSurface( icon ); } #endif SDL_ShowCursor(0); if (!(window = SDL_CreateWindow(CLIENT_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, glConfig.vidWidth, glConfig.vidHeight, flags))) { Com_Printf( "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } opengl_context = SDL_GL_CreateContext(window); Com_Printf( "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } GLimp_DetectAvailableModes(); if (!window) { Com_Printf( "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } screen = window; // FIXME: Defines needed here glstring = (char *) qglGetString (GL_RENDERER); Com_Printf( "GL_RENDERER: %s\n", glstring ); return RSERR_OK; #endif }
int fs_ml_video_create_window(const char *title) { fs_log("fs_ml_video_create_window\n"); g_window_title = g_strdup(title); g_fs_ml_keyboard_input_grab = fs_config_get_boolean( "keyboard_input_grab"); if (g_fs_ml_automatic_input_grab == FS_CONFIG_NONE) { g_fs_ml_keyboard_input_grab = 1; } fs_log("keyboard input grab: %d\n", g_fs_ml_keyboard_input_grab); static int initialized = 0; #ifdef USE_SDL2 SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, g_fs_ml_keyboard_input_grab ? "1" : "0"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); #endif SDL_Init(SDL_INIT_VIDEO); SDL_version version; SDL_VERSION(&version); fs_log("FS-UAE was compiled for SDL %d.%d.%d\n", version.major, version.minor, version.patch); if (!initialized) { #ifdef USE_SDL2 int display_index = 0; SDL_DisplayMode mode; int error = SDL_GetCurrentDisplayMode(display_index, &mode); if (error) { fs_log("SDL_GetCurrentDisplayMode failed\n"); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Display Error", "SDL_GetCurrentDisplayMode failed.", NULL); exit(1); } fs_emu_monitor_init(); const char *mon = fs_config_get_const_string("monitor"); int mon_flag = -1; if (mon == NULL) { mon = "middle-left"; } if (strcmp(mon, "left") == 0) { mon_flag = FS_EMU_MONITOR_FLAG_LEFT; } else if (strcmp(mon, "middle-left") == 0) { mon_flag = FS_EMU_MONITOR_FLAG_MIDDLE_LEFT; } else if (strcmp(mon, "middle-right") == 0) { mon_flag = FS_EMU_MONITOR_FLAG_MIDDLE_RIGHT; } else if (strcmp(mon, "right") == 0) { mon_flag = FS_EMU_MONITOR_FLAG_RIGHT; } else { mon_flag = FS_EMU_MONITOR_FLAG_MIDDLE_LEFT; } FSEmuMonitor monitor; fs_emu_monitor_get_by_flag(mon_flag, &monitor); fs_log("Monitor \"%s\" (flag %d) => index %d\n", mon, mon_flag, monitor.index); g_display = monitor.index; #else const SDL_VideoInfo* info = SDL_GetVideoInfo(); #endif g_fullscreen_width = fs_config_get_int("fullscreen_width"); if (g_fullscreen_width == FS_CONFIG_NONE) { #ifdef USE_SDL2 g_fullscreen_width = mode.w; #else g_fullscreen_width = info->current_w; #endif } g_fullscreen_height = fs_config_get_int("fullscreen_height"); if (g_fullscreen_height == FS_CONFIG_NONE) { #ifdef USE_SDL2 g_fullscreen_height = mode.h; #else g_fullscreen_height = info->current_h; #endif } if (g_fs_emu_video_fullscreen_mode_string == NULL) { g_fs_emu_video_fullscreen_mode = -1; } else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "window") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_WINDOW; } else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "fullscreen") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; } #ifdef USE_SDL2 else if (g_ascii_strcasecmp(g_fs_emu_video_fullscreen_mode_string, "desktop") == 0) { g_fs_emu_video_fullscreen_mode = FULLSCREEN_DESKTOP; } #endif if (g_fs_emu_video_fullscreen_mode == -1) { #ifdef MACOSX g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; #else g_fs_emu_video_fullscreen_mode = FULLSCREEN_FULLSCREEN; #endif #ifdef USE_SDL2 fs_log("defaulting to fullscreen_mode = desktop for SDL2\n"); g_fs_emu_video_fullscreen_mode = FULLSCREEN_DESKTOP; #endif } initialized = 1; } if (g_fs_ml_video_sync) { g_fs_ml_vblank_sync = 1; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); #ifdef USE_SDL2 // setting swap interval after creating OpenGL context #else if (g_fs_ml_vblank_sync) { fs_emu_log("*** Setting swap interval to 1 ***\n"); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); } else { fs_emu_log("*** Setting swap interval to 0 ***\n"); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0); } #endif if (g_fsaa) { fs_log("setting FSAA samples to %d\n", g_fsaa); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, g_fsaa); } g_window_width = fs_config_get_int("window_width"); if (g_window_width == FS_CONFIG_NONE) { g_window_width = 1920 / 2; } g_window_height = fs_config_get_int("window_height"); if (g_window_height == FS_CONFIG_NONE) { g_window_height = 1080/ 2; } #ifdef USE_SDL2 g_window_x = fs_config_get_int("window_x"); if (g_window_x == FS_CONFIG_NONE) { g_window_x = SDL_WINDOWPOS_CENTERED; } g_window_y = fs_config_get_int("window_y"); if (g_window_y == FS_CONFIG_NONE) { g_window_y = SDL_WINDOWPOS_CENTERED; } #endif g_window_resizable = fs_config_get_boolean("window_resizable"); if (g_window_resizable == FS_CONFIG_NONE) { g_window_resizable = 1; } g_fs_ml_automatic_input_grab = fs_config_get_boolean( "automatic_input_grab"); if (g_fs_ml_automatic_input_grab == FS_CONFIG_NONE) { if (fs_ml_mouse_integration()) { g_fs_ml_automatic_input_grab = 0; } else { g_fs_ml_automatic_input_grab = 1; } } fs_log("automatic input grab: %d\n", g_fs_ml_automatic_input_grab); g_initial_input_grab = g_fs_ml_automatic_input_grab; if (fs_config_get_boolean("initial_input_grab") == 1) { g_initial_input_grab = 1; } else if (fs_config_get_boolean("initial_input_grab") == 0 || // deprecated names: fs_config_get_boolean("input_grab") == 0 || fs_config_get_boolean("grab_input") == 0) { g_initial_input_grab = 0; } set_video_mode(); #ifdef USE_SDL2 if (g_fs_ml_vblank_sync) { fs_emu_log("*** Setting swap interval to 1 ***\n"); if (SDL_GL_SetSwapInterval(1) != 0) { fs_emu_warning("SDL_GL_SetSwapInterval(1) failed"); } } else { fs_emu_log("*** Setting swap interval to 0 ***\n"); SDL_GL_SetSwapInterval(0); } #endif // we display a black frame as soon as possible (to reduce flickering on // startup) glClear(GL_COLOR_BUFFER_BIT); #ifdef USE_SDL2 SDL_GL_SwapWindow(g_fs_ml_window); #else SDL_GL_SwapBuffers(); #endif fs_gl_finish(); #ifdef USE_SDL2 // set in SDL_CreateWindow instead #else SDL_WM_SetCaption(g_window_title, fs_get_application_name()); #endif fs_log("initial input grab: %d\n", g_initial_input_grab); if (g_initial_input_grab && !g_has_input_grab) { fs_ml_grab_input(1, 1); } fs_ml_show_cursor(0, 1); // this function must be called from the video thread fs_log("init_opengl\n"); fs_emu_video_init_opengl(); #ifdef WINDOWS #ifdef USE_SDL2 // we use only SDL functions with SDL2 #else fs_ml_init_raw_input(); #endif #else #ifdef USE_SDL2 SDL_StartTextInput(); #else // enable keysym to unicode char translation SDL_EnableUNICODE(1); #endif #endif fs_log("create windows is done\n"); return 1; }
int main(int argc, char *argv[]) { int fsaa, accel; int value; int i, done; SDL_DisplayMode mode; SDL_Event event; Uint32 then, now, frames; int status; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); /* Initialize parameters */ fsaa = 0; accel = 0; /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); if (!state) { return 1; } for (i = 1; i < argc;) { int consumed; consumed = SDLTest_CommonArg(state, i); if (consumed == 0) { if (SDL_strcasecmp(argv[i], "--fsaa") == 0) { ++fsaa; consumed = 1; } else if (SDL_strcasecmp(argv[i], "--accel") == 0) { ++accel; consumed = 1; } else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) { i++; if (!argv[i]) { consumed = -1; } else { depth = SDL_atoi(argv[i]); consumed = 1; } } else { consumed = -1; } } if (consumed < 0) { SDL_Log("Usage: %s %s [--fsaa] [--accel] [--zdepth %%d]\n", argv[0], SDLTest_CommonUsage(state)); quit(1); } i += consumed; } /* Set OpenGL parameters */ state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS; state->gl_red_size = 5; state->gl_green_size = 5; state->gl_blue_size = 5; state->gl_depth_size = depth; state->gl_major_version = 1; state->gl_minor_version = 1; state->gl_profile_mask = SDL_GL_CONTEXT_PROFILE_ES; if (fsaa) { state->gl_multisamplebuffers=1; state->gl_multisamplesamples=fsaa; } if (accel) { state->gl_accelerated=1; } if (!SDLTest_CommonInit(state)) { quit(2); } context = SDL_calloc(state->num_windows, sizeof(context)); if (context == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } /* Create OpenGL ES contexts */ for (i = 0; i < state->num_windows; i++) { context[i] = SDL_GL_CreateContext(state->windows[i]); if (!context[i]) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError()); quit(2); } } if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) { SDL_GL_SetSwapInterval(1); } else { SDL_GL_SetSwapInterval(0); } SDL_GetCurrentDisplayMode(0, &mode); SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format)); SDL_Log("\n"); SDL_Log("Vendor : %s\n", glGetString(GL_VENDOR)); SDL_Log("Renderer : %s\n", glGetString(GL_RENDERER)); SDL_Log("Version : %s\n", glGetString(GL_VERSION)); SDL_Log("Extensions : %s\n", glGetString(GL_EXTENSIONS)); SDL_Log("\n"); status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); if (!status) { SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_RED_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value); if (!status) { SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_GREEN_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value); if (!status) { SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_BLUE_SIZE: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value); if (!status) { SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", depth, value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_DEPTH_SIZE: %s\n", SDL_GetError()); } if (fsaa) { status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value); if (!status) { SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n", SDL_GetError()); } status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value); if (!status) { SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n", SDL_GetError()); } } if (accel) { status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value); if (!status) { SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n", SDL_GetError()); } } /* Set rendering settings for each context */ for (i = 0; i < state->num_windows; ++i) { float aspectAdjust; status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); /* Continue for next window */ continue; } aspectAdjust = (4.0f / 3.0f) / ((float)state->window_w / state->window_h); glViewport(0, 0, state->window_w, state->window_h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(-2.0, 2.0, -2.0 * aspectAdjust, 2.0 * aspectAdjust, -20.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glShadeModel(GL_SMOOTH); } /* Main render loop */ frames = 0; then = SDL_GetTicks(); done = 0; while (!done) { /* Check for events */ ++frames; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: for (i = 0; i < state->num_windows; ++i) { if (event.window.windowID == SDL_GetWindowID(state->windows[i])) { status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); break; } /* Change view port to the new window dimensions */ glViewport(0, 0, event.window.data1, event.window.data2); /* Update window content */ Render(); SDL_GL_SwapWindow(state->windows[i]); break; } } break; } } SDLTest_CommonEvent(state, &event, &done); } for (i = 0; i < state->num_windows; ++i) { if (state->windows[i] == NULL) continue; status = SDL_GL_MakeCurrent(state->windows[i], context[i]); if (status) { SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); /* Continue for next window */ continue; } Render(); SDL_GL_SwapWindow(state->windows[i]); } } /* Print out some timing information */ now = SDL_GetTicks(); if (now > then) { SDL_Log("%2.2f frames per second\n", ((double) frames * 1000) / (now - then)); } #if !defined(__ANDROID__) quit(0); #endif return 0; }
static int GLimp_SetMode( void ) { const char* glstring; //int sdlcolorbits; int /*colorbits, depthbits, stencilbits, */stereo; //int tcolorbits, tdepthbits, tstencilbits; int samples; int i = 0; SDL_DisplayMode displayMode; //SDL_Surface *vidscreen = NULL; Uint32 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE; static int desktop_w, desktop_h; // desktop resolution /*if(window) { return RSERR_INVALID_MODE; }*/ ri.Printf( PRINT_DEVELOPER, "Initializing OpenGL display\n"); //if ( r_allowResize->integer ) // flags |= SDL_WINDOW_RESIZABLE; // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio //videoInfo = SDL_GetVideoInfo(); //if( videoInfo->current_h == 0 ) if( SDL_GetDesktopDisplayMode( 0, &displayMode ) == 0 )//FIXME: Use SDL_GetWindowDisplayIndex instead of 0? { if( !desktop_w ) { // first time through, resolve desktop resolution desktop_w = displayMode.w; desktop_h = displayMode.h; } } else { ri.Printf( PRINT_ALL, "Cannot get display info, assuming 800x600\n" ); if( !desktop_w ) { // first time through, resolve desktop resolution desktop_w = 800; desktop_h = 600; } } glConfig.displayAspect = (float)desktop_w / (float)desktop_h; ri.Printf( PRINT_DEVELOPER, "Estimated display aspect: %.3f\n", glConfig.displayAspect ); //if( !failSafe ) //{ if ( r_width->modified || r_height->modified || r_pixelAspect->modified ) { for ( i = 0; i < 12; i++ ) { if ( r_width->integer == vidModes[ i ].width && r_height->integer == vidModes[ i ].height && r_pixelAspect->integer == vidModes[ i ].pixelAspect ) { Cvar_SetValue( "r_mode", i ); break; } } if ( i == 12 ) Cvar_Set( "r_mode", "-1" ); } else if ( r_mode->modified && r_mode->integer >= 0 ) { Cvar_SetValue( "r_width", vidModes[ r_mode->integer ].width ); Cvar_SetValue( "r_height", vidModes[ r_mode->integer ].height ); Cvar_SetValue( "r_pixelAspect", vidModes[ r_mode->integer ].pixelAspect ); } r_width->modified = qfalse; r_height->modified = qfalse; r_pixelAspect->modified = qfalse; r_mode->modified = qfalse; glConfig.vidWidth = ( r_width->integer ? r_width->integer : desktop_w ); glConfig.vidHeight = ( r_height->integer ? r_height->integer : desktop_h ); if(glConfig.vidWidth > desktop_w) { glConfig.vidWidth = desktop_w; } if(glConfig.vidHeight > desktop_h) { glConfig.vidHeight = desktop_h; } glConfig.windowAspect = glConfig.vidWidth / ( (float)glConfig.vidHeight * r_pixelAspect->value ); /*} else if( glConfig.vidWidth != R_FAILSAFE_WIDTH && glConfig.vidHeight != R_FAILSAFE_HEIGHT ) { ri.Printf( PRINT_ALL, "Setting mode %dx%d failed, falling back on mode %dx%d\n", glConfig.vidWidth, glConfig.vidHeight, R_FAILSAFE_WIDTH, R_FAILSAFE_HEIGHT ); glConfig.vidWidth = R_FAILSAFE_WIDTH; glConfig.vidHeight = R_FAILSAFE_HEIGHT; glConfig.windowAspect = 1.0f; } else return RSERR_INVALID_MODE;*/ ri.Printf (PRINT_DEVELOPER, "...setting mode %dx%d\n", glConfig.vidWidth, glConfig.vidHeight); if (r_fullscreen->integer) { glConfig.vidWidth = desktop_w; glConfig.vidHeight = desktop_h; flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } /*colorbits = r_colorbits->value; if (!colorbits || colorbits > 32) colorbits = 32; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; samples = r_ext_multisample->value;*/ samples = r_ext_multisample->value; /*for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 32) colorbits = 24; else if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 32) tcolorbits = 24; if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } if (tcolorbits >= 24) sdlcolorbits = 8; else sdlcolorbits = 4;*/ //#ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ // if (sdlcolorbits == 4) // sdlcolorbits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ // SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); //#endif /*SDL_GL_SetAttribute( SDL_GL_RED_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, depthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, stencilbits ); */ if(r_stereoEnabled->integer) { //glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { //glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if ( !(window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, glConfig.vidWidth, glConfig.vidHeight, flags )) ) //if (!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) { ri.Printf( PRINT_ALL, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); return RSERR_INVALID_MODE; } if ( !(context = SDL_GL_CreateContext( window )) ) { ri.Printf( PRINT_ALL, "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); SDL_DestroyWindow( window ); window = NULL; return RSERR_INVALID_MODE; } //if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) < 0 ) if( SDL_GL_SetSwapInterval( r_swapInterval->integer ) != 0 ) ri.Printf( PRINT_ALL, "r_swapInterval failed (%s)\n", SDL_GetError( ) ); #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); //SDL_WM_SetIcon( icon, NULL ); SDL_SetWindowIcon( window, icon ); SDL_FreeSurface( icon ); } #endif //SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE); //SDL_ShowCursor(0); //SDL_ShowCursor(0); GLimp_GetCurrentContext(); //ri.Printf( PRINT_DEVELOPER, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", // sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &glConfig.colorBits ); SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &glConfig.depthBits ); SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &glConfig.stencilBits ); SDL_GL_GetAttribute( SDL_GL_STEREO, &stereo ); if(stereo) { glConfig.stereoEnabled = qtrue; } else { glConfig.stereoEnabled = qfalse; } if(SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) { glConfig.isFullscreen = qtrue; } else { if(r_fullscreen->integer) { Cvar_Set( "r_fullscreen", "0" ); } glConfig.isFullscreen = qfalse; } /*glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } */ GLimp_DetectAvailableModes(); if (!window || !context) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } //screen = vidscreen; glstring = (char *) qglGetString (GL_RENDERER); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }