src/video/windx5/SDL_dx5video.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 11 Feb 2004 16:10:16 +0000
changeset 809 dba98fb391e7
parent 769 b8d311d90021
child 815 6176f9a0d61a
permissions -rw-r--r--
Date: Tue, 13 Jan 2004 19:25:37 +0300
From: Dmitry Yakimov
Subject: [SDL] [PATCH] SDL bug patch

Let me introduce 2 fixes to SDL.

1. Preventing great slowdown on fast machines while hardware
flipping (it's obviously bug).
2. Setting up 85 Hz of monitor if supported. The reason is that
Win98 by default sets lowest frequency 60 Hz.
And we can't set up maximum frequency because some users can have
wrong monitor drivers.
This is important for shareware and commercial programs.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@769
     3
    Copyright (C) 1997-2004 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@0
     6
    modify it under the terms of the GNU Library General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@0
     8
    version 2 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@0
    13
    Library General Public License for more details.
slouken@0
    14
slouken@0
    15
    You should have received a copy of the GNU Library General Public
slouken@0
    16
    License along with this library; if not, write to the Free
slouken@0
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
#ifdef SAVE_RCSID
slouken@0
    24
static char rcsid =
slouken@0
    25
 "@(#) $Id$";
slouken@0
    26
#endif
slouken@0
    27
slouken@0
    28
#include <stdio.h>
slouken@0
    29
#include <stdlib.h>
slouken@0
    30
#include <malloc.h>
slouken@0
    31
#include <windows.h>
slouken@0
    32
#include "directx.h"
slouken@0
    33
slouken@0
    34
/* Not yet in the mingw32 cross-compile headers */
slouken@0
    35
#ifndef CDS_FULLSCREEN
slouken@0
    36
#define CDS_FULLSCREEN	4
slouken@0
    37
#endif
slouken@0
    38
slouken@0
    39
#include "SDL_error.h"
slouken@0
    40
#include "SDL_timer.h"
slouken@0
    41
#include "SDL_events.h"
slouken@0
    42
#include "SDL_syswm.h"
slouken@0
    43
#include "SDL_sysvideo.h"
slouken@0
    44
#include "SDL_blit.h"
slouken@0
    45
#include "SDL_pixels_c.h"
slouken@0
    46
#include "SDL_dx5video.h"
slouken@0
    47
#include "SDL_syswm_c.h"
slouken@0
    48
#include "SDL_sysmouse_c.h"
slouken@0
    49
#include "SDL_dx5events_c.h"
slouken@0
    50
#include "SDL_dx5yuv_c.h"
slouken@0
    51
#include "SDL_wingl_c.h"
slouken@0
    52
slouken@453
    53
#ifdef _WIN32_WCE
slouken@453
    54
#define NO_CHANGEDISPLAYSETTINGS
slouken@453
    55
#endif
slouken@453
    56
#ifndef WS_MAXIMIZE
slouken@453
    57
#define WS_MAXIMIZE		0
slouken@453
    58
#endif
slouken@453
    59
#ifndef SWP_NOCOPYBITS
slouken@453
    60
#define SWP_NOCOPYBITS	0
slouken@453
    61
#endif
slouken@453
    62
#ifndef PC_NOCOLLAPSE
slouken@453
    63
#define PC_NOCOLLAPSE	0
slouken@453
    64
#endif
slouken@453
    65
slouken@0
    66
slouken@0
    67
/* DirectX function pointers for video and events */
slouken@0
    68
HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
slouken@453
    69
HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter);
slouken@0
    70
slouken@0
    71
/* This is the rect EnumModes2 uses */
slouken@0
    72
struct DX5EnumRect {
slouken@0
    73
	SDL_Rect r;
slouken@809
    74
	int refreshRate;
slouken@0
    75
	struct DX5EnumRect* next;
slouken@0
    76
};
slouken@0
    77
static struct DX5EnumRect *enumlists[NUM_MODELISTS];
slouken@0
    78
slouken@0
    79
/*
slouken@0
    80
 * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
slouken@0
    81
 */
slouken@0
    82
slouken@0
    83
/* Keyboard */
slouken@0
    84
slouken@0
    85
static DIOBJECTDATAFORMAT KBD_fmt[] = {
slouken@0
    86
	{ &GUID_Key, 0, 0x8000000C, 0x00000000 },
slouken@0
    87
	{ &GUID_Key, 1, 0x8000010C, 0x00000000 },
slouken@0
    88
	{ &GUID_Key, 2, 0x8000020C, 0x00000000 },
slouken@0
    89
	{ &GUID_Key, 3, 0x8000030C, 0x00000000 },
slouken@0
    90
	{ &GUID_Key, 4, 0x8000040C, 0x00000000 },
slouken@0
    91
	{ &GUID_Key, 5, 0x8000050C, 0x00000000 },
slouken@0
    92
	{ &GUID_Key, 6, 0x8000060C, 0x00000000 },
slouken@0
    93
	{ &GUID_Key, 7, 0x8000070C, 0x00000000 },
slouken@0
    94
	{ &GUID_Key, 8, 0x8000080C, 0x00000000 },
slouken@0
    95
	{ &GUID_Key, 9, 0x8000090C, 0x00000000 },
slouken@0
    96
	{ &GUID_Key, 10, 0x80000A0C, 0x00000000 },
slouken@0
    97
	{ &GUID_Key, 11, 0x80000B0C, 0x00000000 },
slouken@0
    98
	{ &GUID_Key, 12, 0x80000C0C, 0x00000000 },
slouken@0
    99
	{ &GUID_Key, 13, 0x80000D0C, 0x00000000 },
slouken@0
   100
	{ &GUID_Key, 14, 0x80000E0C, 0x00000000 },
slouken@0
   101
	{ &GUID_Key, 15, 0x80000F0C, 0x00000000 },
slouken@0
   102
	{ &GUID_Key, 16, 0x8000100C, 0x00000000 },
slouken@0
   103
	{ &GUID_Key, 17, 0x8000110C, 0x00000000 },
slouken@0
   104
	{ &GUID_Key, 18, 0x8000120C, 0x00000000 },
slouken@0
   105
	{ &GUID_Key, 19, 0x8000130C, 0x00000000 },
slouken@0
   106
	{ &GUID_Key, 20, 0x8000140C, 0x00000000 },
slouken@0
   107
	{ &GUID_Key, 21, 0x8000150C, 0x00000000 },
slouken@0
   108
	{ &GUID_Key, 22, 0x8000160C, 0x00000000 },
slouken@0
   109
	{ &GUID_Key, 23, 0x8000170C, 0x00000000 },
slouken@0
   110
	{ &GUID_Key, 24, 0x8000180C, 0x00000000 },
slouken@0
   111
	{ &GUID_Key, 25, 0x8000190C, 0x00000000 },
slouken@0
   112
	{ &GUID_Key, 26, 0x80001A0C, 0x00000000 },
slouken@0
   113
	{ &GUID_Key, 27, 0x80001B0C, 0x00000000 },
slouken@0
   114
	{ &GUID_Key, 28, 0x80001C0C, 0x00000000 },
slouken@0
   115
	{ &GUID_Key, 29, 0x80001D0C, 0x00000000 },
slouken@0
   116
	{ &GUID_Key, 30, 0x80001E0C, 0x00000000 },
slouken@0
   117
	{ &GUID_Key, 31, 0x80001F0C, 0x00000000 },
slouken@0
   118
	{ &GUID_Key, 32, 0x8000200C, 0x00000000 },
slouken@0
   119
	{ &GUID_Key, 33, 0x8000210C, 0x00000000 },
slouken@0
   120
	{ &GUID_Key, 34, 0x8000220C, 0x00000000 },
slouken@0
   121
	{ &GUID_Key, 35, 0x8000230C, 0x00000000 },
slouken@0
   122
	{ &GUID_Key, 36, 0x8000240C, 0x00000000 },
slouken@0
   123
	{ &GUID_Key, 37, 0x8000250C, 0x00000000 },
slouken@0
   124
	{ &GUID_Key, 38, 0x8000260C, 0x00000000 },
slouken@0
   125
	{ &GUID_Key, 39, 0x8000270C, 0x00000000 },
slouken@0
   126
	{ &GUID_Key, 40, 0x8000280C, 0x00000000 },
slouken@0
   127
	{ &GUID_Key, 41, 0x8000290C, 0x00000000 },
slouken@0
   128
	{ &GUID_Key, 42, 0x80002A0C, 0x00000000 },
slouken@0
   129
	{ &GUID_Key, 43, 0x80002B0C, 0x00000000 },
slouken@0
   130
	{ &GUID_Key, 44, 0x80002C0C, 0x00000000 },
slouken@0
   131
	{ &GUID_Key, 45, 0x80002D0C, 0x00000000 },
slouken@0
   132
	{ &GUID_Key, 46, 0x80002E0C, 0x00000000 },
slouken@0
   133
	{ &GUID_Key, 47, 0x80002F0C, 0x00000000 },
slouken@0
   134
	{ &GUID_Key, 48, 0x8000300C, 0x00000000 },
slouken@0
   135
	{ &GUID_Key, 49, 0x8000310C, 0x00000000 },
slouken@0
   136
	{ &GUID_Key, 50, 0x8000320C, 0x00000000 },
slouken@0
   137
	{ &GUID_Key, 51, 0x8000330C, 0x00000000 },
slouken@0
   138
	{ &GUID_Key, 52, 0x8000340C, 0x00000000 },
slouken@0
   139
	{ &GUID_Key, 53, 0x8000350C, 0x00000000 },
slouken@0
   140
	{ &GUID_Key, 54, 0x8000360C, 0x00000000 },
slouken@0
   141
	{ &GUID_Key, 55, 0x8000370C, 0x00000000 },
slouken@0
   142
	{ &GUID_Key, 56, 0x8000380C, 0x00000000 },
slouken@0
   143
	{ &GUID_Key, 57, 0x8000390C, 0x00000000 },
slouken@0
   144
	{ &GUID_Key, 58, 0x80003A0C, 0x00000000 },
slouken@0
   145
	{ &GUID_Key, 59, 0x80003B0C, 0x00000000 },
slouken@0
   146
	{ &GUID_Key, 60, 0x80003C0C, 0x00000000 },
slouken@0
   147
	{ &GUID_Key, 61, 0x80003D0C, 0x00000000 },
slouken@0
   148
	{ &GUID_Key, 62, 0x80003E0C, 0x00000000 },
slouken@0
   149
	{ &GUID_Key, 63, 0x80003F0C, 0x00000000 },
slouken@0
   150
	{ &GUID_Key, 64, 0x8000400C, 0x00000000 },
slouken@0
   151
	{ &GUID_Key, 65, 0x8000410C, 0x00000000 },
slouken@0
   152
	{ &GUID_Key, 66, 0x8000420C, 0x00000000 },
slouken@0
   153
	{ &GUID_Key, 67, 0x8000430C, 0x00000000 },
slouken@0
   154
	{ &GUID_Key, 68, 0x8000440C, 0x00000000 },
slouken@0
   155
	{ &GUID_Key, 69, 0x8000450C, 0x00000000 },
slouken@0
   156
	{ &GUID_Key, 70, 0x8000460C, 0x00000000 },
slouken@0
   157
	{ &GUID_Key, 71, 0x8000470C, 0x00000000 },
slouken@0
   158
	{ &GUID_Key, 72, 0x8000480C, 0x00000000 },
slouken@0
   159
	{ &GUID_Key, 73, 0x8000490C, 0x00000000 },
slouken@0
   160
	{ &GUID_Key, 74, 0x80004A0C, 0x00000000 },
slouken@0
   161
	{ &GUID_Key, 75, 0x80004B0C, 0x00000000 },
slouken@0
   162
	{ &GUID_Key, 76, 0x80004C0C, 0x00000000 },
slouken@0
   163
	{ &GUID_Key, 77, 0x80004D0C, 0x00000000 },
slouken@0
   164
	{ &GUID_Key, 78, 0x80004E0C, 0x00000000 },
slouken@0
   165
	{ &GUID_Key, 79, 0x80004F0C, 0x00000000 },
slouken@0
   166
	{ &GUID_Key, 80, 0x8000500C, 0x00000000 },
slouken@0
   167
	{ &GUID_Key, 81, 0x8000510C, 0x00000000 },
slouken@0
   168
	{ &GUID_Key, 82, 0x8000520C, 0x00000000 },
slouken@0
   169
	{ &GUID_Key, 83, 0x8000530C, 0x00000000 },
slouken@0
   170
	{ &GUID_Key, 84, 0x8000540C, 0x00000000 },
slouken@0
   171
	{ &GUID_Key, 85, 0x8000550C, 0x00000000 },
slouken@0
   172
	{ &GUID_Key, 86, 0x8000560C, 0x00000000 },
slouken@0
   173
	{ &GUID_Key, 87, 0x8000570C, 0x00000000 },
slouken@0
   174
	{ &GUID_Key, 88, 0x8000580C, 0x00000000 },
slouken@0
   175
	{ &GUID_Key, 89, 0x8000590C, 0x00000000 },
slouken@0
   176
	{ &GUID_Key, 90, 0x80005A0C, 0x00000000 },
slouken@0
   177
	{ &GUID_Key, 91, 0x80005B0C, 0x00000000 },
slouken@0
   178
	{ &GUID_Key, 92, 0x80005C0C, 0x00000000 },
slouken@0
   179
	{ &GUID_Key, 93, 0x80005D0C, 0x00000000 },
slouken@0
   180
	{ &GUID_Key, 94, 0x80005E0C, 0x00000000 },
slouken@0
   181
	{ &GUID_Key, 95, 0x80005F0C, 0x00000000 },
slouken@0
   182
	{ &GUID_Key, 96, 0x8000600C, 0x00000000 },
slouken@0
   183
	{ &GUID_Key, 97, 0x8000610C, 0x00000000 },
slouken@0
   184
	{ &GUID_Key, 98, 0x8000620C, 0x00000000 },
slouken@0
   185
	{ &GUID_Key, 99, 0x8000630C, 0x00000000 },
slouken@0
   186
	{ &GUID_Key, 100, 0x8000640C, 0x00000000 },
slouken@0
   187
	{ &GUID_Key, 101, 0x8000650C, 0x00000000 },
slouken@0
   188
	{ &GUID_Key, 102, 0x8000660C, 0x00000000 },
slouken@0
   189
	{ &GUID_Key, 103, 0x8000670C, 0x00000000 },
slouken@0
   190
	{ &GUID_Key, 104, 0x8000680C, 0x00000000 },
slouken@0
   191
	{ &GUID_Key, 105, 0x8000690C, 0x00000000 },
slouken@0
   192
	{ &GUID_Key, 106, 0x80006A0C, 0x00000000 },
slouken@0
   193
	{ &GUID_Key, 107, 0x80006B0C, 0x00000000 },
slouken@0
   194
	{ &GUID_Key, 108, 0x80006C0C, 0x00000000 },
slouken@0
   195
	{ &GUID_Key, 109, 0x80006D0C, 0x00000000 },
slouken@0
   196
	{ &GUID_Key, 110, 0x80006E0C, 0x00000000 },
slouken@0
   197
	{ &GUID_Key, 111, 0x80006F0C, 0x00000000 },
slouken@0
   198
	{ &GUID_Key, 112, 0x8000700C, 0x00000000 },
slouken@0
   199
	{ &GUID_Key, 113, 0x8000710C, 0x00000000 },
slouken@0
   200
	{ &GUID_Key, 114, 0x8000720C, 0x00000000 },
slouken@0
   201
	{ &GUID_Key, 115, 0x8000730C, 0x00000000 },
slouken@0
   202
	{ &GUID_Key, 116, 0x8000740C, 0x00000000 },
slouken@0
   203
	{ &GUID_Key, 117, 0x8000750C, 0x00000000 },
slouken@0
   204
	{ &GUID_Key, 118, 0x8000760C, 0x00000000 },
slouken@0
   205
	{ &GUID_Key, 119, 0x8000770C, 0x00000000 },
slouken@0
   206
	{ &GUID_Key, 120, 0x8000780C, 0x00000000 },
slouken@0
   207
	{ &GUID_Key, 121, 0x8000790C, 0x00000000 },
slouken@0
   208
	{ &GUID_Key, 122, 0x80007A0C, 0x00000000 },
slouken@0
   209
	{ &GUID_Key, 123, 0x80007B0C, 0x00000000 },
slouken@0
   210
	{ &GUID_Key, 124, 0x80007C0C, 0x00000000 },
slouken@0
   211
	{ &GUID_Key, 125, 0x80007D0C, 0x00000000 },
slouken@0
   212
	{ &GUID_Key, 126, 0x80007E0C, 0x00000000 },
slouken@0
   213
	{ &GUID_Key, 127, 0x80007F0C, 0x00000000 },
slouken@0
   214
	{ &GUID_Key, 128, 0x8000800C, 0x00000000 },
slouken@0
   215
	{ &GUID_Key, 129, 0x8000810C, 0x00000000 },
slouken@0
   216
	{ &GUID_Key, 130, 0x8000820C, 0x00000000 },
slouken@0
   217
	{ &GUID_Key, 131, 0x8000830C, 0x00000000 },
slouken@0
   218
	{ &GUID_Key, 132, 0x8000840C, 0x00000000 },
slouken@0
   219
	{ &GUID_Key, 133, 0x8000850C, 0x00000000 },
slouken@0
   220
	{ &GUID_Key, 134, 0x8000860C, 0x00000000 },
slouken@0
   221
	{ &GUID_Key, 135, 0x8000870C, 0x00000000 },
slouken@0
   222
	{ &GUID_Key, 136, 0x8000880C, 0x00000000 },
slouken@0
   223
	{ &GUID_Key, 137, 0x8000890C, 0x00000000 },
slouken@0
   224
	{ &GUID_Key, 138, 0x80008A0C, 0x00000000 },
slouken@0
   225
	{ &GUID_Key, 139, 0x80008B0C, 0x00000000 },
slouken@0
   226
	{ &GUID_Key, 140, 0x80008C0C, 0x00000000 },
slouken@0
   227
	{ &GUID_Key, 141, 0x80008D0C, 0x00000000 },
slouken@0
   228
	{ &GUID_Key, 142, 0x80008E0C, 0x00000000 },
slouken@0
   229
	{ &GUID_Key, 143, 0x80008F0C, 0x00000000 },
slouken@0
   230
	{ &GUID_Key, 144, 0x8000900C, 0x00000000 },
slouken@0
   231
	{ &GUID_Key, 145, 0x8000910C, 0x00000000 },
slouken@0
   232
	{ &GUID_Key, 146, 0x8000920C, 0x00000000 },
slouken@0
   233
	{ &GUID_Key, 147, 0x8000930C, 0x00000000 },
slouken@0
   234
	{ &GUID_Key, 148, 0x8000940C, 0x00000000 },
slouken@0
   235
	{ &GUID_Key, 149, 0x8000950C, 0x00000000 },
slouken@0
   236
	{ &GUID_Key, 150, 0x8000960C, 0x00000000 },
slouken@0
   237
	{ &GUID_Key, 151, 0x8000970C, 0x00000000 },
slouken@0
   238
	{ &GUID_Key, 152, 0x8000980C, 0x00000000 },
slouken@0
   239
	{ &GUID_Key, 153, 0x8000990C, 0x00000000 },
slouken@0
   240
	{ &GUID_Key, 154, 0x80009A0C, 0x00000000 },
slouken@0
   241
	{ &GUID_Key, 155, 0x80009B0C, 0x00000000 },
slouken@0
   242
	{ &GUID_Key, 156, 0x80009C0C, 0x00000000 },
slouken@0
   243
	{ &GUID_Key, 157, 0x80009D0C, 0x00000000 },
slouken@0
   244
	{ &GUID_Key, 158, 0x80009E0C, 0x00000000 },
slouken@0
   245
	{ &GUID_Key, 159, 0x80009F0C, 0x00000000 },
slouken@0
   246
	{ &GUID_Key, 160, 0x8000A00C, 0x00000000 },
slouken@0
   247
	{ &GUID_Key, 161, 0x8000A10C, 0x00000000 },
slouken@0
   248
	{ &GUID_Key, 162, 0x8000A20C, 0x00000000 },
slouken@0
   249
	{ &GUID_Key, 163, 0x8000A30C, 0x00000000 },
slouken@0
   250
	{ &GUID_Key, 164, 0x8000A40C, 0x00000000 },
slouken@0
   251
	{ &GUID_Key, 165, 0x8000A50C, 0x00000000 },
slouken@0
   252
	{ &GUID_Key, 166, 0x8000A60C, 0x00000000 },
slouken@0
   253
	{ &GUID_Key, 167, 0x8000A70C, 0x00000000 },
slouken@0
   254
	{ &GUID_Key, 168, 0x8000A80C, 0x00000000 },
slouken@0
   255
	{ &GUID_Key, 169, 0x8000A90C, 0x00000000 },
slouken@0
   256
	{ &GUID_Key, 170, 0x8000AA0C, 0x00000000 },
slouken@0
   257
	{ &GUID_Key, 171, 0x8000AB0C, 0x00000000 },
slouken@0
   258
	{ &GUID_Key, 172, 0x8000AC0C, 0x00000000 },
slouken@0
   259
	{ &GUID_Key, 173, 0x8000AD0C, 0x00000000 },
slouken@0
   260
	{ &GUID_Key, 174, 0x8000AE0C, 0x00000000 },
slouken@0
   261
	{ &GUID_Key, 175, 0x8000AF0C, 0x00000000 },
slouken@0
   262
	{ &GUID_Key, 176, 0x8000B00C, 0x00000000 },
slouken@0
   263
	{ &GUID_Key, 177, 0x8000B10C, 0x00000000 },
slouken@0
   264
	{ &GUID_Key, 178, 0x8000B20C, 0x00000000 },
slouken@0
   265
	{ &GUID_Key, 179, 0x8000B30C, 0x00000000 },
slouken@0
   266
	{ &GUID_Key, 180, 0x8000B40C, 0x00000000 },
slouken@0
   267
	{ &GUID_Key, 181, 0x8000B50C, 0x00000000 },
slouken@0
   268
	{ &GUID_Key, 182, 0x8000B60C, 0x00000000 },
slouken@0
   269
	{ &GUID_Key, 183, 0x8000B70C, 0x00000000 },
slouken@0
   270
	{ &GUID_Key, 184, 0x8000B80C, 0x00000000 },
slouken@0
   271
	{ &GUID_Key, 185, 0x8000B90C, 0x00000000 },
slouken@0
   272
	{ &GUID_Key, 186, 0x8000BA0C, 0x00000000 },
slouken@0
   273
	{ &GUID_Key, 187, 0x8000BB0C, 0x00000000 },
slouken@0
   274
	{ &GUID_Key, 188, 0x8000BC0C, 0x00000000 },
slouken@0
   275
	{ &GUID_Key, 189, 0x8000BD0C, 0x00000000 },
slouken@0
   276
	{ &GUID_Key, 190, 0x8000BE0C, 0x00000000 },
slouken@0
   277
	{ &GUID_Key, 191, 0x8000BF0C, 0x00000000 },
slouken@0
   278
	{ &GUID_Key, 192, 0x8000C00C, 0x00000000 },
slouken@0
   279
	{ &GUID_Key, 193, 0x8000C10C, 0x00000000 },
slouken@0
   280
	{ &GUID_Key, 194, 0x8000C20C, 0x00000000 },
slouken@0
   281
	{ &GUID_Key, 195, 0x8000C30C, 0x00000000 },
slouken@0
   282
	{ &GUID_Key, 196, 0x8000C40C, 0x00000000 },
slouken@0
   283
	{ &GUID_Key, 197, 0x8000C50C, 0x00000000 },
slouken@0
   284
	{ &GUID_Key, 198, 0x8000C60C, 0x00000000 },
slouken@0
   285
	{ &GUID_Key, 199, 0x8000C70C, 0x00000000 },
slouken@0
   286
	{ &GUID_Key, 200, 0x8000C80C, 0x00000000 },
slouken@0
   287
	{ &GUID_Key, 201, 0x8000C90C, 0x00000000 },
slouken@0
   288
	{ &GUID_Key, 202, 0x8000CA0C, 0x00000000 },
slouken@0
   289
	{ &GUID_Key, 203, 0x8000CB0C, 0x00000000 },
slouken@0
   290
	{ &GUID_Key, 204, 0x8000CC0C, 0x00000000 },
slouken@0
   291
	{ &GUID_Key, 205, 0x8000CD0C, 0x00000000 },
slouken@0
   292
	{ &GUID_Key, 206, 0x8000CE0C, 0x00000000 },
slouken@0
   293
	{ &GUID_Key, 207, 0x8000CF0C, 0x00000000 },
slouken@0
   294
	{ &GUID_Key, 208, 0x8000D00C, 0x00000000 },
slouken@0
   295
	{ &GUID_Key, 209, 0x8000D10C, 0x00000000 },
slouken@0
   296
	{ &GUID_Key, 210, 0x8000D20C, 0x00000000 },
slouken@0
   297
	{ &GUID_Key, 211, 0x8000D30C, 0x00000000 },
slouken@0
   298
	{ &GUID_Key, 212, 0x8000D40C, 0x00000000 },
slouken@0
   299
	{ &GUID_Key, 213, 0x8000D50C, 0x00000000 },
slouken@0
   300
	{ &GUID_Key, 214, 0x8000D60C, 0x00000000 },
slouken@0
   301
	{ &GUID_Key, 215, 0x8000D70C, 0x00000000 },
slouken@0
   302
	{ &GUID_Key, 216, 0x8000D80C, 0x00000000 },
slouken@0
   303
	{ &GUID_Key, 217, 0x8000D90C, 0x00000000 },
slouken@0
   304
	{ &GUID_Key, 218, 0x8000DA0C, 0x00000000 },
slouken@0
   305
	{ &GUID_Key, 219, 0x8000DB0C, 0x00000000 },
slouken@0
   306
	{ &GUID_Key, 220, 0x8000DC0C, 0x00000000 },
slouken@0
   307
	{ &GUID_Key, 221, 0x8000DD0C, 0x00000000 },
slouken@0
   308
	{ &GUID_Key, 222, 0x8000DE0C, 0x00000000 },
slouken@0
   309
	{ &GUID_Key, 223, 0x8000DF0C, 0x00000000 },
slouken@0
   310
	{ &GUID_Key, 224, 0x8000E00C, 0x00000000 },
slouken@0
   311
	{ &GUID_Key, 225, 0x8000E10C, 0x00000000 },
slouken@0
   312
	{ &GUID_Key, 226, 0x8000E20C, 0x00000000 },
slouken@0
   313
	{ &GUID_Key, 227, 0x8000E30C, 0x00000000 },
slouken@0
   314
	{ &GUID_Key, 228, 0x8000E40C, 0x00000000 },
slouken@0
   315
	{ &GUID_Key, 229, 0x8000E50C, 0x00000000 },
slouken@0
   316
	{ &GUID_Key, 230, 0x8000E60C, 0x00000000 },
slouken@0
   317
	{ &GUID_Key, 231, 0x8000E70C, 0x00000000 },
slouken@0
   318
	{ &GUID_Key, 232, 0x8000E80C, 0x00000000 },
slouken@0
   319
	{ &GUID_Key, 233, 0x8000E90C, 0x00000000 },
slouken@0
   320
	{ &GUID_Key, 234, 0x8000EA0C, 0x00000000 },
slouken@0
   321
	{ &GUID_Key, 235, 0x8000EB0C, 0x00000000 },
slouken@0
   322
	{ &GUID_Key, 236, 0x8000EC0C, 0x00000000 },
slouken@0
   323
	{ &GUID_Key, 237, 0x8000ED0C, 0x00000000 },
slouken@0
   324
	{ &GUID_Key, 238, 0x8000EE0C, 0x00000000 },
slouken@0
   325
	{ &GUID_Key, 239, 0x8000EF0C, 0x00000000 },
slouken@0
   326
	{ &GUID_Key, 240, 0x8000F00C, 0x00000000 },
slouken@0
   327
	{ &GUID_Key, 241, 0x8000F10C, 0x00000000 },
slouken@0
   328
	{ &GUID_Key, 242, 0x8000F20C, 0x00000000 },
slouken@0
   329
	{ &GUID_Key, 243, 0x8000F30C, 0x00000000 },
slouken@0
   330
	{ &GUID_Key, 244, 0x8000F40C, 0x00000000 },
slouken@0
   331
	{ &GUID_Key, 245, 0x8000F50C, 0x00000000 },
slouken@0
   332
	{ &GUID_Key, 246, 0x8000F60C, 0x00000000 },
slouken@0
   333
	{ &GUID_Key, 247, 0x8000F70C, 0x00000000 },
slouken@0
   334
	{ &GUID_Key, 248, 0x8000F80C, 0x00000000 },
slouken@0
   335
	{ &GUID_Key, 249, 0x8000F90C, 0x00000000 },
slouken@0
   336
	{ &GUID_Key, 250, 0x8000FA0C, 0x00000000 },
slouken@0
   337
	{ &GUID_Key, 251, 0x8000FB0C, 0x00000000 },
slouken@0
   338
	{ &GUID_Key, 252, 0x8000FC0C, 0x00000000 },
slouken@0
   339
	{ &GUID_Key, 253, 0x8000FD0C, 0x00000000 },
slouken@0
   340
	{ &GUID_Key, 254, 0x8000FE0C, 0x00000000 },
slouken@0
   341
	{ &GUID_Key, 255, 0x8000FF0C, 0x00000000 },
slouken@0
   342
};
slouken@0
   343
