Commit dc312617 authored by Sam Lantinga's avatar Sam Lantinga

The old windows video drivers are superceded by the unified win32 driver.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401989
parent bd9931af
/*
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"
#ifndef _SDL_lowvideo_h
#define _SDL_lowvideo_h
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifndef SetClassLongPtr
#define SetClassLongPtr SetClassLong
#endif
#ifndef GetWindowLongPtr
#define GetWindowLongPtr GetWindowLong
#endif
#ifndef SetWindowLongPtr
#define SetWindowLongPtr SetWindowLong
#endif
#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC GWL_WNDPROC
#endif
#ifndef GCLP_HICON
#define GCLP_HICON GCL_HICON
#endif
#include "../SDL_sysvideo.h"
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this
#define WINDIB_FULLSCREEN() \
( \
SDL_VideoSurface && \
(SDL_VideoSurface->flags & SDL_FULLSCREEN) && \
((SDL_VideoSurface->flags & SDL_INTERNALOPENGL) || \
((SDL_strcmp(this->name, "windib") == 0) || \
(SDL_strcmp(this->name, "gapi") == 0))) \
)
#define DDRAW_FULLSCREEN() \
( \
SDL_VideoSurface && \
(SDL_VideoSurface->flags & SDL_FULLSCREEN) && \
(SDL_VideoSurface->flags & SDL_INTERNALOPENGL) && \
(SDL_strcmp(this->name, "directx") == 0) \
)
#define DINPUT_FULLSCREEN() DDRAW_FULLSCREEN()
/* The main window -- and a function to set it for the audio */
#ifdef _WIN32_WCE
extern LPWSTR SDL_Appname;
#else
extern LPSTR SDL_Appname;
#endif
extern HINSTANCE SDL_Instance;
extern HWND SDL_Window;
extern BOOL SDL_windowid;
/* Variables and functions exported to other parts of the native video
subsystem (SDL_sysevents.c)
*/
extern void WIN_FlushMessageQueue();
/* Called by windows message loop when system palette is available */
extern void (*WIN_RealizePalette) (_THIS);
/* Called by windows message loop when the system palette changes */
extern void (*WIN_PaletteChanged) (_THIS, HWND window);
/* Called by windows message loop when a portion of the screen needs update */
extern void (*WIN_WinPAINT) (_THIS, HDC hdc);
/* Called by windows message loop when the message isn't handled */
extern LONG(*HandleMessage) (_THIS, HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam);
/* The window cursor (from SDL_sysmouse.c) */
extern HCURSOR SDL_hcursor;
/* The bounds of the window in screen coordinates */
extern RECT SDL_bounds;
/* The position of the window in windowed mode */
extern int SDL_windowX;
extern int SDL_windowY;
/* Flag -- SDL is performing a resize, rather than the user */
extern int SDL_resizing;
/* Flag -- the mouse is in relative motion mode */
extern int mouse_relative;
/* The GDI fullscreen mode currently active */
#ifndef NO_CHANGEDISPLAYSETTINGS
extern DEVMODE SDL_desktop_mode;
extern DEVMODE SDL_fullscreen_mode;
#endif
/* The system gamma ramp for GDI modes */
extern WORD *gamma_saved;
/* This is really from SDL_dx5audio.c */
extern void DX5_SoundFocus(HWND window);
/* DJM: This is really from SDL_sysevents.c, we need it in
GDL_CreateWindow as well */
LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam);
/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */
typedef int (WINAPI * ToUnicodeFN) (UINT, UINT, PBYTE, LPWSTR, int, UINT);
extern ToUnicodeFN SDL_ToUnicode;
#endif /* SDL_lowvideo_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
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>
#include "SDL_events.h"
#include "SDL_video.h"
#include "SDL_syswm.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "SDL_lowvideo.h"
#include "SDL_syswm_c.h"
#include "SDL_main.h"
#include "SDL_loadso.h"
#ifdef WMMSG_DEBUG
#include "wmmsg.h"
#endif
#ifdef _WIN32_WCE
#include "../gapi/SDL_gapivideo.h"
#define IsZoomed(HWND) 1
#define NO_GETKEYBOARDSTATE
#if _WIN32_WCE < 420
#define NO_CHANGEDISPLAYSETTINGS
#endif
#endif
/* The window we use for everything... */
#ifdef _WIN32_WCE
LPWSTR SDL_Appname = NULL;
#else
LPSTR SDL_Appname = NULL;
#endif
Uint32 SDL_Appstyle = 0;
HINSTANCE SDL_Instance = NULL;
HWND SDL_Window = NULL;
RECT SDL_bounds = { 0, 0, 0, 0 };
int SDL_windowX = 0;
int SDL_windowY = 0;
int SDL_resizing = 0;
int mouse_relative = 0;
int posted = 0;
#ifndef NO_CHANGEDISPLAYSETTINGS
DEVMODE SDL_desktop_mode;
DEVMODE SDL_fullscreen_mode;
#endif
WORD *gamma_saved = NULL;
/* Functions called by the message processing function */
LONG(*HandleMessage) (_THIS, HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) = NULL;
void (*WIN_RealizePalette) (_THIS);
void (*WIN_PaletteChanged) (_THIS, HWND window);
void (*WIN_WinPAINT) (_THIS, HDC hdc);
extern void DIB_SwapGamma(_THIS);
#ifndef NO_GETKEYBOARDSTATE
/* Variables and support functions for SDL_ToUnicode() */
static int codepage;
static int Is9xME();
static int GetCodePage();
static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, BYTE * keystate,
LPWSTR wchars, int wsize, UINT flags);
ToUnicodeFN SDL_ToUnicode = ToUnicode9xME;
#endif /* !NO_GETKEYBOARDSTATE */
#if defined(_WIN32_WCE)
// dynamically load aygshell dll because we want SDL to work on HPC and be300
HINSTANCE aygshell = NULL;
BOOL(WINAPI * SHFullScreen) (HWND hwndRequester, DWORD dwState) = 0;
#define SHFS_SHOWTASKBAR 0x0001
#define SHFS_HIDETASKBAR 0x0002
#define SHFS_SHOWSIPBUTTON 0x0004
#define SHFS_HIDESIPBUTTON 0x0008
#define SHFS_SHOWSTARTICON 0x0010
#define SHFS_HIDESTARTICON 0x0020
static void
LoadAygshell(void)
{
if (!aygshell)
aygshell = SDL_LoadObject("aygshell.dll");
if ((aygshell != 0) && (SHFullScreen == 0)) {
SHFullScreen = (int (WINAPI *) (struct HWND__ *, unsigned long))
SDL_LoadFunction(aygshell, "SHFullScreen");
}
}
/* for gapi landscape mode */
static void
GapiTransform(SDL_ScreenOrientation rotate, char hires, Sint16 * x,
Sint16 * y)
{
Sint16 rotatedX;
Sint16 rotatedY;
if (hires) {
*x = *x * 2;
*y = *y * 2;
}
switch (rotate) {
case SDL_ORIENTATION_UP:
{
/* this code needs testing on a real device!
So it will be enabled later */
/*
#ifdef _WIN32_WCE
#if _WIN32_WCE >= 420
// test device orientation
// FIXME: do not check every mouse message
DEVMODE settings;
SDL_memset(&settings, 0, sizeof(DEVMODE));
settings.dmSize = sizeof(DEVMODE);
settings.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
if( settings.dmOrientation == DMDO_90 )
{
rotatedX = SDL_VideoSurface->h - *x;
rotatedY = *y;
*x = rotatedX;
*y = rotatedY;
}
#endif
#endif */
}
break;
case SDL_ORIENTATION_RIGHT:
if (!SDL_VideoSurface)
break;
rotatedX = SDL_VideoSurface->w - *y;
rotatedY = *x;
*x = rotatedX;
*y = rotatedY;
break;
case SDL_ORIENTATION_LEFT:
if (!SDL_VideoSurface)
break;
rotatedX = *y;
rotatedY = SDL_VideoSurface->h - *x;
*x = rotatedX;
*y = rotatedY;
break;
}
}
#endif
/* JC 14 Mar 2006
This is used all over the place, in the windib driver and in the dx5 driver
So we may as well stick it here instead of having multiple copies scattered
about
*/
void
WIN_FlushMessageQueue()
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static void
SDL_RestoreGameMode(void)
{
#ifdef _WIN32_WCE
SDL_VideoDevice *this = current_video;
if (SDL_strcmp(this->name, "gapi") == 0) {
if (this->hidden->suspended) {
this->hidden->suspended = 0;
}
}
#else
ShowWindow(SDL_Window, SW_RESTORE);
#endif
#ifndef NO_CHANGEDISPLAYSETTINGS
#ifndef _WIN32_WCE
ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN);
#endif
#endif /* NO_CHANGEDISPLAYSETTINGS */
}
static void
SDL_RestoreDesktopMode(void)
{
#ifdef _WIN32_WCE
SDL_VideoDevice *this = current_video;
if (SDL_strcmp(this->name, "gapi") == 0) {
if (!this->hidden->suspended) {
this->hidden->suspended = 1;
}
}
#else
/* WinCE does not have a taskbar, so minimizing is not convenient */
ShowWindow(SDL_Window, SW_MINIMIZE);
#endif
#ifndef NO_CHANGEDISPLAYSETTINGS
#ifndef _WIN32_WCE
ChangeDisplaySettings(NULL, 0);
#endif
#endif /* NO_CHANGEDISPLAYSETTINGS */
}
#ifdef WM_MOUSELEAVE
/*
Special code to handle mouse leave events - this sucks...
http://support.microsoft.com/support/kb/articles/q183/1/07.asp
TrackMouseEvent() is only available on Win98 and WinNT.
_TrackMouseEvent() is available on Win95, but isn't yet in the mingw32
development environment, and only works on systems that have had IE 3.0
or newer installed on them (which is not the case with the base Win95).
Therefore, we implement our own version of _TrackMouseEvent() which
uses our own implementation if TrackMouseEvent() is not available.
*/
static BOOL(WINAPI * _TrackMouseEvent) (TRACKMOUSEEVENT * ptme) = NULL;
static VOID CALLBACK
TrackMouseTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
RECT rect;
POINT pt;
GetClientRect(hWnd, &rect);
MapWindowPoints(hWnd, NULL, (LPPOINT) & rect, 2);
GetCursorPos(&pt);
if (!PtInRect(&rect, pt) || (WindowFromPoint(pt) != hWnd)) {
if (!KillTimer(hWnd, idEvent)) {
/* Error killing the timer! */
}
PostMessage(hWnd, WM_MOUSELEAVE, 0, 0);
}
}
static BOOL WINAPI
WIN_TrackMouseEvent(TRACKMOUSEEVENT * ptme)
{
if (ptme->dwFlags == TME_LEAVE) {
return SetTimer(ptme->hwndTrack, ptme->dwFlags, 100,
(TIMERPROC) TrackMouseTimerProc) != 0;
}
return FALSE;
}
#endif /* WM_MOUSELEAVE */
/* Function to retrieve the current keyboard modifiers */
static void
WIN_GetKeyboardState(void)
{
#ifndef NO_GETKEYBOARDSTATE
SDLMod state;
BYTE keyboard[256];
Uint8 *kstate = SDL_GetKeyState(NULL);
state = KMOD_NONE;
if (GetKeyboardState(keyboard)) {
if (keyboard[VK_LSHIFT] & 0x80) {
state |= KMOD_LSHIFT;
kstate[SDLK_LSHIFT] = SDL_PRESSED;
}
if (keyboard[VK_RSHIFT] & 0x80) {
state |= KMOD_RSHIFT;
kstate[SDLK_RSHIFT] = SDL_PRESSED;
}
if (keyboard[VK_LCONTROL] & 0x80) {
state |= KMOD_LCTRL;
kstate[SDLK_LCTRL] = SDL_PRESSED;
}
if (keyboard[VK_RCONTROL] & 0x80) {
state |= KMOD_RCTRL;
kstate[SDLK_RCTRL] = SDL_PRESSED;
}
if (keyboard[VK_LMENU] & 0x80) {
state |= KMOD_LALT;
kstate[SDLK_LALT] = SDL_PRESSED;
}
if (keyboard[VK_RMENU] & 0x80) {
state |= KMOD_RALT;
kstate[SDLK_RALT] = SDL_PRESSED;
}
if (keyboard[VK_NUMLOCK] & 0x01) {
state |= KMOD_NUM;
kstate[SDLK_NUMLOCK] = SDL_PRESSED;
}
if (keyboard[VK_CAPITAL] & 0x01) {
state |= KMOD_CAPS;
kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
}
}
SDL_SetModState(state);
#endif /* !NO_GETKEYBOARDSTATE */
}
/* The main Win32 event handler
DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it
*/
LRESULT CALLBACK
WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
SDL_VideoDevice *this = current_video;
static int mouse_pressed = 0;
static int in_window = 0;
#ifdef WMMSG_DEBUG
fprintf(stderr, "Received windows message: ");
if (msg > MAX_WMMSG) {
fprintf(stderr, "%d", msg);
} else {
fprintf(stderr, "%s", wmtab[msg]);
}
fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam);
#endif
switch (msg) {
case WM_ACTIVATE:
{
SDL_VideoDevice *this = current_video;
BOOL minimized;
Uint8 appstate;
minimized = HIWORD(wParam);
if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
/* Gain the following states */
appstate = SDL_APPACTIVE | SDL_APPINPUTFOCUS;
if (this->input_grab != SDL_GRAB_OFF) {
WIN_GrabInput(this, SDL_GRAB_ON);
}
if (!(SDL_GetAppState() & SDL_APPINPUTFOCUS)) {
if (!DDRAW_FULLSCREEN()) {
DIB_SwapGamma(this);
}
if (WINDIB_FULLSCREEN()) {
SDL_RestoreGameMode();
}
}
#if defined(_WIN32_WCE)
if (WINDIB_FULLSCREEN()) {
LoadAygshell();
if (SHFullScreen)
SHFullScreen(SDL_Window,
SHFS_HIDESTARTICON |
SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);
else
ShowWindow(FindWindow
(TEXT("HHTaskBar"), NULL), SW_HIDE);
}
#endif
posted = SDL_PrivateAppActive(1, appstate);
WIN_GetKeyboardState();
} else {
/* Lose the following states */
appstate = SDL_APPINPUTFOCUS;
if (minimized) {
appstate |= SDL_APPACTIVE;
}
if (this->input_grab != SDL_GRAB_OFF) {
WIN_GrabInput(this, SDL_GRAB_OFF);
}
if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
if (!DDRAW_FULLSCREEN()) {
DIB_SwapGamma(this);
}
if (WINDIB_FULLSCREEN()) {
SDL_RestoreDesktopMode();
#if defined(_WIN32_WCE)
LoadAygshell();
if (SHFullScreen)
SHFullScreen(SDL_Window,
SHFS_SHOWSTARTICON |
SHFS_SHOWTASKBAR |
SHFS_SHOWSIPBUTTON);
else
ShowWindow(FindWindow
(TEXT("HHTaskBar"), NULL), SW_SHOW);
#endif
}
}
posted = SDL_PrivateAppActive(0, appstate);
}
return (0);
}
break;
case WM_MOUSEMOVE:
{
/* Mouse is handled by DirectInput when fullscreen */
if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) {
Sint16 x, y;
/* mouse has entered the window */
if (!in_window) {
#ifdef WM_MOUSELEAVE
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = SDL_Window;
_TrackMouseEvent(&tme);
#endif /* WM_MOUSELEAVE */
in_window = TRUE;
posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
}
/* mouse has moved within the window */
x = LOWORD(lParam);
y = HIWORD(lParam);
if (mouse_relative) {
POINT center;
center.x = (SDL_VideoSurface->w / 2);
center.y = (SDL_VideoSurface->h / 2);
x -= (Sint16) center.x;
y -= (Sint16) center.y;
if (x || y) {
ClientToScreen(SDL_Window, &center);
SetCursorPos(center.x, center.y);
posted = SDL_PrivateMouseMotion(0, 1, x, y);
}
} else {
#ifdef _WIN32_WCE
if (SDL_VideoSurface)
GapiTransform(this->hidden->userOrientation,
this->hidden->hiresFix, &x, &y);
#endif
posted = SDL_PrivateMouseMotion(0, 0, x, y);
}
}
}
return (0);
#ifdef WM_MOUSELEAVE
case WM_MOUSELEAVE:
{
/* Mouse is handled by DirectInput when fullscreen */
if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) {
/* mouse has left the window */
/* or */
/* Elvis has left the building! */
posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
}
in_window = FALSE;
}
return (0);
#endif /* WM_MOUSELEAVE */
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
{
/* Mouse is handled by DirectInput when fullscreen */
if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) {
Sint16 x, y;
Uint8 button, state;
/* DJM:
We want the SDL window to take focus so that
it acts like a normal windows "component"
(e.g. gains keyboard focus on a mouse click).
*/
SetFocus(SDL_Window);
/* Figure out which button to use */
switch (msg) {
case WM_LBUTTONDOWN:
button = SDL_BUTTON_LEFT;
state = SDL_PRESSED;
break;
case WM_LBUTTONUP:
button = SDL_BUTTON_LEFT;
state = SDL_RELEASED;
break;
case WM_MBUTTONDOWN:
button = SDL_BUTTON_MIDDLE;
state = SDL_PRESSED;
break;
case WM_MBUTTONUP:
button = SDL_BUTTON_MIDDLE;
state = SDL_RELEASED;
break;
case WM_RBUTTONDOWN:
button = SDL_BUTTON_RIGHT;
state = SDL_PRESSED;
break;
case WM_RBUTTONUP:
button = SDL_BUTTON_RIGHT;
state = SDL_RELEASED;
break;
default:
/* Eh? Unknown button? */
return (0);
}
if (state == SDL_PRESSED) {
/* Grab mouse so we get up events */
if (++mouse_pressed > 0) {
SetCapture(hwnd);
}
} else {
/* Release mouse after all up events */
if (--mouse_pressed <= 0) {
ReleaseCapture();
mouse_pressed = 0;
}
}
if (mouse_relative) {
/* RJR: March 28, 2000
report internal mouse position if in relative mode */
x = 0;
y = 0;
} else {
x = (Sint16) LOWORD(lParam);
y = (Sint16) HIWORD(lParam);
#ifdef _WIN32_WCE
if (SDL_VideoSurface)
GapiTransform(this->hidden->userOrientation,
this->hidden->hiresFix, &x, &y);
#endif
}
posted = SDL_PrivateMouseButton(state, button, x, y);
}
}
return (0);
#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
case WM_MOUSEWHEEL:
if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) {
int move = (short) HIWORD(wParam);
if (move) {
Uint8 button;
if (move > 0)
button = SDL_BUTTON_WHEELUP;
else
button = SDL_BUTTON_WHEELDOWN;
posted = SDL_PrivateMouseButton(SDL_PRESSED, button, 0, 0);
posted |= SDL_PrivateMouseButton(SDL_RELEASED, button, 0, 0);
}
}
return (0);
#endif
#ifdef WM_GETMINMAXINFO
/* This message is sent as a way for us to "check" the values
* of a position change. If we don't like it, we can adjust
* the values before they are changed.
*/
case WM_GETMINMAXINFO:
{
MINMAXINFO *info;
RECT size;
int x, y;
int style;
int width;
int height;
/* We don't want to clobber an internal resize */
if (SDL_resizing)
return (0);
/* We allow resizing with the SDL_RESIZABLE flag */
if (SDL_PublicSurface &&
(SDL_PublicSurface->flags & SDL_RESIZABLE)) {
return (0);
}
/* Get the current position of our window */
GetWindowRect(SDL_Window, &size);
x = size.left;
y = size.top;
/* Calculate current width and height of our window */
size.top = 0;
size.left = 0;
if (SDL_PublicSurface != NULL) {
size.bottom = SDL_PublicSurface->h;
size.right = SDL_PublicSurface->w;
} else {
size.bottom = 0;
size.right = 0;
}
/* DJM - according to the docs for GetMenu(), the
return value is undefined if hwnd is a child window.
Aparently it's too difficult for MS to check
inside their function, so I have to do it here.
*/
style = GetWindowLong(hwnd, GWL_STYLE);
AdjustWindowRect(&size,
style,
style & WS_CHILDWINDOW ? FALSE
: GetMenu(hwnd) != NULL);
width = size.right - size.left;
height = size.bottom - size.top;
/* Fix our size to the current size */
info = (MINMAXINFO *) lParam;
info->ptMaxSize.x = width;
info->ptMaxSize.y = height;
info->ptMaxPosition.x = x;
info->ptMaxPosition.y = y;
info->ptMinTrackSize.x = width;
info->ptMinTrackSize.y = height;
info->ptMaxTrackSize.x = width;
info->ptMaxTrackSize.y = height;
}
return (0);
#endif /* WM_GETMINMAXINFO */
case WM_WINDOWPOSCHANGED:
{
SDL_VideoDevice *this = current_video;
int w, h;
GetClientRect(SDL_Window, &SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds + 1);
if (!SDL_resizing && !IsZoomed(SDL_Window) &&
SDL_PublicSurface &&
!(SDL_PublicSurface->flags & SDL_FULLSCREEN)) {
SDL_windowX = SDL_bounds.left;
SDL_windowY = SDL_bounds.top;
}
w = SDL_bounds.right - SDL_bounds.left;
h = SDL_bounds.bottom - SDL_bounds.top;
if (this->input_grab != SDL_GRAB_OFF) {
ClipCursor(&SDL_bounds);
}
if (SDL_PublicSurface &&
(SDL_PublicSurface->flags & SDL_RESIZABLE)) {
SDL_PrivateResize(w, h);
}
}
break;
/* We need to set the cursor */
case WM_SETCURSOR:
{
Uint16 hittest;
hittest = LOWORD(lParam);
if (hittest == HTCLIENT) {
SetCursor(SDL_hcursor);
return (TRUE);
}
}
break;
/* We are about to get palette focus! */
case WM_QUERYNEWPALETTE:
{
WIN_RealizePalette(current_video);
return (TRUE);
}
break;
/* Another application changed the palette */
case WM_PALETTECHANGED:
{
WIN_PaletteChanged(current_video, (HWND) wParam);
}
break;
/* We were occluded, refresh our display */
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(SDL_Window, &ps);
if (current_video->screen &&
!(current_video->screen->flags & SDL_INTERNALOPENGL)) {
WIN_WinPAINT(current_video, hdc);
}
EndPaint(SDL_Window, &ps);
}
return (0);
/* DJM: Send an expose event in this case */
case WM_ERASEBKGND:
{
posted = SDL_PrivateExpose();
}
return (0);
case WM_CLOSE:
{
if ((posted = SDL_PrivateQuit()))
PostQuitMessage(0);
}
return (0);
case WM_DESTROY:
{
PostQuitMessage(0);
}
return (0);
#ifndef NO_GETKEYBOARDSTATE
case WM_INPUTLANGCHANGE:
{
codepage = GetCodePage();
}
return (TRUE);
#endif
default:
{
/* Special handling by the video driver */
if (HandleMessage) {
return (HandleMessage(current_video,
hwnd, msg, wParam, lParam));
}
}
break;
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
/* Allow the application handle to be stored and retrieved later */
static void *SDL_handle = NULL;
void
SDL_SetModuleHandle(void *handle)
{
SDL_handle = handle;
}
void *
SDL_GetModuleHandle(void)
{
void *handle;
if (SDL_handle) {
handle = SDL_handle;
} else {
handle = GetModuleHandle(NULL);
}
return (handle);
}
/* This allows the SDL_WINDOWID hack */
BOOL SDL_windowid = FALSE;
static int app_registered = 0;
/* Register the class for this application -- exported for winmain.c */
int
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
{
WNDCLASS class;
#ifdef WM_MOUSELEAVE
HMODULE handle;
#endif
/* Only do this once... */
if (app_registered) {
++app_registered;
return (0);
}
#ifndef CS_BYTEALIGNCLIENT
#define CS_BYTEALIGNCLIENT 0
#endif
if (!name && !SDL_Appname) {
name = "SDL_app";
SDL_Appstyle = CS_BYTEALIGNCLIENT;
SDL_Instance = hInst ? hInst : SDL_GetModuleHandle();
}
if (name) {
#ifdef _WIN32_WCE
/* WinCE uses the UNICODE version */
SDL_Appname = SDL_iconv_utf8_ucs2(name);
#else
SDL_Appname = SDL_iconv_utf8_latin1(name);
#endif /* _WIN32_WCE */
SDL_Appstyle = style;
SDL_Instance = hInst ? hInst : SDL_GetModuleHandle();
}
/* Register the application class */
class.hCursor = NULL;
class.hIcon = LoadImage(SDL_Instance, SDL_Appname,
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
class.lpszMenuName = NULL;
class.lpszClassName = SDL_Appname;
class.hbrBackground = NULL;
class.hInstance = SDL_Instance;
class.style = SDL_Appstyle;
#if SDL_VIDEO_OPENGL
class.style |= CS_OWNDC;
#endif
class.lpfnWndProc = WinMessage;
class.cbWndExtra = 0;
class.cbClsExtra = 0;
if (!RegisterClass(&class)) {
SDL_SetError("Couldn't register application class");
return (-1);
}
#ifdef WM_MOUSELEAVE
/* Get the version of TrackMouseEvent() we use */
_TrackMouseEvent = NULL;
handle = GetModuleHandle("USER32.DLL");
if (handle) {
_TrackMouseEvent =
(BOOL(WINAPI *) (TRACKMOUSEEVENT *)) GetProcAddress(handle,
"TrackMouseEvent");
}
if (_TrackMouseEvent == NULL) {
_TrackMouseEvent = WIN_TrackMouseEvent;
}
#endif /* WM_MOUSELEAVE */
#ifndef NO_GETKEYBOARDSTATE
/* Initialise variables for SDL_ToUnicode() */
codepage = GetCodePage();
SDL_ToUnicode = Is9xME()? ToUnicode9xME : ToUnicode;
#endif
app_registered = 1;
return (0);
}
/* Unregisters the windowclass registered in SDL_RegisterApp above. */
void
SDL_UnregisterApp()
{
WNDCLASS class;
/* SDL_RegisterApp might not have been called before */
if (!app_registered) {
return;
}
--app_registered;
if (app_registered == 0) {
/* Check for any registered window classes. */
if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
UnregisterClass(SDL_Appname, SDL_Instance);
}
SDL_free(SDL_Appname);
SDL_Appname = NULL;
}
}
#ifndef NO_GETKEYBOARDSTATE
/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */
static int
Is9xME()
{
OSVERSIONINFO info;
SDL_memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof(info);
if (!GetVersionEx(&info)) {
return 0;
}
return (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
}
static int
GetCodePage()
{
char buff[8];
int lcid = MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT);
int cp = GetACP();
if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buff, sizeof(buff))) {
cp = SDL_atoi(buff);
}
return cp;
}
static int WINAPI
ToUnicode9xME(UINT vkey, UINT scancode, PBYTE keystate, LPWSTR wchars,
int wsize, UINT flags)
{
BYTE chars[2];
if (ToAsciiEx
(vkey, scancode, keystate, (WORD *) chars, 0,
GetKeyboardLayout(0)) == 1) {
return MultiByteToWideChar(codepage, 0, chars, 1, wchars, wsize);
}
return 0;
}
#endif /* !NO_GETKEYBOARDSTATE */
/* vi: set ts=4 sw=4 expandtab: */
/*
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>
#include "SDL_mouse.h"
#include "../../events/SDL_events_c.h"
#include "../SDL_cursor_c.h"
#include "SDL_sysmouse_c.h"
#include "SDL_lowvideo.h"
#ifdef _WIN32_WCE
#define USE_STATIC_CURSOR
#endif
HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */
/* The implementation dependent data for the window manager cursor */
/* For some reason when creating a windows cursor, the ands and xors memory
is not copied, so we need to keep track of it and free it when we are done
with the cursor. If we free the memory prematurely, the app crashes. :-}
*/
struct WMcursor
{
HCURSOR curs;
#ifndef USE_STATIC_CURSOR
Uint8 *ands;
Uint8 *xors;
#endif
};
/* Convert bits to padded bytes */
#define PAD_BITS(bits) ((bits+7)/8)
#ifdef CURSOR_DEBUG
static void
PrintBITMAP(FILE * out, char *bits, int w, int h)
{
int i;
unsigned char ch;
while (h-- > 0) {
for (i = 0; i < w; ++i) {
if ((i % 8) == 0)
ch = *bits++;
if (ch & 0x80)
fprintf(out, "X");
else
fprintf(out, " ");
ch <<= 1;
}
fprintf(out, "\n");
}
}
#endif
#ifndef USE_STATIC_CURSOR
/* Local functions to convert the SDL cursor mask into Windows format */
static void
memnot(Uint8 * dst, Uint8 * src, int len)
{
while (len-- > 0)
*dst++ = ~*src++;
}
static void
memxor(Uint8 * dst, Uint8 * src1, Uint8 * src2, int len)
{
while (len-- > 0)
*dst++ = (*src1++) ^ (*src2++);
}
#endif /* !USE_STATIC_CURSOR */
void
WIN_FreeWMCursor(_THIS, WMcursor * cursor)
{
#ifndef USE_STATIC_CURSOR
if (cursor->curs == GetCursor())
SetCursor(NULL);
if (cursor->curs != NULL)
DestroyCursor(cursor->curs);
if (cursor->ands != NULL)
SDL_free(cursor->ands);
if (cursor->xors != NULL)
SDL_free(cursor->xors);
#endif /* !USE_STATIC_CURSOR */
SDL_free(cursor);
}
WMcursor *
WIN_CreateWMCursor(_THIS,
Uint8 * data, Uint8 * mask, int w, int h, int hot_x,
int hot_y)
{
#ifdef USE_STATIC_CURSOR
WMcursor *cursor;
/* Allocate the cursor */
cursor = (WMcursor *) SDL_malloc(sizeof(*cursor));
if (cursor) {
cursor->curs = LoadCursor(NULL, IDC_ARROW);
}
return (cursor);
#else
WMcursor *cursor;
int allowed_x;
int allowed_y;
int run, pad, i;
Uint8 *aptr, *xptr;
/* Check to make sure the cursor size is okay */
allowed_x = GetSystemMetrics(SM_CXCURSOR);
allowed_y = GetSystemMetrics(SM_CYCURSOR);
if ((w > allowed_x) || (h > allowed_y)) {
SDL_SetError("Only cursors of dimension (%dx%d) are allowed",
allowed_x, allowed_y);
return (NULL);
}
/* Allocate the cursor */
cursor = (WMcursor *) SDL_malloc(sizeof(*cursor));
if (cursor == NULL) {
SDL_SetError("Out of memory");
return (NULL);
}
cursor->curs = NULL;
cursor->ands = NULL;
cursor->xors = NULL;
/* Pad out to the normal cursor size */
run = PAD_BITS(w);
pad = PAD_BITS(allowed_x) - run;
aptr = cursor->ands = (Uint8 *) SDL_malloc((run + pad) * allowed_y);
xptr = cursor->xors = (Uint8 *) SDL_malloc((run + pad) * allowed_y);
if ((aptr == NULL) || (xptr == NULL)) {
WIN_FreeWMCursor(NULL, cursor);
SDL_OutOfMemory();
return (NULL);
}
for (i = 0; i < h; ++i) {
memxor(xptr, data, mask, run);
xptr += run;
data += run;
memnot(aptr, mask, run);
mask += run;
aptr += run;
SDL_memset(xptr, 0, pad);
xptr += pad;
SDL_memset(aptr, ~0, pad);
aptr += pad;
}
pad += run;
for (; i < allowed_y; ++i) {
SDL_memset(xptr, 0, pad);
xptr += pad;
SDL_memset(aptr, ~0, pad);
aptr += pad;
}
/* Create the cursor */
cursor->curs = CreateCursor((HINSTANCE)
GetWindowLongPtr(SDL_Window,
GWLP_HINSTANCE), hot_x,
hot_y, allowed_x, allowed_y, cursor->ands,
cursor->xors);
if (cursor->curs == NULL) {
WIN_FreeWMCursor(NULL, cursor);
SDL_SetError("Windows couldn't create the requested cursor");
return (NULL);
}
return (cursor);
#endif /* USE_STATIC_CURSOR */
}
int
WIN_ShowWMCursor(_THIS, WMcursor * cursor)
{
POINT mouse_pos;
/* The fullscreen cursor must be done in software with DirectInput */
if (!this->screen || DDRAW_FULLSCREEN()) {
return (0);
}
/* Set the window cursor to our cursor, if applicable */
if (cursor != NULL) {
SDL_hcursor = cursor->curs;
} else {
SDL_hcursor = NULL;
}
GetCursorPos(&mouse_pos);
if (PtInRect(&SDL_bounds, mouse_pos)) {
SetCursor(SDL_hcursor);
}
return (1);
}
void
WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
{
if (DDRAW_FULLSCREEN()) {
SDL_PrivateMouseMotion(0, 0, x, y);
} else if (mouse_relative) {
/* RJR: March 28, 2000
leave physical cursor at center of screen if
mouse hidden and grabbed */
SDL_PrivateMouseMotion(0, 0, x, y);
} else {
POINT pt;
pt.x = x;
pt.y = y;
ClientToScreen(SDL_Window, &pt);
SetCursorPos(pt.x, pt.y);
}
}
/* Update the current mouse state and position */
void
WIN_UpdateMouse(_THIS)
{
RECT rect;
POINT pt;
if (!DDRAW_FULLSCREEN()) {
GetClientRect(SDL_Window, &rect);
GetCursorPos(&pt);
MapWindowPoints(NULL, SDL_Window, &pt, 1);
if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)) {
SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
SDL_PrivateMouseMotion(0, 0, (Sint16) pt.x, (Sint16) pt.y);
} else {
SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
}
}
}
/* Check to see if we need to enter or leave mouse relative mode */
void
WIN_CheckMouseMode(_THIS)
{
#ifndef _WIN32_WCE
/* If the mouse is hidden and input is grabbed, we use relative mode */
if (!(SDL_cursorstate & CURSOR_VISIBLE) &&
(this->input_grab != SDL_GRAB_OFF)) {
mouse_relative = 1;
} else {
mouse_relative = 0;
}
#else
mouse_relative = 0;
#endif
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#include "SDL_lowvideo.h"
/* Functions to be exported */
extern void WIN_FreeWMCursor(_THIS, WMcursor * cursor);
extern WMcursor *WIN_CreateWMCursor(_THIS,
Uint8 * data, Uint8 * mask, int w, int h,
int hot_x, int hot_y);
extern int WIN_ShowWMCursor(_THIS, WMcursor * cursor);
extern void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y);
extern void WIN_UpdateMouse(_THIS);
extern void WIN_CheckMouseMode(_THIS);
/* vi: set ts=4 sw=4 expandtab: */
/*
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>
#include "SDL_version.h"
#include "SDL_video.h"
#include "SDL_loadso.h"
#include "SDL_syswm.h"
#include "../SDL_pixels_c.h"
#include "../SDL_cursor_c.h"
#include "SDL_syswm_c.h"
#include "SDL_wingl_c.h"
#ifdef _WIN32_WCE
#define DISABLE_ICON_SUPPORT
#endif
/* The screen icon -- needs to be freed on SDL_VideoQuit() */
HICON screen_icn = NULL;
#ifdef _WIN32_WCE
BOOL(WINAPI * CoreCatchInput) (int flag) = NULL;
int input_catched = 0;
HINSTANCE coredll = NULL;
// the same API call that gx.dll does to catch the input
void
LoadInputCatchFunc()
{
coredll = SDL_LoadObject("coredll.dll");
if (coredll) {
CoreCatchInput =
(int (WINAPI *) (int)) GetProcAddress(coredll,
(const unsigned short *)
1453);
}
}
#endif
/* Win32 icon mask semantics are different from those of SDL:
SDL applies the mask to the icon and copies result to desktop.
Win32 applies the mask to the desktop and XORs the icon on.
This means that the SDL mask needs to be applied to the icon and
then inverted and passed to Win32.
*/
void
WIN_SetWMIcon(_THIS, SDL_Surface * icon, Uint8 * mask)
{
#ifdef DISABLE_ICON_SUPPORT
return;
#else
SDL_Palette *pal_256;
SDL_Surface *icon_256;
Uint8 *pdata, *pwin32;
Uint8 *mdata, *mwin32, m = 0;
int icon_len;
int icon_plen;
int icon_mlen;
int icon_pitch;
int mask_pitch;
SDL_Rect bounds;
int i, skip;
int row, col;
struct /* quasi-BMP format */ Win32Icon
{
Uint32 biSize;
Sint32 biWidth;
Sint32 biHeight;
Uint16 biPlanes;
Uint16 biBitCount;
Uint32 biCompression;
Uint32 biSizeImage;
Sint32 biXPelsPerMeter;
Sint32 biYPelsPerMeter;
Uint32 biClrUsed;
Uint32 biClrImportant;
struct /* RGBQUAD -- note it's BGR ordered */
{
Uint8 rgbBlue;
Uint8 rgbGreen;
Uint8 rgbRed;
Uint8 rgbReserved;
} biColors[256];
/* Pixels:
Uint8 pixels[]
*/
/* Mask:
Uint8 mask[]
*/
} *icon_win32;
/* Allocate the win32 bmp icon and set everything to zero */
icon_pitch = ((icon->w + 3) & ~3);
mask_pitch = ((icon->w + 7) / 8);
icon_plen = icon->h * icon_pitch;
icon_mlen = icon->h * mask_pitch;
icon_len = sizeof(*icon_win32) + icon_plen + icon_mlen;
icon_win32 = (struct Win32Icon *) SDL_stack_alloc(Uint8, icon_len);
if (icon_win32 == NULL) {
return;
}
SDL_memset(icon_win32, 0, icon_len);
/* Set the basic BMP parameters */
icon_win32->biSize = sizeof(*icon_win32) - sizeof(icon_win32->biColors);
icon_win32->biWidth = icon->w;
icon_win32->biHeight = icon->h * 2;
icon_win32->biPlanes = 1;
icon_win32->biBitCount = 8;
icon_win32->biSizeImage = icon_plen + icon_mlen;
/* Allocate a standard 256 color icon surface */
icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
icon_win32->biBitCount, 0, 0, 0, 0);
if (icon_256 == NULL) {
SDL_stack_free(icon_win32);
return;
}
pal_256 = icon_256->format->palette;
if (icon->format->palette &&
(icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)) {
Uint8 black;
SDL_memcpy(pal_256->colors, icon->format->palette->colors,
pal_256->ncolors * sizeof(SDL_Color));
/* Make sure that 0 is black! */
black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00);
pal_256->colors[black] = pal_256->colors[0];
pal_256->colors[0].r = 0x00;
pal_256->colors[0].g = 0x00;
pal_256->colors[0].b = 0x00;
} else {
SDL_DitherColors(pal_256->colors, icon_256->format->BitsPerPixel);
}
/* Now copy color data to the icon BMP */
for (i = 0; i < (1 << icon_win32->biBitCount); ++i) {
icon_win32->biColors[i].rgbRed = pal_256->colors[i].r;
icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g;
icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b;
}
/* Convert icon to a standard surface format. This may not always
be necessary, as Windows supports a variety of BMP formats, but
it greatly simplifies our code.
*/
bounds.x = 0;
bounds.y = 0;
bounds.w = icon->w;
bounds.h = icon->h;
if (SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0) {
SDL_stack_free(icon_win32);
SDL_FreeSurface(icon_256);
return;
}
/* Copy pixels upside-down to icon BMP, masked with the icon mask */
if (SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch)) {
SDL_stack_free(icon_win32);
SDL_FreeSurface(icon_256);
SDL_SetError("Warning: Unexpected icon_256 characteristics");
return;
}
pdata = (Uint8 *) icon_256->pixels;
mdata = mask;
pwin32 =
(Uint8 *) icon_win32 + sizeof(*icon_win32) + icon_plen - icon_pitch;
skip = icon_pitch - icon->w;
for (row = 0; row < icon->h; ++row) {
for (col = 0; col < icon->w; ++col) {
if ((col % 8) == 0) {
m = *mdata++;
}
if ((m & 0x80) != 0x00) {
*pwin32 = *pdata;
}
m <<= 1;
++pdata;
++pwin32;
}
pdata += skip;
pwin32 += skip;
pwin32 -= 2 * icon_pitch;
}
SDL_FreeSurface(icon_256);
/* Copy mask inverted and upside-down to icon BMP */
mdata = mask;
mwin32 = (Uint8 *) icon_win32
+ sizeof(*icon_win32) + icon_plen + icon_mlen - mask_pitch;
for (row = 0; row < icon->h; ++row) {
for (col = 0; col < mask_pitch; ++col) {
*mwin32++ = ~*mdata++;
}
mwin32 -= 2 * mask_pitch;
}
/* Finally, create the icon handle and set the window icon */
screen_icn = CreateIconFromResourceEx((Uint8 *) icon_win32, icon_len,
TRUE, 0x00030000, icon->w, icon->h,
LR_DEFAULTCOLOR);
if (screen_icn == NULL) {
SDL_SetError("Couldn't create Win32 icon handle");
} else {
SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR) screen_icn);
}
SDL_stack_free(icon_win32);
#endif /* DISABLE_ICON_SUPPORT */
}
void
WIN_SetWMCaption(_THIS, const char *title, const char *icon)
{
#ifdef _WIN32_WCE
/* WinCE uses the UNICODE version */
LPWSTR lpszW = SDL_iconv_utf8_ucs2((char *) title);
SetWindowText(SDL_Window, lpszW);
SDL_free(lpszW);
#else
char *lpsz = SDL_iconv_utf8_latin1((char *) title);
SetWindowText(SDL_Window, lpsz);
SDL_free(lpsz);
#endif
}
int
WIN_IconifyWindow(_THIS)
{
ShowWindow(SDL_Window, SW_MINIMIZE);
return (1);
}
SDL_GrabMode
WIN_GrabInput(_THIS, SDL_GrabMode mode)
{
if (mode == SDL_GRAB_OFF) {
ClipCursor(NULL);
if (!(SDL_cursorstate & CURSOR_VISIBLE)) {
/* RJR: March 28, 2000
must be leaving relative mode, move mouse from
center of window to where it belongs ... */
POINT pt;
int x, y;
SDL_GetMouseState(&x, &y);
pt.x = x;
pt.y = y;
ClientToScreen(SDL_Window, &pt);
SetCursorPos(pt.x, pt.y);
}
#ifdef _WIN32_WCE
if (input_catched) {
if (!CoreCatchInput)
LoadInputCatchFunc();
if (CoreCatchInput)
CoreCatchInput(0);
}
#endif
} else {
ClipCursor(&SDL_bounds);
if (!(SDL_cursorstate & CURSOR_VISIBLE)) {
/* RJR: March 28, 2000
must be entering relative mode, get ready by
moving mouse to center of window ... */
POINT pt;
pt.x = (SDL_VideoSurface->w / 2);
pt.y = (SDL_VideoSurface->h / 2);
ClientToScreen(SDL_Window, &pt);
SetCursorPos(pt.x, pt.y);
}
#ifdef _WIN32_WCE
if (!input_catched) {
if (!CoreCatchInput)
LoadInputCatchFunc();
if (CoreCatchInput)
CoreCatchInput(1);
}
#endif
}
return (mode);
}
/* If 'info' is the right version, this function fills it and returns 1.
Otherwise, in case of a version mismatch, it returns -1.
*/
int
WIN_GetWMInfo(_THIS, SDL_SysWMinfo * info)
{
if (info->version.major <= SDL_MAJOR_VERSION) {
info->window = SDL_Window;
if (SDL_VERSIONNUM(info->version.major,
info->version.minor,
info->version.patch) >= SDL_VERSIONNUM(1, 2, 5)) {
#if SDL_VIDEO_OPENGL
info->hglrc = GL_hrc;
#else
info->hglrc = NULL;
#endif
}
return (1);
} else {
SDL_SetError("Application not compiled with SDL %d.%d\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return (-1);
}
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#include "SDL_lowvideo.h"
/* Data that needs to be freed at SDL_SYS_VideoQuit() */
extern HICON screen_icn;
/* Functions to be exported */
extern void WIN_SetWMIcon(_THIS, SDL_Surface * icon, Uint8 * mask);
extern void WIN_SetWMCaption(_THIS, const char *title, const char *icon);
extern int WIN_IconifyWindow(_THIS);
extern SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode);
extern int WIN_GetWMInfo(_THIS, SDL_SysWMinfo * info);
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
/* WGL implementation of SDL OpenGL support */
#if SDL_VIDEO_OPENGL
#include "SDL_opengl.h"
#endif
#include "SDL_lowvideo.h"
#include "SDL_wingl_c.h"
#if SDL_VIDEO_OPENGL
#define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL"
#endif
/* If setting the HDC fails, we may need to recreate the window (MSDN) */
static int
WIN_GL_ResetWindow(_THIS)
{
int status = 0;
#ifndef _WIN32_WCE /* FIXME WinCE needs the UNICODE version of CreateWindow() */
/* This doesn't work with DirectX code (see CVS comments) */
/* If we were passed a window, then we can't create a new one */
if (!SDL_windowid && SDL_strcmp(this->name, "windib") == 0) {
/* Save the existing window attributes */
LONG style;
RECT rect = { 0, 0, 0, 0 };
style = GetWindowLong(SDL_Window, GWL_STYLE);
GetWindowRect(SDL_Window, &rect);
DestroyWindow(SDL_Window);
WIN_FlushMessageQueue();
SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
style,
rect.left, rect.top,
(rect.right - rect.left) + 1,
(rect.top - rect.bottom) + 1,
NULL, NULL, SDL_Instance, NULL);
WIN_FlushMessageQueue();
if (SDL_Window) {
this->SetCaption(this, this->wm_title, this->wm_icon);
} else {
SDL_SetError("Couldn't create window");
status = -1;
}
} else
#endif /* !_WIN32_WCE */
{
SDL_SetError("Unable to reset window for OpenGL context");
status = -1;
}
return (status);
}
#if SDL_VIDEO_OPENGL
static int
ExtensionSupported(const char *extension, const char *extensions)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = SDL_strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
if (!extensions)
return 0;
/* It takes a bit of care to be fool-proof about parsing the
* OpenGL extensions string. Don't be fooled by sub-strings,
* etc. */
start = extensions;
for (;;) {
where = SDL_strstr(start, extension);
if (!where)
break;
terminator = where + SDL_strlen(extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return 1;
start = terminator;
}
return 0;
}
static void
Init_WGL_ARB_extensions(_THIS)
{
HWND hwnd;
HDC hdc;
HGLRC hglrc;
int pformat;
const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
const char *extensions;
hwnd = CreateWindow(SDL_Appname, SDL_Appname, WS_POPUP | WS_DISABLED,
0, 0, 10, 10, NULL, NULL, SDL_Instance, NULL);
WIN_FlushMessageQueue();
hdc = GetDC(hwnd);
pformat = ChoosePixelFormat(hdc, &GL_pfd);
SetPixelFormat(hdc, pformat, &GL_pfd);
hglrc = this->gl_data->wglCreateContext(hdc);
if (hglrc) {
this->gl_data->wglMakeCurrent(hdc, hglrc);
}
wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB) {
extensions = wglGetExtensionsStringARB(hdc);
} else {
extensions = NULL;
}
this->gl_data->WGL_ARB_pixel_format = 0;
if (ExtensionSupported("WGL_ARB_pixel_format", extensions)) {
this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
(HDC, const int *,
const FLOAT *, UINT, int *,
UINT *))
this->gl_data->wglGetProcAddress("wglChoosePixelFormatARB");
this->gl_data->wglGetPixelFormatAttribivARB =
(BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB");
if ((this->gl_data->wglChoosePixelFormatARB != NULL) &&
(this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
this->gl_data->WGL_ARB_pixel_format = 1;
}
}
if (hglrc) {
this->gl_data->wglMakeCurrent(NULL, NULL);
this->gl_data->wglDeleteContext(hglrc);
}
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
WIN_FlushMessageQueue();
}
#endif /* SDL_VIDEO_OPENGL */
int
WIN_GL_SetupWindow(_THIS)
{
int retval;
#if SDL_VIDEO_OPENGL
int i;
unsigned int matching;
int iAttribs[64];
int *iAttr;
float fAttribs[1] = { 0 };
const GLubyte *(WINAPI * glGetStringFunc) (GLenum);
const char *wglext;
/* load the gl driver from a default path */
if (!this->gl_config.driver_loaded) {
/* no driver has been loaded, use default (ourselves) */
if (WIN_GL_LoadLibrary(this, NULL) < 0) {
return (-1);
}
}
for (i = 0;; ++i) {
/* Get the window device context for our OpenGL drawing */
GL_hdc = GetDC(SDL_Window);
if (GL_hdc == NULL) {
SDL_SetError("Unable to get DC for SDL_Window");
return (-1);
}
/* Set up the pixel format descriptor with our needed format */
SDL_memset(&GL_pfd, 0, sizeof(GL_pfd));
GL_pfd.nSize = sizeof(GL_pfd);
GL_pfd.nVersion = 1;
GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
if (this->gl_config.double_buffer) {
GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
}
if (this->gl_config.stereo) {
GL_pfd.dwFlags |= PFD_STEREO;
}
GL_pfd.iPixelType = PFD_TYPE_RGBA;
GL_pfd.cColorBits = this->gl_config.buffer_size;
GL_pfd.cRedBits = this->gl_config.red_size;
GL_pfd.cGreenBits = this->gl_config.green_size;
GL_pfd.cBlueBits = this->gl_config.blue_size;
GL_pfd.cAlphaBits = this->gl_config.alpha_size;
GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
GL_pfd.cAccumBits =
(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
GL_pfd.cDepthBits = this->gl_config.depth_size;
GL_pfd.cStencilBits = this->gl_config.stencil_size;
/* initialize WGL_ARB_pixel_format */
Init_WGL_ARB_extensions(this);
/* setup WGL_ARB_pixel_format attribs */
iAttr = &iAttribs[0];
*iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
*iAttr++ = GL_TRUE;
*iAttr++ = WGL_ACCELERATION_ARB;
*iAttr++ = WGL_FULL_ACCELERATION_ARB;
*iAttr++ = WGL_RED_BITS_ARB;
*iAttr++ = this->gl_config.red_size;
*iAttr++ = WGL_GREEN_BITS_ARB;
*iAttr++ = this->gl_config.green_size;
*iAttr++ = WGL_BLUE_BITS_ARB;
*iAttr++ = this->gl_config.blue_size;
if (this->gl_config.alpha_size) {
*iAttr++ = WGL_ALPHA_BITS_ARB;
*iAttr++ = this->gl_config.alpha_size;
}
*iAttr++ = WGL_DOUBLE_BUFFER_ARB;
*iAttr++ = this->gl_config.double_buffer;
*iAttr++ = WGL_DEPTH_BITS_ARB;
*iAttr++ = this->gl_config.depth_size;
if (this->gl_config.stencil_size) {
*iAttr++ = WGL_STENCIL_BITS_ARB;
*iAttr++ = this->gl_config.stencil_size;
}
if (this->gl_config.accum_red_size) {
*iAttr++ = WGL_ACCUM_RED_BITS_ARB;
*iAttr++ = this->gl_config.accum_red_size;
}
if (this->gl_config.accum_green_size) {
*iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
*iAttr++ = this->gl_config.accum_green_size;
}
if (this->gl_config.accum_blue_size) {
*iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
*iAttr++ = this->gl_config.accum_blue_size;
}
if (this->gl_config.accum_alpha_size) {
*iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
*iAttr++ = this->gl_config.accum_alpha_size;
}
if (this->gl_config.stereo) {
*iAttr++ = WGL_STEREO_ARB;
*iAttr++ = GL_TRUE;
}
if (this->gl_config.multisamplebuffers) {
*iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
*iAttr++ = this->gl_config.multisamplebuffers;
}
if (this->gl_config.multisamplesamples) {
*iAttr++ = WGL_SAMPLES_ARB;
*iAttr++ = this->gl_config.multisamplesamples;
}
if (this->gl_config.accelerated >= 0) {
*iAttr++ = WGL_ACCELERATION_ARB;
*iAttr++ =
(this->gl_config.
accelerated ? WGL_GENERIC_ACCELERATION_ARB :
WGL_NO_ACCELERATION_ARB);
}
*iAttr = 0;
/* Choose and set the closest available pixel format */
if (!this->gl_data->WGL_ARB_pixel_format ||
!this->gl_data->wglChoosePixelFormatARB(GL_hdc, iAttribs,
fAttribs, 1,
&pixel_format, &matching)
|| !matching) {
pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
this->gl_data->WGL_ARB_pixel_format = 0;
}
if (!pixel_format) {
SDL_SetError("No matching GL pixel format available");
return (-1);
}
if (!SetPixelFormat(GL_hdc, pixel_format, &GL_pfd)) {
if (i == 0) {
/* First time through, try resetting the window */
if (WIN_GL_ResetWindow(this) < 0) {
return (-1);
}
continue;
}
SDL_SetError("Unable to set HDC pixel format");
return (-1);
}
/* We either succeeded or failed by this point */
break;
}
DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
if (GL_hrc == NULL) {
SDL_SetError("Unable to create GL context");
return (-1);
}
if (WIN_GL_MakeCurrent(this) < 0) {
return (-1);
}
gl_active = 1;
/* Vsync control under Windows. Checking glGetString here is
* somewhat a documented and reliable hack - it was originally
* as a feature added by mistake, but since so many people rely
* on it, it will not be removed. strstr should be safe here.*/
glGetStringFunc = WIN_GL_GetProcAddress(this, "glGetString");
if (glGetStringFunc) {
wglext = (const char *) glGetStringFunc(GL_EXTENSIONS);
} else {
/* Uh oh, something is seriously wrong here... */
wglext = NULL;
}
if (wglext && SDL_strstr(wglext, "WGL_EXT_swap_control")) {
this->gl_data->wglSwapIntervalEXT =
WIN_GL_GetProcAddress(this, "wglSwapIntervalEXT");
this->gl_data->wglGetSwapIntervalEXT =
WIN_GL_GetProcAddress(this, "wglGetSwapIntervalEXT");
} else {
this->gl_data->wglSwapIntervalEXT = NULL;
this->gl_data->wglGetSwapIntervalEXT = NULL;
}
if (this->gl_config.swap_control >= 0) {
if (this->gl_data->wglSwapIntervalEXT) {
this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control);
}
}
#else
SDL_SetError("WIN driver not configured with OpenGL");
#endif
if (gl_active) {
retval = 0;
} else {
retval = -1;
}
return (retval);
}
void
WIN_GL_ShutDown(_THIS)
{
#if SDL_VIDEO_OPENGL
/* Clean up OpenGL */
if (GL_hrc) {
this->gl_data->wglMakeCurrent(NULL, NULL);
this->gl_data->wglDeleteContext(GL_hrc);
GL_hrc = NULL;
}
if (GL_hdc) {
ReleaseDC(SDL_Window, GL_hdc);
GL_hdc = NULL;
}
gl_active = 0;
WIN_GL_UnloadLibrary(this);
#endif /* SDL_VIDEO_OPENGL */
}
#if SDL_VIDEO_OPENGL
/* Make the current context active */
int
WIN_GL_MakeCurrent(_THIS)
{
int retval;
retval = 0;
if (!this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc)) {
SDL_SetError("Unable to make GL context current");
retval = -1;
}
return (retval);
}
/* Get attribute data from glX. */
int
WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int *value)
{
int retval;
if (this->gl_data->WGL_ARB_pixel_format) {
int wgl_attrib;
switch (attrib) {
case SDL_GL_RED_SIZE:
wgl_attrib = WGL_RED_BITS_ARB;
break;
case SDL_GL_GREEN_SIZE:
wgl_attrib = WGL_GREEN_BITS_ARB;
break;
case SDL_GL_BLUE_SIZE:
wgl_attrib = WGL_BLUE_BITS_ARB;
break;
case SDL_GL_ALPHA_SIZE:
wgl_attrib = WGL_ALPHA_BITS_ARB;
break;
case SDL_GL_DOUBLEBUFFER:
wgl_attrib = WGL_DOUBLE_BUFFER_ARB;
break;
case SDL_GL_BUFFER_SIZE:
wgl_attrib = WGL_COLOR_BITS_ARB;
break;
case SDL_GL_DEPTH_SIZE:
wgl_attrib = WGL_DEPTH_BITS_ARB;
break;
case SDL_GL_STENCIL_SIZE:
wgl_attrib = WGL_STENCIL_BITS_ARB;
break;
case SDL_GL_ACCUM_RED_SIZE:
wgl_attrib = WGL_ACCUM_RED_BITS_ARB;
break;
case SDL_GL_ACCUM_GREEN_SIZE:
wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB;
break;
case SDL_GL_ACCUM_BLUE_SIZE:
wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB;
break;
case SDL_GL_ACCUM_ALPHA_SIZE:
wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB;
break;
case SDL_GL_STEREO:
wgl_attrib = WGL_STEREO_ARB;
break;
case SDL_GL_MULTISAMPLEBUFFERS:
wgl_attrib = WGL_SAMPLE_BUFFERS_ARB;
break;
case SDL_GL_MULTISAMPLESAMPLES:
wgl_attrib = WGL_SAMPLES_ARB;
break;
case SDL_GL_ACCELERATED_VISUAL:
wgl_attrib = WGL_ACCELERATION_ARB;
this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format,
0, 1, &wgl_attrib,
value);
if (*value == WGL_NO_ACCELERATION_ARB) {
*value = SDL_FALSE;
} else {
*value = SDL_TRUE;
}
return 0;
break;
case SDL_GL_SWAP_CONTROL:
if (this->gl_data->wglGetSwapIntervalEXT) {
*value = this->gl_data->wglGetSwapIntervalEXT();
return 0;
} else {
return -1;
}
break;
default:
return (-1);
}
this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0,
1, &wgl_attrib, value);
return 0;
}
retval = 0;
switch (attrib) {
case SDL_GL_RED_SIZE:
*value = GL_pfd.cRedBits;
break;
case SDL_GL_GREEN_SIZE:
*value = GL_pfd.cGreenBits;
break;
case SDL_GL_BLUE_SIZE:
*value = GL_pfd.cBlueBits;
break;
case SDL_GL_ALPHA_SIZE:
*value = GL_pfd.cAlphaBits;
break;
case SDL_GL_DOUBLEBUFFER:
if (GL_pfd.dwFlags & PFD_DOUBLEBUFFER) {
*value = 1;
} else {
*value = 0;
}
break;
case SDL_GL_BUFFER_SIZE:
*value = GL_pfd.cColorBits;
break;
case SDL_GL_DEPTH_SIZE:
*value = GL_pfd.cDepthBits;
break;
case SDL_GL_STENCIL_SIZE:
*value = GL_pfd.cStencilBits;
break;
case SDL_GL_ACCUM_RED_SIZE:
*value = GL_pfd.cAccumRedBits;
break;
case SDL_GL_ACCUM_GREEN_SIZE:
*value = GL_pfd.cAccumGreenBits;
break;
case SDL_GL_ACCUM_BLUE_SIZE:
*value = GL_pfd.cAccumBlueBits;
break;
case SDL_GL_ACCUM_ALPHA_SIZE:
*value = GL_pfd.cAccumAlphaBits;
break;
case SDL_GL_STEREO:
if (GL_pfd.dwFlags & PFD_STEREO) {
*value = 1;
} else {
*value = 0;
}
break;
case SDL_GL_MULTISAMPLEBUFFERS:
*value = 0;
break;
case SDL_GL_MULTISAMPLESAMPLES:
*value = 1;
break;
case SDL_GL_SWAP_CONTROL:
if (this->gl_data->wglGetSwapIntervalEXT) {
*value = this->gl_data->wglGetSwapIntervalEXT();
return 0;
} else {
return -1;
}
break;
default:
retval = -1;
break;
}
return retval;
}
void
WIN_GL_SwapBuffers(_THIS)
{
SwapBuffers(GL_hdc);
}
void
WIN_GL_UnloadLibrary(_THIS)
{
if (this->gl_config.driver_loaded) {
FreeLibrary((HMODULE) this->gl_config.dll_handle);
this->gl_data->wglGetProcAddress = NULL;
this->gl_data->wglCreateContext = NULL;
this->gl_data->wglDeleteContext = NULL;
this->gl_data->wglMakeCurrent = NULL;
this->gl_data->wglChoosePixelFormatARB = NULL;
this->gl_data->wglGetPixelFormatAttribivARB = NULL;
this->gl_data->wglSwapIntervalEXT = NULL;
this->gl_data->wglGetSwapIntervalEXT = NULL;
this->gl_config.dll_handle = NULL;
this->gl_config.driver_loaded = 0;
}
}
/* Passing a NULL path means load pointers from the application */
int
WIN_GL_LoadLibrary(_THIS, const char *path)
{
HMODULE handle;
if (gl_active) {
SDL_SetError("OpenGL context already created");
return -1;
}
if (path == NULL) {
path = DEFAULT_GL_DRIVER_PATH;
}
handle = LoadLibrary(path);
if (handle == NULL) {
SDL_SetError("Could not load OpenGL library");
return -1;
}
/* Unload the old driver and reset the pointers */
WIN_GL_UnloadLibrary(this);
/* Load new function pointers */
SDL_memset(this->gl_data, 0, sizeof(*this->gl_data));
this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
GetProcAddress(handle, "wglGetProcAddress");
this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
GetProcAddress(handle, "wglCreateContext");
this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
GetProcAddress(handle, "wglDeleteContext");
this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
GetProcAddress(handle, "wglMakeCurrent");
this->gl_data->wglSwapIntervalEXT = (void (WINAPI *) (int))
GetProcAddress(handle, "wglSwapIntervalEXT");
this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *) (void))
GetProcAddress(handle, "wglGetSwapIntervalEXT");
if ((this->gl_data->wglGetProcAddress == NULL) ||
(this->gl_data->wglCreateContext == NULL) ||
(this->gl_data->wglDeleteContext == NULL) ||
(this->gl_data->wglMakeCurrent == NULL)) {
SDL_SetError("Could not retrieve OpenGL functions");
FreeLibrary(handle);
return -1;
}
this->gl_config.dll_handle = handle;
SDL_strlcpy(this->gl_config.driver_path, path,
SDL_arraysize(this->gl_config.driver_path));
this->gl_config.driver_loaded = 1;
return 0;
}
void *
WIN_GL_GetProcAddress(_THIS, const char *proc)
{
void *func;
/* This is to pick up extensions */
func = this->gl_data->wglGetProcAddress(proc);
if (!func) {
/* This is probably a normal GL function */
func = GetProcAddress(this->gl_config.dll_handle, proc);
}
return func;
}
#endif /* SDL_VIDEO_OPENGL */
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
/* WGL implementation of SDL OpenGL support */
#include "../SDL_sysvideo.h"
struct SDL_PrivateGLData
{
int gl_active; /* to stop switching drivers while we have a valid context */
#if SDL_VIDEO_OPENGL
PIXELFORMATDESCRIPTOR GL_pfd;
HDC GL_hdc;
HGLRC GL_hrc;
int pixel_format;
int WGL_ARB_pixel_format;
void *(WINAPI * wglGetProcAddress) (const char *proc);
HGLRC(WINAPI * wglCreateContext) (HDC hdc);
BOOL(WINAPI * wglDeleteContext) (HGLRC hglrc);
BOOL(WINAPI * wglMakeCurrent) (HDC hdc, HGLRC hglrc);
BOOL(WINAPI * wglChoosePixelFormatARB) (HDC hdc,
const int *piAttribIList,
const FLOAT * pfAttribFList,
UINT nMaxFormats,
int *piFormats,
UINT * nNumFormats);
BOOL(WINAPI * wglGetPixelFormatAttribivARB) (HDC hdc, int iPixelFormat,
int iLayerPlane,
UINT nAttributes,
const int *piAttributes,
int *piValues);
void (WINAPI * wglSwapIntervalEXT) (int interval);
int (WINAPI * wglGetSwapIntervalEXT) (void);
#endif /* SDL_VIDEO_OPENGL */
};
/* Old variable names */
#define gl_active (this->gl_data->gl_active)
#define GL_pfd (this->gl_data->GL_pfd)
#define GL_hdc (this->gl_data->GL_hdc)
#define GL_hrc (this->gl_data->GL_hrc)
#define pixel_format (this->gl_data->pixel_format)
/* OpenGL functions */
extern int WIN_GL_SetupWindow(_THIS);
extern void WIN_GL_ShutDown(_THIS);
#if SDL_VIDEO_OPENGL
extern int WIN_GL_MakeCurrent(_THIS);
extern int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int *value);
extern void WIN_GL_SwapBuffers(_THIS);
extern void WIN_GL_UnloadLibrary(_THIS);
extern int WIN_GL_LoadLibrary(_THIS, const char *path);
extern void *WIN_GL_GetProcAddress(_THIS, const char *proc);
#endif
#if SDL_VIDEO_OPENGL
#ifndef WGL_ARB_pixel_format
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NEED_PALETTE_ARB 0x2004
#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
#define WGL_SWAP_METHOD_ARB 0x2007
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
#define WGL_TRANSPARENT_ARB 0x200A
#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
#define WGL_SHARE_DEPTH_ARB 0x200C
#define WGL_SHARE_STENCIL_ARB 0x200D
#define WGL_SHARE_ACCUM_ARB 0x200E
#define WGL_SUPPORT_GDI_ARB 0x200F
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_STEREO_ARB 0x2012
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
#define WGL_RED_SHIFT_ARB 0x2016
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_GREEN_SHIFT_ARB 0x2018
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_BLUE_SHIFT_ARB 0x201A
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_ALPHA_SHIFT_ARB 0x201C
#define WGL_ACCUM_BITS_ARB 0x201D
#define WGL_ACCUM_RED_BITS_ARB 0x201E
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_AUX_BUFFERS_ARB 0x2024
#define WGL_NO_ACCELERATION_ARB 0x2025
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_SWAP_EXCHANGE_ARB 0x2028
#define WGL_SWAP_COPY_ARB 0x2029
#define WGL_SWAP_UNDEFINED_ARB 0x202A
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_TYPE_COLORINDEX_ARB 0x202C
#endif
#ifndef WGL_ARB_multisample
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#endif
#endif
/* vi: set ts=4 sw=4 expandtab: */
#define MAX_WMMSG (sizeof(wmtab)/sizeof(wmtab[0]))
char *wmtab[] = {
"WM_NULL",
"WM_CREATE",
"WM_DESTROY",
"WM_MOVE",
"UNKNOWN (4)",
"WM_SIZE",
"WM_ACTIVATE",
"WM_SETFOCUS",
"WM_KILLFOCUS",
"UNKNOWN (9)",
"WM_ENABLE",
"WM_SETREDRAW",
"WM_SETTEXT",
"WM_GETTEXT",
"WM_GETTEXTLENGTH",
"WM_PAINT",
"WM_CLOSE",
"WM_QUERYENDSESSION",
"WM_QUIT",
"WM_QUERYOPEN",
"WM_ERASEBKGND",
"WM_SYSCOLORCHANGE",
"WM_ENDSESSION",
"UNKNOWN (23)",
"WM_SHOWWINDOW",
"UNKNOWN (25)",
"WM_SETTINGCHANGE",
"WM_DEVMODECHANGE",
"WM_ACTIVATEAPP",
"WM_FONTCHANGE",
"WM_TIMECHANGE",
"WM_CANCELMODE",
"WM_SETCURSOR",
"WM_MOUSEACTIVATE",
"WM_CHILDACTIVATE",
"WM_QUEUESYNC",
"WM_GETMINMAXINFO",
"UNKNOWN (37)",
"WM_PAINTICON",
"WM_ICONERASEBKGND",
"WM_NEXTDLGCTL",
"UNKNOWN (41)",
"WM_SPOOLERSTATUS",
"WM_DRAWITEM",
"WM_MEASUREITEM",
"WM_DELETEITEM",
"WM_VKEYTOITEM",
"WM_CHARTOITEM",
"WM_SETFONT",
"WM_GETFONT",
"WM_SETHOTKEY",
"WM_GETHOTKEY",
"UNKNOWN (52)",
"UNKNOWN (53)",
"UNKNOWN (54)",
"WM_QUERYDRAGICON",
"UNKNOWN (56)",
"WM_COMPAREITEM",
"UNKNOWN (58)",
"UNKNOWN (59)",
"UNKNOWN (60)",
"WM_GETOBJECT",
"UNKNOWN (62)",
"UNKNOWN (63)",
"UNKNOWN (64)",
"WM_COMPACTING",
"UNKNOWN (66)",
"UNKNOWN (67)",
"WM_COMMNOTIFY",
"UNKNOWN (69)",
"WM_WINDOWPOSCHANGING",
"WM_WINDOWPOSCHANGED",
"WM_POWER",
"UNKNOWN (73)",
"WM_COPYDATA",
"WM_CANCELJOURNAL",
"UNKNOWN (76)",
"UNKNOWN (77)",
"WM_NOTIFY",
"UNKNOWN (79)",
"WM_INPUTLANGCHANGEREQUEST",
"WM_INPUTLANGCHANGE",
"WM_TCARD",
"WM_HELP",
"WM_USERCHANGED",
"WM_NOTIFYFORMAT",
"UNKNOWN (86)",
"UNKNOWN (87)",
"UNKNOWN (88)",
"UNKNOWN (89)",
"UNKNOWN (90)",
"UNKNOWN (91)",
"UNKNOWN (92)",
"UNKNOWN (93)",
"UNKNOWN (94)",
"UNKNOWN (95)",
"UNKNOWN (96)",
"UNKNOWN (97)",
"UNKNOWN (98)",
"UNKNOWN (99)",
"UNKNOWN (100)",
"UNKNOWN (101)",
"UNKNOWN (102)",
"UNKNOWN (103)",
"UNKNOWN (104)",
"UNKNOWN (105)",
"UNKNOWN (106)",
"UNKNOWN (107)",
"UNKNOWN (108)",
"UNKNOWN (109)",
"UNKNOWN (110)",
"UNKNOWN (111)",
"UNKNOWN (112)",
"UNKNOWN (113)",
"UNKNOWN (114)",
"UNKNOWN (115)",
"UNKNOWN (116)",
"UNKNOWN (117)",
"UNKNOWN (118)",
"UNKNOWN (119)",
"UNKNOWN (120)",
"UNKNOWN (121)",
"UNKNOWN (122)",
"WM_CONTEXTMENU",
"WM_STYLECHANGING",
"WM_STYLECHANGED",
"WM_DISPLAYCHANGE",
"WM_GETICON",
"WM_SETICON",
"WM_NCCREATE",
"WM_NCDESTROY",
"WM_NCCALCSIZE",
"WM_NCHITTEST",
"WM_NCPAINT",
"WM_NCACTIVATE",
"WM_GETDLGCODE",
"WM_SYNCPAINT",
"UNKNOWN (137)",
"UNKNOWN (138)",
"UNKNOWN (139)",
"UNKNOWN (140)",
"UNKNOWN (141)",
"UNKNOWN (142)",
"UNKNOWN (143)",
"UNKNOWN (144)",
"UNKNOWN (145)",
"UNKNOWN (146)",
"UNKNOWN (147)",
"UNKNOWN (148)",
"UNKNOWN (149)",
"UNKNOWN (150)",
"UNKNOWN (151)",
"UNKNOWN (152)",
"UNKNOWN (153)",
"UNKNOWN (154)",
"UNKNOWN (155)",
"UNKNOWN (156)",
"UNKNOWN (157)",
"UNKNOWN (158)",
"UNKNOWN (159)",
"WM_NCMOUSEMOVE",
"WM_NCLBUTTONDOWN",
"WM_NCLBUTTONUP",
"WM_NCLBUTTONDBLCLK",
"WM_NCRBUTTONDOWN",
"WM_NCRBUTTONUP",
"WM_NCRBUTTONDBLCLK",
"WM_NCMBUTTONDOWN",
"WM_NCMBUTTONUP",
"WM_NCMBUTTONDBLCLK",
"UNKNOWN (170)",
"UNKNOWN (171)",
"UNKNOWN (172)",
"UNKNOWN (173)",
"UNKNOWN (174)",
"UNKNOWN (175)",
"UNKNOWN (176)",
"UNKNOWN (177)",
"UNKNOWN (178)",
"UNKNOWN (179)",
"UNKNOWN (180)",
"UNKNOWN (181)",
"UNKNOWN (182)",
"UNKNOWN (183)",
"UNKNOWN (184)",
"UNKNOWN (185)",
"UNKNOWN (186)",
"UNKNOWN (187)",
"UNKNOWN (188)",
"UNKNOWN (189)",
"UNKNOWN (190)",
"UNKNOWN (191)",
"UNKNOWN (192)",
"UNKNOWN (193)",
"UNKNOWN (194)",
"UNKNOWN (195)",
"UNKNOWN (196)",
"UNKNOWN (197)",
"UNKNOWN (198)",
"UNKNOWN (199)",
"UNKNOWN (200)",
"UNKNOWN (201)",
"UNKNOWN (202)",
"UNKNOWN (203)",
"UNKNOWN (204)",
"UNKNOWN (205)",
"UNKNOWN (206)",
"UNKNOWN (207)",
"UNKNOWN (208)",
"UNKNOWN (209)",
"UNKNOWN (210)",
"UNKNOWN (211)",
"UNKNOWN (212)",
"UNKNOWN (213)",
"UNKNOWN (214)",
"UNKNOWN (215)",
"UNKNOWN (216)",
"UNKNOWN (217)",
"UNKNOWN (218)",
"UNKNOWN (219)",
"UNKNOWN (220)",
"UNKNOWN (221)",
"UNKNOWN (222)",
"UNKNOWN (223)",
"UNKNOWN (224)",
"UNKNOWN (225)",
"UNKNOWN (226)",
"UNKNOWN (227)",
"UNKNOWN (228)",
"UNKNOWN (229)",
"UNKNOWN (230)",
"UNKNOWN (231)",
"UNKNOWN (232)",
"UNKNOWN (233)",
"UNKNOWN (234)",
"UNKNOWN (235)",
"UNKNOWN (236)",
"UNKNOWN (237)",
"UNKNOWN (238)",
"UNKNOWN (239)",
"UNKNOWN (240)",
"UNKNOWN (241)",
"UNKNOWN (242)",
"UNKNOWN (243)",
"UNKNOWN (244)",
"UNKNOWN (245)",
"UNKNOWN (246)",
"UNKNOWN (247)",
"UNKNOWN (248)",
"UNKNOWN (249)",
"UNKNOWN (250)",
"UNKNOWN (251)",
"UNKNOWN (252)",
"UNKNOWN (253)",
"UNKNOWN (254)",
"UNKNOWN (255)",
"WM_KEYDOWN",
"WM_KEYUP",
"WM_CHAR",
"WM_DEADCHAR",
"WM_SYSKEYDOWN",
"WM_SYSKEYUP",
"WM_SYSCHAR",
"WM_SYSDEADCHAR",
"WM_KEYLAST",
"UNKNOWN (265)",
"UNKNOWN (266)",
"UNKNOWN (267)",
"UNKNOWN (268)",
"UNKNOWN (269)",
"UNKNOWN (270)",
"UNKNOWN (271)",
"WM_INITDIALOG",
"WM_COMMAND",
"WM_SYSCOMMAND",
"WM_TIMER",
"WM_HSCROLL",
"WM_VSCROLL",
"WM_INITMENU",
"WM_INITMENUPOPUP",
"UNKNOWN (280)",
"UNKNOWN (281)",
"UNKNOWN (282)",
"UNKNOWN (283)",
"UNKNOWN (284)",
"UNKNOWN (285)",
"UNKNOWN (286)",
"WM_MENUSELECT",
"WM_MENUCHAR",
"WM_ENTERIDLE",
"WM_MENURBUTTONUP",
"WM_MENUDRAG",
"WM_MENUGETOBJECT",
"WM_UNINITMENUPOPUP",
"WM_MENUCOMMAND",
"UNKNOWN (295)",
"UNKNOWN (296)",
"UNKNOWN (297)",
"UNKNOWN (298)",
"UNKNOWN (299)",
"UNKNOWN (300)",
"UNKNOWN (301)",
"UNKNOWN (302)",
"UNKNOWN (303)",
"UNKNOWN (304)",
"UNKNOWN (305)",
"WM_CTLCOLORMSGBOX",
"WM_CTLCOLOREDIT",
"WM_CTLCOLORLISTBOX",
"WM_CTLCOLORBTN",
"WM_CTLCOLORDLG",
"WM_CTLCOLORSCROLLBAR",
"WM_CTLCOLORSTATIC",
"UNKNOWN (313)",
"UNKNOWN (314)",
"UNKNOWN (315)",
"UNKNOWN (316)",
"UNKNOWN (317)",
"UNKNOWN (318)",
"UNKNOWN (319)",
"UNKNOWN (320)",
"UNKNOWN (321)",
"UNKNOWN (322)",
"UNKNOWN (323)",
"UNKNOWN (324)",
"UNKNOWN (325)",
"UNKNOWN (326)",
"UNKNOWN (327)",
"UNKNOWN (328)",
"UNKNOWN (329)",
"UNKNOWN (330)",
"UNKNOWN (331)",
"UNKNOWN (332)",
"UNKNOWN (333)",
"UNKNOWN (334)",
"UNKNOWN (335)",
"UNKNOWN (336)",
"UNKNOWN (337)",
"UNKNOWN (338)",
"UNKNOWN (339)",
"UNKNOWN (340)",
"UNKNOWN (341)",
"UNKNOWN (342)",
"UNKNOWN (343)",
"UNKNOWN (344)",
"UNKNOWN (345)",
"UNKNOWN (346)",
"UNKNOWN (347)",
"UNKNOWN (348)",
"UNKNOWN (349)",
"UNKNOWN (350)",
"UNKNOWN (351)",
"UNKNOWN (352)",
"UNKNOWN (353)",
"UNKNOWN (354)",
"UNKNOWN (355)",
"UNKNOWN (356)",
"UNKNOWN (357)",
"UNKNOWN (358)",
"UNKNOWN (359)",
"UNKNOWN (360)",
"UNKNOWN (361)",
"UNKNOWN (362)",
"UNKNOWN (363)",
"UNKNOWN (364)",
"UNKNOWN (365)",
"UNKNOWN (366)",
"UNKNOWN (367)",
"UNKNOWN (368)",
"UNKNOWN (369)",
"UNKNOWN (370)",
"UNKNOWN (371)",
"UNKNOWN (372)",
"UNKNOWN (373)",
"UNKNOWN (374)",
"UNKNOWN (375)",
"UNKNOWN (376)",
"UNKNOWN (377)",
"UNKNOWN (378)",
"UNKNOWN (379)",
"UNKNOWN (380)",
"UNKNOWN (381)",
"UNKNOWN (382)",
"UNKNOWN (383)",
"UNKNOWN (384)",
"UNKNOWN (385)",
"UNKNOWN (386)",
"UNKNOWN (387)",
"UNKNOWN (388)",
"UNKNOWN (389)",
"UNKNOWN (390)",
"UNKNOWN (391)",
"UNKNOWN (392)",
"UNKNOWN (393)",
"UNKNOWN (394)",
"UNKNOWN (395)",
"UNKNOWN (396)",
"UNKNOWN (397)",
"UNKNOWN (398)",
"UNKNOWN (399)",
"UNKNOWN (400)",
"UNKNOWN (401)",
"UNKNOWN (402)",
"UNKNOWN (403)",
"UNKNOWN (404)",
"UNKNOWN (405)",
"UNKNOWN (406)",
"UNKNOWN (407)",
"UNKNOWN (408)",
"UNKNOWN (409)",
"UNKNOWN (410)",
"UNKNOWN (411)",
"UNKNOWN (412)",
"UNKNOWN (413)",
"UNKNOWN (414)",
"UNKNOWN (415)",
"UNKNOWN (416)",
"UNKNOWN (417)",
"UNKNOWN (418)",
"UNKNOWN (419)",
"UNKNOWN (420)",
"UNKNOWN (421)",
"UNKNOWN (422)",
"UNKNOWN (423)",
"UNKNOWN (424)",
"UNKNOWN (425)",
"UNKNOWN (426)",
"UNKNOWN (427)",
"UNKNOWN (428)",
"UNKNOWN (429)",
"UNKNOWN (430)",
"UNKNOWN (431)",
"UNKNOWN (432)",
"UNKNOWN (433)",
"UNKNOWN (434)",
"UNKNOWN (435)",
"UNKNOWN (436)",
"UNKNOWN (437)",
"UNKNOWN (438)",
"UNKNOWN (439)",
"UNKNOWN (440)",
"UNKNOWN (441)",
"UNKNOWN (442)",
"UNKNOWN (443)",
"UNKNOWN (444)",
"UNKNOWN (445)",
"UNKNOWN (446)",
"UNKNOWN (447)",
"UNKNOWN (448)",
"UNKNOWN (449)",
"UNKNOWN (450)",
"UNKNOWN (451)",
"UNKNOWN (452)",
"UNKNOWN (453)",
"UNKNOWN (454)",
"UNKNOWN (455)",
"UNKNOWN (456)",
"UNKNOWN (457)",
"UNKNOWN (458)",
"UNKNOWN (459)",
"UNKNOWN (460)",
"UNKNOWN (461)",
"UNKNOWN (462)",
"UNKNOWN (463)",
"UNKNOWN (464)",
"UNKNOWN (465)",
"UNKNOWN (466)",
"UNKNOWN (467)",
"UNKNOWN (468)",
"UNKNOWN (469)",
"UNKNOWN (470)",
"UNKNOWN (471)",
"UNKNOWN (472)",
"UNKNOWN (473)",
"UNKNOWN (474)",
"UNKNOWN (475)",
"UNKNOWN (476)",
"UNKNOWN (477)",
"UNKNOWN (478)",
"UNKNOWN (479)",
"UNKNOWN (480)",
"UNKNOWN (481)",
"UNKNOWN (482)",
"UNKNOWN (483)",
"UNKNOWN (484)",
"UNKNOWN (485)",
"UNKNOWN (486)",
"UNKNOWN (487)",
"UNKNOWN (488)",
"UNKNOWN (489)",
"UNKNOWN (490)",
"UNKNOWN (491)",
"UNKNOWN (492)",
"UNKNOWN (493)",
"UNKNOWN (494)",
"UNKNOWN (495)",
"UNKNOWN (496)",
"UNKNOWN (497)",
"UNKNOWN (498)",
"UNKNOWN (499)",
"UNKNOWN (500)",
"UNKNOWN (501)",
"UNKNOWN (502)",
"UNKNOWN (503)",
"UNKNOWN (504)",
"UNKNOWN (505)",
"UNKNOWN (506)",
"UNKNOWN (507)",
"UNKNOWN (508)",
"UNKNOWN (509)",
"UNKNOWN (510)",
"UNKNOWN (511)",
"WM_MOUSEMOVE",
"WM_LBUTTONDOWN",
"WM_LBUTTONUP",
"WM_LBUTTONDBLCLK",
"WM_RBUTTONDOWN",
"WM_RBUTTONUP",
"WM_RBUTTONDBLCLK",
"WM_MBUTTONDOWN",
"WM_MBUTTONUP",
"WM_MOUSELAST",
"WM_MOUSELAST",
"UNKNOWN (523)",
"UNKNOWN (524)",
"UNKNOWN (525)",
"UNKNOWN (526)",
"UNKNOWN (527)",
"WM_PARENTNOTIFY",
"WM_ENTERMENULOOP",
"WM_EXITMENULOOP",
"WM_NEXTMENU",
"WM_SIZING",
"WM_CAPTURECHANGED",
"WM_MOVING",
"UNKNOWN (535)",
"WM_POWERBROADCAST",
"WM_DEVICECHANGE",
"UNKNOWN (538)",
"UNKNOWN (539)",
"UNKNOWN (540)",
"UNKNOWN (541)",
"UNKNOWN (542)",
"UNKNOWN (543)",
"WM_MDICREATE",
"WM_MDIDESTROY",
"WM_MDIACTIVATE",
"WM_MDIRESTORE",
"WM_MDINEXT",
"WM_MDIMAXIMIZE",
"WM_MDITILE",
"WM_MDICASCADE",
"WM_MDIICONARRANGE",
"WM_MDIGETACTIVE",
"UNKNOWN (554)",
"UNKNOWN (555)",
"UNKNOWN (556)",
"UNKNOWN (557)",
"UNKNOWN (558)",
"UNKNOWN (559)",
"WM_MDISETMENU",
"WM_ENTERSIZEMOVE",
"WM_EXITSIZEMOVE",
"WM_DROPFILES",
"WM_MDIREFRESHMENU",
"UNKNOWN (565)",
"UNKNOWN (566)",
"UNKNOWN (567)",
"UNKNOWN (568)",
"UNKNOWN (569)",
"UNKNOWN (570)",
"UNKNOWN (571)",
"UNKNOWN (572)",
"UNKNOWN (573)",
"UNKNOWN (574)",
"UNKNOWN (575)",
"UNKNOWN (576)",
"UNKNOWN (577)",
"UNKNOWN (578)",
"UNKNOWN (579)",
"UNKNOWN (580)",
"UNKNOWN (581)",
"UNKNOWN (582)",
"UNKNOWN (583)",
"UNKNOWN (584)",
"UNKNOWN (585)",
"UNKNOWN (586)",
"UNKNOWN (587)",
"UNKNOWN (588)",
"UNKNOWN (589)",
"UNKNOWN (590)",
"UNKNOWN (591)",
"UNKNOWN (592)",
"UNKNOWN (593)",
"UNKNOWN (594)",
"UNKNOWN (595)",
"UNKNOWN (596)",
"UNKNOWN (597)",
"UNKNOWN (598)",
"UNKNOWN (599)",
"UNKNOWN (600)",
"UNKNOWN (601)",
"UNKNOWN (602)",
"UNKNOWN (603)",
"UNKNOWN (604)",
"UNKNOWN (605)",
"UNKNOWN (606)",
"UNKNOWN (607)",
"UNKNOWN (608)",
"UNKNOWN (609)",
"UNKNOWN (610)",
"UNKNOWN (611)",
"UNKNOWN (612)",
"UNKNOWN (613)",
"UNKNOWN (614)",
"UNKNOWN (615)",
"UNKNOWN (616)",
"UNKNOWN (617)",
"UNKNOWN (618)",
"UNKNOWN (619)",
"UNKNOWN (620)",
"UNKNOWN (621)",
"UNKNOWN (622)",
"UNKNOWN (623)",
"UNKNOWN (624)",
"UNKNOWN (625)",
"UNKNOWN (626)",
"UNKNOWN (627)",
"UNKNOWN (628)",
"UNKNOWN (629)",
"UNKNOWN (630)",
"UNKNOWN (631)",
"UNKNOWN (632)",
"UNKNOWN (633)",
"UNKNOWN (634)",
"UNKNOWN (635)",
"UNKNOWN (636)",
"UNKNOWN (637)",
"UNKNOWN (638)",
"UNKNOWN (639)",
"UNKNOWN (640)",
"UNKNOWN (641)",
"UNKNOWN (642)",
"UNKNOWN (643)",
"UNKNOWN (644)",
"UNKNOWN (645)",
"UNKNOWN (646)",
"UNKNOWN (647)",
"UNKNOWN (648)",
"UNKNOWN (649)",
"UNKNOWN (650)",
"UNKNOWN (651)",
"UNKNOWN (652)",
"UNKNOWN (653)",
"UNKNOWN (654)",
"UNKNOWN (655)",
"UNKNOWN (656)",
"UNKNOWN (657)",
"UNKNOWN (658)",
"UNKNOWN (659)",
"UNKNOWN (660)",
"UNKNOWN (661)",
"UNKNOWN (662)",
"UNKNOWN (663)",
"UNKNOWN (664)",
"UNKNOWN (665)",
"UNKNOWN (666)",
"UNKNOWN (667)",
"UNKNOWN (668)",
"UNKNOWN (669)",
"UNKNOWN (670)",
"UNKNOWN (671)",
"UNKNOWN (672)",
"WM_MOUSEHOVER",
"UNKNOWN (674)",
"WM_MOUSELEAVE",
"UNKNOWN (676)",
"UNKNOWN (677)",
"UNKNOWN (678)",
"UNKNOWN (679)",
"UNKNOWN (680)",
"UNKNOWN (681)",
"UNKNOWN (682)",
"UNKNOWN (683)",
"UNKNOWN (684)",
"UNKNOWN (685)",
"UNKNOWN (686)",
"UNKNOWN (687)",
"UNKNOWN (688)",
"UNKNOWN (689)",
"UNKNOWN (690)",
"UNKNOWN (691)",
"UNKNOWN (692)",
"UNKNOWN (693)",
"UNKNOWN (694)",
"UNKNOWN (695)",
"UNKNOWN (696)",
"UNKNOWN (697)",
"UNKNOWN (698)",
"UNKNOWN (699)",
"UNKNOWN (700)",
"UNKNOWN (701)",
"UNKNOWN (702)",
"UNKNOWN (703)",
"UNKNOWN (704)",
"UNKNOWN (705)",
"UNKNOWN (706)",
"UNKNOWN (707)",
"UNKNOWN (708)",
"UNKNOWN (709)",
"UNKNOWN (710)",
"UNKNOWN (711)",
"UNKNOWN (712)",
"UNKNOWN (713)",
"UNKNOWN (714)",
"UNKNOWN (715)",
"UNKNOWN (716)",
"UNKNOWN (717)",
"UNKNOWN (718)",
"UNKNOWN (719)",
"UNKNOWN (720)",
"UNKNOWN (721)",
"UNKNOWN (722)",
"UNKNOWN (723)",
"UNKNOWN (724)",
"UNKNOWN (725)",
"UNKNOWN (726)",
"UNKNOWN (727)",
"UNKNOWN (728)",
"UNKNOWN (729)",
"UNKNOWN (730)",
"UNKNOWN (731)",
"UNKNOWN (732)",
"UNKNOWN (733)",
"UNKNOWN (734)",
"UNKNOWN (735)",
"UNKNOWN (736)",
"UNKNOWN (737)",
"UNKNOWN (738)",
"UNKNOWN (739)",
"UNKNOWN (740)",
"UNKNOWN (741)",
"UNKNOWN (742)",
"UNKNOWN (743)",
"UNKNOWN (744)",
"UNKNOWN (745)",
"UNKNOWN (746)",
"UNKNOWN (747)",
"UNKNOWN (748)",
"UNKNOWN (749)",
"UNKNOWN (750)",
"UNKNOWN (751)",
"UNKNOWN (752)",
"UNKNOWN (753)",
"UNKNOWN (754)",
"UNKNOWN (755)",
"UNKNOWN (756)",
"UNKNOWN (757)",
"UNKNOWN (758)",
"UNKNOWN (759)",
"UNKNOWN (760)",
"UNKNOWN (761)",
"UNKNOWN (762)",
"UNKNOWN (763)",
"UNKNOWN (764)",
"UNKNOWN (765)",
"UNKNOWN (766)",
"UNKNOWN (767)",
"WM_CUT",
"WM_COPY",
"WM_PASTE",
"WM_CLEAR",
"WM_UNDO",
"WM_RENDERFORMAT",
"WM_RENDERALLFORMATS",
"WM_DESTROYCLIPBOARD",
"WM_DRAWCLIPBOARD",
"WM_PAINTCLIPBOARD",
"WM_VSCROLLCLIPBOARD",
"WM_SIZECLIPBOARD",
"WM_ASKCBFORMATNAME",
"WM_CHANGECBCHAIN",
"WM_HSCROLLCLIPBOARD",
"WM_QUERYNEWPALETTE",
"WM_PALETTEISCHANGING",
"WM_PALETTECHANGED",
"WM_HOTKEY",
"UNKNOWN (787)",
"UNKNOWN (788)",
"UNKNOWN (789)",
"UNKNOWN (790)",
"WM_PRINT",
"WM_PRINTCLIENT",
"UNKNOWN (793)",
"UNKNOWN (794)",
"UNKNOWN (795)",
"UNKNOWN (796)",
"UNKNOWN (797)",
"UNKNOWN (798)",
"UNKNOWN (799)",
"UNKNOWN (800)",
"UNKNOWN (801)",
"UNKNOWN (802)",
"UNKNOWN (803)",
"UNKNOWN (804)",
"UNKNOWN (805)",
"UNKNOWN (806)",
"UNKNOWN (807)",
"UNKNOWN (808)",
"UNKNOWN (809)",
"UNKNOWN (810)",
"UNKNOWN (811)",
"UNKNOWN (812)",
"UNKNOWN (813)",
"UNKNOWN (814)",
"UNKNOWN (815)",
"UNKNOWN (816)",
"UNKNOWN (817)",
"UNKNOWN (818)",
"UNKNOWN (819)",
"UNKNOWN (820)",
"UNKNOWN (821)",
"UNKNOWN (822)",
"UNKNOWN (823)",
"UNKNOWN (824)",
"UNKNOWN (825)",
"UNKNOWN (826)",
"UNKNOWN (827)",
"UNKNOWN (828)",
"UNKNOWN (829)",
"UNKNOWN (830)",
"UNKNOWN (831)",
"UNKNOWN (832)",
"UNKNOWN (833)",
"UNKNOWN (834)",
"UNKNOWN (835)",
"UNKNOWN (836)",
"UNKNOWN (837)",
"UNKNOWN (838)",
"UNKNOWN (839)",
"UNKNOWN (840)",
"UNKNOWN (841)",
"UNKNOWN (842)",
"UNKNOWN (843)",
"UNKNOWN (844)",
"UNKNOWN (845)",
"UNKNOWN (846)",
"UNKNOWN (847)",
"UNKNOWN (848)",
"UNKNOWN (849)",
"UNKNOWN (850)",
"UNKNOWN (851)",
"UNKNOWN (852)",
"UNKNOWN (853)",
"UNKNOWN (854)",
"UNKNOWN (855)",
"WM_HANDHELDFIRST",
"UNKNOWN (857)",
"UNKNOWN (858)",
"UNKNOWN (859)",
"UNKNOWN (860)",
"UNKNOWN (861)",
"UNKNOWN (862)",
"WM_HANDHELDLAST",
"WM_AFXFIRST",
"UNKNOWN (865)",
"UNKNOWN (866)",
"UNKNOWN (867)",
"UNKNOWN (868)",
"UNKNOWN (869)",
"UNKNOWN (870)",
"UNKNOWN (871)",
"UNKNOWN (872)",
"UNKNOWN (873)",
"UNKNOWN (874)",
"UNKNOWN (875)",
"UNKNOWN (876)",
"UNKNOWN (877)",
"UNKNOWN (878)",
"UNKNOWN (879)",
"UNKNOWN (880)",
"UNKNOWN (881)",
"UNKNOWN (882)",
"UNKNOWN (883)",
"UNKNOWN (884)",
"UNKNOWN (885)",
"UNKNOWN (886)",
"UNKNOWN (887)",
"UNKNOWN (888)",
"UNKNOWN (889)",
"UNKNOWN (890)",
"UNKNOWN (891)",
"UNKNOWN (892)",
"UNKNOWN (893)",
"UNKNOWN (894)",
"WM_AFXLAST",
"WM_PENWINFIRST",
"UNKNOWN (897)",
"UNKNOWN (898)",
"UNKNOWN (899)",
"UNKNOWN (900)",
"UNKNOWN (901)",
"UNKNOWN (902)",
"UNKNOWN (903)",
"UNKNOWN (904)",
"UNKNOWN (905)",
"UNKNOWN (906)",
"UNKNOWN (907)",
"UNKNOWN (908)",
"UNKNOWN (909)",
"UNKNOWN (910)",
"WM_PENWINLAST",
"UNKNOWN (912)",
"UNKNOWN (913)",
"UNKNOWN (914)",
"UNKNOWN (915)",
"UNKNOWN (916)",
"UNKNOWN (917)",
"UNKNOWN (918)",
"UNKNOWN (919)",
"UNKNOWN (920)",
"UNKNOWN (921)",
"UNKNOWN (922)",
"UNKNOWN (923)",
"UNKNOWN (924)",
"UNKNOWN (925)",
"UNKNOWN (926)",
"UNKNOWN (927)",
"UNKNOWN (928)",
"UNKNOWN (929)",
"UNKNOWN (930)",
"UNKNOWN (931)",
"UNKNOWN (932)",
"UNKNOWN (933)",
"UNKNOWN (934)",
"UNKNOWN (935)",
"UNKNOWN (936)",
"UNKNOWN (937)",
"UNKNOWN (938)",
"UNKNOWN (939)",
"UNKNOWN (940)",
"UNKNOWN (941)",
"UNKNOWN (942)",
"UNKNOWN (943)",
"UNKNOWN (944)",
"UNKNOWN (945)",
"UNKNOWN (946)",
"UNKNOWN (947)",
"UNKNOWN (948)",
"UNKNOWN (949)",
"UNKNOWN (950)",
"UNKNOWN (951)",
"UNKNOWN (952)",
"UNKNOWN (953)",
"UNKNOWN (954)",
"UNKNOWN (955)",
"UNKNOWN (956)",
"UNKNOWN (957)",
"UNKNOWN (958)",
"UNKNOWN (959)",
"UNKNOWN (960)",
"UNKNOWN (961)",
"UNKNOWN (962)",
"UNKNOWN (963)",
"UNKNOWN (964)",
"UNKNOWN (965)",
"UNKNOWN (966)",
"UNKNOWN (967)",
"UNKNOWN (968)",
"UNKNOWN (969)",
"UNKNOWN (970)",
"UNKNOWN (971)",
"UNKNOWN (972)",
"UNKNOWN (973)",
"UNKNOWN (974)",
"UNKNOWN (975)",
"UNKNOWN (976)",
"UNKNOWN (977)",
"UNKNOWN (978)",
"UNKNOWN (979)",
"UNKNOWN (980)",
"UNKNOWN (981)",
"UNKNOWN (982)",
"UNKNOWN (983)",
"UNKNOWN (984)",
"UNKNOWN (985)",
"UNKNOWN (986)",
"UNKNOWN (987)",
"UNKNOWN (988)",
"UNKNOWN (989)",
"UNKNOWN (990)",
"UNKNOWN (991)",
"UNKNOWN (992)",
"UNKNOWN (993)",
"UNKNOWN (994)",
"UNKNOWN (995)",
"UNKNOWN (996)",
"UNKNOWN (997)",
"UNKNOWN (998)",
"UNKNOWN (999)",
"UNKNOWN (1000)",
"UNKNOWN (1001)",
"UNKNOWN (1002)",
"UNKNOWN (1003)",
"UNKNOWN (1004)",
"UNKNOWN (1005)",
"UNKNOWN (1006)",
"UNKNOWN (1007)",
"UNKNOWN (1008)",
"UNKNOWN (1009)",
"UNKNOWN (1010)",
"UNKNOWN (1011)",
"UNKNOWN (1012)",
"UNKNOWN (1013)",
"UNKNOWN (1014)",
"UNKNOWN (1015)",
"UNKNOWN (1016)",
"UNKNOWN (1017)",
"UNKNOWN (1018)",
"UNKNOWN (1019)",
"UNKNOWN (1020)",
"UNKNOWN (1021)",
"UNKNOWN (1022)",
"UNKNOWN (1023)",
"WM_USER"
};
/* vi: set ts=4 sw=4 expandtab: */
/*
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>
#include "SDL_main.h"
#include "SDL_events.h"
#include "SDL_syswm.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "../wincommon/SDL_lowvideo.h"
#include "SDL_dibvideo.h"
#include "SDL_vkeys.h"
#ifndef WM_APP
#define WM_APP 0x8000
#endif
#ifdef _WIN32_WCE
#define NO_GETKEYBOARDSTATE
#endif
/* The translation table from a Microsoft VK keysym to a SDL keysym */
static SDLKey VK_keymap[SDLK_LAST];
static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode,
SDL_keysym * keysym, int pressed);
/* Masks for processing the windows KEYDOWN and KEYUP messages */
#define REPEATED_KEYMASK (1<<30)
#define EXTENDED_KEYMASK (1<<24)
/* DJM: If the user setup the window for us, we want to save his window proc,
and give him a chance to handle some messages. */
#ifdef STRICT
#define WNDPROCTYPE WNDPROC
#else
#define WNDPROCTYPE FARPROC
#endif
static WNDPROCTYPE userWindowProc = NULL;
#ifdef _WIN32_WCE
WPARAM
rotateKey(WPARAM key, SDL_ScreenOrientation direction)
{
if (direction != SDL_ORIENTATION_LEFT)
return key;
switch (key) {
case 0x26: /* up */
return 0x27;
case 0x27: /* right */
return 0x28;
case 0x28: /* down */
return 0x25;
case 0x25: /* left */
return 0x26;
}
return key;
}
#endif
/* The main Win32 event handler */
LRESULT
DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
extern int posted;
switch (msg) {
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
{
SDL_keysym keysym;
#ifdef _WIN32_WCE
// Drop GAPI artefacts
if (wParam == 0x84 || wParam == 0x5B)
return 0;
// Rotate key if necessary
if (this->hidden->orientation != SDL_ORIENTATION_UP)
wParam = rotateKey(wParam, this->hidden->orientation);
#endif
/* Ignore repeated keys */
if (lParam & REPEATED_KEYMASK) {
return (0);
}
switch (wParam) {
case VK_CONTROL:
if (lParam & EXTENDED_KEYMASK)
wParam = VK_RCONTROL;
else
wParam = VK_LCONTROL;
break;
case VK_SHIFT:
/* EXTENDED trick doesn't work here */
{
Uint8 *state = SDL_GetKeyState(NULL);
if (state[SDLK_LSHIFT] == SDL_RELEASED
&& (GetKeyState(VK_LSHIFT) & 0x8000)) {
wParam = VK_LSHIFT;
} else if (state[SDLK_RSHIFT] == SDL_RELEASED
&& (GetKeyState(VK_RSHIFT) & 0x8000)) {
wParam = VK_RSHIFT;
} else {
/* Probably a key repeat */
return (0);
}
}
break;
case VK_MENU:
if (lParam & EXTENDED_KEYMASK)
wParam = VK_RMENU;
else
wParam = VK_LMENU;
break;
}
#ifdef NO_GETKEYBOARDSTATE
/* this is the workaround for the missing ToAscii() and ToUnicode() in CE (not necessary at KEYUP!) */
if (SDL_TranslateUNICODE) {
MSG m;
m.hwnd = hwnd;
m.message = msg;
m.wParam = wParam;
m.lParam = lParam;
m.time = 0;
if (TranslateMessage(&m)
&& PeekMessage(&m, hwnd, 0, WM_USER, PM_NOREMOVE)
&& (m.message == WM_CHAR)) {
GetMessage(&m, hwnd, 0, WM_USER);
wParam = m.wParam;
}
}
#endif /* NO_GETKEYBOARDSTATE */
posted = SDL_PrivateKeyboard(SDL_PRESSED,
TranslateKey(wParam,
HIWORD(lParam),
&keysym, 1));
}
return (0);
case WM_SYSKEYUP:
case WM_KEYUP:
{
SDL_keysym keysym;
#ifdef _WIN32_WCE
// Drop GAPI artifacts
if (wParam == 0x84 || wParam == 0x5B)
return 0;
// Rotate key if necessary
if (this->hidden->orientation != SDL_ORIENTATION_UP)
wParam = rotateKey(wParam, this->hidden->orientation);
#endif
switch (wParam) {
case VK_CONTROL:
if (lParam & EXTENDED_KEYMASK)
wParam = VK_RCONTROL;
else
wParam = VK_LCONTROL;
break;
case VK_SHIFT:
/* EXTENDED trick doesn't work here */
{
Uint8 *state = SDL_GetKeyState(NULL);
if (state[SDLK_LSHIFT] == SDL_PRESSED
&& !(GetKeyState(VK_LSHIFT) & 0x8000)) {
wParam = VK_LSHIFT;
} else if (state[SDLK_RSHIFT] == SDL_PRESSED
&& !(GetKeyState(VK_RSHIFT) & 0x8000)) {
wParam = VK_RSHIFT;
} else {
/* Probably a key repeat */
return (0);
}
}
break;
case VK_MENU:
if (lParam & EXTENDED_KEYMASK)
wParam = VK_RMENU;
else
wParam = VK_LMENU;
break;
}
/* Windows only reports keyup for print screen */
if (wParam == VK_SNAPSHOT
&& SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED) {
posted = SDL_PrivateKeyboard(SDL_PRESSED,
TranslateKey(wParam,
HIWORD
(lParam),
&keysym, 1));
}
posted = SDL_PrivateKeyboard(SDL_RELEASED,
TranslateKey(wParam,
HIWORD(lParam),
&keysym, 0));
}
return (0);
#if defined(SC_SCREENSAVE) && defined(SC_MONITORPOWER)
case WM_SYSCOMMAND:
{
if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
(wParam & 0xFFF0) == SC_MONITORPOWER)
return (0);
}
/* Fall through to default processing */
#endif /* SC_SCREENSAVE && SC_MONITORPOWER */
default:
{
/* Only post the event if we're watching for it */
if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
SDL_SysWMmsg wmmsg;
SDL_VERSION(&wmmsg.version);
wmmsg.hwnd = hwnd;
wmmsg.msg = msg;
wmmsg.wParam = wParam;
wmmsg.lParam = lParam;
posted = SDL_PrivateSysWMEvent(&wmmsg);
/* DJM: If the user isn't watching for private
messages in her SDL event loop, then pass it
along to any win32 specific window proc.
*/
} else if (userWindowProc) {
return CallWindowProc(userWindowProc, hwnd, msg, wParam,
lParam);
}
}
break;
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
void
DIB_PumpEvents(_THIS)
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
}
}
}
void
DIB_InitOSKeymap(_THIS)
{
int i;
/* Map the VK keysyms */
for (i = 0; i < SDL_arraysize(VK_keymap); ++i)
VK_keymap[i] = SDLK_UNKNOWN;
VK_keymap[VK_BACK] = SDLK_BACKSPACE;
VK_keymap[VK_TAB] = SDLK_TAB;
VK_keymap[VK_CLEAR] = SDLK_CLEAR;
VK_keymap[VK_RETURN] = SDLK_RETURN;
VK_keymap[VK_PAUSE] = SDLK_PAUSE;
VK_keymap[VK_ESCAPE] = SDLK_ESCAPE;
VK_keymap[VK_SPACE] = SDLK_SPACE;
VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE;
VK_keymap[VK_COMMA] = SDLK_COMMA;
VK_keymap[VK_MINUS] = SDLK_MINUS;
VK_keymap[VK_PERIOD] = SDLK_PERIOD;
VK_keymap[VK_SLASH] = SDLK_SLASH;
VK_keymap[VK_0] = SDLK_0;
VK_keymap[VK_1] = SDLK_1;
VK_keymap[VK_2] = SDLK_2;
VK_keymap[VK_3] = SDLK_3;
VK_keymap[VK_4] = SDLK_4;
VK_keymap[VK_5] = SDLK_5;
VK_keymap[VK_6] = SDLK_6;
VK_keymap[VK_7] = SDLK_7;
VK_keymap[VK_8] = SDLK_8;
VK_keymap[VK_9] = SDLK_9;
VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON;
VK_keymap[VK_EQUALS] = SDLK_EQUALS;
VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET;
VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH;
VK_keymap[VK_OEM_102] = SDLK_LESS;
VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET;
VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE;
VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE;
VK_keymap[VK_A] = SDLK_a;
VK_keymap[VK_B] = SDLK_b;
VK_keymap[VK_C] = SDLK_c;
VK_keymap[VK_D] = SDLK_d;
VK_keymap[VK_E] = SDLK_e;
VK_keymap[VK_F] = SDLK_f;
VK_keymap[VK_G] = SDLK_g;
VK_keymap[VK_H] = SDLK_h;
VK_keymap[VK_I] = SDLK_i;
VK_keymap[VK_J] = SDLK_j;
VK_keymap[VK_K] = SDLK_k;
VK_keymap[VK_L] = SDLK_l;
VK_keymap[VK_M] = SDLK_m;
VK_keymap[VK_N] = SDLK_n;
VK_keymap[VK_O] = SDLK_o;
VK_keymap[VK_P] = SDLK_p;
VK_keymap[VK_Q] = SDLK_q;
VK_keymap[VK_R] = SDLK_r;
VK_keymap[VK_S] = SDLK_s;
VK_keymap[VK_T] = SDLK_t;
VK_keymap[VK_U] = SDLK_u;
VK_keymap[VK_V] = SDLK_v;
VK_keymap[VK_W] = SDLK_w;
VK_keymap[VK_X] = SDLK_x;
VK_keymap[VK_Y] = SDLK_y;
VK_keymap[VK_Z] = SDLK_z;
VK_keymap[VK_DELETE] = SDLK_DELETE;
VK_keymap[VK_NUMPAD0] = SDLK_KP0;
VK_keymap[VK_NUMPAD1] = SDLK_KP1;
VK_keymap[VK_NUMPAD2] = SDLK_KP2;
VK_keymap[VK_NUMPAD3] = SDLK_KP3;
VK_keymap[VK_NUMPAD4] = SDLK_KP4;
VK_keymap[VK_NUMPAD5] = SDLK_KP5;
VK_keymap[VK_NUMPAD6] = SDLK_KP6;
VK_keymap[VK_NUMPAD7] = SDLK_KP7;
VK_keymap[VK_NUMPAD8] = SDLK_KP8;
VK_keymap[VK_NUMPAD9] = SDLK_KP9;
VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD;
VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE;
VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY;
VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS;
VK_keymap[VK_ADD] = SDLK_KP_PLUS;
VK_keymap[VK_UP] = SDLK_UP;
VK_keymap[VK_DOWN] = SDLK_DOWN;
VK_keymap[VK_RIGHT] = SDLK_RIGHT;
VK_keymap[VK_LEFT] = SDLK_LEFT;
VK_keymap[VK_INSERT] = SDLK_INSERT;
VK_keymap[VK_HOME] = SDLK_HOME;
VK_keymap[VK_END] = SDLK_END;
VK_keymap[VK_PRIOR] = SDLK_PAGEUP;
VK_keymap[VK_NEXT] = SDLK_PAGEDOWN;
VK_keymap[VK_F1] = SDLK_F1;
VK_keymap[VK_F2] = SDLK_F2;
VK_keymap[VK_F3] = SDLK_F3;
VK_keymap[VK_F4] = SDLK_F4;
VK_keymap[VK_F5] = SDLK_F5;
VK_keymap[VK_F6] = SDLK_F6;
VK_keymap[VK_F7] = SDLK_F7;
VK_keymap[VK_F8] = SDLK_F8;
VK_keymap[VK_F9] = SDLK_F9;
VK_keymap[VK_F10] = SDLK_F10;
VK_keymap[VK_F11] = SDLK_F11;
VK_keymap[VK_F12] = SDLK_F12;
VK_keymap[VK_F13] = SDLK_F13;
VK_keymap[VK_F14] = SDLK_F14;
VK_keymap[VK_F15] = SDLK_F15;
VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK;
VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK;
VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK;
VK_keymap[VK_RSHIFT] = SDLK_RSHIFT;
VK_keymap[VK_LSHIFT] = SDLK_LSHIFT;
VK_keymap[VK_RCONTROL] = SDLK_RCTRL;
VK_keymap[VK_LCONTROL] = SDLK_LCTRL;
VK_keymap[VK_RMENU] = SDLK_RALT;
VK_keymap[VK_LMENU] = SDLK_LALT;
VK_keymap[VK_RWIN] = SDLK_RSUPER;
VK_keymap[VK_LWIN] = SDLK_LSUPER;
VK_keymap[VK_HELP] = SDLK_HELP;
#ifdef VK_PRINT
VK_keymap[VK_PRINT] = SDLK_PRINT;
#endif
VK_keymap[VK_SNAPSHOT] = SDLK_PRINT;
VK_keymap[VK_CANCEL] = SDLK_BREAK;
VK_keymap[VK_APPS] = SDLK_MENU;
}
static SDL_keysym *
TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym * keysym, int pressed)
{
/* Set the keysym information */
keysym->scancode = (unsigned char) scancode;
keysym->sym = VK_keymap[vkey];
keysym->mod = KMOD_NONE;
keysym->unicode = 0;
if (pressed && SDL_TranslateUNICODE) {
#ifdef NO_GETKEYBOARDSTATE
/* Uh oh, better hope the vkey is close enough.. */
keysym->unicode = vkey;
#else
BYTE keystate[256];
Uint16 wchars[2];
GetKeyboardState(keystate);
if (SDL_ToUnicode
((UINT) vkey, scancode, keystate, wchars,
sizeof(wchars) / sizeof(wchars[0]), 0) == 1) {
keysym->unicode = wchars[0];
}
#endif /* NO_GETKEYBOARDSTATE */
}
return (keysym);
}
int
DIB_CreateWindow(_THIS)
{
char *windowid = SDL_getenv("SDL_WINDOWID");
SDL_RegisterApp(NULL, 0, 0);
SDL_windowid = (windowid != NULL);
if (SDL_windowid) {
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
/* wince 2.1 does not have strtol */
wchar_t *windowid_t =
SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1,
windowid_t, SDL_strlen(windowid) + 1);
SDL_Window = (HWND) wcstol(windowid_t, NULL, 0);
SDL_free(windowid_t);
#else
SDL_Window = (HWND) SDL_strtoull(windowid, NULL, 0);
#endif
if (SDL_Window == NULL) {
SDL_SetError("Couldn't get user specified window");
return (-1);
}
/* DJM: we want all event's for the user specified
window to be handled by SDL.
*/
userWindowProc =
(WNDPROCTYPE) GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);
SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR) WinMessage);
} else {
SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
| WS_MINIMIZEBOX), CW_USEDEFAULT,
CW_USEDEFAULT, 0, 0, NULL, NULL,
SDL_Instance, NULL);
if (SDL_Window == NULL) {
SDL_SetError("Couldn't create window");
return (-1);
}
ShowWindow(SDL_Window, SW_HIDE);
}
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
return (0);
}
void
DIB_DestroyWindow(_THIS)
{
if (SDL_windowid) {
SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR) userWindowProc);
} else {
DestroyWindow(SDL_Window);
}
SDL_UnregisterApp();
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#include "../wincommon/SDL_lowvideo.h"
/* Variables and functions exported by SDL_dibevents.c to other parts
of the native video subsystem (SDL_dibvideo.c)
*/
extern LONG
DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern int DIB_CreateWindow(_THIS);
extern void DIB_DestroyWindow(_THIS);
extern void DIB_PumpEvents(_THIS);
extern void DIB_InitOSKeymap(_THIS);
/* vi: set ts=4 sw=4 expandtab: */
/*
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.c
extern 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_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_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) { /* 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 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 *) 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);
handle = CreatePalette(palette);
SDL_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);
}
#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" */
screen_pal = DIB_CreatePalette(vformat->BitsPerPixel);
}
/* Fill in some window manager capabilities */
this->info.wm_available = 1;
#ifdef _WIN32_WCE
this->hidden->origRotation = -1;
#endif
/* 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;
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) SDL_malloc(dib_size);
SDL_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);
depth = 0;
switch (dib_hdr->biBitCount) {
case 8:
depth = 8;
break;
case 24:
depth = 24;
break;
case 32:
depth = 32;
break;
case 16:
if (dib_hdr->biCompression == BI_BITFIELDS) {
/* check the red mask */
switch (((DWORD *) ((char *) dib_hdr + dib_hdr->biSize))[0]) {
case 0xf800:
depth = 16;
break; /* 565 */
case 0x7c00:
depth = 15;
break; /* 555 */
}
}
}
SDL_free(dib_hdr);
return depth;
#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;
Uint32 Rmask, Gmask, Bmask;
/* Clean up any GL context that may be hanging around */
if (current->flags & SDL_INTERNALOPENGL) {
WIN_GL_ShutDown(this);
}
SDL_resizing = 1;
/* 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;
Bmask = 0x00000000;
break;
}
video = SDL_CreateRGBSurface(SDL_SWSURFACE,
0, 0, bpp, Rmask, Gmask, Bmask, 0);
if (video == NULL) {
SDL_OutOfMemory();
return (NULL);
}
}
/* Fill in part of the video surface */
prev_flags = video->flags;
video->flags = 0; /* Clear flags */
video->w = width;
video->h = height;
video->pitch = SDL_CalculatePitch(video);
/* Small fix for WinCE/Win32 - when activating window
SDL_VideoSurface is equal to zero, so activating code
is not called properly for fullscreen windows because
macros WINDIB_FULLSCREEN uses SDL_VideoSurface
*/
SDL_VideoSurface = video;
#if defined(_WIN32_WCE)
if (flags & SDL_FULLSCREEN)
video->flags |= SDL_FULLSCREEN;
#endif
#ifndef NO_CHANGEDISPLAYSETTINGS
/* Set fullscreen mode if appropriate */
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
DEVMODE settings;
BOOL changed;
SDL_memset(&settings, 0, sizeof(DEVMODE));
settings.dmSize = sizeof(DEVMODE);
#ifdef _WIN32_WCE
// try to rotate screen to fit requested resolution
if (this->hidden->supportRotation) {
DWORD rotation;
// ask current mode
settings.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
rotation = settings.dmDisplayOrientation;
if ((width > GetDeviceCaps(GetDC(NULL), HORZRES))
&& (height < GetDeviceCaps(GetDC(NULL), VERTRES))) {
switch (rotation) {
case DMDO_0:
settings.dmDisplayOrientation = DMDO_90;
break;
case DMDO_270:
settings.dmDisplayOrientation = DMDO_180;
break;
}
if (settings.dmDisplayOrientation != rotation) {
// go to landscape
this->hidden->origRotation = rotation;
ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_RESET,
NULL);
}
}
if ((width < GetDeviceCaps(GetDC(NULL), HORZRES))
&& (height > GetDeviceCaps(GetDC(NULL), VERTRES))) {
switch (rotation) {
case DMDO_90:
settings.dmDisplayOrientation = DMDO_0;
break;
case DMDO_180:
settings.dmDisplayOrientation = DMDO_270;
break;
}
if (settings.dmDisplayOrientation != rotation) {
// go to portrait
this->hidden->origRotation = rotation;
ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_RESET,
NULL);
}
}
}
#endif
#ifndef _WIN32_WCE
settings.dmBitsPerPel = video->format->BitsPerPixel;
settings.dmPelsWidth = width;
settings.dmPelsHeight = height;
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (width <= (int) SDL_desktop_mode.dmPelsWidth &&
height <= (int) SDL_desktop_mode.dmPelsHeight) {
settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
settings.dmFields |= DM_DISPLAYFREQUENCY;
}
changed =
(ChangeDisplaySettings(&settings, CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL);
if (!changed && (settings.dmFields & DM_DISPLAYFREQUENCY)) {
settings.dmFields &= ~DM_DISPLAYFREQUENCY;
changed =
(ChangeDisplaySettings(&settings, CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL);
}
#else
changed = 1;
#endif
if (changed) {
video->flags |= SDL_FULLSCREEN;
SDL_fullscreen_mode = settings;
}
}
#endif /* !NO_CHANGEDISPLAYSETTINGS */
/* Reset the palette and create a new one if necessary */
if (screen_pal != NULL) {
/* RJR: March 28, 2000
delete identity palette if switching from a palettized mode */
DeleteObject(screen_pal);
screen_pal = NULL;
}
if (bpp <= 8) {
/* RJR: March 28, 2000
create identity palette switching to a palettized mode */
screen_pal = DIB_CreatePalette(bpp);
}
style = GetWindowLong(SDL_Window, GWL_STYLE);
style &= ~(resizestyle | WS_MAXIMIZE);
if ((video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
style &= ~windowstyle;
style |= directstyle;
} else {
#ifndef NO_CHANGEDISPLAYSETTINGS
if ((prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
ChangeDisplaySettings(NULL, 0);
}
#endif
if (flags & SDL_NOFRAME) {
style &= ~windowstyle;
style |= directstyle;
video->flags |= SDL_NOFRAME;
} else {
style &= ~directstyle;
style |= windowstyle;
if (flags & SDL_RESIZABLE) {
style |= resizestyle;
video->flags |= SDL_RESIZABLE;
}
}
#if WS_MAXIMIZE
if (IsZoomed(SDL_Window))
style |= WS_MAXIMIZE;
#endif
}
/* DJM: Don't piss of anyone who has setup his own window */
if (!SDL_windowid)
SetWindowLong(SDL_Window, GWL_STYLE, style);
/* Delete the old bitmap if necessary */
if (screen_bmp != NULL) {
DeleteObject(screen_bmp);
}
if (!(flags & SDL_INTERNALOPENGL)) {
BOOL is16bitmode = (video->format->BytesPerPixel == 2);
/* Suss out the bitmap info header */
binfo_size = sizeof(*binfo);
if (is16bitmode) {
/* 16bit modes, palette area used for rgb bitmasks */
binfo_size += 3 * sizeof(DWORD);
} else if (video->format->palette) {
binfo_size += video->format->palette->ncolors * sizeof(RGBQUAD);
}
binfo = (BITMAPINFO *) SDL_malloc(binfo_size);
if (!binfo) {
if (video != current) {
SDL_FreeSurface(video);
}
SDL_OutOfMemory();
return (NULL);
}
binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
binfo->bmiHeader.biWidth = video->w;
binfo->bmiHeader.biHeight = -video->h; /* -ve for topdown bitmap */
binfo->bmiHeader.biPlanes = 1;
binfo->bmiHeader.biSizeImage = video->h * video->pitch;
binfo->bmiHeader.biXPelsPerMeter = 0;
binfo->bmiHeader.biYPelsPerMeter = 0;
binfo->bmiHeader.biClrUsed = 0;
binfo->bmiHeader.biClrImportant = 0;
binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
if (is16bitmode) {
/* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */
binfo->bmiHeader.biCompression = BI_BITFIELDS;
((Uint32 *) binfo->bmiColors)[0] = video->format->Rmask;
((Uint32 *) binfo->bmiColors)[1] = video->format->Gmask;
((Uint32 *) binfo->bmiColors)[2] = video->format->Bmask;
} else {
binfo->bmiHeader.biCompression = BI_RGB; /* BI_BITFIELDS for 565 vs 555 */
if (video->format->palette) {
SDL_memset(binfo->bmiColors, 0,
video->format->palette->ncolors * sizeof(RGBQUAD));
}
}
/* Create the offscreen bitmap buffer */
hdc = GetDC(SDL_Window);
screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
(void **) (&video->pixels), NULL, 0);
ReleaseDC(SDL_Window, hdc);
SDL_free(binfo);
if (screen_bmp == NULL) {
if (video != current) {
SDL_FreeSurface(video);
}
SDL_SetError("Couldn't create DIB section");
return (NULL);
}
this->UpdateRects = DIB_NormalUpdate;
/* Set video surface flags */
if (bpp <= 8) {
/* BitBlt() maps colors for us */
video->flags |= SDL_HWPALETTE;
}
}
#ifndef _WIN32_WCE
/* Resize the window */
if (!SDL_windowid && !IsZoomed(SDL_Window)) {
#else
if (!SDL_windowid) {
#endif
HWND top;
UINT swp_flags;
const char *window = NULL;
const char *center = NULL;
if (!SDL_windowX && !SDL_windowY) {
window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
center = SDL_getenv("SDL_VIDEO_CENTERED");
if (window) {
if (SDL_sscanf(window, "%d,%d", &x, &y) == 2) {
SDL_windowX = x;
SDL_windowY = y;
}
if (SDL_strcmp(window, "center") == 0) {
center = window;
}
}
}
swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
bounds.left = SDL_windowX;
bounds.top = SDL_windowY;
bounds.right = SDL_windowX + video->w;
bounds.bottom = SDL_windowY + video->h;
AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
(GetMenu(SDL_Window) != NULL), 0);
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
if ((flags & SDL_FULLSCREEN)) {
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
} else if (center) {
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
} else if (SDL_windowX || SDL_windowY || window) {
x = bounds.left;
y = bounds.top;
} else {
x = y = -1;
swp_flags |= SWP_NOMOVE;
}
if (flags & SDL_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
if (!(flags & SDL_FULLSCREEN)) {
SDL_windowX = SDL_bounds.left;
SDL_windowY = SDL_bounds.top;
}
SetForegroundWindow(SDL_Window);
}
SDL_resizing = 0;
/* Set up for OpenGL */
if (flags & SDL_INTERNALOPENGL) {
if (WIN_GL_SetupWindow(this) < 0) {
return (NULL);
}
video->flags |= SDL_INTERNALOPENGL;
}
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
/* We're live! */
return (video);
}
/* We don't actually allow hardware surfaces in the DIB driver */
static int
DIB_AllocHWSurface(_THIS, SDL_Surface * surface)
{
return (-1);
}
static void
DIB_FreeHWSurface(_THIS, SDL_Surface * surface)
{
return;
}
static int
DIB_LockHWSurface(_THIS, SDL_Surface * surface)
{
return (0);
}
static void
DIB_UnlockHWSurface(_THIS, SDL_Surface * surface)
{
return;
}
static void
DIB_NormalUpdate(_THIS, int numrects, SDL_Rect * rects)
{
HDC hdc, mdc;
int i;
hdc = GetDC(SDL_Window);
if (screen_pal) {
SelectPalette(hdc, screen_pal, FALSE);
}
mdc = CreateCompatibleDC(hdc);
SelectObject(mdc, screen_bmp);
for (i = 0; i < numrects; ++i) {
BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h,
mdc, rects[i].x, rects[i].y, SRCCOPY);
}
DeleteDC(mdc);
ReleaseDC(SDL_Window, hdc);
}
int
DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
{
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
HDC hdc, mdc;
RGBQUAD *pal;
#else
HDC hdc;
#endif
int i;
/* Update the display palette */
hdc = GetDC(SDL_Window);
if (screen_pal) {
PALETTEENTRY *entries;
entries = SDL_stack_alloc(PALETTEENTRY, ncolors);
for (i = 0; i < ncolors; ++i) {
entries[i].peRed = colors[i].r;
entries[i].peGreen = colors[i].g;
entries[i].peBlue = colors[i].b;
entries[i].peFlags = PC_NOCOLLAPSE;
}
SetPaletteEntries(screen_pal, firstcolor, ncolors, entries);
SelectPalette(hdc, screen_pal, FALSE);
RealizePalette(hdc);
SDL_stack_free(entries);
}
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
/* Copy palette colors into DIB palette */
pal = SDL_stack_alloc(RGBQUAD, ncolors);
for (i = 0; i < ncolors; ++i) {
pal[i].rgbRed = colors[i].r;
pal[i].rgbGreen = colors[i].g;
pal[i].rgbBlue = colors[i].b;
pal[i].rgbReserved = 0;
}
/* Set the DIB palette and update the display */
mdc = CreateCompatibleDC(hdc);
SelectObject(mdc, screen_bmp);
SetDIBColorTable(mdc, firstcolor, ncolors, pal);
BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, mdc, 0, 0, SRCCOPY);
DeleteDC(mdc);
SDL_stack_free(pal);
#endif
ReleaseDC(SDL_Window, hdc);
return (1);
}
static void
DIB_CheckGamma(_THIS)
{
#ifndef NO_GAMMA_SUPPORT
HDC hdc;
WORD ramp[3 * 256];
/* If we fail to get gamma, disable gamma control */
hdc = GetDC(SDL_Window);
if (!GetDeviceGammaRamp(hdc, ramp)) {
this->GetGammaRamp = NULL;
this->SetGammaRamp = NULL;
}
ReleaseDC(SDL_Window, hdc);
#endif /* !NO_GAMMA_SUPPORT */
}
void
DIB_SwapGamma(_THIS)
{
#ifndef NO_GAMMA_SUPPORT
HDC hdc;
if (gamma_saved) {
hdc = GetDC(SDL_Window);
if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
/* About to leave active state, restore gamma */
SetDeviceGammaRamp(hdc, gamma_saved);
} else {
/* About to enter active state, set game gamma */
GetDeviceGammaRamp(hdc, gamma_saved);
SetDeviceGammaRamp(hdc, this->gamma);
}
ReleaseDC(SDL_Window, hdc);
}
#endif /* !NO_GAMMA_SUPPORT */
}
void
DIB_QuitGamma(_THIS)
{
#ifndef NO_GAMMA_SUPPORT
if (gamma_saved) {
/* Restore the original gamma if necessary */
if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
HDC hdc;
hdc = GetDC(SDL_Window);
SetDeviceGammaRamp(hdc, gamma_saved);
ReleaseDC(SDL_Window, hdc);
}
/* Free the saved gamma memory */
SDL_free(gamma_saved);
gamma_saved = 0;
}
#endif /* !NO_GAMMA_SUPPORT */
}
int
DIB_SetGammaRamp(_THIS, Uint16 * ramp)
{
#ifdef NO_GAMMA_SUPPORT
SDL_SetError("SDL compiled without gamma ramp support");
return -1;
#else
HDC hdc;
BOOL succeeded;
/* Set the ramp for the display */
if (!gamma_saved) {
gamma_saved = (WORD *) SDL_malloc(3 * 256 * sizeof(*gamma_saved));
if (!gamma_saved) {
SDL_OutOfMemory();
return -1;
}
hdc = GetDC(SDL_Window);
GetDeviceGammaRamp(hdc, gamma_saved);
ReleaseDC(SDL_Window, hdc);
}
if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
hdc = GetDC(SDL_Window);
succeeded = SetDeviceGammaRamp(hdc, ramp);
ReleaseDC(SDL_Window, hdc);
} else {
succeeded = TRUE;
}
return succeeded ? 0 : -1;
#endif /* !NO_GAMMA_SUPPORT */
}
int
DIB_GetGammaRamp(_THIS, Uint16 * ramp)
{
#ifdef NO_GAMMA_SUPPORT
SDL_SetError("SDL compiled without gamma ramp support");
return -1;
#else
HDC hdc;
BOOL succeeded;
/* Get the ramp from the display */
hdc = GetDC(SDL_Window);
succeeded = GetDeviceGammaRamp(hdc, ramp);
ReleaseDC(SDL_Window, hdc);
return succeeded ? 0 : -1;
#endif /* !NO_GAMMA_SUPPORT */
}
void
DIB_VideoQuit(_THIS)
{
int i, j;
/* Destroy the window and everything associated with it */
if (SDL_Window) {
/* Delete the screen bitmap (also frees screen->pixels) */
if (this->screen) {
#ifndef NO_CHANGEDISPLAYSETTINGS
if (this->screen->flags & SDL_FULLSCREEN) {
ChangeDisplaySettings(NULL, 0);
ShowWindow(SDL_Window, SW_HIDE);
}
#endif
if (this->screen->flags & SDL_OPENGL) {
WIN_GL_ShutDown(this);
}
this->screen->pixels = NULL;
}
if (screen_bmp) {
DeleteObject(screen_bmp);
screen_bmp = NULL;
}
if (screen_icn) {
DestroyIcon(screen_icn);
screen_icn = NULL;
}
DIB_QuitGamma(this);
DIB_DestroyWindow(this);
SDL_Window = NULL;
#if defined(_WIN32_WCE)
// Unload wince aygshell library to prevent leak
if (aygshell) {
FreeLibrary(aygshell);
aygshell = NULL;
}
#endif
}
for (i = 0; i < SDL_arraysize(SDL_modelist); ++i) {
if (!SDL_modelist[i]) {
continue;
}
for (j = 0; SDL_modelist[i][j]; ++j) {
SDL_free(SDL_modelist[i][j]);
}
SDL_free(SDL_modelist[i]);
SDL_modelist[i] = NULL;
SDL_nummodes[i] = 0;
}
}
/* Exported for the windows message loop only */
static void
DIB_FocusPalette(_THIS, int foreground)
{
if (screen_pal != NULL) {
HDC hdc;
hdc = GetDC(SDL_Window);
SelectPalette(hdc, screen_pal, FALSE);
if (RealizePalette(hdc))
InvalidateRect(SDL_Window, NULL, FALSE);
ReleaseDC(SDL_Window, hdc);
}
}
static void
DIB_RealizePalette(_THIS)
{
DIB_FocusPalette(this, 1);
}
static void
DIB_PaletteChanged(_THIS, HWND window)
{
if (window != SDL_Window) {
DIB_FocusPalette(this, 0);
}
}
/* Exported for the windows message loop only */
static void
DIB_WinPAINT(_THIS, HDC hdc)
{
HDC mdc;
if (screen_pal) {
SelectPalette(hdc, screen_pal, FALSE);
}
mdc = CreateCompatibleDC(hdc);
SelectObject(mdc, screen_bmp);
BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h,
mdc, 0, 0, SRCCOPY);
DeleteDC(mdc);
}
/* Stub in case DirectX isn't available */
#if !SDL_AUDIO_DRIVER_DSOUND
void
DX5_SoundFocus(HWND hwnd)
{
return;
}
#endif
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#ifndef _SDL_dibvideo_h
#define _SDL_dibvideo_h
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* for PDA */
typedef enum
{
SDL_ORIENTATION_UP,
SDL_ORIENTATION_DOWN,
SDL_ORIENTATION_LEFT,
SDL_ORIENTATION_RIGHT
} SDL_ScreenOrientation;
/* Private display data */
struct SDL_PrivateVideoData
{
HBITMAP screen_bmp;
HPALETTE screen_pal;
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
SDL_ScreenOrientation orientation;
#ifdef _WIN32_WCE
int invert; /* do to remove, used by GAPI driver! */
char hiresFix; /* using hires mode without defining hires resource */
int supportRotation; /* for Pocket PC devices */
DWORD origRotation; /* for Pocket PC devices */
#endif
};
/* Old variable names */
#define screen_bmp (this->hidden->screen_bmp)
#define screen_pal (this->hidden->screen_pal)
#define SDL_nummodes (this->hidden->SDL_nummodes)
#define SDL_modelist (this->hidden->SDL_modelist)
#endif /* _SDL_dibvideo_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
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
*/
#ifndef VK_0
#define VK_0 '0'
#define VK_1 '1'
#define VK_2 '2'
#define VK_3 '3'
#define VK_4 '4'
#define VK_5 '5'
#define VK_6 '6'
#define VK_7 '7'
#define VK_8 '8'
#define VK_9 '9'
#define VK_A 'A'
#define VK_B 'B'
#define VK_C 'C'
#define VK_D 'D'
#define VK_E 'E'
#define VK_F 'F'
#define VK_G 'G'
#define VK_H 'H'
#define VK_I 'I'
#define VK_J 'J'
#define VK_K 'K'
#define VK_L 'L'
#define VK_M 'M'
#define VK_N 'N'
#define VK_O 'O'
#define VK_P 'P'
#define VK_Q 'Q'
#define VK_R 'R'
#define VK_S 'S'
#define VK_T 'T'
#define VK_U 'U'
#define VK_V 'V'
#define VK_W 'W'
#define VK_X 'X'
#define VK_Y 'Y'
#define VK_Z 'Z'
#endif /* VK_0 */
/* These keys haven't been defined, but were experimentally determined */
#define VK_SEMICOLON 0xBA
#define VK_EQUALS 0xBB
#define VK_COMMA 0xBC
#define VK_MINUS 0xBD
#define VK_PERIOD 0xBE
#define VK_SLASH 0xBF
#define VK_GRAVE 0xC0
#define VK_LBRACKET 0xDB
#define VK_BACKSLASH 0xDC
#define VK_RBRACKET 0xDD
#define VK_APOSTROPHE 0xDE
#define VK_BACKTICK 0xDF
#define VK_OEM_102 0xE2
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
/* CAUTION!!!! If you modify this file, check ../windib/SDL_sysevents.c */
#include "directx.h"
#include "SDL_main.h"
#include "SDL_events.h"
#include "SDL_video.h"
#include "SDL_syswm.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "../wincommon/SDL_lowvideo.h"
#include "SDL_dx5video.h"
#ifndef WM_APP
#define WM_APP 0x8000
#endif
#ifdef _WIN32_WCE
#define NO_GETKEYBOARDSTATE
#endif
/* The keyboard and mouse device input */
#define MAX_INPUTS 16 /* Maximum of 16-1 input devices */
#define INPUT_QSIZE 512 /* Buffer up to 512 input messages */
static LPDIRECTINPUT dinput = NULL;
static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS];
static HANDLE SDL_DIevt[MAX_INPUTS];
static void (*SDL_DIfun[MAX_INPUTS]) (const int, DIDEVICEOBJECTDATA *);
static int SDL_DIndev = 0;
static int mouse_lost;
static int mouse_pressed;
static int mouse_buttons_swapped = 0;
/* The translation table from a DirectInput scancode to an SDL keysym */
static SDLKey DIK_keymap[256];
static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym * keysym,
int pressed);
/* DJM: If the user setup the window for us, we want to save his window proc,
and give him a chance to handle some messages. */
#ifdef STRICT
#define WNDPROCTYPE WNDPROC
#else
#define WNDPROCTYPE FARPROC
#endif
static WNDPROCTYPE userWindowProc = NULL;
static HWND
GetTopLevelParent(HWND hWnd)
{
HWND hParentWnd;
while (1) {
hParentWnd = GetParent(hWnd);
if (hParentWnd == NULL)
break;
hWnd = hParentWnd;
}
return hWnd;
}
/* Convert a DirectInput return code to a text message */
static void
SetDIerror(char *function, int code)
{
static char *error;
static char errbuf[1024];
errbuf[0] = 0;
switch (code) {
case DIERR_GENERIC:
error = "Undefined error!";
break;
case DIERR_OLDDIRECTINPUTVERSION:
error = "Your version of DirectInput needs upgrading";
break;
case DIERR_INVALIDPARAM:
error = "Invalid parameters";
break;
case DIERR_OUTOFMEMORY:
error = "Out of memory";
break;
case DIERR_DEVICENOTREG:
error = "Device not registered";
break;
case DIERR_NOINTERFACE:
error = "Interface not supported";
break;
case DIERR_NOTINITIALIZED:
error = "Device not initialized";
break;
default:
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
"%s: Unknown DirectInput error: 0x%x", function, code);
break;
}
if (!errbuf[0]) {
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
error);
}
SDL_SetError("%s", errbuf);
return;
}
/* Initialize DirectInput
Note: If NONEXCLUSIVE access is requested for the devices, normal
windows input messages will continue to be generated for that
input device, in addition to DirectInput messages.
*/
static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA * events);
static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA * events);
struct
{
char *name;
REFGUID guid;
LPCDIDATAFORMAT format;
DWORD win_level;
DWORD raw_level;
void (*fun) (const int numevents, DIDEVICEOBJECTDATA * events);
} inputs[] = {
{
"keyboard",
&GUID_SysKeyboard, &c_dfDIKeyboard,
(DISCL_FOREGROUND | DISCL_NONEXCLUSIVE),
(DISCL_FOREGROUND | DISCL_NONEXCLUSIVE), handle_keyboard}, {
"mouse",
&GUID_SysMouse, &c_dfDIMouse,
(DISCL_FOREGROUND | DISCL_NONEXCLUSIVE),
(DISCL_FOREGROUND | DISCL_EXCLUSIVE), handle_mouse}, {
NULL, NULL, NULL, 0, 0, NULL}
};
static int
DX5_DInputInit(_THIS)
{
int i;
LPDIRECTINPUTDEVICE device;
HRESULT result;
DIPROPDWORD dipdw;
HWND topwnd;
/* Create the DirectInput object */
result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, &dinput, NULL);
if (result != DI_OK) {
SetDIerror("DirectInputCreate", result);
return (-1);
}
/* Create all of our registered input devices */
SDL_DIndev = 0;
for (i = 0; inputs[i].name; ++i) {
/* Create the DirectInput device */
result = IDirectInput_CreateDevice(dinput, inputs[i].guid,
&device, NULL);
if (result != DI_OK) {
SetDIerror("DirectInput::CreateDevice", result);
return (-1);
}
result = IDirectInputDevice_QueryInterface(device,
&IID_IDirectInputDevice2,
(LPVOID *) & SDL_DIdev[i]);
IDirectInputDevice_Release(device);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::QueryInterface", result);
return (-1);
}
topwnd = GetTopLevelParent(SDL_Window);
result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i],
topwnd,
inputs[i].win_level);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::SetCooperativeLevel", result);
return (-1);
}
result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i],
inputs[i].format);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::SetDataFormat", result);
return (-1);
}
/* Set buffered input -- we aren't polling */
SDL_memset(&dipdw, 0, sizeof(dipdw));
dipdw.diph.dwSize = sizeof(dipdw);
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = INPUT_QSIZE;
result = IDirectInputDevice2_SetProperty(SDL_DIdev[i],
DIPROP_BUFFERSIZE,
&dipdw.diph);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::SetProperty", result);
return (-1);
}
/* Create an event to be signaled when input is ready */
SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
if (SDL_DIevt[i] == NULL) {
SDL_SetError("Couldn't create DirectInput event");
return (-1);
}
result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i],
SDL_DIevt[i]);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::SetEventNotification", result);
return (-1);
}
SDL_DIfun[i] = inputs[i].fun;
/* Acquire the device for input */
IDirectInputDevice2_Acquire(SDL_DIdev[i]);
/* Increment the number of devices we have */
++SDL_DIndev;
}
mouse_pressed = 0;
mouse_buttons_swapped = GetSystemMetrics(SM_SWAPBUTTON);
/* DirectInput is ready! */
return (0);
}
/* Clean up DirectInput */
static void
DX5_DInputQuit(_THIS)
{
int i;
if (dinput != NULL) {
/* Close and release all DirectInput devices */
for (i = 0; i < MAX_INPUTS; ++i) {
if (SDL_DIdev[i] != NULL) {
IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
IDirectInputDevice2_SetEventNotification(SDL_DIdev[i], NULL);
if (SDL_DIevt[i] != NULL) {
CloseHandle(SDL_DIevt[i]);
SDL_DIevt[i] = NULL;
}
IDirectInputDevice2_Release(SDL_DIdev[i]);
SDL_DIdev[i] = NULL;
}
}
/* Release DirectInput */
IDirectInput_Release(dinput);
dinput = NULL;
}
}
/* Flag to tell SDL whether or not we queued an event */
static int posted = 0;
/* Input event handler functions */
static void
handle_keyboard(const int numevents, DIDEVICEOBJECTDATA * keybuf)
{
int i;
SDL_keysym keysym;
/* Translate keyboard messages */
for (i = 0; i < numevents; ++i) {
if (keybuf[i].dwData & 0x80) {
posted = SDL_PrivateKeyboard(SDL_PRESSED,
TranslateKey(keybuf[i].dwOfs,
&keysym, 1));
} else {
posted = SDL_PrivateKeyboard(SDL_RELEASED,
TranslateKey(keybuf[i].dwOfs,
&keysym, 0));
}
}
}
static void
handle_mouse(const int numevents, DIDEVICEOBJECTDATA * ptrbuf)
{
int i;
Sint16 xrel, yrel;
Uint8 state;
Uint8 button;
DWORD timestamp = 0;
/* Sanity check. Mailing list reports this being NULL unexpectedly. */
if (SDL_PublicSurface == NULL) {
return;
}
/* If we are in windowed mode, Windows is taking care of the mouse */
if ((SDL_PublicSurface->flags & SDL_INTERNALOPENGL) ||
!(SDL_PublicSurface->flags & SDL_FULLSCREEN)) {
return;
}
/* If the mouse was lost, regain some sense of mouse state */
if (mouse_lost) {
POINT mouse_pos;
Uint8 old_state;
Uint8 new_state;
/* Set ourselves up with the current cursor position */
GetCursorPos(&mouse_pos);
ScreenToClient(SDL_Window, &mouse_pos);
posted = SDL_PrivateMouseMotion(0, 0,
(Sint16) mouse_pos.x,
(Sint16) mouse_pos.y);
/* Check for mouse button changes */
old_state = SDL_GetMouseState(NULL, NULL);
new_state = 0;
{ /* Get the new DirectInput button state for the mouse */
DIMOUSESTATE distate;
HRESULT result;
result = IDirectInputDevice2_GetDeviceState(SDL_DIdev[1],
sizeof(distate),
&distate);
if (result != DI_OK) {
/* Try again next time */
SetDIerror("IDirectInputDevice2::GetDeviceState", result);
return;
}
for (i = 3; i >= 0; --i) {
if ((distate.rgbButtons[i] & 0x80) == 0x80) {
new_state |= 0x01;
}
new_state <<= 1;
}
}
for (i = 0; i < 8; ++i) {
if ((old_state & 0x01) != (new_state & 0x01)) {
button = (Uint8) (i + 1);
/* Button #2 on two button mice is button 3
(the middle button is button 2)
*/
if (button == 2) {
button = 3;
} else if (button == 3) {
button = 2;
}
if (new_state & 0x01) {
/* Grab mouse so we get mouse-up */
if (++mouse_pressed > 0) {
SetCapture(SDL_Window);
}
state = SDL_PRESSED;
} else {
/* Release mouse after all mouse-ups */
if (--mouse_pressed <= 0) {
ReleaseCapture();
mouse_pressed = 0;
}
state = SDL_RELEASED;
}
if (mouse_buttons_swapped) {
if (button == 1)
button = 3;
else if (button == 3)
button = 1;
}
posted = SDL_PrivateMouseButton(state, button, 0, 0);
}
old_state >>= 1;
new_state >>= 1;
}
mouse_lost = 0;
return;
}
/* Translate mouse messages */
xrel = 0;
yrel = 0;
for (i = 0; i < (int) numevents; ++i) {
switch (ptrbuf[i].dwOfs) {
case DIMOFS_X:
if (timestamp != ptrbuf[i].dwTimeStamp) {
if (xrel || yrel) {
posted = SDL_PrivateMouseMotion(0, 1, xrel, yrel);
xrel = 0;
yrel = 0;
}
timestamp = ptrbuf[i].dwTimeStamp;
}
xrel += (Sint16) ptrbuf[i].dwData;
break;
case DIMOFS_Y:
if (timestamp != ptrbuf[i].dwTimeStamp) {
if (xrel || yrel) {
posted = SDL_PrivateMouseMotion(0, 1, xrel, yrel);
xrel = 0;
yrel = 0;
}
timestamp = ptrbuf[i].dwTimeStamp;
}
yrel += (Sint16) ptrbuf[i].dwData;
break;
case DIMOFS_Z:
if (xrel || yrel) {
posted = SDL_PrivateMouseMotion(0, 1, xrel, yrel);
xrel = 0;
yrel = 0;
}
timestamp = 0;
if ((int) ptrbuf[i].dwData > 0)
button = SDL_BUTTON_WHEELUP;
else
button = SDL_BUTTON_WHEELDOWN;
posted = SDL_PrivateMouseButton(SDL_PRESSED, button, 0, 0);
posted |= SDL_PrivateMouseButton(SDL_RELEASED, button, 0, 0);
break;
case DIMOFS_BUTTON0:
case DIMOFS_BUTTON1:
case DIMOFS_BUTTON2:
case DIMOFS_BUTTON3:
if (xrel || yrel) {
posted = SDL_PrivateMouseMotion(0, 1, xrel, yrel);
xrel = 0;
yrel = 0;
}
timestamp = 0;
button = (Uint8) (ptrbuf[i].dwOfs - DIMOFS_BUTTON0) + 1;
/* Button #2 on two button mice is button 3
(the middle button is button 2)
*/
if (button == 2) {
button = 3;
} else if (button == 3) {
button = 2;
}
if (ptrbuf[i].dwData & 0x80) {
/* Grab mouse so we get mouse-up */
if (++mouse_pressed > 0) {
SetCapture(SDL_Window);
}
state = SDL_PRESSED;
} else {
/* Release mouse after all mouse-ups */
if (--mouse_pressed <= 0) {
ReleaseCapture();
mouse_pressed = 0;
}
state = SDL_RELEASED;
}
if (mouse_buttons_swapped) {
if (button == 1)
button = 3;
else if (button == 3)
button = 1;
}
posted = SDL_PrivateMouseButton(state, button, 0, 0);
break;
}
}
if (xrel || yrel) {
posted = SDL_PrivateMouseMotion(0, 1, xrel, yrel);
}
}
/* The main Win32 event handler */
LRESULT
DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
#ifdef WM_ACTIVATEAPP
case WM_ACTIVATEAPP:
{
int i, active;
active = (wParam && (GetForegroundWindow() == hwnd));
if (active) {
for (i = 0; SDL_DIdev[i]; ++i) {
IDirectInputDevice2_Acquire(SDL_DIdev[i]);
}
} else {
for (i = 0; SDL_DIdev[i]; ++i) {
IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
}
mouse_lost = 1;
}
}
break;
#endif /* WM_ACTIVATEAPP */
#ifdef WM_DISPLAYCHANGE
case WM_DISPLAYCHANGE:
{
WPARAM BitsPerPixel;
WORD SizeX, SizeY;
/* Ack! The display changed size and/or depth! */
SizeX = LOWORD(lParam);
SizeY = HIWORD(lParam);
BitsPerPixel = wParam;
/* We cause this message when we go fullscreen */
}
break;
#endif /* WM_DISPLAYCHANGE */
/* The keyboard is handled via DirectInput */
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
{
/* Pass syskey to DefWindwoProc (ALT-F4, etc.) */
}
break;
case WM_KEYUP:
case WM_KEYDOWN:
{
/* Ignore windows keyboard messages */ ;
}
return (0);
#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
/* Don't allow screen savers or monitor power downs.
This is because they quietly clear DirectX surfaces.
It would be better to allow the application to
decide whether or not to blow these off, but the
semantics of SDL_PrivateSysWMEvent() don't allow
the application that choice.
*/
case WM_SYSCOMMAND:
{
if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
(wParam & 0xFFF0) == SC_MONITORPOWER)
return (0);
}
/* Fall through to default processing */
#endif /* SC_SCREENSAVE || SC_MONITORPOWER */
default:
{
/* Only post the event if we're watching for it */
if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
SDL_SysWMmsg wmmsg;
SDL_VERSION(&wmmsg.version);
wmmsg.hwnd = hwnd;
wmmsg.msg = msg;
wmmsg.wParam = wParam;
wmmsg.lParam = lParam;
posted = SDL_PrivateSysWMEvent(&wmmsg);
/* DJM: If the user isn't watching for private
messages in her SDL event loop, then pass it
along to any win32 specific window proc.
*/
} else if (userWindowProc) {
return CallWindowProc(userWindowProc, hwnd, msg, wParam,
lParam);
}
}
break;
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
/* This function checks the windows message queue and DirectInput and returns
1 if there was input, 0 if there was no input, or -1 if the application has
posted a quit message.
*/
static int
DX5_CheckInput(_THIS, int timeout, BOOL processInput)
{
MSG msg;
int i;
HRESULT result;
DWORD event;
/* Check the normal windows queue (highest preference) */
posted = 0;
while (!posted && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
} else {
return (-1);
}
}
if (posted) {
return (1);
}
/* Pump the DirectInput flow */
if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
for (i = 0; i < SDL_DIndev; ++i) {
result = IDirectInputDevice2_Poll(SDL_DIdev[i]);
if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED)) {
if (SDL_strcmp(inputs[i].name, "mouse") == 0) {
mouse_lost = 1;
}
IDirectInputDevice2_Acquire(SDL_DIdev[i]);
IDirectInputDevice2_Poll(SDL_DIdev[i]);
}
}
}
/* Wait for messages and input events */
event = MsgWaitForMultipleObjects(SDL_DIndev, SDL_DIevt, FALSE,
timeout, QS_ALLEVENTS);
if ((event >= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0 + SDL_DIndev))) {
DWORD numevents;
static DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
event -= WAIT_OBJECT_0;
numevents = INPUT_QSIZE;
result =
IDirectInputDevice2_GetDeviceData(SDL_DIdev[event],
sizeof(DIDEVICEOBJECTDATA),
evtbuf, &numevents, 0);
if ((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED)) {
if (SDL_strcmp(inputs[event].name, "mouse") == 0) {
mouse_lost = 1;
}
IDirectInputDevice2_Acquire(SDL_DIdev[event]);
result =
IDirectInputDevice2_GetDeviceData(SDL_DIdev[event],
sizeof
(DIDEVICEOBJECTDATA),
evtbuf, &numevents, 0);
}
/* Handle the events */
if (result == DI_OK && processInput) {
/* Note: This can post multiple events to event queue
*/
(*SDL_DIfun[event]) ((int) numevents, evtbuf);
return (1);
}
}
if (event != WAIT_TIMEOUT) {
/* Maybe there was a windows message? */
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (GetMessage(&msg, NULL, 0, 0) > 0) {
DispatchMessage(&msg);
} else {
return (-1);
}
return (1);
}
}
return (0);
}
/* Change cooperative level based on whether or not we are fullscreen */
void
DX5_DInputReset(_THIS, int fullscreen)
{
DWORD level;
int i;
HRESULT result;
HWND topwnd;
for (i = 0; i < MAX_INPUTS; ++i) {
if (SDL_DIdev[i] != NULL) {
if (fullscreen) {
level = inputs[i].raw_level;
} else {
level = inputs[i].win_level;
}
IDirectInputDevice2_Unacquire(SDL_DIdev[i]);
topwnd = GetTopLevelParent(SDL_Window);
result =
IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i],
topwnd, level);
IDirectInputDevice2_Acquire(SDL_DIdev[i]);
if (result != DI_OK) {
SetDIerror("DirectInputDevice::SetCooperativeLevel", result);
}
}
}
mouse_lost = 1;
/* Flush pending input */
DX5_CheckInput(this, 0, FALSE);
}
void
DX5_PumpEvents(_THIS)
{
/* Wait for messages and DirectInput */
while (DX5_CheckInput(this, 0, TRUE) > 0) {
/* Loop and check again */ ;
}
}
void
DX5_InitOSKeymap(_THIS)
{
#ifndef DIK_PAUSE
#define DIK_PAUSE 0xC5
#endif
#ifndef DIK_OEM_102
#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */
#endif
int i;
/* Map the DIK scancodes to SDL keysyms */
for (i = 0; i < SDL_arraysize(DIK_keymap); ++i)
DIK_keymap[i] = 0;
/* Defined DIK_* constants */
DIK_keymap[DIK_ESCAPE] = SDLK_ESCAPE;
DIK_keymap[DIK_1] = SDLK_1;
DIK_keymap[DIK_2] = SDLK_2;
DIK_keymap[DIK_3] = SDLK_3;
DIK_keymap[DIK_4] = SDLK_4;
DIK_keymap[DIK_5] = SDLK_5;
DIK_keymap[DIK_6] = SDLK_6;
DIK_keymap[DIK_7] = SDLK_7;
DIK_keymap[DIK_8] = SDLK_8;
DIK_keymap[DIK_9] = SDLK_9;
DIK_keymap[DIK_0] = SDLK_0;
DIK_keymap[DIK_MINUS] = SDLK_MINUS;
DIK_keymap[DIK_EQUALS] = SDLK_EQUALS;
DIK_keymap[DIK_BACK] = SDLK_BACKSPACE;
DIK_keymap[DIK_TAB] = SDLK_TAB;
DIK_keymap[DIK_Q] = SDLK_q;
DIK_keymap[DIK_W] = SDLK_w;
DIK_keymap[DIK_E] = SDLK_e;
DIK_keymap[DIK_R] = SDLK_r;
DIK_keymap[DIK_T] = SDLK_t;
DIK_keymap[DIK_Y] = SDLK_y;
DIK_keymap[DIK_U] = SDLK_u;
DIK_keymap[DIK_I] = SDLK_i;
DIK_keymap[DIK_O] = SDLK_o;
DIK_keymap[DIK_P] = SDLK_p;
DIK_keymap[DIK_LBRACKET] = SDLK_LEFTBRACKET;
DIK_keymap[DIK_RBRACKET] = SDLK_RIGHTBRACKET;
DIK_keymap[DIK_RETURN] = SDLK_RETURN;
DIK_keymap[DIK_LCONTROL] = SDLK_LCTRL;
DIK_keymap[DIK_A] = SDLK_a;
DIK_keymap[DIK_S] = SDLK_s;
DIK_keymap[DIK_D] = SDLK_d;
DIK_keymap[DIK_F] = SDLK_f;
DIK_keymap[DIK_G] = SDLK_g;
DIK_keymap[DIK_H] = SDLK_h;
DIK_keymap[DIK_J] = SDLK_j;
DIK_keymap[DIK_K] = SDLK_k;
DIK_keymap[DIK_L] = SDLK_l;
DIK_keymap[DIK_SEMICOLON] = SDLK_SEMICOLON;
DIK_keymap[DIK_APOSTROPHE] = SDLK_QUOTE;
DIK_keymap[DIK_GRAVE] = SDLK_BACKQUOTE;
DIK_keymap[DIK_LSHIFT] = SDLK_LSHIFT;
DIK_keymap[DIK_BACKSLASH] = SDLK_BACKSLASH;
DIK_keymap[DIK_OEM_102] = SDLK_BACKSLASH;
DIK_keymap[DIK_Z] = SDLK_z;
DIK_keymap[DIK_X] = SDLK_x;
DIK_keymap[DIK_C] = SDLK_c;
DIK_keymap[DIK_V] = SDLK_v;
DIK_keymap[DIK_B] = SDLK_b;
DIK_keymap[DIK_N] = SDLK_n;
DIK_keymap[DIK_M] = SDLK_m;
DIK_keymap[DIK_COMMA] = SDLK_COMMA;
DIK_keymap[DIK_PERIOD] = SDLK_PERIOD;
DIK_keymap[DIK_SLASH] = SDLK_SLASH;
DIK_keymap[DIK_RSHIFT] = SDLK_RSHIFT;
DIK_keymap[DIK_MULTIPLY] = SDLK_KP_MULTIPLY;
DIK_keymap[DIK_LMENU] = SDLK_LALT;
DIK_keymap[DIK_SPACE] = SDLK_SPACE;
DIK_keymap[DIK_CAPITAL] = SDLK_CAPSLOCK;
DIK_keymap[DIK_F1] = SDLK_F1;
DIK_keymap[DIK_F2] = SDLK_F2;
DIK_keymap[DIK_F3] = SDLK_F3;
DIK_keymap[DIK_F4] = SDLK_F4;
DIK_keymap[DIK_F5] = SDLK_F5;
DIK_keymap[DIK_F6] = SDLK_F6;
DIK_keymap[DIK_F7] = SDLK_F7;
DIK_keymap[DIK_F8] = SDLK_F8;
DIK_keymap[DIK_F9] = SDLK_F9;
DIK_keymap[DIK_F10] = SDLK_F10;
DIK_keymap[DIK_NUMLOCK] = SDLK_NUMLOCK;
DIK_keymap[DIK_SCROLL] = SDLK_SCROLLOCK;
DIK_keymap[DIK_NUMPAD7] = SDLK_KP7;
DIK_keymap[DIK_NUMPAD8] = SDLK_KP8;
DIK_keymap[DIK_NUMPAD9] = SDLK_KP9;
DIK_keymap[DIK_SUBTRACT] = SDLK_KP_MINUS;
DIK_keymap[DIK_NUMPAD4] = SDLK_KP4;
DIK_keymap[DIK_NUMPAD5] = SDLK_KP5;
DIK_keymap[DIK_NUMPAD6] = SDLK_KP6;
DIK_keymap[DIK_ADD] = SDLK_KP_PLUS;
DIK_keymap[DIK_NUMPAD1] = SDLK_KP1;
DIK_keymap[DIK_NUMPAD2] = SDLK_KP2;
DIK_keymap[DIK_NUMPAD3] = SDLK_KP3;
DIK_keymap[DIK_NUMPAD0] = SDLK_KP0;
DIK_keymap[DIK_DECIMAL] = SDLK_KP_PERIOD;
DIK_keymap[DIK_F11] = SDLK_F11;
DIK_keymap[DIK_F12] = SDLK_F12;
DIK_keymap[DIK_F13] = SDLK_F13;
DIK_keymap[DIK_F14] = SDLK_F14;
DIK_keymap[DIK_F15] = SDLK_F15;
DIK_keymap[DIK_NUMPADEQUALS] = SDLK_KP_EQUALS;
DIK_keymap[DIK_NUMPADENTER] = SDLK_KP_ENTER;
DIK_keymap[DIK_RCONTROL] = SDLK_RCTRL;
DIK_keymap[DIK_DIVIDE] = SDLK_KP_DIVIDE;
DIK_keymap[DIK_SYSRQ] = SDLK_PRINT;
DIK_keymap[DIK_RMENU] = SDLK_RALT;
DIK_keymap[DIK_PAUSE] = SDLK_PAUSE;
DIK_keymap[DIK_HOME] = SDLK_HOME;
DIK_keymap[DIK_UP] = SDLK_UP;
DIK_keymap[DIK_PRIOR] = SDLK_PAGEUP;
DIK_keymap[DIK_LEFT] = SDLK_LEFT;
DIK_keymap[DIK_RIGHT] = SDLK_RIGHT;
DIK_keymap[DIK_END] = SDLK_END;
DIK_keymap[DIK_DOWN] = SDLK_DOWN;
DIK_keymap[DIK_NEXT] = SDLK_PAGEDOWN;
DIK_keymap[DIK_INSERT] = SDLK_INSERT;
DIK_keymap[DIK_DELETE] = SDLK_DELETE;
DIK_keymap[DIK_LWIN] = SDLK_LMETA;
DIK_keymap[DIK_RWIN] = SDLK_RMETA;
DIK_keymap[DIK_APPS] = SDLK_MENU;
}
static SDL_keysym *
TranslateKey(UINT scancode, SDL_keysym * keysym, int pressed)
{
/* Set the keysym information */
keysym->scancode = (unsigned char) scancode;
keysym->sym = DIK_keymap[scancode];
keysym->mod = KMOD_NONE;
keysym->unicode = 0;
if (pressed && SDL_TranslateUNICODE) {
UINT vkey;
#ifndef NO_GETKEYBOARDSTATE
BYTE keystate[256];
Uint16 wchars[2];
#endif
vkey = MapVirtualKey(scancode, 1);
#ifdef NO_GETKEYBOARDSTATE
/* Uh oh, better hope the vkey is close enough.. */
keysym->unicode = vkey;
#else
GetKeyboardState(keystate);
if (SDL_ToUnicode
(vkey, scancode, keystate, wchars,
sizeof(wchars) / sizeof(wchars[0]), 0) == 1) {
keysym->unicode = wchars[0];
}
#endif /* NO_GETKEYBOARDSTATE */
}
return (keysym);
}
int
DX5_CreateWindow(_THIS)
{
char *windowid = SDL_getenv("SDL_WINDOWID");
int i;
/* Clear out DirectInput variables in case we fail */
for (i = 0; i < MAX_INPUTS; ++i) {
SDL_DIdev[i] = NULL;
SDL_DIevt[i] = NULL;
SDL_DIfun[i] = NULL;
}
SDL_RegisterApp(NULL, 0, 0);
SDL_windowid = (windowid != NULL);
if (SDL_windowid) {
SDL_Window = (HWND) SDL_strtoull(windowid, NULL, 0);
if (SDL_Window == NULL) {
SDL_SetError("Couldn't get user specified window");
return (-1);
}
/* DJM: we want all event's for the user specified
window to be handled by SDL.
*/
userWindowProc =
(WNDPROCTYPE) GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);
SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR) WinMessage);
} else {
SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
| WS_MINIMIZEBOX), CW_USEDEFAULT,
CW_USEDEFAULT, 0, 0, NULL, NULL,
SDL_Instance, NULL);
if (SDL_Window == NULL) {
SDL_SetError("Couldn't create window");
return (-1);
}
ShowWindow(SDL_Window, SW_HIDE);
}
/* Initialize DirectInput */
if (DX5_DInputInit(this) < 0) {
return (-1);
}
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
/* Ready to roll */
return (0);
}
void
DX5_DestroyWindow(_THIS)
{
/* Close down DirectInput */
DX5_DInputQuit(this);
/* Destroy our window */
if (SDL_windowid) {
SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR) userWindowProc);
} else {
DestroyWindow(SDL_Window);
}
SDL_UnregisterApp();
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#include "../wincommon/SDL_lowvideo.h"
/* Variables and functions exported by SDL_dx5events.c to other parts
of the native video subsystem (SDL_dx5video.c)
*/
extern LONG
DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern int DX5_CreateWindow(_THIS);
extern void DX5_DestroyWindow(_THIS);
extern void DX5_PumpEvents(_THIS);
extern void DX5_InitOSKeymap(_THIS);
extern void DX5_DInputReset(_THIS, int fullscreen);
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#include "directx.h"
/* Not yet in the mingw32 cross-compile headers */
#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif
#include "SDL_timer.h"
#include "SDL_events.h"
#include "SDL_syswm.h"
#include "../SDL_sysvideo.h"
#include "../SDL_blit.h"
#include "../SDL_pixels_c.h"
#include "SDL_dx5video.h"
#include "../wincommon/SDL_syswm_c.h"
#include "../wincommon/SDL_sysmouse_c.h"
#include "SDL_dx5events_c.h"
#include "SDL_dx5yuv_c.h"
#include "../wincommon/SDL_wingl_c.h"
#ifdef _WIN32_WCE
#define NO_CHANGEDISPLAYSETTINGS
#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
/* DirectX function pointers for video and events */
HRESULT(WINAPI * DDrawCreate) (GUID FAR * lpGUID, LPDIRECTDRAW FAR * lplpDD,
IUnknown FAR * pUnkOuter);
HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
LPDIRECTINPUT * ppDI, LPUNKNOWN punkOuter);
/* This is the rect EnumModes2 uses */
struct DX5EnumRect
{
SDL_Rect r;
int refreshRate;
struct DX5EnumRect *next;
};
static struct DX5EnumRect *enumlists[NUM_MODELISTS];
/*
* Experimentally determined values for c_cfDI* constants used in DirectX 5.0
*/
/* Keyboard */
static DIOBJECTDATAFORMAT KBD_fmt[] = {
{&GUID_Key, 0, 0x8000000C, 0x00000000},
{&GUID_Key, 1, 0x8000010C, 0x00000000},
{&GUID_Key, 2, 0x8000020C, 0x00000000},
{&GUID_Key, 3, 0x8000030C, 0x00000000},
{&GUID_Key, 4, 0x8000040C, 0x00000000},
{&GUID_Key, 5, 0x8000050C, 0x00000000},
{&GUID_Key, 6, 0x8000060C, 0x00000000},
{&GUID_Key, 7, 0x8000070C, 0x00000000},
{&GUID_Key, 8, 0x8000080C, 0x00000000},
{&GUID_Key, 9, 0x8000090C, 0x00000000},
{&GUID_Key, 10, 0x80000A0C, 0x00000000},
{&GUID_Key, 11, 0x80000B0C, 0x00000000},
{&GUID_Key, 12, 0x80000C0C, 0x00000000},
{&GUID_Key, 13, 0x80000D0C, 0x00000000},
{&GUID_Key, 14, 0x80000E0C, 0x00000000},
{&GUID_Key, 15, 0x80000F0C, 0x00000000},
{&GUID_Key, 16, 0x8000100C, 0x00000000},
{&GUID_Key, 17, 0x8000110C, 0x00000000},
{&GUID_Key, 18, 0x8000120C, 0x00000000},
{&GUID_Key, 19, 0x8000130C, 0x00000000},
{&GUID_Key, 20, 0x8000140C, 0x00000000},
{&GUID_Key, 21, 0x8000150C, 0x00000000},
{&GUID_Key, 22, 0x8000160C, 0x00000000},
{&GUID_Key, 23, 0x8000170C, 0x00000000},
{&GUID_Key, 24, 0x8000180C, 0x00000000},
{&GUID_Key, 25, 0x8000190C, 0x00000000},
{&GUID_Key, 26, 0x80001A0C, 0x00000000},
{&GUID_Key, 27, 0x80001B0C, 0x00000000},
{&GUID_Key, 28, 0x80001C0C, 0x00000000},
{&GUID_Key, 29, 0x80001D0C, 0x00000000},
{&GUID_Key, 30, 0x80001E0C, 0x00000000},
{&GUID_Key, 31, 0x80001F0C, 0x00000000},
{&GUID_Key, 32, 0x8000200C, 0x00000000},
{&GUID_Key, 33, 0x8000210C, 0x00000000},
{&GUID_Key, 34, 0x8000220C, 0x00000000},
{&GUID_Key, 35, 0x8000230C, 0x00000000},
{&GUID_Key, 36, 0x8000240C, 0x00000000},
{&GUID_Key, 37, 0x8000250C, 0x00000000},
{&GUID_Key, 38, 0x8000260C, 0x00000000},
{&GUID_Key, 39, 0x8000270C, 0x00000000},
{&GUID_Key, 40, 0x8000280C, 0x00000000},
{&GUID_Key, 41, 0x8000290C, 0x00000000},
{&GUID_Key, 42, 0x80002A0C, 0x00000000},
{&GUID_Key, 43, 0x80002B0C, 0x00000000},
{&GUID_Key, 44, 0x80002C0C, 0x00000000},
{&GUID_Key, 45, 0x80002D0C, 0x00000000},
{&GUID_Key, 46, 0x80002E0C, 0x00000000},
{&GUID_Key, 47, 0x80002F0C, 0x00000000},
{&GUID_Key, 48, 0x8000300C, 0x00000000},
{&GUID_Key, 49, 0x8000310C, 0x00000000},
{&GUID_Key, 50, 0x8000320C, 0x00000000},
{&GUID_Key, 51, 0x8000330C, 0x00000000},
{&GUID_Key, 52, 0x8000340C, 0x00000000},
{&GUID_Key, 53, 0x8000350C, 0x00000000},
{&GUID_Key, 54, 0x8000360C, 0x00000000},
{&GUID_Key, 55, 0x8000370C, 0x00000000},
{&GUID_Key, 56, 0x8000380C, 0x00000000},
{&GUID_Key, 57, 0x8000390C, 0x00000000},
{&GUID_Key, 58, 0x80003A0C, 0x00000000},
{&GUID_Key, 59, 0x80003B0C, 0x00000000},
{&GUID_Key, 60, 0x80003C0C, 0x00000000},
{&GUID_Key, 61, 0x80003D0C, 0x00000000},
{&GUID_Key, 62, 0x80003E0C, 0x00000000},
{&GUID_Key, 63, 0x80003F0C, 0x00000000},
{&GUID_Key, 64, 0x8000400C, 0x00000000},
{&GUID_Key, 65, 0x8000410C, 0x00000000},
{&GUID_Key, 66, 0x8000420C, 0x00000000},
{&GUID_Key, 67, 0x8000430C, 0x00000000},
{&GUID_Key, 68, 0x8000440C, 0x00000000},
{&GUID_Key, 69, 0x8000450C, 0x00000000},
{&GUID_Key, 70, 0x8000460C, 0x00000000},
{&GUID_Key, 71, 0x8000470C, 0x00000000},
{&GUID_Key, 72, 0x8000480C, 0x00000000},
{&GUID_Key, 73, 0x8000490C, 0x00000000},
{&GUID_Key, 74, 0x80004A0C, 0x00000000},
{&GUID_Key, 75, 0x80004B0C, 0x00000000},
{&GUID_Key, 76, 0x80004C0C, 0x00000000},
{&GUID_Key, 77, 0x80004D0C, 0x00000000},
{&GUID_Key, 78, 0x80004E0C, 0x00000000},
{&GUID_Key, 79, 0x80004F0C, 0x00000000},
{&GUID_Key, 80, 0x8000500C, 0x00000000},
{&GUID_Key, 81, 0x8000510C, 0x00000000},
{&GUID_Key, 82, 0x8000520C, 0x00000000},
{&GUID_Key, 83, 0x8000530C, 0x00000000},
{&GUID_Key, 84, 0x8000540C, 0x00000000},
{&GUID_Key, 85, 0x8000550C, 0x00000000},
{&GUID_Key, 86, 0x8000560C, 0x00000000},
{&GUID_Key, 87, 0x8000570C, 0x00000000},
{&GUID_Key, 88, 0x8000580C, 0x00000000},
{&GUID_Key, 89, 0x8000590C, 0x00000000},
{&GUID_Key, 90, 0x80005A0C, 0x00000000},
{&GUID_Key, 91, 0x80005B0C, 0x00000000},
{&GUID_Key, 92, 0x80005C0C, 0x00000000},
{&GUID_Key, 93, 0x80005D0C, 0x00000000},
{&GUID_Key, 94, 0x80005E0C, 0x00000000},
{&GUID_Key, 95, 0x80005F0C, 0x00000000},
{&GUID_Key, 96, 0x8000600C, 0x00000000},
{&GUID_Key, 97, 0x8000610C, 0x00000000},
{&GUID_Key, 98, 0x8000620C, 0x00000000},
{&GUID_Key, 99, 0x8000630C, 0x00000000},
{&GUID_Key, 100, 0x8000640C, 0x00000000},
{&GUID_Key, 101, 0x8000650C, 0x00000000},
{&GUID_Key, 102, 0x8000660C, 0x00000000},
{&GUID_Key, 103, 0x8000670C, 0x00000000},
{&GUID_Key, 104, 0x8000680C, 0x00000000},
{&GUID_Key, 105, 0x8000690C, 0x00000000},
{&GUID_Key, 106, 0x80006A0C, 0x00000000},
{&GUID_Key, 107, 0x80006B0C, 0x00000000},
{&GUID_Key, 108, 0x80006C0C, 0x00000000},
{&GUID_Key, 109, 0x80006D0C, 0x00000000},
{&GUID_Key, 110, 0x80006E0C, 0x00000000},
{&GUID_Key, 111, 0x80006F0C, 0x00000000},
{&GUID_Key, 112, 0x8000700C, 0x00000000},
{&GUID_Key, 113, 0x8000710C, 0x00000000},
{&GUID_Key, 114, 0x8000720C, 0x00000000},
{&GUID_Key, 115, 0x8000730C, 0x00000000},
{&GUID_Key, 116, 0x8000740C, 0x00000000},
{&GUID_Key, 117, 0x8000750C, 0x00000000},
{&GUID_Key, 118, 0x8000760C, 0x00000000},
{&GUID_Key, 119, 0x8000770C, 0x00000000},
{&GUID_Key, 120, 0x8000780C, 0x00000000},
{&GUID_Key, 121, 0x8000790C, 0x00000000},
{&GUID_Key, 122, 0x80007A0C, 0x00000000},
{&GUID_Key, 123, 0x80007B0C, 0x00000000},
{&GUID_Key, 124, 0x80007C0C, 0x00000000},
{&GUID_Key, 125, 0x80007D0C, 0x00000000},
{&GUID_Key, 126, 0x80007E0C, 0x00000000},
{&GUID_Key, 127, 0x80007F0C, 0x00000000},
{&GUID_Key, 128, 0x8000800C, 0x00000000},
{&GUID_Key, 129, 0x8000810C, 0x00000000},
{&GUID_Key, 130, 0x8000820C, 0x00000000},
{&GUID_Key, 131, 0x8000830C, 0x00000000},
{&GUID_Key, 132, 0x8000840C, 0x00000000},
{&GUID_Key, 133, 0x8000850C, 0x00000000},
{&GUID_Key, 134, 0x8000860C, 0x00000000},
{&GUID_Key, 135, 0x8000870C, 0x00000000},
{&GUID_Key, 136, 0x8000880C, 0x00000000},
{&GUID_Key, 137, 0x8000890C, 0x00000000},
{&GUID_Key, 138, 0x80008A0C, 0x00000000},
{&GUID_Key, 139, 0x80008B0C, 0x00000000},
{&GUID_Key, 140, 0x80008C0C, 0x00000000},
{&GUID_Key, 141, 0x80008D0C, 0x00000000},
{&GUID_Key, 142, 0x80008E0C, 0x00000000},
{&GUID_Key, 143, 0x80008F0C, 0x00000000},
{&GUID_Key, 144, 0x8000900C, 0x00000000},
{&GUID_Key, 145, 0x8000910C, 0x00000000},
{&GUID_Key, 146, 0x8000920C, 0x00000000},
{&GUID_Key, 147, 0x8000930C, 0x00000000},
{&GUID_Key, 148, 0x8000940C, 0x00000000},
{&GUID_Key, 149, 0x8000950C, 0x00000000},
{&GUID_Key, 150, 0x8000960C, 0x00000000},
{&GUID_Key, 151, 0x8000970C, 0x00000000},
{&GUID_Key, 152, 0x8000980C, 0x00000000},
{&GUID_Key, 153, 0x8000990C, 0x00000000},
{&GUID_Key, 154, 0x80009A0C, 0x00000000},
{&GUID_Key, 155, 0x80009B0C, 0x00000000},
{&GUID_Key, 156, 0x80009C0C, 0x00000000},
{&GUID_Key, 157, 0x80009D0C, 0x00000000},
{&GUID_Key, 158, 0x80009E0C, 0x00000000},
{&GUID_Key, 159, 0x80009F0C, 0x00000000},
{&GUID_Key, 160, 0x8000A00C, 0x00000000},
{&GUID_Key, 161, 0x8000A10C, 0x00000000},
{&GUID_Key, 162, 0x8000A20C, 0x00000000},
{&GUID_Key, 163, 0x8000A30C, 0x00000000},
{&GUID_Key, 164, 0x8000A40C, 0x00000000},
{&GUID_Key, 165, 0x8000A50C, 0x00000000},
{&GUID_Key, 166, 0x8000A60C, 0x00000000},
{&GUID_Key, 167, 0x8000A70C, 0x00000000},
{&GUID_Key, 168, 0x8000A80C, 0x00000000},
{&GUID_Key, 169, 0x8000A90C, 0x00000000},
{&GUID_Key, 170, 0x8000AA0C, 0x00000000},
{&GUID_Key, 171, 0x8000AB0C, 0x00000000},
{&GUID_Key, 172, 0x8000AC0C, 0x00000000},
{&GUID_Key, 173, 0x8000AD0C, 0x00000000},
{&GUID_Key, 174, 0x8000AE0C, 0x00000000},
{&GUID_Key, 175, 0x8000AF0C, 0x00000000},
{&GUID_Key, 176, 0x8000B00C, 0x00000000},
{&GUID_Key, 177, 0x8000B10C, 0x00000000},
{&GUID_Key, 178, 0x8000B20C, 0x00000000},
{&GUID_Key, 179, 0x8000B30C, 0x00000000},
{&GUID_Key, 180, 0x8000B40C, 0x00000000},
{&GUID_Key, 181, 0x8000B50C, 0x00000000},
{&GUID_Key, 182, 0x8000B60C, 0x00000000},
{&GUID_Key, 183, 0x8000B70C, 0x00000000},
{&GUID_Key, 184, 0x8000B80C, 0x00000000},
{&GUID_Key, 185, 0x8000B90C, 0x00000000},
{&GUID_Key, 186, 0x8000BA0C, 0x00000000},
{&GUID_Key, 187, 0x8000BB0C, 0x00000000},
{&GUID_Key, 188, 0x8000BC0C, 0x00000000},
{&GUID_Key, 189, 0x8000BD0C, 0x00000000},
{&GUID_Key, 190, 0x8000BE0C, 0x00000000},
{&GUID_Key, 191, 0x8000BF0C, 0x00000000},
{&GUID_Key, 192, 0x8000C00C, 0x00000000},
{&GUID_Key, 193, 0x8000C10C, 0x00000000},
{&GUID_Key, 194, 0x8000C20C, 0x00000000},
{&GUID_Key, 195, 0x8000C30C, 0x00000000},
{&GUID_Key, 196, 0x8000C40C, 0x00000000},
{&GUID_Key, 197, 0x8000C50C, 0x00000000},
{&GUID_Key, 198, 0x8000C60C, 0x00000000},
{&GUID_Key, 199, 0x8000C70C, 0x00000000},
{&GUID_Key, 200, 0x8000C80C, 0x00000000},
{&GUID_Key, 201, 0x8000C90C, 0x00000000},
{&GUID_Key, 202, 0x8000CA0C, 0x00000000},
{&GUID_Key, 203, 0x8000CB0C, 0x00000000},
{&GUID_Key, 204, 0x8000CC0C, 0x00000000},
{&GUID_Key, 205, 0x8000CD0C, 0x00000000},
{&GUID_Key, 206, 0x8000CE0C, 0x00000000},
{&GUID_Key, 207, 0x8000CF0C, 0x00000000},
{&GUID_Key, 208, 0x8000D00C, 0x00000000},
{&GUID_Key, 209, 0x8000D10C, 0x00000000},
{&GUID_Key, 210, 0x8000D20C, 0x00000000},
{&GUID_Key, 211, 0x8000D30C, 0x00000000},
{&GUID_Key, 212, 0x8000D40C, 0x00000000},
{&GUID_Key, 213, 0x8000D50C, 0x00000000},
{&GUID_Key, 214, 0x8000D60C, 0x00000000},
{&GUID_Key, 215, 0x8000D70C, 0x00000000},
{&GUID_Key, 216, 0x8000D80C, 0x00000000},
{&GUID_Key, 217, 0x8000D90C, 0x00000000},
{&GUID_Key, 218, 0x8000DA0C, 0x00000000},
{&GUID_Key, 219, 0x8000DB0C, 0x00000000},
{&GUID_Key, 220, 0x8000DC0C, 0x00000000},
{&GUID_Key, 221, 0x8000DD0C, 0x00000000},
{&GUID_Key, 222, 0x8000DE0C, 0x00000000},
{&GUID_Key, 223, 0x8000DF0C, 0x00000000},
{&GUID_Key, 224, 0x8000E00C, 0x00000000},
{&GUID_Key, 225, 0x8000E10C, 0x00000000},
{&GUID_Key, 226, 0x8000E20C, 0x00000000},
{&GUID_Key, 227, 0x8000E30C, 0x00000000},
{&GUID_Key, 228, 0x8000E40C, 0x00000000},
{&GUID_Key, 229, 0x8000E50C, 0x00000000},
{&GUID_Key, 230, 0x8000E60C, 0x00000000},
{&GUID_Key, 231, 0x8000E70C, 0x00000000},
{&GUID_Key, 232, 0x8000E80C, 0x00000000},
{&GUID_Key, 233, 0x8000E90C, 0x00000000},
{&GUID_Key, 234, 0x8000EA0C, 0x00000000},
{&GUID_Key, 235, 0x8000EB0C, 0x00000000},
{&GUID_Key, 236, 0x8000EC0C, 0x00000000},
{&GUID_Key, 237, 0x8000ED0C, 0x00000000},
{&GUID_Key, 238, 0x8000EE0C, 0x00000000},
{&GUID_Key, 239, 0x8000EF0C, 0x00000000},
{&GUID_Key, 240, 0x8000F00C, 0x00000000},
{&GUID_Key, 241, 0x8000F10C, 0x00000000},
{&GUID_Key, 242, 0x8000F20C, 0x00000000},
{&GUID_Key, 243, 0x8000F30C, 0x00000000},
{&GUID_Key, 244, 0x8000F40C, 0x00000000},
{&GUID_Key, 245, 0x8000F50C, 0x00000000},
{&GUID_Key, 246, 0x8000F60C, 0x00000000},
{&GUID_Key, 247, 0x8000F70C, 0x00000000},
{&GUID_Key, 248, 0x8000F80C, 0x00000000},
{&GUID_Key, 249, 0x8000F90C, 0x00000000},
{&GUID_Key, 250, 0x8000FA0C, 0x00000000},
{&GUID_Key, 251, 0x8000FB0C, 0x00000000},
{&GUID_Key, 252, 0x8000FC0C, 0x00000000},
{&GUID_Key, 253, 0x8000FD0C, 0x00000000},
{&GUID_Key, 254, 0x8000FE0C, 0x00000000},
{&GUID_Key, 255, 0x8000FF0C, 0x00000000},
};
const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
/* Mouse */
static DIOBJECTDATAFORMAT PTR_fmt[] = {
{&GUID_XAxis, 0, 0x00FFFF03, 0x00000000},
{&GUID_YAxis, 4, 0x00FFFF03, 0x00000000},
{&GUID_ZAxis, 8, 0x80FFFF03, 0x00000000},
{NULL, 12, 0x00FFFF0C, 0x00000000},
{NULL, 13, 0x00FFFF0C, 0x00000000},
{NULL, 14, 0x80FFFF0C, 0x00000000},
{NULL, 15, 0x80FFFF0C, 0x00000000},
};
const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
/* Joystick */
static DIOBJECTDATAFORMAT JOY_fmt[] = {
{&GUID_XAxis, 0, 0x80FFFF03, 0x00000100},
{&GUID_YAxis, 4, 0x80FFFF03, 0x00000100},
{&GUID_ZAxis, 8, 0x80FFFF03, 0x00000100},
{&GUID_RxAxis, 12, 0x80FFFF03, 0x00000100},
{&GUID_RyAxis, 16, 0x80FFFF03, 0x00000100},
{&GUID_RzAxis, 20, 0x80FFFF03, 0x00000100},
{&GUID_Slider, 24, 0x80FFFF03, 0x00000100},
{&GUID_Slider, 28, 0x80FFFF03, 0x00000100},
{&GUID_POV, 32, 0x80FFFF10, 0x00000000},
{&GUID_POV, 36, 0x80FFFF10, 0x00000000},
{&GUID_POV, 40, 0x80FFFF10, 0x00000000},
{&GUID_POV, 44, 0x80FFFF10, 0x00000000},
{NULL, 48, 0x80FFFF0C, 0x00000000},
{NULL, 49, 0x80FFFF0C, 0x00000000},
{NULL, 50, 0x80FFFF0C, 0x00000000},
{NULL, 51, 0x80FFFF0C, 0x00000000},
{NULL, 52, 0x80FFFF0C, 0x00000000},
{NULL, 53, 0x80FFFF0C, 0x00000000},
{NULL, 54, 0x80FFFF0C, 0x00000000},
{NULL, 55, 0x80FFFF0C, 0x00000000},
{NULL, 56, 0x80FFFF0C, 0x00000000},
{NULL, 57, 0x80FFFF0C, 0x00000000},
{NULL, 58, 0x80FFFF0C, 0x00000000},
{NULL, 59, 0x80FFFF0C, 0x00000000},
{NULL, 60, 0x80FFFF0C, 0x00000000},
{NULL, 61, 0x80FFFF0C, 0x00000000},
{NULL, 62, 0x80FFFF0C, 0x00000000},
{NULL, 63, 0x80FFFF0C, 0x00000000},
{NULL, 64, 0x80FFFF0C, 0x00000000},
{NULL, 65, 0x80FFFF0C, 0x00000000},
{NULL, 66, 0x80FFFF0C, 0x00000000},
{NULL, 67, 0x80FFFF0C, 0x00000000},
{NULL, 68, 0x80FFFF0C, 0x00000000},
{NULL, 69, 0x80FFFF0C, 0x00000000},
{NULL, 70, 0x80FFFF0C, 0x00000000},
{NULL, 71, 0x80FFFF0C, 0x00000000},
{NULL, 72, 0x80FFFF0C, 0x00000000},
{NULL, 73, 0x80FFFF0C, 0x00000000},
{NULL, 74, 0x80FFFF0C, 0x00000000},
{NULL, 75, 0x80FFFF0C, 0x00000000},
{NULL, 76, 0x80FFFF0C, 0x00000000},
{NULL, 77, 0x80FFFF0C, 0x00000000},
{NULL, 78, 0x80FFFF0C, 0x00000000},
{NULL, 79, 0x80FFFF0C, 0x00000000},
};
const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
/* Initialization/Query functions */
static int DX5_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat * format,
Uint32 flags);
static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface * current, int width,
int height, int bpp, Uint32 flags);
static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color * colors);
static int DX5_SetGammaRamp(_THIS, Uint16 * ramp);
static int DX5_GetGammaRamp(_THIS, Uint16 * ramp);
static void DX5_VideoQuit(_THIS);
/* Hardware surface functions */
static int DX5_AllocHWSurface(_THIS, SDL_Surface * surface);
static int DX5_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst);
static int DX5_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect,
Uint32 color);
static int DX5_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key);
static int DX5_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha);
static int DX5_LockHWSurface(_THIS, SDL_Surface * surface);
static void DX5_UnlockHWSurface(_THIS, SDL_Surface * surface);
static int DX5_FlipHWSurface(_THIS, SDL_Surface * surface);
static void DX5_FreeHWSurface(_THIS, SDL_Surface * surface);
static int DX5_AllocDDSurface(_THIS, SDL_Surface * surface,
LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
/* Windows message handling functions */
static void DX5_RealizePalette(_THIS);
static void DX5_PaletteChanged(_THIS, HWND window);
static void DX5_WinPAINT(_THIS, HDC hdc);
/* WinDIB driver functions for manipulating gamma ramps */
extern int DIB_SetGammaRamp(_THIS, Uint16 * ramp);
extern int DIB_GetGammaRamp(_THIS, Uint16 * ramp);
extern void DIB_QuitGamma(_THIS);
/* Functions for loading the DirectX functions dynamically */
static int DX5_loaded = 0;
static HINSTANCE DDrawDLL = NULL;
static HINSTANCE DInputDLL = NULL;
void
DX5_Unload(void)
{
if (--DX5_loaded == 0) {
if (DDrawDLL != NULL) {
FreeLibrary(DDrawDLL);
DDrawCreate = NULL;
DDrawDLL = NULL;
}
if (DInputDLL != NULL) {
FreeLibrary(DInputDLL);
DInputCreate = NULL;
DInputDLL = NULL;
}
}
}
int
DX5_Load(void)
{
int status = 0;
if (++DX5_loaded == 1) {
DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
if (DDrawDLL != NULL) {
DDrawCreate = (void *) GetProcAddress(DDrawDLL,
TEXT("DirectDrawCreate"));
}
DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
if (DInputDLL != NULL) {
DInputCreate = (void *) GetProcAddress(DInputDLL,
TEXT
("DirectInputCreateA"));
}
if (DDrawDLL && DDrawCreate && DInputDLL && DInputCreate) {
status = 0;
} else {
DX5_Unload();
status = -1;
}
}
return status;
}
/* DX5 driver bootstrap functions */
static int
DX5_Available(void)
{
int ddraw_ok = 0;
HRESULT(WINAPI * DDrawCreate) (GUID *, LPDIRECTDRAW *, IUnknown *);
LPDIRECTDRAW DDraw;
/* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
if (DX5_Load() < 0) {
return -1;
}
/* Try to create a valid DirectDraw object */
DDrawCreate = (void *) GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate"));
if ((DDrawCreate != NULL) && !FAILED(DDrawCreate(NULL, &DDraw, NULL))) {
if (!FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
NULL, DDSCL_NORMAL))) {
DDSURFACEDESC desc;
LPDIRECTDRAWSURFACE DDrawSurf;
LPDIRECTDRAWSURFACE3 DDrawSurf3;
/* Try to create a DirectDrawSurface3 object */
SDL_memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS;
desc.ddsCaps.dwCaps =
DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
if (!FAILED
(IDirectDraw_CreateSurface(DDraw, &desc, &DDrawSurf, NULL))) {
if (!FAILED
(IDirectDrawSurface_QueryInterface
(DDrawSurf, &IID_IDirectDrawSurface3,
(LPVOID *) & DDrawSurf3))) {
/* Yay! */
ddraw_ok = 1;
/* Clean up.. */
IDirectDrawSurface3_Release(DDrawSurf3);
}
IDirectDrawSurface_Release(DDrawSurf);
}
}
IDirectDraw_Release(DDraw);
}
DX5_Unload();
return ddraw_ok;
}
static void
DX5_DeleteDevice(SDL_VideoDevice * this)
{
/* Free DirectDraw object */
if (ddraw2 != NULL) {
IDirectDraw2_Release(ddraw2);
}
DX5_Unload();
if (this) {
if (this->hidden) {
SDL_free(this->hidden);
}
if (this->gl_data) {
SDL_free(this->gl_data);
}
SDL_free(this);
}
}
static SDL_VideoDevice *
DX5_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Load DirectX */
if (DX5_Load() < 0) {
return (NULL);
}
/* 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();
DX5_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 = DX5_VideoInit;
device->ListModes = DX5_ListModes;
device->SetVideoMode = DX5_SetVideoMode;
device->UpdateMouse = WIN_UpdateMouse;
device->CreateYUVOverlay = DX5_CreateYUVOverlay;
device->SetColors = DX5_SetColors;
device->UpdateRects = NULL;
device->VideoQuit = DX5_VideoQuit;
device->AllocHWSurface = DX5_AllocHWSurface;
device->CheckHWBlit = DX5_CheckHWBlit;
device->FillHWRect = DX5_FillHWRect;
device->SetHWColorKey = DX5_SetHWColorKey;
device->SetHWAlpha = DX5_SetHWAlpha;
device->LockHWSurface = DX5_LockHWSurface;
device->UnlockHWSurface = DX5_UnlockHWSurface;
device->FlipHWSurface = DX5_FlipHWSurface;
device->FreeHWSurface = DX5_FreeHWSurface;
device->SetGammaRamp = DX5_SetGammaRamp;
device->GetGammaRamp = DX5_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 = DX5_InitOSKeymap;
device->PumpEvents = DX5_PumpEvents;
/* Set up the windows message handling functions */
WIN_RealizePalette = DX5_RealizePalette;
WIN_PaletteChanged = DX5_PaletteChanged;
WIN_WinPAINT = DX5_WinPAINT;
HandleMessage = DX5_HandleMessage;
device->free = DX5_DeleteDevice;
/* We're finally ready */
return device;
}
VideoBootStrap DIRECTX_bootstrap = {
"directx", "Win95/98/2000 DirectX",
DX5_Available, DX5_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 HRESULT WINAPI
EnumModes2(DDSURFACEDESC * desc, VOID * udata)
{
SDL_VideoDevice *this = (SDL_VideoDevice *) udata;
struct DX5EnumRect *enumrect;
#if defined(NONAMELESSUNION)
int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
int refreshRate = desc->u2.dwRefreshRate;
#else
int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
int refreshRate = desc->dwRefreshRate;
#endif
int maxRefreshRate;
if (desc->dwWidth <= SDL_desktop_mode.dmPelsWidth &&
desc->dwHeight <= SDL_desktop_mode.dmPelsHeight) {
maxRefreshRate = SDL_desktop_mode.dmDisplayFrequency;
} else {
maxRefreshRate = 85; /* safe value? */
}
switch (bpp) {
case 8:
case 16:
case 24:
case 32:
bpp /= 8;
--bpp;
if (enumlists[bpp] &&
enumlists[bpp]->r.w == (Uint16) desc->dwWidth &&
enumlists[bpp]->r.h == (Uint16) desc->dwHeight) {
if (refreshRate > enumlists[bpp]->refreshRate &&
refreshRate <= maxRefreshRate) {
enumlists[bpp]->refreshRate = refreshRate;
#ifdef DDRAW_DEBUG
fprintf(stderr,
"New refresh rate for %d bpp: %dx%d at %d Hz\n",
(bpp + 1) * 8, (int) desc->dwWidth,
(int) desc->dwHeight, refreshRate);
#endif
}
break;
}
++SDL_nummodes[bpp];
enumrect =
(struct DX5EnumRect *) SDL_malloc(sizeof(struct DX5EnumRect));
if (!enumrect) {
SDL_OutOfMemory();
return (DDENUMRET_CANCEL);
}
enumrect->refreshRate = refreshRate;
enumrect->r.x = 0;
enumrect->r.y = 0;
enumrect->r.w = (Uint16) desc->dwWidth;
enumrect->r.h = (Uint16) desc->dwHeight;
enumrect->next = enumlists[bpp];
enumlists[bpp] = enumrect;
#ifdef DDRAW_DEBUG
fprintf(stderr, "New mode for %d bpp: %dx%d at %d Hz\n",
(bpp + 1) * 8, (int) desc->dwWidth, (int) desc->dwHeight,
refreshRate);
#endif
break;
}
return (DDENUMRET_OK);
}
void
SetDDerror(const char *function, int code)
{
static char *error;
static char errbuf[1024];
errbuf[0] = 0;
switch (code) {
case DDERR_GENERIC:
error = "Undefined error!";
break;
case DDERR_EXCEPTION:
error = "Exception encountered";
break;
case DDERR_INVALIDOBJECT:
error = "Invalid object";
break;
case DDERR_INVALIDPARAMS:
error = "Invalid parameters";
break;
case DDERR_NOTFOUND:
error = "Object not found";
break;
case DDERR_INVALIDRECT:
error = "Invalid rectangle";
break;
case DDERR_INVALIDCAPS:
error = "Invalid caps member";
break;
case DDERR_INVALIDPIXELFORMAT:
error = "Invalid pixel format";
break;
case DDERR_OUTOFMEMORY:
error = "Out of memory";
break;
case DDERR_OUTOFVIDEOMEMORY:
error = "Out of video memory";
break;
case DDERR_SURFACEBUSY:
error = "Surface busy";
break;
case DDERR_SURFACELOST:
error = "Surface was lost";
break;
case DDERR_WASSTILLDRAWING:
error = "DirectDraw is still drawing";
break;
case DDERR_INVALIDSURFACETYPE:
error = "Invalid surface type";
break;
case DDERR_NOEXCLUSIVEMODE:
error = "Not in exclusive access mode";
break;
case DDERR_NOPALETTEATTACHED:
error = "No palette attached";
break;
case DDERR_NOPALETTEHW:
error = "No palette hardware";
break;
case DDERR_NOT8BITCOLOR:
error = "Not 8-bit color";
break;
case DDERR_EXCLUSIVEMODEALREADYSET:
error = "Exclusive mode was already set";
break;
case DDERR_HWNDALREADYSET:
error = "Window handle already set";
break;
case DDERR_HWNDSUBCLASSED:
error = "Window handle is subclassed";
break;
case DDERR_NOBLTHW:
error = "No blit hardware";
break;
case DDERR_IMPLICITLYCREATED:
error = "Surface was implicitly created";
break;
case DDERR_INCOMPATIBLEPRIMARY:
error = "Incompatible primary surface";
break;
case DDERR_NOCOOPERATIVELEVELSET:
error = "No cooperative level set";
break;
case DDERR_NODIRECTDRAWHW:
error = "No DirectDraw hardware";
break;
case DDERR_NOEMULATION:
error = "No emulation available";
break;
case DDERR_NOFLIPHW:
error = "No flip hardware";
break;
case DDERR_NOTFLIPPABLE:
error = "Surface not flippable";
break;
case DDERR_PRIMARYSURFACEALREADYEXISTS:
error = "Primary surface already exists";
break;
case DDERR_UNSUPPORTEDMODE:
error = "Unsupported mode";
break;
case DDERR_WRONGMODE:
error = "Surface created in different mode";
break;
case DDERR_UNSUPPORTED:
error = "Operation not supported";
break;
case E_NOINTERFACE:
error = "Interface not present";
break;
default:
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
"%s: Unknown DirectDraw error: 0x%x", function, code);
break;
}
if (!errbuf[0]) {
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
error);
}
SDL_SetError("%s", errbuf);
return;
}
static int
DX5_UpdateVideoInfo(_THIS)
{
/* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
#if DIRECTDRAW_VERSION <= 0x300
#error Your version of DirectX must be greater than or equal to 5.0
#endif
#ifndef IDirectDrawGammaControl_SetGammaRamp
/*if gamma is undefined then we really have directx <= 0x500 */
DDCAPS DDCaps;
#else
DDCAPS_DX5 DDCaps;
#endif
HRESULT result;
/* Fill in our hardware acceleration capabilities */
SDL_memset(&DDCaps, 0, sizeof(DDCaps));
DDCaps.dwSize = sizeof(DDCaps);
result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *) & DDCaps, NULL);
if (result != DD_OK) {
SetDDerror("DirectDraw2::GetCaps", result);
return (-1);
}
this->info.hw_available = 1;
if ((DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT) {
this->info.blit_hw = 1;
}
if (((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT)) {
this->info.blit_hw_CC = 1;
}
if ((DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA) {
/* This is only for alpha channel, and DirectX 6
doesn't support 2D alpha blits yet, so set it 0
*/
this->info.blit_hw_A = 0;
}
if ((DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM) {
this->info.blit_sw = 1;
/* This isn't necessarily true, but the HEL will cover us */
this->info.blit_sw_CC = this->info.blit_hw_CC;
this->info.blit_sw_A = this->info.blit_hw_A;
}
if ((DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL) {
this->info.blit_fill = 1;
}
/* Find out how much video memory is available */
{
DDSCAPS ddsCaps;
DWORD total_mem;
ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
result = IDirectDraw2_GetAvailableVidMem(ddraw2,
&ddsCaps, &total_mem, NULL);
if (result != DD_OK) {
total_mem = DDCaps.dwVidMemTotal;
}
this->info.video_mem = total_mem / 1024;
}
return (0);
}
int
DX5_VideoInit(_THIS, SDL_PixelFormat * vformat)
{
HRESULT result;
LPDIRECTDRAW ddraw;
int i, j;
HDC hdc;
/* Intialize everything */
ddraw2 = NULL;
SDL_primary = NULL;
SDL_clipper = NULL;
SDL_palette = NULL;
for (i = 0; i < NUM_MODELISTS; ++i) {
SDL_nummodes[i] = 0;
SDL_modelist[i] = NULL;
SDL_modeindex[i] = 0;
}
colorchange_expected = 0;
/* Create the window */
if (DX5_CreateWindow(this) < 0) {
return (-1);
}
#if !SDL_AUDIO_DISABLED
DX5_SoundFocus(SDL_Window);
#endif
/* Create the DirectDraw object */
result = DDrawCreate(NULL, &ddraw, NULL);
if (result != DD_OK) {
SetDDerror("DirectDrawCreate", result);
return (-1);
}
result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
(LPVOID *) & ddraw2);
IDirectDraw_Release(ddraw);
if (result != DD_OK) {
SetDDerror("DirectDraw::QueryInterface", result);
return (-1);
}
/* Determine the screen depth */
hdc = GetDC(SDL_Window);
vformat->BitsPerPixel = GetDeviceCaps(hdc, PLANES) *
GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(SDL_Window, hdc);
#ifndef NO_CHANGEDISPLAYSETTINGS
/* 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;
#endif
/* Enumerate the available fullscreen modes */
for (i = 0; i < NUM_MODELISTS; ++i)
enumlists[i] = NULL;
result =
IDirectDraw2_EnumDisplayModes(ddraw2, DDEDM_REFRESHRATES, NULL, this,
EnumModes2);
if (result != DD_OK) {
SetDDerror("DirectDraw2::EnumDisplayModes", result);
return (-1);
}
for (i = 0; i < NUM_MODELISTS; ++i) {
struct DX5EnumRect *rect;
SDL_modelist[i] = (SDL_Rect **)
SDL_malloc((SDL_nummodes[i] + 1) * sizeof(SDL_Rect *));
if (SDL_modelist[i] == NULL) {
SDL_OutOfMemory();
return (-1);
}
for (j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next) {
SDL_modelist[i][j] = &rect->r;
}
SDL_modelist[i][j] = NULL;
if (SDL_nummodes[i] > 0) {
SDL_qsort(SDL_modelist[i], SDL_nummodes[i],
sizeof *SDL_modelist[i], cmpmodes);
}
}
/* Fill in some window manager capabilities */
this->info.wm_available = 1;
/* Fill in the video hardware capabilities */
DX5_UpdateVideoInfo(this);
return (0);
}
SDL_Rect **
DX5_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
{
int bpp;
bpp = format->BitsPerPixel;
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
/* FIXME: No support for 1 bpp or 4 bpp formats */
switch (bpp) { /* Does windows support other BPP? */
case 8:
case 16:
case 24:
case 32:
bpp = (bpp / 8) - 1;
if (SDL_nummodes[bpp] > 0)
return (SDL_modelist[bpp]);
/* Fall through */
default:
return ((SDL_Rect **) 0);
}
} else {
if (this->screen->format->BitsPerPixel == bpp) {
return ((SDL_Rect **) - 1);
} else {
return ((SDL_Rect **) 0);
}
}
}
/* Various screen update functions available */
static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect * rects);
static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
SDL_Surface *
DX5_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp, Uint32 flags)
{
SDL_Surface *video;
HRESULT result;
DWORD sharemode;
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);
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE dd_surface1;
LPDIRECTDRAWSURFACE3 dd_surface3;
SDL_resizing = 1;
#ifdef DDRAW_DEBUG
fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
#endif
/* Clean up any previous DirectDraw surfaces */
if (current->hwdata) {
this->FreeHWSurface(this, current);
current->hwdata = NULL;
}
if (SDL_primary != NULL) {
IDirectDrawSurface3_Release(SDL_primary);
SDL_primary = NULL;
}
#ifndef NO_CHANGEDISPLAYSETTINGS
/* Unset any previous OpenGL fullscreen mode */
if ((current->flags & (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) ==
(SDL_INTERNALOPENGL | SDL_FULLSCREEN)) {
ChangeDisplaySettings(NULL, 0);
}
#endif
/* Clean up any GL context that may be hanging around */
if (current->flags & SDL_INTERNALOPENGL) {
WIN_GL_ShutDown(this);
}
/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
if (flags & SDL_INTERNALOPENGL) {
Uint32 Rmask, Gmask, Bmask;
/* Recalculate the bitmasks if necessary */
if (bpp == current->format->BitsPerPixel) {
video = current;
} else {
switch (bpp) {
case 15:
case 16:
if (0 /*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;
Bmask = 0x00000000;
break;
}
video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
Rmask, Gmask, Bmask, 0);
if (video == NULL) {
SDL_OutOfMemory();
return (NULL);
}
}
/* Fill in part of the video surface */
video->flags = 0; /* Clear flags */
video->w = width;
video->h = height;
video->pitch = SDL_CalculatePitch(video);
#ifndef NO_CHANGEDISPLAYSETTINGS
/* Set fullscreen mode if appropriate.
Ugh, since our list of valid video modes comes from
the DirectX driver, we may not actually be able to
change to the desired resolution here.
FIXME: Should we do a closest match?
*/
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
DEVMODE settings;
BOOL changed;
SDL_memset(&settings, 0, sizeof(DEVMODE));
settings.dmSize = sizeof(DEVMODE);
settings.dmBitsPerPel = video->format->BitsPerPixel;
settings.dmPelsWidth = width;
settings.dmPelsHeight = height;
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (width <= (int) SDL_desktop_mode.dmPelsWidth
&& height <= (int) SDL_desktop_mode.dmPelsHeight) {
settings.dmDisplayFrequency =
SDL_desktop_mode.dmDisplayFrequency;
settings.dmFields |= DM_DISPLAYFREQUENCY;
}
changed =
(ChangeDisplaySettings(&settings, CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL);
if (!changed && (settings.dmFields & DM_DISPLAYFREQUENCY)) {
settings.dmFields &= ~DM_DISPLAYFREQUENCY;
changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN)
== DISP_CHANGE_SUCCESSFUL);
}
if (changed) {
video->flags |= SDL_FULLSCREEN;
SDL_fullscreen_mode = settings;
}
}
#endif /* !NO_CHANGEDISPLAYSETTINGS */
style = GetWindowLong(SDL_Window, GWL_STYLE);
style &= ~(resizestyle | WS_MAXIMIZE);
if (video->flags & SDL_FULLSCREEN) {
style &= ~windowstyle;
style |= directstyle;
} else {
if (flags & SDL_NOFRAME) {
style &= ~windowstyle;
style |= directstyle;
video->flags |= SDL_NOFRAME;
} else {
style &= ~directstyle;
style |= windowstyle;
if (flags & SDL_RESIZABLE) {
style |= resizestyle;
video->flags |= SDL_RESIZABLE;
}
}
#if WS_MAXIMIZE
if (IsZoomed(SDL_Window))
style |= WS_MAXIMIZE;
#endif
}
/* DJM: Don't piss of anyone who has setup his own window */
if (!SDL_windowid)
SetWindowLong(SDL_Window, GWL_STYLE, style);
/* Resize the window (copied from SDL WinDIB driver) */
if (!SDL_windowid && !IsZoomed(SDL_Window)) {
RECT bounds;
int x, y;
HWND top;
UINT swp_flags;
const char *window = NULL;
const char *center = NULL;
if (!SDL_windowX && !SDL_windowY) {
window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
center = SDL_getenv("SDL_VIDEO_CENTERED");
if (window) {
if (SDL_sscanf(window, "%d,%d", &x, &y) == 2) {
SDL_windowX = x;
SDL_windowY = y;
}
if (SDL_strcmp(window, "center") == 0) {
center = window;
}
}
}
swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
bounds.left = SDL_windowX;
bounds.top = SDL_windowY;
bounds.right = SDL_windowX + video->w;
bounds.bottom = SDL_windowY + video->h;
AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
(GetMenu(SDL_Window) != NULL), 0);
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
if ((flags & SDL_FULLSCREEN)) {
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
} else if (center) {
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
} else if (SDL_windowX || SDL_windowY || window) {
x = bounds.left;
y = bounds.top;
} else {
x = y = -1;
swp_flags |= SWP_NOMOVE;
}
if (flags & SDL_FULLSCREEN) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
}
SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
if (!(flags & SDL_FULLSCREEN)) {
SDL_windowX = SDL_bounds.left;
SDL_windowY = SDL_bounds.top;
}
SetForegroundWindow(SDL_Window);
}
SDL_resizing = 0;
/* Set up for OpenGL */
if (WIN_GL_SetupWindow(this) < 0) {
return (NULL);
}
video->flags |= SDL_INTERNALOPENGL;
return (video);
}
/* Set the appropriate window style */
style = GetWindowLong(SDL_Window, GWL_STYLE);
style &= ~(resizestyle | WS_MAXIMIZE);
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
style &= ~windowstyle;
style |= directstyle;
} else {
if (flags & SDL_NOFRAME) {
style &= ~windowstyle;
style |= directstyle;
} else {
style &= ~directstyle;
style |= windowstyle;
if (flags & SDL_RESIZABLE) {
style |= resizestyle;
}
}
#if WS_MAXIMIZE
if (IsZoomed(SDL_Window))
style |= WS_MAXIMIZE;
#endif
}
/* DJM: Don't piss of anyone who has setup his own window */
if (!SDL_windowid)
SetWindowLong(SDL_Window, GWL_STYLE, style);
/* Set DirectDraw sharing mode.. exclusive when fullscreen */
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
sharemode = DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT;
} else {
sharemode = DDSCL_NORMAL;
}
result = IDirectDraw2_SetCooperativeLevel(ddraw2, SDL_Window, sharemode);
if (result != DD_OK) {
SetDDerror("DirectDraw2::SetCooperativeLevel", result);
return (NULL);
}
/* Set the display mode, if we are in fullscreen mode */
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
RECT bounds;
struct DX5EnumRect *rect;
int maxRefreshRate;
/* Cover up desktop during mode change */
bounds.left = 0;
bounds.top = 0;
bounds.right = GetSystemMetrics(SM_CXSCREEN);
bounds.bottom = GetSystemMetrics(SM_CYSCREEN);
AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
(GetMenu(SDL_Window) != NULL), 0);
SetWindowPos(SDL_Window, HWND_TOPMOST, bounds.left, bounds.top,
bounds.right - bounds.left, bounds.bottom - bounds.top,
SWP_NOCOPYBITS);
ShowWindow(SDL_Window, SW_SHOW);
while (GetForegroundWindow() != SDL_Window) {
SetForegroundWindow(SDL_Window);
SDL_Delay(100);
}
/* find maximum monitor refresh rate for this resolution */
/* Dmitry Yakimov ftech@tula.net */
maxRefreshRate = 0; /* system default */
for (rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next) {
if ((width == rect->r.w) && (height == rect->r.h)) {
maxRefreshRate = rect->refreshRate;
break;
}
}
#ifdef DDRAW_DEBUG
fprintf(stderr, "refresh rate = %d Hz\n", maxRefreshRate);
#endif
result =
IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp,
maxRefreshRate, 0);
if (result != DD_OK) {
result =
IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0);
if (result != DD_OK) {
/* We couldn't set fullscreen mode, try window */
return (DX5_SetVideoMode
(this, current, width, height, bpp,
flags & ~SDL_FULLSCREEN));
}
}
DX5_DInputReset(this, 1);
} else {
DX5_DInputReset(this, 0);
}
DX5_UpdateVideoInfo(this);
/* Create a primary DirectDraw surface */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY);
if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
/* There's no windowed double-buffering */
flags &= ~SDL_DOUBLEBUF;
}
if ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX | DDSCAPS_FLIP);
ddsd.dwBackBufferCount = 1;
}
result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL);
if ((result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)) {
ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX | DDSCAPS_FLIP);
ddsd.dwBackBufferCount = 0;
result = IDirectDraw2_CreateSurface(ddraw2,
&ddsd, &dd_surface1, NULL);
}
if (result != DD_OK) {
SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
return (NULL);
}
result = IDirectDrawSurface_QueryInterface(dd_surface1,
&IID_IDirectDrawSurface3,
(LPVOID *) & SDL_primary);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface::QueryInterface", result);
return (NULL);
}
IDirectDrawSurface_Release(dd_surface1);
/* Get the format of the primary DirectDraw surface */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface::GetSurfaceDesc", result);
return (NULL);
}
if (!(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)) {
SDL_SetError("Primary DDRAW surface is not RGB format");
return (NULL);
}
/* Free old palette and create a new one if we're in 8-bit mode */
if (SDL_palette != NULL) {
IDirectDrawPalette_Release(SDL_palette);
SDL_palette = NULL;
}
#if defined(NONAMELESSUNION)
if (ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8) {
#else
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) {
#endif
int i;
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
/* We have access to the entire palette */
for (i = 0; i < 256; ++i) {
SDL_colors[i].peFlags = (PC_NOCOLLAPSE | PC_RESERVED);
SDL_colors[i].peRed = 0;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
} else {
/* First 10 colors are reserved by Windows */
for (i = 0; i < 10; ++i) {
SDL_colors[i].peFlags = PC_EXPLICIT;
SDL_colors[i].peRed = i;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
for (i = 10; i < (10 + 236); ++i) {
SDL_colors[i].peFlags = PC_NOCOLLAPSE;
SDL_colors[i].peRed = 0;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
/* Last 10 colors are reserved by Windows */
for (i = 246; i < 256; ++i) {
SDL_colors[i].peFlags = PC_EXPLICIT;
SDL_colors[i].peRed = i;
SDL_colors[i].peGreen = 0;
SDL_colors[i].peBlue = 0;
}
}
result = IDirectDraw2_CreatePalette(ddraw2,
(DDPCAPS_8BIT |
DDPCAPS_ALLOW256), SDL_colors,
&SDL_palette, NULL);
if (result != DD_OK) {
SetDDerror("DirectDraw2::CreatePalette", result);
return (NULL);
}
result = IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::SetPalette", result);
return (NULL);
}
}
/* Create our video surface using the same pixel format */
video = current;
if ((width != video->w) || (height != video->h)
|| (video->format->BitsPerPixel !=
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount)) {
#else
ddsd.ddpfPixelFormat.dwRGBBitCount)) {
#endif
SDL_FreeSurface(video);
video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
ddsd.ddpfPixelFormat.u2.dwRBitMask,
ddsd.ddpfPixelFormat.u3.dwGBitMask,
ddsd.ddpfPixelFormat.u4.dwBBitMask,
#else
ddsd.ddpfPixelFormat.dwRGBBitCount,
ddsd.ddpfPixelFormat.dwRBitMask,
ddsd.ddpfPixelFormat.dwGBitMask,
ddsd.ddpfPixelFormat.dwBBitMask,
#endif
0);
if (video == NULL) {
SDL_OutOfMemory();
return (NULL);
}
video->w = width;
video->h = height;
video->pitch = 0;
}
video->flags = 0; /* Clear flags */
/* If not fullscreen, locking is possible, but it doesn't do what
the caller really expects -- if the locked surface is written to,
the appropriate portion of the entire screen is modified, not
the application window, as we would like.
Note that it is still possible to write directly to display
memory, but the application must respect the clip list of
the surface. There might be some odd timing interactions
involving clip list updates and background refreshing as
Windows moves other windows across our window.
We currently don't support this, even though it might be a
good idea since BeOS has an implementation of BDirectWindow
that does the same thing. This would be most useful for
applications that do complete screen updates every frame.
-- Fixme?
*/
if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
/* Necessary if we're going from fullscreen to window */
if (video->pixels == NULL) {
video->pitch = (width * video->format->BytesPerPixel);
/* Pitch needs to be QWORD (8-byte) aligned */
video->pitch = (video->pitch + 7) & ~7;
video->pixels = (void *) SDL_malloc(video->h * video->pitch);
if (video->pixels == NULL) {
if (video != current) {
SDL_FreeSurface(video);
}
SDL_OutOfMemory();
return (NULL);
}
}
dd_surface3 = NULL;
#if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */
if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
video->flags |= SDL_HWSURFACE;
} else {
video->flags |= SDL_SWSURFACE;
}
#else
video->flags |= SDL_SWSURFACE;
#endif
if ((flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME)) {
video->flags |= SDL_RESIZABLE;
}
if (flags & SDL_NOFRAME) {
video->flags |= SDL_NOFRAME;
}
} else {
/* Necessary if we're going from window to fullscreen */
if (video->pixels != NULL) {
SDL_free(video->pixels);
video->pixels = NULL;
}
dd_surface3 = SDL_primary;
video->flags |= SDL_HWSURFACE;
}
/* See if the primary surface has double-buffering enabled */
if ((ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP) {
video->flags |= SDL_DOUBLEBUF;
}
/* Allocate the SDL surface associated with the primary surface */
if (DX5_AllocDDSurface(this, video, dd_surface3,
video->flags & SDL_HWSURFACE) < 0) {
if (video != current) {
SDL_FreeSurface(video);
}
return (NULL);
}
/* Use the appropriate blitting function */
if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
video->flags |= SDL_FULLSCREEN;
if (video->format->palette != NULL) {
video->flags |= SDL_HWPALETTE;
}
this->UpdateRects = DX5_DirectUpdate;
} else {
this->UpdateRects = DX5_WindowUpdate;
}
/* Make our window the proper size, set the clipper, then show it */
if ((flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) {
/* Create and set a clipper on our primary surface */
if (SDL_clipper == NULL) {
result = IDirectDraw2_CreateClipper(ddraw2,
0, &SDL_clipper, NULL);
if (result != DD_OK) {
if (video != current) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDraw2::CreateClipper", result);
return (NULL);
}
}
result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
if (result != DD_OK) {
if (video != current) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDrawClipper::SetHWnd", result);
return (NULL);
}
result = IDirectDrawSurface3_SetClipper(SDL_primary, SDL_clipper);
if (result != DD_OK) {
if (video != current) {
SDL_FreeSurface(video);
}
SetDDerror("DirectDrawSurface3::SetClipper", result);
return (NULL);
}
/* Resize the window (copied from SDL WinDIB driver) */
if (!SDL_windowid && !IsZoomed(SDL_Window)) {
RECT bounds;
int x, y;
UINT swp_flags;
const char *window = NULL;
const char *center = NULL;
if (!SDL_windowX && !SDL_windowY) {
window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
center = SDL_getenv("SDL_VIDEO_CENTERED");
if (window) {
if (SDL_sscanf(window, "%d,%d", &x, &y) == 2) {
SDL_windowX = x;
SDL_windowY = y;
}
if (SDL_strcmp(window, "center") == 0) {
center = window;
}
}
}
swp_flags = SWP_NOCOPYBITS;
bounds.left = SDL_windowX;
bounds.top = SDL_windowY;
bounds.right = SDL_windowX + video->w;
bounds.bottom = SDL_windowY + video->h;
AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
(GetMenu(SDL_Window) != NULL), 0);
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
if (center) {
x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
} else if (SDL_windowX || SDL_windowY || window) {
x = bounds.left;
y = bounds.top;
} else {
x = y = -1;
swp_flags |= SWP_NOMOVE;
}
SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height,
swp_flags);
SDL_windowX = SDL_bounds.left;
SDL_windowY = SDL_bounds.top;
}
}
ShowWindow(SDL_Window, SW_SHOW);
SetForegroundWindow(SDL_Window);
SDL_resizing = 0;
/* JC 14 Mar 2006
Flush the message loop or this can cause big problems later
Especially if the user decides to use dialog boxes or assert()!
*/
WIN_FlushMessageQueue();
/* We're live! */
return (video);
}
struct private_hwdata
{
LPDIRECTDRAWSURFACE3 dd_surface;
LPDIRECTDRAWSURFACE3 dd_writebuf;
};
static int
DX5_AllocDDSurface(_THIS, SDL_Surface * surface,
LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
{
LPDIRECTDRAWSURFACE dd_surface1;
LPDIRECTDRAWSURFACE3 dd_surface3;
DDSURFACEDESC ddsd;
HRESULT result;
/* Clear the hardware flag, in case we fail */
surface->flags &= ~flag;
/* Allocate the hardware acceleration data */
surface->hwdata = (struct private_hwdata *)
SDL_malloc(sizeof(*surface->hwdata));
if (surface->hwdata == NULL) {
SDL_OutOfMemory();
return (-1);
}
dd_surface3 = NULL;
/* Set up the surface description */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS |
DDSD_PITCH | DDSD_PIXELFORMAT);
ddsd.dwWidth = surface->w;
ddsd.dwHeight = surface->h;
#if defined(NONAMELESSUNION)
ddsd.u1.lPitch = surface->pitch;
#else
ddsd.lPitch = surface->pitch;
#endif
if ((flag & SDL_HWSURFACE) == SDL_HWSURFACE) {
ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY);
} else {
ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
}
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
if (surface->format->palette) {
ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
}
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
#else
ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
#endif
/* Create the DirectDraw video surface */
if (requested != NULL) {
dd_surface3 = requested;
} else {
result = IDirectDraw2_CreateSurface(ddraw2,
&ddsd, &dd_surface1, NULL);
if (result != DD_OK) {
SetDDerror("DirectDraw2::CreateSurface", result);
goto error_end;
}
result = IDirectDrawSurface_QueryInterface(dd_surface1,
&IID_IDirectDrawSurface3,
(LPVOID *) & dd_surface3);
IDirectDrawSurface_Release(dd_surface1);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface::QueryInterface", result);
goto error_end;
}
}
if ((flag & SDL_HWSURFACE) == SDL_HWSURFACE) {
/* Check to see whether the surface actually ended up
in video memory, and fail if not. We expect the
surfaces we create here to actually be in hardware!
*/
result = IDirectDrawSurface3_GetCaps(dd_surface3, &ddsd.ddsCaps);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::GetCaps", result);
goto error_end;
}
if ((ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) !=
DDSCAPS_VIDEOMEMORY) {
SDL_SetError("No room in video memory");
goto error_end;
}
} else {
/* Try to hook our surface memory */
ddsd.dwFlags = DDSD_LPSURFACE;
ddsd.lpSurface = surface->pixels;
result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3, &ddsd, 0);
if (result != DD_OK) {
SetDDerror("DirectDraw2::SetSurfaceDesc", result);
goto error_end;
}
}
/* Make sure the surface format was set properly */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
&ddsd,
(DDLOCK_NOSYSLOCK | DDLOCK_WAIT), NULL);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Lock", result);
goto error_end;
}
IDirectDrawSurface3_Unlock(dd_surface3, NULL);
if ((flag & SDL_HWSURFACE) == SDL_SWSURFACE) {
if (ddsd.lpSurface != surface->pixels) {
SDL_SetError("DDraw didn't use SDL surface memory");
goto error_end;
}
if (
#if defined(NONAMELESSUNION)
ddsd.u1.lPitch
#else
ddsd.lPitch
#endif
!= (LONG) surface->pitch) {
SDL_SetError("DDraw created surface with wrong pitch");
goto error_end;
}
} else {
#if defined(NONAMELESSUNION)
surface->pitch = (Uint16) ddsd.u1.lPitch;
#else
surface->pitch = (Uint16) ddsd.lPitch;
#endif
}
#if defined(NONAMELESSUNION)
if ((ddsd.ddpfPixelFormat.u1.dwRGBBitCount !=
surface->format->BitsPerPixel) ||
(ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
(ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
(ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask)) {
#else
if ((ddsd.ddpfPixelFormat.dwRGBBitCount !=
surface->format->BitsPerPixel) ||
(ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
(ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
(ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask)) {
#endif
SDL_SetError("DDraw didn't use SDL surface description");
goto error_end;
}
if ((ddsd.dwWidth != (DWORD) surface->w) ||
(ddsd.dwHeight != (DWORD) surface->h)) {
SDL_SetError("DDraw created surface with wrong size");
goto error_end;
}
/* Set the surface private data */
surface->flags |= flag;
surface->hwdata->dd_surface = dd_surface3;
if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
LPDIRECTDRAWSURFACE3 dd_writebuf;
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
&ddsd.ddsCaps,
&dd_writebuf);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::GetAttachedSurface", result);
} else {
dd_surface3 = dd_writebuf;
}
}
surface->hwdata->dd_writebuf = dd_surface3;
/* We're ready to go! */
return (0);
/* Okay, so goto's are cheesy, but there are so many possible
errors in this function, and the cleanup is the same in
every single case. Is there a better way, other than deeply
nesting the code?
*/
error_end:
if ((dd_surface3 != NULL) && (dd_surface3 != requested)) {
IDirectDrawSurface_Release(dd_surface3);
}
SDL_free(surface->hwdata);
surface->hwdata = NULL;
return (-1);
}
static int
DX5_AllocHWSurface(_THIS, SDL_Surface * surface)
{
/* DDraw limitation -- you need to set cooperative level first */
if (SDL_primary == NULL) {
SDL_SetError("You must set a non-GL video mode first");
return (-1);
}
return (DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
}
#ifdef DDRAW_DEBUG
void
PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
{
DDSURFACEDESC ddsd;
/* Lock and load! */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
(DDLOCK_NOSYSLOCK | DDLOCK_WAIT),
NULL) != DD_OK) {
return;
}
IDirectDrawSurface3_Unlock(surface, NULL);
fprintf(stderr, "%s:\n", title);
fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
ddsd.dwWidth, ddsd.dwHeight,
(flags & SDL_HWSURFACE) ? "hardware" : "software",
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
#else
ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
#endif
fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n",
#if defined(NONAMELESSUNION)
ddsd.ddpfPixelFormat.u2.dwRBitMask,
ddsd.ddpfPixelFormat.u3.dwGBitMask,
ddsd.ddpfPixelFormat.u4.dwBBitMask);
#else
ddsd.ddpfPixelFormat.dwRBitMask,
ddsd.ddpfPixelFormat.dwGBitMask, ddsd.ddpfPixelFormat.dwBBitMask);
#endif
}
#endif /* DDRAW_DEBUG */
static int
DX5_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
LPDIRECTDRAWSURFACE3 src_surface;
LPDIRECTDRAWSURFACE3 dst_surface;
DWORD flags;
RECT rect;
HRESULT result;
/* Set it up.. the desination must have a DDRAW surface */
src_surface = src->hwdata->dd_writebuf;
dst_surface = dst->hwdata->dd_writebuf;
rect.top = (LONG) srcrect->y;
rect.bottom = (LONG) srcrect->y + srcrect->h;
rect.left = (LONG) srcrect->x;
rect.right = (LONG) srcrect->x + srcrect->w;
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY)
flags = DDBLTFAST_SRCCOLORKEY;
else
flags = DDBLTFAST_NOCOLORKEY;
/* FIXME: We can remove this flag for _really_ fast blit queuing,
but it will affect the return values of locks and flips.
*/
flags |= DDBLTFAST_WAIT;
/* Do the blit! */
result = IDirectDrawSurface3_BltFast(dst_surface,
dstrect->x, dstrect->y, src_surface,
&rect, flags);
if (result != DD_OK) {
if (result == DDERR_SURFACELOST) {
result = IDirectDrawSurface3_Restore(src_surface);
result = IDirectDrawSurface3_Restore(dst_surface);
/* The surfaces need to be reloaded with artwork */
SDL_SetError("Blit surfaces were lost, reload them");
return (-2);
}
SetDDerror("IDirectDrawSurface3::BltFast", result);
#ifdef DDRAW_DEBUG
fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w,
dstrect->h, dstrect->x, dstrect->y);
fprintf(stderr,
"HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src,
dst, dstrect->x, dstrect->y);
PrintSurface("SRC", src_surface, src->flags);
PrintSurface("DST", dst_surface, dst->flags);
fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
#endif
/* Unexpected error, fall back to software blit */
return (src->map->sw_blit(src, srcrect, dst, dstrect));
}
return (0);
}
static int
DX5_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
{
int accelerated;
/* We need to have a DDraw surface for HW blits */
if ((src->flags & SDL_HWSURFACE) == SDL_SWSURFACE) {
/* Allocate a DDraw surface for the blit */
if (src->hwdata == NULL) {
DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
}
}
if (src->hwdata == NULL) {
return (0);
}
/* Set initial acceleration on */
src->flags |= SDL_HWACCEL;
/* Set the surface attributes */
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
if (DX5_SetHWColorKey(this, src, src->format->colorkey) < 0) {
src->flags &= ~SDL_HWACCEL;
}
}
if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
if (DX5_SetHWAlpha(this, src, src->format->alpha) < 0) {
src->flags &= ~SDL_HWACCEL;
}
}
/* Check to see if final surface blit is accelerated */
accelerated = !!(src->flags & SDL_HWACCEL);
if (accelerated) {
#ifdef DDRAW_DEBUG
fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
#endif
src->map->hw_blit = DX5_HWAccelBlit;
}
return (accelerated);
}
static int
DX5_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
{
LPDIRECTDRAWSURFACE3 dst_surface;
RECT area;
DDBLTFX bltfx;
HRESULT result;
#ifdef DDRAW_DEBUG
fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x,
dstrect->y);
#endif
dst_surface = dst->hwdata->dd_writebuf;
area.top = (LONG) dstrect->y;
area.bottom = (LONG) dstrect->y + dstrect->h;
area.left = (LONG) dstrect->x;
area.right = (LONG) dstrect->x + dstrect->w;
bltfx.dwSize = sizeof(bltfx);
#if defined(NONAMELESSUNION)
bltfx.u5.dwFillColor = color;
#else
bltfx.dwFillColor = color;
#endif
result = IDirectDrawSurface3_Blt(dst_surface,
&area, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
if (result == DDERR_SURFACELOST) {
IDirectDrawSurface3_Restore(dst_surface);
result = IDirectDrawSurface3_Blt(dst_surface,
&area, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT,
&bltfx);
}
if (result != DD_OK) {
SetDDerror("IDirectDrawSurface3::Blt", result);
return (-1);
}
return (0);
}
static int
DX5_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
{
DDCOLORKEY colorkey;
HRESULT result;
/* Set the surface colorkey */
colorkey.dwColorSpaceLowValue = key;
colorkey.dwColorSpaceHighValue = key;
result =
IDirectDrawSurface3_SetColorKey(surface->hwdata->dd_surface,
DDCKEY_SRCBLT, &colorkey);
if (result != DD_OK) {
SetDDerror("IDirectDrawSurface3::SetColorKey", result);
return (-1);
}
return (0);
}
static int
DX5_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha)
{
return (-1);
}
static int
DX5_LockHWSurface(_THIS, SDL_Surface * surface)
{
HRESULT result;
LPDIRECTDRAWSURFACE3 dd_surface;
DDSURFACEDESC ddsd;
/* Lock and load! */
dd_surface = surface->hwdata->dd_writebuf;
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
(DDLOCK_NOSYSLOCK | DDLOCK_WAIT), NULL);
if (result == DDERR_SURFACELOST) {
result = IDirectDrawSurface3_Restore(surface->hwdata->dd_surface);
result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
(DDLOCK_NOSYSLOCK | DDLOCK_WAIT),
NULL);
}
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Lock", result);
return (-1);
}
/* Pitch might have changed -- recalculate pitch and offset */
#if defined(NONAMELESSUNION)
if (surface->pitch != ddsd.u1.lPitch) {
surface->pitch = ddsd.u1.lPitch;
#else
if (surface->pitch != ddsd.lPitch) {
surface->pitch = (Uint16) ddsd.lPitch;
#endif
surface->offset =
((ddsd.dwHeight - surface->h) / 2) * surface->pitch +
((ddsd.dwWidth - surface->w) / 2) *
surface->format->BytesPerPixel;
}
surface->pixels = ddsd.lpSurface;
return (0);
}
static void
DX5_UnlockHWSurface(_THIS, SDL_Surface * surface)
{
IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
surface->pixels = NULL;
}
static int
DX5_FlipHWSurface(_THIS, SDL_Surface * surface)
{
HRESULT result;
LPDIRECTDRAWSURFACE3 dd_surface;
dd_surface = surface->hwdata->dd_surface;
/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
/* Dmitry Yakimov (ftech@tula.net) */
while (IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) ==
DDERR_WASSTILLDRAWING);
result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
if (result == DDERR_SURFACELOST) {
result = IDirectDrawSurface3_Restore(surface->hwdata->dd_surface);
while (IDirectDrawSurface3_GetFlipStatus
(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
}
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Flip", result);
return (-1);
}
return (0);
}
static void
DX5_FreeHWSurface(_THIS, SDL_Surface * surface)
{
if (surface->hwdata) {
if (surface->hwdata->dd_surface != SDL_primary) {
IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
}
SDL_free(surface->hwdata);
surface->hwdata = NULL;
}
}
void
DX5_WindowUpdate(_THIS, int numrects, SDL_Rect * rects)
{
HRESULT result;
int i;
RECT src, dst;
for (i = 0; i < numrects; ++i) {
src.top = (LONG) rects[i].y;
src.bottom = (LONG) rects[i].y + rects[i].h;
src.left = (LONG) rects[i].x;
src.right = (LONG) rects[i].x + rects[i].w;
dst.top = SDL_bounds.top + src.top;
dst.left = SDL_bounds.left + src.left;
dst.bottom = SDL_bounds.top + src.bottom;
dst.right = SDL_bounds.left + src.right;
result = IDirectDrawSurface3_Blt(SDL_primary, &dst,
this->screen->hwdata->dd_surface,
&src, DDBLT_WAIT, NULL);
/* Doh! Check for lost surface and restore it */
if (result == DDERR_SURFACELOST) {
IDirectDrawSurface3_Restore(SDL_primary);
IDirectDrawSurface3_Blt(SDL_primary, &dst,
this->screen->hwdata->dd_surface,
&src, DDBLT_WAIT, NULL);
}
}
}
void
DX5_DirectUpdate(_THIS, int numrects, SDL_Rect * rects)
{
}
/* Compress a full palette into the limited number of colors given to us
by windows.
The "best" way to do this is to sort the colors by diversity and place
the most diverse colors into the limited palette. Unfortunately this
results in widely varying colors being displayed in the interval during
which the windows palette has been set, and the mapping of the shadow
surface to the new palette. This is especially noticeable during fades.
To deal with this problem, we can copy a predetermined portion of the
full palette, and use that as the limited palette. This allows colors
to fade smoothly as the remapping is very similar on each palette change.
Unfortunately, this breaks applications which partition the palette into
distinct and widely varying areas, expecting all colors to be available.
I'm making them both available, chosen at compile time.
If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
otherwise the sort-by-diversity algorithm will be used.
*/
#define SIMPLE_COMPRESSION
#define CS_CS_DIST(A, B) ({ \
int r = (A.r - B.r); \
int g = (A.g - B.g); \
int b = (A.b - B.b); \
(r*r + g*g + b*b); \
})
static void
DX5_CompressPalette(_THIS, SDL_Color * colors, int ncolors, int maxcolors)
{
#ifdef SIMPLE_COMPRESSION
int i, j;
#else
static SDL_Color zero = { 0, 0, 0, 0 };
int i, j;
int max, dist;
int prev, next;
int *pool;
int *seen, *order;
#endif
/* Does this happen? */
if (maxcolors > ncolors) {
maxcolors = ncolors;
}
#ifdef SIMPLE_COMPRESSION
/* Just copy the first "maxcolors" colors */
for (j = 10, i = 0; i < maxcolors; ++i, ++j) {
SDL_colors[j].peRed = colors[i].r;
SDL_colors[j].peGreen = colors[i].g;
SDL_colors[j].peBlue = colors[i].b;
}
#else
/* Allocate memory for the arrays we use */
pool = SDL_stack_alloc(int, 2 * ncolors);
if (pool == NULL) {
/* No worries, just return */ ;
return;
}
seen = pool;
SDL_memset(seen, 0, ncolors * sizeof(int));
order = pool + ncolors;
/* Start with the brightest color */
max = 0;
for (i = 0; i < ncolors; ++i) {
dist = CS_CS_DIST(zero, colors[i]);
if (dist >= max) {
max = dist;
next = i;
}
}
j = 0;
order[j++] = next;
seen[next] = 1;
prev = next;
/* Keep going through all the colors */
while (j < maxcolors) {
max = 0;
for (i = 0; i < ncolors; ++i) {
if (seen[i]) {
continue;
}
dist = CS_CS_DIST(colors[i], colors[prev]);
if (dist >= max) {
max = dist;
next = i;
}
}
order[j++] = next;
seen[next] = 1;
prev = next;
}
/* Compress the colors to the palette */
for (j = 10, i = 0; i < maxcolors; ++i, ++j) {
SDL_colors[j].peRed = colors[order[i]].r;
SDL_colors[j].peGreen = colors[order[i]].g;
SDL_colors[j].peBlue = colors[order[i]].b;
}
SDL_stack_free(pool);
#endif /* SIMPLE_COMPRESSION */
}
/* Set the system colormap in both fullscreen and windowed modes */
int
DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
{
int i;
int alloct_all;
/* Copy palette colors into display palette */
alloct_all = 0;
if (SDL_palette != NULL) {
if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) {
/* We can set all entries explicitly */
for (i = 0; i < ncolors; ++i) {
int j = firstcolor + i;
SDL_colors[j].peRed = colors[i].r;
SDL_colors[j].peGreen = colors[i].g;
SDL_colors[j].peBlue = colors[i].b;
}
IDirectDrawPalette_SetEntries(SDL_palette, 0,
firstcolor, ncolors,
&SDL_colors[firstcolor]);
alloct_all = 1;
} else {
/* Grab the 236 most diverse colors in the palette */
DX5_CompressPalette(this, colors, ncolors, 236);
/* This sends an WM_PALETTECHANGED message to us */
colorchange_expected = 1;
IDirectDrawPalette_SetEntries(SDL_palette, 0, 0, 256, SDL_colors);
}
}
return (alloct_all);
}
/* Gamma code is only available on DirectX 7 and newer */
static int
DX5_SetGammaRamp(_THIS, Uint16 * ramp)
{
#ifdef IDirectDrawGammaControl_SetGammaRamp
LPDIRECTDRAWGAMMACONTROL gamma;
DDGAMMARAMP gamma_ramp;
HRESULT result;
#endif
/* In windowed or OpenGL mode, use windib gamma code */
if (!DDRAW_FULLSCREEN()) {
return DIB_SetGammaRamp(this, ramp);
}
#ifndef IDirectDrawGammaControl_SetGammaRamp
SDL_SetError("SDL compiled without DirectX gamma ramp support");
return -1;
#else
/* Check for a video mode! */
if (!SDL_primary) {
SDL_SetError("A video mode must be set for gamma correction");
return (-1);
}
/* Get the gamma control object */
result = IDirectDrawSurface3_QueryInterface(SDL_primary,
&IID_IDirectDrawGammaControl,
(LPVOID *) & gamma);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
return (-1);
}
/* Set up the gamma ramp */
SDL_memcpy(gamma_ramp.red, &ramp[0 * 256], 256 * sizeof(*ramp));
SDL_memcpy(gamma_ramp.green, &ramp[1 * 256], 256 * sizeof(*ramp));
SDL_memcpy(gamma_ramp.blue, &ramp[2 * 256], 256 * sizeof(*ramp));
result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
if (result != DD_OK) {
SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
}
/* Release the interface and return */
IDirectDrawGammaControl_Release(gamma);
return (result == DD_OK) ? 0 : -1;
#endif /* !IDirectDrawGammaControl_SetGammaRamp */
}
static int
DX5_GetGammaRamp(_THIS, Uint16 * ramp)
{
#ifdef IDirectDrawGammaControl_SetGammaRamp
LPDIRECTDRAWGAMMACONTROL gamma;
DDGAMMARAMP gamma_ramp;
HRESULT result;
#endif
/* In windowed or OpenGL mode, use windib gamma code */
if (!DDRAW_FULLSCREEN()) {
return DIB_GetGammaRamp(this, ramp);
}
#ifndef IDirectDrawGammaControl_SetGammaRamp
SDL_SetError("SDL compiled without DirectX gamma ramp support");
return -1;
#else
/* Check for a video mode! */
if (!SDL_primary) {
SDL_SetError("A video mode must be set for gamma correction");
return (-1);
}
/* Get the gamma control object */
result = IDirectDrawSurface3_QueryInterface(SDL_primary,
&IID_IDirectDrawGammaControl,
(LPVOID *) & gamma);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
return (-1);
}
/* Set up the gamma ramp */
result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
if (result == DD_OK) {
SDL_memcpy(&ramp[0 * 256], gamma_ramp.red, 256 * sizeof(*ramp));
SDL_memcpy(&ramp[1 * 256], gamma_ramp.green, 256 * sizeof(*ramp));
SDL_memcpy(&ramp[2 * 256], gamma_ramp.blue, 256 * sizeof(*ramp));
} else {
SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
}
/* Release the interface and return */
IDirectDrawGammaControl_Release(gamma);
return (result == DD_OK) ? 0 : -1;
#endif /* !IDirectDrawGammaControl_SetGammaRamp */
}
void
DX5_VideoQuit(_THIS)
{
int i, j;
/* If we're fullscreen GL, we need to reset the display */
if (this->screen != NULL) {
#ifndef NO_CHANGEDISPLAYSETTINGS
if ((this->screen->flags & (SDL_INTERNALOPENGL | SDL_FULLSCREEN)) ==
(SDL_INTERNALOPENGL | SDL_FULLSCREEN)) {
ChangeDisplaySettings(NULL, 0);
ShowWindow(SDL_Window, SW_HIDE);
}
#endif
if (this->screen->flags & SDL_INTERNALOPENGL) {
WIN_GL_ShutDown(this);
}
}
/* Free any palettes we used */
if (SDL_palette != NULL) {
IDirectDrawPalette_Release(SDL_palette);
SDL_palette = NULL;
}
/* Allow the primary surface to be freed */
if (SDL_primary != NULL) {
SDL_primary = NULL;
}
/* Free video mode lists */
for (i = 0; i < NUM_MODELISTS; ++i) {
if (SDL_modelist[i] != NULL) {
for (j = 0; SDL_modelist[i][j]; ++j)
SDL_free(SDL_modelist[i][j]);
SDL_free(SDL_modelist[i]);
SDL_modelist[i] = NULL;
}
}
/* Free the window */
DIB_QuitGamma(this);
if (SDL_Window) {
DX5_DestroyWindow(this);
}
/* Free our window icon */
if (screen_icn) {
DestroyIcon(screen_icn);
screen_icn = NULL;
}
}
/* Exported for the windows message loop only */
void
DX5_RealizePalette(_THIS)
{
if (SDL_palette) {
IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
}
}
static void
DX5_Recolor8Bit(_THIS, SDL_Surface * surface, Uint8 * mapping)
{
int row, col;
Uint8 *pixels;
if (surface->w && surface->h) {
if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
if (this->LockHWSurface(this, surface) < 0) {
return;
}
}
for (row = 0; row < surface->h; ++row) {
pixels = (Uint8 *) surface->pixels + row * surface->pitch;
for (col = 0; col < surface->w; ++col, ++pixels) {
*pixels = mapping[*pixels];
}
}
if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
this->UnlockHWSurface(this, surface);
}
SDL_UpdateRect(surface, 0, 0, 0, 0);
}
}
void
DX5_PaletteChanged(_THIS, HWND window)
{
SDL_Palette *palette;
SDL_Color *saved = NULL;
HDC hdc;
int i;
PALETTEENTRY *entries;
/* This is true when the window is closing */
if ((SDL_primary == NULL) || (SDL_VideoSurface == NULL))
return;
/* We need to get the colors as they were set */
palette = this->physpal;
if (!palette)
palette = SDL_VideoSurface->format->palette;
if (palette == NULL) { /* Sometimes we don't have a palette */
return;
}
entries = SDL_stack_alloc(PALETTEENTRY, palette->ncolors);
hdc = GetDC(window);
GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
ReleaseDC(window, hdc);
if (!colorchange_expected) {
saved = SDL_stack_alloc(SDL_Color, palette->ncolors);
SDL_memcpy(saved, palette->colors,
palette->ncolors * sizeof(SDL_Color));
}
for (i = 0; i < palette->ncolors; ++i) {
palette->colors[i].r = entries[i].peRed;
palette->colors[i].g = entries[i].peGreen;
palette->colors[i].b = entries[i].peBlue;
}
SDL_stack_free(entries);
if (!colorchange_expected) {
Uint8 mapping[256];
SDL_memset(mapping, 0, sizeof(mapping));
for (i = 0; i < palette->ncolors; ++i) {
mapping[i] = SDL_FindColor(palette,
saved[i].r, saved[i].g, saved[i].b);
}
DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
SDL_stack_free(saved);
}
colorchange_expected = 0;
/* Notify all mapped surfaces of the change */
SDL_FormatChanged(SDL_VideoSurface);
}
/* Exported for the windows message loop only */
void
DX5_WinPAINT(_THIS, HDC hdc)
{
SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
#ifndef _SDL_dx5video_h
#define _SDL_dx5video_h
#include "directx.h"
/* Private display data */
struct SDL_PrivateVideoData
{
LPDIRECTDRAW2 ddraw2;
LPDIRECTDRAWSURFACE3 SDL_primary;
LPDIRECTDRAWCLIPPER SDL_clipper;
LPDIRECTDRAWPALETTE SDL_palette;
PALETTEENTRY SDL_colors[256];
int colorchange_expected;
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
int SDL_modeindex[NUM_MODELISTS];
};
/* Old variable names */
#define ddraw2 (this->hidden->ddraw2)
#define SDL_primary (this->hidden->SDL_primary)
#define SDL_clipper (this->hidden->SDL_clipper)
#define SDL_palette (this->hidden->SDL_palette)
#define SDL_colors (this->hidden->SDL_colors)
#define colorchange_expected (this->hidden->colorchange_expected)
#define SDL_nummodes (this->hidden->SDL_nummodes)
#define SDL_modelist (this->hidden->SDL_modelist)
#define SDL_modeindex (this->hidden->SDL_modeindex)
/* DirectX function pointers for video and events */
extern HRESULT(WINAPI * DDrawCreate) (GUID FAR * lpGUID,
LPDIRECTDRAW FAR * lplpDD,
IUnknown FAR * pUnkOuter);
extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
LPDIRECTINPUT * ppDI,
LPUNKNOWN punkOuter);
/* DirectDraw error reporting function */
extern void SetDDerror(const char *function, int code);
#endif /* _SDL_dx5video_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
/* This is the DirectDraw implementation of YUV video overlays */
#include "SDL_video.h"
#include "SDL_dx5yuv_c.h"
#include "../SDL_yuvfuncs.h"
//#define USE_DIRECTX_OVERLAY
/* The functions used to manipulate software video overlays */
static struct private_yuvhwfuncs dx5_yuvfuncs = {
DX5_LockYUVOverlay,
DX5_UnlockYUVOverlay,
DX5_DisplayYUVOverlay,
DX5_FreeYUVOverlay
};
struct private_yuvhwdata
{
LPDIRECTDRAWSURFACE3 surface;
/* These are just so we don't have to allocate them separately */
Uint16 pitches[3];
Uint8 *planes[3];
};
static LPDIRECTDRAWSURFACE3
CreateYUVSurface(_THIS, int width, int height, Uint32 format)
{
HRESULT result;
LPDIRECTDRAWSURFACE dd_surface1;
LPDIRECTDRAWSURFACE3 dd_surface3;
DDSURFACEDESC ddsd;
/* Set up the surface description */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT);
ddsd.dwWidth = width;
ddsd.dwHeight = height;
#ifdef USE_DIRECTX_OVERLAY
ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY);
#else
ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY);
#endif
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwFourCC = format;
/* Create the DirectDraw video surface */
result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL);
if (result != DD_OK) {
SetDDerror("DirectDraw2::CreateSurface", result);
return (NULL);
}
result = IDirectDrawSurface_QueryInterface(dd_surface1,
&IID_IDirectDrawSurface3,
(LPVOID *) & dd_surface3);
IDirectDrawSurface_Release(dd_surface1);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface::QueryInterface", result);
return (NULL);
}
/* Make sure the surface format was set properly */
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
&ddsd, DDLOCK_NOSYSLOCK, NULL);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Lock", result);
IDirectDrawSurface_Release(dd_surface3);
return (NULL);
}
IDirectDrawSurface3_Unlock(dd_surface3, NULL);
if (!(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) ||
(ddsd.ddpfPixelFormat.dwFourCC != format)) {
SDL_SetError("DDraw didn't use requested FourCC format");
IDirectDrawSurface_Release(dd_surface3);
return (NULL);
}
/* We're ready to go! */
return (dd_surface3);
}
#ifdef DEBUG_YUV
static char *
PrintFOURCC(Uint32 code)
{
static char buf[5];
buf[3] = code >> 24;
buf[2] = (code >> 16) & 0xFF;
buf[1] = (code >> 8) & 0xFF;
buf[0] = (code & 0xFF);
return (buf);
}
#endif
SDL_Overlay *
DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
SDL_Surface * display)
{
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
#ifdef DEBUG_YUV
DWORD numcodes;
DWORD *codes;
printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format));
IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL);
if (numcodes) {
DWORD i;
codes = SDL_malloc(numcodes * sizeof(*codes));
if (codes) {
IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes);
for (i = 0; i < numcodes; ++i) {
fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i]));
}
SDL_free(codes);
}
} else {
fprintf(stderr, "No FOURCC codes supported\n");
}
#endif
/* Create the overlay structure */
overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay);
if (overlay == NULL) {
SDL_OutOfMemory();
return (NULL);
}
SDL_memset(overlay, 0, (sizeof *overlay));
/* Fill in the basic members */
overlay->format = format;
overlay->w = width;
overlay->h = height;
/* Set up the YUV surface function structure */
overlay->hwfuncs = &dx5_yuvfuncs;
/* Create the pixel data and lookup tables */
hwdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *hwdata);
overlay->hwdata = hwdata;
if (hwdata == NULL) {
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
return (NULL);
}
hwdata->surface = CreateYUVSurface(this, width, height, format);
if (hwdata->surface == NULL) {
SDL_FreeYUVOverlay(overlay);
return (NULL);
}
overlay->hw_overlay = 1;
/* Set up the plane pointers */
overlay->pitches = hwdata->pitches;
overlay->pixels = hwdata->planes;
switch (format) {
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
overlay->planes = 3;
break;
default:
overlay->planes = 1;
break;
}
/* We're all done.. */
return (overlay);
}
int
DX5_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
{
HRESULT result;
LPDIRECTDRAWSURFACE3 surface;
DDSURFACEDESC ddsd;
surface = overlay->hwdata->surface;
SDL_memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
result = IDirectDrawSurface3_Lock(surface, NULL,
&ddsd, DDLOCK_NOSYSLOCK, NULL);
if (result == DDERR_SURFACELOST) {
result = IDirectDrawSurface3_Restore(surface);
result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
(DDLOCK_NOSYSLOCK | DDLOCK_WAIT),
NULL);
}
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Lock", result);
return (-1);
}
/* Find the pitch and offset values for the overlay */
#if defined(NONAMELESSUNION)
overlay->pitches[0] = (Uint16) ddsd.u1.lPitch;
#else
overlay->pitches[0] = (Uint16) ddsd.lPitch;
#endif
overlay->pixels[0] = (Uint8 *) ddsd.lpSurface;
switch (overlay->format) {
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
/* Add the two extra planes */
overlay->pitches[1] = overlay->pitches[0] / 2;
overlay->pitches[2] = overlay->pitches[0] / 2;
overlay->pixels[1] = overlay->pixels[0] +
overlay->pitches[0] * overlay->h;
overlay->pixels[2] = overlay->pixels[1] +
overlay->pitches[1] * overlay->h / 2;
break;
default:
/* Only one plane, no worries */
break;
}
return (0);
}
void
DX5_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
{
LPDIRECTDRAWSURFACE3 surface;
surface = overlay->hwdata->surface;
IDirectDrawSurface3_Unlock(surface, NULL);
}
int
DX5_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
SDL_Rect * dst)
{
HRESULT result;
LPDIRECTDRAWSURFACE3 surface;
RECT srcrect, dstrect;
surface = overlay->hwdata->surface;
srcrect.top = src->y;
srcrect.bottom = srcrect.top + src->h;
srcrect.left = src->x;
srcrect.right = srcrect.left + src->w;
dstrect.top = SDL_bounds.top + dst->y;
dstrect.left = SDL_bounds.left + dst->x;
dstrect.bottom = dstrect.top + dst->h;
dstrect.right = dstrect.left + dst->w;
#ifdef USE_DIRECTX_OVERLAY
result = IDirectDrawSurface3_UpdateOverlay(surface, &srcrect,
SDL_primary, &dstrect,
DDOVER_SHOW, NULL);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::UpdateOverlay", result);
return (-1);
}
#else
result =
IDirectDrawSurface3_Blt(SDL_primary, &dstrect, surface, &srcrect,
DDBLT_WAIT, NULL);
if (result != DD_OK) {
SetDDerror("DirectDrawSurface3::Blt", result);
return (-1);
}
#endif
return (0);
}
void
DX5_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
{
struct private_yuvhwdata *hwdata;
hwdata = overlay->hwdata;
if (hwdata) {
if (hwdata->surface) {
IDirectDrawSurface_Release(hwdata->surface);
}
SDL_free(hwdata);
}
}
/* vi: set ts=4 sw=4 expandtab: */
/*
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"
/* This is the DirectDraw implementation of YUV video overlays */
#include "SDL_video.h"
#include "../wincommon/SDL_lowvideo.h"
#include "SDL_dx5video.h"
extern SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height,
Uint32 format,
SDL_Surface * display);
extern int DX5_LockYUVOverlay(_THIS, SDL_Overlay * overlay);
extern void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay);
extern int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay,
SDL_Rect * src, SDL_Rect * dst);
extern void DX5_FreeYUVOverlay(_THIS, SDL_Overlay * overlay);
/* vi: set ts=4 sw=4 expandtab: */
#ifndef _directx_h
#define _directx_h
/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#ifndef WIN32
#define WIN32
#endif
#undef WINNT
/* Far pointers don't exist in 32-bit code */
#ifndef FAR
#define FAR
#endif
/* Error codes not yet included in Win32 API header files */
#ifndef MAKE_HRESULT
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))))
#endif
#ifndef S_OK
#define S_OK (HRESULT)0x00000000L
#endif
#ifndef SUCCEEDED
#define SUCCEEDED(x) ((HRESULT)(x) >= 0)
#endif
#ifndef FAILED
#define FAILED(x) ((HRESULT)(x)<0)
#endif
#ifndef E_FAIL
#define E_FAIL (HRESULT)0x80000008L
#endif
#ifndef E_NOINTERFACE
#define E_NOINTERFACE (HRESULT)0x80004002L
#endif
#ifndef E_OUTOFMEMORY
#define E_OUTOFMEMORY (HRESULT)0x8007000EL
#endif
#ifndef E_INVALIDARG
#define E_INVALIDARG (HRESULT)0x80070057L
#endif
#ifndef E_NOTIMPL
#define E_NOTIMPL (HRESULT)0x80004001L
#endif
#ifndef REGDB_E_CLASSNOTREG
#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L
#endif
/* Severity codes */
#ifndef SEVERITY_ERROR
#define SEVERITY_ERROR 1
#endif
/* Error facility codes */
#ifndef FACILITY_WIN32
#define FACILITY_WIN32 7
#endif
#ifndef FIELD_OFFSET
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
#endif
/* DirectX headers (if it isn't included, I haven't tested it yet)
*/
/* We need these defines to mark what version of DirectX API we use */
#define DIRECTDRAW_VERSION 0x0700
#define DIRECTSOUND_VERSION 0x0500
#define DIRECTINPUT_VERSION 0x0500
#ifdef __GNUC__
#define NONAMELESSUNION
#endif
#include <ddraw.h>
#include <dsound.h>
#include <dinput.h>
#endif /* _directx_h */
/* vi: set ts=4 sw=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment