bool allegro_init() { cpu_capabilities = 0; notes << "Allegro: "; if(cfgUseSSE && SDL_HasSSE()) cpu_capabilities |= CPU_SSE; if(cfgUseMMX && SDL_HasMMX()) cpu_capabilities |= CPU_MMX; if(cfgUseMMXExt && SDL_HasMMXExt()) cpu_capabilities |= CPU_MMXPLUS; if(cpu_capabilities & CPU_SSE) notes << "SSE, "; else notes << "no SSE, "; if(cpu_capabilities & CPU_MMX) notes << "MMX, "; else notes << "no MMX, "; if(cpu_capabilities & CPU_MMXPLUS) notes << "MMXExt"; else notes << "no MMXExt"; notes << endl; screen = create_bitmap_ex(32, SCREEN_W, SCREEN_H); notes << "Allegro screen format:" << endl; DumpPixelFormat(screen->surf->format); return true; }
/* This function does not reset the video mode if it fails, because we might be trying * yet another video mode, so we'd just thrash the display. On fatal error, * LowLevelWindow_Win32::~LowLevelWindow_Win32 will call Shutdown(). */ CString LowLevelWindow_Win32::TryVideoMode( RageDisplay::VideoModeParams p, bool &bNewDeviceOut ) { ASSERT_M( p.bpp == 16 || p.bpp == 32, ssprintf("%i", p.bpp) ); bNewDeviceOut = false; /* We're only allowed to change the pixel format of a window exactly once. */ bool bCanSetPixelFormat = true; /* Do we have an old window? */ if( GraphicsWindow::GetHwnd() == NULL ) { /* No. Always create and show the window before changing the video mode. * Otherwise, some other window may have focus, and changing the video mode will * cause that window to be resized. */ GraphicsWindow::CreateGraphicsWindow( p ); GraphicsWindow::ConfigureGraphicsWindow( p ); } else { /* We already have a window. Assume that it's pixel format has already been * set. */ LOG->Trace("Setting new window, can't reuse old"); bCanSetPixelFormat = false; } ASSERT( GraphicsWindow::GetHwnd() ); /* Set the display mode: switch to a fullscreen mode or revert to windowed mode. */ LOG->Trace("SetScreenMode ..."); CString sErr = GraphicsWindow::SetScreenMode( p ); if( !sErr.empty() ) return sErr; PIXELFORMATDESCRIPTOR PixelFormat; int iPixelFormat = ChooseWindowPixelFormat( p, &PixelFormat ); if( iPixelFormat == 0 ) { /* Destroy the window. */ DestroyGraphicsWindowAndOpenGLContext(); return "Pixel format not found"; } bool bNeedToSetPixelFormat = false; { /* We'll need to recreate it if the pixel format is going to change. We * aren't allowed to change the pixel format twice. */ PIXELFORMATDESCRIPTOR DestPixelFormat; ZERO( DestPixelFormat ); DescribePixelFormat( GraphicsWindow::GetHDC(), iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &DestPixelFormat ); if( memcmp( &DestPixelFormat, &g_CurrentPixelFormat, sizeof(PIXELFORMATDESCRIPTOR) ) ) { LOG->Trace("Reset: pixel format changing" ); bNeedToSetPixelFormat = true; } } if( bNeedToSetPixelFormat && !bCanSetPixelFormat ) { /* * The screen mode has changed, so we need to set the pixel format. If we're * not allowed to do so, destroy the window and make a new one. * * For some reason, if we destroy the old window before creating the new one, * the "fullscreen apps go under the taskbar" glitch will happen when we quit. * We have to create the new window first. */ LOG->Trace( "Mode requires new pixel format, and we've already set one; resetting OpenGL context" ); if( g_HGLRC != NULL ) { wglMakeCurrent( NULL, NULL ); wglDeleteContext( g_HGLRC ); g_HGLRC = NULL; } GraphicsWindow::RecreateGraphicsWindow(p); // DestroyGraphicsWindowAndOpenGLContext(); // GraphicsWindow::CreateGraphicsWindow( p ); bNewDeviceOut = true; } GraphicsWindow::ConfigureGraphicsWindow( p ); GraphicsWindow::SetVideoModeParams( p ); if( bNeedToSetPixelFormat ) { /* Set the pixel format. */ if( !SetPixelFormat(GraphicsWindow::GetHDC(), iPixelFormat, &PixelFormat) ) { /* Destroy the window. */ DestroyGraphicsWindowAndOpenGLContext(); return werr_ssprintf( GetLastError(), "Pixel format failed" ); } DescribePixelFormat( GraphicsWindow::GetHDC(), iPixelFormat, sizeof(g_CurrentPixelFormat), &g_CurrentPixelFormat ); DumpPixelFormat( g_CurrentPixelFormat ); } if( g_HGLRC == NULL ) { g_HGLRC = wglCreateContext( GraphicsWindow::GetHDC() ); if ( g_HGLRC == NULL ) { DestroyGraphicsWindowAndOpenGLContext(); return hr_ssprintf( GetLastError(), "wglCreateContext" ); } if( !wglMakeCurrent( GraphicsWindow::GetHDC(), g_HGLRC ) ) { DestroyGraphicsWindowAndOpenGLContext(); return hr_ssprintf( GetLastError(), "wglCreateContext" ); } } return ""; // we set the video mode successfully }
/////////////////// // Set the video mode bool SetVideoMode() { if(bDedicated) { notes << "SetVideoMode: dedicated mode, ignoring" << endl; return true; // ignore this case } if (!tLXOptions) { warnings << "SetVideoMode: Don't know what video mode to set, ignoring" << endl; return false; } bool resetting = false; // Check if already running if (VideoPostProcessor::videoSurface()) { resetting = true; notes << "resetting video mode" << endl; // seems to be a win-only problem, it works without problems here under MacOSX #ifdef WIN32 // using hw surfaces? if ((VideoPostProcessor::videoSurface()->flags & SDL_HWSURFACE) != 0) { warnings << "cannot change video mode because current mode uses hardware surfaces" << endl; // TODO: you would have to reset whole game, this is not enough! // The problem is in all allocated surfaces - they are hardware and when you switch // to window, you will most probably get software rendering // Also, hardware surfaces are freed from the video memory when reseting video mode // so you would first have to convert all surfaces to software and then perform this // TODO: in menu_options, restart the game also for fullscreen-change if hw surfaces are currently used return false; } #endif } else { notes << "setting video mode" << endl; } // uninit first to ensure that the video thread is not running VideoPostProcessor::uninit(); bool HardwareAcceleration = false; int DoubleBuf = false; int vidflags = 0; // it is faster with doublebuffering in hardware accelerated mode // also, it seems that it's possible that there are effects in hardware mode with double buf disabled // Use doublebuf when hardware accelerated if (HardwareAcceleration) DoubleBuf = true; // Check that the bpp is valid switch (tLXOptions->iColourDepth) { case 0: case 16: case 24: case 32: break; default: tLXOptions->iColourDepth = 16; } notes << "ColorDepth: " << tLXOptions->iColourDepth << endl; // BlueBeret's addition (2007): OpenGL support bool opengl = tLXOptions->bOpenGL; // Initialize the video if(tLXOptions->bFullscreen) { vidflags |= SDL_FULLSCREEN; } if (opengl) { vidflags |= SDL_OPENGL; #ifndef REAL_OPENGL vidflags |= SDL_OPENGLBLIT; // SDL will behave like normally #endif // HINT: it seems that with OGL activated, SDL_SetVideoMode will already set the OGL depth size // though this main pixel format of the screen surface was always 32 bit for me in OGL under MacOSX //#ifndef MACOSX /* short colorbitsize = (tLXOptions->iColourDepth==16) ? 5 : 8; SDL_GL_SetAttribute (SDL_GL_RED_SIZE, colorbitsize); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, colorbitsize); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, colorbitsize); SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, colorbitsize); //SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, tLXOptions->iColourDepth); */ //#endif //SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 8); //SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24); //SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 32); SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); // always use double buffering in OGL mode } if(HardwareAcceleration) { vidflags |= SDL_HWSURFACE | SDL_HWPALETTE | SDL_HWACCEL; // Most (perhaps all) systems use software drawing for their stuff (windows etc.) // Because of that we cannot have hardware accelerated support in window - OS screen // is software surface. How would you make the window hardware, if it's on the screen? // Anyway, SDL takes care of this by istelf and disables the flag when needed iSurfaceFormat = SDL_HWSURFACE; } else { vidflags |= SDL_SWSURFACE; iSurfaceFormat = SDL_SWSURFACE; } if(DoubleBuf && !opengl) vidflags |= SDL_DOUBLEBUF; #ifdef WIN32 UnSubclassWindow(); // Unsubclass before doing anything with the window #endif #ifdef WIN32 // Reset the video subsystem under WIN32, else we get a "Could not reset OpenGL context" error when switching mode if (opengl && tLX) { // Don't reset when we're setting up the mode for first time (OpenLieroX not yet initialized) SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_InitSubSystem(SDL_INIT_VIDEO); } #endif VideoPostProcessor::init(); int scrW = VideoPostProcessor::get()->screenWidth(); int scrH = VideoPostProcessor::get()->screenHeight(); setvideomode: if( SDL_SetVideoMode(scrW, scrH, tLXOptions->iColourDepth, vidflags) == NULL) { if (resetting) { errors << "Failed to reset video mode" << " (ErrorMsg: " << SDL_GetError() << ")," << " let's wait a bit and retry" << endl; SDL_Delay(500); resetting = false; goto setvideomode; } if(tLXOptions->iColourDepth != 0) { errors << "Failed to use " << tLXOptions->iColourDepth << " bpp" << " (ErrorMsg: " << SDL_GetError() << ")," << " trying automatic bpp detection ..." << endl; tLXOptions->iColourDepth = 0; goto setvideomode; } if(vidflags & SDL_OPENGL) { errors << "Failed to use OpenGL" << " (ErrorMsg: " << SDL_GetError() << ")," << " trying without ..." << endl; vidflags &= ~(SDL_OPENGL | SDL_OPENGLBLIT | SDL_HWSURFACE | SDL_HWPALETTE | SDL_HWACCEL); goto setvideomode; } if(vidflags & SDL_FULLSCREEN) { errors << "Failed to set full screen video mode " << scrW << "x" << scrH << "x" << tLXOptions->iColourDepth << " (ErrorMsg: " << SDL_GetError() << ")," << " trying window mode ..." << endl; vidflags &= ~SDL_FULLSCREEN; goto setvideomode; } SystemError("Failed to set the video mode " + itoa(scrW) + "x" + itoa(scrH) + "x" + itoa(tLXOptions->iColourDepth) + "\nErrorMsg: " + std::string(SDL_GetError())); return false; } SDL_WM_SetCaption(GetGameVersion().asHumanString().c_str(),NULL); SDL_ShowCursor(SDL_DISABLE); #ifdef WIN32 // Hint: Reset the mouse state - this should avoid the mouse staying pressed GetMouse()->Button = 0; GetMouse()->Down = 0; GetMouse()->FirstDown = 0; GetMouse()->Up = 0; if (!tLXOptions->bFullscreen) { SubclassWindow(); } #endif // Set the change mode flag if (tLX) tLX->bVideoModeChanged = true; #ifdef REAL_OPENGL if((SDL_GetVideoSurface()->flags & SDL_OPENGL)) { static SDL_PixelFormat OGL_format32 = { NULL, //SDL_Palette *palette; 32, //Uint8 BitsPerPixel; 4, //Uint8 BytesPerPixel; 0, 0, 0, 0, //Uint8 Rloss, Gloss, Bloss, Aloss; #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ 0, 8, 16, 24, //Uint8 Rshift, Gshift, Bshift, Ashift; 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, #else 24, 16, 8, 0, //Uint8 Rshift, Gshift, Bshift, Ashift; 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF, #endif 0, //Uint32 colorkey; 255 //Uint8 alpha; }; // some GFX stuff in OLX seems very slow when this is used // (probably the blit from alpha surf to this format is slow) /* static SDL_PixelFormat OGL_format24 = { NULL, //SDL_Palette *palette; 24, //Uint8 BitsPerPixel; 3, //Uint8 BytesPerPixel; 0, 0, 0, 0, //Uint8 Rloss, Gloss, Bloss, Aloss; #if SDL_BYTEORDER == SDL_LIL_ENDIAN // OpenGL RGBA masks 0, 8, 16, 0, //Uint8 Rshift, Gshift, Bshift, Ashift; 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000, #else 16, 8, 0, 0, //Uint8 Rshift, Gshift, Bshift, Ashift; 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000, #endif 0, //Uint32 colorkey; 255 //Uint8 alpha; }; */ //if(tLXOptions->iColourDepth == 32) mainPixelFormat = &OGL_format32; //else // mainPixelFormat = &OGL_format24; } else #endif mainPixelFormat = SDL_GetVideoSurface()->format; DumpPixelFormat(mainPixelFormat); if(SDL_GetVideoSurface()->flags & SDL_DOUBLEBUF) notes << "using doublebuffering" << endl; // Correct the surface format according to SDL #ifdef REAL_OPENGL if(((SDL_GetVideoSurface()->flags & SDL_OPENGL) != 0)) { iSurfaceFormat = SDL_SWSURFACE; } else #endif if((SDL_GetVideoSurface()->flags & SDL_HWSURFACE) != 0) { iSurfaceFormat = SDL_HWSURFACE; notes << "using hardware surfaces" << endl; } else { iSurfaceFormat = SDL_SWSURFACE; // HINT: under MacOSX, it doesn't seem to make any difference in performance if (HardwareAcceleration) hints << "Unable to use hardware surfaces, falling back to software." << endl; notes << "using software surfaces" << endl; } if(SDL_GetVideoSurface()->flags & SDL_OPENGL) { hints << "using OpenGL" << endl; #ifdef REAL_OPENGL OGL_init(); #else FillSurface(SDL_GetVideoSurface(), Color(0, 0, 0)); #endif } else FillSurface(SDL_GetVideoSurface(), Color(0, 0, 0)); VideoPostProcessor::get()->resetVideo(); notes << "video mode was set successfully" << endl; return true; }