From 821460d208c9c819cc9cbcaa76893b309170222b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 30 Jul 2023 20:56:28 -0300 Subject: [PATCH] Patch refactor --- src/console.c | 6 +- src/hardware/hw_cache.c | 262 +++++++++++++++++++++++++++------------- src/hardware/hw_draw.c | 25 ++-- src/r_defs.h | 23 +++- src/r_patch.c | 103 ++++++++++++---- src/r_patch.h | 2 + src/r_picformats.c | 112 +++++++++-------- src/r_picformats.h | 2 +- src/r_plane.c | 4 +- src/r_segs.c | 20 ++- src/r_textures.c | 145 +++++++++++----------- src/r_textures.h | 4 +- src/r_things.c | 61 ++++------ src/v_video.c | 47 +++---- 14 files changed, 479 insertions(+), 337 deletions(-) diff --git a/src/console.c b/src/console.c index 21b608ce4..d92694d46 100644 --- a/src/console.c +++ b/src/console.c @@ -1772,10 +1772,10 @@ static void CON_DrawBackpic(void) // then fill the sides with a solid color. if (x > 0) { - column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0])); - if (!column->topdelta) + column_t *column = &con_backpic->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - UINT8 *source = (UINT8 *)(column) + 3; + UINT8 *source = column->pixels; INT32 color = (source[0] | V_NOSCALESTART); // left side V_DrawFill(0, 0, x, con_curlines, color); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index d6245df64..50e4adfac 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -50,6 +50,109 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm 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 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; + + for (size_t i = 0; i < patchcol->num_posts; i++) + { + post_t *post = &patchcol->posts[i]; + source = patchcol->pixels + post->data_offset; + count = ((post->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; + position = originy + post->topdelta; + + yfrac = 0; + if (position < 0) + { + yfrac = -position<> 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]; + alpha = 0xFF; + // Make pixel transparent if chroma keyed + if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) + alpha = 0x00; + + if (mipmap->colormap) + texel = mipmap->colormap->data[texel]; + + switch (bpp) + { + case 2: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3: + colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4: + colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; + // default is 1 + default: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; + } + + dest += blockmodulo; + yfrac += yfracstep; + } + } +} + +static void HWR_DrawPostsInCache(const doompost_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; @@ -106,57 +209,55 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; - //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) texel = mipmap->colormap->data[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 : // uhhhhhhhh.......... - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); - texelu16 = (UINT16)((alpha<<8) | texel); - memcpy(dest, &texelu16, sizeof(UINT16)); - break; - case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); - break; - case 4 : colortemp = V_GetColor(texel); - colortemp.s.alpha = alpha; - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)); - break; + case 2: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3: + colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4: + colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; // default is 1 default: - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); - else - *dest = texel; - break; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; } dest += blockmodulo; yfrac += yfracstep; } - patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); + patchcol = (const doompost_t *)((const UINT8 *)patchcol + patchcol->length + 4); } } -static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, +static void HWR_DrawFlippedPostsInCache(const doompost_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, INT32 pblockheight, INT32 blockmodulo, fixed_t yfracstep, fixed_t scale_y, texpatch_t *originPatch, INT32 patchheight, @@ -216,57 +317,54 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; - //Hurdler: 25/04/2000: now support colormap in hardware mode if (mipmap->colormap) texel = mipmap->colormap->data[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 : // uhhhhhhhh.......... - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); - texelu16 = (UINT16)((alpha<<8) | texel); - memcpy(dest, &texelu16, sizeof(UINT16)); - break; - case 3 : colortemp = V_GetColor(texel); - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); - break; - case 4 : colortemp = V_GetColor(texel); - colortemp.s.alpha = alpha; - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - { - RGBA_t rgbatexel; - rgbatexel.rgba = *(UINT32 *)dest; - colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); - } - memcpy(dest, &colortemp, sizeof(RGBA_t)); - break; + case 2: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3: + colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4: + colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; // default is 1 default: - if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); - else - *dest = texel; - break; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; } dest += blockmodulo; yfrac -= yfracstep; } - patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); + patchcol = (const doompost_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 @@ -307,7 +405,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, // Draw each column to the block cache for (; ncols--; block += bpp, xfrac += xfracstep) { - patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS])); + patchcol = &realpatch->columns[xfrac>>FRACBITS]; HWR_DrawColumnInCache(patchcol, block, mipmap, pblockheight, blockmodulo, @@ -327,13 +425,13 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, INT32 col, ncols; fixed_t xfrac, xfracstep; fixed_t yfracstep, scale_y; - const column_t *patchcol; + const doompost_t *patchcol; UINT8 *block = mipmap->data; INT32 bpp; INT32 blockmodulo; INT32 width, height; // Column drawing function pointer. - static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, + static void (*ColumnDrawerPointer)(const doompost_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, INT32 pblockheight, INT32 blockmodulo, fixed_t yfracstep, fixed_t scale_y, texpatch_t *originPatch, INT32 patchheight, @@ -342,7 +440,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, if (texture->width <= 0 || texture->height <= 0) return; - ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedPostsInCache : HWR_DrawPostsInCache; x1 = patch->originx; width = SHORT(realpatch->width); @@ -372,14 +470,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, 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", - width, height, - texture->width, texture->height, - pblockwidth, pblockheight); - CONS_Debug(DBG_RENDER, " col %d ncols %d x %d\n", col, ncols, x); -*/ - // source advance xfrac = 0; if (x1 < 0) @@ -401,9 +491,9 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) { if (patch->flip & 1) - patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[(width-1)-(xfrac>>FRACBITS)])); + patchcol = (const doompost_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[(width-1)-(xfrac>>FRACBITS)])); else - patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); + patchcol = (const doompost_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); ColumnDrawerPointer(patchcol, block, mipmap, pblockheight, blockmodulo, diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index eb0b9e332..896f1aa3f 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -131,6 +131,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p float cy = FIXED_TO_FLOAT(y); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 blendmode = ((option & V_BLENDMASK) >> V_BLENDSHIFT); + UINT8 opacity = 0xFF; GLPatch_t *hwrPatch; // 3--2 @@ -149,6 +150,14 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p hwrPatch = ((GLPatch_t *)gpatch->hardware); + if (alphalevel) + { + if (alphalevel == 10) opacity = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF + else if (alphalevel == 11) opacity = softwaretranstogl[st_translucency]; // V_HUDTRANS + else if (alphalevel == 12) opacity = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE + else opacity = softwaretranstogl[10-alphalevel]; + } + dupx = (float)vid.dupx; dupy = (float)vid.dupy; @@ -269,13 +278,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre - if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT) + if (opacity == 0xFF && cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT) { - const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0])); - if (!column->topdelta) + const column_t *column = &gpatch->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + const UINT8 *source = column->pixels; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]); } } // centre screen @@ -353,11 +362,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - - if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF - else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS - else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE - else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + Surf.PolyColor.s.alpha = opacity; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); } diff --git a/src/r_defs.h b/src/r_defs.h index a9b9a4a08..000d2ceab 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -719,14 +719,26 @@ typedef struct { UINT8 topdelta; // -1 is the last post in a column UINT8 length; // length data bytes follows -} ATTRPACK post_t; +} ATTRPACK doompost_t; #if defined(_MSC_VER) #pragma pack() #endif -// column_t is a list of 0 or more post_t, (UINT8)-1 terminated -typedef post_t column_t; +typedef struct +{ + size_t topdelta; + size_t length; + size_t data_offset; +} post_t; + +// column_t is a list of 0 or more post_t +typedef struct +{ + size_t num_posts; + post_t *posts; + UINT8 *pixels; +} column_t; // // OTHER TYPES @@ -800,8 +812,9 @@ typedef struct INT16 width, height; INT16 leftoffset, topoffset; - INT32 *columnofs; // Column offsets. This is relative to patch->columns - UINT8 *columns; // Software column data + UINT8 *pixels; + column_t *columns; + post_t *posts; void *hardware; // OpenGL patch, allocated whenever necessary void *flats[4]; // The patch as flats diff --git a/src/r_patch.c b/src/r_patch.c index 7c561e959..863b7af53 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -27,40 +27,89 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest) { patch_t *patch = (dest == NULL) ? Z_Calloc(sizeof(patch_t), PU_PATCH, NULL) : (patch_t *)(dest); + if (!source) + return patch; - if (source) - { - INT32 col, colsize; - size_t size = sizeof(INT32) * SHORT(source->width); - size_t offs = (sizeof(INT16) * 4) + size; + (void)srcsize; - patch->width = SHORT(source->width); - patch->height = SHORT(source->height); - patch->leftoffset = SHORT(source->leftoffset); - patch->topoffset = SHORT(source->topoffset); - patch->columnofs = Z_Calloc(size, PU_PATCH_DATA, NULL); + patch->width = SHORT(source->width); + patch->height = SHORT(source->height); + patch->leftoffset = SHORT(source->leftoffset); + patch->topoffset = SHORT(source->topoffset); - for (col = 0; col < source->width; col++) - { - // This makes the column offsets relative to the column data itself, - // instead of the entire patch data - patch->columnofs[col] = LONG(source->columnofs[col]) - offs; - } + size_t total_pixels = 0; + size_t total_posts = 0; - if (!srcsize) - I_Error("Patch_Create: no source size!"); + Patch_CalcDataSizes(source, &total_pixels, &total_posts); - colsize = (INT32)(srcsize) - (INT32)offs; - if (colsize <= 0) - I_Error("Patch_Create: no column data!"); + patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL); + patch->posts = Z_Calloc(sizeof(post_t) * total_posts, PU_PATCH_DATA, NULL); + patch->pixels = Z_Calloc(sizeof(UINT8) * total_pixels, PU_PATCH_DATA, NULL); - patch->columns = Z_Calloc(colsize, PU_PATCH_DATA, NULL); - M_Memcpy(patch->columns, ((UINT8 *)source + LONG(source->columnofs[0])), colsize); - } + Patch_MakeColumns(source, patch->width, patch->pixels, patch->columns, patch->posts, false); return patch; } +void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts) +{ + for (INT32 i = 0; i < source->width; i++) + { + doompost_t *src_posts = (doompost_t*)((UINT8 *)source + LONG(source->columnofs[i])); + for (doompost_t *post = src_posts; post->topdelta != 0xff ;) + { + (*total_posts)++; + (*total_pixels) += post->length; + post = (doompost_t *)((UINT8 *)post + post->length + 4); + } + } +} + +void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip) +{ + column_t *column = flip ? columns + (num_columns - 1) : columns; + + for (size_t i = 0; i < num_columns; i++) + { + size_t prevdelta = 0; + size_t data_offset = 0; + + column->pixels = pixels; + column->posts = posts; + column->num_posts = 0; + + doompost_t *src_posts = (doompost_t*)((UINT8 *)source + LONG(source->columnofs[i])); + + for (doompost_t *post = src_posts; post->topdelta != 0xff ;) + { + size_t topdelta = post->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + posts->topdelta = topdelta; + posts->length = (size_t)post->length; + posts->data_offset = data_offset; + + memcpy(pixels, (UINT8 *)post + 3, post->length); + + data_offset += posts->length; + pixels += posts->length; + + column->num_posts++; + + posts++; + + post = (doompost_t *)((UINT8 *)post + post->length + 4); + } + + if (flip) + column--; + else + column++; + } +} + // // Frees a patch from memory. // @@ -96,10 +145,12 @@ static void Patch_FreeData(patch_t *patch) } #endif - if (patch->columnofs) - Z_Free(patch->columnofs); + if (patch->pixels) + Z_Free(patch->pixels); if (patch->columns) Z_Free(patch->columns); + if (patch->posts) + Z_Free(patch->posts); } void Patch_Free(patch_t *patch) diff --git a/src/r_patch.h b/src/r_patch.h index a0ab3e75a..cea3b0fe5 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -19,6 +19,8 @@ // Patch functions patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); +void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts); +void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip); void Patch_Free(patch_t *patch); #define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) diff --git a/src/r_picformats.c b/src/r_picformats.c index 3e817f4a0..c7be4ea22 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -538,8 +538,6 @@ void *Picture_GetPatchPixel( INT32 x, INT32 y, pictureflags_t flags) { - fixed_t ofs; - column_t *column; INT32 inbpp = Picture_FormatBPP(informat); softwarepatch_t *doompatch = (softwarepatch_t *)patch; boolean isdoompatch = Picture_IsDoomPatchFormat(informat); @@ -550,30 +548,30 @@ void *Picture_GetPatchPixel( width = (isdoompatch ? SHORT(doompatch->width) : patch->width); - if (x >= 0 && x < width) + if (x < 0 || x >= width) + return NULL; + + INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; + UINT8 *s8 = NULL; + UINT16 *s16 = NULL; + UINT32 *s32 = NULL; + + if (isdoompatch) { - INT32 colx = (flags & PICFLAGS_XFLIP) ? (width-1)-x : x; - INT32 topdelta, prevdelta = -1; - INT32 colofs = (isdoompatch ? LONG(doompatch->columnofs[colx]) : patch->columnofs[colx]); + INT32 prevdelta = -1; + INT32 colofs = LONG(doompatch->columnofs[colx]); // Column offsets are pointers, so no casting is required. - if (isdoompatch) - column = (column_t *)((UINT8 *)doompatch + colofs); - else - column = (column_t *)((UINT8 *)patch->columns + colofs); + doompost_t *column = (doompost_t *)((UINT8 *)doompatch + colofs); while (column->topdelta != 0xff) { - UINT8 *s8 = NULL; - UINT16 *s16 = NULL; - UINT32 *s32 = NULL; - - topdelta = column->topdelta; + INT32 topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - ofs = (y - topdelta); + size_t ofs = y - topdelta; if (y >= topdelta && ofs < column->length) { @@ -592,12 +590,38 @@ void *Picture_GetPatchPixel( } if (inbpp == PICDEPTH_32BPP) - column = (column_t *)((UINT32 *)column + column->length); + column = (doompost_t *)((UINT32 *)column + column->length); else if (inbpp == PICDEPTH_16BPP) - column = (column_t *)((UINT16 *)column + column->length); + column = (doompost_t *)((UINT16 *)column + column->length); else - column = (column_t *)((UINT8 *)column + column->length); - column = (column_t *)((UINT8 *)column + 4); + column = (doompost_t *)((UINT8 *)column + column->length); + column = (doompost_t *)((UINT8 *)column + 4); + } + } + else + { + column_t *column = &patch->columns[colx]; + for (size_t i = 0; i < column->num_posts; i++) + { + post_t *post = &column->posts[i]; + + size_t ofs = y - post->topdelta; + + if (y >= (INT32)post->topdelta && ofs < post->length) + { + s8 = column->pixels + post->data_offset; + switch (inbpp) + { + case PICDEPTH_32BPP: + s32 = (UINT32 *)s8; + return &s32[ofs]; + case PICDEPTH_16BPP: + s16 = (UINT16 *)s8; + return &s16[ofs]; + default: // PICDEPTH_8BPP + return &s8[ofs]; + } + } } } @@ -738,29 +762,25 @@ boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size) /** Converts a texture to a flat. * - * \param trickytex The texture number. + * \param texnum The texture number. * \return The converted flat. */ -void *Picture_TextureToFlat(size_t trickytex) +void *Picture_TextureToFlat(size_t texnum) { texture_t *texture; - size_t tex; UINT8 *converted; size_t flatsize; - fixed_t col, ofs; - column_t *column; UINT8 *desttop, *dest, *deststop; UINT8 *source; - if (trickytex >= (unsigned)numtextures) + if (texnum >= (unsigned)numtextures) I_Error("Picture_TextureToFlat: invalid texture number!"); // Check the texture cache // If the texture's not there, it'll be generated right now - tex = trickytex; - texture = textures[tex]; - R_CheckTextureCache(tex); + texture = textures[texnum]; + R_CheckTextureCache(texnum); // Allocate the flat flatsize = (texture->width * texture->height); @@ -770,41 +790,37 @@ void *Picture_TextureToFlat(size_t trickytex) // Now we're gonna write to it desttop = converted; deststop = desttop + flatsize; - for (col = 0; col < texture->width; col++, desttop++) + + if (!texture->holes) { - // no post_t info - if (!texture->holes) + for (size_t col = 0; col < (size_t)texture->width; col++, desttop++) { - column = (column_t *)(R_GetColumn(tex, col)); - source = (UINT8 *)(column); + source = R_GetColumn(texnum, col)->pixels; dest = desttop; - for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + for (size_t ofs = 0; dest < deststop && ofs < (size_t)texture->height; ofs++) { if (source[ofs] != TRANSPARENTPIXEL) *dest = source[ofs]; dest += texture->width; } } - else + } + else + { + for (size_t col = 0; col < (size_t)texture->width; col++, desttop++) { - INT32 topdelta, prevdelta = -1; - column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3); - while (column->topdelta != 0xff) + column_t *column = (column_t *)R_GetColumn(texnum, col); + for (size_t i = 0; i < column->num_posts; i++) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - - dest = desttop + (topdelta * texture->width); - source = (UINT8 *)column + 3; - for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + post_t *post = &column->posts[i]; + dest = desttop + (post->topdelta * texture->width); + source = column->pixels + post->data_offset; + for (size_t ofs = 0; dest < deststop && ofs < post->length; ofs++) { if (source[ofs] != TRANSPARENTPIXEL) *dest = source[ofs]; dest += texture->width; } - column = (column_t *)((UINT8 *)column + column->length + 4); } } } diff --git a/src/r_picformats.h b/src/r_picformats.h index 4050a1b71..c8a5b5d26 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -75,7 +75,7 @@ void *Picture_GetPatchPixel( INT32 x, INT32 y, pictureflags_t flags); -void *Picture_TextureToFlat(size_t trickytex); +void *Picture_TextureToFlat(size_t texnum); INT32 Picture_FormatBPP(pictureformat_t format); boolean Picture_IsPatchFormat(pictureformat_t format); diff --git a/src/r_plane.c b/src/r_plane.c index c568484b6..12c06c283 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -669,9 +669,7 @@ static void R_DrawSkyPlane(visplane_t *pl) angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); dc_x = x; - dc_source = - R_GetColumn(texturetranslation[skytexture], - -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + dc_source = R_GetColumn(texturetranslation[skytexture], -angle)->pixels; // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 colfunc(); } } diff --git a/src/r_segs.c b/src/r_segs.c index facab62ab..51f0659e9 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -86,10 +86,7 @@ static fixed_t *maskedtextureheight = NULL; static void R_Render2sidedMultiPatchColumn(column_t *column) { - INT32 topscreen, bottomscreen; - - topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall - bottomscreen = topscreen + spryscale * lengthcol; + INT32 bottomscreen = sprtopscreen + spryscale * lengthcol; dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -110,7 +107,7 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) { - dc_source = (UINT8 *)column + 3; + dc_source = column->pixels; if (colfunc == colfuncs[BASEDRAWFUNC]) (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); @@ -382,7 +379,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_iscale = 0xffffffffu / (unsigned)spryscale; // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + col = R_GetColumn(texnum, maskedtexturecol[dc_x]); for (i = 0; i < dc_numlights; i++) { @@ -457,7 +454,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_iscale = 0xffffffffu / (unsigned)spryscale; // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); + col = R_GetColumn(texnum, maskedtexturecol[dc_x]); #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) @@ -897,7 +894,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_iscale = 0xffffffffu / (unsigned)spryscale; // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); + col = R_GetColumn(texnum,maskedtexturecol[dc_x]); // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -1336,7 +1333,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS)); + dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS))->pixels; dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1397,7 +1394,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS)); + dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS))->pixels; dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1433,8 +1430,7 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn + (rw_offset_bot>>FRACBITS)); + dc_source = R_GetColumn(bottomtexture, texturecolumn + (rw_offset_bot>>FRACBITS))->pixels; dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; diff --git a/src/r_textures.c b/src/r_textures.c index 8b47f455e..5896ab30d 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -48,7 +48,7 @@ INT32 numtextures = 0; // total number of textures found, // size of following tables texture_t **textures = NULL; -UINT32 **texturecolumnofs; // column offset lookup table for each texture +column_t **texturecolumns; // columns for each texture UINT8 **texturecache; // graphics data for each generated full-size texture INT32 *texturewidth; @@ -78,7 +78,7 @@ static INT32 tidcachelen = 0; // R_DrawColumnInCache // Clip and draw a column from a patch into a cached post. // -static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawColumnInCache(doompost_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source; @@ -110,7 +110,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t if (count > 0) M_Memcpy(cache + position, source, count); - patch = (column_t *)((UINT8 *)patch + patch->length + 4); + patch = (doompost_t *)((UINT8 *)patch + patch->length + 4); } } @@ -118,7 +118,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t // R_DrawFlippedColumnInCache // Similar to R_DrawColumnInCache; it draws the column inverted, however. // -static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawFlippedColumnInCache(doompost_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; @@ -153,7 +153,7 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex *dest++ = *source; } - patch = (column_t *)((UINT8 *)patch + patch->length + 4); + patch = (doompost_t *)((UINT8 *)patch + patch->length + 4); } } @@ -161,7 +161,7 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex // R_DrawBlendColumnInCache // Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). // -static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendColumnInCache(doompost_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; @@ -198,7 +198,7 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); } - patch = (column_t *)((UINT8 *)patch + patch->length + 4); + patch = (doompost_t *)((UINT8 *)patch + patch->length + 4); } } @@ -206,7 +206,7 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa // R_DrawBlendFlippedColumnInCache // Similar to the one above except that the column is inverted. // -static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +static inline void R_DrawBlendFlippedColumnInCache(doompost_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) { INT32 count, position; UINT8 *source, *dest; @@ -242,7 +242,7 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); } - patch = (column_t *)((UINT8 *)patch + patch->length + 4); + patch = (doompost_t *)((UINT8 *)patch + patch->length + 4); } } @@ -263,16 +263,8 @@ UINT8 *R_GenerateTexture(size_t texnum) UINT8 *blocktex; texture_t *texture; texpatch_t *patch; - softwarepatch_t *realpatch; - UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; - column_t *patchcol; - UINT8 *colofs; - - UINT16 wadnum; - lumpnum_t lumpnum; - size_t lumplength; I_Assert(texnum <= (size_t)numtextures); texture = textures[texnum]; @@ -289,11 +281,11 @@ UINT8 *R_GenerateTexture(size_t texnum) boolean holey = false; patch = texture->patches; - wadnum = patch->wad; - lumpnum = patch->lump; - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - realpatch = (softwarepatch_t *)pdata; + UINT16 wadnum = patch->wad; + lumpnum_t lumpnum = patch->lump; + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + softwarepatch_t *realpatch = (softwarepatch_t *)pdata; #ifndef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) @@ -307,10 +299,10 @@ UINT8 *R_GenerateTexture(size_t texnum) // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) holey = true; - colofs = (UINT8 *)realpatch->columnofs; + UINT8 *colofs = (UINT8 *)realpatch->columnofs; for (x = 0; x < texture->width && !holey; x++) { - column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); + doompost_t *col = (doompost_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); INT32 topdelta, prevdelta = -1, y = 0; while (col->topdelta != 0xff) { @@ -321,7 +313,7 @@ UINT8 *R_GenerateTexture(size_t texnum) if (topdelta > y) break; y = topdelta + col->length + 1; - col = (column_t *)((UINT8 *)col + col->length + 4); + col = (doompost_t *)((UINT8 *)col + col->length + 4); } if (y < texture->height) holey = true; // this texture is HOLEy! D: @@ -332,26 +324,26 @@ UINT8 *R_GenerateTexture(size_t texnum) { texture->holes = true; texture->flip = patch->flip; - blocksize = lumplength; - block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function - &texturecache[texnum]); - M_Memcpy(block, realpatch, blocksize); + + size_t total_pixels = 0; + size_t total_posts = 0; + + Patch_CalcDataSizes(realpatch, &total_pixels, &total_posts); + + blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); texturememory += blocksize; - // use the patch's column lookup - colofs = (block + 8); - texturecolumnofs[texnum] = (UINT32 *)colofs; + block = Z_Calloc(blocksize, PU_STATIC, &texturecache[texnum]); blocktex = block; - if (patch->flip & 1) // flip the patch horizontally - { - UINT8 *realcolofs = (UINT8 *)realpatch->columnofs; - for (x = 0; x < texture->width; x++) - *(UINT32 *)&colofs[x<<2] = realcolofs[( texture->width-1-x )<<2]; // swap with the offset of the other side of the texture - } - // we can't as easily flip the patch vertically sadly though, - // we have wait until the texture itself is drawn to do that - for (x = 0; x < texture->width; x++) - *(UINT32 *)&colofs[x<<2] = LONG(LONG(*(UINT32 *)&colofs[x<<2]) + 3); + + UINT8 *pixels = block; + column_t *columns = (column_t *)(block + (sizeof(UINT8) * total_pixels)); + post_t *posts = (post_t *)(block + (sizeof(UINT8) * total_pixels) + (sizeof(column_t) * texture->width)); + + texturecolumns[texnum] = columns; + + Patch_MakeColumns(realpatch, texture->width, pixels, columns, posts, texture->flip); + goto done; } @@ -362,35 +354,44 @@ UINT8 *R_GenerateTexture(size_t texnum) multipatch: texture->holes = false; texture->flip = 0; - blocksize = (texture->width * 4) + (texture->width * texture->height); + + size_t total_pixels = texture->width * texture->height; + + blocksize = (sizeof(column_t) * texture->width) + (sizeof(UINT8) * total_pixels); texturememory += blocksize; - block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); - memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack + block = Z_Malloc(blocksize, PU_STATIC, &texturecache[texnum]); + blocktex = block; + memset(blocktex, TRANSPARENTPIXEL, total_pixels); // Transparency hack - // columns lookup table - colofs = block; - texturecolumnofs[texnum] = (UINT32 *)colofs; + column_t *columns = (column_t *)(block + (sizeof(UINT8) * total_pixels)); + texturecolumns[texnum] = columns; - // texture data after the lookup table - blocktex = block + (texture->width*4); + size_t data_offset = 0; + for (x = 0; x < texture->width; x++) + { + column_t *column = &columns[x]; + column->num_posts = 0; + column->posts = NULL; + column->pixels = blocktex + data_offset; + data_offset += texture->height; + } // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - boolean dealloc = true; - static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. + static void (*columnDrawer)(doompost_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. if (patch->style != AST_COPY) - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; + columnDrawer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; else - ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; + columnDrawer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; - wadnum = patch->wad; - lumpnum = patch->lump; - pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); - lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = (softwarepatch_t *)pdata; - dealloc = true; + UINT16 wadnum = patch->wad; + lumpnum_t lumpnum = patch->lump; + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + UINT8 *pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + softwarepatch_t *realpatch = (softwarepatch_t *)pdata; + boolean dealloc = true; #ifndef NO_PNG_LUMPS if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) @@ -441,14 +442,13 @@ UINT8 *R_GenerateTexture(size_t texnum) for (; x < x2; x++) { + doompost_t *patchcol; if (patch->flip & 1) - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + patchcol = (doompost_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); else - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + patchcol = (doompost_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); - // generate column ofset lookup - *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); - ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height); + columnDrawer(patchcol, columns[x].pixels, patch, texture->height, height); } if (dealloc) @@ -513,24 +513,19 @@ void R_CheckTextureCache(INT32 tex) R_GenerateTexture(tex); } -// -// R_GetColumn -// -UINT8 *R_GetColumn(fixed_t tex, INT32 col) +column_t *R_GetColumn(fixed_t tex, INT32 col) { - UINT8 *data; INT32 width = texturewidth[tex]; - if (width & (width - 1)) col = (UINT32)col % width; else col &= (width - 1); - data = texturecache[tex]; + UINT8 *data = texturecache[tex]; if (!data) - data = R_GenerateTexture(tex); + R_GenerateTexture(tex); - return data + LONG(texturecolumnofs[tex][col]); + return &texturecolumns[tex][col]; } void *R_GetFlat(lumpnum_t flatlumpnum) @@ -1016,7 +1011,7 @@ static void R_AllocateTextures(INT32 add) recallocuser(&textures, oldsize, newsize); // Allocate texture column offset table. - recallocuser(&texturecolumnofs, oldsize, newsize); + recallocuser(&texturecolumns, oldsize, newsize); // Allocate texture referencing cache. recallocuser(&texturecache, oldsize, newsize); // Allocate texture width table. diff --git a/src/r_textures.h b/src/r_textures.h index 394b4f824..46b5904d7 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -72,7 +72,7 @@ extern texture_t **textures; extern INT32 *texturewidth; extern fixed_t *textureheight; // needed for texture pegging -extern UINT32 **texturecolumnofs; // column offset lookup table for each texture +extern column_t **texturecolumns; // columns for each texture extern UINT8 **texturecache; // graphics data for each generated full-size texture // Load TEXTURES definitions, create lookup tables @@ -89,7 +89,7 @@ void R_ClearTextureNumCache(boolean btell); // Retrieve texture data. void *R_GetLevelFlat(levelflat_t *levelflat); -UINT8 *R_GetColumn(fixed_t tex, INT32 col); +column_t *R_GetColumn(fixed_t tex, INT32 col); void *R_GetFlat(lumpnum_t flatnum); boolean R_CheckPowersOfTwo(void); diff --git a/src/r_things.c b/src/r_things.c index 90b80dda8..c67adc425 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -639,23 +639,14 @@ fixed_t windowtop = 0, windowbottom = 0; void R_DrawMaskedColumn(column_t *column) { - INT32 topscreen; - INT32 bottomscreen; - fixed_t basetexturemid; - INT32 topdelta, prevdelta = 0; + fixed_t basetexturemid = dc_texturemid; - basetexturemid = dc_texturemid; - - for (; column->topdelta != 0xff ;) + for (size_t i = 0; i < column->num_posts; i++) { - // calculate unclipped screen coordinates - // for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = topscreen + spryscale*column->length; + post_t *post = &column->posts[i]; + + INT32 topscreen = sprtopscreen + spryscale*post->topdelta; + INT32 bottomscreen = topscreen + spryscale*post->length; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -679,8 +670,8 @@ void R_DrawMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { - dc_source = (UINT8 *)column + 3; - dc_texturemid = basetexturemid - (topdelta<pixels + post->data_offset; + dc_texturemid = basetexturemid - (post->topdelta<length + 4); } dc_texturemid = basetexturemid; @@ -706,21 +696,15 @@ void R_DrawFlippedMaskedColumn(column_t *column) INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - INT32 topdelta, prevdelta = -1; UINT8 *d,*s; - for (; column->topdelta != 0xff ;) + for (size_t i = 0; i < column->num_posts; i++) { - // calculate unclipped screen coordinates - // for post - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - topdelta = lengthcol-column->length-topdelta; + post_t *post = &column->posts[i]; + INT32 topdelta = lengthcol-post->length-post->topdelta; topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length - : sprbotscreen + spryscale*column->length; + bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length + : sprbotscreen + spryscale*post->length; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -744,8 +728,8 @@ void R_DrawFlippedMaskedColumn(column_t *column) if (dc_yl <= dc_yh && dc_yh > 0) { - dc_source = ZZ_Alloc(column->length); - for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) + dc_source = ZZ_Alloc(post->length); + for (s = column->pixels+post->data_offset+post->length, d = dc_source; d < dc_source+post->length; --s) *d++ = *s; dc_texturemid = basetexturemid - (topdelta<length + 4); } dc_texturemid = basetexturemid; @@ -950,7 +933,7 @@ static void R_DrawVisSprite(vissprite_t *vis) sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + column = &patch->columns[texturecolumn]; localcolfunc (column); } @@ -968,9 +951,9 @@ static void R_DrawVisSprite(vissprite_t *vis) texturecolumn = frac>>FRACBITS; if (texturecolumn < 0 || texturecolumn >= pwidth) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + column = &patch->columns[texturecolumn]; #else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); + column = &patch->columns[frac>>FRACBITS]; #endif sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); @@ -990,9 +973,9 @@ static void R_DrawVisSprite(vissprite_t *vis) texturecolumn = frac>>FRACBITS; if (texturecolumn < 0 || texturecolumn >= pwidth) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + column = &patch->columns[texturecolumn]; #else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); + column = &patch->columns[frac>>FRACBITS]; #endif localcolfunc (column); } @@ -1057,9 +1040,9 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (texturecolumn < 0 || texturecolumn >= patch->width) I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn"); - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + column = &patch->columns[texturecolumn]; #else - column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); + column = &patch->columns[frac>>FRACBITS]; #endif R_DrawMaskedColumn(column); } diff --git a/src/v_video.c b/src/v_video.c index 461a5e3bc..4495a4a30 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -516,7 +516,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; - const column_t *column; + column_t *column; UINT8 *desttop, *dest, *deststart, *destend; const UINT8 *source, *deststop; fixed_t pwidth; // patch width @@ -703,12 +703,12 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (!(scrn & V_SCALEPATCHMASK)) { // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) - if (x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT) + if (!v_translevel && x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT) { - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[0])); - if (!column->topdelta) + column = &patch->columns[0]; + if (column->num_posts && !column->posts[0].topdelta) { - source = (const UINT8 *)(column) + 3; + source = column->pixels; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]); } } @@ -758,7 +758,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++) { - INT32 topdelta, prevdelta = -1; if (scrn & V_FLIP) // offx is measured from right edge instead of left { if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) @@ -773,27 +772,24 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + column = &patch->columns[col>>FRACBITS]; + + for (size_t i = 0; i < column->num_posts; i++) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; + post_t *post = &column->posts[i]; + source = column->pixels + post->data_offset; dest = desttop; if (scrn & V_FLIP) dest = deststart + (destend - desttop); - dest += FixedInt(FixedMul(topdelta<topdelta<>FRACBITS) < column->length; ofs += rowfrac) + 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) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } - column = (const column_t *)((const UINT8 *)column + column->length + 4); } } } @@ -808,7 +804,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; - const column_t *column; + column_t *column; UINT8 *desttop, *dest; const UINT8 *source, *deststop; @@ -1044,20 +1040,18 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++) { - INT32 topdelta, prevdelta = -1; if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) continue; if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - while (column->topdelta != 0xff) + column = &patch->columns[col>>FRACBITS]; + + for (size_t i = 0; i < column->num_posts; i++) { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; + post_t *post = &column->posts[i]; + INT32 topdelta = post->topdelta; + source = column->pixels + post->data_offset; dest = desttop; if ((topdelta< 0) { @@ -1067,13 +1061,12 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN else ofs = sy-(topdelta<>FRACBITS) < column->length && ((ofs - sy) + (topdelta<>FRACBITS) < post->length && ((ofs - sy) + (topdelta<= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } - column = (const column_t *)((const UINT8 *)column + column->length + 4); } } }