Merge branch 'opengl-new-patch-features-support' into 'master'

OpenGL new patch features support (part 1: flipping)

See merge request STJr/SRB2Internal!211
This commit is contained in:
Monster Iestyn 2019-04-11 15:32:06 -04:00
commit 6d702b86c2
1 changed files with 328 additions and 135 deletions

View File

@ -41,37 +41,316 @@ static INT32 blocksize, blockwidth, blockheight;
INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes
INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole
// sprite, use alpha and chroma key for hole
static const INT32 format2bpp[16] =
{
0, //0
0, //1
1, //2 GR_TEXFMT_ALPHA_8
1, //3 GR_TEXFMT_INTENSITY_8
1, //4 GR_TEXFMT_ALPHA_INTENSITY_44
1, //5 GR_TEXFMT_P_8
4, //6 GR_RGBA
0, //7
0, //8
0, //9
2, //10 GR_TEXFMT_RGB_565
2, //11 GR_TEXFMT_ARGB_1555
2, //12 GR_TEXFMT_ARGB_4444
2, //13 GR_TEXFMT_ALPHA_INTENSITY_88
2, //14 GR_TEXFMT_AP_88
};
// This code was originally placed directly in HWR_DrawPatchInCache.
// It is now split from it for my sanity! (and the sanity of others)
// -- Monster Iestyn (13/02/19)
static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap,
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp)
{
fixed_t yfrac, position, count;
UINT8 *dest;
const UINT8 *source;
INT32 topdelta, prevdelta = -1;
INT32 originy = 0;
// for writing a pixel to dest
RGBA_t colortemp;
UINT8 alpha;
UINT8 texel;
UINT16 texelu16;
(void)patchheight; // This parameter is unused
if (originPatch) // originPatch can be NULL here, unlike in the software version
originy = originPatch->originy;
while (patchcol->topdelta != 0xff)
{
topdelta = patchcol->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
source = (const UINT8 *)patchcol + 3;
count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS;
position = originy + topdelta;
yfrac = 0;
//yfracstep = (patchcol->length << FRACBITS) / count;
if (position < 0)
{
yfrac = -position<<FRACBITS;
count += (((position * scale_y) + (FRACUNIT/2)) >> FRACBITS);
position = 0;
}
position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS;
if (position < 0)
position = 0;
if (position + count >= pblockheight)
count = pblockheight - position;
dest = block + (position*blockmodulo);
while (count > 0)
{
count--;
texel = source[yfrac>>FRACBITS];
if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel))
alpha = 0x80;
else
alpha = 0xff;
//Hurdler: not perfect, but better than holes
if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED))
texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX;
//Hurdler: 25/04/2000: now support colormap in hardware mode
else if (mipmap->colormap)
texel = mipmap->colormap[texel];
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
break;
}
dest += blockmodulo;
yfrac += yfracstep;
}
patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4);
}
}
static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap,
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp)
{
fixed_t yfrac, position, count;
UINT8 *dest;
const UINT8 *source;
INT32 topdelta, prevdelta = -1;
INT32 originy = 0;
// for writing a pixel to dest
RGBA_t colortemp;
UINT8 alpha;
UINT8 texel;
UINT16 texelu16;
if (originPatch) // originPatch can be NULL here, unlike in the software version
originy = originPatch->originy;
while (patchcol->topdelta != 0xff)
{
topdelta = patchcol->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
topdelta = patchheight-patchcol->length-topdelta;
source = (const UINT8 *)patchcol + 3;
count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS;
position = originy + topdelta;
yfrac = (patchcol->length-1) << FRACBITS;
if (position < 0)
{
yfrac += position<<FRACBITS;
count += (((position * scale_y) + (FRACUNIT/2)) >> FRACBITS);
position = 0;
}
position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS;
if (position < 0)
position = 0;
if (position + count >= pblockheight)
count = pblockheight - position;
dest = block + (position*blockmodulo);
while (count > 0)
{
count--;
texel = source[yfrac>>FRACBITS];
if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel))
alpha = 0x80;
else
alpha = 0xff;
//Hurdler: not perfect, but better than holes
if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED))
texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX;
//Hurdler: 25/04/2000: now support colormap in hardware mode
else if (mipmap->colormap)
texel = mipmap->colormap[texel];
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
break;
}
dest += blockmodulo;
yfrac -= yfracstep;
}
patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4);
}
}
// Simplified patch caching function
// for use by sprites and other patches that are not part of a wall texture
// no alpha or flipping should be present since we do not want non-texture graphics to have them
// no offsets are used either
// -- Monster Iestyn (13/02/19)
static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight, INT32 blockmodulo,
INT32 ptexturewidth, INT32 ptextureheight,
INT32 originx, INT32 originy, // where to draw patch in surface block
const patch_t *realpatch, INT32 bpp)
INT32 pblockwidth, INT32 pblockheight,
INT32 pwidth, INT32 pheight,
const patch_t *realpatch)
{
INT32 ncols;
fixed_t xfrac, xfracstep;
fixed_t yfracstep, scale_y;
const column_t *patchcol;
UINT8 *block = mipmap->grInfo.data;
INT32 bpp;
INT32 blockmodulo;
if (pwidth <= 0 || pheight <= 0)
return;
ncols = (pwidth * pblockwidth) / pwidth;
// source advance
xfrac = 0;
xfracstep = (pwidth << FRACBITS) / pblockwidth;
yfracstep = (pheight << FRACBITS) / pblockheight;
scale_y = (pblockheight << FRACBITS) / pheight;
bpp = format2bpp[mipmap->grInfo.format];
if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp?
blockmodulo = blockwidth*bpp;
// Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep)
{
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS]));
HWR_DrawColumnInCache(patchcol, block, mipmap,
pblockheight, blockmodulo,
yfracstep, scale_y,
NULL, pheight, // not that pheight is going to get used anyway...
bpp);
}
}
// This function we use for caching patches that belong to textures
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight,
texture_t *texture, texpatch_t *patch,
const patch_t *realpatch)
{
INT32 x, x1, x2;
INT32 col, ncols;
fixed_t xfrac, xfracstep;
fixed_t yfrac, yfracstep, position, count;
fixed_t scale_y;
RGBA_t colortemp;
UINT8 *dest;
const UINT8 *source;
fixed_t yfracstep, scale_y;
const column_t *patchcol;
UINT8 alpha;
UINT8 *block = mipmap->grInfo.data;
UINT8 texel;
UINT16 texelu16;
INT32 bpp;
INT32 blockmodulo;
INT32 width, height;
// Column drawing function pointer.
static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap,
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp);
if (!ptexturewidth)
if (texture->width <= 0 || texture->height <= 0)
return;
x1 = originx;
x2 = x1 + SHORT(realpatch->width);
/*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then.
continue;
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache;
}
else*/
{
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
}
if (x1 > ptexturewidth || x2 < 0)
x1 = patch->originx;
width = SHORT(realpatch->width);
height = SHORT(realpatch->height);
x2 = x1 + width;
if (x1 > texture->width || x2 < 0)
return; // patch not located within texture's x bounds, ignore
if (originy > ptextureheight || (originy + SHORT(realpatch->height)) < 0)
if (patch->originy > texture->height || (patch->originy + height) < 0)
return; // patch not located within texture's y bounds, ignore
// patch is actually inside the texture!
@ -84,19 +363,18 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
x = x1;
// right edge
if (x2 > ptexturewidth)
x2 = ptexturewidth;
if (x2 > texture->width)
x2 = texture->width;
col = x * pblockwidth / ptexturewidth;
ncols = ((x2 - x) * pblockwidth) / ptexturewidth;
col = x * pblockwidth / texture->width;
ncols = ((x2 - x) * pblockwidth) / texture->width;
/*
CONS_Debug(DBG_RENDER, "patch %dx%d texture %dx%d block %dx%d\n", SHORT(realpatch->width),
SHORT(realpatch->height),
ptexturewidth,
textureheight,
pblockwidth,pblockheight);
CONS_Debug(DBG_RENDER, "patch %dx%d texture %dx%d block %dx%d\n",
width, height,
texture->width, texture->height,
pblockwidth, pblockheight);
CONS_Debug(DBG_RENDER, " col %d ncols %d x %d\n", col, ncols, x);
*/
@ -105,90 +383,31 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
if (x1 < 0)
xfrac = -x1<<FRACBITS;
xfracstep = (ptexturewidth << FRACBITS) / pblockwidth;
yfracstep = (ptextureheight<< FRACBITS) / pblockheight;
xfracstep = (texture->width << FRACBITS) / pblockwidth;
yfracstep = (texture->height<< FRACBITS) / pblockheight;
scale_y = (pblockheight << FRACBITS) / texture->height;
bpp = format2bpp[mipmap->grInfo.format];
if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp?
blockmodulo = blockwidth*bpp;
// Draw each column to the block cache
for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep)
{
INT32 topdelta, prevdelta = -1;
patchcol = (const column_t *)((const UINT8 *)realpatch
+ LONG(realpatch->columnofs[xfrac>>FRACBITS]));
if (patch->flip & 1)
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[(width-1)-(xfrac>>FRACBITS)]));
else
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS]));
scale_y = (pblockheight << FRACBITS) / ptextureheight;
while (patchcol->topdelta != 0xff)
{
topdelta = patchcol->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
source = (const UINT8 *)patchcol + 3;
count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS;
position = originy + topdelta;
yfrac = 0;
//yfracstep = (patchcol->length << FRACBITS) / count;
if (position < 0)
{
yfrac = -position<<FRACBITS;
count += (((position * scale_y) + (FRACUNIT/2)) >> FRACBITS);
position = 0;
}
position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS;
if (position < 0)
position = 0;
if (position + count >= pblockheight)
count = pblockheight - position;
dest = block + (position*blockmodulo);
while (count > 0)
{
count--;
texel = source[yfrac>>FRACBITS];
if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel))
alpha = 0x80;
else
alpha = 0xff;
//Hurdler: not perfect, but better than holes
if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED))
texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX;
//Hurdler: 25/04/2000: now support colormap in hardware mode
else if (mipmap->colormap)
texel = mipmap->colormap[texel];
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
break;
}
dest += blockmodulo;
yfrac += yfracstep;
}
patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4);
}
ColumnDrawerPointer(patchcol, block, mipmap,
pblockheight, blockmodulo,
yfracstep, scale_y,
patch, height,
bpp);
}
}
@ -349,26 +568,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
//CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight);
}
static const INT32 format2bpp[16] =
{
0, //0
0, //1
1, //2 GR_TEXFMT_ALPHA_8
1, //3 GR_TEXFMT_INTENSITY_8
1, //4 GR_TEXFMT_ALPHA_INTENSITY_44
1, //5 GR_TEXFMT_P_8
4, //6 GR_RGBA
0, //7
0, //8
0, //9
2, //10 GR_TEXFMT_RGB_565
2, //11 GR_TEXFMT_ARGB_1555
2, //12 GR_TEXFMT_ARGB_4444
2, //13 GR_TEXFMT_ALPHA_INTENSITY_88
2, //14 GR_TEXFMT_AP_88
};
static UINT8 *MakeBlock(GLMipmap_t *grMipmap)
{
UINT8 *block;
@ -452,13 +651,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
HWR_DrawPatchInCache(&grtex->mipmap,
HWR_DrawTexturePatchInCache(&grtex->mipmap,
blockwidth, blockheight,
blockwidth*format2bpp[grtex->mipmap.grInfo.format],
texture->width, texture->height,
patch->originx, patch->originy,
realpatch,
format2bpp[grtex->mipmap.grInfo.format]);
texture, patch,
realpatch);
Z_Unlock(realpatch);
}
//Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :(
@ -545,11 +741,8 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
HWR_DrawPatchInCache(grMipmap,
newwidth, newheight,
blockwidth*format2bpp[grMipmap->grInfo.format],
grPatch->width, grPatch->height,
0, 0,
patch,
format2bpp[grMipmap->grInfo.format]);
patch);
}
grPatch->max_s = (float)newwidth / (float)blockwidth;