Fix PNG issue in OpenGL + optimize PNG sprite loading

This commit is contained in:
Jaime Passos 2020-10-02 19:48:13 -03:00
parent 304e4bb1f9
commit aaa9cff6ac
6 changed files with 89 additions and 74 deletions

View File

@ -109,12 +109,6 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
if (mipmap->colormap)
texel = mipmap->colormap[texel];
// If the mipmap is chromakeyed, check if the texel's color
// is equivalent to the chroma key's color index.
alpha = 0xff;
if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
alpha = 0x00;
// 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
@ -512,11 +506,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
{
// Dummy variables.
INT32 pngwidth, pngheight;
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, &pngwidth, &pngheight, NULL, NULL, lumplength, NULL, 0);
}
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
#ifdef WALLFLATS
@ -558,12 +548,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && Picture_IsLumpPNG((const UINT8 *)patch, len))
{
// Dummy variables.
INT32 pngwidth, pngheight;
INT16 topoffset, leftoffset;
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, &pngwidth, &pngheight, &topoffset, &leftoffset, len, NULL, 0);
}
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, NULL, 0);
#endif
// don't do it twice (like a cache)
@ -885,7 +870,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
#ifndef NO_PNG_LUMPS
else if (levelflat->type == LEVELFLAT_PNG)
{
INT32 pngwidth, pngheight;
INT32 pngwidth = 0, pngheight = 0;
GLMipmap_t *mipmap = levelflat->mipmap;
UINT8 *flat;
size_t size;

View File

@ -798,6 +798,8 @@ static void PNG_warn(png_structp PNG, png_const_charp pngtext)
CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext);
}
static png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'};
static png_bytep *PNG_Read(
const UINT8 *png,
INT32 *w, INT32 *h, INT16 *topoffset, INT16 *leftoffset,
@ -824,8 +826,6 @@ static png_bytep *PNG_Read(
png_io_t png_io;
png_bytep *row_pointers;
png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'};
png_voidp *user_chunk_ptr;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn);
@ -852,7 +852,6 @@ static png_bytep *PNG_Read(
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif
// set our own read function
png_io.buffer = png;
png_io.size = size;
png_io.position = 0;
@ -896,7 +895,7 @@ static png_bytep *PNG_Read(
// color is present on the image, the palette flag is disabled.
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
if (trans_num == 256)
if (trans && trans_num == 256)
{
int i;
for (i = 0; i < trans_num; i++)
@ -950,7 +949,6 @@ static png_bytep *PNG_Read(
*topoffset = (INT16)BIGENDIAN_LONG(*offsets);
}
// bye
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
if (chunk.data)
Z_Free(chunk.data);
@ -987,12 +985,28 @@ void *Picture_PNGConvert(
png_uint_32 x, y;
png_bytep row;
boolean palette = false;
png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, &palette, insize);
png_uint_32 width = *w, height = *h;
png_bytep *row_pointers = NULL;
png_uint_32 width, height;
INT32 pngwidth, pngheight;
INT16 loffs = 0, toffs = 0;
if (png == NULL)
I_Error("Picture_PNGConvert: picture was NULL!");
if (w == NULL)
w = &pngwidth;
if (h == NULL)
h = &pngheight;
if (topoffset == NULL)
topoffset = &toffs;
if (leftoffset == NULL)
leftoffset = &loffs;
row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, &palette, insize);
width = *w;
height = *h;
if (row_pointers == NULL)
I_Error("Picture_PNGConvert: row_pointers was NULL!");
@ -1158,7 +1172,6 @@ void *Picture_PNGConvert(
{
void *converted;
pictureformat_t informat = PICFMT_NONE;
INT16 patleftoffset = 0, pattopoffset = 0;
// Figure out the format of the flat, from the bit depth of the output format
switch (outbpp)
@ -1174,14 +1187,8 @@ void *Picture_PNGConvert(
break;
}
// Also find out if leftoffset and topoffset aren't pointing to NULL.
if (leftoffset)
patleftoffset = *leftoffset;
if (topoffset)
pattopoffset = *topoffset;
// Now, convert it!
converted = Picture_PatchConvert(informat, flat, outformat, insize, outsize, (INT16)width, (INT16)height, patleftoffset, pattopoffset, flags);
converted = Picture_PatchConvert(informat, flat, outformat, insize, outsize, (INT16)width, (INT16)height, loffs, toffs, flags);
Z_Free(flat);
return converted;
}
@ -1195,10 +1202,12 @@ void *Picture_PNGConvert(
* \param png The PNG image.
* \param width A pointer to the input picture's width.
* \param height A pointer to the input picture's height.
* \param topoffset A pointer to the input picture's vertical offset.
* \param leftoffset A pointer to the input picture's horizontal offset.
* \param size The input picture's size.
* \return True if reading the file succeeded, false if it failed.
*/
boolean Picture_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size)
{
png_structp png_ptr;
png_infop png_info_ptr;
@ -1211,9 +1220,9 @@ boolean Picture_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t si
#endif
png_io_t png_io;
png_voidp *user_chunk_ptr;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
PNG_error, PNG_warn);
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn);
if (!png_ptr)
I_Error("Picture_PNGDimensions: Couldn't initialize libpng!");
@ -1237,23 +1246,41 @@ boolean Picture_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t si
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif
// set our own read function
png_io.buffer = png;
png_io.size = size;
png_io.position = 0;
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
memset(&chunk, 0x00, sizeof(png_chunk_t));
chunkname = grAb_chunk; // I want to read a grAb chunk
user_chunk_ptr = png_get_user_chunk_ptr(png_ptr);
png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader);
png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits(png_ptr, 2048, 2048);
#endif
png_read_info(png_ptr, png_info_ptr);
png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL);
png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type,
NULL, NULL, NULL);
// Read grAB chunk
if ((topoffset || leftoffset) && (chunk.data != NULL))
{
INT32 *offsets = (INT32 *)chunk.data;
// read left offset
if (leftoffset != NULL)
*leftoffset = (INT16)BIGENDIAN_LONG(*offsets);
offsets++;
// read top offset
if (topoffset != NULL)
*topoffset = (INT16)BIGENDIAN_LONG(*offsets);
}
// okay done. stop.
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
if (chunk.data)
Z_Free(chunk.data);
*width = (INT32)w;
*height = (INT32)h;
@ -1634,11 +1661,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
lumplength = W_LumpLength(lump);
if (Picture_IsLumpPNG((const UINT8 *)patch, lumplength))
{
INT32 pngwidth, pngheight;
INT16 toffs, loffs;
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, &pngwidth, &pngheight, &toffs, &loffs, lumplength, NULL, 0);
}
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
// Because there's something wrong with SPR_DFLM, I guess

View File

@ -110,7 +110,7 @@ void *Picture_PNGConvert(
INT16 *topoffset, INT16 *leftoffset,
size_t insize, size_t *outsize,
pictureflags_t flags);
boolean Picture_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size);
#endif
#define PICTURE_PNG_USELOOKUP

View File

@ -397,11 +397,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
{
// Dummy variables.
INT32 pngwidth, pngheight;
realpatch = (patch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_PATCH, &pngwidth, &pngheight, NULL, NULL, lumplength, NULL, 0);
}
realpatch = (patch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
#ifdef WALLFLATS
@ -800,10 +796,10 @@ Rloadflats (INT32 i, INT32 w)
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength))
{
INT16 width, height;
Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, lumplength);
texture->width = width;
texture->height = height;
INT32 width, height;
Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength);
texture->width = (INT16)width;
texture->height = (INT16)height;
}
else
#endif
@ -898,10 +894,10 @@ Rloadtextures (INT32 i, INT32 w)
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width, height;
Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
texture->width = width;
texture->height = height;
INT32 width, height;
Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength);
texture->width = (INT16)width;
texture->height = (INT16)height;
}
else
#endif

View File

@ -259,6 +259,12 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
{
if (memcmp(lumpinfo[l].name,sprname,4)==0)
{
INT32 width, height;
INT16 topoffset, leftoffset;
#ifndef NO_PNG_LUMPS
boolean isPNG = false;
#endif
frame = R_Char2Frame(lumpinfo[l].name[4]);
rotation = R_Char2Rotation(lumpinfo[l].name[5]);
@ -274,28 +280,35 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
// store sprite info in lookup tables
//FIXME : numspritelumps do not duplicate sprite replacements
W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0);
#ifndef NO_PNG_LUMPS
{
patch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC);
size_t len = W_LumpLengthPwad(wadnum, l);
// lump is a png so convert it
if (Picture_IsLumpPNG((UINT8 *)png, len))
{
// Dummy variables.
INT32 pngwidth, pngheight;
INT16 topoffset, leftoffset;
patch_t *converted = (patch_t *)Picture_PNGConvert((UINT8 *)png, PICFMT_PATCH, &pngwidth, &pngheight, &topoffset, &leftoffset, len, NULL, 0);
M_Memcpy(&patch, converted, sizeof(INT16)*4); // only copy the header because that's all we need
Z_Free(converted);
Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len);
isPNG = true;
}
Z_Free(png);
}
if (!isPNG)
#endif
spritecachedinfo[numspritelumps].width = SHORT(patch.width)<<FRACBITS;
spritecachedinfo[numspritelumps].offset = SHORT(patch.leftoffset)<<FRACBITS;
spritecachedinfo[numspritelumps].topoffset = SHORT(patch.topoffset)<<FRACBITS;
spritecachedinfo[numspritelumps].height = SHORT(patch.height)<<FRACBITS;
{
W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0);
width = SHORT(patch.width);
height = SHORT(patch.height);
topoffset = SHORT(patch.topoffset);
leftoffset = SHORT(patch.leftoffset);
}
spritecachedinfo[numspritelumps].width = width<<FRACBITS;
spritecachedinfo[numspritelumps].offset = leftoffset<<FRACBITS;
spritecachedinfo[numspritelumps].topoffset = topoffset<<FRACBITS;
spritecachedinfo[numspritelumps].height = height<<FRACBITS;
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (rendermode != render_none) // not for psprite

View File

@ -1685,10 +1685,8 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
// lump is a png so convert it
if (Picture_IsLumpPNG((UINT8 *)lumpdata, len))
{
// Dummy variables.
size_t newlen;
INT32 pngwidth, pngheight;
srcdata = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_PATCH, &pngwidth, &pngheight, NULL, NULL, len, &newlen, 0);
srcdata = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, &newlen, 0);
ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]);
M_Memcpy(ptr, srcdata, newlen);
Z_Free(srcdata);