X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=vid_sdl.c;h=9618cb611d2ebcd80884afe8fa10bc9e785c96d5;hp=ea0e80005f2dd4eb3528b872da1bd5882c6e69a2;hb=a37cd455150d17f68eec25ae6fa57808d940f1ae;hpb=2e9672e5e2e088ff3b50e5000b00170d70ab44aa diff --git a/vid_sdl.c b/vid_sdl.c index ea0e8000..9618cb61 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -18,9 +18,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #undef WIN32_LEAN_AND_MEAN //hush a warning, SDL.h redefines this #include +#include #include #include "quakedef.h" +#include "image.h" #ifdef WIN32 #define SDL_R_RESTART @@ -388,7 +390,7 @@ void Sys_SendKeyEvents( void ) break; case SDL_KEYDOWN: case SDL_KEYUP: - Key_Event( MapKey( event.key.keysym.sym ), (char)event.key.keysym.unicode, (event.key.state == SDL_PRESSED) ); + Key_Event( MapKey( event.key.keysym.sym ), event.key.keysym.unicode, (event.key.state == SDL_PRESSED) ); break; case SDL_ACTIVEEVENT: if( event.active.state & SDL_APPACTIVE ) @@ -488,7 +490,7 @@ void VID_Init (void) //Cvar_RegisterVariable(&joy_sensitivityroll); #ifdef SDL_R_RESTART - R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap); + R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL); #endif if (SDL_Init(SDL_INIT_VIDEO) < 0) @@ -503,7 +505,7 @@ void VID_Init (void) #ifdef WIN32 #include "resource.h" #include -static void VID_SetCaption() +static void VID_SetCaption(void) { SDL_SysWMinfo info; HICON icon; @@ -530,7 +532,10 @@ static void VID_SetCaption() #endif SetClassLongPtr( info.window, GCLP_HICON, (LONG_PTR)icon ); } -static void VID_SetIcon() +static void VID_SetIcon_Pre(void) +{ +} +static void VID_SetIcon_Post(void) { } #else @@ -538,7 +543,7 @@ static void VID_SetIcon() #include "darkplaces.xpm" #include "nexuiz.xpm" static SDL_Surface *icon = NULL; -static void VID_SetIcon() +static void VID_SetIcon_Pre(void) { /* * Somewhat restricted XPM reader. Only supports XPMs saved by GIMP 2.4 at @@ -549,104 +554,213 @@ static void VID_SetIcon() int thenone = -1; static SDL_Color palette[256]; unsigned short palenc[256]; // store color id by char + char *xpm; + char **idata, *data; + const SDL_version *version; - char **idata = ENGINE_ICON; - char *data = idata[0]; - - if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4) + version = SDL_Linked_Version(); + // only use non-XPM icon support in SDL v1.3 and higher + // SDL v1.2 does not support "smooth" transparency, and thus is better + // off the xpm way + if(version->major >= 2 || (version->major == 1 && version->minor >= 3)) { - // NOTE: Only 1-char colornames are supported - Con_Printf("Sorry, but this does not even look similar to an XPM.\n"); - return; - } + data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL); + if(data) + { + unsigned int red = 0x00FF0000; + unsigned int green = 0x0000FF00; + unsigned int blue = 0x000000FF; + unsigned int alpha = 0xFF000000; + width = image_width; + height = image_height; + + // reallocate with malloc, as this is in tempmempool (do not want) + xpm = data; + data = malloc(width * height * 4); + memcpy(data, xpm, width * height * 4); + Mem_Free(xpm); + xpm = NULL; + + icon = SDL_CreateRGBSurface(SDL_SRCALPHA, width, height, 32, LittleLong(red), LittleLong(green), LittleLong(blue), LittleLong(alpha)); + + if(icon == NULL) { + Con_Printf( "Failed to create surface for the window Icon!\n" + "%s\n", SDL_GetError()); + free(data); + return; + } - if(isize != 1) - { - // NOTE: Only 1-char colornames are supported - Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize); - return; + icon->pixels = data; + } } - for(i = 0; i < colors; ++i) + // we only get here if non-XPM icon was missing, or SDL version is not + // sufficient for transparent non-XPM icons + if(!icon) { - unsigned int r, g, b; - char idx; + xpm = (char *) FS_LoadFile("darkplaces-icon.xpm", tempmempool, false, NULL); + idata = NULL; + if(xpm) + idata = XPM_DecodeString(xpm); + if(!idata) + idata = ENGINE_ICON; + if(xpm) + Mem_Free(xpm); + + data = idata[0]; + + if(sscanf(data, "%i %i %i %i", &width, &height, &colors, &isize) != 4) + { + // NOTE: Only 1-char colornames are supported + Con_Printf("Sorry, but this does not even look similar to an XPM.\n"); + return; + } - if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4) + if(isize != 1) { - char foo[2]; - if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0 + // NOTE: Only 1-char colornames are supported + Con_Printf("This XPM's palette is either huge or idiotically unoptimized. It's key size is %i\n", isize); + return; + } + + for(i = 0; i < colors; ++i) + { + unsigned int r, g, b; + char idx; + + if(sscanf(idata[i+1], "%c c #%02x%02x%02x", &idx, &r, &g, &b) != 4) { - Con_Printf("This XPM's palette looks odd. Can't continue.\n"); - return; + char foo[2]; + if(sscanf(idata[i+1], "%c c Non%1[e]", &idx, foo) != 2) // I take the DailyWTF credit for this. --div0 + { + Con_Printf("This XPM's palette looks odd. Can't continue.\n"); + return; + } + else + { + palette[i].r = 255; // color key + palette[i].g = 0; + palette[i].b = 255; + thenone = i; // weeeee + } } else { - palette[i].r = 255; // color key - palette[i].g = 0; - palette[i].b = 255; - thenone = i; // weeeee + palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key + palette[i].g = g; + palette[i].b = b; } + + palenc[(unsigned char) idx] = i; } - else + + // allocate the image data + data = (char*) malloc(width*height); + + for(j = 0; j < height; ++j) { - palette[i].r = r - (r == 255 && g == 0 && b == 255); // change 255/0/255 pink to 254/0/255 for color key - palette[i].g = g; - palette[i].b = b; + for(i = 0; i < width; ++i) + { + // casting to the safest possible datatypes ^^ + data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]]; + } } - palenc[(unsigned char) idx] = i; - } + if(icon != NULL) + { + // SDL_FreeSurface should free the data too + // but for completeness' sake... + if(icon->flags & SDL_PREALLOC) + { + free(icon->pixels); + icon->pixels = NULL; // safety + } + SDL_FreeSurface(icon); + } - // allocate the image data - data = (char*) malloc(width*height); + icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed + // 8 bit surfaces get an empty palette allocated according to the docs + // so it's a palette image for sure :) no endian check necessary for the mask - for(j = 0; j < height; ++j) - { - for(i = 0; i < width; ++i) - { - // casting to the safest possible datatypes ^^ - data[j * width + i] = palenc[((unsigned char*)idata[colors+j+1])[i]]; + if(icon == NULL) { + Con_Printf( "Failed to create surface for the window Icon!\n" + "%s\n", SDL_GetError()); + free(data); + return; } + + icon->pixels = data; + SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors); + SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone); } - if(icon != NULL) + SDL_WM_SetIcon(icon, NULL); +} +static void VID_SetIcon_Post(void) +{ +#if SDL_VIDEO_DRIVER_X11 && !SDL_VIDEO_DRIVER_QUARTZ + int j; + char *data; + const SDL_version *version; + + version = SDL_Linked_Version(); + // only use non-XPM icon support in SDL v1.3 and higher + // SDL v1.2 does not support "smooth" transparency, and thus is better + // off the xpm way + if(!(version->major >= 2 || (version->major == 1 && version->minor >= 3))) { - // SDL_FreeSurface should free the data too - // but for completeness' sake... - if(icon->flags & SDL_PREALLOC) + // in this case, we did not set the good icon yet + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + if(SDL_GetWMInfo(&info) == 1 && info.subsystem == SDL_SYSWM_X11) { - free(icon->pixels); - icon->pixels = NULL; // safety - } - SDL_FreeSurface(icon); - } + data = (char *) loadimagepixelsbgra("darkplaces-icon", false, false, false, NULL); + if(data) + { + // use _NET_WM_ICON too + static long netwm_icon[MAX_NETWM_ICON]; + int pos = 0; + int i = 1; - icon = SDL_CreateRGBSurface(SDL_SRCCOLORKEY, width, height, 8, 0,0,0,0);// rmask, gmask, bmask, amask); no mask needed - // 8 bit surfaces get an empty palette allocated according to the docs - // so it's a palette image for sure :) no endian check necessary for the mask + while(data) + { + if(pos + 2 * image_width * image_height < MAX_NETWM_ICON) + { + netwm_icon[pos++] = image_width; + netwm_icon[pos++] = image_height; + for(i = 0; i < image_height; ++i) + for(j = 0; j < image_width; ++j) + netwm_icon[pos++] = BuffLittleLong((unsigned char *) &data[(i*image_width+j)*4]); + } + else + { + Con_Printf("Skipping NETWM icon #%d because there is no space left\n", i); + } + ++i; + Mem_Free(data); + data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL); + } - if(icon == NULL) { - Con_Printf( "Failed to create surface for the window Icon!\n" - "%s\n", SDL_GetError()); - free(data); - return; + info.info.x11.lock_func(); + { + Atom net_wm_icon = XInternAtom(info.info.x11.display, "_NET_WM_ICON", false); + XChangeProperty(info.info.x11.display, info.info.x11.wmwindow, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos); + } + info.info.x11.unlock_func(); + } + } } - icon->pixels = data; - SDL_SetPalette(icon, SDL_PHYSPAL|SDL_LOGPAL, palette, 0, colors); - SDL_SetColorKey(icon, SDL_SRCCOLORKEY, thenone); - - SDL_WM_SetIcon(icon, NULL); +#endif } -static void VID_SetCaption() +static void VID_SetCaption(void) { SDL_WM_SetCaption( gamename, NULL ); } #endif -static void VID_OutputVersion() +static void VID_OutputVersion(void) { const SDL_version *version; version = SDL_Linked_Version(); @@ -656,15 +770,15 @@ static void VID_OutputVersion() version->major, version->minor, version->patch ); } -int VID_InitMode(int fullscreen, int *width, int *height, int bpp, int refreshrate, int stereobuffer, int samples) +qboolean VID_InitMode(viddef_mode_t *mode) { int i; static int notfirstvideomode = false; int flags = SDL_OPENGL; const char *drivername; - win_half_width = *width>>1; - win_half_height = *height>>1; + win_half_width = mode->width>>1; + win_half_height = mode->height>>1; if(vid_resizable.integer) flags |= SDL_RESIZABLE; @@ -703,14 +817,14 @@ int VID_InitMode(int fullscreen, int *width, int *height, int bpp, int refreshra // Knghtbrd: should do platform-specific extension string function here vid_isfullscreen = false; - if (fullscreen) { + if (mode->fullscreen) { flags |= SDL_FULLSCREEN; vid_isfullscreen = true; } //flags |= SDL_HWSURFACE; SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); - if (bpp >= 32) + if (mode->bitsperpixel >= 32) { SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); @@ -726,26 +840,27 @@ int VID_InitMode(int fullscreen, int *width, int *height, int bpp, int refreshra SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16); } - if (stereobuffer) + if (mode->stereobuffer) SDL_GL_SetAttribute (SDL_GL_STEREO, 1); if (vid_vsync.integer) SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); else SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 0); - if (samples > 1) + if (mode->samples > 1) { SDL_GL_SetAttribute (SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, samples); + SDL_GL_SetAttribute (SDL_GL_MULTISAMPLESAMPLES, mode->samples); } - video_bpp = bpp; + video_bpp = mode->bitsperpixel; video_flags = flags; - VID_SetIcon(); - screen = SDL_SetVideoMode(*width, *height, bpp, flags); + VID_SetIcon_Pre(); + screen = SDL_SetVideoMode(mode->width, mode->height, mode->bitsperpixel, flags); + VID_SetIcon_Post(); if (screen == NULL) { - Con_Printf("Failed to set video mode to %ix%i: %s\n", *width, *height, SDL_GetError()); + Con_Printf("Failed to set video mode to %ix%i: %s\n", mode->width, mode->height, SDL_GetError()); VID_Shutdown(); return false; } @@ -761,7 +876,6 @@ int VID_InitMode(int fullscreen, int *width, int *height, int bpp, int refreshra gl_platform = "SDL"; gl_platformextensions = ""; - gl_videosyncavailable = true; GL_Init(); @@ -830,7 +944,7 @@ void VID_Finish (void) VID_UpdateGamma(false, 256); - if (r_render.integer && !vid_hidden) + if (!vid_hidden) { CHECKGLERROR if (r_speeds.integer == 2 || gl_finish.integer)