/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

/*
** RW_IMP.C
**
** This file contains ALL Win32 specific stuff having to do with the
** software refresh.  When a port is being made the following functions
** must be implemented by the port:
**
** SWimp_EndFrame
** SWimp_Init
** SWimp_SetPalette
** SWimp_Shutdown
*/

#include "win_local.h"
#include "win_swimp.h"
#ifdef _WIN32_WCE
#include <aygshell.h>
#endif

swwstate_t sww_state;

/*
** SWimp_Init
**
** This routine is responsible for initializing the implementation
** specific stuff in a software rendering subsystem.
*/
static qboolean SWimp_Init( void ) {
	Win_Init();
	return qtrue;
}

void SWimp_FatalShutdown( void ) {
	DIB_Shutdown();
#ifdef USE_DDRAW
	DDRAW_FatalShutdown();
#endif /* USE_DDRAW */
	if( sww_state.hWnd ) {
		DestroyWindow( sww_state.hWnd );
		sww_state.hWnd = NULL;
	}
}

/*
** SWimp_Shutdown
**
** System specific graphics subsystem shutdown routine.  Destroys
** DIBs or DDRAW surfaces as appropriate.
*/
static void SWimp_Shutdown( void ) {
	Com_Printf( "Shutting down SW imp...\n" );
	DIB_Shutdown();
#ifdef USE_DDRAW
	DDRAW_Shutdown();
#endif /* USE_DDRAW */

	if( sww_state.hWnd ) {
		Com_Printf( "...destroying window\n" );
		Win_DestroyWindow( sww_state.hWnd );
		sww_state.hWnd = NULL;
#ifdef _WIN32_WCE
		if( sww_state.flags & QVF_FULLSCREEN_ENABLED ) {
			SHFullScreen( sww_state.hWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | 
                  SHFS_SHOWSTARTICON );
		}
#endif
	}

	memset( &sww_state, 0, sizeof( sww_state ) );
}

static void SWimp_BeginFrame( float stereo_spearation ) {
}


/*
** SWimp_EndFrame
**
** This does an implementation specific copy from the backbuffer to the
** front buffer.  In the Win32 case it uses BitBlt or BltFast depending
** on whether we're using DIB sections/GDI or DDRAW.
*/
static void SWimp_EndFrame( byte **buffer, int *rowbytes ) {
#ifdef USE_DDRAW
	if( sww_state.flags & QVF_ACCELERATED ) {
		DDRAW_EndFrame( buffer, rowbytes );
		return;
	}
#endif /* USE_DDRAW */

	BitBlt( sww_state.hDC,
		    0, 0,
			sww_state.width,
			sww_state.height,
			sww_state.hdcDIBSection,
			0, 0,
			SRCCOPY );
}

/*
** SWimp_SetMode
*/
#include "vid_modes.h"

static vidSetModeResult_t SWimp_SetMode( int *pwidth, int *pheight, byte **buffer, int *rowbytes, const byte *palette, int mode, qboolean fullscreen ) {
	const char *win_fs[] = { "W", "FS" };
	vidSetModeResult_t retval;

	Com_Printf( "setting mode %d:", mode );

	if( !VID_GetModeInfo( pwidth, pheight, mode ) ) {
		Com_Printf( " invalid mode\n" );
		return SETMODE_ERROR;
	}

	Com_Printf( " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );

	if( sww_state.hWnd ) {
		// free resources in use
		SWimp_Shutdown();
	}

	sww_state.width = *pwidth;
	sww_state.height = *pheight;

#if (defined _WIN32_WCE)
	if( fullscreen ) {
		sww_state.hWnd = Win_CreateWindow( *pwidth, *pheight, qtrue );
		
		if( DIB_Init( buffer, rowbytes, palette ) ) {
			retval = SETMODE_FULLSCREEN;
			sww_state.flags |= QVF_FULLSCREEN_ENABLED;
			SHFullScreen( sww_state.hWnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON );

		} else {
			// failed to set a valid mode in windowed mode
			retval = SETMODE_ERROR;
		}
	} else
#elif (defined USE_DDRAW)
	if( fullscreen ) {
		// create a new window
		sww_state.hWnd = Win_CreateWindow( *pwidth, *pheight, qtrue );

		if( !DDRAW_Init( buffer, rowbytes, palette ) ) {
			Win_DestroyWindow( sww_state.hWnd );
			sww_state.hWnd = Win_CreateWindow( *pwidth, *pheight, qfalse );

			if( DIB_Init( buffer, rowbytes, palette ) ) {
				// mode is legal but not as fullscreen
				retval = SETMODE_WINDOWED;
			} else {
				// failed to set a valid mode in windowed mode
				retval = SETMODE_ERROR;
			}
		} else {
			retval = SETMODE_FULLSCREEN;
			sww_state.flags |= QVF_FULLSCREEN_ENABLED|QVF_ACCELERATED;
		}
	} else
#endif /* USE_DDRAW */
	{
		sww_state.hWnd = Win_CreateWindow( *pwidth, *pheight, qfalse );
		
		if( DIB_Init( buffer, rowbytes, palette ) ) {
			retval = SETMODE_WINDOWED;
		} else {
			// failed to set a valid mode in windowed mode
			retval = SETMODE_ERROR;
		}

	}

	if( retval == SETMODE_ERROR ) {
		Win_DestroyWindow( sww_state.hWnd );
		sww_state.hWnd = NULL;
	}

	return retval;
}

/*
** SWimp_UpdatePalette
**
** System specific palette setting routine.  A NULL palette means
** to use the existing palette.  The palette is expected to be in
** a padded 4-byte xRGB format.
*/
static void SWimp_UpdatePalette( const byte *palette ) {
#ifdef USE_DDRAW
	if( sww_state.flags & QVF_ACCELERATED ) {
		DDRAW_SetPalette( palette );
		return;
	}
#endif /* USE_DDRAW */

	DIB_SetPalette( palette );
}

static void SWimp_UpdateGamma( const byte *gammatable ) {
}

/*
============
SWimp_GetFlags
============
*/
static vidFlags_t SWimp_GetFlags( void ) {
	return sww_state.flags;
}

/*
@@@@@@@@@@@@
SWimp_FillAPI
@@@@@@@@@@@@
*/
void Video_FillSWAPI( vidSWAPI_t *api ) {
	api->Init = SWimp_Init;
	api->Shutdown = SWimp_Shutdown;
	api->UpdateGamma = SWimp_UpdateGamma;
	api->GetFlags = SWimp_GetFlags;
	api->SetMode = SWimp_SetMode;
	api->UpdatePalette = SWimp_UpdatePalette;
	api->BeginFrame = SWimp_BeginFrame;
	api->EndFrame = SWimp_EndFrame;
}

