Implement V_DrawIntoPatchRGBA

This commit is contained in:
Lactozilla 2023-11-01 20:39:02 -03:00
parent 9d6cb93127
commit 5a89823cc6
7 changed files with 528 additions and 113 deletions

View file

@ -262,7 +262,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
INT32 pwidth, INT32 pheight,
const patch_t *realpatch)
{
if (pwidth <= 0 || pheight <= 0)
if (pwidth <= 0 || pheight <= 0 || realpatch->columns == NULL)
return;
// source advance
@ -547,7 +547,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
}
// patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
void HWR_MakePatch (patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{
if (grMipmap->width == 0)
{

View file

@ -42,7 +42,7 @@ void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_MakePatch(patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);

View file

@ -330,13 +330,15 @@ static int lib_patch_setPixel(lua_State *L)
UINT32 pixel = (UINT32)color;
Patch_SetPixel(patch, &pixel, PICFMT_FLAT32, x, y, true);
}
else if (color >= 0 && color <= 0xFF)
{
UINT16 pixel_u8 = (UINT8)color;
Patch_SetPixel(patch, &pixel_u8, PICFMT_FLAT, x, y, true);
}
else
{
UINT16 pixel = 0x0000;
if (color >= 0 && color <= 0xFF)
pixel = 0xFF00 | (UINT8)color;
Patch_SetPixel(patch, &pixel, PICFMT_FLAT16, x, y, true);
UINT16 empty_px = 0x0000;
Patch_SetPixel(patch, &empty_px, PICFMT_FLAT16, x, y, true);
}
return 0;
@ -487,12 +489,7 @@ static int lib_patch_copy(lua_State *L)
}
else
{
if (patch->format == PATCH_FORMAT_RGBA)
{
// Unimplemented
}
else
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, copy_transparent);
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, copy_transparent);
}
return 0;

View file

@ -46,6 +46,8 @@ sprcache_t *spritecachedinfo;
lighttable_t *colormaps;
lighttable_t *fadecolormap;
colorlookup_t r_colorlookup;
// for debugging/info purposes
size_t flatmemory, spritememory, texturememory;
@ -53,51 +55,42 @@ size_t flatmemory, spritememory, texturememory;
INT16 color8to16[256]; // remap color index to highcolor rgb value
INT16 *hicolormaps; // test a 32k colormap remaps high -> high
// Blends two pixels together, using the equation
// that matches the specified alpha style.
// Blends two pixels together, using the equation that matches the specified alpha style.
UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{
RGBA_t output;
INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
#define clamp(c) max(min((c), 0xFF), 0x00)
if (style == AST_TRANSLUCENT)
{
if (fullalpha <= 0)
output.rgba = background.rgba;
else
{
// don't go too high
if (fullalpha >= 0xFF)
fullalpha = 0xFF;
alpha = (UINT8)fullalpha;
// if the background pixel is empty,
// match software and don't blend anything
if (!background.s.alpha)
{
// ...unless the foreground pixel ISN'T actually translucent.
if (alpha == 0xFF)
output.rgba = foreground.rgba;
else
output.rgba = 0;
}
else
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = 0xFF;
}
UINT8 beta = 0xFF - alpha;
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = clamp(((INT16)background.s.alpha) + fullalpha);
}
return output.rgba;
}
#define clamp(c) max(min(c, 0xFF), 0x00);
else
{
float falpha = ((float)alpha / 256.0f);
float falpha = ((float)alpha / 255.0f);
float fr = ((float)foreground.s.red * falpha);
float fg = ((float)foreground.s.green * falpha);
float fb = ((float)foreground.s.blue * falpha);
if (background.s.alpha == 0x00)
output.s.alpha = clamp(fullalpha);
else
output.s.alpha = 0xFF;
if (style == AST_ADD)
{
output.s.red = clamp((int)(background.s.red + fr));
@ -118,9 +111,9 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph
}
else if (style == AST_MODULATE)
{
fr = ((float)foreground.s.red / 256.0f);
fg = ((float)foreground.s.green / 256.0f);
fb = ((float)foreground.s.blue / 256.0f);
fr = ((float)foreground.s.red / 255.0f);
fg = ((float)foreground.s.green / 255.0f);
fb = ((float)foreground.s.blue / 255.0f);
output.s.red = clamp((int)(background.s.red * fr));
output.s.green = clamp((int)(background.s.green * fg));
output.s.blue = clamp((int)(background.s.blue * fb));
@ -128,12 +121,49 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph
// just copy the pixel
else if (style == AST_COPY)
output.rgba = foreground.rgba;
output.s.alpha = 0xFF;
return output.rgba;
}
#undef clamp
return 0;
return output.rgba;
}
static UINT32 BlendPixelForTexture(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{
RGBA_t output;
if (style == AST_TRANSLUCENT)
{
INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
if (fullalpha <= 0)
output.rgba = background.rgba;
else
{
// don't go too high
if (fullalpha >= 0xFF)
fullalpha = 0xFF;
alpha = (UINT8)fullalpha;
// if the background pixel is empty, match software and don't blend anything
if (!background.s.alpha)
{
// ...unless the foreground pixel ISN'T actually translucent.
if (alpha == 0xFF)
output.rgba = foreground.rgba;
else
output.rgba = 0;
}
else
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = 0xFF;
}
}
return output.rgba;
}
return ASTBlendPixel(background, foreground, style, alpha);
}
INT32 ASTTextureBlendingThreshold[2] = {255/11, (10*255/11)};
@ -151,13 +181,13 @@ UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UIN
if (alpha < ASTTextureBlendingThreshold[0])
return background.rgba;
return ASTBlendPixel(background, foreground, style, alpha);
return BlendPixelForTexture(background, foreground, style, alpha);
}
else // just copy the pixel
return foreground.rgba;
}
else
return ASTBlendPixel(background, foreground, style, alpha);
return BlendPixelForTexture(background, foreground, style, alpha);
}
// Blends two palette indexes for a texture patch, then
@ -189,18 +219,16 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
// just copy the pixel
else if (style == AST_COPY)
return foreground;
// use ASTBlendPixel for all other blend modes
// and find the nearest colour in the palette
// use ASTBlendPixel for all other blend modes and find the nearest color in the palette
else if (style != AST_TRANSLUCENT)
{
RGBA_t texel;
RGBA_t bg = V_GetMasterColor(background);
RGBA_t fg = V_GetMasterColor(foreground);
texel.rgba = ASTBlendPixel(bg, fg, style, alpha);
texel.rgba = BlendPixelForTexture(bg, fg, style, alpha);
return NearestColor(texel.s.red, texel.s.green, texel.s.blue);
}
// fallback if all above fails, somehow
// return the background pixel
return background;
}

View file