slouken@0
   344
const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
slouken@0
   345
slouken@0
   346
slouken@0
   347
/* Mouse */
slouken@0
   348
slouken@0
   349
static DIOBJECTDATAFORMAT PTR_fmt[] = {
slouken@0
   350
	{ &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 },
slouken@0
   351
	{ &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 },
slouken@0
   352
	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 },
slouken@0
   353
	{ NULL, 12, 0x00FFFF0C, 0x00000000 },
slouken@0
   354
	{ NULL, 13, 0x00FFFF0C, 0x00000000 },
slouken@0
   355
	{ NULL, 14, 0x80FFFF0C, 0x00000000 },
slouken@0
   356
	{ NULL, 15, 0x80FFFF0C, 0x00000000 },
slouken@0
   357
};
slouken@0
   358
slouken@0
   359
const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
slouken@0
   360
slouken@0
   361
slouken@0
   362
/* Joystick */
slouken@0
   363
slouken@0
   364
static DIOBJECTDATAFORMAT JOY_fmt[] = {
slouken@0
   365
	{ &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 },
slouken@0
   366
	{ &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 },
slouken@0
   367
	{ &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 },
slouken@0
   368
	{ &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 },
slouken@0
   369
	{ &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 },
slouken@0
   370
	{ &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 },
slouken@0
   371
	{ &GUID_Slider, 24, 0x80FFFF03, 0x00000100 },
slouken@0
   372
	{ &GUID_Slider, 28, 0x80FFFF03, 0x00000100 },
slouken@0
   373
	{ &GUID_POV, 32, 0x80FFFF10, 0x00000000 },
slouken@0
   374
	{ &GUID_POV, 36, 0x80FFFF10, 0x00000000 },
slouken@0
   375
	{ &GUID_POV, 40, 0x80FFFF10, 0x00000000 },
slouken@0
   376
	{ &GUID_POV, 44, 0x80FFFF10, 0x00000000 },
slouken@0
   377
	{ NULL, 48, 0x80FFFF0C, 0x00000000 },
slouken@0
   378
	{ NULL, 49, 0x80FFFF0C, 0x00000000 },
slouken@0
   379
	{ NULL, 50, 0x80FFFF0C, 0x00000000 },
slouken@0
   380
	{ NULL, 51, 0x80FFFF0C, 0x00000000 },
slouken@0
   381
	{ NULL, 52, 0x80FFFF0C, 0x00000000 },
slouken@0
   382
	{ NULL, 53, 0x80FFFF0C, 0x00000000 },
slouken@0
   383
	{ NULL, 54, 0x80FFFF0C, 0x00000000 },
slouken@0
   384
	{ NULL, 55, 0x80FFFF0C, 0x00000000 },
slouken@0
   385
	{ NULL, 56, 0x80FFFF0C, 0x00000000 },
slouken@0
   386
	{ NULL, 57, 0x80FFFF0C, 0x00000000 },
slouken@0
   387
	{ NULL, 58, 0x80FFFF0C, 0x00000000 },
slouken@0
   388
	{ NULL, 59, 0x80FFFF0C, 0x00000000 },
slouken@0
   389
	{ NULL, 60, 0x80FFFF0C, 0x00000000 },
slouken@0
   390
	{ NULL, 61, 0x80FFFF0C, 0x00000000 },
slouken@0
   391
	{ NULL, 62, 0x80FFFF0C, 0x00000000 },
slouken@0
   392
	{ NULL, 63, 0x80FFFF0C, 0x00000000 },
slouken@0
   393
	{ NULL, 64, 0x80FFFF0C, 0x00000000 },
slouken@0
   394
	{ NULL, 65, 0x80FFFF0C, 0x00000000 },
slouken@0
   395
	{ NULL, 66, 0x80FFFF0C, 0x00000000 },
slouken@0
   396
	{ NULL, 67, 0x80FFFF0C, 0x00000000 },
slouken@0
   397
	{ NULL, 68, 0x80FFFF0C, 0x00000000 },
slouken@0
   398
	{ NULL, 69, 0x80FFFF0C, 0x00000000 },
slouken@0
   399
	{ NULL, 70, 0x80FFFF0C, 0x00000000 },
slouken@0
   400
	{ NULL, 71, 0x80FFFF0C, 0x00000000 },
slouken@0
   401
	{ NULL, 72, 0x80FFFF0C, 0x00000000 },
slouken@0
   402
	{ NULL, 73, 0x80FFFF0C, 0x00000000 },
slouken@0
   403
	{ NULL, 74, 0x80FFFF0C, 0x00000000 },
slouken@0
   404
	{ NULL, 75, 0x80FFFF0C, 0x00000000 },
slouken@0
   405
	{ NULL, 76, 0x80FFFF0C, 0x00000000 },
slouken@0
   406
	{ NULL, 77, 0x80FFFF0C, 0x00000000 },
slouken@0
   407
	{ NULL, 78, 0x80FFFF0C, 0x00000000 },
slouken@0
   408
	{ NULL, 79, 0x80FFFF0C, 0x00000000 },
slouken@0
   409
};
slouken@0
   410
slouken@0
   411
const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
slouken@0
   412
slouken@0
   413
slouken@0
   414
/* Initialization/Query functions */
slouken@0
   415
static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
slouken@0
   416
static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
slouken@0
   417
static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
slouken@0
   418
static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
slouken@0
   419
			 SDL_Color *colors);
slouken@0
   420
static int DX5_SetGammaRamp(_THIS, Uint16 *ramp);
slouken@0
   421
static int DX5_GetGammaRamp(_THIS, Uint16 *ramp);
slouken@0
   422
static void DX5_VideoQuit(_THIS);
slouken@0
   423
slouken@0
   424
/* Hardware surface functions */
slouken@0
   425
static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface);
slouken@0
   426
static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
slouken@0
   427
static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
slouken@0
   428
static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
slouken@0
   429
static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
slouken@0
   430
static int DX5_LockHWSurface(_THIS, SDL_Surface *surface);
slouken@0
   431
static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface);
slouken@0
   432
static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface);
slouken@0
   433
static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface);
slouken@0
   434
slouken@0
   435
static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
slouken@0
   436
				LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
slouken@0
   437
slouken@0
   438
/* Windows message handling functions */
slouken@0
   439
static void DX5_RealizePalette(_THIS);
slouken@0
   440
static void DX5_PaletteChanged(_THIS, HWND window);
slouken@0
   441
static void DX5_WinPAINT(_THIS, HDC hdc);
slouken@0
   442
slouken@338
   443
/* WinDIB driver functions for manipulating gamma ramps */
slouken@338
   444
extern int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
slouken@338
   445
extern int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
slouken@338
   446
extern void DIB_QuitGamma(_THIS);
slouken@338
   447
slouken@0
   448
/* DX5 driver bootstrap functions */
slouken@0
   449
slouken@0
   450
static int DX5_Available(void)
slouken@0
   451
{
slouken@0
   452
	HINSTANCE DInputDLL;
slouken@0
   453
	HINSTANCE DDrawDLL;
slouken@0
   454
	int dinput_ok;
slouken@0
   455
	int ddraw_ok;
slouken@0
   456
slouken@0
   457
	/* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
slouken@0
   458
	dinput_ok = 0;
slouken@453
   459
	DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
slouken@0
   460
	if ( DInputDLL != NULL ) {
slouken@0
   461
		dinput_ok = 1;
slouken@0
   462
	  	FreeLibrary(DInputDLL);
slouken@0
   463
	}
slouken@0
   464
	ddraw_ok = 0;
slouken@453
   465
	DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
slouken@0
   466
	if ( DDrawDLL != NULL ) {
slouken@0
   467
	  HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
slouken@0
   468
	  LPDIRECTDRAW DDraw;
slouken@0
   469
slouken@0
   470
	  /* Try to create a valid DirectDraw object */
slouken@453
   471
	  DDrawCreate = (void *)GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate"));
slouken@0
   472
	  if ( (DDrawCreate != NULL)
slouken@0
   473
			&& !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
slouken@0
   474
	    if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
slouken@0
   475
							NULL, DDSCL_NORMAL)) ) {
slouken@0
   476
	      DDSURFACEDESC desc;
slouken@0
   477
	      LPDIRECTDRAWSURFACE  DDrawSurf;
slouken@0
   478
	      LPDIRECTDRAWSURFACE3 DDrawSurf3;
slouken@0
   479
slouken@0
   480
	      /* Try to create a DirectDrawSurface3 object */
slouken@0
   481
	      memset(&desc, 0, sizeof(desc));
slouken@0
   482
	      desc.dwSize = sizeof(desc);
slouken@0
   483
	      desc.dwFlags = DDSD_CAPS;
slouken@0
   484
	      desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
slouken@0
   485
	      if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
slouken@0
   486
							&DDrawSurf, NULL)) ) {
slouken@0
   487
	        if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
slouken@0
   488
			&IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
slouken@0
   489
	          /* Yay! */
slouken@0
   490
		  ddraw_ok = 1;
slouken@0
   491
slouken@0
   492
	          /* Clean up.. */
slouken@0
   493
	          IDirectDrawSurface3_Release(DDrawSurf3);
slouken@0
   494
	        }
slouken@0
   495
	        IDirectDrawSurface_Release(DDrawSurf);
slouken@0
   496
	      }
slouken@0
   497
	    }
slouken@0
   498
	    IDirectDraw_Release(DDraw);
slouken@0
   499
	  }
slouken@0
   500
	  FreeLibrary(DDrawDLL);
slouken@0
   501
	}
slouken@0
   502
	return(dinput_ok && ddraw_ok);
slouken@0
   503
}
slouken@0
   504
slouken@0
   505
/* Functions for loading the DirectX functions dynamically */
slouken@0
   506
static HINSTANCE DDrawDLL = NULL;
slouken@0
   507
static HINSTANCE DInputDLL = NULL;
slouken@0
   508
slouken@0
   509
static void DX5_Unload(void)
slouken@0
   510
{
slouken@0
   511
	if ( DDrawDLL != NULL ) {
slouken@0
   512
		FreeLibrary(DDrawDLL);
slouken@0
   513
		DDrawCreate = NULL;
slouken@0
   514
		DDrawDLL = NULL;
slouken@0
   515
	}
slouken@0
   516
	if ( DInputDLL != NULL ) {
slouken@0
   517
		FreeLibrary(DInputDLL);
slouken@0
   518
		DInputCreate = NULL;
slouken@0
   519
		DInputDLL = NULL;
slouken@0
   520
	}
slouken@0
   521
}
slouken@0
   522
static int DX5_Load(void)
slouken@0
   523
{
slouken@0
   524
	int status;
slouken@0
   525
slouken@0
   526
	DX5_Unload();
slouken@453
   527
	DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL"));
slouken@0
   528
	if ( DDrawDLL != NULL ) {
slouken@0
   529
		DDrawCreate = (void *)GetProcAddress(DDrawDLL,
slouken@453
   530
					TEXT("DirectDrawCreate"));
slouken@0
   531
	}
slouken@453
   532
	DInputDLL = LoadLibrary(TEXT("DINPUT.DLL"));
slouken@0
   533
	if ( DInputDLL != NULL ) {
slouken@0
   534
		DInputCreate = (void *)GetProcAddress(DInputDLL,
slouken@453
   535
					TEXT("DirectInputCreateA"));
slouken@0
   536
	}
slouken@0
   537
	if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) {
slouken@0
   538
		status = 0;
slouken@0
   539
	} else {
slouken@0
   540
		DX5_Unload();
slouken@0
   541
		status = -1;
slouken@0
   542
	}
slouken@0
   543
	return status;
slouken@0
   544
}
slouken@0
   545
slouken@0
   546
static void DX5_DeleteDevice(SDL_VideoDevice *this)
slouken@0
   547
{
slouken@0
   548
	/* Free DirectDraw object */
slouken@0
   549
	if ( ddraw2 != NULL ) {
slouken@0
   550
		IDirectDraw2_Release(ddraw2);
slouken@0
   551
	}
slouken@0
   552
	DX5_Unload();
slouken@0
   553
	if ( this ) {
slouken@0
   554
		if ( this->hidden ) {
slouken@0
   555
			free(this->hidden);
slouken@0
   556
		}
slouken@0
   557
		if ( this->gl_data ) {
slouken@0
   558
			free(this->gl_data);
slouken@0
   559
		}
slouken@0
   560
		free(this);
slouken@0
   561
	}
slouken@0
   562
}
slouken@0
   563
slouken@0
   564
static SDL_VideoDevice *DX5_CreateDevice(int devindex)
slouken@0
   565
{
slouken@0
   566
	SDL_VideoDevice *device;
slouken@0
   567
slouken@0
   568
	/* Load DirectX */
slouken@0
   569
	if ( DX5_Load() < 0 ) {
slouken@0
   570
		return(NULL);
slouken@0
   571
	}
slouken@0
   572
slouken@0
   573
	/* Initialize all variables that we clean on shutdown */
slouken@0
   574
	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
slouken@0
   575
	if ( device ) {
slouken@0
   576
		memset(device, 0, (sizeof *device));
slouken@0
   577
		device->hidden = (struct SDL_PrivateVideoData *)
slouken@0
   578
				malloc((sizeof *device->hidden));
slouken@0
   579
		device->gl_data = (struct SDL_PrivateGLData *)
slouken@0
   580
				malloc((sizeof *device->gl_data));
slouken@0
   581
	}
slouken@0
   582
	if ( (device == NULL) || (device->hidden == NULL) ||
slouken@0
   583
		                 (device->gl_data == NULL) ) {
slouken@0
   584
		SDL_OutOfMemory();
slouken@0
   585
		DX5_DeleteDevice(device);
slouken@0
   586
		return(NULL);
slouken@0
   587
	}
slouken@0
   588
	memset(device->hidden, 0, (sizeof *device->hidden));
slouken@0
   589
	memset(device->gl_data, 0, (sizeof *device->gl_data));
slouken@0
   590
slouken@0
   591
	/* Set the function pointers */
slouken@0
   592
	device->VideoInit = DX5_VideoInit;
slouken@0
   593
	device->ListModes = DX5_ListModes;
slouken@0
   594
	device->SetVideoMode = DX5_SetVideoMode;
slouken@0
   595
	device->UpdateMouse = WIN_UpdateMouse;
slouken@0
   596
	device->CreateYUVOverlay = DX5_CreateYUVOverlay;
slouken@0
   597
	device->SetColors = DX5_SetColors;
slouken@0
   598
	device->UpdateRects = NULL;
slouken@0
   599
	device->VideoQuit = DX5_VideoQuit;
slouken@0
   600
	device->AllocHWSurface = DX5_AllocHWSurface;
slouken@0
   601
	device->CheckHWBlit = DX5_CheckHWBlit;
slouken@0
   602
	device->FillHWRect = DX5_FillHWRect;
slouken@0
   603
	device->SetHWColorKey = DX5_SetHWColorKey;
slouken@0
   604
	device->SetHWAlpha = DX5_SetHWAlpha;
slouken@0
   605
	device->LockHWSurface = DX5_LockHWSurface;
slouken@0
   606
	device->UnlockHWSurface = DX5_UnlockHWSurface;
slouken@0
   607
	device->FlipHWSurface = DX5_FlipHWSurface;
slouken@0
   608
	device->FreeHWSurface = DX5_FreeHWSurface;
slouken@0
   609
	device->SetGammaRamp = DX5_SetGammaRamp;
slouken@0
   610
	device->GetGammaRamp = DX5_GetGammaRamp;
slouken@0
   611
#ifdef HAVE_OPENGL
slouken@453
   612
	device->GL_LoadLibrary = WIN_GL_LoadLibrary;
slouken@453
   613
	device->GL_GetProcAddress = WIN_GL_GetProcAddress;
slouken@453
   614
	device->GL_GetAttribute = WIN_GL_GetAttribute;
slouken@453
   615
	device->GL_MakeCurrent = WIN_GL_MakeCurrent;
slouken@453
   616
	device->GL_SwapBuffers = WIN_GL_SwapBuffers;
slouken@0
   617
#endif
slouken@0
   618
	device->SetCaption = WIN_SetWMCaption;
slouken@0
   619
	device->SetIcon = WIN_SetWMIcon;
slouken@0
   620
	device->IconifyWindow = WIN_IconifyWindow;
slouken@0
   621
	device->GrabInput = WIN_GrabInput;
slouken@0
   622
	device->GetWMInfo = WIN_GetWMInfo;
slouken@0
   623
	device->FreeWMCursor = WIN_FreeWMCursor;
slouken@0
   624
	device->CreateWMCursor = WIN_CreateWMCursor;
slouken@0
   625
	device->ShowWMCursor = WIN_ShowWMCursor;
slouken@0
   626
	device->WarpWMCursor = WIN_WarpWMCursor;
slouken@0
   627
	device->CheckMouseMode = WIN_CheckMouseMode;
slouken@0
   628
	device->InitOSKeymap = DX5_InitOSKeymap;
slouken@0
   629
	device->PumpEvents = DX5_PumpEvents;
slouken@0
   630
slouken@0
   631
	/* Set up the windows message handling functions */
slouken@0
   632
	WIN_RealizePalette = DX5_RealizePalette;
slouken@0
   633
	WIN_PaletteChanged = DX5_PaletteChanged;
slouken@0
   634
	WIN_WinPAINT = DX5_WinPAINT;
slouken@0
   635
	HandleMessage = DX5_HandleMessage;
slouken@0
   636
slouken@0
   637
	device->free = DX5_DeleteDevice;
slouken@0
   638
slouken@0
   639
	/* We're finally ready */
slouken@0
   640
	return device;
slouken@0
   641
}
slouken@0
   642
slouken@0
   643
VideoBootStrap DIRECTX_bootstrap = {
slouken@0
   644
	"directx", "Win95/98/2000 DirectX",
slouken@0
   645
	DX5_Available, DX5_CreateDevice
slouken@0
   646
};
slouken@0
   647
slouken@0
   648
static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
slouken@0
   649
{
slouken@0
   650
	SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
slouken@0
   651
	struct DX5EnumRect *enumrect;
slouken@0
   652
#if defined(NONAMELESSUNION)
slouken@0
   653
	int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
slouken@809
   654
	int refreshRate = desc->u2.dwRefreshRate;
slouken@0
   655
#else
slouken@0
   656
	int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
slouken@809
   657
	int refreshRate = desc->dwRefreshRate;
slouken@0
   658
#endif
slouken@0
   659
slouken@0
   660
	switch (bpp)  {
slouken@0
   661
		case 8:
slouken@0
   662
		case 16:
slouken@0
   663
		case 24:
slouken@0
   664
		case 32:
slouken@0
   665
			bpp /= 8; --bpp;
slouken@809
   666
			if ( enumlists[bpp] &&
slouken@809
   667
			     enumlists[bpp]->r.w == (Uint16)desc->dwWidth &&
slouken@809
   668
			     enumlists[bpp]->r.h == (Uint16)desc->dwHeight ) {
slouken@809
   669
				if ( refreshRate > enumlists[bpp]->refreshRate &&
slouken@809
   670
				     refreshRate <= 85 /* safe value? */ ) {
slouken@809
   671
					enumlists[bpp]->refreshRate = refreshRate;
slouken@809
   672
printf("New refresh rate for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
slouken@809
   673
				}
slouken@809
   674
				break;
slouken@809
   675
			}
slouken@0
   676
			++SDL_nummodes[bpp];
slouken@0
   677
			enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
slouken@0
   678
			if ( !enumrect ) {
slouken@0
   679
				SDL_OutOfMemory();
slouken@0
   680
				return(DDENUMRET_CANCEL);
slouken@0
   681
			}
slouken@809
   682
			enumrect->refreshRate = refreshRate;
slouken@0
   683
			enumrect->r.x = 0;
slouken@0
   684
			enumrect->r.y = 0;
slouken@0
   685
			enumrect->r.w = (Uint16)desc->dwWidth;
slouken@0
   686
			enumrect->r.h = (Uint16)desc->dwHeight;
slouken@0
   687
			enumrect->next = enumlists[bpp];
slouken@0
   688
			enumlists[bpp] = enumrect;
slouken@809
   689
printf("New mode for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
slouken@0
   690
			break;
slouken@0
   691
	}
slouken@0
   692
slouken@0
   693
	return(DDENUMRET_OK);
slouken@0
   694
}
slouken@0
   695
slouken@0
   696
void SetDDerror(const char *function, int code)
slouken@0
   697
{
slouken@0
   698
	static char *error;
slouken@453
   699
	static char  errbuf[1024];
slouken@0
   700
slouken@0
   701
	errbuf[0] = 0;
slouken@0
   702
	switch (code) {
slouken@0
   703
		case DDERR_GENERIC:
slouken@0
   704
			error = "Undefined error!";
slouken@0
   705
			break;
slouken@0
   706
		case DDERR_EXCEPTION:
slouken@0
   707
			error = "Exception encountered";
slouken@0
   708
			break;
slouken@0
   709
		case DDERR_INVALIDOBJECT:
slouken@0
   710
			error = "Invalid object";
slouken@0
   711
			break;
slouken@0
   712
		case DDERR_INVALIDPARAMS:
slouken@0
   713
			error = "Invalid parameters";
slouken@0
   714
			break;
slouken@0
   715
		case DDERR_NOTFOUND:
slouken@0
   716
			error = "Object not found";
slouken@0
   717
			break;
slouken@0
   718
		case DDERR_INVALIDRECT:
slouken@0
   719
			error = "Invalid rectangle";
slouken@0
   720
			break;
slouken@0
   721
		case DDERR_INVALIDCAPS:
slouken@0
   722
			error = "Invalid caps member";
slouken@0
   723
			break;
slouken@0
   724
		case DDERR_INVALIDPIXELFORMAT:
slouken@0
   725
			error = "Invalid pixel format";
slouken@0
   726
			break;
slouken@0
   727
		case DDERR_OUTOFMEMORY:
slouken@0
   728
			error = "Out of memory";
slouken@0
   729
			break;
slouken@0
   730
		case DDERR_OUTOFVIDEOMEMORY:
slouken@0
   731
			error = "Out of video memory";
slouken@0
   732
			break;
slouken@0
   733
		case DDERR_SURFACEBUSY:
slouken@0
   734
			error = "Surface busy";
slouken@0
   735
			break;
slouken@0
   736
		case DDERR_SURFACELOST:
slouken@0
   737
			error = "Surface was lost";
slouken@0
   738
			break;
slouken@0
   739
		case DDERR_WASSTILLDRAWING:
slouken@0
   740
			error = "DirectDraw is still drawing";
slouken@0
   741
			break;
slouken@0
   742
		case DDERR_INVALIDSURFACETYPE:
slouken@0
   743
			error = "Invalid surface type";
slouken@0
   744
			break;
slouken@0
   745
		case DDERR_NOEXCLUSIVEMODE:
slouken@0
   746
			error = "Not in exclusive access mode";
slouken@0
   747
			break;
slouken@0
   748
		case DDERR_NOPALETTEATTACHED:
slouken@0
   749
			error = "No palette attached";
slouken@0
   750
			break;
slouken@0
   751
		case DDERR_NOPALETTEHW:
slouken@0
   752
			error = "No palette hardware";
slouken@0
   753
			break;
slouken@0
   754
		case DDERR_NOT8BITCOLOR:
slouken@0
   755
			error = "Not 8-bit color";
slouken@0
   756
			break;
slouken@0
   757
		case DDERR_EXCLUSIVEMODEALREADYSET:
slouken@0
   758
			error = "Exclusive mode was already set";
slouken@0
   759
			break;
slouken@0
   760
		case DDERR_HWNDALREADYSET:
slouken@0
   761
			error = "Window handle already set";
slouken@0
   762
			break;
slouken@0
   763
		case DDERR_HWNDSUBCLASSED:
slouken@0
   764
			error = "Window handle is subclassed";
slouken@0
   765
			break;
slouken@0
   766
		case DDERR_NOBLTHW:
slouken@0
   767
			error = "No blit hardware";
slouken@0
   768
			break;
slouken@0
   769
		case DDERR_IMPLICITLYCREATED:
slouken@0
   770
			error = "Surface was implicitly created";
slouken@0
   771
			break;
slouken@0
   772
		case DDERR_INCOMPATIBLEPRIMARY:
slouken@0
   773
			error = "Incompatible primary surface";
slouken@0
   774
			break;
slouken@0
   775
		case DDERR_NOCOOPERATIVELEVELSET:
slouken@0
   776
			error = "No cooperative level set";
slouken@0
   777
			break;
slouken@0
   778
		case DDERR_NODIRECTDRAWHW:
slouken@0
   779
			error = "No DirectDraw hardware";
slouken@0
   780
			break;
slouken@0
   781
		case DDERR_NOEMULATION:
slouken@0
   782
			error = "No emulation available";
slouken@0
   783
			break;
slouken@0
   784
		case DDERR_NOFLIPHW:
slouken@0
   785
			error = "No flip hardware";
slouken@0
   786
			break;
slouken@0
   787
		case DDERR_NOTFLIPPABLE:
slouken@0
   788
			error = "Surface not flippable";
slouken@0
   789
			break;
slouken@0
   790
		case DDERR_PRIMARYSURFACEALREADYEXISTS:
slouken@0
   791
			error = "Primary surface already exists";
slouken@0
   792
			break;
slouken@0
   793
		case DDERR_UNSUPPORTEDMODE:
slouken@0
   794
			error = "Unsupported mode";
slouken@0
   795
			break;
slouken@0
   796
		case DDERR_WRONGMODE:
slouken@0
   797
			error = "Surface created in different mode";
slouken@0
   798
			break;
slouken@0
   799
		case DDERR_UNSUPPORTED:
slouken@0
   800
			error = "Operation not supported";
slouken@0
   801
			break;
slouken@0
   802
		case E_NOINTERFACE:
slouken@0
   803
			error = "Interface not present";
slouken@0
   804
			break;
slouken@0
   805
		default:
slouken@0
   806
			sprintf(errbuf, "%s: Unknown DirectDraw error: 0x%x",
slouken@0
   807
								function, code);
slouken@0
   808
			break;
slouken@0
   809
	}
slouken@0
   810
	if ( ! errbuf[0] ) {
slouken@0
   811
		sprintf(errbuf, "%s: %s", function, error);
slouken@0
   812
	}
slouken@0
   813
	SDL_SetError("%s", errbuf);
slouken@0
   814
	return;
slouken@0
   815
}
slouken@0
   816
slouken@0
   817
slouken@0
   818
static int DX5_UpdateVideoInfo(_THIS)
slouken@0
   819
{
slouken@0
   820
	/* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
slouken@0
   821
#if DIRECTDRAW_VERSION <= 0x300
slouken@0
   822
#error Your version of DirectX must be greater than or equal to 5.0
slouken@0
   823
#endif
slouken@334
   824
#ifndef IDirectDrawGammaControl_SetGammaRamp
slouken@0
   825
	/*if gamma is undefined then we really have directx <= 0x500*/
slouken@0
   826
	DDCAPS DDCaps;
slouken@0
   827
#else
slouken@0
   828
	DDCAPS_DX5 DDCaps;
slouken@0
   829
#endif
slouken@0
   830
	HRESULT result;
slouken@0
   831
slouken@0
   832
	/* Fill in our hardware acceleration capabilities */
slouken@0
   833
	memset(&DDCaps, 0, sizeof(DDCaps));
slouken@0
   834
	DDCaps.dwSize = sizeof(DDCaps);
slouken@0
   835
	result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
slouken@0
   836
	if ( result != DD_OK ) {
slouken@0
   837
		SetDDerror("DirectDraw2::GetCaps", result);
slouken@0
   838
		return(-1);
slouken@0
   839
	}
slouken@0
   840
	this->info.hw_available = 1;
slouken@0
   841
	if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
slouken@0
   842
		this->info.blit_hw = 1;
slouken@0
   843
	}
slouken@0
   844
	if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
slouken@0
   845
	     ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
slouken@0
   846
		this->info.blit_hw_CC = 1;
slouken@0
   847
	}
slouken@0
   848
	if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
slouken@0
   849
		/* This is only for alpha channel, and DirectX 6
slouken@0
   850
		   doesn't support 2D alpha blits yet, so set it 0
slouken@0
   851
		 */
slouken@0
   852
		this->info.blit_hw_A = 0;
slouken@0
   853
	}
slouken@0
   854
	if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
slouken@0
   855
		this->info.blit_sw = 1;
slouken@0
   856
		/* This isn't necessarily true, but the HEL will cover us */
slouken@0
   857
		this->info.blit_sw_CC = this->info.blit_hw_CC;
slouken@0
   858
		this->info.blit_sw_A = this->info.blit_hw_A;
slouken@0
   859
	}
slouken@0
   860
	if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
slouken@0
   861
		this->info.blit_fill = 1;
slouken@0
   862
	}
slouken@0
   863
slouken@0
   864
	/* Find out how much video memory is available */
slouken@0
   865
	{ DDSCAPS ddsCaps;
slouken@0
   866
	  DWORD total_mem;
slouken@0
   867
		ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
slouken@0
   868
		result = IDirectDraw2_GetAvailableVidMem(ddraw2,
slouken@0
   869
						&ddsCaps, &total_mem, NULL);
slouken@0
   870
		if ( result != DD_OK ) {
slouken@0
   871
			total_mem = DDCaps.dwVidMemTotal; 
slouken@0
   872
		}
slouken@0
   873
		this->info.video_mem = total_mem/1024;
slouken@0
   874
	}
slouken@0
   875
	return(0);
slouken@0
   876
}
slouken@0
   877
slouken@0
   878
int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
slouken@0
   879
{
slouken@0
   880
	HRESULT result;
slouken@0
   881
	LPDIRECTDRAW ddraw;
slouken@0
   882
	int i, j;
slouken@0
   883
	HDC hdc;
slouken@0
   884
slouken@0
   885
	/* Intialize everything */
slouken@0
   886
	ddraw2 = NULL;
slouken@0
   887
	SDL_primary = NULL;
slouken@0
   888
	SDL_clipper = NULL;
slouken@0
   889
	SDL_palette = NULL;
slouken@0
   890
	for ( i=0; i<NUM_MODELISTS; ++i ) {
slouken@0
   891
		SDL_nummodes[i] = 0;
slouken@0
   892
		SDL_modelist[i] = NULL;
slouken@0
   893
		SDL_modeindex[i] = 0;
slouken@0
   894
	}
slouken@0
   895
	colorchange_expected = 0;
slouken@0
   896
slouken@0
   897
	/* Create the window */
slouken@0
   898
	if ( DX5_CreateWindow(this) < 0 ) {
slouken@0
   899
		return(-1);
slouken@0
   900
	}
slouken@169
   901
#ifndef DISABLE_AUDIO
slouken@0
   902
	DX5_SoundFocus(SDL_Window);
slouken@169
   903
#endif
slouken@0
   904
slouken@0
   905
	/* Create the DirectDraw object */
slouken@0
   906
	result = DDrawCreate(NULL, &ddraw, NULL);
slouken@0
   907
	if ( result != DD_OK ) {
slouken@0
   908
		SetDDerror("DirectDrawCreate", result);
slouken@0
   909
		return(-1);
slouken@0
   910
	}
slouken@0
   911
	result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
slouken@0
   912
							(LPVOID *)&ddraw2);
slouken@0
   913
	IDirectDraw_Release(ddraw);
slouken@0
   914
	if ( result != DD_OK ) {
slouken@0
   915
		SetDDerror("DirectDraw::QueryInterface", result);
slouken@0
   916
		return(-1);
slouken@0
   917
	}
slouken@0
   918
slouken@0
   919
	/* Determine the screen depth */
slouken@0
   920
	hdc = GetDC(SDL_Window);
slouken@0
   921
	vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
slouken@0
   922
					GetDeviceCaps(hdc,BITSPIXEL);
slouken@0
   923
	ReleaseDC(SDL_Window, hdc);
slouken@0
   924
slouken@0
   925
	/* Enumerate the available fullscreen modes */
slouken@0
   926
	for ( i=0; i<NUM_MODELISTS; ++i )
slouken@0
   927
		enumlists[i] = NULL;
slouken@0
   928
slouken@809
   929
	result = IDirectDraw2_EnumDisplayModes(ddraw2,DDEDM_REFRESHRATES,NULL,this,EnumModes2);
slouken@0
   930
	if ( result != DD_OK ) {
slouken@0
   931
		SetDDerror("DirectDraw2::EnumDisplayModes", result);
slouken@0
   932
		return(-1);
slouken@0
   933
	}
slouken@0
   934
	for ( i=0; i<NUM_MODELISTS; ++i ) {
slouken@0
   935
		struct DX5EnumRect *rect;
slouken@0
   936
		SDL_modelist[i] = (SDL_Rect **)
slouken@0
   937
				malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
slouken@0
   938
		if ( SDL_modelist[i] == NULL ) {
slouken@0
   939
			SDL_OutOfMemory();
slouken@0
   940
			return(-1);
slouken@0
   941
		}
slouken@0
   942
		for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
slouken@809
   943
			SDL_modelist[i][j] = &rect->r;
slouken@0
   944
		}
slouken@0
   945
		SDL_modelist[i][j] = NULL;
slouken@0
   946
	}
slouken@0
   947
	
slouken@0
   948
	/* Fill in some window manager capabilities */
slouken@0
   949
	this->info.wm_available = 1;
slouken@0
   950
slouken@0
   951
	/* Fill in the video hardware capabilities */
slouken@0
   952
	DX5_UpdateVideoInfo(this);
slouken@0
   953
slouken@0
   954
	return(0);
slouken@0
   955
}
slouken@0
   956
slouken@0
   957
SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
slouken@0
   958
{
slouken@0
   959
	int bpp;
slouken@0
   960
slouken@0
   961
	bpp = format->BitsPerPixel;
slouken@0
   962
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
   963
		/* FIXME:  No support for 1 bpp or 4 bpp formats */
slouken@0
   964
		switch (bpp) {  /* Does windows support other BPP? */
slouken@0
   965
			case 8:
slouken@0
   966
			case 16:
slouken@0
   967
			case 24:
slouken@0
   968
			case 32:
slouken@0
   969
				bpp = (bpp/8)-1;
slouken@0
   970
				if ( SDL_nummodes[bpp] > 0 )
slouken@0
   971
					return(SDL_modelist[bpp]);
slouken@0
   972
				/* Fall through */
slouken@0
   973
			default:
slouken@0
   974
				return((SDL_Rect **)0);
slouken@0
   975
		}
slouken@0
   976
	} else {
slouken@0
   977
		if ( this->screen->format->BitsPerPixel == bpp ) {
slouken@0
   978
			return((SDL_Rect **)-1);
slouken@0
   979
		} else {
slouken@0
   980
			return((SDL_Rect **)0);
slouken@0
   981
		}
slouken@0
   982
	}
slouken@0
   983
}
slouken@0
   984
slouken@0
   985
/* Various screen update functions available */
slouken@0
   986
static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
slouken@0
   987
static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
slouken@0
   988
slouken@0
   989
SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
slouken@0
   990
				int width, int height, int bpp, Uint32 flags)
slouken@0
   991
{
slouken@0
   992
	SDL_Surface *video;
slouken@0
   993
	HRESULT result;
slouken@0
   994
	DWORD sharemode;
slouken@0
   995
	DWORD style;
slouken@0
   996
	const DWORD directstyle =
slouken@0
   997
			(WS_POPUP);
slouken@0
   998
	const DWORD windowstyle = 
slouken@0
   999
			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
slouken@0
  1000
	const DWORD resizestyle =
slouken@0
  1001
			(WS_THICKFRAME|WS_MAXIMIZEBOX);
slouken@0
  1002
	DDSURFACEDESC ddsd;
slouken@0
  1003
	LPDIRECTDRAWSURFACE  dd_surface1;
slouken@0
  1004
	LPDIRECTDRAWSURFACE3 dd_surface3;
slouken@0
  1005
	BOOL was_visible;
slouken@0
  1006
slouken@0
  1007
#ifdef DDRAW_DEBUG
slouken@0
  1008
 fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp);
slouken@0
  1009
#endif
slouken@0
  1010
	/* See whether or not we should center the window */
slouken@0
  1011
	was_visible = IsWindowVisible(SDL_Window);
slouken@0
  1012
slouken@0
  1013
	/* Clean up any previous DirectDraw surfaces */
slouken@0
  1014
	if ( current->hwdata ) {
slouken@0
  1015
		this->FreeHWSurface(this, current);
slouken@0
  1016
		current->hwdata = NULL;
slouken@0
  1017
	}
slouken@0
  1018
	if ( SDL_primary != NULL ) {
slouken@0
  1019
		IDirectDrawSurface3_Release(SDL_primary);
slouken@0
  1020
		SDL_primary = NULL;
slouken@0
  1021
	}
slouken@0
  1022
slouken@453
  1023
#ifndef NO_CHANGEDISPLAYSETTINGS
slouken@0
  1024
	/* Unset any previous OpenGL fullscreen mode */
slouken@0
  1025
	if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
slouken@0
  1026
	                       (SDL_OPENGL|SDL_FULLSCREEN) ) {
slouken@0
  1027
		ChangeDisplaySettings(NULL, 0);
slouken@0
  1028
	}
slouken@453
  1029
#endif
slouken@0
  1030
slouken@0
  1031
	/* Clean up any GL context that may be hanging around */
slouken@0
  1032
	if ( current->flags & SDL_OPENGL ) {
slouken@0
  1033
		WIN_GL_ShutDown(this);
slouken@0
  1034
	}
slouken@0
  1035
slouken@0
  1036
	/* If we are setting a GL mode, use GDI, not DirectX (yuck) */
slouken@0
  1037
	if ( flags & SDL_OPENGL ) {
slouken@0
  1038
		RECT bounds;
slouken@0
  1039
		int x, y;
slouken@0
  1040
		Uint32 Rmask, Gmask, Bmask;
slouken@0
  1041
slouken@0
  1042
		/* Recalculate the bitmasks if necessary */
slouken@0
  1043
		if ( bpp == current->format->BitsPerPixel ) {
slouken@0
  1044
			video = current;
slouken@0
  1045
		} else {
slouken@0
  1046
			switch (bpp) {
slouken@0
  1047
			    case 15:
slouken@0
  1048
			    case 16:
slouken@0
  1049
				if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
slouken@0
  1050
					/* 5-5-5 */
slouken@0
  1051
					Rmask = 0x00007c00;
slouken@0
  1052
					Gmask = 0x000003e0;
slouken@0
  1053
					Bmask = 0x0000001f;
slouken@0
  1054
				} else {
slouken@0
  1055
					/* 5-6-5 */
slouken@0
  1056
					Rmask = 0x0000f800;
slouken@0
  1057
					Gmask = 0x000007e0;
slouken@0
  1058
					Bmask = 0x0000001f;
slouken@0
  1059
				}
slouken@0
  1060
				break;
slouken@0
  1061
			    case 24:
slouken@0
  1062
			    case 32:
slouken@0
  1063
				/* GDI defined as 8-8-8 */
slouken@0
  1064
				Rmask = 0x00ff0000;
slouken@0
  1065
				Gmask = 0x0000ff00;
slouken@0
  1066
				Bmask = 0x000000ff;
slouken@0
  1067
				break;
slouken@0
  1068
			    default:
slouken@0
  1069
				Rmask = 0x00000000;
slouken@0
  1070
				Gmask = 0x00000000;
slouken@0
  1071
				Bmask = 0x00000000;
slouken@0
  1072
				break;
slouken@0
  1073
			}
slouken@0
  1074
			video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
slouken@0
  1075
			                             Rmask, Gmask, Bmask, 0);
slouken@0
  1076
			if ( video == NULL ) {
slouken@0
  1077
				SDL_OutOfMemory();
slouken@0
  1078
				return(NULL);
slouken@0
  1079
			}
slouken@0
  1080
		}
slouken@0
  1081
slouken@0
  1082
		/* Fill in part of the video surface */
slouken@0
  1083
		video->flags = 0;	/* Clear flags */
slouken@0
  1084
		video->w = width;
slouken@0
  1085
		video->h = height;
slouken@0
  1086
		video->pitch = SDL_CalculatePitch(video);
slouken@0
  1087
slouken@453
  1088
#ifndef NO_CHANGEDISPLAYSETTINGS
slouken@0
  1089
		/* Set fullscreen mode if appropriate.
slouken@0
  1090
		   Ugh, since our list of valid video modes comes from
slouken@0
  1091
		   the DirectX driver, we may not actually be able to
slouken@0
  1092
		   change to the desired resolution here.
slouken@0
  1093
		   FIXME: Should we do a closest match?
slouken@0
  1094
		 */
slouken@0
  1095
		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  1096
			DEVMODE settings;
slouken@0
  1097
slouken@0
  1098
			memset(&settings, 0, sizeof(DEVMODE));
slouken@0
  1099
			settings.dmSize = sizeof(DEVMODE);
slouken@0
  1100
			settings.dmBitsPerPel = video->format->BitsPerPixel;
slouken@0
  1101
			settings.dmPelsWidth = width;
slouken@0
  1102
			settings.dmPelsHeight = height;
slouken@0
  1103
			settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
slouken@0
  1104
			if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
slouken@0
  1105
				video->flags |= SDL_FULLSCREEN;
slouken@304
  1106
				SDL_fullscreen_mode = settings;
slouken@0
  1107
			}
slouken@0
  1108
		}
slouken@453
  1109
#endif /* !NO_CHANGEDISPLAYSETTINGS */
slouken@0
  1110
slouken@0
  1111
		style = GetWindowLong(SDL_Window, GWL_STYLE);
slouken@0
  1112
		style &= ~(resizestyle|WS_MAXIMIZE);
slouken@448
  1113
		if ( video->flags & SDL_FULLSCREEN ) {
slouken@0
  1114
			style &= ~windowstyle;
slouken@0
  1115
			style |= directstyle;
slouken@0
  1116
		} else {
slouken@0
  1117
			if ( flags & SDL_NOFRAME ) {
slouken@0
  1118
				style &= ~windowstyle;
slouken@0
  1119
				style |= directstyle;
slouken@0
  1120
				video->flags |= SDL_NOFRAME;
slouken@0
  1121
			} else {
slouken@0
  1122
				style &= ~directstyle;
slouken@0
  1123
				style |= windowstyle;
slouken@0
  1124
				if ( flags & SDL_RESIZABLE ) {
slouken@0
  1125
					style |= resizestyle;
slouken@0
  1126
					video->flags |= SDL_RESIZABLE;
slouken@0
  1127
				}
slouken@0
  1128
			}
slouken@453
  1129
#if WS_MAXIMIZE
slouken@0
  1130
			if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
slouken@453
  1131
#endif
slouken@0
  1132
		}
slouken@0
  1133
		SetWindowLong(SDL_Window, GWL_STYLE, style);
slouken@0
  1134
slouken@0
  1135
		/* Resize the window (copied from SDL WinDIB driver) */
slouken@0
  1136
		if ( SDL_windowid == NULL ) {
slouken@448
  1137
			HWND top;
slouken@0
  1138
			UINT swp_flags;
slouken@0
  1139
slouken@0
  1140
			SDL_resizing = 1;
slouken@468
  1141
			bounds.top    = 0;
slouken@0
  1142
			bounds.bottom = video->h;
slouken@468
  1143
			bounds.left   = 0;
slouken@468
  1144
			bounds.right  = video->w;
slouken@453
  1145
			AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
slouken@0
  1146
			width = bounds.right-bounds.left;
slouken@0
  1147
			height = bounds.bottom-bounds.top;
slouken@0
  1148
			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
slouken@0
  1149
			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
slouken@0
  1150
			if ( y < 0 ) { /* Cover up title bar for more client area */
slouken@0
  1151
				y -= GetSystemMetrics(SM_CYCAPTION)/2;
slouken@0
  1152
			}
slouken@448
  1153
			swp_flags = (SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
slouken@486
  1154
			if ( was_visible && !(video->flags & SDL_FULLSCREEN) ) {
slouken@0
  1155
				swp_flags |= SWP_NOMOVE;
slouken@0
  1156
			}
slouken@448
  1157
			if ( video->flags & SDL_FULLSCREEN ) {
slouken@448
  1158
				top = HWND_TOPMOST;
slouken@448
  1159
			} else {
slouken@448
  1160
				top = HWND_NOTOPMOST;
slouken@448
  1161
			}
slouken@448
  1162
			SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
slouken@0
  1163
			SDL_resizing = 0;
slouken@0
  1164
			SetForegroundWindow(SDL_Window);
slouken@0
  1165
		}
slouken@0
  1166
slouken@0
  1167
		/* Set up for OpenGL */
slouken@0
  1168
		if ( WIN_GL_SetupWindow(this) < 0 ) {
slouken@0
  1169
			return(NULL);
slouken@0
  1170
		}
slouken@0
  1171
		video->flags |= SDL_OPENGL;
slouken@0
  1172
		return(video);
slouken@0
  1173
	}
slouken@0
  1174
slouken@0
  1175
	/* Set the appropriate window style */
slouken@0
  1176
	style = GetWindowLong(SDL_Window, GWL_STYLE);
slouken@0
  1177
	style &= ~(resizestyle|WS_MAXIMIZE);
slouken@0
  1178
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  1179
		style &= ~windowstyle;
slouken@0
  1180
		style |= directstyle;
slouken@0
  1181
	} else {
slouken@0
  1182
		if ( flags & SDL_NOFRAME ) {
slouken@0
  1183
			style &= ~windowstyle;
slouken@0
  1184
			style |= directstyle;
slouken@0
  1185
		} else {
slouken@0
  1186
			style &= ~directstyle;
slouken@0
  1187
			style |= windowstyle;
slouken@0
  1188
			if ( flags & SDL_RESIZABLE ) {
slouken@0
  1189
				style |= resizestyle;
slouken@0
  1190
			}
slouken@0
  1191
		}
slouken@453
  1192
#if WS_MAXIMIZE
slouken@0
  1193
		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
slouken@453
  1194
#endif
slouken@0
  1195
	}
slouken@0
  1196
	SetWindowLong(SDL_Window, GWL_STYLE, style);
slouken@0
  1197
slouken@0
  1198
	/* Set DirectDraw sharing mode.. exclusive when fullscreen */
slouken@0
  1199
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  1200
		sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
slouken@0
  1201
	} else {
slouken@0
  1202
		sharemode = DDSCL_NORMAL;
slouken@0
  1203
	}
slouken@0
  1204
	result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
slouken@0
  1205
	if ( result != DD_OK ) {
slouken@0
  1206
		SetDDerror("DirectDraw2::SetCooperativeLevel", result);
slouken@0
  1207
		return(NULL);
slouken@0
  1208
	}
slouken@0
  1209
slouken@0
  1210
	/* Set the display mode, if we are in fullscreen mode */
slouken@0
  1211
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@809
  1212
		struct DX5EnumRect *rect;
slouken@809
  1213
		int maxRefreshRate;
slouken@809
  1214
slouken@0
  1215
		/* Cover up desktop during mode change */
slouken@0
  1216
		SDL_resizing = 1;
slouken@0
  1217
		SetWindowPos(SDL_Window, NULL, 0, 0, 
slouken@0
  1218
			GetSystemMetrics(SM_CXSCREEN),
slouken@0
  1219
			GetSystemMetrics(SM_CYSCREEN),
slouken@0
  1220
			(SWP_NOCOPYBITS | SWP_NOZORDER));
slouken@0
  1221
		SDL_resizing = 0;
slouken@0
  1222
		ShowWindow(SDL_Window, SW_SHOW);
slouken@0
  1223
		while ( GetForegroundWindow() != SDL_Window ) {
slouken@0
  1224
			SetForegroundWindow(SDL_Window);
slouken@0
  1225
			SDL_Delay(100);
slouken@0
  1226
		}
slouken@809
  1227
slouken@809
  1228
		/* find maximum monitor refresh rate for this resolution */
slouken@809
  1229
		/* Dmitry Yakimov ftech@tula.net */
slouken@809
  1230
		maxRefreshRate = 0; /* system default */
slouken@809
  1231
		for ( rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next ) {
slouken@809
  1232
			if ( (width == rect->r.w) && (height == rect->r.h) ) {
slouken@809
  1233
				maxRefreshRate = rect->refreshRate;
slouken@809
  1234
				break;
slouken@809
  1235
			}
slouken@809
  1236
		}
slouken@809
  1237
		printf("refresh rate = %d Hz\n", maxRefreshRate);
slouken@809
  1238
slouken@809
  1239
		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, maxRefreshRate, 0);
slouken@0
  1240
		if ( result != DD_OK ) {
slouken@809
  1241
			result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0);
slouken@809
  1242
			if ( result != DD_OK ) {
slouken@809
  1243
				/* We couldn't set fullscreen mode, try window */
slouken@809
  1244
				return(DX5_SetVideoMode(this, current, width, height, bpp, flags & ~SDL_FULLSCREEN)); 
slouken@809
  1245
			}
slouken@0
  1246
		}
slouken@0
  1247
		DX5_DInputReset(this, 1);
slouken@0
  1248
	} else {
slouken@0
  1249
		DX5_DInputReset(this, 0);
slouken@0
  1250
	}
slouken@0
  1251
	DX5_UpdateVideoInfo(this);
slouken@0
  1252
slouken@0
  1253
	/* Create a primary DirectDraw surface */
slouken@0
  1254
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1255
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1256
	ddsd.dwFlags = DDSD_CAPS;
slouken@0
  1257
	ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
slouken@0
  1258
	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
slouken@0
  1259
		/* There's no windowed double-buffering */
slouken@0
  1260
		flags &= ~SDL_DOUBLEBUF;
slouken@0
  1261
	}
slouken@0
  1262
	if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
slouken@0
  1263
		ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
slouken@0
  1264
		ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
slouken@0
  1265
		ddsd.dwBackBufferCount = 1;
slouken@0
  1266
	}
slouken@0
  1267
	result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
slouken@0
  1268
	if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
slouken@0
  1269
		ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
slouken@0
  1270
		ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
slouken@0
  1271
		ddsd.dwBackBufferCount = 0;
slouken@0
  1272
		result = IDirectDraw2_CreateSurface(ddraw2,
slouken@0
  1273
						&ddsd, &dd_surface1, NULL); 
slouken@0
  1274
	}
slouken@0
  1275
	if ( result != DD_OK ) {
slouken@0
  1276
		SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
slouken@0
  1277
		return(NULL);
slouken@0
  1278
	}
slouken@0
  1279
	result = IDirectDrawSurface_QueryInterface(dd_surface1,
slouken@0
  1280
			&IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
slouken@0
  1281
	if ( result != DD_OK ) {
slouken@0
  1282
		SetDDerror("DirectDrawSurface::QueryInterface", result);
slouken@0
  1283
		return(NULL);
slouken@0
  1284
	}
slouken@0
  1285
	result = IDirectDrawSurface_Release(dd_surface1);
slouken@0
  1286
	if ( result != DD_OK ) {
slouken@0
  1287
		SetDDerror("DirectDrawSurface::Release", result);
slouken@0
  1288
		return(NULL);
slouken@0
  1289
	}
slouken@0
  1290
slouken@0
  1291
	/* Get the format of the primary DirectDraw surface */
slouken@0
  1292
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1293
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1294
	ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
slouken@0
  1295
	result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
slouken@0
  1296
	if ( result != DD_OK ) {
slouken@0
  1297
		SetDDerror("DirectDrawSurface::Release", result);
slouken@0
  1298
		return(NULL);
slouken@0
  1299
	}
slouken@0
  1300
	if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
slouken@0
  1301
		SDL_SetError("Primary DDRAW surface is not RGB format");
slouken@0
  1302
		return(NULL);
slouken@0
  1303
	}
slouken@0
  1304
slouken@0
  1305
	/* Free old palette and create a new one if we're in 8-bit mode */
slouken@0
  1306
	if ( SDL_palette != NULL ) {
slouken@0
  1307
		IDirectDrawPalette_Release(SDL_palette);
slouken@0
  1308
		SDL_palette = NULL;
slouken@0
  1309
	}
slouken@0
  1310
#if defined(NONAMELESSUNION)
slouken@0
  1311
	if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
slouken@0
  1312
#else
slouken@0
  1313
	if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
slouken@0
  1314
#endif
slouken@0
  1315
		int i;
slouken@0
  1316
slouken@0
  1317
		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  1318
			/* We have access to the entire palette */
slouken@0
  1319
			for ( i=0; i<256; ++i ) {
slouken@0
  1320
				SDL_colors[i].peFlags =
slouken@0
  1321
						(PC_NOCOLLAPSE|PC_RESERVED);
slouken@0
  1322
				SDL_colors[i].peRed = 0;
slouken@0
  1323
				SDL_colors[i].peGreen = 0;
slouken@0
  1324
				SDL_colors[i].peBlue = 0;
slouken@0
  1325
			}
slouken@0
  1326
		} else {
slouken@0
  1327
			/* First 10 colors are reserved by Windows */
slouken@0
  1328
			for ( i=0; i<10; ++i ) {
slouken@0
  1329
				SDL_colors[i].peFlags = PC_EXPLICIT;
slouken@0
  1330
				SDL_colors[i].peRed = i;
slouken@0
  1331
				SDL_colors[i].peGreen = 0;
slouken@0
  1332
				SDL_colors[i].peBlue = 0;
slouken@0
  1333
			}
slouken@0
  1334
			for ( i=10; i<(10+236); ++i ) {
slouken@0
  1335
				SDL_colors[i].peFlags = PC_NOCOLLAPSE;
slouken@0
  1336
				SDL_colors[i].peRed = 0;
slouken@0
  1337
				SDL_colors[i].peGreen = 0;
slouken@0
  1338
				SDL_colors[i].peBlue = 0;
slouken@0
  1339
			}
slouken@0
  1340
			/* Last 10 colors are reserved by Windows */
slouken@0
  1341
			for ( i=246; i<256; ++i ) {
slouken@0
  1342
				SDL_colors[i].peFlags = PC_EXPLICIT;
slouken@0
  1343
				SDL_colors[i].peRed = i;
slouken@0
  1344
				SDL_colors[i].peGreen = 0;
slouken@0
  1345
				SDL_colors[i].peBlue = 0;
slouken@0
  1346
			}
slouken@0
  1347
		}
slouken@0
  1348
		result = IDirectDraw2_CreatePalette(ddraw2,
slouken@0
  1349
		     			(DDPCAPS_8BIT|DDPCAPS_ALLOW256),
slouken@0
  1350
						SDL_colors, &SDL_palette, NULL);
slouken@0
  1351
		if ( result != DD_OK ) {
slouken@0
  1352
			SetDDerror("DirectDraw2::CreatePalette", result);
slouken@0
  1353
			return(NULL);
slouken@0
  1354
		}
slouken@0
  1355
		result = IDirectDrawSurface3_SetPalette(SDL_primary,
slouken@0
  1356
								SDL_palette);
slouken@0
  1357
		if ( result != DD_OK ) {
slouken@0
  1358
			SetDDerror("DirectDrawSurface3::SetPalette", result);
slouken@0
  1359
			return(NULL);
slouken@0
  1360
		}
slouken@0
  1361
	}
slouken@0
  1362
slouken@0
  1363
	/* Create our video surface using the same pixel format */
slouken@0
  1364
	video = current;
slouken@0
  1365
	if ( (width != video->w) || (height != video->h)
slouken@0
  1366
			|| (video->format->BitsPerPixel != 
slouken@0
  1367
#if defined(NONAMELESSUNION)
slouken@0
  1368
				ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
slouken@0
  1369
#else
slouken@0
  1370
				ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
slouken@0
  1371
#endif
slouken@0
  1372
		SDL_FreeSurface(video);
slouken@0
  1373
		video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
slouken@0
  1374
#if defined(NONAMELESSUNION)
slouken@0
  1375
				ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
slouken@0
  1376
					ddsd.ddpfPixelFormat.u2.dwRBitMask,
slouken@0
  1377
					ddsd.ddpfPixelFormat.u3.dwGBitMask,
slouken@0
  1378
					ddsd.ddpfPixelFormat.u4.dwBBitMask,
slouken@0
  1379
#else
slouken@0
  1380
				ddsd.ddpfPixelFormat.dwRGBBitCount,
slouken@0
  1381
					ddsd.ddpfPixelFormat.dwRBitMask,
slouken@0
  1382
					ddsd.ddpfPixelFormat.dwGBitMask,
slouken@0
  1383
					ddsd.ddpfPixelFormat.dwBBitMask,
slouken@0
  1384
#endif
slouken@0
  1385
								0);
slouken@0
  1386
		if ( video == NULL ) {
slouken@0
  1387
			SDL_OutOfMemory();
slouken@0
  1388
			return(NULL);
slouken@0
  1389
		}
slouken@0
  1390
		video->w = width;
slouken@0
  1391
		video->h = height;
slouken@0
  1392
		video->pitch = 0;
slouken@0
  1393
	}
slouken@0
  1394
	video->flags = 0;	/* Clear flags */
slouken@0
  1395
slouken@0
  1396
	/* If not fullscreen, locking is possible, but it doesn't do what 
slouken@0
  1397
	   the caller really expects -- if the locked surface is written to,
slouken@0
  1398
	   the appropriate portion of the entire screen is modified, not 
slouken@0
  1399
	   the application window, as we would like.
slouken@0
  1400
	   Note that it is still possible to write directly to display
slouken@0
  1401
	   memory, but the application must respect the clip list of
slouken@0
  1402
	   the surface.  There might be some odd timing interactions
slouken@0
  1403
	   involving clip list updates and background refreshing as
slouken@0
  1404
	   Windows moves other windows across our window.
slouken@0
  1405
	   We currently don't support this, even though it might be a
slouken@0
  1406
	   good idea since BeOS has an implementation of BDirectWindow
slouken@0
  1407
	   that does the same thing.  This would be most useful for
slouken@0
  1408
	   applications that do complete screen updates every frame.
slouken@0
  1409
	    -- Fixme?
slouken@0
  1410
	*/
slouken@0
  1411
	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
slouken@0
  1412
		/* Necessary if we're going from fullscreen to window */
slouken@0
  1413
		if ( video->pixels == NULL ) {
slouken@0
  1414
			video->pitch = (width*video->format->BytesPerPixel);
slouken@0
  1415
			/* Pitch needs to be QWORD (8-byte) aligned */
slouken@0
  1416
			video->pitch = (video->pitch + 7) & ~7;
slouken@0
  1417
			video->pixels = (void *)malloc(video->h*video->pitch);
slouken@0
  1418
			if ( video->pixels == NULL ) {
slouken@0
  1419
				if ( video != current ) {
slouken@0
  1420
					SDL_FreeSurface(video);
slouken@0
  1421
				}
slouken@0
  1422
				SDL_OutOfMemory();
slouken@0
  1423
				return(NULL);
slouken@0
  1424
			}
slouken@0
  1425
		}
slouken@0
  1426
		dd_surface3 = NULL;
slouken@443
  1427
#if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */
slouken@443
  1428
		if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@443
  1429
			video->flags |= SDL_HWSURFACE;
slouken@443
  1430
		} else {
slouken@443
  1431
			video->flags |= SDL_SWSURFACE;
slouken@443
  1432
		}
slouken@443
  1433
#else
slouken@0
  1434
		video->flags |= SDL_SWSURFACE;
slouken@443
  1435
#endif
slouken@0
  1436
		if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
slouken@0
  1437
			video->flags |= SDL_RESIZABLE;
slouken@0
  1438
		}
slouken@0
  1439
		if ( flags & SDL_NOFRAME ) {
slouken@0
  1440
			video->flags |= SDL_NOFRAME;
slouken@0
  1441
		}
slouken@0
  1442
	} else {
slouken@0
  1443
		/* Necessary if we're going from window to fullscreen */
slouken@0
  1444
		if ( video->pixels != NULL ) {
slouken@0
  1445
			free(video->pixels);
slouken@0
  1446
			video->pixels = NULL;
slouken@0
  1447
		}
slouken@0
  1448
		dd_surface3 = SDL_primary;
slouken@0
  1449
		video->flags |= SDL_HWSURFACE;
slouken@0
  1450
	}
slouken@0
  1451
slouken@0
  1452
	/* See if the primary surface has double-buffering enabled */
slouken@0
  1453
	if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
slouken@0
  1454
		video->flags |= SDL_DOUBLEBUF;
slouken@0
  1455
	}
slouken@0
  1456
slouken@0
  1457
	/* Allocate the SDL surface associated with the primary surface */
slouken@0
  1458
	if ( DX5_AllocDDSurface(this, video, dd_surface3,
slouken@0
  1459
	                        video->flags&SDL_HWSURFACE) < 0 ) {
slouken@0
  1460
		if ( video != current ) {
slouken@0
  1461
			SDL_FreeSurface(video);
slouken@0
  1462
		}
slouken@0
  1463
		return(NULL);
slouken@0
  1464
	}
slouken@0
  1465
slouken@0
  1466
	/* Use the appropriate blitting function */
slouken@0
  1467
	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  1468
		video->flags |= SDL_FULLSCREEN;
slouken@0
  1469
		if ( video->format->palette != NULL ) {
slouken@0
  1470
			video->flags |= SDL_HWPALETTE;
slouken@0
  1471
		}
slouken@0
  1472
		this->UpdateRects = DX5_DirectUpdate;
slouken@0
  1473
	} else {
slouken@0
  1474
		this->UpdateRects = DX5_WindowUpdate;
slouken@0
  1475
	}
slouken@0
  1476
slouken@0
  1477
	/* Make our window the proper size, set the clipper, then show it */
slouken@0
  1478
	if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
slouken@0
  1479
		RECT bounds;
slouken@0
  1480
		int  x, y;
slouken@0
  1481
		UINT swp_flags;
slouken@0
  1482
slouken@0
  1483
		/* Create and set a clipper on our primary surface */
slouken@0
  1484
		if ( SDL_clipper == NULL ) {
slouken@0
  1485
			result = IDirectDraw2_CreateClipper(ddraw2,
slouken@0
  1486
							0, &SDL_clipper, NULL);
slouken@0
  1487
			if ( result != DD_OK ) {
slouken@0
  1488
				if ( video != current ) {
slouken@0
  1489
					SDL_FreeSurface(video);
slouken@0
  1490
				}
slouken@0
  1491
				SetDDerror("DirectDraw2::CreateClipper",result);
slouken@0
  1492
				return(NULL);
slouken@0
  1493
			}
slouken@0
  1494
		}
slouken@0
  1495
		result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
slouken@0
  1496
		if ( result != DD_OK ) {
slouken@0
  1497
			if ( video != current ) {
slouken@0
  1498
				SDL_FreeSurface(video);
slouken@0
  1499
			}
slouken@0
  1500
			SetDDerror("DirectDrawClipper::SetHWnd", result);
slouken@0
  1501
			return(NULL);
slouken@0
  1502
		}
slouken@0
  1503
		result = IDirectDrawSurface3_SetClipper(SDL_primary,
slouken@0
  1504
								SDL_clipper);
slouken@0
  1505
		if ( result != DD_OK ) {
slouken@0
  1506
			if ( video != current ) {
slouken@0
  1507
				SDL_FreeSurface(video);
slouken@0
  1508
			}
slouken@0
  1509
			SetDDerror("DirectDrawSurface3::SetClipper", result);
slouken@0
  1510
			return(NULL);
slouken@0
  1511
		}
slouken@0
  1512
slouken@0
  1513
		/* Set the size of the window, centering and adjusting */
slouken@0
  1514
		SDL_resizing = 1;
slouken@468
  1515
		bounds.top    = 0;
slouken@0
  1516
		bounds.bottom = video->h;
slouken@468
  1517
		bounds.left   = 0;
slouken@468
  1518
		bounds.right  = video->w;
slouken@453
  1519
		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE, 0);
slouken@0
  1520
		width = bounds.right-bounds.left;
slouken@0
  1521
		height = bounds.bottom-bounds.top;
slouken@0
  1522
		x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
slouken@0
  1523
		y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
slouken@0
  1524
		if ( y < 0 ) { /* Cover up title bar for more client area */
slouken@0
  1525
			y -= GetSystemMetrics(SM_CYCAPTION)/2;
slouken@0
  1526
		}
slouken@0
  1527
		swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER);
slouken@0
  1528
		if ( was_visible ) {
slouken@0
  1529
			swp_flags |= SWP_NOMOVE;
slouken@0
  1530
		}
slouken@0
  1531
		SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
slouken@0
  1532
		SDL_resizing = 0;
slouken@0
  1533
	}
slouken@0
  1534
	ShowWindow(SDL_Window, SW_SHOW);
slouken@0
  1535
	SetForegroundWindow(SDL_Window);
slouken@0
  1536
slouken@0
  1537
	/* We're live! */
slouken@0
  1538
	return(video);
slouken@0
  1539
}
slouken@0
  1540
slouken@0
  1541
struct private_hwdata {
slouken@0
  1542
	LPDIRECTDRAWSURFACE3 dd_surface;
slouken@0
  1543
	LPDIRECTDRAWSURFACE3 dd_writebuf;
slouken@0
  1544
};
slouken@0
  1545
slouken@0
  1546
static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
slouken@0
  1547
				LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
slouken@0
  1548
{
slouken@0
  1549
	LPDIRECTDRAWSURFACE  dd_surface1;
slouken@0
  1550
	LPDIRECTDRAWSURFACE3 dd_surface3;
slouken@0
  1551
	DDSURFACEDESC ddsd;
slouken@0
  1552
	HRESULT result;
slouken@0
  1553
slouken@0
  1554
	/* Clear the hardware flag, in case we fail */
slouken@0
  1555
	surface->flags &= ~flag;
slouken@0
  1556
slouken@0
  1557
	/* Allocate the hardware acceleration data */
slouken@0
  1558
	surface->hwdata = (struct private_hwdata *)
slouken@0
  1559
					malloc(sizeof(*surface->hwdata));
slouken@0
  1560
	if ( surface->hwdata == NULL ) {
slouken@0
  1561
		SDL_OutOfMemory();
slouken@0
  1562
		return(-1);
slouken@0
  1563
	}
slouken@0
  1564
	dd_surface3 = NULL;
slouken@0
  1565
slouken@0
  1566
	/* Set up the surface description */
slouken@0
  1567
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1568
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1569
	ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
slouken@0
  1570
					DDSD_PITCH|DDSD_PIXELFORMAT);
slouken@0
  1571
	ddsd.dwWidth = surface->w;
slouken@0
  1572
	ddsd.dwHeight= surface->h;
slouken@0
  1573
#if defined(NONAMELESSUNION)
slouken@0
  1574
	ddsd.u1.lPitch = surface->pitch;
slouken@0
  1575
#else
slouken@0
  1576
	ddsd.lPitch = surface->pitch;
slouken@0
  1577
#endif
slouken@0
  1578
	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@0
  1579
		ddsd.ddsCaps.dwCaps =
slouken@0
  1580
				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
slouken@0
  1581
	} else {
slouken@0
  1582
		ddsd.ddsCaps.dwCaps =
slouken@0
  1583
				(DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
slouken@0
  1584
	}
slouken@0
  1585
	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
slouken@0
  1586
	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
slouken@0
  1587
	if ( surface->format->palette ) {
slouken@0
  1588
		ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
slouken@0
  1589
	}
slouken@0
  1590
#if defined(NONAMELESSUNION)
slouken@0
  1591
	ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
slouken@0
  1592
	ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
slouken@0
  1593
	ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
slouken@0
  1594
	ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
slouken@0
  1595
#else
slouken@0
  1596
	ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
slouken@0
  1597
	ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
slouken@0
  1598
	ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
slouken@0
  1599
	ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
slouken@0
  1600
#endif
slouken@0
  1601
slouken@0
  1602
	/* Create the DirectDraw video surface */
slouken@0
  1603
	if ( requested != NULL ) {
slouken@0
  1604
		dd_surface3 = requested;
slouken@0
  1605
	} else {
slouken@0
  1606
		result = IDirectDraw2_CreateSurface(ddraw2,
slouken@0
  1607
						&ddsd, &dd_surface1, NULL); 
slouken@0
  1608
		if ( result != DD_OK ) {
slouken@0
  1609
			SetDDerror("DirectDraw2::CreateSurface", result);
slouken@0
  1610
			goto error_end;
slouken@0
  1611
		}
slouken@0
  1612
		result = IDirectDrawSurface_QueryInterface(dd_surface1,
slouken@0
  1613
			&IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
slouken@0
  1614
		IDirectDrawSurface_Release(dd_surface1);
slouken@0
  1615
		if ( result != DD_OK ) {
slouken@0
  1616
			SetDDerror("DirectDrawSurface::QueryInterface", result);
slouken@0
  1617
			goto error_end;
slouken@0
  1618
		}
slouken@0
  1619
	}
slouken@0
  1620
slouken@0
  1621
	if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@0
  1622
		/* Check to see whether the surface actually ended up
slouken@0
  1623
		   in video memory, and fail if not.  We expect the
slouken@0
  1624
		   surfaces we create here to actually be in hardware!
slouken@0
  1625
		*/
slouken@0
  1626
		result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
slouken@0
  1627
		if ( result != DD_OK ) {
slouken@0
  1628
			SetDDerror("DirectDrawSurface3::GetCaps", result);
slouken@0
  1629
			goto error_end;
slouken@0
  1630
		}
slouken@0
  1631
		if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
slouken@0
  1632
							DDSCAPS_VIDEOMEMORY ) {
slouken@0
  1633
			SDL_SetError("No room in video memory");
slouken@0
  1634
			goto error_end;
slouken@0
  1635
		}
slouken@0
  1636
	} else {
slouken@0
  1637
		/* Try to hook our surface memory */
slouken@0
  1638
		ddsd.dwFlags = DDSD_LPSURFACE;
slouken@0
  1639
		ddsd.lpSurface = surface->pixels;
slouken@0
  1640
		result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
slouken@0
  1641
								&ddsd, 0);
slouken@0
  1642
		if ( result != DD_OK ) {
slouken@0
  1643
			SetDDerror("DirectDraw2::SetSurfaceDesc", result);
slouken@0
  1644
			goto error_end;
slouken@0
  1645
		}
slouken@0
  1646
	
slouken@0
  1647
	}
slouken@0
  1648
slouken@0
  1649
	/* Make sure the surface format was set properly */
slouken@0
  1650
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1651
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1652
	result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
slouken@443
  1653
		&ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
slouken@0
  1654
	if ( result != DD_OK ) {
slouken@0
  1655
		SetDDerror("DirectDrawSurface3::Lock", result);
slouken@0
  1656
		goto error_end;
slouken@0
  1657
	}
slouken@0
  1658
	IDirectDrawSurface3_Unlock(dd_surface3, NULL);
slouken@0
  1659
slouken@0
  1660
	if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
slouken@0
  1661
		if ( ddsd.lpSurface != surface->pixels ) {
slouken@0
  1662
			SDL_SetError("DDraw didn't use SDL surface memory");
slouken@0
  1663
			goto error_end;
slouken@0
  1664
		}
slouken@0
  1665
		if (
slouken@0
  1666
#if defined(NONAMELESSUNION)
slouken@0
  1667
			ddsd.u1.lPitch
slouken@0
  1668
#else
slouken@0
  1669
			ddsd.lPitch
slouken@0
  1670
#endif
slouken@0
  1671
				 != (LONG)surface->pitch ) {
slouken@0
  1672
			SDL_SetError("DDraw created surface with wrong pitch");
slouken@0
  1673
			goto error_end;
slouken@0
  1674
		}
slouken@0
  1675
	} else {
slouken@0
  1676
#if defined(NONAMELESSUNION)
slouken@0
  1677
		surface->pitch = (Uint16)ddsd.u1.lPitch;
slouken@0
  1678
#else
slouken@0
  1679
		surface->pitch = (Uint16)ddsd.lPitch;
slouken@0
  1680
#endif
slouken@0
  1681
	}
slouken@0
  1682
#if defined(NONAMELESSUNION)
slouken@0
  1683
	if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
slouken@0
  1684
					surface->format->BitsPerPixel) ||
slouken@0
  1685
	     (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
slouken@0
  1686
	     (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
slouken@0
  1687
	     (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
slouken@0
  1688
#else
slouken@0
  1689
	if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
slouken@0
  1690
					surface->format->BitsPerPixel) ||
slouken@0
  1691
	     (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
slouken@0
  1692
	     (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
slouken@0
  1693
	     (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
slouken@0
  1694
#endif
slouken@0
  1695
		SDL_SetError("DDraw didn't use SDL surface description");
slouken@0
  1696
		goto error_end;
slouken@0
  1697
	}
slouken@0
  1698
	if ( (ddsd.dwWidth != (DWORD)surface->w) ||
slouken@0
  1699
		(ddsd.dwHeight != (DWORD)surface->h) ) {
slouken@0
  1700
		SDL_SetError("DDraw created surface with wrong size");
slouken@0
  1701
		goto error_end;
slouken@0
  1702
	}
slouken@0
  1703
slouken@0
  1704
	/* Set the surface private data */
slouken@0
  1705
	surface->flags |= flag;
slouken@0
  1706
	surface->hwdata->dd_surface = dd_surface3;
slouken@0
  1707
	if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
slouken@0
  1708
		LPDIRECTDRAWSURFACE3 dd_writebuf;
slouken@0
  1709
slouken@0
  1710
		ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
slouken@0
  1711
		result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
slouken@0
  1712
						&ddsd.ddsCaps, &dd_writebuf);
slouken@0
  1713
		if ( result != DD_OK ) {
slouken@0
  1714
			SetDDerror("DirectDrawSurface3::GetAttachedSurface",
slouken@0
  1715
								result);
slouken@0
  1716
		} else {
slouken@0
  1717
			dd_surface3 = dd_writebuf;
slouken@0
  1718
		}
slouken@0
  1719
	}
slouken@0
  1720
	surface->hwdata->dd_writebuf = dd_surface3;
slouken@0
  1721
slouken@0
  1722
	/* We're ready to go! */
slouken@0
  1723
	return(0);
slouken@0
  1724
slouken@0
  1725
	/* Okay, so goto's are cheesy, but there are so many possible
slouken@0
  1726
	   errors in this function, and the cleanup is the same in 
slouken@0
  1727
	   every single case.  Is there a better way, other than deeply
slouken@0
  1728
	   nesting the code?
slouken@0
  1729
	*/
slouken@0
  1730
error_end:
slouken@0
  1731
	if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
slouken@0
  1732
		IDirectDrawSurface_Release(dd_surface3);
slouken@0
  1733
	}
slouken@0
  1734
	free(surface->hwdata);
slouken@0
  1735
	surface->hwdata = NULL;
slouken@0
  1736
	return(-1);
slouken@0
  1737
}
slouken@0
  1738
slouken@0
  1739
static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
slouken@0
  1740
{
slouken@0
  1741
	/* DDraw limitation -- you need to set cooperative level first */
slouken@0
  1742
	if ( SDL_primary == NULL ) {
slouken@0
  1743
		SDL_SetError("You must set a non-GL video mode first");
slouken@0
  1744
		return(-1);
slouken@0
  1745
	}
slouken@0
  1746
	return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
slouken@0
  1747
}
slouken@0
  1748
slouken@1
  1749
#ifdef DDRAW_DEBUG
slouken@0
  1750
