2009-11-04 21:44:48 +00:00
|
|
|
#include "quakedef.h"
|
2009-11-04 23:20:50 +00:00
|
|
|
#ifdef D3DQUAKE
|
2011-01-04 02:56:16 +00:00
|
|
|
#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
|
|
|
|
#define HMONITOR_DECLARED
|
|
|
|
DECLARE_HANDLE(HMONITOR);
|
|
|
|
#endif
|
2009-11-04 21:44:48 +00:00
|
|
|
#include <d3d9.h>
|
|
|
|
LPDIRECT3DDEVICE9 pD3DDev9;
|
|
|
|
|
2010-05-01 22:47:47 +00:00
|
|
|
typedef struct d3dtexture_s
|
|
|
|
{
|
|
|
|
struct d3dtexture_s *next;
|
|
|
|
texid_t tex;
|
|
|
|
qboolean loaded;
|
|
|
|
char name[1];
|
|
|
|
} d3dtexture_t;
|
|
|
|
static d3dtexture_t *d3dtextures;
|
|
|
|
|
|
|
|
static d3dtexture_t *d3d_lookup_texture(char *ident)
|
|
|
|
{
|
|
|
|
d3dtexture_t *tex;
|
|
|
|
|
|
|
|
if (ident)
|
|
|
|
{
|
|
|
|
for (tex = d3dtextures; tex; tex = tex->next)
|
|
|
|
if (!strcmp(tex->name, ident))
|
|
|
|
return tex;
|
|
|
|
|
|
|
|
tex = malloc(sizeof(*tex)+strlen(ident));
|
|
|
|
strcpy(tex->name, ident);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tex = malloc(sizeof(*tex));
|
|
|
|
tex->name[0] = '\0';
|
|
|
|
}
|
2010-11-06 23:05:29 +00:00
|
|
|
tex->loaded = false;
|
2010-05-01 22:47:47 +00:00
|
|
|
tex->tex.ptr = NULL;
|
|
|
|
tex->next = d3dtextures;
|
|
|
|
d3dtextures = tex;
|
2009-11-04 21:44:48 +00:00
|
|
|
|
2010-05-01 22:47:47 +00:00
|
|
|
return tex;
|
|
|
|
}
|
2009-11-04 21:44:48 +00:00
|
|
|
|
|
|
|
extern cvar_t gl_picmip;
|
|
|
|
extern cvar_t gl_picmip2d;
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_AllocNewTexture(int width, int height)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
2010-05-01 22:47:47 +00:00
|
|
|
IDirect3DTexture9 *tx;
|
|
|
|
texid_t ret = r_nulltex;
|
|
|
|
if (!FAILED(IDirect3DDevice9_CreateTexture(pD3DDev9, width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tx, NULL)))
|
|
|
|
ret.ptr = tx;
|
|
|
|
return ret;
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
void D3D9_DestroyTexture (texid_t tex)
|
|
|
|
{
|
|
|
|
IDirect3DTexture9 *tx = tex.ptr;
|
|
|
|
IDirect3DTexture9_Release(tx);
|
|
|
|
}
|
|
|
|
|
2009-11-04 21:44:48 +00:00
|
|
|
static void D3D9_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
|
|
|
|
{
|
|
|
|
// if (gl_config.arb_texture_non_power_of_two) //NPOT is a simple extension that relaxes errors.
|
|
|
|
// {
|
|
|
|
// TRACE(("dbg: GL_RoundDimensions: GL_ARB_texture_non_power_of_two\n"));
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
{
|
|
|
|
int width = *scaled_width;
|
|
|
|
int height = *scaled_height;
|
|
|
|
for (*scaled_width = 1 ; *scaled_width < width ; *scaled_width<<=1)
|
|
|
|
;
|
|
|
|
for (*scaled_height = 1 ; *scaled_height < height ; *scaled_height<<=1)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mipmap)
|
|
|
|
{
|
|
|
|
TRACE(("dbg: GL_RoundDimensions: %i\n", gl_picmip.ival));
|
|
|
|
*scaled_width >>= gl_picmip.ival;
|
|
|
|
*scaled_height >>= gl_picmip.ival;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*scaled_width >>= gl_picmip2d.ival;
|
|
|
|
*scaled_height >>= gl_picmip2d.ival;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE(("dbg: GL_RoundDimensions: %i\n", gl_max_size.ival));
|
|
|
|
if (gl_max_size.ival)
|
|
|
|
{
|
|
|
|
if (*scaled_width > gl_max_size.ival)
|
|
|
|
*scaled_width = gl_max_size.ival;
|
|
|
|
if (*scaled_height > gl_max_size.ival)
|
|
|
|
*scaled_height = gl_max_size.ival;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*scaled_width < 1)
|
|
|
|
*scaled_width = 1;
|
|
|
|
if (*scaled_height < 1)
|
|
|
|
*scaled_height = 1;
|
|
|
|
}
|
|
|
|
|
2010-05-01 22:47:47 +00:00
|
|
|
static void Upload_Texture_32(LPDIRECT3DTEXTURE9 tex, unsigned int *data, int width, int height, unsigned int flags)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
unsigned int *dest;
|
|
|
|
unsigned char swapbuf[4];
|
|
|
|
unsigned char swapbuf2[4];
|
|
|
|
D3DLOCKED_RECT lock;
|
|
|
|
|
|
|
|
D3DSURFACE_DESC desc;
|
|
|
|
IDirect3DTexture9_GetLevelDesc(tex, 0, &desc);
|
|
|
|
|
2010-11-06 23:05:29 +00:00
|
|
|
IDirect3DTexture9_LockRect(tex, 0, &lock, NULL, D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY);
|
2009-11-04 21:44:48 +00:00
|
|
|
|
|
|
|
if (width == desc.Width && height == desc.Height)
|
|
|
|
{
|
|
|
|
// if (desc.lPitch == twidth*4)
|
|
|
|
// {
|
|
|
|
// memcpy(desc.lpSurface, data, width*height*4);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
{
|
|
|
|
for (y = 0; y < height; y++)
|
|
|
|
{
|
|
|
|
dest = (unsigned int *)((char *)lock.pBits + lock.Pitch*y);
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{
|
|
|
|
*(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = data[x];
|
|
|
|
swapbuf[0] = swapbuf2[2];
|
|
|
|
swapbuf[2] = swapbuf2[0];
|
|
|
|
dest[x] = *(unsigned int*)swapbuf;
|
|
|
|
}
|
|
|
|
data += width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
int iny;
|
|
|
|
unsigned int *row, *inrow;
|
|
|
|
|
|
|
|
for (y = 0; y < desc.Height; y++)
|
|
|
|
{
|
|
|
|
row = (unsigned int*)((char *)lock.pBits + lock.Pitch*y);
|
|
|
|
iny = (y * height) / desc.Height;
|
|
|
|
inrow = data + width*iny;
|
|
|
|
for (x = 0; x < desc.Width; x++)
|
|
|
|
{
|
|
|
|
*(unsigned int*)swapbuf2 = *(unsigned int*)swapbuf = inrow[(x * width)/desc.Width];
|
|
|
|
swapbuf[0] = swapbuf2[2];
|
|
|
|
swapbuf[2] = swapbuf2[0];
|
|
|
|
row[x] = *(unsigned int*)swapbuf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//mimic opengl and draw it white
|
|
|
|
// memset(desc.lpSurface, 255, twidth*theight*4);
|
|
|
|
}
|
|
|
|
|
|
|
|
IDirect3DTexture9_UnlockRect(tex, 0);
|
2010-05-01 22:47:47 +00:00
|
|
|
|
|
|
|
if (!(flags & IF_NOMIPMAP))
|
|
|
|
IDirect3DBaseTexture9_GenerateMipSubLevels(tex);
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//create a basic shader from a 32bit image
|
2010-05-01 22:47:47 +00:00
|
|
|
static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned int *data, int width, int height, int flags)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
int nwidth, nheight;
|
|
|
|
|
|
|
|
LPDIRECT3DTEXTURE9 newsurf;
|
|
|
|
/*
|
|
|
|
if (!(flags & TF_MANDATORY))
|
|
|
|
{
|
|
|
|
Con_Printf("Texture upload missing flags\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
nwidth = width;
|
|
|
|
nheight = height;
|
|
|
|
D3D9_RoundDimensions(&nwidth, &nheight, !(flags & IF_NOMIPMAP));
|
|
|
|
|
2010-05-01 22:47:47 +00:00
|
|
|
newsurf = tex->tex.ptr;
|
|
|
|
if (!newsurf)
|
|
|
|
IDirect3DDevice9_CreateTexture(pD3DDev9, nwidth, nheight, 0, ((flags & IF_NOMIPMAP)?0:D3DUSAGE_AUTOGENMIPMAP), D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &newsurf, NULL);
|
2009-11-04 21:44:48 +00:00
|
|
|
|
|
|
|
if (!newsurf)
|
|
|
|
return NULL;
|
|
|
|
|
2010-05-01 22:47:47 +00:00
|
|
|
Upload_Texture_32(newsurf, data, width, height, flags);
|
2009-11-04 21:44:48 +00:00
|
|
|
|
2010-11-06 23:05:29 +00:00
|
|
|
tex->loaded = true;
|
|
|
|
|
2009-11-04 21:44:48 +00:00
|
|
|
return (LPDIRECT3DBASETEXTURE9)newsurf;
|
|
|
|
}
|
|
|
|
|
2010-11-11 18:22:49 +00:00
|
|
|
static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
static unsigned trans[1024*1024];
|
|
|
|
int i, s;
|
|
|
|
qboolean noalpha;
|
|
|
|
int p;
|
|
|
|
|
|
|
|
if (width*height > 1024*1024)
|
|
|
|
Sys_Error("GL_Upload8: image too big (%i*%i)", width, height);
|
|
|
|
|
|
|
|
s = width*height;
|
|
|
|
// if there are no transparent pixels, make it a 3 component
|
|
|
|
// texture even if it was specified as otherwise
|
2010-05-01 22:47:47 +00:00
|
|
|
if (fmt == TF_TRANS8_FULLBRIGHT)
|
|
|
|
{
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
noalpha = true;
|
|
|
|
if (p > 255-vid.fullbright)
|
2010-11-11 18:22:49 +00:00
|
|
|
trans[i] = pal32[p];
|
2010-05-01 22:47:47 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
noalpha = false;
|
2010-11-11 18:22:49 +00:00
|
|
|
trans[i] = pal32[p] & 0x00ffffff;
|
2010-05-01 22:47:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((fmt!=TF_SOLID8) && !(flags & IF_NOALPHA))
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
noalpha = true;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
if (p == 255)
|
|
|
|
{
|
|
|
|
noalpha = false;
|
|
|
|
trans[i] = 0;
|
|
|
|
}
|
|
|
|
else
|
2010-11-11 18:22:49 +00:00
|
|
|
trans[i] = pal32[p];
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(fmt)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
if (noalpha)
|
|
|
|
fmt = TF_SOLID8;
|
|
|
|
break;
|
|
|
|
case TF_H2_T7G1:
|
|
|
|
fmt = TF_TRANS8;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
if (p == 0)
|
|
|
|
trans[i] &= 0x00ffffff;
|
|
|
|
else if( p & 1 )
|
|
|
|
{
|
|
|
|
trans[i] &= 0x00ffffff;
|
|
|
|
trans[i] |= ( ( int )( 255 * 0.5 ) ) << 24;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
trans[i] |= 0xff000000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TF_H2_TRANS8_0:
|
|
|
|
fmt = TF_TRANS8;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
if (p == 0)
|
|
|
|
trans[i] &= 0x00ffffff;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* case TF_H2_T4A4:
|
|
|
|
fmt = TF_TRANS8;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
trans[i] = d_8to24rgbtable[ColorIndex[p>>4]] & 0x00ffffff;
|
|
|
|
trans[i] |= ( int )ColorPercent[p&15] << 24;
|
|
|
|
//trans[i] = 0x7fff0000;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=(s&~3)-4 ; i>=0 ; i-=4)
|
|
|
|
{
|
2010-11-11 18:22:49 +00:00
|
|
|
trans[i] = pal32[data[i]];
|
|
|
|
trans[i+1] = pal32[data[i+1]];
|
|
|
|
trans[i+2] = pal32[data[i+2]];
|
|
|
|
trans[i+3] = pal32[data[i+3]];
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
for (i=s&~3 ; i<s ; i++) //wow, funky
|
|
|
|
{
|
2010-11-11 18:22:49 +00:00
|
|
|
trans[i] = pal32[data[i]];
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
}
|
2010-05-01 22:47:47 +00:00
|
|
|
return D3D9_LoadTexture_32(tex, trans, width, height, flags);
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
switch (fmt)
|
|
|
|
{
|
2010-11-13 17:22:46 +00:00
|
|
|
case TF_RGBX32:
|
|
|
|
flags |= IF_NOALPHA;
|
|
|
|
//fall through
|
2009-11-04 21:44:48 +00:00
|
|
|
case TF_RGBA32:
|
2010-05-01 22:47:47 +00:00
|
|
|
Upload_Texture_32(tex.ptr, data, width, height, flags);
|
|
|
|
break;
|
2009-11-04 21:44:48 +00:00
|
|
|
default:
|
2010-05-01 22:47:47 +00:00
|
|
|
OutputDebugString(va("D3D_LoadTextureFmt doesn't support fmt %i (%s)", fmt, name));
|
2009-11-04 21:44:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
texid_t tid;
|
2010-05-01 22:47:47 +00:00
|
|
|
d3dtexture_t *tex;
|
2010-11-06 23:05:29 +00:00
|
|
|
switch (fmt)
|
|
|
|
{
|
|
|
|
case TF_TRANS8_FULLBRIGHT:
|
|
|
|
{
|
|
|
|
qbyte *d = data;
|
|
|
|
unsigned int c = width * height;
|
|
|
|
while (c)
|
|
|
|
{
|
|
|
|
if (d[--c] > 255 - vid.fullbright)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*reject it if there's no fullbrights*/
|
|
|
|
if (!c)
|
|
|
|
return r_nulltex;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-05-01 22:47:47 +00:00
|
|
|
tex = d3d_lookup_texture(identifier);
|
|
|
|
|
2009-11-04 21:44:48 +00:00
|
|
|
switch (fmt)
|
|
|
|
{
|
|
|
|
case TF_SOLID8:
|
|
|
|
case TF_TRANS8:
|
|
|
|
case TF_H2_T7G1:
|
|
|
|
case TF_H2_TRANS8_0:
|
|
|
|
case TF_H2_T4A4:
|
2010-05-01 22:47:47 +00:00
|
|
|
case TF_TRANS8_FULLBRIGHT:
|
2010-11-11 18:22:49 +00:00
|
|
|
tid.ptr = D3D9_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt);
|
2009-11-04 21:44:48 +00:00
|
|
|
return tid;
|
|
|
|
case TF_RGBA32:
|
2010-05-01 22:47:47 +00:00
|
|
|
tid.ptr = D3D9_LoadTexture_32(tex, data, width, height, flags);
|
2009-11-04 21:44:48 +00:00
|
|
|
return tid;
|
|
|
|
default:
|
2010-05-01 22:47:47 +00:00
|
|
|
OutputDebugString(va("D3D_LoadTextureFmt doesn't support fmt %i (%s)", fmt, name));
|
2009-11-04 21:44:48 +00:00
|
|
|
return r_nulltex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_LoadCompressed (char *name)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
|
|
|
return r_nulltex;
|
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_FindTexture (char *identifier)
|
2010-05-01 22:47:47 +00:00
|
|
|
{
|
|
|
|
d3dtexture_t *tex = d3d_lookup_texture(identifier);
|
|
|
|
return tex->tex;
|
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags)
|
2010-05-01 22:47:47 +00:00
|
|
|
{
|
2010-11-11 18:22:49 +00:00
|
|
|
d3dtexture_t *tex = d3d_lookup_texture(identifier);
|
|
|
|
tex->tex.ptr = D3D9_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8);
|
|
|
|
return tex->tex;
|
2010-05-01 22:47:47 +00:00
|
|
|
}
|
2010-11-02 23:17:25 +00:00
|
|
|
texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags)
|
2009-11-04 21:44:48 +00:00
|
|
|
{
|
2010-11-11 18:22:49 +00:00
|
|
|
unsigned int pal32[256];
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
pal32[i] = 0x00000000 |
|
|
|
|
(palette24[i*3+2]<<24) |
|
|
|
|
(palette24[i*3+1]<<8) |
|
|
|
|
(palette24[i*3+0]<<0);
|
|
|
|
}
|
2010-11-13 17:22:46 +00:00
|
|
|
return D3D9_LoadTexture8Pal32(identifier, width, height, data, (qbyte*)pal32, flags);
|
2009-11-04 21:44:48 +00:00
|
|
|
}
|
2010-11-02 23:17:25 +00:00
|
|
|
|
2009-11-04 23:20:50 +00:00
|
|
|
#endif
|