@ -404,9 +404,6 @@ void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
if (x < 0 || x >= patch->width || y < 0 || y >= patch->height)
return NULL;
if (Patch_NeedsUpdate(patch, true))
Patch_DoDynamicUpdate(patch, true);
if (patch->format == PATCH_FORMAT_RGBA)
{
// Well, that makes it easy
@ -415,9 +412,6 @@ void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
}
else
{
if (patch->columns == NULL)
return NULL;
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
if (pixels_opaque)
{
@ -430,6 +424,12 @@ void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
}
}
if (Patch_NeedsUpdate(patch, true))
Patch_DoDynamicUpdate(patch, true);
if (patch->columns == NULL)
return NULL;
column_t *column = &patch->columns[x];
for (unsigned i = 0; i < column->num_posts; i++)
@ -509,25 +509,26 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
size_t position = (x * patch->height) + y;
if (patch->format == PATCH_FORMAT_RGBA)
{
size_t position = (x * patch->height) + y;
RGBA_t *dest = (RGBA_t*)(&patch->pixels[position * 4]);
if (!pixel_is_opaque)
{
if (transparent_overwrite)
{
// No longer a pixel in this position, so columns need to be rebuilt
dest->s.alpha = 0;
dpatch->update_columns = true;
dpatch->is_dirty = true;
// No longer a pixel in this position, so columns need to be rebuilt
dpatch->update_columns = true;
}
}
else
{
// No pixel in this position, so columns need to be rebuilt
// No longer a pixel in this position, so columns need to be rebuilt
if (dest->s.alpha == 0)
dpatch->update_columns = true;
@ -538,21 +539,20 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
}
else
{
size_t position = (x * patch->height) + y;
if (!pixel_is_opaque)
{
if (transparent_overwrite)
{
// No longer a pixel in this position, so columns need to be rebuilt
unset_bit_array(dpatch->pixels_opaque, position);
dpatch->update_columns = true;
dpatch->is_dirty = true;
// No longer a pixel in this position, so columns need to be rebuilt
dpatch->update_columns = true;
}
}
else
{
// No pixel in this position, so columns need to be rebuilt
// No longer a pixel in this position, so columns need to be rebuilt
if (!in_bit_array(dpatch->pixels_opaque, position))
{
set_bit_array(dpatch->pixels_opaque, position);
@ -771,11 +771,6 @@ void Patch_DoDynamicUpdate(patch_t *patch, boolean update_columns)
return;
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
if (!dpatch->is_dirty)
return;
if (patch->columns == NULL)
Patch_InitDynamicColumns(patch);
if (Patch_CheckDirtyRect(dpatch))
{
@ -787,6 +782,9 @@ void Patch_DoDynamicUpdate(patch_t *patch, boolean update_columns)
if (update_columns && dpatch->update_columns && Patch_CheckDirtyColumns(dpatch))
{
if (patch->columns == NULL)
Patch_InitDynamicColumns(patch);
for (INT32 x = dpatch->column_dirty[0]; x < dpatch->column_dirty[1]; x++)
Patch_RebuildColumn(patch, x, dpatch->pixels_opaque);

View file

@ -479,6 +479,8 @@ static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5};
static const UINT8 *v_colormap = NULL;
static const UINT8 *v_translevel = NULL;
static UINT8 v_opacity;
static UINT32 v_blendmode;
static inline UINT8 standardpdraw(const UINT8 *dest, const UINT8 *source, fixed_t ofs)
{
@ -497,7 +499,109 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix
return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff));
}
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
// input 8bpp output 8bpp
static void standardpdraw_i8o8(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT8 *d = (UINT8 *)dest;
*d = *s;
}
static void mappedpdraw_i8o8(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT8 *d = (UINT8 *)dest;
*d = *(v_colormap + *s);
}
static void translucentpdraw_i8o8(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT8 *d = (UINT8 *)dest;
*d = *(v_translevel + ((*s<<8)&0xff00) + (*d&0xff));
}
static void transmappedpdraw_i8o8(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT8 *d = (UINT8 *)dest;
*d = *(v_translevel + (((*(v_colormap + *s))<<8)&0xff00) + (*d&0xff));
}
// input 8bpp output 32bpp
static void standardpdraw_i8o32(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
RGBA_t *d = (RGBA_t *)dest;
*d = pMasterPalette[*s];
}
static void mappedpdraw_i8o32(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
RGBA_t *d = (RGBA_t *)dest;
*d = pMasterPalette[*(v_colormap + *s)];
}
static void translucentpdraw_i8o32(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT32 *d = (UINT32 *)dest;
*d = ASTBlendPixel(*(RGBA_t *)d, pMasterPalette[*s], v_blendmode, v_opacity);
}
static void transmappedpdraw_i8o32(void *dest, void *source)
{
UINT8 *s = (UINT8 *)source;
UINT32 *d = (UINT32 *)dest;
*d = ASTBlendPixel(*(RGBA_t *)d, pMasterPalette[*(v_colormap + *s)], v_blendmode, v_opacity);
}
// input 32bpp output 8bpp
static void standardpdraw_i32o8(void *dest, void *source)
{
RGBA_t src = *(RGBA_t *)source;
UINT8 *d = (UINT8 *)dest;
if (src.s.alpha != 0)
*d = GetColorLUT(&r_colorlookup, src.s.red, src.s.green, src.s.blue);
}
static void standardpdraw_ia32o8(void *dest, void *source)
{
RGBA_t src = *(RGBA_t *)source;
UINT8 *d = (UINT8 *)dest;
src.rgba = ASTBlendPixel(pMasterPalette[*d], src, AST_TRANSLUCENT, 255);
*d = GetColorLUT(&r_colorlookup, src.s.red, src.s.green, src.s.blue);
}
static void translucentpdraw_i32o8(void *dest, void *source)
{
RGBA_t src = *(RGBA_t *)source;
UINT8 *d = (UINT8 *)dest;
RGBA_t texel;
texel.rgba = ASTBlendPixel(pMasterPalette[*d], src, v_blendmode, v_opacity);
*d = GetColorLUT(&r_colorlookup, texel.s.red, texel.s.green, texel.s.blue);
// UINT8 idx = GetColorLUT(&r_colorlookup, src.s.red, src.s.green, src.s.blue);
// *d = *(v_translevel + ((idx<<8)&0xff00) + (*d&0xff));
}
// input 32bpp output 32bpp
static void standardpdraw_i32o32(void *dest, void *source)
{
RGBA_t *s = (RGBA_t *)source;
RGBA_t *d = (RGBA_t *)dest;
*d = *s;
}
#if 0
static void standardpdraw_ia32o32(void *dest, void *source)
{
RGBA_t *s = (RGBA_t *)source;
RGBA_t *d = (RGBA_t *)dest;
*d = ASTBlendPixel(*(RGBA_t *)d, *s, AST_TRANSLUCENT, 255);
}
#endif
static void translucentpdraw_i32o32(void *dest, void *source)
{
RGBA_t *s = (RGBA_t *)source;
UINT32 *d = (UINT32 *)dest;
*d = ASTBlendPixel(*(RGBA_t *)d, *s, v_blendmode, v_opacity);
}
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch);
static void AdjustPositionByOffsets(patch_t *patch, fixed_t pscale, fixed_t vscale, INT32 scrn, fixed_t *x, fixed_t *y)
{
@ -666,7 +770,7 @@ void V_DrawPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scr
if (patch->format == PATCH_FORMAT_RGBA)
{
V_DrawPatchRGBA(x, y, pscale, vscale, scrn, patch, colormap);
V_DrawPatchRGBA(x, y, pscale, vscale, scrn, patch);
return;
}
@ -816,9 +920,9 @@ void V_DrawPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scr
}
// Draws a patch scaled to arbitrary size.
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap)
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch)
{
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
void (*patchdrawfunc)(void*, void*);
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT32 blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT);
@ -826,24 +930,19 @@ static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale
INT32 dup;
column_t *column;
UINT8 *desttop, *dest, *deststart, *destend;
const RGBA_t *source;
RGBA_t *source;
const UINT8 *deststop;
fixed_t pwidth; // patch width
fixed_t offx = 0; // x offset
UINT8 perplayershuffle = 0;
static colorlookup_t colorlookup;
if (Patch_NeedsUpdate(patch, true))
Patch_DoDynamicUpdate(patch, true);
if (patch->columns == NULL || rendermode == render_none)
return;
patchdrawfunc = standardpdraw;
v_translevel = NULL;
if (alphalevel || blendmode)
{
if (alphalevel == 10) // V_HUDTRANSHALF
@ -856,18 +955,22 @@ static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale
if (alphalevel >= 10)
return; // invis
if (alphalevel || blendmode)
{
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
patchdrawfunc = translucentpdraw;
}
}
int alpha = (int)((float)(9 - alphalevel) * (255 / 9.0));
if (alpha < 0)
v_opacity = 0;
else if (alpha > 255)
v_opacity = 255;
else
v_opacity = (UINT8)alpha;
v_colormap = NULL;
if (colormap)
v_blendmode = blendmode+1;
patchdrawfunc = translucentpdraw_i32o8;
}
else
{
v_colormap = colormap;
patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
v_opacity = 255;
v_blendmode = 0;
patchdrawfunc = standardpdraw_ia32o8;
}
dup = vid.dup;
@ -900,7 +1003,7 @@ static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale
if (!desttop)
return;
InitColorLUT(&colorlookup, pMasterPalette, false);
InitColorLUT(&r_colorlookup, pMasterPalette, false);
deststop = desttop + vid.rowbytes * vid.height;
@ -929,7 +1032,7 @@ static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale
source = (RGBA_t*)column->pixels;
if (source->s.alpha)
{
UINT8 palidx = GetColorLUT(&colorlookup, source->s.red, source->s.green, source->s.blue);
UINT8 palidx = GetColorLUT(&r_colorlookup, source->s.red, source->s.green, source->s.blue);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, palidx);
}
}
@ -985,11 +1088,7 @@ static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale
for (ofs = 0; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length; ofs += rowfrac)
{
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
{
RGBA_t texel = source[ofs>>FRACBITS];
UINT8 palidx = GetColorLUT(&colorlookup, texel.s.red, texel.s.green, texel.s.blue);
*dest = patchdrawfunc(dest, &palidx, 0);
}
patchdrawfunc(dest, &source[ofs>>FRACBITS]);
dest += vid.width;
}
}
@ -1011,7 +1110,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
UINT8 perplayershuffle = 0;
if (patch->columns == NULL || rendermode == render_none)
if (rendermode == render_none)
return;
#ifdef HWRENDER
@ -1025,7 +1124,10 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
if (Patch_NeedsUpdate(patch, true))
Patch_DoDynamicUpdate(patch, true);
if (patch->columns == NULL || rendermode == render_none)
if (patch->columns == NULL)
return;
if (patch->format == PATCH_FORMAT_RGBA)
return;
patchdrawfunc = standardpdraw;
@ -1241,11 +1343,302 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
}
}
static void V_DrawIntoPatchRGBA(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 flags, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h, boolean copy_transparent)
{
if (dest_patch->type != PATCH_TYPE_DYNAMIC)
return;
dynamicpatch_t *dpatch = (dynamicpatch_t *)dest_patch;
boolean source_paletted = src_patch->format == PATCH_FORMAT_PALETTE;
if (source_paletted && Patch_NeedsUpdate(src_patch, true))
{
Patch_DoDynamicUpdate(src_patch, true);
if (src_patch->columns == NULL)
return;
}
if (sx < 0)
{
w += sx;
sx = 0;
}
if (sy < 0)
{
h += sy;
sy = 0;
}
if (sx >= src_patch->width << FRACBITS || w <= 0)
return;
if (sy >= src_patch->height << FRACBITS || h <= 0)
return;
void (*patchdrawfunc)(void*, void*) = NULL;
v_translevel = NULL;
v_colormap = NULL;
UINT32 alphalevel = ((flags & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT32 blendmode = ((flags & V_BLENDMASK) >> V_BLENDSHIFT);
if (alphalevel || blendmode)
{
if (alphalevel >= 10)
return;
int alpha = (int)((float)(9 - alphalevel) * (255 / 9.0));
if (alpha < 0)
v_opacity = 0;
else if (alpha > 255)
v_opacity = 255;
else
v_opacity = (UINT8)alpha;
v_blendmode = blendmode+1;
}
else
{
v_opacity = 255;
v_blendmode = 0;
}
if (source_paletted)
{
v_colormap = colormap;
if (dest_patch->format == PATCH_FORMAT_PALETTE)
{
if (alphalevel || blendmode)
{
v_translevel = R_GetBlendTable(v_blendmode, alphalevel);
patchdrawfunc = v_colormap ? transmappedpdraw_i8o8 : translucentpdraw_i8o8;
}
else
patchdrawfunc = v_colormap ? mappedpdraw_i8o8 : standardpdraw_i8o8;
}
else
{
if (alphalevel || blendmode)
patchdrawfunc = v_colormap ? transmappedpdraw_i8o32 : translucentpdraw_i8o32;
else
patchdrawfunc = v_colormap ? mappedpdraw_i8o32 : standardpdraw_i8o32;
}
}
else
{
if (dest_patch->format == PATCH_FORMAT_PALETTE)
{
if (alphalevel || blendmode)
patchdrawfunc = translucentpdraw_i32o8;
else
patchdrawfunc = standardpdraw_i32o8;
InitColorLUT(&r_colorlookup, pMasterPalette, false);
}
else
{
if (alphalevel || blendmode)
patchdrawfunc = translucentpdraw_i32o32;
else
patchdrawfunc = standardpdraw_i32o32;
}
}
fixed_t fdup = pscale;
fixed_t vdup = vscale;
fixed_t colfrac = FixedDiv(FRACUNIT, fdup);
fixed_t rowfrac = FixedDiv(FRACUNIT, vdup);
AdjustPositionByOffsets(src_patch, pscale, vscale, flags, &x, &y);
fixed_t pwidth = src_patch->width;
if (pscale != FRACUNIT)
pwidth = (pwidth * pscale) >> FRACBITS;
Patch_MarkDirtyRect(dest_patch, x >> FRACBITS, y >> FRACBITS, (x + w) >> FRACBITS, (y + h) >> FRACBITS);
if (copy_transparent)
Patch_ClearRect(dest_patch, x >> FRACBITS, y >> FRACBITS, w >> FRACBITS, h >> FRACBITS);
if (dest_patch->pixels == NULL)
dest_patch->pixels = Z_Calloc(dest_patch->width * dest_patch->height, PU_PATCH_DATA, NULL);
if (source_paletted)
{
int dest_x = x >> FRACBITS;
for (fixed_t col = sx; (col>>FRACBITS) < src_patch->width && (col - sx) < w; col += colfrac, dest_x++)
{
if (dest_x < 0)
continue;
else if (dest_x >= dest_patch->width)
break;
unsigned texturecolumn = col >> FRACBITS;
if (flags & V_FLIP)
texturecolumn = src_patch->width - 1 - texturecolumn;
column_t *column = &src_patch->columns[texturecolumn];
for (unsigned i = 0; i < column->num_posts; i++)
{
post_t *post = &column->posts[i];
INT32 topdelta = post->topdelta << FRACBITS;
UINT8 *source = column->pixels + post->data_offset;
int dest_y = y >> FRACBITS;
fixed_t ofs;
if (topdelta - sy > 0)
{
dest_y = (y + FixedMul(topdelta - sy, vdup)) >> FRACBITS;
ofs = 0;
}
else
ofs = sy - topdelta;
if (dest_patch->format == PATCH_FORMAT_RGBA)
{
// source 8bpp, dest 32bpp
RGBA_t *dest_pixels = (RGBA_t *)dest_patch->pixels;
for (; dest_y < dest_patch->height && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + topdelta) < h; ofs += rowfrac, dest_y++)
{
if (dest_y < 0)
continue;
size_t position = (dest_x * dest_patch->height) + dest_y;
RGBA_t *dest = &dest_pixels[position];
if (dest->s.alpha == 0)
dpatch->update_columns = true;
patchdrawfunc(dest, (void*)(&source[ofs >> FRACBITS]));
dpatch->is_dirty = true;
}
}
else
{
// source 8bpp, dest 8bpp
for (; dest_y < dest_patch->height && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + topdelta) < h; ofs += rowfrac, dest_y++)
{
if (dest_y < 0)
continue;
size_t position = (dest_x * dest_patch->height) + dest_y;
UINT8 *dest = &dest_patch->pixels[position];
if (!in_bit_array(dpatch->pixels_opaque, position))
{
set_bit_array(dpatch->pixels_opaque, position);
dpatch->update_columns = true;
*dest = 0;
}
patchdrawfunc(dest, (void*)(&source[ofs >> FRACBITS]));
dpatch->is_dirty = true;
}
}
if (dest_y >= dest_patch->height)
break;
}
}
}
else
{
RGBA_t *src_pixels = (RGBA_t *)src_patch->pixels;
int dest_y = y >> FRACBITS;
for (fixed_t row = sy; (row>>FRACBITS) < src_patch->height && (row - sy) < h; row += rowfrac, dest_y++)
{
if (dest_y < 0)
continue;
else if (dest_y >= dest_patch->height)
break;
int dest_x = x >> FRACBITS;
if (dest_patch->format == PATCH_FORMAT_RGBA)
{
RGBA_t *dest_pixels = (RGBA_t *)dest_patch->pixels;
// source 32bpp, dest 32bpp
for (fixed_t col = sx; (col>>FRACBITS) < src_patch->width && (col - sx) < w; col += colfrac, dest_x++)
{
if (dest_x < 0)
continue;
else if (dest_x >= dest_patch->width)
break;
unsigned texturecolumn = col >> FRACBITS;
if (flags & V_FLIP)
texturecolumn = src_patch->width - 1 - texturecolumn;
size_t dest_position = (dest_x * dest_patch->height) + dest_y;
size_t src_position = (texturecolumn * src_patch->height) + (row>>FRACBITS);
RGBA_t *dest = &dest_pixels[dest_position];
RGBA_t *src = &src_pixels[src_position];
if (dest->s.alpha == 0)
dpatch->update_columns = true;
patchdrawfunc(dest, src);
dpatch->is_dirty = true;
}
}
else
{
// source 32bpp, dest 8bpp
for (fixed_t col = sx; (col>>FRACBITS) < src_patch->width && (col - sx) < w; col += colfrac, dest_x++)
{
if (dest_x < 0)
continue;
else if (dest_x >= dest_patch->width)
break;
unsigned texturecolumn = col >> FRACBITS;
if (flags & V_FLIP)
texturecolumn = src_patch->width - 1 - texturecolumn;
size_t dest_position = (dest_x * dest_patch->height) + dest_y;
size_t src_position = (texturecolumn * src_patch->height) + (row>>FRACBITS);
UINT8 *dest = &dest_patch->pixels[dest_position];
RGBA_t *src = &src_pixels[src_position];
if (!in_bit_array(dpatch->pixels_opaque, dest_position))
{
set_bit_array(dpatch->pixels_opaque, dest_position);
dpatch->update_columns = true;
*dest = 0;
}
patchdrawfunc(dest, src);
dpatch->is_dirty = true;
}
}
}
}
}
void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 flags, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h, boolean copy_transparent)
{
if (dest_patch->type != PATCH_TYPE_DYNAMIC)
return;
if (src_patch->format != PATCH_FORMAT_PALETTE || dest_patch->format != PATCH_FORMAT_PALETTE)
{
V_DrawIntoPatchRGBA(dest_patch, src_patch, x, y, pscale, vscale, flags, colormap, sx, sy, w, h, copy_transparent);
return;
}
dynamicpatch_t *dpatch = (dynamicpatch_t *)dest_patch;
if (Patch_NeedsUpdate(src_patch, true))
@ -1281,13 +1674,10 @@ void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t
if (alphalevel || blendmode)
{
if (alphalevel >= 10)
return; // invis
return;
if (alphalevel || blendmode)
{
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
patchdrawfunc = translucentpdraw;
}
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
patchdrawfunc = translucentpdraw;
}
if (colormap)
@ -1307,12 +1697,12 @@ void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t
if (pscale != FRACUNIT)
pwidth = (pwidth * pscale) >> FRACBITS;
int dest_x = x;
int dest_x = x >> FRACBITS;
Patch_MarkDirtyRect(dest_patch, x, y, x + (w >> FRACBITS), y + (h >> FRACBITS));
Patch_MarkDirtyRect(dest_patch, x >> FRACBITS, y >> FRACBITS, (x + w) >> FRACBITS, (y + h) >> FRACBITS);
if (copy_transparent)
Patch_ClearRect(dest_patch, x, y, w >> FRACBITS, h >> FRACBITS);
Patch_ClearRect(dest_patch, x >> FRACBITS, y >> FRACBITS, w >> FRACBITS, h >> FRACBITS);
if (dest_patch->pixels == NULL)
dest_patch->pixels = Z_Calloc(dest_patch->width * dest_patch->height, PU_PATCH_DATA, NULL);
@ -1336,12 +1726,12 @@ void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t
INT32 topdelta = post->topdelta << FRACBITS;
UINT8 *source = column->pixels + post->data_offset;
int dest_y = y;
int dest_y = y >> FRACBITS;
fixed_t ofs;
if (topdelta - sy > 0)
{
dest_y = y + FixedInt(FixedMul(topdelta - sy, vdup));
dest_y = (y + FixedMul(topdelta - sy, vdup)) >> FRACBITS;
ofs = 0;
}
else

View file

@ -53,6 +53,8 @@ void InitColorLUT(colorlookup_t *lut, RGBA_t *palette, boolean makecolors);
UINT8 GetColorLUT(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b);
UINT8 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b);
extern colorlookup_t r_colorlookup;
// Set the current RGB palette lookup to use for palettized graphics
void V_SetPalette(INT32 palettenum);