📄 sdl_video.c
字号:
--i; *w = sizes[i]->w; *h = sizes[i]->h; *BitsPerPixel = SDL_closest_depths[table][b]; supported = 1; } } if ( ! supported ) { SDL_SetError("No video mode large enough for %dx%d", *w, *h); } return(supported);}/* This should probably go somewhere else -- like SDL_surface.c */static void SDL_ClearSurface(SDL_Surface *surface){ Uint32 black; black = SDL_MapRGB(surface->format, 0, 0, 0); SDL_FillRect(surface, NULL, black); if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) { SDL_Flip(surface); SDL_FillRect(surface, NULL, black); } SDL_Flip(surface);}/* * Create a shadow surface suitable for fooling the app. :-) */static void SDL_CreateShadowSurface(int depth){ Uint32 Rmask, Gmask, Bmask; /* Allocate the shadow surface */ if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { Rmask = (SDL_VideoSurface->format)->Rmask; Gmask = (SDL_VideoSurface->format)->Gmask; Bmask = (SDL_VideoSurface->format)->Bmask; } else { Rmask = Gmask = Bmask = 0; } SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, SDL_VideoSurface->w, SDL_VideoSurface->h, depth, Rmask, Gmask, Bmask, 0); if ( SDL_ShadowSurface == NULL ) { return; } /* 8-bit shadow surfaces report that they have exclusive palette */ if ( SDL_ShadowSurface->format->palette ) { SDL_ShadowSurface->flags |= SDL_HWPALETTE; if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { memcpy(SDL_ShadowSurface->format->palette->colors, SDL_VideoSurface->format->palette->colors, SDL_VideoSurface->format->palette->ncolors* sizeof(SDL_Color)); } else { SDL_DitherColors( SDL_ShadowSurface->format->palette->colors, depth); } } /* If the video surface is resizable, the shadow should say so */ if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) { SDL_ShadowSurface->flags |= SDL_RESIZABLE; } /* If the video surface has no frame, the shadow should say so */ if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) { SDL_ShadowSurface->flags |= SDL_NOFRAME; } /* If the video surface is fullscreen, the shadow should say so */ if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { SDL_ShadowSurface->flags |= SDL_FULLSCREEN; } /* If the video surface is flippable, the shadow should say so */ if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { SDL_ShadowSurface->flags |= SDL_DOUBLEBUF; } return;}/* * Set the requested video mode, allocating a shadow buffer if necessary. */SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags){ SDL_VideoDevice *video, *this; SDL_Surface *prev_mode, *mode; int video_w; int video_h; int video_bpp; int is_opengl; SDL_GrabMode saved_grab; /* Start up the video driver, if necessary.. WARNING: This is the only function protected this way! */ if ( ! current_video ) { if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) { return(NULL); } } this = video = current_video; /* Default to the current video bpp */ if ( bpp == 0 ) { flags |= SDL_ANYFORMAT; bpp = SDL_VideoSurface->format->BitsPerPixel; } /* Get a good video mode, the closest one possible */ video_w = width; video_h = height; video_bpp = bpp; if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) { return(NULL); } /* Check the requested flags */ /* There's no palette in > 8 bits-per-pixel mode */ if ( video_bpp > 8 ) { flags &= ~SDL_HWPALETTE; }#if 0 if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) { /* There's no windowed double-buffering */ flags &= ~SDL_DOUBLEBUF; }#endif if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { /* Use hardware surfaces when double-buffering */ flags |= SDL_HWSURFACE; } is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL ); if ( is_opengl ) { /* These flags are for 2D video modes only */ flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF); } /* Reset the keyboard here so event callbacks can run */ SDL_ResetKeyboard(); SDL_ResetMouse(); /* Clean up any previous video mode */ if ( SDL_PublicSurface != NULL ) { SDL_PublicSurface = NULL; } if ( SDL_ShadowSurface != NULL ) { SDL_Surface *ready_to_go; ready_to_go = SDL_ShadowSurface; SDL_ShadowSurface = NULL; SDL_FreeSurface(ready_to_go); } if ( video->physpal ) { free(video->physpal->colors); free(video->physpal); video->physpal = NULL; } if( video->gammacols) { free(video->gammacols); video->gammacols = NULL; } /* Save the previous grab state and turn off grab for mode switch */ saved_grab = SDL_WM_GrabInputOff(); /* Try to set the video mode, along with offset and clipping */ prev_mode = SDL_VideoSurface; SDL_LockCursor(); SDL_VideoSurface = NULL; /* In case it's freed by driver */ mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags); if ( mode ) { /* Prevent resize events from mode change */ SDL_PrivateResize(mode->w, mode->h); /* Sam - If we asked for OpenGL mode, and didn't get it, fail */ if ( is_opengl && !(mode->flags & SDL_OPENGL) ) { mode = NULL; } } /* * rcg11292000 * If you try to set an SDL_OPENGL surface, and fail to find a * matching visual, then the next call to SDL_SetVideoMode() * will segfault, since we no longer point to a dummy surface, * but rather NULL. * Sam 11/29/00 * WARNING, we need to make sure that the previous mode hasn't * already been freed by the video driver. What do we do in * that case? Should we call SDL_VideoInit() again? */ SDL_VideoSurface = (mode != NULL) ? mode : prev_mode; if ( (mode != NULL) && (!is_opengl) ) { /* Sanity check */ if ( (mode->w < width) || (mode->h < height) ) { SDL_SetError("Video mode smaller than requested"); return(NULL); } /* If we have a palettized surface, create a default palette */ if ( mode->format->palette ) { SDL_PixelFormat *vf = mode->format; SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); video->SetColors(this, 0, vf->palette->ncolors, vf->palette->colors); } /* Clear the surface to black */ video->offset_x = 0; video->offset_y = 0; mode->offset = 0; SDL_SetClipRect(mode, NULL); SDL_ClearSurface(mode); /* Now adjust the offsets to match the desired mode */ video->offset_x = (mode->w-width)/2; video->offset_y = (mode->h-height)/2; mode->offset = video->offset_y*mode->pitch + video->offset_x*mode->format->BytesPerPixel;#ifdef DEBUG_VIDEO fprintf(stderr, "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n", width, height, bpp, mode->w, mode->h, mode->format->BitsPerPixel, mode->offset);#endif mode->w = width; mode->h = height; SDL_SetClipRect(mode, NULL); } SDL_ResetCursor(); SDL_UnlockCursor(); /* If we failed setting a video mode, return NULL... (Uh Oh!) */ if ( mode == NULL ) { return(NULL); } /* If there is no window manager, set the SDL_NOFRAME flag */ if ( ! video->info.wm_available ) { mode->flags |= SDL_NOFRAME; } /* Reset the mouse cursor and grab for new video mode */ SDL_SetCursor(NULL); if ( video->UpdateMouse ) { video->UpdateMouse(this); } SDL_WM_GrabInput(saved_grab); SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */ /* If we're running OpenGL, make the context current */ if ( (video->screen->flags & SDL_OPENGL) && video->GL_MakeCurrent ) { if ( video->GL_MakeCurrent(this) < 0 ) { return(NULL); } } /* Set up a fake SDL surface for OpenGL "blitting" */ if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) { /* Load GL functions for performing the texture updates */#ifdef HAVE_OPENGL#define SDL_PROC(ret,func,params) \do { \ video->func = SDL_GL_GetProcAddress(#func); \ if ( ! video->func ) { \ SDL_SetError("Couldn't load GL function: %s\n", #func); \ return(NULL); \ } \} while ( 0 );#include "SDL_glfuncs.h"#undef SDL_PROC /* Create a software surface for blitting */#ifdef GL_VERSION_1_2 /* If the implementation either supports the packed pixels extension, or implements the core OpenGL 1.2 API, it will support the GL_UNSIGNED_SHORT_5_6_5 texture format. */ if ( (bpp == 16) && (strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") || (atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f)) ) { video->is_32bit = 0; SDL_VideoSurface = SDL_CreateRGBSurface( flags, width, height, 16, 31 << 11, 63 << 5, 31, 0 ); } else#endif /* OpenGL 1.2 */ { video->is_32bit = 1; SDL_VideoSurface = SDL_CreateRGBSurface( flags, width, height, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000#else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF#endif ); } if ( ! SDL_VideoSurface ) { return(NULL); } SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT; /* Free the original video mode surface (is this safe?) */ SDL_FreeSurface(mode); /* Set the surface completely opaque & white by default */ memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch ); video->glGenTextures( 1, &video->texture ); video->glBindTexture( GL_TEXTURE_2D, video->texture ); video->glTexImage2D( GL_TEXTURE_2D, 0, video->is_32bit ? GL_RGBA : GL_RGB, 256, 256, 0, video->is_32bit ? GL_RGBA : GL_RGB,#ifdef GL_VERSION_1_2 video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,#else GL_UNSIGNED_BYTE,#endif NULL); video->UpdateRects = SDL_GL_UpdateRectsLock;#else SDL_SetError("Somebody forgot to #define HAVE_OPENGL"); return(NULL);#endif } /* Create a shadow surface if necessary */ /* There are three conditions under which we create a shadow surface: 1. We need a particular bits-per-pixel that we didn't get. 2. We need a hardware palette and didn't get one. 3. We need a software surface and got a hardware surface. */ if ( !(SDL_VideoSurface->flags & SDL_OPENGL) && ( ( !(flags&SDL_ANYFORMAT) && (SDL_VideoSurface->format->BitsPerPixel != bpp)) || ( (flags&SDL_HWPALETTE) && !(SDL_VideoSurface->flags&SDL_HWPALETTE)) || /* If the surface is in hardware, video writes are visible as soon as they are performed, so we need to buffer them */ ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) && (SDL_VideoSurface->flags&SDL_HWSURFACE)) ) ) { SDL_CreateShadowSurface(bpp); if ( SDL_ShadowSurface == NULL ) { SDL_SetError("Couldn't create shadow surface"); return(NULL); } SDL_PublicSurface = SDL_ShadowSurface; } else { SDL_PublicSurface = SDL_VideoSurface; } video->info.vfmt = SDL_VideoSurface->format; /* We're done! */ return(SDL_PublicSurface);}/* * Convert a surface into the video pixel format. */SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface){ Uint32 flags; if ( ! SDL_PublicSurface ) { SDL_SetError("No video mode has been set"); return(NULL); } /* Set the flags appropriate for copying to display surface */ if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw) flags = SDL_HWSURFACE; else flags = SDL_SWSURFACE;#ifdef AUTORLE_DISPLAYFORMAT flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA)); flags |= SDL_RLEACCELOK;#else flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK);#endif return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags));}/* * Convert a surface into a format that's suitable for blitting to * the screen, but including an alpha channel. */SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface){ SDL_PixelFormat *vf; SDL_PixelFormat *format; SDL_Surface *converted; Uint32 flags; /* default to ARGB8888 */ Uint32 amask = 0xff000000; Uint32 rmask = 0x00ff0000; Uint32 gmask = 0x0000ff00; Uint32 bmask = 0x000000ff; if ( ! SDL_PublicSurface ) { SDL_SetError("No video mode has been set"); return(NULL); } vf = SDL_PublicSurface->format; switch(vf->BytesPerPixel) { case 2: /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. For anything else (like ARGB4444) it doesn't matter since we have no special code for it anyway */ if ( (vf->Rmask == 0x1f) && (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { rmask = 0xff; bmask = 0xff0000; } break; case 3: case 4: /* Keep the video format, as long as the high 8 bits are unused or alpha */ if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) { rmask = 0xff; bmask = 0xff0000; } break; default: /* We have no other optimised formats right now. When/if a new optimised alpha format is written, add the converter here */ break; } format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); flags = SDL_PublicSurface->flags & SDL_HWSURFACE; flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); converted = SDL_ConvertSurface(surface, format, flags); SDL_FreeFormat(format); return(converted);}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -