ref_dx2 (WIP)

This commit is contained in:
lewa_j
2025-12-08 00:34:23 +03:00
parent 5daf686a82
commit d414eeb246
5 changed files with 2018 additions and 0 deletions

19
ref/dx2/dllmain.cpp Normal file
View 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

File diff suppressed because it is too large Load Diff

722
ref/dx2/r_image.c Normal file
View 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
View 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
View 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
)