diff options
author | Adam Moss <moss@lindenlab.com> | 2007-04-18 09:17:53 +0000 |
---|---|---|
committer | Adam Moss <moss@lindenlab.com> | 2007-04-18 09:17:53 +0000 |
commit | 208ccf8c2c583669c78719d92aff0c354b85d151 (patch) | |
tree | 72f6f4b28c78748dda1741a5a3f4f8451f73c96f /indra/llwindow | |
parent | 0277259455c4354f81ea8a24c8ab93f27567bc6f (diff) |
SL-24485, SL-40331, SL-23136, SL-40330, SL-25816, SL-40567,
SL-40568: land moss/linuxmisc-r60383: misc linuxclient & opensource
fixes.
svn merge svn+ssh://svn.lindenlab.com/svn/linden/release@60383
svn+ssh://svn.lindenlab.com/svn/linden/branches/moss/linuxmisc-r60383 ->
release
Diffstat (limited to 'indra/llwindow')
-rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 288 |
1 files changed, 173 insertions, 115 deletions
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 3f1aa1a469..6b25eabfd1 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -1,6 +1,6 @@ /** * @file llwindowsdl.cpp - * @brief Platform-dependent implementation of llwindow + * @brief SDL implementation of LLWindow class * * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. * $License$ @@ -35,12 +35,6 @@ extern BOOL gDebugWindowProc; -// culled from winuser.h -//const S32 WHEEL_DELTA = 120; /* Value for rolling one detent */ -// On the Mac, the scroll wheel reports a delta of 1 for each detent. -// There's also acceleration for faster scrolling, based on a slider in the system preferences. -const S32 WHEEL_DELTA = 1; /* Value for rolling one detent */ -const S32 BITS_PER_PIXEL = 32; const S32 MAX_NUM_RESOLUTIONS = 32; // @@ -54,37 +48,11 @@ const S32 MAX_NUM_RESOLUTIONS = 32; // TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar // set of reasons): Stash a pointer to the LLWindowSDL object here and // maintain in the constructor and destructor. This assumes that there will -// be only one object of this class at any time. Hopefully this is true. +// be only one object of this class at any time. Currently this is true. static LLWindowSDL *gWindowImplementation = NULL; static BOOL was_fullscreen = FALSE; -// Cross-platform bits: - -void show_window_creation_error(const char* title) -{ - llwarns << title << llendl; - shell_open( "help/window_creation_error.html"); - /* - OSMessageBox( - "Second Life is unable to run because it can't set up your display.\n" - "We need to be able to make a 32-bit color window at 1024x768, with\n" - "an 8 bit alpha channel.\n" - "\n" - "First, be sure your monitor is set to True Color (32-bit) in\n" - "Start -> Control Panels -> Display -> Settings.\n" - "\n" - "Otherwise, this may be due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "ATI drivers are available at http://www.ati.com/\n" - "nVidia drivers are available at http://www.nvidia.com/\n" - "\n" - "If you continue to receive this message, contact customer service.", - title, - OSMB_OK); - */ -} - void maybe_lock_display(void) { @@ -255,7 +223,7 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width, #endif // LL_GTK // Get the original aspect ratio of the main device. - mOriginalAspectRatio = 1024.0 / 768.0; // !!! FIXME //(double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); + mOriginalAspectRatio = 1024.0 / 768.0; // !!! *FIX: ? //(double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); if (!title) title = "SDL Window"; // *FIX: (???) @@ -305,6 +273,105 @@ static SDL_Surface *Load_BMP_Resource(const char *basename) return SDL_LoadBMP(path_buffer); } +#if LL_X11 +// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM +// on this machine. It works by searching /var/log/var/log/Xorg.?.log or +// /var/log/XFree86.?.log for a ': VideoRAM: (%d+) kB' regex, where '?' is +// the X11 display number derived from $DISPLAY +static int x11_detect_VRAM_kb_fp(FILE *fp) +{ + const int line_buf_size = 1000; + char line_buf[line_buf_size]; + while (fgets(line_buf, line_buf_size, fp)) + { + //lldebugs << "XLOG: " << line_buf << llendl; + + // Why the ad-hoc parser instead of using a regex? Our + // favourite regex implementation - libboost_regex - is + // quite a heavy and troublesome dependency for the client, so + // it seems a shame to introduce it for such a simple task. + const char part1_template[] = ": VideoRAM: "; + const char part2_template[] = " kB"; + char *part1 = strstr(line_buf, part1_template); + if (part1) // found start of matching line + { + part1 = &part1[strlen(part1_template)]; // -> after + char *part2 = strstr(part1, part2_template); + if (part2) // found end of matching line + { + // now everything between part1 and part2 is + // supposed to be numeric, describing the + // number of kB of Video RAM supported + int rtn = 0; + for (; part1 < part2; ++part1) + { + //lldebugs << "kB" << *part1 << llendl; + if (*part1 < '0' || *part1 > '9') + { + // unexpected char, abort parse + rtn = 0; + break; + } + rtn *= 10; + rtn += (*part1) - '0'; + } + if (rtn > 0) + { + // got the kB number. return it now. + return rtn; + } + } + } + } + return 0; // 'could not detect' +} +static int x11_detect_VRAM_kb() +{ + std::string x_log_location("/var/log/"); + std::string fname; + int rtn = 0; // 'could not detect' + int display_num = 0; + FILE *fp; + char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc + // parse DISPLAY number so we can go grab the right log file + if (display_env[0] == ':' && + display_env[1] >= '0' && display_env[1] <= '9') + { + display_num = display_env[1] - '0'; + } + + // *TODO: we could be smarter and see which of Xorg/XFree86 has the + // freshest time-stamp. + + // Try XOrg log first + fname = x_log_location; + fname += "Xorg."; + fname += ('0' + display_num); + fname += ".log"; + fp = fopen(fname.c_str(), "r"); + if (fp) + { + rtn = x11_detect_VRAM_kb_fp(fp); + fclose(fp); + } + // Try old XFree86 log otherwise + if (rtn == 0) + { + fname = x_log_location; + fname += "XFree86."; + fname += ('0' + display_num); + fname += ".log"; + fp = fopen(fname.c_str(), "r"); + if (fp) + { + rtn = x11_detect_VRAM_kb_fp(fp); + fclose(fp); + } + } + return rtn; +} +#endif // LL_X11 + BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) { //bool glneedsinit = false; @@ -491,67 +558,40 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B { llinfos << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << llendl; } - - /*if (!load_all_glsyms(gllibname)) - { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - return FALSE; - }*/ - - gGLManager.mVRAM = videoInfo->video_mem / 1024; + + // Detect video memory size. +# if LL_X11 + gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024; if (gGLManager.mVRAM != 0) { - llinfos << "Detected " << gGLManager.mVRAM << "MB VRAM." << llendl; - } - // If VRAM is not detected, that is handled later - -#if 0 // *FIX: all video cards suck under Linux. :) - // Since we just created the context, it needs to be set up. - glNeedsInit = TRUE; - if(glNeedsInit) - { - // Check for some explicitly unsupported cards. - const char* RENDERER = (const char*) glGetString(GL_RENDERER); - - const char* CARD_LIST[] = - { "RAGE 128", - "RIVA TNT2", - "Intel 810", - "3Dfx/Voodoo3", - "Radeon 7000", - "Radeon 7200", - "Radeon 7500", - "Radeon DDR", - "Radeon VE", - "GDI Generic" }; - const S32 CARD_COUNT = sizeof(CARD_LIST)/sizeof(char*); - - // Future candidates: - // ProSavage/Twister - // SuperSavage - - S32 i; - for (i = 0; i < CARD_COUNT; i++) + llinfos << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << llendl; + } else +# endif // LL_X11 + { + // fallback to letting SDL detect VRAM. + // note: I've not seen SDL's detection ever actually find + // VRAM != 0, but if SDL *does* detect it then that's a bonus. + gGLManager.mVRAM = videoInfo->video_mem / 1024; + if (gGLManager.mVRAM != 0) { - if (check_for_card(RENDERER, CARD_LIST[i])) - { - close(); - shell_open( "help/unsupported_card.html" ); - return FALSE; - } + llinfos << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << llendl; } } -#endif + // If VRAM is not detected, that is handled later - GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits; + // *TODO: Now would be an appropriate time to check for some + // explicitly unsupported cards. + //const char* RENDERER = (const char*) glGetString(GL_RENDERER); - glGetIntegerv(GL_RED_BITS, &redBits); - glGetIntegerv(GL_GREEN_BITS, &greenBits); - glGetIntegerv(GL_BLUE_BITS, &blueBits); - glGetIntegerv(GL_ALPHA_BITS, &alphaBits); - glGetIntegerv(GL_DEPTH_BITS, &depthBits); - glGetIntegerv(GL_STENCIL_BITS, &stencilBits); + GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits; + glGetIntegerv(GL_RED_BITS, &redBits); + glGetIntegerv(GL_GREEN_BITS, &greenBits); + glGetIntegerv(GL_BLUE_BITS, &blueBits); + glGetIntegerv(GL_ALPHA_BITS, &alphaBits); + glGetIntegerv(GL_DEPTH_BITS, &depthBits); + glGetIntegerv(GL_STENCIL_BITS, &stencilBits); + llinfos << "GL buffer:" << llendl llinfos << " Red Bits " << S32(redBits) << llendl llinfos << " Green Bits " << S32(greenBits) << llendl @@ -1002,7 +1042,9 @@ void LLWindowSDL::beforeDialog() { // Everything that we/SDL asked for should happen before we // potentially hand control over to GTK. + maybe_lock_display(); XSync(mSDL_Display, False); + maybe_unlock_display(); } #endif // LL_X11 @@ -1046,6 +1088,7 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent) llinfos << "X11 hint for urgency, " << urgent << llendl; + maybe_lock_display(); wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID); if (!wm_hints) wm_hints = XAllocWMHints(); @@ -1058,6 +1101,7 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent) XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints); XFree(wm_hints); XSync(mSDL_Display, False); + maybe_unlock_display(); } } #endif // LL_X11 @@ -1762,10 +1806,12 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) { //llinfos << "X11 POINTER GRABBY" << llendl; //newmode = SDL_WM_GrabInput(wantmode); + maybe_lock_display(); result = XGrabPointer(mSDL_Display, mSDL_XWindowID, True, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + maybe_unlock_display(); if (GrabSuccess == result) newmode = SDL_GRAB_ON; else @@ -1775,10 +1821,12 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture) //llinfos << "X11 POINTER UNGRABBY" << llendl; newmode = SDL_GRAB_OFF; //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF); - + + maybe_lock_display(); XUngrabPointer(mSDL_Display, CurrentTime); // Make sure the ungrab happens RIGHT NOW. XSync(mSDL_Display, False); + maybe_unlock_display(); } else { newmode = SDL_GRAB_QUERY; // neutral @@ -1855,7 +1903,7 @@ void LLWindowSDL::gatherInput() std::string saved_locale = setlocale(LC_ALL, NULL); // Do a limited number of pumps so SL doesn't starve! - // FIXME - this should ideally be time-limited, not count-limited. + // *TODO: this should ideally be time-limited, not count-limited. gtk_main_iteration_do(0); // Always do one non-blocking pump for (int iter=0; iter<10; ++iter) if (gtk_events_pending()) @@ -2081,8 +2129,8 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty if (bmpsurface && bmpsurface->w%8==0) { SDL_Surface *cursurface; - llinfos << "Loaded cursor file " << filename << " " - << bmpsurface->w << "x" << bmpsurface->h << llendl; + lldebugs << "Loaded cursor file " << filename << " " + << bmpsurface->w << "x" << bmpsurface->h << llendl; cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE, bmpsurface->w, bmpsurface->h, @@ -2262,14 +2310,14 @@ void LLWindowSDL::hideCursor() { if(!mCursorHidden) { - // llinfos << "hideCursor: hiding" << llendl; + // llinfos << "hideCursor: hiding" << llendl; mCursorHidden = TRUE; mHideCursorPermanent = TRUE; SDL_ShowCursor(0); } else { - // llinfos << "hideCursor: already hidden" << llendl; + // llinfos << "hideCursor: already hidden" << llendl; } adjustCursorDecouple(); @@ -2279,14 +2327,14 @@ void LLWindowSDL::showCursor() { if(mCursorHidden) { - // llinfos << "showCursor: showing" << llendl; + // llinfos << "showCursor: showing" << llendl; mCursorHidden = FALSE; mHideCursorPermanent = FALSE; SDL_ShowCursor(1); } else { - // llinfos << "showCursor: already visible" << llendl; + // llinfos << "showCursor: already visible" << llendl; } adjustCursorDecouple(); @@ -2312,7 +2360,8 @@ void LLWindowSDL::hideCursorUntilMouseMove() // -// LLSplashScreenSDL +// LLSplashScreenSDL - I don't think we'll bother to implement this; it's +// fairly obsolete at this point. // LLSplashScreenSDL::LLSplashScreenSDL() { @@ -2330,7 +2379,6 @@ void LLSplashScreenSDL::updateImpl(const char* mesg) { } - void LLSplashScreenSDL::hideImpl() { } @@ -2418,7 +2466,7 @@ S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type) G_CALLBACK (response_callback), &response); - // we should be able to us a gtk_dialog_run(), but it's + // we should be able to use a gtk_dialog_run(), but it's // apparently not written to exist in a world without a higher // gtk_main(), so we manage its signal/destruction outselves. gtk_widget_show_all (win); @@ -2440,7 +2488,7 @@ S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type) } else { - fprintf(stderr, "MSGBOX: %s: %s\n", caption, text); + llinfos << "MSGBOX: " << caption << ": " << text << llendl; llinfos << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << llendl; rtn = OSBTN_OK; } @@ -2536,7 +2584,7 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b) #else S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type) { - fprintf(stderr, "MSGBOX: %s: %s\n", caption, text); + llinfos << "MSGBOX: " << caption << ": " << text << llendl; return 0; } @@ -2553,11 +2601,15 @@ void spawn_web_browser(const char* escaped_url) llinfos << "spawn_web_browser: " << escaped_url << llendl; #if LL_LINUX -# if LL_X11 - if (gWindowImplementation && - gWindowImplementation->mSDL_Display) // Just in case - before forking. +# if LL_X11 + if (gWindowImplementation && gWindowImplementation->mSDL_Display) + { + maybe_lock_display(); + // Just in case - before forking. XSync(gWindowImplementation->mSDL_Display, False); -# endif // LL_X11 + maybe_unlock_display(); + } +# endif // LL_X11 std::string cmd; cmd = gDirUtilp->getAppRODataDir().c_str(); @@ -2595,8 +2647,8 @@ void spawn_web_browser(const char* escaped_url) void shell_open( const char* file_path ) { - // *FIX: (???) - fprintf(stderr, "shell_open: %s\n", file_path); + // *TODO: This function is deprecated and should probably go away. + llwarns << "Deprecated shell_open(): " << file_path << llendl; } void *LLWindowSDL::getPlatformWindow() @@ -2604,18 +2656,14 @@ void *LLWindowSDL::getPlatformWindow() #if LL_GTK && LL_LIBXUL_ENABLED if (ll_try_gtk_init()) { + maybe_lock_display(); GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - // These hacks were attempts to get Gecko to see the keyboard, - // but I think they're doomed to fail. - //GdkWindow *gdkwin = gdk_window_foreign_new(SDL_XWindowID); - //GTK_WIDGET(win)->window = gdkwin; - //gtk_widget_set_parent_window(win, gdkwin); - // show the hidden-widget while debugging (needs mozlib change) //gtk_widget_show_all(GTK_WIDGET(win)); gtk_widget_realize(GTK_WIDGET(win)); + maybe_unlock_display(); return win; } #endif // LL_GTK && LL_LIBXUL_ENABLED @@ -2625,8 +2673,18 @@ void *LLWindowSDL::getPlatformWindow() void LLWindowSDL::bringToFront() { - // *FIX: (???) - fprintf(stderr, "bringToFront\n"); + // This is currently used when we are 'launched' to a specific + // map position externally. + llinfos << "bringToFront" << llendl; +#if LL_X11 + if (mSDL_Display && !mFullscreen) + { + maybe_lock_display(); + XRaiseWindow(mSDL_Display, mSDL_XWindowID); + XSync(mSDL_Display, False); + maybe_unlock_display(); + } +#endif // LL_X11 } #endif // LL_SDL |