mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
ref_dx2 (WIP)
This commit is contained in:
19
ref/dx2/dllmain.cpp
Normal file
19
ref/dx2/dllmain.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "windows.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
1039
ref/dx2/r_context.c
Normal file
1039
ref/dx2/r_context.c
Normal file
File diff suppressed because it is too large
Load Diff
722
ref/dx2/r_image.c
Normal file
722
ref/dx2/r_image.c
Normal file
@@ -0,0 +1,722 @@
|
||||
/*
|
||||
r_context.c -- dx2 renderer image
|
||||
Copyright (C) 2025 lewa_j
|
||||
|
||||
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 3 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.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "com_strings.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "crtlib.h"
|
||||
#include "crclib.h"
|
||||
|
||||
#define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
|
||||
|
||||
static dx_texture_t dx_textures[MAX_TEXTURES];
|
||||
static dx_texture_t *dx_texturesHashTable[TEXTURES_HASH_SIZE];
|
||||
static uint dx_numTextures;
|
||||
|
||||
static rgbdata_t *GL_FakeImage(int width, int height, int depth, int flags)
|
||||
{
|
||||
static byte data2D[1024]; // 16x16x4
|
||||
static rgbdata_t r_image;
|
||||
|
||||
// also use this for bad textures, but without alpha
|
||||
r_image.width = Q_max(1, width);
|
||||
r_image.height = Q_max(1, height);
|
||||
r_image.depth = Q_max(1, depth);
|
||||
r_image.flags = flags;
|
||||
r_image.type = PF_BGRA_32;
|
||||
r_image.size = r_image.width * r_image.height * r_image.depth * 4;
|
||||
r_image.buffer = (r_image.size > sizeof(data2D)) ? NULL : data2D;
|
||||
r_image.palette = NULL;
|
||||
r_image.numMips = 1;
|
||||
r_image.encode = 0;
|
||||
|
||||
if (FBitSet(r_image.flags, IMAGE_CUBEMAP))
|
||||
r_image.size *= 6;
|
||||
memset(data2D, 0xFF, sizeof(data2D));
|
||||
|
||||
return &r_image;
|
||||
}
|
||||
|
||||
static byte dottexture[8][8] =
|
||||
{
|
||||
{0,1,1,0,0,0,0,0},
|
||||
{1,1,1,1,0,0,0,0},
|
||||
{1,1,1,1,0,0,0,0},
|
||||
{0,1,1,0,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,0},
|
||||
{0,0,0,0,0,0,0,0},
|
||||
};
|
||||
|
||||
static void GL_CreateInternalTextures(void)
|
||||
{
|
||||
int dx2, dy, d;
|
||||
int x, y;
|
||||
rgbdata_t *pic;
|
||||
|
||||
// emo-texture from quake1
|
||||
pic = GL_FakeImage(16, 16, 1, IMAGE_HAS_COLOR);
|
||||
|
||||
for (y = 0; y < 16; y++)
|
||||
{
|
||||
for (x = 0; x < 16; x++)
|
||||
{
|
||||
if ((y < 8) ^ (x < 8))
|
||||
((uint *)pic->buffer)[y * 16 + x] = 0xFFFF00FF;
|
||||
else ((uint *)pic->buffer)[y * 16 + x] = 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
tr.defaultTexture = GL_LoadTextureFromBuffer(REF_DEFAULT_TEXTURE, pic, TF_COLORMAP, false);
|
||||
|
||||
// particle texture from quake1
|
||||
pic = GL_FakeImage(8, 8, 1, IMAGE_HAS_COLOR | IMAGE_HAS_ALPHA);
|
||||
|
||||
for (x = 0; x < 8; x++)
|
||||
{
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
if (dottexture[x][y])
|
||||
pic->buffer[(y * 8 + x) * 4 + 3] = 255;
|
||||
else pic->buffer[(y * 8 + x) * 4 + 3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
tr.particleTexture = GL_LoadTextureFromBuffer(REF_PARTICLE_TEXTURE, pic, TF_CLAMP, false);
|
||||
|
||||
// white texture
|
||||
pic = GL_FakeImage(4, 4, 1, IMAGE_HAS_COLOR);
|
||||
for (x = 0; x < 16; x++)
|
||||
((uint *)pic->buffer)[x] = 0xFFFFFFFF;
|
||||
tr.whiteTexture = GL_LoadTextureFromBuffer(REF_WHITE_TEXTURE, pic, TF_COLORMAP, false);
|
||||
|
||||
// gray texture
|
||||
pic = GL_FakeImage(4, 4, 1, IMAGE_HAS_COLOR);
|
||||
for (x = 0; x < 16; x++)
|
||||
((uint *)pic->buffer)[x] = 0xFF7F7F7F;
|
||||
tr.grayTexture = GL_LoadTextureFromBuffer(REF_GRAY_TEXTURE, pic, TF_COLORMAP, false);
|
||||
|
||||
// black texture
|
||||
pic = GL_FakeImage(4, 4, 1, IMAGE_HAS_COLOR);
|
||||
for (x = 0; x < 16; x++)
|
||||
((uint *)pic->buffer)[x] = 0xFF000000;
|
||||
tr.blackTexture = GL_LoadTextureFromBuffer(REF_BLACK_TEXTURE, pic, TF_COLORMAP, false);
|
||||
|
||||
// cinematic dummy
|
||||
pic = GL_FakeImage(640, 100, 1, IMAGE_HAS_COLOR);
|
||||
tr.cinTexture = GL_LoadTextureFromBuffer("*cintexture", pic, TF_NOMIPMAP | TF_CLAMP, false);
|
||||
}
|
||||
|
||||
void R_InitImages(void)
|
||||
{
|
||||
memset(dx_textures, 0, sizeof(dx_textures));
|
||||
memset(dx_texturesHashTable, 0, sizeof(dx_texturesHashTable));
|
||||
dx_numTextures = 0;
|
||||
|
||||
// create unused 0-entry
|
||||
Q_strncpy(dx_textures->name, "*unused*", sizeof(dx_textures->name));
|
||||
dx_textures->hashValue = COM_HashKey(dx_textures->name, TEXTURES_HASH_SIZE);
|
||||
dx_textures->nextHash = dx_texturesHashTable[dx_textures->hashValue];
|
||||
dx_texturesHashTable[dx_textures->hashValue] = dx_textures;
|
||||
dx_numTextures = 1;
|
||||
|
||||
GL_CreateInternalTextures();
|
||||
}
|
||||
|
||||
dx_texture_t *R_GetTexture(unsigned int texnum)
|
||||
{
|
||||
Assert(texnum < MAX_TEXTURES);
|
||||
return &dx_textures[texnum];
|
||||
}
|
||||
|
||||
void R_ShowTextures( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const byte *R_GetTextureOriginalBuffer(unsigned int idx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static qboolean GL_CheckTexName(const char *name)
|
||||
{
|
||||
int len;
|
||||
|
||||
if( COM_StringEmptyOrNULL( name ))
|
||||
return false;
|
||||
|
||||
len = Q_strlen(name);
|
||||
|
||||
// because multi-layered textures can exceed name string
|
||||
if (len >= sizeof(dx_textures->name))
|
||||
{
|
||||
gEngfuncs.Con_Printf(S_ERROR "LoadTexture: too long name %s (%d)\n", name, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static dx_texture_t *GL_TextureForName(const char *name)
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
uint hash;
|
||||
|
||||
// find the texture in array
|
||||
hash = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
||||
|
||||
for (tex = dx_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash)
|
||||
{
|
||||
if (!Q_stricmp(tex->name, name))
|
||||
return tex;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static dx_texture_t *GL_AllocTexture(const char *name, texFlags_t flags)
|
||||
{
|
||||
dx_texture_t *tex = NULL;
|
||||
|
||||
// find a free texture_t slot
|
||||
uint i;
|
||||
|
||||
//skip 0
|
||||
for (i = 1; i < MAX_TEXTURES; i++)
|
||||
{
|
||||
if (dx_textures[i].used)
|
||||
continue;
|
||||
|
||||
tex = &dx_textures[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
gEngfuncs.Host_Error("%s: MAX_TEXTURES limit exceeds\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy initial params
|
||||
Q_strncpy(tex->name, name, sizeof(tex->name));
|
||||
tex->used = 1;
|
||||
tex->flags = flags;
|
||||
|
||||
// increase counter
|
||||
dx_numTextures = Q_max((tex - dx_textures) + 1, dx_numTextures);
|
||||
|
||||
// add to hash table
|
||||
tex->hashValue = COM_HashKey(name, TEXTURES_HASH_SIZE);
|
||||
tex->nextHash = dx_texturesHashTable[tex->hashValue];
|
||||
dx_texturesHashTable[tex->hashValue] = tex;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void GL_ProcessImage(dx_texture_t *tex, rgbdata_t *pic)
|
||||
{
|
||||
uint img_flags = 0;
|
||||
|
||||
// force upload texture as RGB or RGBA (detail textures requires this)
|
||||
if (tex->flags & TF_FORCE_COLOR) pic->flags |= IMAGE_HAS_COLOR;
|
||||
if (pic->flags & IMAGE_HAS_ALPHA) tex->flags |= TF_HAS_ALPHA;
|
||||
|
||||
if (ImageCompressed(pic->type))
|
||||
{
|
||||
if (!pic->numMips)
|
||||
tex->flags |= TF_NOMIPMAP; // disable mipmapping by user request
|
||||
|
||||
// clear all the unsupported flags
|
||||
tex->flags &= ~TF_KEEP_SOURCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy flag about luma pixels
|
||||
if (pic->flags & IMAGE_HAS_LUMA)
|
||||
tex->flags |= TF_HAS_LUMA;
|
||||
|
||||
if (pic->flags & IMAGE_QUAKEPAL)
|
||||
tex->flags |= TF_QUAKEPAL;
|
||||
|
||||
// create luma texture from quake texture
|
||||
if (tex->flags & TF_MAKELUMA)
|
||||
{
|
||||
img_flags |= IMAGE_MAKE_LUMA;
|
||||
tex->flags &= ~TF_MAKELUMA;
|
||||
}
|
||||
|
||||
if (!FBitSet(tex->flags, TF_IMG_UPLOADED) && FBitSet(tex->flags, TF_KEEP_SOURCE))
|
||||
tex->original = gEngfuncs.FS_CopyImage(pic); // because current pic will be expanded to rgba
|
||||
|
||||
// we need to expand image into RGBA buffer
|
||||
if (pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32)
|
||||
img_flags |= IMAGE_FORCE_RGBA;
|
||||
|
||||
// processing image before uploading (force to rgba, make luma etc)
|
||||
if (pic->buffer) gEngfuncs.Image_Process(&pic, 0, 0, img_flags, 0);
|
||||
|
||||
if (FBitSet(tex->flags, TF_LUMINANCE))
|
||||
ClearBits(pic->flags, IMAGE_HAS_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
static int GL_CalcMipmapCount(dx_texture_t *tex, qboolean haveBuffer)
|
||||
{
|
||||
int width, height;
|
||||
int mipcount;
|
||||
|
||||
Assert(tex != NULL);
|
||||
|
||||
//TEMP
|
||||
return 1;
|
||||
|
||||
if (!haveBuffer)
|
||||
return 1;
|
||||
|
||||
// generate mip-levels by user request
|
||||
if (FBitSet(tex->flags, TF_NOMIPMAP))
|
||||
return 1;
|
||||
|
||||
// mip-maps can't exceeds 16
|
||||
for (mipcount = 0; mipcount < 16; mipcount++)
|
||||
{
|
||||
width = Q_max(1, (tex->width >> mipcount));
|
||||
height = Q_max(1, (tex->height >> mipcount));
|
||||
if (width == 1 && height == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
return mipcount + 1;
|
||||
}
|
||||
|
||||
static byte *GL_ResampleTexture(const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap)
|
||||
{
|
||||
uint frac, fracStep;
|
||||
uint *in = (uint *)source;
|
||||
uint p1[0x1000], p2[0x1000];
|
||||
byte *pix1, *pix2, *pix3, *pix4;
|
||||
uint *out, *inRow1, *inRow2;
|
||||
static byte *scaledImage = NULL; // pointer to a scaled image
|
||||
vec3_t normal;
|
||||
int i, x, y;
|
||||
|
||||
if (!source) return NULL;
|
||||
|
||||
scaledImage = Mem_Realloc(r_temppool, scaledImage, outWidth * outHeight * 4);
|
||||
fracStep = inWidth * 0x10000 / outWidth;
|
||||
out = (uint *)scaledImage;
|
||||
|
||||
frac = fracStep >> 2;
|
||||
for (i = 0; i < outWidth; i++)
|
||||
{
|
||||
p1[i] = 4 * (frac >> 16);
|
||||
frac += fracStep;
|
||||
}
|
||||
|
||||
frac = (fracStep >> 2) * 3;
|
||||
for (i = 0; i < outWidth; i++)
|
||||
{
|
||||
p2[i] = 4 * (frac >> 16);
|
||||
frac += fracStep;
|
||||
}
|
||||
|
||||
if (isNormalMap)
|
||||
{
|
||||
for (y = 0; y < outHeight; y++, out += outWidth)
|
||||
{
|
||||
inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight);
|
||||
inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight);
|
||||
|
||||
for (x = 0; x < outWidth; x++)
|
||||
{
|
||||
pix1 = (byte *)inRow1 + p1[x];
|
||||
pix2 = (byte *)inRow1 + p2[x];
|
||||
pix3 = (byte *)inRow2 + p1[x];
|
||||
pix4 = (byte *)inRow2 + p2[x];
|
||||
|
||||
normal[0] = MAKE_SIGNED(pix1[0]) + MAKE_SIGNED(pix2[0]) + MAKE_SIGNED(pix3[0]) + MAKE_SIGNED(pix4[0]);
|
||||
normal[1] = MAKE_SIGNED(pix1[1]) + MAKE_SIGNED(pix2[1]) + MAKE_SIGNED(pix3[1]) + MAKE_SIGNED(pix4[1]);
|
||||
normal[2] = MAKE_SIGNED(pix1[2]) + MAKE_SIGNED(pix2[2]) + MAKE_SIGNED(pix3[2]) + MAKE_SIGNED(pix4[2]);
|
||||
|
||||
if (!VectorNormalizeLength(normal))
|
||||
VectorSet(normal, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
((byte *)(out + x))[0] = 128 + (byte)(127.0f * normal[0]);
|
||||
((byte *)(out + x))[1] = 128 + (byte)(127.0f * normal[1]);
|
||||
((byte *)(out + x))[2] = 128 + (byte)(127.0f * normal[2]);
|
||||
((byte *)(out + x))[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < outHeight; y++, out += outWidth)
|
||||
{
|
||||
inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight);
|
||||
inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight);
|
||||
|
||||
for (x = 0; x < outWidth; x++)
|
||||
{
|
||||
pix1 = (byte *)inRow1 + p1[x];
|
||||
pix2 = (byte *)inRow1 + p2[x];
|
||||
pix3 = (byte *)inRow2 + p1[x];
|
||||
pix4 = (byte *)inRow2 + p2[x];
|
||||
|
||||
((byte *)(out + x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
|
||||
((byte *)(out + x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
|
||||
((byte *)(out + x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
|
||||
((byte *)(out + x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
static void GL_TextureImageRAW(dx_texture_t *tex, int width, int height, int type, const char *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
DDSURFACEDESC ddsd = {};
|
||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_LPSURFACE;
|
||||
DXCheck(IDirectDrawSurface_Lock(tex->dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL));
|
||||
|
||||
int pitch = ddsd.lPitch;
|
||||
if (!pitch)
|
||||
pitch = ddsd.dwWidth * 4;
|
||||
char *dst = (char *)ddsd.lpSurface;
|
||||
|
||||
for (int j = 0; j < (int)ddsd.dwHeight; j++)
|
||||
{
|
||||
//RGBA to BGRA
|
||||
if (type == PF_RGBA_32)
|
||||
{
|
||||
for (int i = 0; i < ddsd.dwWidth; i++)
|
||||
{
|
||||
dst[i * 4 + 0] = data[i * 4 + 2];
|
||||
dst[i * 4 + 1] = data[i * 4 + 1];
|
||||
dst[i * 4 + 2] = data[i * 4 + 0];
|
||||
dst[i * 4 + 3] = data[i * 4 + 3];
|
||||
}
|
||||
}
|
||||
else if (type == PF_BGRA_32)
|
||||
{
|
||||
memcpy(dst, data, ddsd.dwWidth * 4);
|
||||
}
|
||||
|
||||
dst += pitch;
|
||||
data += ddsd.dwWidth * 4;
|
||||
}
|
||||
|
||||
DXCheck(IDirectDrawSurface_Unlock(tex->dds, ddsd.lpSurface));
|
||||
}
|
||||
|
||||
static qboolean GL_UploadTexture(dx_texture_t *tex, rgbdata_t *pic)
|
||||
{
|
||||
byte *buf, *data;
|
||||
size_t texsize, size;
|
||||
uint width, height;
|
||||
uint i, j, numSides;
|
||||
qboolean normalMap;
|
||||
const byte *bufend;
|
||||
|
||||
// dedicated server
|
||||
if (!dxc.window)
|
||||
return true;
|
||||
|
||||
Assert(pic != NULL);
|
||||
Assert(tex != NULL);
|
||||
|
||||
qboolean supported = true;
|
||||
|
||||
if (FBitSet(pic->flags, IMAGE_CUBEMAP))
|
||||
supported = false;
|
||||
else if (FBitSet(pic->flags, IMAGE_MULTILAYER) && pic->depth >= 1)
|
||||
supported = false;
|
||||
else if (pic->width > 1 && pic->height > 1 && pic->depth > 1)
|
||||
supported = false;
|
||||
else if (FBitSet(tex->flags, TF_RECTANGLE))
|
||||
supported = false;
|
||||
else if (FBitSet(tex->flags, TF_MULTISAMPLE))
|
||||
supported = false;
|
||||
|
||||
// make sure what target is correct
|
||||
if (!supported)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: %s is not supported\n", __func__, tex->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (pic->type == PF_BC6H_SIGNED || pic->type == PF_BC6H_UNSIGNED || pic->type == PF_BC7_UNORM || pic->type == PF_BC7_SRGB)
|
||||
if (ImageCompressed(pic->type))
|
||||
{
|
||||
gEngfuncs.Con_DPrintf(S_ERROR "%s: compressed textures are not supported\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// store original sizes
|
||||
tex->srcWidth = pic->width;
|
||||
tex->srcHeight = pic->height;
|
||||
|
||||
// set the texture dimensions
|
||||
{
|
||||
int step = 0;// (int)gl_round_down.value;
|
||||
int scaled_width, scaled_height;
|
||||
|
||||
for (scaled_width = 1; scaled_width < pic->width; scaled_width <<= 1);
|
||||
|
||||
if (step > 0 && pic->width < scaled_width && (step == 1 || (scaled_width - pic->width) > (scaled_width >> step)))
|
||||
scaled_width >>= 1;
|
||||
|
||||
for (scaled_height = 1; scaled_height < pic->height; scaled_height <<= 1);
|
||||
|
||||
if (step > 0 && pic->height < scaled_height && (step == 1 || (scaled_height - pic->height) > (scaled_height >> step)))
|
||||
scaled_height >>= 1;
|
||||
|
||||
tex->width = Q_max(1, scaled_width);
|
||||
tex->height = Q_max(1, scaled_height);
|
||||
}
|
||||
|
||||
DDSURFACEDESC ddsd = {};
|
||||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
//if (pic->numMips > 1)
|
||||
// ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
||||
ddsd.dwWidth = tex->width;
|
||||
ddsd.dwHeight = tex->height;
|
||||
|
||||
#if 0
|
||||
//RGBA8
|
||||
ddsd.dwFlags |= DDSD_PIXELFORMAT;
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
|
||||
ddsd.ddpfPixelFormat.dwRBitMask = 0xFF;
|
||||
ddsd.ddpfPixelFormat.dwGBitMask = 0xFF00;
|
||||
ddsd.ddpfPixelFormat.dwBBitMask = 0xFF0000;
|
||||
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
|
||||
#endif
|
||||
|
||||
DXCheck(IDirectDraw_CreateSurface(dxc.pdd, &ddsd, &tex->dds, NULL));
|
||||
|
||||
tex->fogParams[0] = pic->fogParams[0];
|
||||
tex->fogParams[1] = pic->fogParams[1];
|
||||
tex->fogParams[2] = pic->fogParams[2];
|
||||
tex->fogParams[3] = pic->fogParams[3];
|
||||
|
||||
buf = pic->buffer;
|
||||
bufend = pic->buffer + pic->size; // total image size include all the layers, cube sides, mipmaps
|
||||
normalMap = FBitSet(tex->flags, TF_NORMALMAP) ? true : false;
|
||||
|
||||
if (Q_max(1, pic->numMips) > 1) // not-compressed DDS
|
||||
{
|
||||
//TEMP
|
||||
j = 0;
|
||||
//for (j = 0; j < Q_max(1, pic->numMips); j++)
|
||||
{
|
||||
// track the buffer bounds
|
||||
if (buf != NULL && buf >= bufend)
|
||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
||||
|
||||
width = Q_max(1, (tex->width >> j));
|
||||
height = Q_max(1, (tex->height >> j));
|
||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
||||
GL_TextureImageRAW(tex, width, height, pic->type, buf);
|
||||
buf += size; // move pointer
|
||||
tex->numMips++;
|
||||
}
|
||||
}
|
||||
else // RGBA32
|
||||
{
|
||||
// track the buffer bounds
|
||||
if (buf != NULL && buf >= bufend)
|
||||
gEngfuncs.Host_Error("%s: %s image buffer overflow\n", __func__, tex->name);
|
||||
|
||||
int mipCount = GL_CalcMipmapCount(tex, (buf != NULL));
|
||||
|
||||
// NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides
|
||||
if (((pic->width != tex->width) || (pic->height != tex->height)))
|
||||
data = GL_ResampleTexture(buf, pic->width, pic->height, tex->width, tex->height, normalMap);
|
||||
else data = buf;
|
||||
|
||||
//if (!ImageCompressed(pic->type) && !FBitSet(tex->flags, TF_NOMIPMAP) && FBitSet(pic->flags, IMAGE_ONEBIT_ALPHA))
|
||||
// data = GL_ApplyFilter(data, tex->width, tex->height);
|
||||
|
||||
// mips will be auto-generated if desired
|
||||
for (j = 0; j < mipCount; j++)
|
||||
{
|
||||
width = Q_max(1, (tex->width >> j));
|
||||
height = Q_max(1, (tex->height >> j));
|
||||
size = gEngfuncs.Image_CalcImageSize(pic->type, width, height, 1);
|
||||
GL_TextureImageRAW(tex, width, height, pic->type, data);
|
||||
//if (mipCount > 1)
|
||||
// GL_BuildMipMap(data, width, height, tex->depth, tex->flags);
|
||||
tex->numMips++;
|
||||
}
|
||||
}
|
||||
|
||||
SetBits(tex->flags, TF_IMG_UPLOADED); // done
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int GL_LoadTextureFromBuffer(const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update)
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
|
||||
if (!GL_CheckTexName(name))
|
||||
return 0;
|
||||
|
||||
// see if already loaded
|
||||
if ((tex = GL_TextureForName(name)) && !update)
|
||||
return (tex - dx_textures);
|
||||
|
||||
// couldn't loading image
|
||||
if (!pic) return 0;
|
||||
|
||||
if (update)
|
||||
{
|
||||
if (tex == NULL)
|
||||
gEngfuncs.Host_Error("%s: couldn't find texture %s for update\n", __func__, name);
|
||||
SetBits(tex->flags, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// allocate the new one
|
||||
tex = GL_AllocTexture(name, flags);
|
||||
}
|
||||
|
||||
GL_ProcessImage(tex, pic);
|
||||
|
||||
if (!GL_UploadTexture(tex, pic))
|
||||
{
|
||||
memset(tex, 0, sizeof(dx_texture_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (tex - dx_textures);
|
||||
}
|
||||
|
||||
void GL_ProcessTexture(int texnum, float gamma, int topColor, int bottomColor)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void GetDetailScaleForTexture(int texture, float *xScale, float *yScale)
|
||||
{
|
||||
*xScale = *yScale = 1.0f;
|
||||
}
|
||||
|
||||
void GetExtraParmsForTexture(int texture, byte *red, byte *green, byte *blue, byte *alpha)
|
||||
{
|
||||
*red = *green = *blue = *alpha = 0;
|
||||
}
|
||||
|
||||
int GL_FindTexture(const char *name)
|
||||
{
|
||||
gEngfuncs.Con_Printf("GL_FindTexture(%s)\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *GL_TextureName(unsigned int texnum)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const byte *GL_TextureData(unsigned int texnum)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
|
||||
{
|
||||
dx_texture_t *tex;
|
||||
rgbdata_t *pic;
|
||||
uint picFlags = 0;
|
||||
|
||||
if (!GL_CheckTexName(name))
|
||||
return 0;
|
||||
|
||||
// see if already loaded
|
||||
if ((tex = GL_TextureForName(name)))
|
||||
return (tex - dx_textures);
|
||||
|
||||
gEngfuncs.Con_Printf("GL_LoadTexture(%s, %p, %zu, %X)\n", name, buf, size, flags);
|
||||
|
||||
if (FBitSet(flags, TF_NOFLIP_TGA))
|
||||
SetBits(picFlags, IL_DONTFLIP_TGA);
|
||||
|
||||
if (FBitSet(flags, TF_KEEP_SOURCE) && !FBitSet(flags, TF_EXPAND_SOURCE))
|
||||
SetBits(picFlags, IL_KEEP_8BIT);
|
||||
|
||||
// set some image flags
|
||||
gEngfuncs.Image_SetForceFlags(picFlags);
|
||||
|
||||
pic = gEngfuncs.FS_LoadImage(name, buf, size);
|
||||
if (!pic) return 0; // couldn't loading image
|
||||
|
||||
// allocate the new one
|
||||
tex = GL_AllocTexture(name, flags);
|
||||
GL_ProcessImage(tex, pic);
|
||||
|
||||
if (!GL_UploadTexture(tex, pic))
|
||||
{
|
||||
memset(tex, 0, sizeof(dx_texture_t));
|
||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
||||
return 0;
|
||||
}
|
||||
|
||||
//GL_ApplyTextureParams(tex); // update texture filter, wrap etc
|
||||
gEngfuncs.FS_FreeImage(pic); // release source texture
|
||||
|
||||
// NOTE: always return texnum as index in array or engine will stop work !!!
|
||||
return tex - dx_textures;
|
||||
}
|
||||
|
||||
int GL_CreateTexture(const char *name, int width, int height, const void *buffer, texFlags_t flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GL_LoadTextureArray(const char **names, int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GL_CreateTextureArray(const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GL_FreeTexture(unsigned int texnum)
|
||||
{
|
||||
if (texnum <= 0 || texnum >= MAX_TEXTURES)
|
||||
return;
|
||||
|
||||
gEngfuncs.Con_Printf("GL_FreeTexture(%d) %s\n", texnum, dx_textures[texnum].name);
|
||||
}
|
||||
|
||||
void R_OverrideTextureSourceSize(unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight)
|
||||
{
|
||||
|
||||
}
|
||||
220
ref/dx2/r_local.h
Normal file
220
ref/dx2/r_local.h
Normal file
@@ -0,0 +1,220 @@
|
||||
#pragma once
|
||||
|
||||
#include "const.h"
|
||||
#include "cvardef.h"
|
||||
#include "ref_api.h"
|
||||
#include "render_api.h"
|
||||
#include "com_image.h"
|
||||
|
||||
#define DIRECTDRAW_VERSION 0x0200
|
||||
#define DIRECT3D_VERSION 0x0500//D3DCOLORMODEL bug
|
||||
#include <ddraw.h>
|
||||
#include <d3d.h>
|
||||
|
||||
extern ref_api_t gEngfuncs;
|
||||
|
||||
extern poolhandle_t r_temppool;
|
||||
|
||||
|
||||
#define MAX_TEXTURES 8192
|
||||
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
|
||||
|
||||
// refparams
|
||||
#define RP_NONE 0
|
||||
#define RP_ENVVIEW BIT( 0 ) // used for cubemapshot
|
||||
#define RP_OLDVIEWLEAF BIT( 1 )
|
||||
#define RP_CLIPPLANE BIT( 2 )
|
||||
|
||||
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||
|
||||
typedef struct dx_texture_s
|
||||
{
|
||||
char name[256]; // game path, including extension (can be store image programs)
|
||||
word srcWidth; // keep unscaled sizes
|
||||
word srcHeight;
|
||||
word width; // upload width\height
|
||||
word height;
|
||||
|
||||
byte numMips; // mipmap count
|
||||
|
||||
int used;
|
||||
texFlags_t flags;
|
||||
rgba_t fogParams; // some water textures
|
||||
// contain info about underwater fog
|
||||
rgbdata_t *original; // keep original image
|
||||
#if 0
|
||||
word depth; // texture depth or count of layers for 2D_ARRAY
|
||||
|
||||
GLuint target; // glTarget
|
||||
GLuint texnum; // gl texture binding
|
||||
GLint format; // uploaded format
|
||||
|
||||
// debug info
|
||||
size_t size; // upload size for debug targets
|
||||
|
||||
// detail textures stuff
|
||||
float xscale;
|
||||
float yscale;
|
||||
|
||||
#endif
|
||||
IDirectDrawSurface *dds;
|
||||
uint hashValue;
|
||||
struct dx_texture_s *nextHash;
|
||||
} dx_texture_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int params; // rendering parameters
|
||||
|
||||
qboolean drawWorld; // ignore world for drawing PlayerModel
|
||||
qboolean isSkyVisible; // sky is visible
|
||||
qboolean onlyClientDraw; // disabled by client request
|
||||
qboolean drawOrtho; // draw world as orthogonal projection
|
||||
|
||||
float fov_x, fov_y; // current view fov
|
||||
|
||||
cl_entity_t *currententity;
|
||||
model_t *currentmodel;
|
||||
cl_entity_t *currentbeam; // same as above but for beams
|
||||
|
||||
int viewport[4];
|
||||
//gl_frustum_t frustum;
|
||||
|
||||
mleaf_t *viewleaf;
|
||||
mleaf_t *oldviewleaf;
|
||||
vec3_t pvsorigin;
|
||||
vec3_t vieworg; // locked vieworigin
|
||||
vec3_t viewangles;
|
||||
vec3_t vforward;
|
||||
vec3_t vright;
|
||||
vec3_t vup;
|
||||
|
||||
vec3_t cullorigin;
|
||||
vec3_t cull_vforward;
|
||||
vec3_t cull_vright;
|
||||
vec3_t cull_vup;
|
||||
|
||||
float farClip;
|
||||
|
||||
qboolean fogCustom;
|
||||
qboolean fogEnabled;
|
||||
qboolean fogSkybox;
|
||||
vec4_t fogColor;
|
||||
float fogDensity;
|
||||
float fogStart;
|
||||
float fogEnd;
|
||||
int cached_contents; // in water
|
||||
int cached_waterlevel; // was in water
|
||||
|
||||
float skyMins[2][SKYBOX_MAX_SIDES];
|
||||
float skyMaxs[2][SKYBOX_MAX_SIDES];
|
||||
|
||||
matrix4x4 objectMatrix; // currententity matrix
|
||||
matrix4x4 worldviewMatrix; // modelview for world
|
||||
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
|
||||
|
||||
matrix4x4 projectionMatrix;
|
||||
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
|
||||
byte visbytes[( MAX_MAP_LEAFS + 7 ) / 8];// actual PVS for current frame
|
||||
|
||||
float viewplanedist;
|
||||
mplane_t clipPlane;
|
||||
} ref_instance_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
|
||||
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
|
||||
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
|
||||
uint num_solid_entities;
|
||||
uint num_trans_entities;
|
||||
uint num_beam_entities;
|
||||
} draw_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int defaultTexture; // use for bad textures
|
||||
int particleTexture;
|
||||
int whiteTexture;
|
||||
int grayTexture;
|
||||
int blackTexture;
|
||||
int cinTexture; // cinematic texture
|
||||
// entity lists
|
||||
draw_list_t draw_stack[MAX_DRAW_STACK];
|
||||
int draw_stack_pos;
|
||||
draw_list_t *draw_list;
|
||||
|
||||
int realframecount; // not including viewpasses
|
||||
int framecount;
|
||||
|
||||
qboolean fCustomRendering;
|
||||
qboolean fResetVis;
|
||||
|
||||
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
||||
|
||||
// get from engine
|
||||
cl_entity_t *entities;
|
||||
uint max_entities;
|
||||
} gl_globals_t;
|
||||
|
||||
extern gl_globals_t tr;
|
||||
|
||||
struct dx_context_s
|
||||
{
|
||||
HWND window;
|
||||
int windowWidth;
|
||||
int windowHeight;
|
||||
IDirectDraw *pdd;
|
||||
IDirectDrawSurface *pddsPrimary;
|
||||
IDirectDrawSurface *pddsBack;
|
||||
IDirectDrawClipper *pddClipper;
|
||||
IDirectDrawClipper *pddBackClipper;
|
||||
|
||||
int renderMode;
|
||||
};
|
||||
typedef struct dx_context_s dx_context_t;
|
||||
|
||||
extern dx_context_t dxc;
|
||||
|
||||
const char *dxResultToStr( HRESULT r );
|
||||
|
||||
#define DXCheck(CALL) {\
|
||||
HRESULT r = CALL;\
|
||||
if (r != DD_OK)\
|
||||
gEngfuncs.Con_Printf( S_ERROR "%s:%d: DirectX error %X(%d 0x%X %d) %s at \"" #CALL "\"\n", __FUNCTION__, __LINE__, r, ( r >> 31 ) & 1, ( r >> 16 ) & 0x7FFF, r & 0xFFFF, dxResultToStr( r ) ); \
|
||||
}
|
||||
|
||||
void GL_SetRenderMode( int mode );
|
||||
|
||||
//r_image.c
|
||||
void R_InitImages( void );
|
||||
dx_texture_t *R_GetTexture( unsigned int texnum );
|
||||
|
||||
void R_ShowTextures( void );
|
||||
const byte *R_GetTextureOriginalBuffer( unsigned int idx );
|
||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
|
||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
|
||||
void GetDetailScaleForTexture( int texture, float *xScale, float *yScale );
|
||||
void GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *alpha );
|
||||
int GL_FindTexture( const char *name );
|
||||
const char *GL_TextureName( unsigned int texnum );
|
||||
const byte *GL_TextureData( unsigned int texnum );
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||
int GL_LoadTextureArray( const char **names, int flags );
|
||||
int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
|
||||
void GL_FreeTexture( unsigned int texnum );
|
||||
void R_OverrideTextureSourceSize( unsigned int textnum, unsigned int srcWidth, unsigned int srcHeight );
|
||||
|
||||
//
|
||||
// engine shared convars
|
||||
//
|
||||
DECLARE_ENGINE_SHARED_CVAR_LIST( )
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
18
ref/dx2/wscript
Normal file
18
ref/dx2/wscript
Normal file
@@ -0,0 +1,18 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# mittorn, 2018
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
|
||||
def build(bld):
|
||||
bld.shlib(
|
||||
source = ['r_context.c', 'r_image.c'],
|
||||
target = 'ref_dx2',
|
||||
defines = 'REF_DLL',
|
||||
use = 'engine_includes sdk_includes werror public USER32 DDRAW',
|
||||
install_path = bld.env.LIBDIR
|
||||
)
|
||||
Reference in New Issue
Block a user