void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
slouken@0
  1751
{
slouken@0
  1752
	DDSURFACEDESC ddsd;
slouken@0
  1753
slouken@0
  1754
	/* Lock and load! */
slouken@0
  1755
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1756
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1757
	if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
slouken@0
  1758
			(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
slouken@0
  1759
		return;
slouken@0
  1760
	}
slouken@0
  1761
	IDirectDrawSurface3_Unlock(surface, NULL);
slouken@0
  1762
	
slouken@0
  1763
	fprintf(stderr, "%s:\n", title);
slouken@0
  1764
	fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n",
slouken@0
  1765
		ddsd.dwWidth, ddsd.dwHeight,
slouken@0
  1766
		(flags & SDL_HWSURFACE) ? "hardware" : "software",
slouken@0
  1767
#if defined(NONAMELESSUNION)
slouken@0
  1768
		ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
slouken@0
  1769
#else
slouken@0
  1770
		ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
slouken@0
  1771
#endif
slouken@0
  1772
	fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", 
slouken@0
  1773
#if defined(NONAMELESSUNION)
slouken@0
  1774
	     		ddsd.ddpfPixelFormat.u2.dwRBitMask,
slouken@0
  1775
	     		ddsd.ddpfPixelFormat.u3.dwGBitMask,
slouken@0
  1776
	     		ddsd.ddpfPixelFormat.u4.dwBBitMask);
slouken@0
  1777
#else
slouken@0
  1778
	     		ddsd.ddpfPixelFormat.dwRBitMask,
slouken@0
  1779
	     		ddsd.ddpfPixelFormat.dwGBitMask,
slouken@0
  1780
	     		ddsd.ddpfPixelFormat.dwBBitMask);
slouken@0
  1781
#endif
slouken@0
  1782
}
slouken@1
  1783
#endif /* DDRAW_DEBUG */
slouken@0
  1784
slouken@0
  1785
static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
slouken@0
  1786
					SDL_Surface *dst, SDL_Rect *dstrect)
slouken@0
  1787
{
slouken@0
  1788
	LPDIRECTDRAWSURFACE3 src_surface;
slouken@0
  1789
	LPDIRECTDRAWSURFACE3 dst_surface;
slouken@0
  1790
	DWORD flags;
slouken@0
  1791
	RECT rect;
slouken@0
  1792
	HRESULT result;
slouken@0
  1793
slouken@0
  1794
	/* Set it up.. the desination must have a DDRAW surface */
slouken@0
  1795
	src_surface = src->hwdata->dd_writebuf;
slouken@0
  1796
	dst_surface = dst->hwdata->dd_writebuf;
slouken@468
  1797
	rect.top    = (LONG)srcrect->y;
slouken@468
  1798
	rect.bottom = (LONG)srcrect->y+srcrect->h;
slouken@468
  1799
	rect.left   = (LONG)srcrect->x;
slouken@468
  1800
	rect.right  = (LONG)srcrect->x+srcrect->w;
slouken@0
  1801
	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
slouken@0
  1802
		flags = DDBLTFAST_SRCCOLORKEY;
slouken@0
  1803
	else
slouken@0
  1804
		flags = DDBLTFAST_NOCOLORKEY;
slouken@0
  1805
	/* FIXME:  We can remove this flag for _really_ fast blit queuing,
slouken@0
  1806
	           but it will affect the return values of locks and flips.
slouken@0
  1807
	 */
slouken@0
  1808
	flags |= DDBLTFAST_WAIT;
slouken@0
  1809
slouken@0
  1810
	/* Do the blit! */
slouken@0
  1811
	result = IDirectDrawSurface3_BltFast(dst_surface,
slouken@0
  1812
			dstrect->x, dstrect->y, src_surface, &rect, flags);
slouken@0
  1813
	if ( result != DD_OK ) {
slouken@0
  1814
		if ( result == DDERR_SURFACELOST ) {
slouken@0
  1815
			result = IDirectDrawSurface3_Restore(src_surface);
slouken@0
  1816
			result = IDirectDrawSurface3_Restore(dst_surface);
slouken@0
  1817
			/* The surfaces need to be reloaded with artwork */
slouken@0
  1818
			SDL_SetError("Blit surfaces were lost, reload them");
slouken@0
  1819
			return(-2);
slouken@0
  1820
		}
slouken@0
  1821
		SetDDerror("IDirectDrawSurface3::BltFast", result);
slouken@0
  1822
#ifdef DDRAW_DEBUG
slouken@0
  1823
 fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
slouken@0
  1824
 fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n",
slouken@0
  1825
		(src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
slouken@0
  1826
					dstrect->x, dstrect->y);
slouken@0
  1827
  PrintSurface("SRC", src_surface, src->flags);
slouken@0
  1828
  PrintSurface("DST", dst_surface, dst->flags);
slouken@0
  1829
 fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n",
slouken@0
  1830
		rect.left, rect.top, rect.right, rect.bottom);
slouken@0
  1831
#endif
slouken@0
  1832
		/* Unexpected error, fall back to software blit */
slouken@0
  1833
		return(src->map->sw_blit(src, srcrect, dst, dstrect));
slouken@0
  1834
	}
slouken@0
  1835
	return(0);
slouken@0
  1836
}
slouken@0
  1837
slouken@0
  1838
static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
slouken@0
  1839
{
slouken@0
  1840
	int accelerated;
slouken@0
  1841
slouken@0
  1842
	/* We need to have a DDraw surface for HW blits */
slouken@0
  1843
	if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
slouken@0
  1844
		/* Allocate a DDraw surface for the blit */
slouken@0
  1845
		if ( src->hwdata == NULL ) {
slouken@0
  1846
			DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
slouken@0
  1847
		}
slouken@0
  1848
	}
slouken@0
  1849
	if ( src->hwdata == NULL ) {
slouken@0
  1850
		return(0);
slouken@0
  1851
	}
slouken@0
  1852
slouken@0
  1853
	/* Set initial acceleration on */
slouken@0
  1854
	src->flags |= SDL_HWACCEL;
slouken@0
  1855
slouken@0
  1856
	/* Set the surface attributes */
slouken@0
  1857
	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
slouken@0
  1858
		if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
slouken@0
  1859
			src->flags &= ~SDL_HWACCEL;
slouken@0
  1860
		}
slouken@0
  1861
	}
slouken@0
  1862
	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
slouken@0
  1863
		if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
slouken@0
  1864
			src->flags &= ~SDL_HWACCEL;
slouken@0
  1865
		}
slouken@0
  1866
	}
slouken@0
  1867
slouken@0
  1868
	/* Check to see if final surface blit is accelerated */
slouken@0
  1869
	accelerated = !!(src->flags & SDL_HWACCEL);
slouken@0
  1870
	if ( accelerated ) {
slouken@0
  1871
#ifdef DDRAW_DEBUG
slouken@0
  1872
  fprintf(stderr, "Setting accelerated blit on 0x%p\n", src);
slouken@0
  1873
#endif
slouken@0
  1874
		src->map->hw_blit = DX5_HWAccelBlit;
slouken@0
  1875
	}
slouken@0
  1876
	return(accelerated);
slouken@0
  1877
}
slouken@0
  1878
slouken@0
  1879
static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
slouken@0
  1880
{
slouken@0
  1881
	LPDIRECTDRAWSURFACE3 dst_surface;
slouken@0
  1882
	RECT area;
slouken@0
  1883
	DDBLTFX bltfx;
slouken@0
  1884
	HRESULT result;
slouken@0
  1885
slouken@0
  1886
#ifdef DDRAW_DEBUG
slouken@0
  1887
 fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y);
slouken@0
  1888
#endif
slouken@0
  1889
	dst_surface = dst->hwdata->dd_writebuf;
slouken@468
  1890
	area.top    = (LONG)dstrect->y;
slouken@468
  1891
	area.bottom = (LONG)dstrect->y+dstrect->h;
slouken@468
  1892
	area.left   = (LONG)dstrect->x;
slouken@468
  1893
	area.right  = (LONG)dstrect->x+dstrect->w;
slouken@0
  1894
	bltfx.dwSize = sizeof(bltfx);
slouken@0
  1895
#if defined(NONAMELESSUNION)
slouken@0
  1896
	bltfx.u5.dwFillColor = color;
slouken@0
  1897
#else
slouken@0
  1898
	bltfx.dwFillColor = color;
slouken@0
  1899
#endif
slouken@0
  1900
	result = IDirectDrawSurface3_Blt(dst_surface,
slouken@0
  1901
			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
slouken@0
  1902
	if ( result == DDERR_SURFACELOST ) {
slouken@0
  1903
		IDirectDrawSurface3_Restore(dst_surface);
slouken@0
  1904
		result = IDirectDrawSurface3_Blt(dst_surface,
slouken@0
  1905
			&area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
slouken@0
  1906
	}
slouken@0
  1907
	if ( result != DD_OK ) {
slouken@0
  1908
		SetDDerror("IDirectDrawSurface3::Blt", result);
slouken@0
  1909
		return(-1);
slouken@0
  1910
	}
slouken@0
  1911
	return(0);
slouken@0
  1912
}
slouken@0
  1913
slouken@0
  1914
static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
slouken@0
  1915
{
slouken@0
  1916
	DDCOLORKEY colorkey;
slouken@0
  1917
	HRESULT result;
slouken@0
  1918
slouken@0
  1919
	/* Set the surface colorkey */
slouken@0
  1920
	colorkey.dwColorSpaceLowValue = key;
slouken@0
  1921
	colorkey.dwColorSpaceHighValue = key;
slouken@0
  1922
	result = IDirectDrawSurface3_SetColorKey(
slouken@0
  1923
			surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
slouken@0
  1924
	if ( result != DD_OK ) {
slouken@0
  1925
		SetDDerror("IDirectDrawSurface3::SetColorKey", result);
slouken@0
  1926
		return(-1);
slouken@0
  1927
	}
slouken@0
  1928
	return(0);
slouken@0
  1929
}
slouken@0
  1930
static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
slouken@0
  1931
{
slouken@0
  1932
	return(-1);
slouken@0
  1933
}
slouken@0
  1934
slouken@0
  1935
static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
slouken@0
  1936
{
slouken@0
  1937
	HRESULT result;
slouken@0
  1938
	LPDIRECTDRAWSURFACE3 dd_surface;
slouken@0
  1939
	DDSURFACEDESC ddsd;
slouken@0
  1940
slouken@0
  1941
	/* Lock and load! */
slouken@0
  1942
	dd_surface = surface->hwdata->dd_writebuf;
slouken@0
  1943
	memset(&ddsd, 0, sizeof(ddsd));
slouken@0
  1944
	ddsd.dwSize = sizeof(ddsd);
slouken@0
  1945
	result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
slouken@0
  1946
					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
slouken@0
  1947
	if ( result == DDERR_SURFACELOST ) {
slouken@0
  1948
		result = IDirectDrawSurface3_Restore(
slouken@0
  1949
						surface->hwdata->dd_surface);
slouken@0
  1950
		result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
slouken@0
  1951
					(DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
slouken@0
  1952
	}
slouken@0
  1953
	if ( result != DD_OK ) {
slouken@0
  1954
		SetDDerror("DirectDrawSurface3::Lock", result);
slouken@0
  1955
		return(-1);
slouken@0
  1956
	}
slouken@0
  1957
	/* Pitch might have changed -- recalculate pitch and offset */
slouken@0
  1958
#if defined(NONAMELESSUNION)
slouken@0
  1959
	if ( surface->pitch != ddsd.u1.lPitch ) {
slouken@0
  1960
		surface->pitch = ddsd.u1.lPitch;
slouken@0
  1961
#else
slouken@0
  1962
	if ( surface->pitch != ddsd.lPitch ) {
slouken@0
  1963
		surface->pitch = (Uint16)ddsd.lPitch;
slouken@0
  1964
#endif
slouken@0
  1965
		surface->offset =
slouken@0
  1966
			((ddsd.dwHeight-surface->h)/2)*surface->pitch +
slouken@0
  1967
			((ddsd.dwWidth-surface->w)/2)*
slouken@0
  1968
					surface->format->BytesPerPixel;
slouken@0
  1969
	}
slouken@0
  1970
	surface->pixels = ddsd.lpSurface;
slouken@0
  1971
	return(0);
slouken@0
  1972
}
slouken@0
  1973
slouken@0
  1974
static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
slouken@0
  1975
{
slouken@0
  1976
	IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
slouken@0
  1977
	surface->pixels = NULL;
slouken@0
  1978
}
slouken@0
  1979
slouken@0
  1980
static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
slouken@0
  1981
{
slouken@0
  1982
	HRESULT result;
slouken@0
  1983
	LPDIRECTDRAWSURFACE3 dd_surface;
slouken@0
  1984
slouken@0
  1985
	dd_surface = surface->hwdata->dd_surface;
slouken@809
  1986
slouken@809
  1987
	/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
slouken@809
  1988
	/* Dmitry Yakimov (ftech@tula.net) */
slouken@809
  1989
	while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
slouken@809
  1990
slouken@809
  1991
	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
slouken@0
  1992
	if ( result == DDERR_SURFACELOST ) {
slouken@0
  1993
		result = IDirectDrawSurface3_Restore(
slouken@0
  1994
						surface->hwdata->dd_surface);
slouken@809
  1995
		while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
slouken@809
  1996
		result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
slouken@0
  1997
	}
slouken@0
  1998
	if ( result != DD_OK ) {
slouken@0
  1999
		SetDDerror("DirectDrawSurface3::Flip", result);
slouken@0
  2000
		return(-1);
slouken@0
  2001
	}
slouken@0
  2002
	return(0);
slouken@0
  2003
}
slouken@0
  2004
slouken@0
  2005
static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
slouken@0
  2006
{
slouken@0
  2007
	if ( surface->hwdata ) {
slouken@0
  2008
		if ( surface->hwdata->dd_surface != SDL_primary ) {
slouken@0
  2009
			IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
slouken@0
  2010
		}
slouken@0
  2011
		free(surface->hwdata);
slouken@0
  2012
		surface->hwdata = NULL;
slouken@0
  2013
	}
slouken@0
  2014
}
slouken@0
  2015
slouken@0
  2016
void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
slouken@0
  2017
{
slouken@0
  2018
	HRESULT result;
slouken@0
  2019
	int i;
slouken@0
  2020
	RECT src, dst;
slouken@0
  2021
slouken@0
  2022
	for ( i=0; i<numrects; ++i ) {
slouken@468
  2023
		src.top    = (LONG)rects[i].y;
slouken@468
  2024
		src.bottom = (LONG)rects[i].y+rects[i].h;
slouken@468
  2025
		src.left   = (LONG)rects[i].x;
slouken@468
  2026
		src.right  = (LONG)rects[i].x+rects[i].w;
slouken@468
  2027
		dst.top    = SDL_bounds.top+src.top;
slouken@468
  2028
		dst.left   = SDL_bounds.left+src.left;
slouken@0
  2029
		dst.bottom = SDL_bounds.top+src.bottom;
slouken@468
  2030
		dst.right  = SDL_bounds.left+src.right;
slouken@0
  2031
		result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
slouken@0
  2032
					this->screen->hwdata->dd_surface, &src,
slouken@0
  2033
							DDBLT_WAIT, NULL);
slouken@0
  2034
		/* Doh!  Check for lost surface and restore it */
slouken@0
  2035
		if ( result == DDERR_SURFACELOST ) {
slouken@0
  2036
			IDirectDrawSurface3_Restore(SDL_primary);
slouken@0
  2037
			IDirectDrawSurface3_Blt(SDL_primary, &dst, 
slouken@0
  2038
					this->screen->hwdata->dd_surface, &src,
slouken@0
  2039
							DDBLT_WAIT, NULL);
slouken@0
  2040
		}
slouken@0
  2041
	}
slouken@0
  2042
}
slouken@0
  2043
slouken@0
  2044
void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
slouken@0
  2045
{
slouken@0
  2046
}
slouken@0
  2047
slouken@0
  2048
/* Compress a full palette into the limited number of colors given to us
slouken@0
  2049
   by windows.
slouken@0
  2050
slouken@0
  2051
   The "best" way to do this is to sort the colors by diversity and place
slouken@0
  2052
   the most diverse colors into the limited palette.  Unfortunately this
slouken@0
  2053
   results in widely varying colors being displayed in the interval during
slouken@0
  2054
   which the windows palette has been set, and the mapping of the shadow
slouken@0
  2055
   surface to the new palette.  This is especially noticeable during fades.
slouken@0
  2056
slouken@0
  2057
   To deal with this problem, we can copy a predetermined portion of the
slouken@0
  2058
   full palette, and use that as the limited palette.  This allows colors
slouken@0
  2059
   to fade smoothly as the remapping is very similar on each palette change.
slouken@0
  2060
   Unfortunately, this breaks applications which partition the palette into
slouken@0
  2061
   distinct and widely varying areas, expecting all colors to be available.
slouken@0
  2062
slouken@0
  2063
   I'm making them both available, chosen at compile time.
slouken@0
  2064
   If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
slouken@0
  2065
   otherwise the sort-by-diversity algorithm will be used.
slouken@0
  2066
*/
slouken@0
  2067
#define SIMPLE_COMPRESSION
slouken@0
  2068
#define CS_CS_DIST(A, B) ({						\
slouken@0
  2069
	int r = (A.r - B.r);						\
slouken@0
  2070
	int g = (A.g - B.g);						\
slouken@0
  2071
	int b = (A.b - B.b);						\
slouken@0
  2072
	(r*r + g*g + b*b);						\
slouken@0
  2073
})
slouken@0
  2074
static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
slouken@0
  2075
{
slouken@0
  2076
#ifdef SIMPLE_COMPRESSION
slouken@0
  2077
	int i, j;
slouken@0
  2078
#else
slouken@0
  2079
	static SDL_Color zero = { 0, 0, 0, 0 };
slouken@0
  2080
	int i, j;
slouken@0
  2081
	int max, dist;
slouken@0
  2082
	int prev, next;
slouken@0
  2083
	int *pool;
slouken@0
  2084
	int *seen, *order;
slouken@0
  2085
#endif
slouken@0
  2086
slouken@0
  2087
	/* Does this happen? */
slouken@0
  2088
	if ( maxcolors > ncolors ) {
slouken@0
  2089
		maxcolors = ncolors;
slouken@0
  2090
	}
slouken@0
  2091
slouken@0
  2092
#ifdef SIMPLE_COMPRESSION
slouken@0
  2093
	/* Just copy the first "maxcolors" colors */
slouken@0
  2094
	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
slouken@0
  2095
		SDL_colors[j].peRed = colors[i].r;
slouken@0
  2096
		SDL_colors[j].peGreen = colors[i].g;
slouken@0
  2097
		SDL_colors[j].peBlue = colors[i].b;
slouken@0
  2098
	}
slouken@0
  2099
#else
slouken@0
  2100
	/* Allocate memory for the arrays we use */
slouken@0
  2101
	pool = (int *)alloca(2*ncolors*sizeof(int));
slouken@0
  2102
	if ( pool == NULL ) {
slouken@0
  2103
		/* No worries, just return */;
slouken@0
  2104
		return;
slouken@0
  2105
	}
slouken@0
  2106
	seen = pool;
slouken@0
  2107
	memset(seen, 0, ncolors*sizeof(int));
slouken@0
  2108
	order = pool+ncolors;
slouken@0
  2109
slouken@0
  2110
	/* Start with the brightest color */
slouken@0
  2111
	max = 0;
slouken@0
  2112
	for ( i=0; i<ncolors; ++i ) {
slouken@0
  2113
		dist = CS_CS_DIST(zero, colors[i]);
slouken@0
  2114
		if ( dist >= max ) {
slouken@0
  2115
			max = dist;
slouken@0
  2116
			next = i;
slouken@0
  2117
		}
slouken@0
  2118
	}
slouken@0
  2119
	j = 0;
slouken@0
  2120
	order[j++] = next;
slouken@0
  2121
	seen[next] = 1;
slouken@0
  2122
	prev = next;
slouken@0
  2123
slouken@0
  2124
	/* Keep going through all the colors */
slouken@0
  2125
	while ( j < maxcolors ) {
slouken@0
  2126
		max = 0;
slouken@0
  2127
		for ( i=0; i<ncolors; ++i ) {
slouken@0
  2128
			if ( seen[i] ) {
slouken@0
  2129
				continue;
slouken@0
  2130
			}
slouken@0
  2131
			dist = CS_CS_DIST(colors[i], colors[prev]);
slouken@0
  2132
			if ( dist >= max ) {
slouken@0
  2133
				max = dist;
slouken@0
  2134
				next = i;
slouken@0
  2135
			}
slouken@0
  2136
		}
slouken@0
  2137
		order[j++] = next;
slouken@0
  2138
		seen[next] = 1;
slouken@0
  2139
		prev = next;
slouken@0
  2140
	}
slouken@0
  2141
slouken@0
  2142
	/* Compress the colors to the palette */
slouken@0
  2143
	for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
slouken@0
  2144
		SDL_colors[j].peRed = colors[order[i]].r;
slouken@0
  2145
		SDL_colors[j].peGreen = colors[order[i]].g;
slouken@0
  2146
		SDL_colors[j].peBlue = colors[order[i]].b;
slouken@0
  2147
	}
slouken@0
  2148
#endif /* SIMPLE_COMPRESSION */
slouken@0
  2149
}
slouken@0
  2150
slouken@0
  2151
/* Set the system colormap in both fullscreen and windowed modes */
slouken@0
  2152
int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
slouken@0
  2153
{
slouken@0
  2154
	int i;
slouken@0
  2155
	int alloct_all;
slouken@0
  2156
slouken@0
  2157
	/* Copy palette colors into display palette */
slouken@0
  2158
	alloct_all = 0;
slouken@0
  2159
	if ( SDL_palette != NULL ) {
slouken@0
  2160
		if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
slouken@0
  2161
			/* We can set all entries explicitly */
slouken@0
  2162
			for ( i=0; i< ncolors; ++i ) {
slouken@0
  2163
			        int j = firstcolor + i;
slouken@0
  2164
				SDL_colors[j].peRed = colors[i].r;
slouken@0
  2165
				SDL_colors[j].peGreen = colors[i].g;
slouken@0
  2166
				SDL_colors[j].peBlue = colors[i].b;
slouken@0
  2167
			}
slouken@0
  2168
			IDirectDrawPalette_SetEntries(SDL_palette, 0,
slouken@0
  2169
				firstcolor, ncolors, &SDL_colors[firstcolor]);
slouken@0
  2170
			alloct_all = 1;
slouken@0
  2171
		} else {
slouken@0
  2172
			/* Grab the 236 most diverse colors in the palette */
slouken@0
  2173
			DX5_CompressPalette(this, colors, ncolors, 236);
slouken@0
  2174
			/* This sends an WM_PALETTECHANGED message to us */
slouken@0
  2175
			colorchange_expected = 1;
slouken@0
  2176
			IDirectDrawPalette_SetEntries(SDL_palette, 0,
slouken@0
  2177
							0, 256, SDL_colors);
slouken@0
  2178
		}
slouken@0
  2179
	}
slouken@0
  2180
	return(alloct_all);
slouken@0
  2181
}
slouken@0
  2182
slouken@0
  2183
/* Gamma code is only available on DirectX 7 and newer */
slouken@0
  2184
static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
slouken@0
  2185
{
slouken@338
  2186
#ifdef IDirectDrawGammaControl_SetGammaRamp
slouken@0
  2187
	LPDIRECTDRAWGAMMACONTROL gamma;
slouken@0
  2188
	DDGAMMARAMP gamma_ramp;
slouken@0
  2189
	HRESULT result;
slouken@338
  2190
#endif
slouken@0
  2191
slouken@338
  2192
	/* In windowed or OpenGL mode, use windib gamma code */
slouken@338
  2193
	if ( ! DDRAW_FULLSCREEN() ) {
slouken@338
  2194
		return DIB_SetGammaRamp(this, ramp);
slouken@338
  2195
	}
slouken@338
  2196
slouken@338
  2197
#ifndef IDirectDrawGammaControl_SetGammaRamp
slouken@338
  2198
	SDL_SetError("SDL compiled without DirectX gamma ramp support");
slouken@338
  2199
	return -1;
slouken@338
  2200
#else
slouken@0
  2201
	/* Check for a video mode! */
slouken@0
  2202
	if ( ! SDL_primary ) {
slouken@0
  2203
		SDL_SetError("A video mode must be set for gamma correction");
slouken@0
  2204
		return(-1);
slouken@0
  2205
	}
slouken@0
  2206
slouken@0
  2207
	/* Get the gamma control object */
slouken@0
  2208
	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
slouken@0
  2209
			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
slouken@0
  2210
	if ( result != DD_OK ) {
slouken@0
  2211
		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
slouken@0
  2212
		return(-1);
slouken@0
  2213
	}
slouken@0
  2214
slouken@0
  2215
	/* Set up the gamma ramp */
slouken@0
  2216
	memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
slouken@0
  2217
	memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
slouken@0
  2218
	memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
slouken@0
  2219
	result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
slouken@0
  2220
	if ( result != DD_OK ) {
slouken@0
  2221
		SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
slouken@0
  2222
	}
slouken@0
  2223
slouken@0
  2224
	/* Release the interface and return */
slouken@0
  2225
	IDirectDrawGammaControl_Release(gamma);
slouken@0
  2226
	return (result == DD_OK) ? 0 : -1;
slouken@338
  2227
#endif /* !IDirectDrawGammaControl_SetGammaRamp */
slouken@0
  2228
}
slouken@0
  2229
slouken@0
  2230
static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
slouken@0
  2231
{
slouken@338
  2232
#ifdef IDirectDrawGammaControl_SetGammaRamp
slouken@0
  2233
	LPDIRECTDRAWGAMMACONTROL gamma;
slouken@0
  2234
	DDGAMMARAMP gamma_ramp;
slouken@0
  2235
	HRESULT result;
slouken@338
  2236
#endif
slouken@0
  2237
slouken@338
  2238
	/* In windowed or OpenGL mode, use windib gamma code */
slouken@338
  2239
	if ( ! DDRAW_FULLSCREEN() ) {
slouken@338
  2240
		return DIB_GetGammaRamp(this, ramp);
slouken@338
  2241
	}
slouken@338
  2242
slouken@338
  2243
#ifndef IDirectDrawGammaControl_SetGammaRamp
slouken@338
  2244
	SDL_SetError("SDL compiled without DirectX gamma ramp support");
slouken@338
  2245
	return -1;
slouken@338
  2246
#else
slouken@0
  2247
	/* Check for a video mode! */
slouken@0
  2248
	if ( ! SDL_primary ) {
slouken@0
  2249
		SDL_SetError("A video mode must be set for gamma correction");
slouken@0
  2250
		return(-1);
slouken@0
  2251
	}
slouken@0
  2252
slouken@0
  2253
	/* Get the gamma control object */
slouken@0
  2254
	result = IDirectDrawSurface3_QueryInterface(SDL_primary,
slouken@0
  2255
			&IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
slouken@0
  2256
	if ( result != DD_OK ) {
slouken@0
  2257
		SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
slouken@0
  2258
		return(-1);
slouken@0
  2259
	}
slouken@0
  2260
slouken@0
  2261
	/* Set up the gamma ramp */
slouken@0
  2262
	result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
slouken@0
  2263
	if ( result == DD_OK ) {
slouken@0
  2264
		memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
slouken@0
  2265
		memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
slouken@0
  2266
		memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
slouken@0
  2267
	} else {
slouken@0
  2268
		SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
slouken@0
  2269
	}
slouken@0
  2270
slouken@0
  2271
	/* Release the interface and return */
slouken@0
  2272
	IDirectDrawGammaControl_Release(gamma);
slouken@0
  2273
	return (result == DD_OK) ? 0 : -1;
slouken@338
  2274
#endif /* !IDirectDrawGammaControl_SetGammaRamp */
slouken@0
  2275
}
slouken@0
  2276
slouken@442
  2277
static void FlushMessageQueue()
slouken@442
  2278
{
slouken@442
  2279
	MSG  msg;
slouken@442
  2280
	while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
slouken@442
  2281
		if ( msg.message == WM_QUIT ) break;
slouken@442
  2282
		TranslateMessage( &msg );
slouken@442
  2283
		DispatchMessage( &msg );
slouken@442
  2284
	}
slouken@442
  2285
}
slouken@442
  2286
slouken@0
  2287
void DX5_VideoQuit(_THIS)
slouken@0
  2288
{
slouken@0
  2289
	int i, j;
slouken@0
  2290
slouken@0
  2291
	/* If we're fullscreen GL, we need to reset the display */
slouken@0
  2292
	if ( this->screen != NULL ) {
slouken@453
  2293
#ifndef NO_CHANGEDISPLAYSETTINGS
slouken@0
  2294
		if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
slouken@0
  2295
		                            (SDL_OPENGL|SDL_FULLSCREEN) ) {
slouken@0
  2296
			ChangeDisplaySettings(NULL, 0);
slouken@376
  2297
			ShowWindow(SDL_Window, SW_HIDE);
slouken@0
  2298
		}
slouken@453
  2299
#endif
slouken@0
  2300
		if ( this->screen->flags & SDL_OPENGL ) {
slouken@0
  2301
			WIN_GL_ShutDown(this);
slouken@0
  2302
		}
slouken@0
  2303
	}
slouken@0
  2304
slouken@0
  2305
	/* Free any palettes we used */
slouken@0
  2306
	if ( SDL_palette != NULL ) {
slouken@0
  2307
		IDirectDrawPalette_Release(SDL_palette);
slouken@0
  2308
		SDL_palette = NULL;
slouken@0
  2309
	}
slouken@0
  2310
slouken@0
  2311
	/* Allow the primary surface to be freed */
slouken@0
  2312
	if ( SDL_primary != NULL ) {
slouken@0
  2313
		SDL_primary = NULL;
slouken@0
  2314
	}
slouken@0
  2315
slouken@0
  2316
	/* Free video mode lists */
slouken@0
  2317
	for ( i=0; i<NUM_MODELISTS; ++i ) {
slouken@0
  2318
		if ( SDL_modelist[i] != NULL ) {
slouken@0
  2319
			for ( j=0; SDL_modelist[i][j]; ++j )
slouken@0
  2320
				free(SDL_modelist[i][j]);
slouken@0
  2321
			free(SDL_modelist[i]);
slouken@0
  2322
			SDL_modelist[i] = NULL;
slouken@0
  2323
		}
slouken@0
  2324
	}
slouken@0
  2325
slouken@0
  2326
	/* Free the window */
slouken@338
  2327
	DIB_QuitGamma(this);
slouken@0
  2328
	if ( SDL_Window ) {
slouken@0
  2329
		DX5_DestroyWindow(this);
slouken@442
  2330
		FlushMessageQueue();
slouken@0
  2331
	}
slouken@0
  2332
slouken@0
  2333
	/* Free our window icon */
slouken@0
  2334
	if ( screen_icn ) {
slouken@0
  2335
		DestroyIcon(screen_icn);
slouken@0
  2336
		screen_icn = NULL;
slouken@0
  2337
	}
slouken@0
  2338
}
slouken@0
  2339
slouken@0
  2340
/* Exported for the windows message loop only */
slouken@0
  2341
void DX5_RealizePalette(_THIS)
slouken@0
  2342
{
slouken@0
  2343
	if ( SDL_palette ) {
slouken@0
  2344
		IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
slouken@0
  2345
	}
slouken@0
  2346
}
slouken@0
  2347
static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
slouken@0
  2348
{
slouken@0
  2349
	int row, col;
slouken@0
  2350
	Uint8 *pixels;
slouken@0
  2351
slouken@0
  2352
	if ( surface->w && surface->h ) {
slouken@0
  2353
		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@0
  2354
			if ( this->LockHWSurface(this, surface) < 0 ) {
slouken@0
  2355
				return;
slouken@0
  2356
			}
slouken@0
  2357
		}
slouken@0
  2358
		for ( row=0; row<surface->h; ++row ) {
slouken@0
  2359
			pixels = (Uint8 *)surface->pixels+row*surface->pitch;
slouken@0
  2360
			for ( col=0; col<surface->w; ++col, ++pixels ) {
slouken@0
  2361
				*pixels = mapping[*pixels];
slouken@0
  2362
			}
slouken@0
  2363
		}
slouken@0
  2364
		if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@0
  2365
			this->UnlockHWSurface(this, surface);
slouken@0
  2366
		}
slouken@0
  2367
		SDL_UpdateRect(surface, 0, 0, 0, 0);
slouken@0
  2368
	}
slouken@0
  2369
}
slouken@0
  2370
void DX5_PaletteChanged(_THIS, HWND window)
slouken@0
  2371
{
slouken@0
  2372
	SDL_Palette *palette;
slouken@0
  2373
	SDL_Color *saved = NULL;
slouken@0
  2374
	HDC hdc;
slouken@0
  2375
	int i;
slouken@0
  2376
	PALETTEENTRY *entries;
slouken@0
  2377
slouken@0
  2378
	/* This is true when the window is closing */
slouken@0
  2379
	if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
slouken@0
  2380
		return;
slouken@0
  2381
slouken@0
  2382
	/* We need to get the colors as they were set */
slouken@0
  2383
	palette = this->physpal;
slouken@0
  2384
	if(!palette)
slouken@0
  2385
	        palette = SDL_VideoSurface->format->palette;
slouken@0
  2386
	if ( palette == NULL ) { /* Sometimes we don't have a palette */
slouken@0
  2387
		return;
slouken@0
  2388
	}
slouken@0
  2389
	entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
slouken@0
  2390
	hdc = GetDC(window);
slouken@0
  2391
	GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
slouken@0
  2392
	ReleaseDC(window, hdc);
slouken@0
  2393
	if ( ! colorchange_expected ) {
slouken@0
  2394
		saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
slouken@0
  2395
		memcpy(saved, palette->colors, 
slouken@0
  2396
					palette->ncolors*sizeof(SDL_Color));
slouken@0
  2397
	}
slouken@0
  2398
	for ( i=0; i<palette->ncolors; ++i ) {
slouken@0
  2399
		palette->colors[i].r = entries[i].peRed;
slouken@0
  2400
		palette->colors[i].g = entries[i].peGreen;
slouken@0
  2401
		palette->colors[i].b = entries[i].peBlue;
slouken@0
  2402
	}
slouken@0
  2403
	if ( ! colorchange_expected ) {
slouken@0
  2404
		Uint8 mapping[256];
slouken@0
  2405
slouken@0
  2406
		memset(mapping, 0, sizeof(mapping));
slouken@0
  2407
		for ( i=0; i<palette->ncolors; ++i ) {
slouken@0
  2408
			mapping[i] = SDL_FindColor(palette,
slouken@0
  2409
					saved[i].r, saved[i].g, saved[i].b);
slouken@0
  2410
		}
slouken@0
  2411
		DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
slouken@0
  2412
	}
slouken@0
  2413
	colorchange_expected = 0;
slouken@0
  2414
slouken@0
  2415
	/* Notify all mapped surfaces of the change */
slouken@0
  2416
	SDL_FormatChanged(SDL_VideoSurface);
slouken@0
  2417
}
slouken@0
  2418
slouken@0
  2419
/* Exported for the windows message loop only */
slouken@0
  2420
void DX5_WinPAINT(_THIS, HDC hdc)
slouken@0
  2421
{
slouken@0
  2422
	SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
slouken@0
  2423
}