📄 sdl_dibvideo.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997, 1998, 1999 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_dibvideo.c,v 1.20 2002/10/06 20:31:34 slouken Exp $";#endif#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <windows.h>#if defined(WIN32_PLATFORM_PSPC)#include <aygshell.h> // Add Pocket PC includes#pragma comment( lib, "aygshell" ) // Link Pocket PC library#endif/* Not yet in the mingw32 cross-compile headers */#ifndef CDS_FULLSCREEN#define CDS_FULLSCREEN 4#endif#include "SDL.h"#include "SDL_mutex.h"#include "SDL_syswm.h"#include "SDL_sysvideo.h"#include "SDL_sysevents.h"#include "SDL_events_c.h"#include "SDL_pixels_c.h"#include "SDL_dibvideo.h"#include "SDL_syswm_c.h"#include "SDL_sysmouse_c.h"#include "SDL_dibevents_c.h"#include "SDL_wingl_c.h"#ifdef _WIN32_WCE#define NO_GETDIBITS#define NO_CHANGEDISPLAYSETTINGS#define NO_GAMMA_SUPPORT#endif#ifndef WS_MAXIMIZE#define WS_MAXIMIZE 0#endif#ifndef SWP_NOCOPYBITS#define SWP_NOCOPYBITS 0#endif#ifndef PC_NOCOLLAPSE#define PC_NOCOLLAPSE 0#endif/* Initialization/Query functions */static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);static int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);static void DIB_CheckGamma(_THIS);void DIB_SwapGamma(_THIS);void DIB_QuitGamma(_THIS);int DIB_SetGammaRamp(_THIS, Uint16 *ramp);int DIB_GetGammaRamp(_THIS, Uint16 *ramp);static void DIB_VideoQuit(_THIS);/* Hardware surface functions */static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);/* Windows message handling functions */static void DIB_RealizePalette(_THIS);static void DIB_PaletteChanged(_THIS, HWND window);static void DIB_WinPAINT(_THIS, HDC hdc);/* helper fn */static int DIB_SussScreenDepth();/* DIB driver bootstrap functions */static int DIB_Available(void){ return(1);}static void DIB_DeleteDevice(SDL_VideoDevice *device){ if ( device ) { if ( device->hidden ) { free(device->hidden); } if ( device->gl_data ) { free(device->gl_data); } free(device); }}static SDL_VideoDevice *DIB_CreateDevice(int devindex){ SDL_VideoDevice *device; /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); if ( device ) { memset(device, 0, (sizeof *device)); device->hidden = (struct SDL_PrivateVideoData *) malloc((sizeof *device->hidden)); device->gl_data = (struct SDL_PrivateGLData *) malloc((sizeof *device->gl_data)); } if ( (device == NULL) || (device->hidden == NULL) || (device->gl_data == NULL) ) { SDL_OutOfMemory(); DIB_DeleteDevice(device); return(NULL); } memset(device->hidden, 0, (sizeof *device->hidden)); memset(device->gl_data, 0, (sizeof *device->gl_data)); /* Set the function pointers */ device->VideoInit = DIB_VideoInit; device->ListModes = DIB_ListModes; device->SetVideoMode = DIB_SetVideoMode; device->UpdateMouse = WIN_UpdateMouse; device->SetColors = DIB_SetColors; device->UpdateRects = NULL; device->VideoQuit = DIB_VideoQuit; device->AllocHWSurface = DIB_AllocHWSurface; device->CheckHWBlit = NULL; device->FillHWRect = NULL; device->SetHWColorKey = NULL; device->SetHWAlpha = NULL; device->LockHWSurface = DIB_LockHWSurface; device->UnlockHWSurface = DIB_UnlockHWSurface; device->FlipHWSurface = NULL; device->FreeHWSurface = DIB_FreeHWSurface; device->SetGammaRamp = DIB_SetGammaRamp; device->GetGammaRamp = DIB_GetGammaRamp;#ifdef HAVE_OPENGL device->GL_LoadLibrary = WIN_GL_LoadLibrary; device->GL_GetProcAddress = WIN_GL_GetProcAddress; device->GL_GetAttribute = WIN_GL_GetAttribute; device->GL_MakeCurrent = WIN_GL_MakeCurrent; device->GL_SwapBuffers = WIN_GL_SwapBuffers;#endif device->SetCaption = WIN_SetWMCaption; device->SetIcon = WIN_SetWMIcon; device->IconifyWindow = WIN_IconifyWindow; device->GrabInput = WIN_GrabInput; device->GetWMInfo = WIN_GetWMInfo; device->FreeWMCursor = WIN_FreeWMCursor; device->CreateWMCursor = WIN_CreateWMCursor; device->ShowWMCursor = WIN_ShowWMCursor; device->WarpWMCursor = WIN_WarpWMCursor; device->CheckMouseMode = WIN_CheckMouseMode; device->InitOSKeymap = DIB_InitOSKeymap; device->PumpEvents = DIB_PumpEvents; /* Set up the windows message handling functions */ WIN_RealizePalette = DIB_RealizePalette; WIN_PaletteChanged = DIB_PaletteChanged; WIN_WinPAINT = DIB_WinPAINT; HandleMessage = DIB_HandleMessage; device->free = DIB_DeleteDevice; /* We're finally ready */ return device;}VideoBootStrap WINDIB_bootstrap = { "windib", "Win95/98/NT/2000 GDI", DIB_Available, DIB_CreateDevice};#ifndef NO_CHANGEDISPLAYSETTINGSstatic int cmpmodes(const void *va, const void *vb){ SDL_Rect *a = *(SDL_Rect **)va; SDL_Rect *b = *(SDL_Rect **)vb; if(a->w > b->w) return -1; return b->h - a->h;}static int DIB_AddMode(_THIS, int bpp, int w, int h){ SDL_Rect *mode; int i, index; int next_mode; /* Check to see if we already have this mode */ if ( bpp < 8 ) { /* Not supported */ return(0); } index = ((bpp+7)/8)-1; for ( i=0; i<SDL_nummodes[index]; ++i ) { mode = SDL_modelist[index][i]; if ( (mode->w == w) && (mode->h == h) ) { return(0); } } /* Set up the new video mode rectangle */ mode = (SDL_Rect *)malloc(sizeof *mode); if ( mode == NULL ) { SDL_OutOfMemory(); return(-1); } mode->x = 0; mode->y = 0; mode->w = w; mode->h = h; /* Allocate the new list of modes, and fill in the new mode */ next_mode = SDL_nummodes[index]; SDL_modelist[index] = (SDL_Rect **) realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); if ( SDL_modelist[index] == NULL ) { SDL_OutOfMemory(); SDL_nummodes[index] = 0; free(mode); return(-1); } SDL_modelist[index][next_mode] = mode; SDL_modelist[index][next_mode+1] = NULL; SDL_nummodes[index]++; return(0);}#endif /* !NO_CHANGEDISPLAYSETTINGS */static HPALETTE DIB_CreatePalette(int bpp){/* RJR: March 28, 2000 moved palette creation here from "DIB_VideoInit" */ HPALETTE handle = NULL; if ( bpp <= 8 ) { LOGPALETTE *palette; HDC hdc; int ncolors; int i; ncolors = 1; for ( i=0; i<bpp; ++i ) { ncolors *= 2; } palette = (LOGPALETTE *)malloc(sizeof(*palette)+ ncolors*sizeof(PALETTEENTRY)); palette->palVersion = 0x300; palette->palNumEntries = ncolors; hdc = GetDC(SDL_Window); GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); ReleaseDC(SDL_Window, hdc); handle = CreatePalette(palette); free(palette); } return handle;}int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat){#ifndef NO_CHANGEDISPLAYSETTINGS int i; DEVMODE settings;#endif /* Create the window */ if ( DIB_CreateWindow(this) < 0 ) { return(-1); }#ifndef DISABLE_AUDIO DX5_SoundFocus(SDL_Window);#endif /* Determine the screen depth */ vformat->BitsPerPixel = DIB_SussScreenDepth(); switch (vformat->BitsPerPixel) { case 15: vformat->Rmask = 0x00007c00; vformat->Gmask = 0x000003e0; vformat->Bmask = 0x0000001f; vformat->BitsPerPixel = 16; break; case 16: vformat->Rmask = 0x0000f800; vformat->Gmask = 0x000007e0; vformat->Bmask = 0x0000001f; break; case 24: case 32: /* GDI defined as 8-8-8 */ vformat->Rmask = 0x00ff0000; vformat->Gmask = 0x0000ff00; vformat->Bmask = 0x000000ff; break; default: break; } /* See if gamma is supported on this screen */ DIB_CheckGamma(this);#ifndef NO_CHANGEDISPLAYSETTINGS /* Query for the list of available video modes */ for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) { DIB_AddMode(this, settings.dmBitsPerPel, settings.dmPelsWidth, settings.dmPelsHeight); } /* Sort the mode lists */ for ( i=0; i<NUM_MODELISTS; ++i ) { if ( SDL_nummodes[i] > 0 ) { qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); } }#endif /* !NO_CHANGEDISPLAYSETTINGS */ /* Grab an identity palette if we are in a palettized mode */ if ( vformat->BitsPerPixel <= 8 ) { /* RJR: March 28, 2000 moved palette creation to "DIB_CreatePalette" */ screen_pal = DIB_CreatePalette(vformat->BitsPerPixel); } /* Fill in some window manager capabilities */ this->info.wm_available = 1; /* We're done! */ return(0);}/* We support any format at any dimension */SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags){#ifdef NO_CHANGEDISPLAYSETTINGS return((SDL_Rect **)-1);#else if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); } else { return((SDL_Rect **)-1); }#endif}/* Helper fn to work out which screen depth windows is currently using. 15 bit mode is considered 555 format, 16 bit is 565. returns 0 for unknown mode. (Derived from code in sept 1999 Windows Developer Journal http://www.wdj.com/code/archive.html)*/static int DIB_SussScreenDepth(){#ifdef NO_GETDIBITS int depth; HDC hdc; hdc = GetDC(SDL_Window); depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC(SDL_Window, hdc);#ifndef _WIN32_WCE // AFAIK 16 bit CE devices have indeed RGB 565 if ( depth == 16 ) { depth = 15; /* GDI defined as RGB 555 */ }#endif return(depth);#else int dib_size; LPBITMAPINFOHEADER dib_hdr; HDC hdc; HBITMAP hbm; /* Allocate enough space for a DIB header plus palette (for * 8-bit modes) or bitfields (for 16- and 32-bit modes) */ dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); dib_hdr = (LPBITMAPINFOHEADER) malloc(dib_size); memset(dib_hdr, 0, dib_size); dib_hdr->biSize = sizeof(BITMAPINFOHEADER); /* Get a device-dependent bitmap that's compatible with the screen. */ hdc = GetDC(NULL); hbm = CreateCompatibleBitmap( hdc, 1, 1 ); /* Convert the DDB to a DIB. We need to call GetDIBits twice: * the first call just fills in the BITMAPINFOHEADER; the * second fills in the bitfields or palette. */ GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); DeleteObject(hbm); ReleaseDC(NULL, hdc); switch( dib_hdr->biBitCount ) { case 8: return 8; case 24: return 24; case 32: return 32; case 16: if( dib_hdr->biCompression == BI_BITFIELDS ) { /* check the red mask */ switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) { case 0xf800: return 16; /* 565 */ case 0x7c00: return 15; /* 555 */ } } } return 0; /* poo. */#endif /* NO_GETDIBITS */}/* Various screen update functions available */static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags){ SDL_Surface *video; Uint32 prev_flags; DWORD style; const DWORD directstyle = (WS_POPUP); const DWORD windowstyle = (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX); const DWORD resizestyle = (WS_THICKFRAME|WS_MAXIMIZEBOX); int binfo_size; BITMAPINFO *binfo; HDC hdc; RECT bounds; int x, y; BOOL was_visible; Uint32 Rmask, Gmask, Bmask; /* See whether or not we should center the window */ was_visible = IsWindowVisible(SDL_Window); /* Clean up any GL context that may be hanging around */ if ( current->flags & SDL_OPENGL ) { WIN_GL_ShutDown(this); } /* Recalculate the bitmasks if necessary */ if ( bpp == current->format->BitsPerPixel ) { video = current; } else { switch (bpp) { case 15: case 16: if ( DIB_SussScreenDepth() == 15 ) { /* 5-5-5 */ Rmask = 0x00007c00; Gmask = 0x000003e0; Bmask = 0x0000001f; } else { /* 5-6-5 */ Rmask = 0x0000f800; Gmask = 0x000007e0; Bmask = 0x0000001f; } break; case 24: case 32: /* GDI defined as 8-8-8 */ Rmask = 0x00ff0000; Gmask = 0x0000ff00; Bmask = 0x000000ff; break; default: Rmask = 0x00000000; Gmask = 0x00000000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -