📄 sdl_dibvideo.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org*/#include "SDL_config.h"#define WIN32_LEAN_AND_MEAN#include <windows.h>/* Not yet in the mingw32 cross-compile headers */#ifndef CDS_FULLSCREEN#define CDS_FULLSCREEN 4#endif#include "SDL_syswm.h"#include "../SDL_sysvideo.h"#include "../SDL_pixels_c.h"#include "../../events/SDL_sysevents.h"#include "../../events/SDL_events_c.h"#include "SDL_dibvideo.h"#include "../wincommon/SDL_syswm_c.h"#include "../wincommon/SDL_sysmouse_c.h"#include "SDL_dibevents_c.h"#include "../wincommon/SDL_wingl_c.h"#ifdef _WIN32_WCE#define NO_GETDIBITS#define NO_GAMMA_SUPPORT #if _WIN32_WCE < 420 #define NO_CHANGEDISPLAYSETTINGS #else #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0) #endif#endif#ifndef WS_MAXIMIZE#define WS_MAXIMIZE 0#endif#ifndef WS_THICKFRAME#define WS_THICKFRAME 0#endif#ifndef SWP_NOCOPYBITS#define SWP_NOCOPYBITS 0#endif#ifndef PC_NOCOLLAPSE#define PC_NOCOLLAPSE 0#endif#ifdef _WIN32_WCE// defined and used in SDL_sysevents.cextern HINSTANCE aygshell;#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_GrabStaticColors(HWND window);static void DIB_ReleaseStaticColors(HWND window);static void DIB_Activate(_THIS, BOOL active, BOOL minimized);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 ) { SDL_free(device->hidden); } if ( device->gl_data ) { SDL_free(device->gl_data); } SDL_free(device); }}static SDL_VideoDevice *DIB_CreateDevice(int devindex){ SDL_VideoDevice *device; /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); if ( device ) { SDL_memset(device, 0, (sizeof *device)); device->hidden = (struct SDL_PrivateVideoData *) SDL_malloc((sizeof *device->hidden)); device->gl_data = (struct SDL_PrivateGLData *) SDL_malloc((sizeof *device->gl_data)); } if ( (device == NULL) || (device->hidden == NULL) || (device->gl_data == NULL) ) { SDL_OutOfMemory(); DIB_DeleteDevice(device); return(NULL); } SDL_memset(device->hidden, 0, (sizeof *device->hidden)); SDL_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;#if SDL_VIDEO_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_Activate = DIB_Activate; 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/CE GDI", DIB_Available, DIB_CreateDevice};static 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 b->h - a->h; else return b->w - a->w;}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 || bpp > 32 ) { /* 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 *)SDL_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 **) SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); if ( SDL_modelist[index] == NULL ) { SDL_OutOfMemory(); SDL_nummodes[index] = 0; SDL_free(mode); return(-1); } SDL_modelist[index][next_mode] = mode; SDL_modelist[index][next_mode+1] = NULL; SDL_nummodes[index]++; return(0);}static void DIB_CreatePalette(_THIS, int bpp){/* RJR: March 28, 2000 moved palette creation here from "DIB_VideoInit" */ LOGPALETTE *palette; HDC hdc; int ncolors; ncolors = (1 << bpp); palette = (LOGPALETTE *)SDL_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); screen_pal = CreatePalette(palette); screen_logpal = palette;}int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat){ const char *env = NULL;#ifndef NO_CHANGEDISPLAYSETTINGS int i; DEVMODE settings;#endif /* Create the window */ if ( DIB_CreateWindow(this) < 0 ) { return(-1); }#if !SDL_AUDIO_DISABLED 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 settings.dmSize = sizeof(DEVMODE); settings.dmDriverExtra = 0;#ifdef _WIN32_WCE settings.dmFields = DM_DISPLAYQUERYORIENTATION; this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL;#endif /* Query for the desktop resolution */ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode); this->info.current_w = SDL_desktop_mode.dmPelsWidth; this->info.current_h = SDL_desktop_mode.dmPelsHeight; /* 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);#ifdef _WIN32_WCE if( this->hidden->supportRotation ) DIB_AddMode(this, settings.dmBitsPerPel, settings.dmPelsHeight, settings.dmPelsWidth);#endif } /* Sort the mode lists */ for ( i=0; i<NUM_MODELISTS; ++i ) { if ( SDL_nummodes[i] > 0 ) { SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); } }#else // WinCE and fullscreen mode: // We use only vformat->BitsPerPixel that allow SDL to // emulate other bpp (8, 32) and use triple buffer, // because SDL surface conversion is much faster than the WinCE one. // Although it should be tested on devices with graphics accelerator. DIB_AddMode(this, vformat->BitsPerPixel, GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));#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" */ DIB_CreatePalette(this, vformat->BitsPerPixel); } /* Fill in some window manager capabilities */ this->info.wm_available = 1;#ifdef _WIN32_WCE this->hidden->origRotation = -1;#endif /* Allow environment override of screensaver disable. */ env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); this->hidden->allow_screensaver = ( (env && SDL_atoi(env)) ? 1 : 0 ); /* We're done! */ return(0);}/* We support any format at any dimension */SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags){ if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); } else { return((SDL_Rect **)-1); }}/* 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); return(depth);#else int depth; int dib_size; LPBITMAPINFOHEADER dib_hdr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -