src/video/gapi/SDL_gapivideo.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 07 Mar 2006 05:21:32 +0000
changeset 1480 0a2bd6507477
parent 1472 4aac8563c296
child 1497 420b3f47806d
permissions -rw-r--r--
More Win64 updates
icculus@1251
     1
/*
icculus@1251
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
icculus@1251
     4
icculus@1251
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
icculus@1251
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
icculus@1251
     9
icculus@1251
    10
    This library is distributed in the hope that it will be useful,
icculus@1251
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1251
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
icculus@1251
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
icculus@1251
    18
icculus@1251
    19
    Sam Lantinga
icculus@1251
    20
    slouken@libsdl.org
icculus@1251
    21
*/
slouken@1402
    22
#include "SDL_config.h"
icculus@1251
    23
icculus@1251
    24
/* Pocket PC GAPI SDL video driver implementation;
icculus@1251
    25
Implemented by Dmitry Yakimov - support@activekitten.com
icculus@1251
    26
Inspired by http://arisme.free.fr/ports/SDL.php
icculus@1251
    27
*/
icculus@1251
    28
icculus@1251
    29
// TODO: copy surface on window when lost focus
icculus@1251
    30
// TODO: test buttons rotation
icculus@1251
    31
// TODO: test on be300 and HPC ( check WinDib fullscreen keys catching )
icculus@1251
    32
// TODO: test on smartphones
icculus@1251
    33
// TODO: windib on SH3 PPC2000 landscape test
icculus@1251
    34
// TODO: optimize 8bpp landscape mode
icculus@1251
    35
slouken@1465
    36
// there is some problems in runnings apps from a device landscape mode
slouken@1465
    37
// due to WinCE bugs. Some works and some - does not.
slouken@1465
    38
// TODO: finish Axim Dell X30 and user landscape mode, device landscape mode
slouken@1465
    39
// TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion
slouken@1465
    40
// TODO: fix running GAPI apps from landscape mode - 
slouken@1465
    41
//       wince goes to portrait mode, but does not update video memory
slouken@1465
    42
slouken@1465
    43
slouken@1465
    44
#include "SDL.h"
slouken@1465
    45
#include "SDL_error.h"
icculus@1251
    46
#include "SDL_video.h"
icculus@1251
    47
#include "SDL_mouse.h"
slouken@1361
    48
#include "../SDL_sysvideo.h"
slouken@1361
    49
#include "../SDL_pixels_c.h"
slouken@1361
    50
#include "../../events/SDL_events_c.h"
slouken@1465
    51
#include "../wincommon/SDL_syswm_c.h"
slouken@1465
    52
#include "../wincommon/SDL_sysmouse_c.h"
slouken@1465
    53
#include "../windib/SDL_dibevents_c.h" 
icculus@1251
    54
icculus@1251
    55
#include "SDL_gapivideo.h"
icculus@1251
    56
icculus@1251
    57
#define GAPIVID_DRIVER_NAME "gapi"
icculus@1251
    58
icculus@1251
    59
#if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG)
icculus@1251
    60
#define REPORT_VIDEO_INFO 1
icculus@1251
    61
#else
icculus@1251
    62
#define REPORT_VIDEO_INFO 0
icculus@1251
    63
#endif
icculus@1251
    64
icculus@1251
    65
// for testing with GapiEmu
icculus@1251
    66
#define USE_GAPI_EMU 0
slouken@1465
    67
#define EMULATE_AXIM_X30 0
slouken@1465
    68
#define WITHOUT_GAPI 0
icculus@1251
    69
icculus@1251
    70
#if USE_GAPI_EMU && !REPORT_VIDEO_INFO
icculus@1251
    71
#pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.")
icculus@1251
    72
#endif
icculus@1251
    73
icculus@1251
    74
// defined and used in SDL_sysevents.c
icculus@1251
    75
extern HINSTANCE aygshell;
icculus@1251
    76
extern void SDL_UnregisterApp();
icculus@1251
    77
extern int DIB_AddMode(_THIS, int bpp, int w, int h);
icculus@1251
    78
icculus@1251
    79
/* Initialization/Query functions */
icculus@1251
    80
static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat);
icculus@1251
    81
static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
icculus@1251
    82
static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
icculus@1251
    83
static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
icculus@1251
    84
static void GAPI_VideoQuit(_THIS);
icculus@1251
    85
icculus@1251
    86
/* Hardware surface functions */
icculus@1251
    87
static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface);
icculus@1251
    88
static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface);
icculus@1251
    89
static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface);
icculus@1251
    90
static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface);
icculus@1251
    91
icculus@1251
    92
/* Windows message handling functions, will not be processed */
icculus@1251
    93
static void GAPI_RealizePalette(_THIS);
icculus@1251
    94
static void GAPI_PaletteChanged(_THIS, HWND window);
icculus@1251
    95
static void GAPI_WinPAINT(_THIS, HDC hdc); 
icculus@1251
    96
icculus@1251
    97
/* etc. */
icculus@1251
    98
static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
icculus@1251
    99
icculus@1251
   100
static HMODULE g_hGapiLib = 0;
icculus@1251
   101
#define LINK(type,name,import) \
icculus@1251
   102
	if( g_hGapiLib ) \
icculus@1251
   103
		name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); 
icculus@1251
   104
icculus@1251
   105
static char g_bRawBufferAvailable = 0;
icculus@1251
   106
icculus@1251
   107
/* GAPI driver bootstrap functions */
icculus@1251
   108
icculus@1251
   109
/* hi res definitions */
icculus@1251
   110
typedef struct _RawFrameBufferInfo
icculus@1251
   111
{
icculus@1251
   112
   WORD wFormat;
icculus@1251
   113
   WORD wBPP;
icculus@1251
   114
   VOID *pFramePointer;
icculus@1251
   115
   int  cxStride;
icculus@1251
   116
   int  cyStride;
icculus@1251
   117
   int  cxPixels;
icculus@1251
   118
   int  cyPixels;
icculus@1251
   119
} RawFrameBufferInfo; 
icculus@1251
   120
icculus@1251
   121
static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0};
icculus@1251
   122
icculus@1251
   123
#define GETRAWFRAMEBUFFER   0x00020001
icculus@1251
   124
icculus@1251
   125
#define FORMAT_565 1
icculus@1251
   126
#define FORMAT_555 2
slouken@1465
   127
#define FORMAT_OTHER 3
slouken@1465
   128
slouken@1465
   129
/* Dell Axim x30 hangs when we use GAPI from landscape,
slouken@1465
   130
   so lets avoid using GxOpenDisplay there via GETGXINFO trick 
slouken@1465
   131
   It seems that GAPI subsystem use the same ExtEscape code.
slouken@1465
   132
*/
slouken@1465
   133
#define GETGXINFO 0x00020000
slouken@1465
   134
slouken@1465
   135
typedef struct GXDeviceInfo
slouken@1465
   136
{
slouken@1465
   137
long Version; //00 (should filled with 100 before calling ExtEscape)
slouken@1465
   138
void * pvFrameBuffer; //04
slouken@1465
   139
unsigned long cbStride; //08
slouken@1465
   140
unsigned long cxWidth; //0c
slouken@1465
   141
unsigned long cyHeight; //10
slouken@1465
   142
unsigned long cBPP; //14
slouken@1465
   143
unsigned long ffFormat; //18
slouken@1465
   144
char Unused[0x84-7*4];
slouken@1465
   145
} GXDeviceInfo; 
icculus@1251
   146
icculus@1251
   147
static int GAPI_Available(void)
icculus@1251
   148
{
icculus@1251
   149
	// try to use VGA display, even on emulator
icculus@1251
   150
	HDC hdc = GetDC(NULL); 
icculus@1251
   151
	int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo);
icculus@1251
   152
	ReleaseDC(NULL, hdc);
icculus@1251
   153
	g_bRawBufferAvailable = result > 0;
icculus@1251
   154
slouken@1465
   155
#if WITHOUT_GAPI
slouken@1465
   156
	return g_bRawBufferAvailable;
slouken@1465
   157
#endif
slouken@1465
   158
icculus@1251
   159
#if USE_GAPI_EMU
icculus@1251
   160
	g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll"));
icculus@1251
   161
	if( !g_hGapiLib )
icculus@1251
   162
	{
icculus@1251
   163
		SDL_SetError("Gapi Emu not found!");
icculus@1251
   164
	}
icculus@1251
   165
	return g_hGapiLib != 0;
icculus@1251
   166
#endif
icculus@1251
   167
icculus@1251
   168
	// try to find gx.dll
icculus@1251
   169
	g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll"));
icculus@1251
   170
	if( !g_hGapiLib )
icculus@1251
   171
	{
icculus@1251
   172
		g_hGapiLib = LoadLibrary(_T("gx.dll"));
icculus@1251
   173
		if( !g_hGapiLib ) return g_bRawBufferAvailable;
icculus@1251
   174
	}
icculus@1251
   175
icculus@1251
   176
	return(1);
icculus@1251
   177
}
icculus@1251
   178
icculus@1251
   179
static int cmpmodes(const void *va, const void *vb)
icculus@1251
   180
{
icculus@1251
   181
    SDL_Rect *a = *(SDL_Rect **)va;
icculus@1251
   182
    SDL_Rect *b = *(SDL_Rect **)vb;
icculus@1251
   183
    if ( a->w == b->w )
icculus@1251
   184
        return b->h - a->h;
icculus@1251
   185
    else
icculus@1251
   186
        return b->w - a->w;
icculus@1251
   187
}
icculus@1251
   188
icculus@1251
   189
static int GAPI_AddMode(_THIS, int bpp, int w, int h)
icculus@1251
   190
{
icculus@1251
   191
	SDL_Rect *mode;
icculus@1251
   192
	int i, index;
icculus@1251
   193
	int next_mode;
icculus@1251
   194
icculus@1251
   195
	/* Check to see if we already have this mode */
icculus@1251
   196
	if ( bpp < 8 ) {  /* Not supported */
icculus@1251
   197
		return(0);
icculus@1251
   198
	}
icculus@1251
   199
	index = ((bpp+7)/8)-1;
icculus@1251
   200
	for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) {
icculus@1251
   201
		mode = gapi->SDL_modelist[index][i];
icculus@1251
   202
		if ( (mode->w == w) && (mode->h == h) ) {
icculus@1251
   203
			return(0);
icculus@1251
   204
		}
icculus@1251
   205
	}
icculus@1251
   206
icculus@1251
   207
	/* Set up the new video mode rectangle */
slouken@1336
   208
	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
icculus@1251
   209
	if ( mode == NULL ) {
icculus@1251
   210
		SDL_OutOfMemory();
icculus@1251
   211
		return(-1);
icculus@1251
   212
	}
icculus@1251
   213
	mode->x = 0;
icculus@1251
   214
	mode->y = 0;
icculus@1251
   215
	mode->w = w;
icculus@1251
   216
	mode->h = h;
icculus@1251
   217
icculus@1251
   218
	/* Allocate the new list of modes, and fill in the new mode */
icculus@1251
   219
	next_mode = gapi->SDL_nummodes[index];
icculus@1251
   220
	gapi->SDL_modelist[index] = (SDL_Rect **)
slouken@1336
   221
	       SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
icculus@1251
   222
	if ( gapi->SDL_modelist[index] == NULL ) {
icculus@1251
   223
		SDL_OutOfMemory();
icculus@1251
   224
		gapi->SDL_nummodes[index] = 0;
slouken@1336
   225
		SDL_free(mode);
icculus@1251
   226
		return(-1);
icculus@1251
   227
	}
icculus@1251
   228
	gapi->SDL_modelist[index][next_mode] = mode;
icculus@1251
   229
	gapi->SDL_modelist[index][next_mode+1] = NULL;
icculus@1251
   230
	gapi->SDL_nummodes[index]++;
icculus@1251
   231
icculus@1251
   232
	return(0);
icculus@1251
   233
}
icculus@1251
   234
icculus@1251
   235
static void GAPI_DeleteDevice(SDL_VideoDevice *device)
icculus@1251
   236
{
icculus@1251
   237
	if( g_hGapiLib )
icculus@1251
   238
	{
icculus@1251
   239
		FreeLibrary(g_hGapiLib);
icculus@1251
   240
		g_hGapiLib = 0;
icculus@1251
   241
	}
slouken@1336
   242
	SDL_free(device->hidden);
slouken@1336
   243
	SDL_free(device);
icculus@1251
   244
}
icculus@1251
   245
icculus@1251
   246
static SDL_VideoDevice *GAPI_CreateDevice(int devindex)
icculus@1251
   247
{
icculus@1251
   248
	SDL_VideoDevice *device;
icculus@1251
   249
icculus@1251
   250
	if( !g_hGapiLib && !g_bRawBufferAvailable)
icculus@1251
   251
	{
icculus@1251
   252
		if( !GAPI_Available() )
icculus@1251
   253
		{
icculus@1251
   254
			SDL_SetError("GAPI dll is not found and VGA mode is not available!");
icculus@1251
   255
			return 0;
icculus@1251
   256
		}
icculus@1251
   257
	}
icculus@1251
   258
icculus@1251
   259
	/* Initialize all variables that we clean on shutdown */
slouken@1336
   260
	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
icculus@1251
   261
	if ( device ) {
slouken@1336
   262
		SDL_memset(device, 0, (sizeof *device));
icculus@1251
   263
		device->hidden = (struct SDL_PrivateVideoData *)
slouken@1336
   264
				SDL_malloc((sizeof *device->hidden));
icculus@1251
   265
	}
icculus@1251
   266
	if ( (device == NULL) || (device->hidden == NULL) ) {
icculus@1251
   267
		SDL_OutOfMemory();
icculus@1251
   268
		if ( device ) {
slouken@1336
   269
			SDL_free(device);
icculus@1251
   270
		}
icculus@1251
   271
		return(0);
icculus@1251
   272
	}
slouken@1336
   273
	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
icculus@1251
   274
icculus@1251
   275
	/* Set the function pointers */
icculus@1251
   276
	device->VideoInit = GAPI_VideoInit;
icculus@1251
   277
	device->ListModes = GAPI_ListModes;
icculus@1251
   278
	device->SetVideoMode = GAPI_SetVideoMode;
icculus@1251
   279
	device->UpdateMouse = WIN_UpdateMouse; 
icculus@1251
   280
	device->CreateYUVOverlay = NULL;
icculus@1251
   281
	device->SetColors = GAPI_SetColors;
icculus@1251
   282
	device->UpdateRects = GAPI_UpdateRects;
icculus@1251
   283
	device->VideoQuit = GAPI_VideoQuit;
icculus@1251
   284
	device->AllocHWSurface = GAPI_AllocHWSurface;
icculus@1251
   285
	device->CheckHWBlit = NULL;
icculus@1251
   286
	device->FillHWRect = NULL;
icculus@1251
   287
	device->SetHWColorKey = NULL;
icculus@1251
   288
	device->SetHWAlpha = NULL;
icculus@1251
   289
	device->LockHWSurface = GAPI_LockHWSurface;
icculus@1251
   290
	device->UnlockHWSurface = GAPI_UnlockHWSurface;
icculus@1251
   291
	device->FlipHWSurface = NULL;
icculus@1251
   292
	device->FreeHWSurface = GAPI_FreeHWSurface;
icculus@1251
   293
	device->SetCaption = WIN_SetWMCaption;
icculus@1251
   294
	device->SetIcon = WIN_SetWMIcon;
icculus@1251
   295
	device->IconifyWindow = WIN_IconifyWindow;
icculus@1251
   296
	device->GrabInput = WIN_GrabInput;
icculus@1251
   297
	device->GetWMInfo = WIN_GetWMInfo;
icculus@1251
   298
	device->FreeWMCursor = WIN_FreeWMCursor;
icculus@1251
   299
	device->CreateWMCursor = WIN_CreateWMCursor; 
icculus@1251
   300
	device->ShowWMCursor = WIN_ShowWMCursor;	
icculus@1251
   301
	device->WarpWMCursor = WIN_WarpWMCursor; 
icculus@1251
   302
    device->CheckMouseMode = WIN_CheckMouseMode;
icculus@1251
   303
	device->InitOSKeymap = DIB_InitOSKeymap;
icculus@1251
   304
	device->PumpEvents = DIB_PumpEvents;
icculus@1251
   305
icculus@1251
   306
	/* Set up the windows message handling functions */
icculus@1251
   307
	WIN_RealizePalette = GAPI_RealizePalette;
icculus@1251
   308
	WIN_PaletteChanged = GAPI_PaletteChanged;
icculus@1251
   309
	WIN_WinPAINT = GAPI_WinPAINT;
icculus@1251
   310
	HandleMessage = DIB_HandleMessage; 
icculus@1251
   311
icculus@1251
   312
	device->free = GAPI_DeleteDevice;
icculus@1251
   313
icculus@1251
   314
	/* Load gapi library */
icculus@1251
   315
#define gx device->hidden->gxFunc
icculus@1251
   316
icculus@1251
   317
    LINK( GXOpenDisplay, gx.GXOpenDisplay,         "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" )
icculus@1251
   318
    LINK( GXCloseDisplay, gx.GXCloseDisplay,        "?GXCloseDisplay@@YAHXZ" )
icculus@1251
   319
    LINK( GXBeginDraw, gx.GXBeginDraw,           "?GXBeginDraw@@YAPAXXZ" )
icculus@1251
   320
    LINK( GXEndDraw, gx.GXEndDraw,             "?GXEndDraw@@YAHXZ" )
icculus@1251
   321
    LINK( GXOpenInput, gx.GXOpenInput,           "?GXOpenInput@@YAHXZ" )
icculus@1251
   322
    LINK( GXCloseInput, gx.GXCloseInput,          "?GXCloseInput@@YAHXZ" )
icculus@1251
   323
    LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" )
icculus@1251
   324
    LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys,      "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" )
icculus@1251
   325
    LINK( GXSuspend, gx.GXSuspend,             "?GXSuspend@@YAHXZ" )
icculus@1251
   326
    LINK( GXResume, gx.GXResume,              "?GXResume@@YAHXZ" )
icculus@1251
   327
    LINK( GXSetViewport, gx.GXSetViewport,         "?GXSetViewport@@YAHKKKK@Z" )
icculus@1251
   328
    LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" )
icculus@1251
   329
icculus@1251
   330
	/* wrong gapi.dll */
icculus@1251
   331
	if( !gx.GXOpenDisplay )
icculus@1251
   332
	{
icculus@1251
   333
		if( g_hGapiLib ) 
icculus@1251
   334
		{
icculus@1251
   335
			FreeLibrary(g_hGapiLib);
icculus@1251
   336
			g_hGapiLib = 0;
icculus@1251
   337
		}
icculus@1251
   338
	}
icculus@1251
   339
	
icculus@1251
   340
	if( !gx.GXOpenDisplay && !g_bRawBufferAvailable)
icculus@1251
   341
	{
icculus@1251
   342
		SDL_SetError("Error: damaged or unknown gapi.dll!\n");
icculus@1251
   343
		GAPI_DeleteDevice(device);
icculus@1251
   344
		return 0;
icculus@1251
   345
	}
icculus@1251
   346
icculus@1251
   347
	return device;
icculus@1251
   348
}
icculus@1251
   349
icculus@1251
   350
VideoBootStrap GAPI_bootstrap = {
icculus@1251
   351
	GAPIVID_DRIVER_NAME, "WinCE GAPI video driver",
icculus@1251
   352
	GAPI_Available, GAPI_CreateDevice
icculus@1251
   353
};
icculus@1251
   354
icculus@1251
   355
static void FillStructs(_THIS, BOOL useVga)
icculus@1251
   356
{
icculus@1251
   357
#ifdef _ARM_
icculus@1251
   358
	WCHAR oemstr[100];
icculus@1251
   359
#endif
icculus@1251
   360
	/* fill a device properties */
icculus@1251
   361
icculus@1251
   362
	if( !useVga )
icculus@1251
   363
	{
icculus@1251
   364
		this->hidden->gxProperties = this->hidden->gxFunc.GXGetDisplayProperties();
icculus@1251
   365
		this->hidden->needUpdate = 1;
icculus@1251
   366
		this->hidden->hiresFix = 0;
icculus@1251
   367
		this->hidden->useVga = 0;
slouken@1465
   368
		this->hidden->useGXOpenDisplay = 1;
slouken@1465
   369
icculus@1251
   370
#ifdef _ARM_
icculus@1251
   371
		/* check some devices and extract addition info */
icculus@1251
   372
		SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 );
icculus@1251
   373
icculus@1251
   374
		// buggy iPaq38xx
icculus@1251
   375
		if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (this->hidden->gxProperties.cbxPitch > 0)) 
icculus@1251
   376
		{
icculus@1251
   377
			this->hidden->videoMem = (PIXEL*)0xac0755a0;
icculus@1251
   378
			this->hidden->gxProperties.cbxPitch = -640;
icculus@1251
   379
			this->hidden->gxProperties.cbyPitch = 2;
icculus@1251
   380
			this->hidden->needUpdate = 0;
icculus@1251
   381
		}
slouken@1465
   382
#if (EMULATE_AXIM_X30 == 0)
slouken@1465
   383
		// buggy Dell Axim X30
slouken@1465
   384
		if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 )
slouken@1465
   385
#endif
slouken@1465
   386
		{
slouken@1465
   387
			GXDeviceInfo gxInfo = {0};
slouken@1465
   388
			HDC hdc = GetDC(NULL);
slouken@1465
   389
			int result;
slouken@1465
   390
slouken@1465
   391
			gxInfo.Version = 100;
slouken@1465
   392
			result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo);
slouken@1465
   393
			if( result > 0 )
slouken@1465
   394
			{
slouken@1465
   395
				this->hidden->useGXOpenDisplay = 0;
slouken@1465
   396
				this->hidden->videoMem = gxInfo.pvFrameBuffer;
slouken@1465
   397
				this->hidden->needUpdate = 0;
slouken@1465
   398
				this->hidden->gxProperties.cbxPitch = 2;
slouken@1465
   399
				this->hidden->gxProperties.cbyPitch = 480;
slouken@1465
   400
				this->hidden->gxProperties.cxWidth = gxInfo.cxWidth;
slouken@1465
   401
				this->hidden->gxProperties.cyHeight = gxInfo.cyHeight;
slouken@1465
   402
				this->hidden->gxProperties.ffFormat = gxInfo.ffFormat;
slouken@1465
   403
			}
slouken@1465
   404
		}
icculus@1251
   405
#endif
icculus@1251
   406
	} else
icculus@1251
   407
	{
icculus@1251
   408
	    this->hidden->needUpdate = 0;		
icculus@1251
   409
		this->hidden->hiresFix = 0;
icculus@1251
   410
		this->hidden->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP;
icculus@1251
   411
		this->hidden->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride;
icculus@1251
   412
		this->hidden->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride;
icculus@1251
   413
		this->hidden->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels;
icculus@1251
   414
		this->hidden->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels;
icculus@1251
   415
		this->hidden->videoMem = g_RawFrameBufferInfo.pFramePointer;
icculus@1251
   416
		this->hidden->useVga = 1;
icculus@1251
   417
icculus@1251
   418
		switch( g_RawFrameBufferInfo.wFormat )
icculus@1251
   419
		{
icculus@1251
   420
		case FORMAT_565:
icculus@1251
   421
			this->hidden->gxProperties.ffFormat = kfDirect565;
icculus@1251
   422
			break;
icculus@1251
   423
		case FORMAT_555:
icculus@1251
   424
			this->hidden->gxProperties.ffFormat = kfDirect555;
icculus@1251
   425
			break;
icculus@1251
   426
		default:
icculus@1251
   427
			/* unknown pixel format, try define by BPP! */
icculus@1251
   428
			switch( g_RawFrameBufferInfo.wBPP )
icculus@1251
   429
			{
icculus@1251
   430
			case 4:
icculus@1251
   431
			case 8:
icculus@1251
   432
				this->hidden->gxProperties.ffFormat = kfDirect;
icculus@1251
   433
			case 16:
icculus@1251
   434
				this->hidden->gxProperties.ffFormat = kfDirect565;
icculus@1251
   435
			default:
icculus@1251
   436
				this->hidden->gxProperties.ffFormat = kfDirect;
icculus@1251
   437
				break;
icculus@1251
   438
			}
icculus@1251
   439
		}
icculus@1251
   440
	}
icculus@1251
   441
icculus@1251
   442
	if( this->hidden->gxProperties.cBPP != 16 )
icculus@1251
   443
	{
icculus@1251
   444
		this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
icculus@1251
   445
	} else
icculus@1251
   446
	if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
icculus@1251
   447
	{
icculus@1251
   448
		this->hidden->gapiOrientation = SDL_ORIENTATION_UP;
icculus@1251
   449
	} else
icculus@1251
   450
	if( (this->hidden->gxProperties.cbxPitch > 0) && (this->hidden->gxProperties.cbyPitch < 0 ))
icculus@1251
   451
	{
icculus@1251
   452
		this->hidden->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660
icculus@1251
   453
	} else
icculus@1251
   454
	if( (this->hidden->gxProperties.cbxPitch < 0) && (this->hidden->gxProperties.cbyPitch > 0 ))
icculus@1251
   455
	{
icculus@1251
   456
		this->hidden->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800
icculus@1251
   457
	}
icculus@1251
   458
}
icculus@1251
   459
icculus@1251
   460
static void GAPI_CreatePalette(int ncolors, SDL_Color *colors)
icculus@1251
   461
{
icculus@1251
   462
  // Setup a custom color palette
icculus@1251
   463
   BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ];
icculus@1251
   464
   int i;
icculus@1251
   465
   LOGPALETTE*   pLogical = (LOGPALETTE*)buffer;
icculus@1251
   466
   PALETTEENTRY* entries  = pLogical->palPalEntry;
icculus@1251
   467
   HPALETTE hPalette;
icculus@1251
   468
   HDC hdc;
icculus@1251
   469
icculus@1251
   470
   for (i = 0; i < ncolors; ++i)
icculus@1251
   471
   {
icculus@1251
   472
      // Find intensity by replicating the bit patterns over a byte
icculus@1251
   473
      entries[i].peRed   = colors[i].r;
icculus@1251
   474
      entries[i].peGreen = colors[i].g;
icculus@1251
   475
      entries[i].peBlue  = colors[i].b;
icculus@1251
   476
      entries[i].peFlags = 0;
icculus@1251
   477
   }
icculus@1251
   478
icculus@1251
   479
   // Create the GDI palette object
icculus@1251
   480
   pLogical->palVersion    = 0x0300;
icculus@1251
   481
   pLogical->palNumEntries = ncolors;
icculus@1251
   482
icculus@1251
   483
   hPalette = CreatePalette( pLogical );
icculus@1251
   484
   ASSERT(hPalette);
icculus@1251
   485
	
icculus@1251
   486
icculus@1251
   487
   // Realize the palette
icculus@1251
   488
   hdc = GetDC(0);
icculus@1251
   489
icculus@1251
   490
   SelectPalette( hdc, hPalette, FALSE );
icculus@1251
   491
   RealizePalette( hdc );
icculus@1251
   492
icculus@1251
   493
   ReleaseDC( 0, hdc );
icculus@1251
   494
   DeleteObject( hPalette );
icculus@1251
   495
}
icculus@1251
   496
icculus@1251
   497
int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat)
icculus@1251
   498
{
icculus@1251
   499
	int i,bpp;
icculus@1251
   500
icculus@1251
   501
	/* Create the window */
icculus@1251
   502
	if ( DIB_CreateWindow(this) < 0 ) {
icculus@1251
   503
		return(-1);
icculus@1251
   504
	}
icculus@1251
   505
icculus@1251
   506
	if( g_hGapiLib )
icculus@1251
   507
	{
icculus@1251
   508
		FillStructs(this, 0);
icculus@1251
   509
icculus@1251
   510
		// SDL does not supports 2/4bpp mode, so use 16 bpp
icculus@1251
   511
		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
icculus@1251
   512
		
icculus@1251
   513
		/* set up normal and landscape mode */
icculus@1251
   514
		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);	
icculus@1251
   515
		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);	
icculus@1251
   516
	}
icculus@1251
   517
icculus@1251
   518
	/* add hi-res mode */
icculus@1251
   519
	if( g_bRawBufferAvailable && 
icculus@1251
   520
		!((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels)))
icculus@1251
   521
	{
icculus@1251
   522
		FillStructs(this, 1);
icculus@1251
   523
icculus@1251
   524
		// SDL does not supports 2/4bpp mode, so use 16 bpp
icculus@1251
   525
		bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP;
icculus@1251
   526
icculus@1251
   527
		/* set up normal and landscape mode */
icculus@1251
   528
		GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth);	
icculus@1251
   529
		GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight);	
icculus@1251
   530
	}
icculus@1251
   531
icculus@1251
   532
	/* Sort the mode lists */
icculus@1251
   533
	for ( i=0; i<NUM_MODELISTS; ++i ) {
icculus@1251
   534
		if ( gapi->SDL_nummodes[i] > 0 ) {
slouken@1338
   535
			SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes);
icculus@1251
   536
		}
icculus@1251
   537
	}
icculus@1251
   538
icculus@1251
   539
	vformat->BitsPerPixel = this->hidden->gxProperties.cBPP < 8 ? 16 : (unsigned char)this->hidden->gxProperties.cBPP;
icculus@1251
   540
icculus@1251
   541
	// Get color mask
icculus@1251
   542
	if (this->hidden->gxProperties.ffFormat & kfDirect565) {
icculus@1251
   543
		vformat->BitsPerPixel = 16;
icculus@1251
   544
		vformat->Rmask = 0x0000f800;
icculus@1251
   545
		vformat->Gmask = 0x000007e0;
icculus@1251
   546
		vformat->Bmask = 0x0000001f;
icculus@1251
   547
		this->hidden->videoMode = GAPI_DIRECT_565;
icculus@1251
   548
	}
icculus@1251
   549
	else
icculus@1251
   550
	if (this->hidden->gxProperties.ffFormat & kfDirect555) {
icculus@1251
   551
		vformat->BitsPerPixel = 16;
icculus@1251
   552
		vformat->Rmask = 0x00007c00;
icculus@1251
   553
		vformat->Gmask = 0x000003e0;
icculus@1251
   554
		vformat->Bmask = 0x0000001f;
icculus@1251
   555
		this->hidden->videoMode = GAPI_DIRECT_555;
icculus@1251
   556
	}
icculus@1251
   557
	else
icculus@1251
   558
	if ((this->hidden->gxProperties.ffFormat & kfDirect) && (this->hidden->gxProperties.cBPP < 8)) {
icculus@1251
   559
		// We'll perform the conversion
icculus@1251
   560
		vformat->BitsPerPixel = 16;
icculus@1251
   561
		vformat->Rmask = 0x0000f800; // 16 bit 565
icculus@1251
   562
		vformat->Gmask = 0x000007e0;
icculus@1251
   563
		vformat->Bmask = 0x0000001f;
icculus@1251
   564
		if (this->hidden->gxProperties.ffFormat & kfDirectInverted)
icculus@1251
   565
			this->hidden->invert = (1 << this->hidden->gxProperties.cBPP) - 1;
icculus@1251
   566
		this->hidden->colorscale = this->hidden->gxProperties.cBPP < 8 ? 8 - this->hidden->gxProperties.cBPP : 0;
icculus@1251
   567
		this->hidden->videoMode = GAPI_MONO;
icculus@1251
   568
	}
icculus@1251
   569
	else
icculus@1251
   570
	if (this->hidden->gxProperties.ffFormat & kfPalette) {
icculus@1251
   571
		this->hidden->videoMode = GAPI_PALETTE;
icculus@1251
   572
	} 
icculus@1251
   573
icculus@1251
   574
	/* We're done! */
icculus@1251
   575
	return(0);
icculus@1251
   576
}
icculus@1251
   577
icculus@1251
   578
SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
icculus@1251
   579
{
icculus@1251
   580
	return(this->hidden->SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
icculus@1251
   581
//  	 return (SDL_Rect **) -1;
icculus@1251
   582
}
icculus@1251
   583
icculus@1251
   584
SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
icculus@1251
   585
				int width, int height, int bpp, Uint32 flags)
icculus@1251
   586
{
icculus@1251
   587
	SDL_Surface *video; 
icculus@1251
   588
	Uint32 Rmask, Gmask, Bmask; 
icculus@1251
   589
	DWORD style; 
icculus@1251
   590
	SDL_Rect allScreen;
icculus@1251
   591
icculus@1251
   592
	if( bpp < 4 )
icculus@1251
   593
	{
icculus@1251
   594
		SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!");
icculus@1251
   595
		return 0;
icculus@1251
   596
	}
icculus@1251
   597
icculus@1251
   598
	/* Recalculate bitmasks if necessary */
icculus@1251
   599
	if (bpp == current->format->BitsPerPixel) {
icculus@1251
   600
		video = current;
icculus@1251
   601
	}
icculus@1251
   602
	else {
icculus@1251
   603
		switch(bpp) {
icculus@1251
   604
			case 8:
icculus@1251
   605
				Rmask = 0;
icculus@1251
   606
				Gmask = 0;
icculus@1251
   607
				Bmask = 0;
icculus@1251
   608
				break;
icculus@1251
   609
			case 15:				
icculus@1251
   610
			case 16:
icculus@1251
   611
				/* Default is 565 unless the display is specifically 555 */
icculus@1251
   612
				if (this->hidden->gxProperties.ffFormat & kfDirect555) {
icculus@1251
   613
					Rmask = 0x00007c00;
icculus@1251
   614
					Gmask = 0x000003e0;
icculus@1251
   615
					Bmask = 0x0000001f;
icculus@1251
   616
				}
icculus@1251
   617
				else {
icculus@1251
   618
					Rmask = 0x0000f800;
icculus@1251
   619
					Gmask = 0x000007e0;
icculus@1251
   620
					Bmask = 0x0000001f;
icculus@1251
   621
				}
icculus@1251
   622
				break;
icculus@1251
   623
			case 24:
icculus@1251
   624
			case 32:
icculus@1251
   625
				Rmask = 0x00ff0000;
icculus@1251
   626
				Gmask = 0x0000ff00;
icculus@1251
   627
				Bmask = 0x000000ff;
icculus@1251
   628
				break;
icculus@1251
   629
			default:
icculus@1251
   630
				SDL_SetError("Unsupported Bits Per Pixel format requested");
icculus@1251
   631
				return NULL;
icculus@1251
   632
		}
icculus@1251
   633
		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
icculus@1251
   634
					0, 0, bpp, Rmask, Gmask, Bmask, 0);
icculus@1251
   635
		if ( video == NULL ) {
icculus@1251
   636
			SDL_OutOfMemory();
icculus@1251
   637
			return(NULL);
icculus@1251
   638
		}
icculus@1251
   639
	}
icculus@1251
   640
icculus@1251
   641
	gapi->userOrientation = SDL_ORIENTATION_UP;
icculus@1251
   642
	video->flags = SDL_FULLSCREEN;	/* Clear flags, GAPI supports fullscreen only */
icculus@1251
   643
icculus@1251
   644
	/* GAPI or VGA? */
icculus@1251
   645
	if( g_hGapiLib )
icculus@1251
   646
	{
icculus@1251
   647
		FillStructs(this, 0);
icculus@1251
   648
		if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight))
icculus@1251
   649
			&& (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth)))
icculus@1251
   650
			FillStructs(this, 1); // gapi is found but we use VGA resolution			
icculus@1251
   651
	} else
icculus@1251
   652
		FillStructs(this, 1);
icculus@1251
   653
icculus@1251
   654
	if ( !this->hidden->needUpdate && !this->hidden->videoMem) {
icculus@1251
   655
		SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug");
icculus@1251
   656
		return(NULL);
icculus@1251
   657
	}
icculus@1251
   658
slouken@1465
   659
	/* detect user landscape mode */
icculus@1251
   660
	if( (width > height) && (GetSystemMetrics(SM_CXSCREEN) < GetSystemMetrics(SM_CYSCREEN))) 
icculus@1251
   661
		gapi->userOrientation = SDL_ORIENTATION_RIGHT;
icculus@1251
   662
icculus@1251
   663
	/* shall we apply hires fix? for example when we do not use hires resource */
icculus@1251
   664
	gapi->hiresFix = 0;
icculus@1251
   665
	if( gapi->userOrientation == SDL_ORIENTATION_RIGHT )
icculus@1251
   666
	{
icculus@1251
   667
		if( (width > GetSystemMetrics(SM_CYSCREEN)) || (height > GetSystemMetrics(SM_CXSCREEN)))
icculus@1251
   668
			gapi->hiresFix = 1;
icculus@1251
   669
	} else
icculus@1251
   670
		if( (width > GetSystemMetrics(SM_CXSCREEN)) || (height > GetSystemMetrics(SM_CYSCREEN)))
slouken@1465
   671
			if( !((width == GetSystemMetrics(SM_CYSCREEN)) && (height == GetSystemMetrics(SM_CXSCREEN)))) // user portrait, device landscape
slouken@1465
   672
				gapi->hiresFix = 1;
icculus@1251
   673
icculus@1251
   674
	switch( gapi->userOrientation )
icculus@1251
   675
	{
icculus@1251
   676
	case SDL_ORIENTATION_UP:
icculus@1251
   677
		gapi->startOffset = 0;
icculus@1251
   678
		gapi->dstLineStep = gapi->gxProperties.cbyPitch;
icculus@1251
   679
		gapi->dstPixelStep = gapi->gxProperties.cbxPitch;
icculus@1251
   680
		break;
icculus@1251
   681
	case SDL_ORIENTATION_RIGHT:
icculus@1251
   682
		switch( gapi->gapiOrientation )
icculus@1251
   683
		{
icculus@1251
   684
		case SDL_ORIENTATION_UP:
icculus@1251
   685
		case SDL_ORIENTATION_RIGHT:
icculus@1251
   686
		case SDL_ORIENTATION_LEFT:
icculus@1251
   687
			if( (this->hidden->videoMode == GAPI_MONO) )
icculus@1251
   688
				gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode
icculus@1251
   689
			else
icculus@1251
   690
				gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1);
icculus@1251
   691
				
icculus@1251
   692
			gapi->dstLineStep = gapi->gxProperties.cbxPitch;
icculus@1251
   693
			gapi->dstPixelStep = -gapi->gxProperties.cbyPitch;
icculus@1251
   694
			break;
icculus@1251
   695
		}
icculus@1251
   696
	}
icculus@1251
   697
icculus@1251
   698
	video->w = this->hidden->w = width;
icculus@1251
   699
	video->h = this->hidden->h = height;
icculus@1251
   700
	video->pitch = SDL_CalculatePitch(video); 
icculus@1251
   701
icculus@1251
   702
	/* Small fix for WinCE/Win32 - when activating window
icculus@1251
   703
	   SDL_VideoSurface is equal to zero, so activating code
icculus@1251
   704
	   is not called properly for fullscreen windows because
icculus@1251
   705
	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
icculus@1251
   706
	*/
icculus@1251
   707
	SDL_VideoSurface = video;
icculus@1251
   708
icculus@1251
   709
	/* GAPI is always fullscreen, title bar is useless */
icculus@1251
   710
	style = 0;
icculus@1251
   711
icculus@1251
   712
	if (!SDL_windowid)
slouken@1480
   713
		SetWindowLong(SDL_Window, GWL_STYLE, style);
slouken@1465
   714
icculus@1251
   715
	/* Allocate bitmap */
icculus@1251
   716
	if(gapiBuffer) 
icculus@1251
   717
	{
slouken@1336
   718
		SDL_free(gapiBuffer);
icculus@1251
   719
		gapiBuffer = NULL;
icculus@1251
   720
	}
slouken@1336
   721
	gapiBuffer = SDL_malloc(video->h * video->pitch);
icculus@1251
   722
	video->pixels = gapiBuffer; 
icculus@1251
   723
icculus@1251
   724
	if ( ! this->hidden->buffer ) {
icculus@1251
   725
		SDL_SetError("Couldn't allocate buffer for requested mode");
icculus@1251
   726
		return(NULL);
icculus@1251
   727
	}
icculus@1251
   728
slouken@1336
   729
	SDL_memset(gapiBuffer, 255, video->h * video->pitch);
icculus@1251
   730
	MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
icculus@1251
   731
	ShowWindow(SDL_Window, SW_SHOW);
icculus@1251
   732
	SetForegroundWindow(SDL_Window);
icculus@1251
   733
slouken@1465
   734
	/* Open GAPI display */
slouken@1465
   735
	if( !gapi->useVga && this->hidden->useGXOpenDisplay )
slouken@1465
   736
		if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) )
slouken@1465
   737
		{
slouken@1465
   738
			SDL_SetError("Couldn't initialize GAPI");
slouken@1465
   739
			return(NULL);
slouken@1465
   740
		}
slouken@1465
   741
icculus@1251
   742
#if REPORT_VIDEO_INFO
icculus@1251
   743
	printf("Video properties:\n");
icculus@1251
   744
	printf("display bpp: %d\n", gapi->gxProperties.cBPP);
icculus@1251
   745
	printf("display width: %d\n", gapi->gxProperties.cxWidth);
icculus@1251
   746
	printf("display height: %d\n", gapi->gxProperties.cyHeight);
icculus@1251
   747
	printf("x pitch: %d\n", gapi->gxProperties.cbxPitch);
icculus@1251
   748
	printf("y pitch: %d\n", gapi->gxProperties.cbyPitch);
icculus@1251
   749
	printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat);
slouken@1465
   750
slouken@1465
   751
	if( !gapi->useVga && this->hidden->useGXOpenDisplay && gapi->needUpdate)
slouken@1465
   752
	{
slouken@1465
   753
		gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 
slouken@1465
   754
		gapi->gxFunc.GXEndDraw();
slouken@1465
   755
	}
slouken@1465
   756
icculus@1251
   757
	printf("video memory: 0x%x\n", gapi->videoMem);
icculus@1251
   758
	printf("need update: %d\n", gapi->needUpdate);
icculus@1251
   759
	printf("hi-res fix: %d\n", gapi->hiresFix);
icculus@1251
   760
	printf("VGA is available on the device: %d\n", g_bRawBufferAvailable);
slouken@1465
   761
	printf("use raw framebuffer: %d\n", gapi->useVga);
icculus@1251
   762
	printf("video surface bpp: %d\n", video->format->BitsPerPixel);
icculus@1251
   763
	printf("video surface width: %d\n", video->w);
icculus@1251
   764
	printf("video surface height: %d\n", video->h);
icculus@1251
   765
#endif
icculus@1251
   766
slouken@1465
   767
icculus@1251
   768
	/* Blank screen */
icculus@1251
   769
	allScreen.x = allScreen.y = 0;
icculus@1251
   770
	allScreen.w = video->w - 1;
icculus@1251
   771
	allScreen.h = video->h - 1;
icculus@1251
   772
	GAPI_UpdateRects(this, 1, &allScreen);
icculus@1251
   773
icculus@1251
   774
	/* We're done */
icculus@1251
   775
	return(video);
icculus@1251
   776
}
icculus@1251
   777
icculus@1251
   778
/* We don't actually allow hardware surfaces other than the main one */
icculus@1251
   779
static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface)
icculus@1251
   780
{
icculus@1251
   781
	return(-1);
icculus@1251
   782
}
icculus@1251
   783
static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface)
icculus@1251
   784
{
icculus@1251
   785
	return;
icculus@1251
   786
}
icculus@1251
   787
icculus@1251
   788
/* We need to wait for vertical retrace on page flipped displays */
icculus@1251
   789
static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface)
icculus@1251
   790
{
icculus@1251
   791
	return(0);
icculus@1251
   792
}
icculus@1251
   793
icculus@1251
   794
static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface)
icculus@1251
   795
{
icculus@1251
   796
	return;
icculus@1251
   797
}
icculus@1251
   798
icculus@1251
   799
static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines)
icculus@1251
   800
{
icculus@1251
   801
	if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */
icculus@1251
   802
	{
slouken@1336
   803
		SDL_memcpy(destPointer, srcPointer, width);
icculus@1251
   804
		return 1;
icculus@1251
   805
	} else
icculus@1251
   806
	{
icculus@1251
   807
		// TODO: read 4 pixels, write DWORD
icculus@1251
   808
		int step = gapi->dstPixelStep;
icculus@1251
   809
		while(width--)
icculus@1251
   810
		{
icculus@1251
   811
			*destPointer = *srcPointer++;
icculus@1251
   812
			destPointer += step;
icculus@1251
   813
		}
icculus@1251
   814
	}
icculus@1251
   815
	return 1;
icculus@1251
   816
}
icculus@1251
   817
icculus@1251
   818
/* Video memory is very slow so lets optimize as much as possible */
icculus@1251
   819
static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines)
icculus@1251
   820
{
icculus@1251
   821
	PIXEL *line1, *line2;
icculus@1251
   822
	int step = gapi->dstPixelStep / 2;
icculus@1251
   823
icculus@1251
   824
	if( step == 1 ) /* optimized blitting on most devices */
icculus@1251
   825
	{
slouken@1336
   826
		SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL));
icculus@1251
   827
		return 1;
icculus@1251
   828
	}
icculus@1251
   829
	else
icculus@1251
   830
	{
icculus@1251
   831
		if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) &&
icculus@1251
   832
			(gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up
icculus@1251
   833
		{	
icculus@1251
   834
			// to prevent data misalignment copy only one line
icculus@1251
   835
			if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) 
icculus@1251
   836
				|| ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT))
icculus@1251
   837
				|| (lines == 1) ) 
icculus@1251
   838
			{
icculus@1251
   839
				while(width--)
icculus@1251
   840
				{
icculus@1251
   841
					*destPointer = *srcPointer++;
icculus@1251
   842
					destPointer += step;
icculus@1251
   843
				}
icculus@1251
   844
				return 1;
icculus@1251
   845
			}
icculus@1251
   846
icculus@1251
   847
			/* read two lines at the same time, write DWORD */
icculus@1251
   848
			line1 = srcPointer;
icculus@1251
   849
			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
icculus@1251
   850
icculus@1251
   851
			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
icculus@1251
   852
				while(width--) // iPaq 3800
icculus@1251
   853
				{
icculus@1251
   854
					*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
icculus@1251
   855
					destPointer += step;
icculus@1251
   856
				}
icculus@1251
   857
			else
icculus@1251
   858
			{
icculus@1251
   859
				destPointer += gapi->gxProperties.cbyPitch / 2;
slouken@1465
   860
icculus@1251
   861
				while(width--) // iPaq 3660
icculus@1251
   862
				{
icculus@1251
   863
					*(DWORD*)destPointer =(*line1++ << 16) | *line2++;
icculus@1251
   864
					destPointer += step;
icculus@1251
   865
				}
icculus@1251
   866
			}
icculus@1251
   867
			return 2;
icculus@1251
   868
		} else
icculus@1251
   869
		{
icculus@1251
   870
			// iPaq 3800 and user orientation landscape
icculus@1251
   871
			if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT )
icculus@1251
   872
			{
icculus@1251
   873
				int w1;
icculus@1251
   874
icculus@1251
   875
				// to prevent data misalignment copy only one pixel
icculus@1251
   876
				if( (((unsigned)destPointer & 3) == 0) && (width > 0)) 
icculus@1251
   877
				{
icculus@1251
   878
					*destPointer-- = *srcPointer++;
icculus@1251
   879
					width--;
icculus@1251
   880
				}
icculus@1251
   881
icculus@1251
   882
				destPointer--;
icculus@1251
   883
icculus@1251
   884
				w1 = width / 2;
icculus@1251
   885
icculus@1251
   886
				while(w1--)
icculus@1251
   887
				{
icculus@1251
   888
					DWORD p = *(DWORD*)srcPointer;
icculus@1251
   889
					*((DWORD*)destPointer) = (p << 16) | (p >> 16);
icculus@1251
   890
					destPointer -= 2;
icculus@1251
   891
					srcPointer += 2;
icculus@1251
   892
				}
icculus@1251
   893
icculus@1251
   894
				if( width & 1 ) // copy the last pixel
icculus@1251
   895
				{
icculus@1251
   896
					destPointer++;
icculus@1251
   897
					*destPointer = *srcPointer;
icculus@1251
   898
				}
icculus@1251
   899
icculus@1251
   900
				return 1;
icculus@1251
   901
			}
icculus@1251
   902
icculus@1251
   903
			// modern iPaqs and user orientation landscape
icculus@1251
   904
			// read two pixels, write DWORD
icculus@1251
   905
icculus@1251
   906
			line1 = srcPointer;
icculus@1251
   907
			line2 = srcPointer + SDL_VideoSurface->pitch / 2;
icculus@1251
   908
icculus@1251
   909
			if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) 
icculus@1251
   910
			{
icculus@1251
   911
				while(width--)
icculus@1251
   912
				{
icculus@1251
   913
					*destPointer = *srcPointer++;
icculus@1251
   914
					destPointer += step;
icculus@1251
   915
				}
icculus@1251
   916
				return 1;
icculus@1251
   917
			}
icculus@1251
   918
			
icculus@1251
   919
			while(width--)
icculus@1251
   920
			{
icculus@1251
   921
				*(DWORD*)destPointer =(*line2++ << 16) | *line1++;
icculus@1251
   922
				destPointer -= gapi->gxProperties.cbyPitch / 2;
icculus@1251
   923
			}
icculus@1251
   924
			return 2;
icculus@1251
   925
		}
icculus@1251
   926
	}
icculus@1251
   927
}
icculus@1251
   928
icculus@1251
   929
// Color component masks for 565
icculus@1251
   930
#define REDMASK (31<<11)
icculus@1251
   931
#define GREENMASK (63<<5)
icculus@1251
   932
#define BLUEMASK (31)
icculus@1251
   933
icculus@1251
   934
icculus@1251
   935
static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble)
icculus@1251
   936
{
icculus@1251
   937
	PIXEL *line1, *line2;
icculus@1251
   938
	int step = gapi->dstPixelStep;
icculus@1251
   939
icculus@1251
   940
	if( gapi->userOrientation == SDL_ORIENTATION_UP )
icculus@1251
   941
	{
icculus@1251
   942
		if( yNibble ) // copy bottom half of a line
icculus@1251
   943
		{
icculus@1251
   944
			while(width--)
icculus@1251
   945
			{
icculus@1251
   946
				PIXEL c1 = *srcPointer++;
icculus@1251
   947
				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);			
icculus@1251
   948
				*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
icculus@1251
   949
				destPointer += step;
icculus@1251
   950
			}
icculus@1251
   951
			return 1;
icculus@1251
   952
		}
icculus@1251
   953
icculus@1251
   954
		// either 1 pixel picture or tail, anyway this is the last line
icculus@1251
   955
		if( lines == 1 )
icculus@1251
   956
		{
icculus@1251
   957
			while(width--)
icculus@1251
   958
			{
icculus@1251
   959
				PIXEL c1 = *srcPointer++;
icculus@1251
   960
				c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);			
icculus@1251
   961
				*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
icculus@1251
   962
				destPointer += step;
icculus@1251
   963
			}
icculus@1251
   964
			return 1;
icculus@1251
   965
		}
icculus@1251
   966
icculus@1251
   967
		line1 = srcPointer;
icculus@1251
   968
		line2 = srcPointer + SDL_VideoSurface->pitch / 2;
icculus@1251
   969
icculus@1251
   970
		while(width--)
icculus@1251
   971
		{
icculus@1251
   972
			PIXEL c1 = *line1++;
icculus@1251
   973
			PIXEL c2 = *line2++;
icculus@1251
   974
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
icculus@1251
   975
			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
icculus@1251
   976
			*destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4));
icculus@1251
   977
			destPointer += step;
icculus@1251
   978
		}
icculus@1251
   979
		return 2;
icculus@1251
   980
	} else
icculus@1251
   981
	{
icculus@1251
   982
		int w1;
icculus@1251
   983
		w1 = width / 2;
icculus@1251
   984
icculus@1251
   985
		if( xNibble )
icculus@1251
   986
		{
icculus@1251
   987
			// copy one pixel
icculus@1251
   988
			PIXEL c1 = *srcPointer++;
icculus@1251
   989
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);			
icculus@1251
   990
			*destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF));
icculus@1251
   991
			destPointer++;
icculus@1251
   992
		}
icculus@1251
   993
icculus@1251
   994
		while(w1--)
icculus@1251
   995
		{
icculus@1251
   996
			PIXEL c1 = *srcPointer;
icculus@1251
   997
			PIXEL c2 = *(srcPointer + 1);
icculus@1251
   998
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);
icculus@1251
   999
			c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK);
icculus@1251
  1000
			*destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4));
icculus@1251
  1001
			srcPointer += 2;
icculus@1251
  1002
		}
icculus@1251
  1003
icculus@1251
  1004
		// copy tail
icculus@1251
  1005
		if( (width & 1) && !xNibble )
icculus@1251
  1006
		{
icculus@1251
  1007
			PIXEL c1 = *srcPointer;
icculus@1251
  1008
			c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK);			
icculus@1251
  1009
			*destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4));
icculus@1251
  1010
		}
icculus@1251
  1011
icculus@1251
  1012
		return 1;
icculus@1251
  1013
	}
icculus@1251
  1014
}
icculus@1251
  1015
icculus@1251
  1016
