2003-05-22 05:28:37 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
Class: RageDisplay
|
|
|
|
|
|
|
|
|
|
Desc: See header.
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
|
|
|
|
Chris Danford
|
|
|
|
|
Glenn Maynard
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "RageDisplay.h"
|
2003-05-26 19:42:04 +00:00
|
|
|
#include "RageDisplay_D3D.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "D3D8.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "RageTimer.h"
|
|
|
|
|
#include "RageException.h"
|
|
|
|
|
#include "RageTexture.h"
|
|
|
|
|
#include "RageTextureManager.h"
|
|
|
|
|
#include "RageMath.h"
|
|
|
|
|
#include "RageTypes.h"
|
2003-12-21 02:06:40 +00:00
|
|
|
#include "RageFile.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "GameConstantsAndTypes.h"
|
|
|
|
|
#include "StepMania.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "D3dx8math.h"
|
|
|
|
|
#include "SDL_video.h" // for SDL_Surface
|
|
|
|
|
#include "SDL_utils.h"
|
2003-07-11 03:15:28 +00:00
|
|
|
#include "D3DX8Core.h"
|
2003-11-13 00:39:36 +00:00
|
|
|
#include "PrefsManager.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
#include "arch/arch.h"
|
|
|
|
|
|
2003-05-24 20:04:57 +00:00
|
|
|
// Static libraries
|
|
|
|
|
// load Windows D3D8 dynamically
|
2004-01-31 01:57:33 +00:00
|
|
|
#if defined(_WINDOWS)
|
|
|
|
|
#pragma comment(lib, "D3dx8.lib")
|
|
|
|
|
//#pragma comment(lib, "Dxerr8.lib")
|
|
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
#include <math.h>
|
2003-05-24 02:03:17 +00:00
|
|
|
#include <list>
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
|
2003-07-11 03:15:28 +00:00
|
|
|
CString GetErrorString( HRESULT hr )
|
|
|
|
|
{
|
|
|
|
|
char szError[1024] = "";
|
|
|
|
|
D3DXGetErrorString( hr, szError, sizeof(szError) );
|
|
|
|
|
return szError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
//
|
|
|
|
|
// Globals
|
|
|
|
|
//
|
2003-05-22 23:05:32 +00:00
|
|
|
#if !defined(_XBOX)
|
2003-05-22 22:55:58 +00:00
|
|
|
HMODULE g_D3D8_Module = NULL;
|
2003-05-22 23:05:32 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
LPDIRECT3D8 g_pd3d = NULL;
|
|
|
|
|
LPDIRECT3DDEVICE8 g_pd3dDevice = NULL;
|
|
|
|
|
D3DCAPS8 g_DeviceCaps;
|
|
|
|
|
D3DDISPLAYMODE g_DesktopMode;
|
|
|
|
|
D3DPRESENT_PARAMETERS g_d3dpp;
|
|
|
|
|
int g_ModelMatrixCnt=0;
|
2003-06-05 19:29:27 +00:00
|
|
|
RageDisplay::VideoModeParams g_CurrentParams;
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
/* Direct3D doesn't associate a palette with textures.
|
|
|
|
|
* Instead, we load a palette into a slot. We need to keep track
|
|
|
|
|
* of which texture's palette is stored in what slot. */
|
|
|
|
|
map<unsigned,int> g_TexResourceToPaletteIndex;
|
2003-05-24 02:03:17 +00:00
|
|
|
list<int> g_PaletteIndex;
|
2003-05-24 01:12:30 +00:00
|
|
|
struct TexturePalette { PALETTEENTRY p[256]; };
|
|
|
|
|
map<unsigned,TexturePalette> g_TexResourceToTexturePalette;
|
|
|
|
|
|
2003-05-24 02:03:17 +00:00
|
|
|
/* Load the palette, if any, for the given texture into a palette slot, and make
|
|
|
|
|
* it current. */
|
|
|
|
|
static void SetPalette( unsigned TexResource )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-05-24 02:03:17 +00:00
|
|
|
/* If the texture isn't paletted, we have nothing to do. */
|
|
|
|
|
if( g_TexResourceToTexturePalette.find(TexResource) == g_TexResourceToTexturePalette.end() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Is the palette already loaded? */
|
|
|
|
|
if( g_TexResourceToPaletteIndex.find(TexResource) == g_TexResourceToPaletteIndex.end() )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-05-24 02:03:17 +00:00
|
|
|
/* It's not. Grab the least recently used slot. */
|
|
|
|
|
int iPalIndex = g_PaletteIndex.front();
|
|
|
|
|
|
|
|
|
|
/* If any other texture is currently using this slot, mark that palette unloaded. */
|
|
|
|
|
for( map<unsigned,int>::iterator i = g_TexResourceToPaletteIndex.begin(); i != g_TexResourceToPaletteIndex.end(); ++i )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-05-24 02:03:17 +00:00
|
|
|
if( i->second != iPalIndex )
|
|
|
|
|
continue;
|
|
|
|
|
g_TexResourceToPaletteIndex.erase(i);
|
|
|
|
|
break;
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
2003-05-24 02:03:17 +00:00
|
|
|
|
|
|
|
|
/* Load it. */
|
|
|
|
|
#ifndef _XBOX
|
2003-06-21 16:21:31 +00:00
|
|
|
TexturePalette& pal = g_TexResourceToTexturePalette[TexResource];
|
|
|
|
|
g_pd3dDevice->SetPaletteEntries( iPalIndex, pal.p );
|
2003-05-24 02:03:17 +00:00
|
|
|
#else
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
g_TexResourceToPaletteIndex[TexResource] = iPalIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int iPalIndex = g_TexResourceToPaletteIndex[TexResource];
|
|
|
|
|
|
|
|
|
|
/* Find this palette index in the least-recently-used queue and move it to the end. */
|
|
|
|
|
for(list<int>::iterator i = g_PaletteIndex.begin(); i != g_PaletteIndex.end(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if( *i != iPalIndex )
|
|
|
|
|
continue;
|
|
|
|
|
g_PaletteIndex.erase(i);
|
|
|
|
|
g_PaletteIndex.push_back(iPalIndex);
|
|
|
|
|
break;
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
2003-05-24 02:03:17 +00:00
|
|
|
|
|
|
|
|
#ifndef _XBOX
|
|
|
|
|
g_pd3dDevice->SetCurrentTexturePalette( iPalIndex );
|
|
|
|
|
#else
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
#define D3DFVF_RageSpriteVertex (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
|
|
|
|
#define D3DFVF_RageModelVertex (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
|
2003-10-03 21:38:38 +00:00
|
|
|
static const RageDisplay::PixelFormatDesc PIXEL_FORMAT_DESC[RageDisplay::NUM_PIX_FORMATS] = {
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
/* A8B8G8R8 */
|
|
|
|
|
32,
|
|
|
|
|
{ 0x00FF0000,
|
|
|
|
|
0x0000FF00,
|
|
|
|
|
0x000000FF,
|
|
|
|
|
0xFF000000 }
|
|
|
|
|
}, {
|
|
|
|
|
/* A4R4G4B4 */
|
|
|
|
|
16,
|
|
|
|
|
{ 0x0F00,
|
|
|
|
|
0x00F0,
|
|
|
|
|
0x000F,
|
|
|
|
|
0xF000 },
|
|
|
|
|
}, {
|
|
|
|
|
/* A1B5G5R5 */
|
|
|
|
|
16,
|
|
|
|
|
{ 0x7C00,
|
|
|
|
|
0x03E0,
|
|
|
|
|
0x001F,
|
|
|
|
|
0x8000 },
|
|
|
|
|
}, {
|
|
|
|
|
/* X1R5G5R5 */
|
|
|
|
|
16,
|
|
|
|
|
{ 0x7C00,
|
|
|
|
|
0x03E0,
|
|
|
|
|
0x001F,
|
|
|
|
|
0x0000 },
|
|
|
|
|
}, {
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _XBOX
|
|
|
|
|
/* A8B8G8R8 */
|
|
|
|
|
32,
|
|
|
|
|
{ 0x00FF0000,
|
|
|
|
|
0x0000FF00,
|
|
|
|
|
0x000000FF,
|
|
|
|
|
0xFF000000 }
|
|
|
|
|
#else
|
2003-05-22 05:28:37 +00:00
|
|
|
/* B8G8R8 */
|
|
|
|
|
24,
|
|
|
|
|
{ 0xFF0000,
|
|
|
|
|
0x00FF00,
|
|
|
|
|
0x0000FF,
|
|
|
|
|
0x000000 }
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
}, {
|
|
|
|
|
/* Paletted */
|
|
|
|
|
8,
|
|
|
|
|
{ 0,0,0,0 } /* N/A */
|
2003-06-30 03:13:53 +00:00
|
|
|
}, {
|
|
|
|
|
/* BGR (N/A; OpenGL only) */
|
|
|
|
|
0, { 0,0,0,0 }
|
|
|
|
|
}, {
|
|
|
|
|
/* ABGR (N/A; OpenGL only) */
|
|
|
|
|
0, { 0,0,0,0 }
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2003-10-03 21:38:38 +00:00
|
|
|
static D3DFORMAT D3DFORMATS[RageDisplay::NUM_PIX_FORMATS] =
|
2003-05-29 00:16:29 +00:00
|
|
|
{
|
|
|
|
|
D3DFMT_A8R8G8B8,
|
|
|
|
|
D3DFMT_A4R4G4B4,
|
|
|
|
|
D3DFMT_A1R5G5B5,
|
|
|
|
|
D3DFMT_X1R5G5B5,
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _XBOX
|
2003-05-29 00:16:29 +00:00
|
|
|
D3DFMT_A8R8G8B8,
|
2003-07-22 07:47:27 +00:00
|
|
|
#else
|
|
|
|
|
D3DFMT_R8G8B8,
|
2003-05-29 00:16:29 +00:00
|
|
|
#endif
|
2003-06-30 03:13:53 +00:00
|
|
|
D3DFMT_P8,
|
2003-06-29 08:13:18 +00:00
|
|
|
D3DFMT_UNKNOWN, /* no BGR */
|
2003-06-30 03:13:53 +00:00
|
|
|
D3DFMT_UNKNOWN /* no ABGR */
|
2003-05-29 00:16:29 +00:00
|
|
|
};
|
|
|
|
|
|
2003-10-03 21:38:38 +00:00
|
|
|
const RageDisplay::PixelFormatDesc *RageDisplay_D3D::GetPixelFormatDesc(PixelFormat pf) const
|
2003-05-26 03:12:12 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( pf < NUM_PIX_FORMATS );
|
|
|
|
|
return &PIXEL_FORMAT_DESC[pf];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
RageDisplay_D3D::RageDisplay_D3D( VideoModeParams p )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-06-27 08:33:15 +00:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "RageDisplay_D3D::RageDisplay_D3D()" );
|
|
|
|
|
LOG->MapLog("renderer", "Current renderer: Direct3D");
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-06-27 08:33:15 +00:00
|
|
|
typedef IDirect3D8 * (WINAPI * Direct3DCreate8_t) (UINT SDKVersion);
|
|
|
|
|
Direct3DCreate8_t pDirect3DCreate8;
|
2003-05-22 23:05:32 +00:00
|
|
|
#if defined(_XBOX)
|
2003-06-27 08:33:15 +00:00
|
|
|
pDirect3DCreate8 = Direct3DCreate8;
|
2003-05-22 23:05:32 +00:00
|
|
|
#else
|
2003-06-27 08:33:15 +00:00
|
|
|
g_D3D8_Module = LoadLibrary("D3D8.dll");
|
|
|
|
|
if(!g_D3D8_Module)
|
|
|
|
|
throw RageException_D3DNotInstalled();
|
2003-05-22 22:55:58 +00:00
|
|
|
|
2003-06-27 08:33:15 +00:00
|
|
|
pDirect3DCreate8 = (Direct3DCreate8_t) GetProcAddress(g_D3D8_Module, "Direct3DCreate8");
|
2003-11-01 06:50:12 +00:00
|
|
|
if(!pDirect3DCreate8)
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Direct3DCreate8 not found" );
|
|
|
|
|
throw RageException_D3DNotInstalled();
|
|
|
|
|
}
|
2003-05-22 23:05:32 +00:00
|
|
|
#endif
|
2003-05-22 22:55:58 +00:00
|
|
|
|
2003-06-27 08:33:15 +00:00
|
|
|
g_pd3d = pDirect3DCreate8( D3D_SDK_VERSION );
|
2003-11-01 06:50:12 +00:00
|
|
|
if(!g_pd3d)
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Direct3DCreate8 failed" );
|
|
|
|
|
throw RageException_D3DNotInstalled();
|
|
|
|
|
}
|
2003-06-27 08:33:15 +00:00
|
|
|
|
|
|
|
|
if( FAILED( g_pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &g_DeviceCaps) ) )
|
|
|
|
|
throw RageException_D3DNoAcceleration();
|
|
|
|
|
|
|
|
|
|
D3DADAPTER_IDENTIFIER8 identifier;
|
|
|
|
|
g_pd3d->GetAdapterIdentifier( D3DADAPTER_DEFAULT, 0, &identifier );
|
|
|
|
|
|
|
|
|
|
LOG->Trace(
|
|
|
|
|
"Driver: %s\n"
|
|
|
|
|
"Description: %s\n"
|
2003-10-11 01:51:36 +00:00
|
|
|
"Max texture size: %d\n"
|
|
|
|
|
"Alpha in palette: %s\n",
|
2003-06-27 08:33:15 +00:00
|
|
|
identifier.Driver,
|
|
|
|
|
identifier.Description,
|
2003-10-11 01:51:36 +00:00
|
|
|
g_DeviceCaps.MaxTextureWidth,
|
|
|
|
|
(g_DeviceCaps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE) ? "yes" : "no" );
|
2003-06-27 08:33:15 +00:00
|
|
|
|
|
|
|
|
LOG->Trace( "This display adaptor supports the following modes:" );
|
|
|
|
|
D3DDISPLAYMODE mode;
|
|
|
|
|
for( UINT u=0; u<g_pd3d->GetAdapterModeCount(D3DADAPTER_DEFAULT); u++ )
|
|
|
|
|
if( SUCCEEDED( g_pd3d->EnumAdapterModes( D3DADAPTER_DEFAULT, u, &mode ) ) )
|
|
|
|
|
LOG->Trace( " %ux%u %uHz, format %d", mode.Width, mode.Height, mode.RefreshRate, mode.Format );
|
|
|
|
|
|
|
|
|
|
/* Up until now, all we've done is set up g_pd3d and do some queries. Now,
|
|
|
|
|
* actually initialize the window. Do this after as many error conditions
|
|
|
|
|
* as possible, because if we have to shut it down again we'll flash a window
|
|
|
|
|
* briefly. */
|
2003-07-22 07:47:27 +00:00
|
|
|
//#if defined _WINDOWS
|
2003-06-27 08:33:15 +00:00
|
|
|
if(!SDL_WasInit(SDL_INIT_VIDEO))
|
|
|
|
|
{
|
|
|
|
|
if( SDL_InitSubSystem(SDL_INIT_VIDEO) == -1 )
|
|
|
|
|
RageException::Throw( "SDL_INIT_VIDEO failed: %s", SDL_GetError() );
|
|
|
|
|
}
|
2003-05-26 23:33:37 +00:00
|
|
|
|
2003-06-27 08:33:15 +00:00
|
|
|
/* By default, ignore all SDL events. We'll enable them as we need them.
|
|
|
|
|
* We must not enable any events we don't actually want, since we won't
|
|
|
|
|
* query for them and they'll fill up the event queue.
|
|
|
|
|
*
|
|
|
|
|
* This needs to be done after we initialize video, since it's really part
|
|
|
|
|
* of the SDL video system--it'll be reinitialized on us if we do this first. */
|
|
|
|
|
SDL_EventState(0xFF /*SDL_ALLEVENTS*/, SDL_IGNORE);
|
|
|
|
|
SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
|
2003-07-22 07:47:27 +00:00
|
|
|
//#endif
|
2003-06-27 08:33:15 +00:00
|
|
|
|
|
|
|
|
g_PaletteIndex.clear();
|
|
|
|
|
for( int i = 0; i < 256; ++i )
|
|
|
|
|
g_PaletteIndex.push_back(i);
|
|
|
|
|
|
|
|
|
|
// Save the original desktop format.
|
|
|
|
|
g_pd3d->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_DesktopMode );
|
|
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-06-27 08:33:15 +00:00
|
|
|
// Create the SDL window
|
|
|
|
|
int flags = SDL_RESIZABLE | SDL_SWSURFACE;
|
|
|
|
|
SDL_Surface *screen = SDL_SetVideoMode(p.width, p.height, p.bpp, flags);
|
|
|
|
|
if(!screen)
|
|
|
|
|
RageException::Throw("SDL_SetVideoMode failed: %s", SDL_GetError());
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-06-27 08:33:15 +00:00
|
|
|
|
|
|
|
|
SetVideoMode( p );
|
|
|
|
|
} catch(...) {
|
|
|
|
|
// Clean up; ~RageDisplay will not be called.
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-06-27 08:33:15 +00:00
|
|
|
if( SDL_WasInit(SDL_INIT_VIDEO) )
|
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-06-27 08:33:15 +00:00
|
|
|
|
|
|
|
|
if( g_pd3d )
|
|
|
|
|
{
|
|
|
|
|
g_pd3d->Release();
|
|
|
|
|
g_pd3d = NULL;
|
|
|
|
|
}
|
2003-06-25 21:03:41 +00:00
|
|
|
|
2003-07-11 03:15:28 +00:00
|
|
|
#if !defined(_XBOX)
|
2003-06-27 08:33:15 +00:00
|
|
|
if( g_D3D8_Module )
|
|
|
|
|
{
|
|
|
|
|
FreeLibrary( g_D3D8_Module );
|
|
|
|
|
g_D3D8_Module = NULL;
|
|
|
|
|
}
|
2003-07-11 03:15:28 +00:00
|
|
|
#endif
|
2003-06-27 08:33:15 +00:00
|
|
|
throw;
|
2003-06-25 21:03:41 +00:00
|
|
|
}
|
2003-06-27 08:33:15 +00:00
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::Update(float fDeltaTime)
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-22 05:28:37 +00:00
|
|
|
SDL_Event event;
|
|
|
|
|
while(SDL_GetEvent(event, SDL_VIDEORESIZEMASK))
|
|
|
|
|
{
|
|
|
|
|
switch(event.type)
|
|
|
|
|
{
|
|
|
|
|
case SDL_VIDEORESIZE:
|
2003-06-05 19:29:27 +00:00
|
|
|
g_CurrentParams.width = event.resize.w;
|
|
|
|
|
g_CurrentParams.height = event.resize.h;
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
/* Let DISPLAY know that our resolution has changed. */
|
|
|
|
|
ResolutionChanged();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
bool RageDisplay_D3D::IsSoftwareRenderer()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
RageDisplay_D3D::~RageDisplay_D3D()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-05-26 19:42:04 +00:00
|
|
|
LOG->Trace( "RageDisplay_D3D::~RageDisplay()" );
|
2003-05-24 20:04:57 +00:00
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-22 05:28:37 +00:00
|
|
|
SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
|
2003-05-24 20:04:57 +00:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
g_pd3dDevice->Release();
|
|
|
|
|
g_pd3d->Release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3DFORMAT FindBackBufferType(bool bWindowed, int iBPP)
|
|
|
|
|
{
|
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
|
|
// If windowed, then bpp is ignored. Use whatever works.
|
|
|
|
|
vector<D3DFORMAT> vBackBufferFormats; // throw all possibilities in here
|
|
|
|
|
|
|
|
|
|
/* When windowed, add all formats; otherwise add only formats that match dwBPP. */
|
|
|
|
|
if( iBPP == 16 || bWindowed )
|
|
|
|
|
{
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_R5G6B5 );
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_X1R5G5B5 );
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_A1R5G5B5 );
|
|
|
|
|
}
|
|
|
|
|
if( iBPP == 32 || bWindowed )
|
|
|
|
|
{
|
|
|
|
|
#ifndef _XBOX
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_R8G8B8 );
|
|
|
|
|
#endif
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_X8R8G8B8 );
|
|
|
|
|
vBackBufferFormats.push_back( D3DFMT_A8R8G8B8 );
|
|
|
|
|
}
|
|
|
|
|
if( !bWindowed && iBPP != 16 && iBPP != 32 )
|
2003-05-24 20:04:57 +00:00
|
|
|
{
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-24 20:04:57 +00:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO); // exit out of full screen. The ~RageDisplay will not be called!
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
throw RageException( ssprintf("Invalid BPP '%u' specified", iBPP) );
|
2003-05-24 20:04:57 +00:00
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
// Test each back buffer format until we find something that works.
|
|
|
|
|
for( unsigned i=0; i < vBackBufferFormats.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
D3DFORMAT fmtBackBuffer = vBackBufferFormats[i];
|
|
|
|
|
|
|
|
|
|
D3DFORMAT fmtDisplay;
|
|
|
|
|
if( bWindowed )
|
|
|
|
|
fmtDisplay = g_DesktopMode.Format;
|
|
|
|
|
else // Fullscreen
|
|
|
|
|
fmtDisplay = vBackBufferFormats[i];
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "Testing format: display %d, back buffer %d, windowed %d...",
|
|
|
|
|
fmtDisplay, fmtBackBuffer, bWindowed );
|
|
|
|
|
|
|
|
|
|
hr = g_pd3d->CheckDeviceType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
|
|
|
|
fmtDisplay, fmtBackBuffer, bWindowed );
|
|
|
|
|
|
|
|
|
|
if( FAILED(hr) )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
// done searching
|
|
|
|
|
LOG->Trace( "This will work." );
|
|
|
|
|
return fmtBackBuffer;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-28 00:50:10 +00:00
|
|
|
LOG->Trace( "Couldn't find an appropriate back buffer format." );
|
|
|
|
|
return (D3DFORMAT)-1;
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-22 05:28:37 +00:00
|
|
|
HWND GetHwnd()
|
|
|
|
|
{
|
|
|
|
|
SDL_SysWMinfo info;
|
|
|
|
|
SDL_VERSION(&info.version);
|
|
|
|
|
if( SDL_GetWMInfo(&info) < 0 )
|
2003-05-24 20:04:57 +00:00
|
|
|
{
|
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO); // exit out of full screen. The ~RageDisplay will not be called!
|
2003-05-22 05:28:37 +00:00
|
|
|
RageException::Throw( "SDL_GetWMInfo failed" );
|
2003-05-24 20:04:57 +00:00
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
return info.window;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-05-24 20:04:57 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
/* Set the video mode. */
|
2003-08-27 23:36:09 +00:00
|
|
|
CString RageDisplay_D3D::TryVideoMode( VideoModeParams p, bool &bNewDeviceOut )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-06-05 19:29:27 +00:00
|
|
|
g_CurrentParams = p;
|
|
|
|
|
|
2003-05-30 00:30:40 +00:00
|
|
|
HRESULT hr;
|
|
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
if( FindBackBufferType( p.windowed, p.bpp ) == -1 ) // no possible back buffer formats
|
2003-08-27 23:36:09 +00:00
|
|
|
return ssprintf( "FindBackBufferType(%i,%i) failed", p.windowed, p.bpp ); // failed to set mode
|
2003-05-28 00:50:10 +00:00
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-25 20:19:01 +00:00
|
|
|
/* Set SDL window title and icon -before- creating the window */
|
2003-06-05 19:29:27 +00:00
|
|
|
SDL_WM_SetCaption( p.sWindowTitle, "" );
|
|
|
|
|
mySDL_WM_SetIcon( p.sIconFile );
|
2003-05-30 00:30:40 +00:00
|
|
|
|
2003-05-25 20:19:01 +00:00
|
|
|
|
2003-05-24 20:04:57 +00:00
|
|
|
// HACK: On Windows 98, we can't call SDL_SetVideoMode while D3D is full screen.
|
|
|
|
|
// It will result in "SDL_SetVideoMode failed: DirectDraw2::CreateSurface(PRIMARY):
|
2003-05-24 20:59:27 +00:00
|
|
|
// Not in exclusive access mode". So, we'll Reset the D3D device, then resize the
|
|
|
|
|
// SDL window only if we're not fullscreen.
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
SDL_ShowCursor( p.windowed );
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-08-03 06:41:52 +00:00
|
|
|
|
2003-08-06 07:08:02 +00:00
|
|
|
#ifdef _XBOX
|
|
|
|
|
p.windowed = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-08-03 06:41:52 +00:00
|
|
|
ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) );
|
|
|
|
|
|
2003-08-04 10:18:06 +00:00
|
|
|
g_d3dpp.BackBufferWidth = p.width;
|
|
|
|
|
g_d3dpp.BackBufferHeight = p.height;
|
|
|
|
|
g_d3dpp.BackBufferFormat = FindBackBufferType( p.windowed, p.bpp );
|
|
|
|
|
g_d3dpp.BackBufferCount = 1;
|
|
|
|
|
g_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
|
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
|
|
|
g_d3dpp.hDeviceWindow = NULL;
|
|
|
|
|
g_d3dpp.Windowed = p.windowed;
|
|
|
|
|
g_d3dpp.EnableAutoDepthStencil = TRUE;
|
|
|
|
|
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
|
|
|
|
|
|
2003-08-03 06:41:52 +00:00
|
|
|
if(p.windowed)
|
|
|
|
|
g_d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
|
|
|
|
else
|
|
|
|
|
g_d3dpp.FullScreen_PresentationInterval = p.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
|
|
2003-08-06 07:08:02 +00:00
|
|
|
#ifndef _XBOX
|
|
|
|
|
g_d3dpp.Flags = 0;
|
|
|
|
|
g_d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
2003-08-03 06:41:52 +00:00
|
|
|
#else
|
2003-11-13 00:39:36 +00:00
|
|
|
if(XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I)
|
|
|
|
|
{
|
|
|
|
|
//get supported video flags
|
|
|
|
|
DWORD videoFlags = XGetVideoFlags();
|
|
|
|
|
|
|
|
|
|
//set pal60 if available.
|
|
|
|
|
if(videoFlags & XC_VIDEO_FLAGS_PAL_60Hz)
|
2003-12-30 07:24:03 +00:00
|
|
|
g_d3dpp.FullScreen_RefreshRateInHz = 60;
|
2003-11-13 00:39:36 +00:00
|
|
|
else
|
2003-12-30 07:24:03 +00:00
|
|
|
g_d3dpp.FullScreen_RefreshRateInHz = 50;
|
2003-11-13 00:39:36 +00:00
|
|
|
}
|
|
|
|
|
else
|
2003-12-30 07:24:03 +00:00
|
|
|
g_d3dpp.FullScreen_RefreshRateInHz = 60;
|
2003-11-13 00:39:36 +00:00
|
|
|
|
2003-12-30 07:24:03 +00:00
|
|
|
g_d3dpp.Flags = 0;
|
2003-08-03 06:41:52 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-05-24 20:04:57 +00:00
|
|
|
LOG->Trace( "Present Parameters: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
|
|
|
|
|
g_d3dpp.BackBufferWidth, g_d3dpp.BackBufferHeight, g_d3dpp.BackBufferFormat,
|
|
|
|
|
g_d3dpp.BackBufferCount,
|
|
|
|
|
g_d3dpp.MultiSampleType, g_d3dpp.SwapEffect, g_d3dpp.hDeviceWindow,
|
|
|
|
|
g_d3dpp.Windowed, g_d3dpp.EnableAutoDepthStencil, g_d3dpp.AutoDepthStencilFormat,
|
|
|
|
|
g_d3dpp.Flags, g_d3dpp.FullScreen_RefreshRateInHz,
|
|
|
|
|
g_d3dpp.FullScreen_PresentationInterval
|
|
|
|
|
);
|
|
|
|
|
|
2003-11-13 00:39:36 +00:00
|
|
|
#ifdef _XBOX
|
|
|
|
|
if ( D3D__pDevice )
|
2003-12-30 07:24:03 +00:00
|
|
|
g_pd3dDevice = D3D__pDevice;
|
2003-11-13 00:39:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
if( g_pd3dDevice == NULL ) // device is not yet created. We need to create it
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-06-05 19:29:27 +00:00
|
|
|
bNewDeviceOut = true;
|
2003-05-24 20:04:57 +00:00
|
|
|
hr = g_pd3d->CreateDevice(
|
2003-05-22 05:28:37 +00:00
|
|
|
D3DADAPTER_DEFAULT,
|
|
|
|
|
D3DDEVTYPE_HAL,
|
|
|
|
|
#ifndef _XBOX
|
|
|
|
|
GetHwnd(),
|
|
|
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
|
|
|
|
|
#else
|
|
|
|
|
NULL,
|
2003-08-04 10:18:06 +00:00
|
|
|
D3DCREATE_HARDWARE_VERTEXPROCESSING,
|
2003-05-22 05:28:37 +00:00
|
|
|
#endif
|
|
|
|
|
&g_d3dpp,
|
|
|
|
|
&g_pd3dDevice );
|
2003-05-24 20:04:57 +00:00
|
|
|
if( FAILED(hr) )
|
|
|
|
|
{
|
2003-10-08 07:12:48 +00:00
|
|
|
// Likely D3D_ERR_INVALIDCALL. The driver probably doesn't support this video mode.
|
|
|
|
|
return ssprintf( "CreateDevice failed: '%s'", GetErrorString(hr).c_str() );
|
2003-05-24 20:04:57 +00:00
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2003-06-05 19:29:27 +00:00
|
|
|
bNewDeviceOut = false;
|
2003-05-30 00:30:40 +00:00
|
|
|
hr = g_pd3dDevice->Reset( &g_d3dpp );
|
|
|
|
|
if( FAILED(hr) )
|
|
|
|
|
{
|
2003-10-08 07:12:48 +00:00
|
|
|
// Likely D3D_ERR_INVALIDCALL. The driver probably doesn't support this video mode.
|
|
|
|
|
return ssprintf("g_pd3dDevice->Reset failed: '%s'", GetErrorString(hr).c_str() );
|
2003-05-30 00:30:40 +00:00
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
if( p.windowed )
|
2003-05-24 20:59:27 +00:00
|
|
|
{
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _WINDOWS
|
2003-05-24 20:59:27 +00:00
|
|
|
int flags = SDL_RESIZABLE | SDL_SWSURFACE;
|
|
|
|
|
|
|
|
|
|
// Don't use SDL to change the video mode. This will cause a
|
|
|
|
|
// D3DERR_DRIVERINTERNALERROR on TNTs, V3s, and probably more.
|
|
|
|
|
// if( !windowed )
|
|
|
|
|
// flags |= SDL_FULLSCREEN;
|
|
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
SDL_ShowCursor( p.windowed );
|
2003-05-24 20:59:27 +00:00
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
SDL_Surface *screen = SDL_SetVideoMode(p.width, p.height, p.bpp, flags);
|
2003-05-24 20:59:27 +00:00
|
|
|
if(!screen)
|
|
|
|
|
{
|
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO); // exit out of full screen. The ~RageDisplay will not be called!
|
|
|
|
|
RageException::Throw("SDL_SetVideoMode failed: %s", SDL_GetError());
|
|
|
|
|
}
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2003-05-24 20:59:27 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
ResolutionChanged();
|
|
|
|
|
|
|
|
|
|
this->SetDefaultRenderStates();
|
|
|
|
|
|
2003-05-24 02:09:17 +00:00
|
|
|
/* Palettes were lost by Reset(), so mark them unloaded. */
|
|
|
|
|
g_TexResourceToPaletteIndex.clear();
|
|
|
|
|
|
2003-08-27 23:36:09 +00:00
|
|
|
return ""; // mode change successful
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::ResolutionChanged()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-11-13 00:39:36 +00:00
|
|
|
#ifdef _XBOX
|
2004-01-31 02:17:47 +00:00
|
|
|
g_CurrentParams.width = (int)PREFSMAN->m_fScreenWidth;
|
|
|
|
|
g_CurrentParams.height = (int)PREFSMAN->m_fScreenHeight;
|
2003-11-13 00:39:36 +00:00
|
|
|
D3DVIEWPORT8 viewData2 = { 0,0,640,480, 0.f, 1.f };
|
|
|
|
|
g_pd3dDevice->SetViewport( &viewData2 );
|
|
|
|
|
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
|
|
|
|
|
D3DCOLOR_XRGB(0,0,0), 1.0f, 0x00000000 );
|
2004-01-31 02:17:47 +00:00
|
|
|
D3DVIEWPORT8 viewData = { (DWORD)PREFSMAN->m_fScreenPosX, (DWORD)PREFSMAN->m_fScreenPosY, g_CurrentParams.width, g_CurrentParams.height, 0.f, 1.f };
|
2003-11-13 00:39:36 +00:00
|
|
|
g_pd3dDevice->SetViewport( &viewData );
|
|
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
// no need to clear because D3D uses an overlay
|
|
|
|
|
// SetViewport(0,0);
|
|
|
|
|
//
|
|
|
|
|
// /* Clear any junk that's in the framebuffer. */
|
|
|
|
|
// Clear();
|
|
|
|
|
// Flip();
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetViewport(int shift_left, int shift_down)
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
/* left and down are on a 0..SCREEN_WIDTH, 0..SCREEN_HEIGHT scale.
|
|
|
|
|
* Scale them to the actual viewport range. */
|
2003-06-05 19:29:27 +00:00
|
|
|
shift_left = int( shift_left * float(g_CurrentParams.width) / SCREEN_WIDTH );
|
|
|
|
|
shift_down = int( shift_down * float(g_CurrentParams.height) / SCREEN_HEIGHT );
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
D3DVIEWPORT8 viewData = { shift_left, -shift_down, g_CurrentParams.width, g_CurrentParams.height, 0.f, 1.f };
|
2003-05-22 05:28:37 +00:00
|
|
|
g_pd3dDevice->SetViewport( &viewData );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
int RageDisplay_D3D::GetMaxTextureSize() const
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
return g_DeviceCaps.MaxTextureWidth;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::BeginFrame()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-07-11 03:15:28 +00:00
|
|
|
#ifndef _XBOX
|
2003-05-24 05:44:31 +00:00
|
|
|
if( g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET )
|
2003-06-05 19:29:27 +00:00
|
|
|
SetVideoMode( g_CurrentParams );
|
2003-07-11 03:15:28 +00:00
|
|
|
#endif
|
2003-05-24 05:44:31 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
|
|
|
|
|
D3DCOLOR_XRGB(0,0,0), 1.0f, 0x00000000 );
|
2003-05-24 05:44:31 +00:00
|
|
|
g_pd3dDevice->BeginScene();
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::EndFrame()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->EndScene();
|
|
|
|
|
g_pd3dDevice->Present( 0, 0, 0, 0 );
|
|
|
|
|
ProcessStatsOnFlip();
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-29 17:56:09 +00:00
|
|
|
bool RageDisplay_D3D::SupportsTextureFormat( PixelFormat pixfmt, bool realtime )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-07-22 07:47:27 +00:00
|
|
|
#if defined _XBOX
|
|
|
|
|
// Lazy... Xbox handles paletted textures completely differently
|
|
|
|
|
// than D3D and I don't want to add a bunch of code for it. Also,
|
|
|
|
|
// paletted textures result in worse cache efficiency (see "Xbox
|
|
|
|
|
// Palettized Texture Performance" in XDK). So, we'll force 32bit
|
|
|
|
|
// ARGB textures. -Chris
|
|
|
|
|
return pixfmt == FMT_RGBA8;
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-06-21 16:21:31 +00:00
|
|
|
// Some cards (Savage) don't support alpha in palettes.
|
|
|
|
|
// Don't allow paletted textures if this is the case.
|
|
|
|
|
if( pixfmt == FMT_PAL && !(g_DeviceCaps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE) )
|
|
|
|
|
return false;
|
|
|
|
|
|
2003-06-29 08:13:18 +00:00
|
|
|
if( D3DFORMATS[pixfmt] == D3DFMT_UNKNOWN )
|
|
|
|
|
return false;
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
D3DFORMAT d3dfmt = D3DFORMATS[pixfmt];
|
|
|
|
|
HRESULT hr = g_pd3d->CheckDeviceFormat(
|
|
|
|
|
D3DADAPTER_DEFAULT,
|
|
|
|
|
D3DDEVTYPE_HAL,
|
|
|
|
|
g_d3dpp.BackBufferFormat,
|
|
|
|
|
0,
|
|
|
|
|
D3DRTYPE_TEXTURE,
|
|
|
|
|
d3dfmt);
|
2003-09-03 03:55:39 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
return SUCCEEDED( hr );
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-12 06:49:13 +00:00
|
|
|
SDL_Surface* RageDisplay_D3D::CreateScreenshot()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
#ifndef _XBOX
|
2003-12-13 05:21:46 +00:00
|
|
|
/* Get the back buffer. */
|
2003-05-22 05:28:37 +00:00
|
|
|
IDirect3DSurface8* pSurface;
|
|
|
|
|
g_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pSurface );
|
2003-12-13 05:21:46 +00:00
|
|
|
|
|
|
|
|
/* Get the back buffer description. */
|
|
|
|
|
D3DSURFACE_DESC desc;
|
|
|
|
|
pSurface->GetDesc( &desc );
|
|
|
|
|
|
|
|
|
|
/* Copy the back buffer into a surface of a type we support. */
|
|
|
|
|
IDirect3DSurface8* pCopy;
|
|
|
|
|
g_pd3dDevice->CreateImageSurface( desc.Width, desc.Height, D3DFMT_A8R8G8B8, &pCopy );
|
|
|
|
|
|
|
|
|
|
D3DXLoadSurfaceFromSurface( pCopy, NULL, NULL, pSurface, NULL, NULL, D3DX_DEFAULT, 0 );
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
pSurface->Release();
|
2003-12-13 05:21:46 +00:00
|
|
|
|
|
|
|
|
/* Update desc from the copy. */
|
|
|
|
|
pCopy->GetDesc( &desc );
|
|
|
|
|
|
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
RECT rect;
|
|
|
|
|
rect.left = 0;
|
|
|
|
|
rect.top = 0;
|
|
|
|
|
rect.right = desc.Width;
|
|
|
|
|
rect.bottom = desc.Height;
|
|
|
|
|
pCopy->LockRect( &lr, &rect, D3DLOCK_READONLY );
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-12 06:49:13 +00:00
|
|
|
SDL_Surface *surface = CreateSurfaceFromPixfmt( FMT_RGBA8, lr.pBits, desc.Width, desc.Height, lr.Pitch);
|
|
|
|
|
ASSERT( surface );
|
2003-12-13 05:21:46 +00:00
|
|
|
|
|
|
|
|
pCopy->UnlockRect();
|
|
|
|
|
pCopy->Release();
|
2004-02-12 06:49:13 +00:00
|
|
|
|
|
|
|
|
return surface;
|
2003-05-22 05:28:37 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-05 19:29:27 +00:00
|
|
|
RageDisplay::VideoModeParams RageDisplay_D3D::GetVideoModeParams() const { return g_CurrentParams; }
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
#define SEND_CURRENT_MATRICES \
|
2003-09-21 02:36:28 +00:00
|
|
|
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)GetProjectionTop() ); \
|
|
|
|
|
g_pd3dDevice->SetTransform( D3DTS_VIEW, (D3DMATRIX*)GetViewTop() ); \
|
2003-05-22 05:28:37 +00:00
|
|
|
RageMatrix m; \
|
|
|
|
|
/* Convert to OpenGL-style "pixel-centered" coords */ \
|
|
|
|
|
RageMatrixTranslation( &m, -0.5f, -0.5f, 0 ); \
|
2003-09-21 02:36:28 +00:00
|
|
|
RageMatrixMultiply( &m, &m, GetWorldTop() ); \
|
2003-05-22 05:28:37 +00:00
|
|
|
g_pd3dDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)&m );
|
|
|
|
|
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawQuads( const RageSpriteVertex v[], int iNumVerts )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( (iNumVerts%4) == 0 );
|
|
|
|
|
|
|
|
|
|
if(iNumVerts == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// there isn't a quad primitive in D3D, so we have to fake it with indexed triangles
|
|
|
|
|
int iNumQuads = iNumVerts/4;
|
|
|
|
|
int iNumTriangles = iNumQuads*2;
|
|
|
|
|
int iNumIndices = iNumTriangles*3;
|
|
|
|
|
|
|
|
|
|
// make a temporary index buffer
|
|
|
|
|
static vector<Uint16> vIndices;
|
|
|
|
|
unsigned uOldSize = vIndices.size();
|
|
|
|
|
unsigned uNewSize = max(uOldSize,(unsigned)iNumIndices);
|
|
|
|
|
vIndices.resize( uNewSize );
|
|
|
|
|
for( Uint16 i=(Uint16)uOldSize/6; i<(Uint16)iNumQuads; i++ )
|
|
|
|
|
{
|
|
|
|
|
vIndices[i*6+0] = i*4+0;
|
|
|
|
|
vIndices[i*6+1] = i*4+1;
|
|
|
|
|
vIndices[i*6+2] = i*4+2;
|
|
|
|
|
vIndices[i*6+3] = i*4+2;
|
|
|
|
|
vIndices[i*6+4] = i*4+3;
|
|
|
|
|
vIndices[i*6+5] = i*4+0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageSpriteVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawIndexedPrimitiveUP(
|
|
|
|
|
D3DPT_TRIANGLELIST, // PrimitiveType
|
|
|
|
|
0, // MinIndex
|
|
|
|
|
iNumVerts, // NumVertices
|
|
|
|
|
iNumTriangles, // PrimitiveCount,
|
|
|
|
|
&vIndices[0], // pIndexData,
|
|
|
|
|
D3DFMT_INDEX16, // IndexDataFormat,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageSpriteVertex) // VertexStreamZeroStride
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
StatsAddVerts( iNumVerts );
|
|
|
|
|
}
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawFan( const RageSpriteVertex v[], int iNumVerts )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( iNumVerts >= 3 );
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageSpriteVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawPrimitiveUP(
|
|
|
|
|
D3DPT_TRIANGLEFAN, // PrimitiveType
|
|
|
|
|
iNumVerts-2, // PrimitiveCount,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageSpriteVertex)
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
StatsAddVerts( iNumVerts );
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawStrip( const RageSpriteVertex v[], int iNumVerts )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( iNumVerts >= 3 );
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageSpriteVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawPrimitiveUP(
|
|
|
|
|
D3DPT_TRIANGLESTRIP, // PrimitiveType
|
|
|
|
|
iNumVerts-2, // PrimitiveCount,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageSpriteVertex)
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
StatsAddVerts( iNumVerts );
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawTriangles( const RageSpriteVertex v[], int iNumVerts )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
if( iNumVerts == 0 )
|
|
|
|
|
return;
|
|
|
|
|
ASSERT( iNumVerts >= 3 );
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageSpriteVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawPrimitiveUP(
|
|
|
|
|
D3DPT_TRIANGLELIST, // PrimitiveType
|
|
|
|
|
iNumVerts/3, // PrimitiveCount,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageSpriteVertex)
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
StatsAddVerts( iNumVerts );
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawIndexedTriangles( const RageModelVertex v[], int iNumVerts, const Uint16 pIndices[], int iNumIndices )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
if( iNumIndices == 0 )
|
|
|
|
|
return;
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageModelVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawIndexedPrimitiveUP(
|
|
|
|
|
D3DPT_TRIANGLELIST, // PrimitiveType
|
|
|
|
|
0, // MinIndex
|
2003-06-27 00:57:02 +00:00
|
|
|
iNumVerts, // NumVertices
|
2003-05-22 05:28:37 +00:00
|
|
|
iNumIndices/3, // PrimitiveCount,
|
|
|
|
|
pIndices, // pIndexData,
|
|
|
|
|
D3DFMT_INDEX16, // IndexDataFormat,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageModelVertex) // VertexStreamZeroStride
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
StatsAddVerts( iNumIndices );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-27 00:20:54 +00:00
|
|
|
/* Use the default poly-based implementation. D3D lines apparently don't support
|
|
|
|
|
* AA with greater-than-one widths. */
|
|
|
|
|
/*
|
2003-07-07 01:29:18 +00:00
|
|
|
void RageDisplay_D3D::DrawLineStrip( const RageSpriteVertex v[], int iNumVerts, float LineWidth )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( iNumVerts >= 2 );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&LineWidth) ); // funky cast. See D3DRENDERSTATETYPE doc
|
2003-07-07 01:29:18 +00:00
|
|
|
g_pd3dDevice->SetVertexShader( D3DFVF_RageSpriteVertex );
|
2003-05-22 05:28:37 +00:00
|
|
|
SEND_CURRENT_MATRICES;
|
|
|
|
|
g_pd3dDevice->DrawPrimitiveUP(
|
|
|
|
|
D3DPT_LINESTRIP, // PrimitiveType
|
|
|
|
|
iNumVerts-1, // PrimitiveCount,
|
|
|
|
|
v, // pVertexStreamZeroData,
|
2003-07-07 01:29:18 +00:00
|
|
|
sizeof(RageSpriteVertex)
|
2003-05-22 05:28:37 +00:00
|
|
|
);
|
|
|
|
|
StatsAddVerts( iNumVerts );
|
|
|
|
|
}
|
2003-05-27 00:20:54 +00:00
|
|
|
*/
|
2004-02-04 09:55:18 +00:00
|
|
|
|
|
|
|
|
void RageDisplay_D3D::ClearAllTextures()
|
|
|
|
|
{
|
|
|
|
|
for( int i=0; i<MAX_TEXTURE_UNITS; i++ )
|
|
|
|
|
SetTexture( i, NULL );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RageDisplay_D3D::SetTexture( int iTextureUnitIndex, RageTexture* pTexture )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
if( pTexture == NULL )
|
|
|
|
|
{
|
2004-02-04 09:55:18 +00:00
|
|
|
g_pd3dDevice->SetTexture( iTextureUnitIndex, NULL );
|
2003-05-22 05:28:37 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned uTexHandle = pTexture->GetTexHandle();
|
|
|
|
|
IDirect3DTexture8* pTex = (IDirect3DTexture8*)uTexHandle;
|
2004-02-04 09:55:18 +00:00
|
|
|
g_pd3dDevice->SetTexture( iTextureUnitIndex, pTex );
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
// Set palette (if any)
|
2003-05-24 02:03:17 +00:00
|
|
|
SetPalette(uTexHandle);
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetTextureModeModulate()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetTextureModeGlow(GlowMode m)
|
2004-02-04 09:55:18 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RageDisplay_D3D::SetTextureModeAdd()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetTextureFiltering( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, b ? D3DTEXF_LINEAR : D3DTEXF_POINT );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, b ? D3DTEXF_LINEAR : D3DTEXF_POINT );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetBlendMode( BlendMode mode )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
2003-11-18 04:03:58 +00:00
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ZBIAS, 0 );
|
2003-05-22 05:28:37 +00:00
|
|
|
switch( mode )
|
|
|
|
|
{
|
|
|
|
|
case BLEND_NORMAL:
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
|
|
|
|
break;
|
|
|
|
|
case BLEND_ADD:
|
2003-10-22 01:47:40 +00:00
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
2003-05-22 05:28:37 +00:00
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
|
|
|
|
break;
|
|
|
|
|
case BLEND_NO_EFFECT:
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
2003-11-18 04:03:58 +00:00
|
|
|
|
|
|
|
|
/* This is almost exclusively used to draw masks to the Z-buffer. Make sure
|
|
|
|
|
* masks always win the depth test when drawn at the same position. */
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ZBIAS, 1 );
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-18 20:33:18 +00:00
|
|
|
bool RageDisplay_D3D::IsZWriteEnabled() const
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
DWORD b;
|
2003-11-18 20:33:18 +00:00
|
|
|
g_pd3dDevice->GetRenderState( D3DRS_ZWRITEENABLE, &b );
|
2003-05-22 05:28:37 +00:00
|
|
|
return b!=0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-18 20:33:18 +00:00
|
|
|
bool RageDisplay_D3D::IsZTestEnabled() const
|
|
|
|
|
{
|
|
|
|
|
DWORD b;
|
|
|
|
|
g_pd3dDevice->GetRenderState( D3DRS_ZFUNC, &b );
|
|
|
|
|
return b!=D3DCMP_ALWAYS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RageDisplay_D3D::SetZWrite( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, b );
|
|
|
|
|
}
|
2003-11-18 20:33:18 +00:00
|
|
|
|
|
|
|
|
void RageDisplay_D3D::SetZTest( bool b )
|
|
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ZFUNC, b ? D3DCMP_LESSEQUAL : D3DCMP_ALWAYS );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::ClearZBuffer()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0x00000000 );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetTextureWrapping( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
int mode = b ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, mode );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, mode );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetMaterial(
|
2004-01-06 21:25:46 +00:00
|
|
|
const RageColor &emissive,
|
|
|
|
|
const RageColor &ambient,
|
|
|
|
|
const RageColor &diffuse,
|
|
|
|
|
const RageColor &specular,
|
2003-05-22 05:28:37 +00:00
|
|
|
float shininess
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
D3DMATERIAL8 mat;
|
2003-06-23 17:04:00 +00:00
|
|
|
memcpy( &mat.Diffuse, diffuse, sizeof(float)*4 );
|
|
|
|
|
memcpy( &mat.Ambient, ambient, sizeof(float)*4 );
|
|
|
|
|
memcpy( &mat.Specular, specular, sizeof(float)*4 );
|
|
|
|
|
memcpy( &mat.Emissive, emissive, sizeof(float)*4 );
|
2003-05-22 05:28:37 +00:00
|
|
|
mat.Power = shininess;
|
|
|
|
|
g_pd3dDevice->SetMaterial( &mat );
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-06 19:54:13 +00:00
|
|
|
// need this?
|
|
|
|
|
// device->SetRenderState(D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL);
|
|
|
|
|
// device->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE,D3DMCS_MATERIAL);
|
|
|
|
|
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetLighting( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, b );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetLightOff( int index )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->LightEnable( index, false );
|
|
|
|
|
}
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetLightDirectional(
|
2003-05-22 05:28:37 +00:00
|
|
|
int index,
|
2004-01-06 21:25:46 +00:00
|
|
|
const RageColor &ambient,
|
|
|
|
|
const RageColor &diffuse,
|
|
|
|
|
const RageColor &specular,
|
|
|
|
|
const RageVector3 &dir )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->LightEnable( index, true );
|
|
|
|
|
|
|
|
|
|
D3DLIGHT8 light;
|
|
|
|
|
ZERO( light );
|
2003-06-23 17:04:00 +00:00
|
|
|
light.Type = D3DLIGHT_DIRECTIONAL;
|
2003-06-27 02:04:56 +00:00
|
|
|
|
2003-09-21 18:54:54 +00:00
|
|
|
/* Z for lighting is flipped for D3D compared to OpenGL.
|
|
|
|
|
* XXX: figure out exactly why this is needed. Our transforms
|
|
|
|
|
* are probably goofed up, but the Z test is the same for both
|
|
|
|
|
* API's, so I'm not sure why we don't see other weirdness. -Chris */
|
|
|
|
|
float position[] = { dir.x, dir.y, -dir.z };
|
2003-06-27 02:04:56 +00:00
|
|
|
memcpy( &light.Direction, position, sizeof(position) );
|
2003-05-22 05:28:37 +00:00
|
|
|
memcpy( &light.Diffuse, diffuse, sizeof(diffuse) );
|
|
|
|
|
memcpy( &light.Ambient, ambient, sizeof(ambient) );
|
|
|
|
|
memcpy( &light.Specular, specular, sizeof(specular) );
|
2003-06-23 17:04:00 +00:00
|
|
|
|
|
|
|
|
// Same as OpenGL defaults. Not used in directional lights.
|
|
|
|
|
// light.Attenuation0 = 1;
|
|
|
|
|
// light.Attenuation1 = 0;
|
|
|
|
|
// light.Attenuation2 = 0;
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
g_pd3dDevice->SetLight( index, &light );
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-04 11:05:33 +00:00
|
|
|
void RageDisplay_D3D::SetCullMode( CullMode mode )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2004-02-04 11:05:33 +00:00
|
|
|
switch( mode )
|
|
|
|
|
{
|
|
|
|
|
case CULL_BACK:
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
|
|
|
|
|
break;
|
|
|
|
|
case CULL_FRONT:
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
|
|
|
|
|
break;
|
|
|
|
|
case CULL_NONE:
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::DeleteTexture( unsigned uTexHandle )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
IDirect3DTexture8* pTex = (IDirect3DTexture8*) uTexHandle;
|
|
|
|
|
pTex->Release();
|
|
|
|
|
|
|
|
|
|
// Delete palette (if any)
|
|
|
|
|
if( g_TexResourceToPaletteIndex.find(uTexHandle) != g_TexResourceToPaletteIndex.end() )
|
|
|
|
|
g_TexResourceToPaletteIndex.erase( g_TexResourceToPaletteIndex.find(uTexHandle) );
|
2003-05-24 01:12:30 +00:00
|
|
|
if( g_TexResourceToTexturePalette.find(uTexHandle) != g_TexResourceToTexturePalette.end() )
|
|
|
|
|
g_TexResourceToTexturePalette.erase( g_TexResourceToTexturePalette.find(uTexHandle) );
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
unsigned RageDisplay_D3D::CreateTexture(
|
2003-05-22 05:28:37 +00:00
|
|
|
PixelFormat pixfmt,
|
2004-01-23 06:20:28 +00:00
|
|
|
SDL_Surface* img,
|
|
|
|
|
bool bGenerateMipMaps )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
// texture must be power of two
|
|
|
|
|
ASSERT( img->w == power_of_two(img->w) );
|
|
|
|
|
ASSERT( img->h == power_of_two(img->h) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
|
IDirect3DTexture8* pTex;
|
|
|
|
|
hr = g_pd3dDevice->CreateTexture( img->w, img->h, 1, 0, D3DFORMATS[pixfmt], D3DPOOL_MANAGED, &pTex );
|
2003-05-28 20:25:21 +00:00
|
|
|
if( FAILED(hr) )
|
|
|
|
|
RageException::Throw( "CreateTexture(%i,%i,pixfmt=%i) failed: %s",
|
2003-07-11 03:15:28 +00:00
|
|
|
img->w, img->h, pixfmt, GetErrorString(hr).c_str() );
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
unsigned uTexHandle = (unsigned)pTex;
|
|
|
|
|
|
|
|
|
|
if( pixfmt == FMT_PAL )
|
|
|
|
|
{
|
|
|
|
|
// Save palette
|
2003-05-24 01:12:30 +00:00
|
|
|
TexturePalette pal;
|
|
|
|
|
memset( pal.p, 0, sizeof(pal.p) );
|
2003-05-22 05:28:37 +00:00
|
|
|
for( int i=0; i<img->format->palette->ncolors; i++ )
|
|
|
|
|
{
|
|
|
|
|
SDL_Color c = img->format->palette->colors[i];
|
2003-05-24 01:12:30 +00:00
|
|
|
pal.p[i].peRed = c.r;
|
|
|
|
|
pal.p[i].peGreen = c.g;
|
|
|
|
|
pal.p[i].peBlue = c.b;
|
2003-05-22 05:28:37 +00:00
|
|
|
bool bIsColorKey = img->flags & SDL_SRCCOLORKEY && (unsigned)i == img->format->colorkey;
|
2003-10-08 01:24:53 +00:00
|
|
|
pal.p[i].peFlags = bIsColorKey ? BYTE(0x00) : c.unused;
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-24 01:12:30 +00:00
|
|
|
ASSERT( g_TexResourceToTexturePalette.find(uTexHandle) == g_TexResourceToTexturePalette.end() );
|
|
|
|
|
g_TexResourceToTexturePalette[uTexHandle] = pal;
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-06-29 08:13:18 +00:00
|
|
|
UpdateTexture( uTexHandle, img, 0, 0, img->w, img->h );
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
return uTexHandle;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::UpdateTexture(
|
2003-05-22 05:28:37 +00:00
|
|
|
unsigned uTexHandle,
|
2003-06-29 08:13:18 +00:00
|
|
|
SDL_Surface* img,
|
2003-05-22 05:28:37 +00:00
|
|
|
int xoffset, int yoffset, int width, int height )
|
|
|
|
|
{
|
|
|
|
|
IDirect3DTexture8* pTex = (IDirect3DTexture8*)uTexHandle;
|
2003-05-28 20:25:21 +00:00
|
|
|
ASSERT( pTex != NULL );
|
|
|
|
|
|
2003-06-29 08:13:18 +00:00
|
|
|
/* Make sure that the pixel format of the image is legit. We don't actually
|
|
|
|
|
* care, but the OpenGL renderer does, so make sure people coding in the D3D
|
|
|
|
|
* renderer don't accidentally break the OpenGL one. */
|
|
|
|
|
FindPixelFormat( img->format->BitsPerPixel, img->format->Rmask, img->format->Gmask, img->format->Bmask, img->format->Amask );
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
RECT rect;
|
|
|
|
|
rect.left = xoffset;
|
|
|
|
|
rect.top = yoffset;
|
|
|
|
|
rect.right = width - xoffset;
|
|
|
|
|
rect.bottom = height - yoffset;
|
|
|
|
|
|
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
|
pTex->LockRect( 0, &lr, &rect, 0 );
|
|
|
|
|
|
2003-06-29 08:13:18 +00:00
|
|
|
D3DSURFACE_DESC desc;
|
|
|
|
|
pTex->GetLevelDesc(0, &desc);
|
|
|
|
|
ASSERT( xoffset+width <= int(desc.Width) );
|
|
|
|
|
ASSERT( yoffset+height <= int(desc.Height) );
|
|
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
//
|
|
|
|
|
// Copy bits
|
|
|
|
|
//
|
|
|
|
|
#if _XBOX
|
|
|
|
|
// Xbox textures need to be swizzled
|
|
|
|
|
XGSwizzleRect(
|
|
|
|
|
img->pixels, // pSource,
|
|
|
|
|
img->pitch, // Pitch,
|
|
|
|
|
NULL, // pRect,
|
|
|
|
|
lr.pBits, // pDest,
|
|
|
|
|
img->w, // Width,
|
|
|
|
|
img->h, // Height,
|
|
|
|
|
NULL, // pPoint,
|
|
|
|
|
img->format->BytesPerPixel ); //BytesPerPixel
|
|
|
|
|
#else
|
2003-06-29 08:13:18 +00:00
|
|
|
int texpixfmt;
|
|
|
|
|
for(texpixfmt = 0; texpixfmt < NUM_PIX_FORMATS; ++texpixfmt)
|
|
|
|
|
if(D3DFORMATS[texpixfmt] == desc.Format) break;
|
|
|
|
|
ASSERT( texpixfmt != NUM_PIX_FORMATS );
|
|
|
|
|
|
|
|
|
|
SDL_Surface *Texture = CreateSurfaceFromPixfmt(PixelFormat(texpixfmt), lr.pBits, width, height, lr.Pitch);
|
2003-07-22 07:47:27 +00:00
|
|
|
ASSERT( Texture );
|
2003-06-29 08:13:18 +00:00
|
|
|
SDL_Rect area;
|
|
|
|
|
area.x = area.y = 0;
|
|
|
|
|
area.w = (Uint16) width;
|
|
|
|
|
area.h = (Uint16) height;
|
|
|
|
|
SDL_SetAlpha( img, 0, SDL_ALPHA_OPAQUE );
|
|
|
|
|
// SDL_SetColorKey( img, 0, 0 );
|
|
|
|
|
// SDL_BlitSurface( img, &area, Texture, &area );
|
|
|
|
|
mySDL_BlitSurface( img, Texture, width, height, false );
|
|
|
|
|
|
|
|
|
|
SDL_FreeSurface( Texture );
|
|
|
|
|
#endif
|
2003-07-22 07:47:27 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
pTex->UnlockRect( 0 );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_D3D::SetAlphaTest( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, b );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0 );
|
|
|
|
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER );
|
|
|
|
|
}
|
2003-05-25 00:43:44 +00:00
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
RageMatrix RageDisplay_D3D::GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf )
|
2003-05-25 00:43:44 +00:00
|
|
|
{
|
|
|
|
|
// D3DXMatrixOrthoOffCenterRH
|
|
|
|
|
RageMatrix m(
|
|
|
|
|
2/(r-l), 0, 0, 0,
|
|
|
|
|
0, 2/(t-b), 0, 0,
|
2003-05-27 08:39:34 +00:00
|
|
|
0, 0, -1/(zf-zn), 0,
|
|
|
|
|
-(r+l)/(r-l), -(t+b)/(t-b), -zn/(zf-zn), 1 );
|
2003-05-25 00:43:44 +00:00
|
|
|
return m;
|
2003-05-25 20:19:01 +00:00
|
|
|
}
|
2003-09-21 18:07:29 +00:00
|
|
|
|
2004-01-06 19:54:13 +00:00
|
|
|
void RageDisplay_D3D::SetSphereEnironmentMapping( bool b )
|
|
|
|
|
{
|
|
|
|
|
// http://www.gamasutra.com/features/20000811/wyatt_03.htm
|
|
|
|
|
|
|
|
|
|
if( b )
|
|
|
|
|
{
|
|
|
|
|
RageMatrix tex = RageMatrix
|
|
|
|
|
(
|
|
|
|
|
0.40f, 0.0f, 0.0f, 0.0f,
|
|
|
|
|
0.0f, -0.40f, 0.0f, 0.0f,
|
|
|
|
|
0.0f, 0.0f, 0.0f, 0.0f,
|
|
|
|
|
0.50, -0.50, 0.0f, 1.0f
|
|
|
|
|
);
|
|
|
|
|
g_pd3dDevice->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX*)&tex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tell D3D to use transformed reflection vectors as texture co-ordinate 0
|
|
|
|
|
// and then transform this coordinate by the specified texture matrix, also
|
|
|
|
|
// tell D3D that only the first two coordinates of the output are valid.
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, b ? D3DTTFF_COUNT2 : D3DTTFF_DISABLE );
|
|
|
|
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, b ? D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR : D3DTSS_TCI_PASSTHRU );
|
|
|
|
|
}
|