static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects)
icculus@1251
  1017
{
icculus@1251
  1018
	int i, height;
icculus@1251
  1019
	int linesProcessed;
icculus@1251
  1020
	int xNibble, yNibble;
icculus@1251
  1021
icculus@1251
  1022
	for (i=0; i<numrects; i++)
icculus@1251
  1023
	{
icculus@1251
  1024
		unsigned char *destPointer;
icculus@1251
  1025
		unsigned char *srcPointer;
icculus@1251
  1026
icculus@1251
  1027
		if( gapi->userOrientation == SDL_ORIENTATION_UP )
icculus@1251
  1028
			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep;
icculus@1251
  1029
		else
icculus@1251
  1030
			destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep;
icculus@1251
  1031
icculus@1251
  1032
		srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2;
icculus@1251
  1033
		yNibble = rects[i].y & 1; // TODO: only for 4 bpp
icculus@1251
  1034
		xNibble = rects[i].x & 1;
icculus@1251
  1035
		height = rects[i].h;
icculus@1251
  1036
		while (height > 0)
icculus@1251
  1037
		{
icculus@1251
  1038
			switch(gapi->gxProperties.cBPP)
icculus@1251
  1039
			{
icculus@1251
  1040
			case 2: // TODO
icculus@1251
  1041
			case 4:
icculus@1251
  1042
					linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble);
icculus@1251
  1043
					yNibble = 0;
icculus@1251
  1044
			}
icculus@1251
  1045
			height -= linesProcessed;
icculus@1251
  1046
			if( gapi->userOrientation == SDL_ORIENTATION_UP )
icculus@1251
  1047
				destPointer--; // always fill 1 byte
icculus@1251
  1048
			else destPointer += gapi->dstLineStep;
icculus@1251
  1049
			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
icculus@1251
  1050
		}
icculus@1251
  1051
	}
icculus@1251
  1052
}
icculus@1251
  1053
icculus@1251
  1054
static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects)
icculus@1251
  1055
{
icculus@1251
  1056
	int i, height;
icculus@1251
  1057
	int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8;
icculus@1251
  1058
	int linesProcessed;
icculus@1251
  1059
	for (i=0; i<numrects; i++) {
icculus@1251
  1060
		unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep;
icculus@1251
  1061
		unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel;
icculus@1251
  1062
		height = rects[i].h;
icculus@1251
  1063
icculus@1251
  1064
//		fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h);
icculus@1251
  1065
//		fflush(stderr);
icculus@1251
  1066
		linesProcessed = height;
icculus@1251
  1067
icculus@1251
  1068
		while (height > 0) {
icculus@1251
  1069
			switch(bytesPerPixel)
icculus@1251
  1070
			{
icculus@1251
  1071
			case 1:
icculus@1251
  1072
				linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height);
icculus@1251
  1073
				break;
icculus@1251
  1074
			case 2:
icculus@1251
  1075
#pragma warning(disable: 4133)
icculus@1251
  1076
				linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height);
icculus@1251
  1077
				break;
icculus@1251
  1078
			}
icculus@1251
  1079
			height -= linesProcessed;
icculus@1251
  1080
			destPointer += gapi->dstLineStep * linesProcessed;
icculus@1251
  1081
			srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes
icculus@1251
  1082
		}
icculus@1251
  1083
//		fprintf(stderr, "End of rect\n");
icculus@1251
  1084
//		fflush(stderr);
icculus@1251
  1085
	}
icculus@1251
  1086
}
icculus@1251
  1087
icculus@1251
  1088
icculus@1251
  1089
static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
icculus@1251
  1090
{
icculus@1251
  1091
	if( gapi->needUpdate )
icculus@1251
  1092
		gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 
icculus@1251
  1093
icculus@1251
  1094
	if( gapi->gxProperties.cBPP < 8 )
icculus@1251
  1095
		GAPI_UpdateRectsMono(this, numrects, rects);
icculus@1251
  1096
	else
icculus@1251
  1097
		GAPI_UpdateRectsColor(this, numrects, rects);
icculus@1251
  1098
icculus@1251
  1099
	if( gapi->needUpdate )
icculus@1251
  1100
		gapi->gxFunc.GXEndDraw();
icculus@1251
  1101
}
icculus@1251
  1102
icculus@1251
  1103
static void FlushMessageQueue()
icculus@1251
  1104
{
icculus@1251
  1105
	MSG  msg;
icculus@1251
  1106
	while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
icculus@1251
  1107
		if ( msg.message == WM_QUIT ) break;
icculus@1251
  1108
		TranslateMessage( &msg );
icculus@1251
  1109
		DispatchMessage( &msg );
icculus@1251
  1110
	}
icculus@1251
  1111
}
icculus@1251
  1112
icculus@1251
  1113
icculus@1251
  1114
/* Note:  If we are terminated, this could be called in the middle of
icculus@1251
  1115
   another SDL video routine -- notably UpdateRects.
icculus@1251
  1116
*/
icculus@1251
  1117
void GAPI_VideoQuit(_THIS)
icculus@1251
  1118
{
icculus@1251
  1119
	int i, j;
icculus@1251
  1120
	/* Destroy the window and everything associated with it */
icculus@1251
  1121
	if ( SDL_Window ) 
icculus@1251
  1122
	{
icculus@1251
  1123
	    if ((g_hGapiLib != 0) && this && this->hidden && this->hidden->gxFunc.GXCloseDisplay && !this->hidden->useVga)
icculus@1251
  1124
			this->hidden->gxFunc.GXCloseDisplay(); 
icculus@1251
  1125
icculus@1251
  1126
		if (this->screen->pixels != NULL)
icculus@1251
  1127
		{
slouken@1336
  1128
			SDL_free(this->screen->pixels);
icculus@1251
  1129
			this->screen->pixels = NULL;
icculus@1251
  1130
		}
icculus@1251
  1131
		if ( screen_icn ) {
icculus@1251
  1132
			DestroyIcon(screen_icn);
icculus@1251
  1133
			screen_icn = NULL;
icculus@1251
  1134
		}
icculus@1251
  1135
icculus@1251
  1136
		DIB_DestroyWindow(this);
icculus@1251
  1137
		SDL_UnregisterApp();
icculus@1251
  1138
		FlushMessageQueue();
icculus@1251
  1139
icculus@1251
  1140
		SDL_Window = NULL;
icculus@1251
  1141
#if defined(_WIN32_WCE)
icculus@1251
  1142
icculus@1251
  1143
// Unload wince aygshell library to prevent leak
icculus@1251
  1144
		if( aygshell ) 
icculus@1251
  1145
		{
icculus@1251
  1146
			FreeLibrary(aygshell);
icculus@1251
  1147
			aygshell = NULL;
icculus@1251
  1148
		}
icculus@1251
  1149
#endif
icculus@1251
  1150
icculus@1251
  1151
	/* Free video mode lists */
icculus@1251
  1152
	for ( i=0; i<NUM_MODELISTS; ++i ) {
icculus@1251
  1153
		if ( gapi->SDL_modelist[i] != NULL ) {
icculus@1251
  1154
			for ( j=0; gapi->SDL_modelist[i][j]; ++j )
slouken@1336
  1155
				SDL_free(gapi->SDL_modelist[i][j]);
slouken@1336
  1156
			SDL_free(gapi->SDL_modelist[i]);
icculus@1251
  1157
			gapi->SDL_modelist[i] = NULL;
icculus@1251
  1158
		}
icculus@1251
  1159
	}
icculus@1251
  1160
icculus@1251
  1161
	}
icculus@1251
  1162
icculus@1251
  1163
}
icculus@1251
  1164
icculus@1251
  1165
static void GAPI_RealizePalette(_THIS)
icculus@1251
  1166
{
icculus@1251
  1167
	OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n"));
icculus@1251
  1168
}
icculus@1251
  1169
icculus@1251
  1170
static void GAPI_PaletteChanged(_THIS, HWND window)
icculus@1251
  1171
{
icculus@1251
  1172
	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
icculus@1251
  1173
}
icculus@1251
  1174
icculus@1251
  1175
/* Exported for the windows message loop only */
icculus@1251
  1176
static void GAPI_WinPAINT(_THIS, HDC hdc)
icculus@1251
  1177
{
icculus@1251
  1178
	OutputDebugString(TEXT("GAPI_WinPAINT NOT IMPLEMENTED !\r\n"));
icculus@1251
  1179
}
icculus@1251
  1180
icculus@1251
  1181
int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 
icculus@1251
  1182
{
icculus@1251
  1183
	GAPI_CreatePalette(ncolors, colors);
icculus@1251
  1184
	return 1;
slouken@1312
  1185
}