mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-17 17:41:57 +00:00
Deferred patch updating
This commit is contained in:
parent
5db5e65b90
commit
dca643676c
12 changed files with 406 additions and 342 deletions
|
@ -262,37 +262,29 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
|||
INT32 pwidth, INT32 pheight,
|
||||
const patch_t *realpatch)
|
||||
{
|
||||
INT32 ncols;
|
||||
fixed_t xfrac, xfracstep;
|
||||
fixed_t yfracstep, scale_y;
|
||||
const column_t *patchcol;
|
||||
UINT8 *block = mipmap->data;
|
||||
INT32 bpp;
|
||||
INT32 blockmodulo;
|
||||
|
||||
if (pwidth <= 0 || pheight <= 0)
|
||||
return;
|
||||
|
||||
ncols = pwidth;
|
||||
|
||||
// source advance
|
||||
xfrac = 0;
|
||||
xfracstep = FRACUNIT;
|
||||
yfracstep = FRACUNIT;
|
||||
scale_y = FRACUNIT;
|
||||
fixed_t xfrac = 0;
|
||||
fixed_t xfracstep = FRACUNIT;
|
||||
fixed_t yfracstep = FRACUNIT;
|
||||
fixed_t scale_y = FRACUNIT;
|
||||
|
||||
bpp = format2bpp(mipmap->format);
|
||||
INT32 bpp = format2bpp(mipmap->format);
|
||||
|
||||
if (bpp < 1 || bpp > 4)
|
||||
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
|
||||
|
||||
// NOTE: should this actually be pblockwidth*bpp?
|
||||
blockmodulo = pblockwidth*bpp;
|
||||
INT32 blockmodulo = pblockwidth*bpp;
|
||||
|
||||
// Draw each column to the block cache
|
||||
for (; ncols--; block += bpp, xfrac += xfracstep)
|
||||
UINT8 *block = mipmap->data;
|
||||
|
||||
for (int x = 0; x < pwidth; x++, block += bpp, xfrac += xfracstep)
|
||||
{
|
||||
patchcol = &realpatch->columns[xfrac>>FRACBITS];
|
||||
const column_t *patchcol = &realpatch->columns[xfrac>>FRACBITS];
|
||||
|
||||
HWR_DrawColumnInCache(patchcol, block, mipmap,
|
||||
pblockheight, blockmodulo,
|
||||
|
@ -542,7 +534,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
|
|||
}
|
||||
|
||||
Z_Free(grMipmap->data);
|
||||
grMipmap->data = NULL;
|
||||
|
||||
if (makebitmap)
|
||||
{
|
||||
|
@ -576,8 +567,8 @@ void HWR_FreeTextureData(patch_t *patch)
|
|||
|
||||
if (vid.glstate == VID_GL_LIBRARY_LOADED)
|
||||
HWD.pfnDeleteTexture(grPatch->mipmap);
|
||||
if (grPatch->mipmap->data)
|
||||
Z_Free(grPatch->mipmap->data);
|
||||
|
||||
Z_Free(grPatch->mipmap->data);
|
||||
}
|
||||
|
||||
void HWR_FreeTexture(patch_t *patch)
|
||||
|
@ -641,8 +632,6 @@ void HWR_FreeTextureColormaps(patch_t *patch)
|
|||
Z_Free(next->data);
|
||||
if (next->colormap)
|
||||
Z_Free(next->colormap);
|
||||
next->data = NULL;
|
||||
next->colormap = NULL;
|
||||
HWD.pfnDeleteTexture(next);
|
||||
|
||||
// Free the old colormap mipmap from memory.
|
||||
|
@ -697,9 +686,7 @@ void HWR_InitMapTextures(void)
|
|||
static void FreeMapTexture(GLMapTexture_t *tex)
|
||||
{
|
||||
HWD.pfnDeleteTexture(&tex->mipmap);
|
||||
if (tex->mipmap.data)
|
||||
Z_Free(tex->mipmap.data);
|
||||
tex->mipmap.data = NULL;
|
||||
Z_Free(tex->mipmap.data);
|
||||
}
|
||||
|
||||
void HWR_FreeMapTextures(void)
|
||||
|
@ -897,6 +884,88 @@ static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
|
|||
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
static void HWR_UpdatePatchPixels(GLMipmap_t *mipmap, UINT8 *pixels, INT16 patchheight, bitarray_t *pixels_opaque, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
{
|
||||
INT32 bpp = format2bpp(mipmap->format);
|
||||
if (bpp < 1 || bpp > 4)
|
||||
I_Error("HWR_UpdatePatchPixels: no drawer defined for this bpp (%d)\n",bpp);
|
||||
|
||||
UINT8 *dest_pixels = (UINT8*)mipmap->data;
|
||||
|
||||
for (INT16 y = top; y < bottom; y++)
|
||||
{
|
||||
UINT8 *dest = &dest_pixels[(y * (mipmap->width * bpp)) + (left * bpp)];
|
||||
|
||||
for (INT16 x = left; x < right; x++)
|
||||
{
|
||||
UINT8 texel = 0x00;
|
||||
UINT8 alpha = 0x00;
|
||||
|
||||
size_t position = (x * patchheight) + y;
|
||||
|
||||
if (in_bit_array(pixels_opaque, position))
|
||||
{
|
||||
texel = pixels[position];
|
||||
alpha = 0xFF;
|
||||
|
||||
// Make pixel transparent if chroma keyed
|
||||
if ((mipmap->flags & TF_CHROMAKEYED) && texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)
|
||||
alpha = 0x00;
|
||||
}
|
||||
|
||||
UINT16 texelu16;
|
||||
RGBA_t colortemp;
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 2:
|
||||
texelu16 = (UINT16)((alpha<<8) | texel);
|
||||
memcpy(dest, &texelu16, sizeof(UINT16));
|
||||
break;
|
||||
case 3:
|
||||
colortemp = V_GetColor(texel);
|
||||
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
|
||||
break;
|
||||
case 4:
|
||||
colortemp = V_GetColor(texel);
|
||||
colortemp.s.alpha = alpha;
|
||||
memcpy(dest, &colortemp, sizeof(RGBA_t));
|
||||
break;
|
||||
// default is 1
|
||||
default:
|
||||
*dest = texel;
|
||||
break;
|
||||
}
|
||||
|
||||
dest += bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void HWR_UpdateMipmapRegion(patch_t *patch, GLMipmap_t *grMipmap, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
{
|
||||
GLPatch_t *grPatch = patch->hardware;
|
||||
|
||||
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
|
||||
|
||||
if (pixels_opaque == NULL || grMipmap->width == 0 || grMipmap->data == NULL)
|
||||
HWR_MakePatch(patch, grPatch, grMipmap, true);
|
||||
else
|
||||
HWR_UpdatePatchPixels(grMipmap, patch->pixels, patch->height, pixels_opaque, left, top, right, bottom);
|
||||
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
// If it does have the texture, then call pfnUpdateTextureRegion to update it
|
||||
if (!grMipmap->downloaded)
|
||||
HWD.pfnSetTexture(grMipmap);
|
||||
else
|
||||
HWD.pfnUpdateTextureRegion(grMipmap, left, top, right - left, bottom - top);
|
||||
|
||||
HWR_SetCurrentTexture(grMipmap);
|
||||
|
||||
// The system-memory data can be purged now.
|
||||
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_GetPatch : Downloads a patch to the hardware cache and make it ready for use
|
||||
// -----------------+
|
||||
|
@ -907,11 +976,12 @@ void HWR_GetPatch(patch_t *patch)
|
|||
HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
|
||||
}
|
||||
|
||||
void HWR_UpdatePatch(patch_t *patch)
|
||||
void HWR_UpdatePatchRegion(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
{
|
||||
if (!patch->hardware)
|
||||
Patch_CreateGL(patch);
|
||||
HWR_UpdatePatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
|
||||
|
||||
HWR_UpdateMipmapRegion(patch, ((GLPatch_t *)patch->hardware)->mipmap, left, top, right, bottom);
|
||||
}
|
||||
|
||||
// -------------------+
|
||||
|
|
|
@ -42,6 +42,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
|
|||
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
|
||||
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(UpdateTextureRegion) (GLMipmap_t *TexInfo, INT32 x, INT32 y, INT32 width, INT32 height);
|
||||
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
|
||||
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
|
||||
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
|
||||
|
@ -95,6 +96,7 @@ struct hwdriver_s
|
|||
ClearBuffer pfnClearBuffer;
|
||||
SetTexture pfnSetTexture;
|
||||
UpdateTexture pfnUpdateTexture;
|
||||
UpdateTextureRegion pfnUpdateTextureRegion;
|
||||
DeleteTexture pfnDeleteTexture;
|
||||
ReadRect pfnReadRect;
|
||||
GClipRect pfnGClipRect;
|
||||
|
|
|
@ -117,7 +117,7 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
|
|||
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
|
||||
|
||||
void HWR_GetPatch(patch_t *patch);
|
||||
void HWR_UpdatePatch(patch_t *patch);
|
||||
void HWR_UpdatePatchRegion(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom);
|
||||
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
|
||||
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
|
||||
patch_t *HWR_GetPic(lumpnum_t lumpnum);
|
||||
|
|
|
@ -1333,18 +1333,15 @@ void Flush(void)
|
|||
while (TexCacheHead)
|
||||
{
|
||||
FTextureInfo *pTexInfo = TexCacheHead;
|
||||
GLMipmap_t *texture = pTexInfo->texture;
|
||||
TexCacheHead = pTexInfo->next;
|
||||
|
||||
if (pTexInfo->downloaded)
|
||||
{
|
||||
pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
|
||||
pTexInfo->downloaded = 0;
|
||||
}
|
||||
|
||||
GLMipmap_t *texture = pTexInfo->texture;
|
||||
if (texture)
|
||||
texture->downloaded = 0;
|
||||
|
||||
TexCacheHead = pTexInfo->next;
|
||||
free(pTexInfo);
|
||||
}
|
||||
|
||||
|
@ -1746,9 +1743,9 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
|
|||
CurrentPolyFlags = PolyFlags;
|
||||
}
|
||||
|
||||
static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
|
||||
static RGBA_t *AllocTextureBuffer(unsigned width, unsigned height)
|
||||
{
|
||||
size_t size = pTexInfo->width * pTexInfo->height;
|
||||
size_t size = width * height;
|
||||
if (size > textureBufferSize)
|
||||
{
|
||||
textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t));
|
||||
|
@ -1756,116 +1753,143 @@ static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
|
|||
I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t)));
|
||||
textureBufferSize = size;
|
||||
}
|
||||
return textureBuffer;
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// UpdateTexture : Updates texture data.
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
||||
EXPORT void HWRAPI(UpdateTextureRegion) (GLMipmap_t *pTexInfo, INT32 x, INT32 y, INT32 width, INT32 height)
|
||||
{
|
||||
// Upload a texture
|
||||
GLuint num = pTexInfo->downloaded;
|
||||
boolean update = true;
|
||||
|
||||
INT32 w = pTexInfo->width, h = pTexInfo->height;
|
||||
INT32 i, j;
|
||||
INT32 i, j, dy;
|
||||
|
||||
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
|
||||
const GLvoid *ptex = NULL;
|
||||
RGBA_t *tex = NULL;
|
||||
|
||||
// Generate a new texture name.
|
||||
if (!num)
|
||||
// Generate a new texture ID if there is none
|
||||
if (pTexInfo->downloaded == 0)
|
||||
{
|
||||
pglGenTextures(1, &num);
|
||||
pTexInfo->downloaded = num;
|
||||
GLuint id = 0;
|
||||
pglGenTextures(1, &id);
|
||||
pTexInfo->downloaded = id;
|
||||
update = false;
|
||||
}
|
||||
|
||||
//GL_DBG_Printf("UpdateTexture %d %x\n", (INT32)num, pImgData);
|
||||
|
||||
if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88))
|
||||
if (pTexInfo->format == GL_TEXFMT_P_8 || pTexInfo->format == GL_TEXFMT_AP_88)
|
||||
{
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
ptex = AllocTextureBuffer(width, height);
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
for (j = y, dy = 0; j < y + height; j++, dy++)
|
||||
{
|
||||
for (i = 0; i < w; i++)
|
||||
const GLubyte *src = &pImgData[pTexInfo->width*j+x];
|
||||
RGBA_t *tex = &textureBuffer[width*dy];
|
||||
|
||||
for (i = x; i < x + width; i++)
|
||||
{
|
||||
if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) &&
|
||||
if ((*src == HWR_PATCHES_CHROMAKEY_COLORINDEX) &&
|
||||
(pTexInfo->flags & TF_CHROMAKEYED))
|
||||
{
|
||||
tex[w*j+i].s.red = 0;
|
||||
tex[w*j+i].s.green = 0;
|
||||
tex[w*j+i].s.blue = 0;
|
||||
tex[w*j+i].s.alpha = 0;
|
||||
tex->s.red = 0;
|
||||
tex->s.green = 0;
|
||||
tex->s.blue = 0;
|
||||
tex->s.alpha = 0;
|
||||
pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
|
||||
}
|
||||
else
|
||||
{
|
||||
tex[w*j+i].s.red = myPaletteData[*pImgData].s.red;
|
||||
tex[w*j+i].s.green = myPaletteData[*pImgData].s.green;
|
||||
tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue;
|
||||
tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha;
|
||||
tex->s.red = myPaletteData[*src].s.red;
|
||||
tex->s.green = myPaletteData[*src].s.green;
|
||||
tex->s.blue = myPaletteData[*src].s.blue;
|
||||
tex->s.alpha = myPaletteData[*src].s.alpha;
|
||||
}
|
||||
|
||||
pImgData++;
|
||||
src++;
|
||||
|
||||
if (pTexInfo->format == GL_TEXFMT_AP_88)
|
||||
{
|
||||
if (!(pTexInfo->flags & TF_CHROMAKEYED))
|
||||
tex[w*j+i].s.alpha = *pImgData;
|
||||
pImgData++;
|
||||
tex->s.alpha = *src;
|
||||
src++;
|
||||
}
|
||||
|
||||
tex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_RGBA)
|
||||
{
|
||||
// Directly upload the texture data without any kind of conversion.
|
||||
ptex = pImgData;
|
||||
if (x == 0 && y == 0 && width == pTexInfo->width && height == pTexInfo->height)
|
||||
{
|
||||
// Directly upload the texture data without any kind of conversion.
|
||||
ptex = pImgData;
|
||||
}
|
||||
else
|
||||
{
|
||||
RGBA_t *src_pixels = (RGBA_t *)pTexInfo->data;
|
||||
|
||||
ptex = AllocTextureBuffer(width, height);
|
||||
|
||||
for (j = y, dy = 0; j < y + height; j++, dy++)
|
||||
{
|
||||
RGBA_t *src = &src_pixels[pTexInfo->width*j+x];
|
||||
RGBA_t *tex = &textureBuffer[width*dy];
|
||||
|
||||
for (i = x; i < x + width; i++)
|
||||
{
|
||||
*tex = *src;
|
||||
tex++;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
|
||||
{
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
ptex = AllocTextureBuffer(width, height);
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
for (j = y, dy = 0; j < y + height; j++, dy++)
|
||||
{
|
||||
for (i = 0; i < w; i++)
|
||||
const GLubyte *src = &pImgData[pTexInfo->width*j+x];
|
||||
RGBA_t *tex = &textureBuffer[width*dy];
|
||||
for (i = x; i < x + width; i++)
|
||||
{
|
||||
tex[w*j+i].s.red = *pImgData;
|
||||
tex[w*j+i].s.green = *pImgData;
|
||||
tex[w*j+i].s.blue = *pImgData;
|
||||
pImgData++;
|
||||
tex[w*j+i].s.alpha = *pImgData;
|
||||
pImgData++;
|
||||
tex->s.red = *src;
|
||||
tex->s.green = *src;
|
||||
tex->s.blue = *src;
|
||||
src++;
|
||||
tex->s.alpha = *src;
|
||||
src++;
|
||||
tex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks
|
||||
{
|
||||
AllocTextureBuffer(pTexInfo);
|
||||
ptex = tex = textureBuffer;
|
||||
ptex = AllocTextureBuffer(width, height);
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
for (j = y, dy = 0; j < y + height; j++, dy++)
|
||||
{
|
||||
for (i = 0; i < w; i++)
|
||||
const GLubyte *src = &pImgData[width*j+x];
|
||||
RGBA_t *tex = &textureBuffer[width*dy];
|
||||
for (i = x; i < x + width; i++)
|
||||
{
|
||||
tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't
|
||||
tex[w*j+i].s.green = 255;
|
||||
tex[w*j+i].s.blue = 255;
|
||||
tex[w*j+i].s.alpha = *pImgData;
|
||||
pImgData++;
|
||||
// 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't
|
||||
tex->s.red = 255;
|
||||
tex->s.green = 255;
|
||||
tex->s.blue = 255;
|
||||
tex->s.alpha = *src;
|
||||
src++;
|
||||
tex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format);
|
||||
|
||||
pglBindTexture(GL_TEXTURE_2D, num);
|
||||
tex_downloaded = num;
|
||||
pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
|
||||
tex_downloaded = pTexInfo->downloaded;
|
||||
|
||||
// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
|
||||
if (pTexInfo->flags & TF_TRANSPARENT)
|
||||
|
@ -1881,64 +1905,60 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
|
||||
if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
|
||||
{
|
||||
//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
if (MipMap)
|
||||
{
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
|
||||
if (pTexInfo->flags & TF_TRANSPARENT)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
|
||||
else
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
|
||||
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
}
|
||||
}
|
||||
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8)
|
||||
{
|
||||
//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
if (MipMap)
|
||||
{
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
|
||||
if (pTexInfo->flags & TF_TRANSPARENT)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
|
||||
else
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
|
||||
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MipMap)
|
||||
{
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
// Control the mipmap level of detail
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higher the detail
|
||||
if (pTexInfo->flags & TF_TRANSPARENT)
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
|
||||
else
|
||||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update)
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
else
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1956,6 +1976,11 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
|||
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter);
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
|
||||
{
|
||||
UpdateTextureRegion(pTexInfo, 0, 0, pTexInfo->width, pTexInfo->height);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// SetTexture : The mipmap becomes the current texture source
|
||||
// -----------------+
|
||||
|
|
|
@ -424,7 +424,7 @@ static int lib_patch_copy(lua_State *L)
|
|||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
Patch_Update(patch, patch_update_buffer, src_img_width, src_img_height, PICFMT_FLAT16, sx, sy, sw, sh, dx, dy, copy_transparent);
|
||||
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, PICFMT_FLAT16, sx, sy, sw, sh, dx, dy, copy_transparent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
24
src/r_defs.h
24
src/r_defs.h
|
@ -809,15 +809,14 @@ typedef struct
|
|||
//
|
||||
typedef struct
|
||||
{
|
||||
UINT8 type;
|
||||
|
||||
INT16 width, height;
|
||||
INT16 leftoffset, topoffset;
|
||||
INT32 width_mask;
|
||||
|
||||
UINT8 *pixels;
|
||||
column_t *columns;
|
||||
post_t *posts;
|
||||
|
||||
UINT8 type;
|
||||
|
||||
void *hardware; // OpenGL patch, allocated whenever necessary
|
||||
void *flats[4]; // The patch as flats
|
||||
|
@ -827,6 +826,25 @@ typedef struct
|
|||
#endif
|
||||
} patch_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
patch_t patch;
|
||||
|
||||
post_t *posts;
|
||||
} staticpatch_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
patch_t patch;
|
||||
|
||||
boolean is_dirty;
|
||||
boolean update_columns;
|
||||
|
||||
INT16 rect_dirty[4]; // left, top, right, bottom
|
||||
|
||||
bitarray_t *pixels_opaque;
|
||||
} dynamicpatch_t;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
|
389
src/r_patch.c
389
src/r_patch.c
|
@ -19,13 +19,12 @@
|
|||
#include "hardware/hw_glob.h"
|
||||
#endif
|
||||
|
||||
//
|
||||
// Creates a patch.
|
||||
//
|
||||
static void Patch_MarkDirtyRect(dynamicpatch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom);
|
||||
static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch);
|
||||
|
||||
patch_t *Patch_Create(INT16 width, INT16 height)
|
||||
{
|
||||
patch_t *patch = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL);
|
||||
patch_t *patch = Z_Calloc(sizeof(staticpatch_t), PU_PATCH, NULL);
|
||||
|
||||
patch->width = width;
|
||||
patch->height = height;
|
||||
|
@ -36,18 +35,57 @@ patch_t *Patch_Create(INT16 width, INT16 height)
|
|||
|
||||
patch_t *Patch_CreateDynamic(INT16 width, INT16 height)
|
||||
{
|
||||
patch_t *patch = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL);
|
||||
patch_t *patch = Z_Calloc(sizeof(dynamicpatch_t), PU_PATCH, NULL);
|
||||
|
||||
patch->width = width;
|
||||
patch->height = height;
|
||||
patch->type = PATCH_TYPE_DYNAMIC;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||
dpatch->pixels_opaque = Z_Calloc(BIT_ARRAY_SIZE(width * height), PU_PATCH_DATA, NULL);
|
||||
dpatch->is_dirty = false;
|
||||
dpatch->update_columns = false;
|
||||
|
||||
Patch_ClearDirtyRect(dpatch);
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
static void Patch_MarkDirtyRect(dynamicpatch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
{
|
||||
if (left < dpatch->rect_dirty[0])
|
||||
dpatch->rect_dirty[0] = left;
|
||||
if (top < dpatch->rect_dirty[1])
|
||||
dpatch->rect_dirty[1] = top;
|
||||
if (right > dpatch->rect_dirty[2])
|
||||
dpatch->rect_dirty[2] = right;
|
||||
if (bottom > dpatch->rect_dirty[3])
|
||||
dpatch->rect_dirty[3] = bottom;
|
||||
}
|
||||
|
||||
static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch)
|
||||
{
|
||||
dpatch->rect_dirty[0] = INT16_MAX;
|
||||
dpatch->rect_dirty[1] = INT16_MAX;
|
||||
dpatch->rect_dirty[2] = INT16_MIN;
|
||||
dpatch->rect_dirty[3] = INT16_MIN;
|
||||
}
|
||||
|
||||
static void Patch_InitDynamicColumns(patch_t *patch)
|
||||
{
|
||||
if (patch->columns == NULL)
|
||||
patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL);
|
||||
|
||||
for (INT32 x = 0; x < patch->width; x++)
|
||||
{
|
||||
column_t *column = &patch->columns[x];
|
||||
column->pixels = &patch->pixels[patch->height * x];
|
||||
}
|
||||
}
|
||||
|
||||
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source)
|
||||
{
|
||||
patch_t *patch = Patch_Create(0, 0);
|
||||
patch_t *patch = (patch_t*)Patch_Create(0, 0);
|
||||
if (!source)
|
||||
return patch;
|
||||
|
||||
|
@ -67,10 +105,12 @@ patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source)
|
|||
patch->width_mask = width_po2 - 1;
|
||||
|
||||
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_MakeColumns(source, patch->width, patch->width, patch->pixels, patch->columns, patch->posts, false);
|
||||
staticpatch_t *spatch = (staticpatch_t*)patch;
|
||||
spatch->posts = Z_Calloc(sizeof(post_t) * total_posts, PU_PATCH_DATA, NULL);
|
||||
|
||||
Patch_MakeColumns(source, patch->width, patch->width, patch->pixels, patch->columns, spatch->posts, false);
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
@ -141,9 +181,9 @@ void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width,
|
|||
// Other functions
|
||||
//
|
||||
|
||||
static void Patch_RebuildColumn(column_t *column, INT16 height, UINT8 *is_opaque)
|
||||
static void Patch_RebuildColumn(column_t *column, INT32 x, INT16 height, bitarray_t *is_opaque)
|
||||
{
|
||||
post_t *post;
|
||||
post_t *post = NULL;
|
||||
boolean was_opaque = false;
|
||||
|
||||
unsigned post_count = column->num_posts;
|
||||
|
@ -152,7 +192,7 @@ static void Patch_RebuildColumn(column_t *column, INT16 height, UINT8 *is_opaque
|
|||
for (INT32 y = 0; y < height; y++)
|
||||
{
|
||||
// End span if we have a transparent pixel
|
||||
if (!is_opaque[y])
|
||||
if (!in_bit_array(is_opaque, (x * height) + y))
|
||||
{
|
||||
was_opaque = false;
|
||||
continue;
|
||||
|
@ -195,7 +235,13 @@ column_t *Patch_GetColumn(patch_t *patch, unsigned column)
|
|||
|
||||
void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
|
||||
{
|
||||
if (x < 0 || x >= patch->width || patch->columns == NULL)
|
||||
if (x < 0 || x >= patch->width)
|
||||
return NULL;
|
||||
|
||||
if (Patch_NeedsUpdate(patch))
|
||||
Patch_DoDynamicUpdate(patch);
|
||||
|
||||
if (patch->columns == NULL)
|
||||
return NULL;
|
||||
|
||||
column_t *column = &patch->columns[x];
|
||||
|
@ -249,12 +295,8 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
|
|||
else if (inbpp == PICDEPTH_8BPP)
|
||||
writePixelFunc = PicFmt_WritePixel_i8o8;
|
||||
|
||||
column_t *column = NULL;
|
||||
|
||||
boolean did_update_column = false;
|
||||
|
||||
// If the patch is empty
|
||||
if (!patch->columns)
|
||||
if (!patch->pixels)
|
||||
{
|
||||
if (!pixel_is_opaque)
|
||||
{
|
||||
|
@ -264,167 +306,39 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
|
|||
|
||||
if (patch->pixels == NULL)
|
||||
patch->pixels = Z_Calloc(patch->width * patch->height, PU_PATCH_DATA, NULL);
|
||||
if (patch->columns == NULL)
|
||||
patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL);
|
||||
}
|
||||
|
||||
column = &patch->columns[x];
|
||||
column->pixels = &patch->pixels[patch->height * x];
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
column = &patch->columns[x];
|
||||
column->pixels = &patch->pixels[patch->height * x];
|
||||
// No pixel in this position, so columns need to be rebuilt
|
||||
if (!in_bit_array(dpatch->pixels_opaque, position))
|
||||
dpatch->update_columns = true;
|
||||
|
||||
for (unsigned i = 0; i < column->num_posts; i++)
|
||||
{
|
||||
post_t *post = &column->posts[i];
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
writePixelFunc(&patch->pixels[position], pixel);
|
||||
|
||||
int this_topdelta = (int)post->topdelta;
|
||||
int next_topdelta;
|
||||
if (i < column->num_posts - 1)
|
||||
next_topdelta = column->posts[i + 1].topdelta;
|
||||
else
|
||||
next_topdelta = patch->height;
|
||||
|
||||
// Handle the case where this is the first post, and the pixel is before it
|
||||
if (i == 0 && y < this_topdelta)
|
||||
{
|
||||
if (!pixel_is_opaque)
|
||||
{
|
||||
// If the pixel is transparent, ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
column->posts = Z_Realloc(column->posts, sizeof(post_t) * (column->num_posts + 1), PU_PATCH_DATA, NULL);
|
||||
|
||||
memmove(&column->posts[1], &column->posts[0], column->num_posts * sizeof(post_t));
|
||||
|
||||
column->num_posts++;
|
||||
|
||||
post_t *dest_post = &column->posts[0];
|
||||
dest_post->topdelta = (unsigned)y;
|
||||
dest_post->length = 1;
|
||||
dest_post->data_offset = dest_post->topdelta;
|
||||
|
||||
writePixelFunc(&column->pixels[dest_post->data_offset], pixel);
|
||||
|
||||
did_update_column = true;
|
||||
|
||||
break;
|
||||
}
|
||||
// Pixel is inside a post
|
||||
else if (y >= this_topdelta && y < this_topdelta + (signed)post->length)
|
||||
{
|
||||
// Handle the case where the pixel needs to be removed
|
||||
if (!pixel_is_opaque)
|
||||
{
|
||||
if (!transparent_overwrite)
|
||||
continue;
|
||||
|
||||
int resulting_post_length = y - post->topdelta;
|
||||
if ((resulting_post_length == (signed)post->length - 1 && i == column->num_posts - 1)
|
||||
|| (resulting_post_length == 0))
|
||||
{
|
||||
if (resulting_post_length == 0)
|
||||
post->topdelta++;
|
||||
post->length--;
|
||||
if (post->length == 0)
|
||||
{
|
||||
if (column->num_posts > 1 && i < column->num_posts - 1)
|
||||
memmove(&column->posts[i], &column->posts[i + 1], (column->num_posts - i) * sizeof(post_t));
|
||||
column->num_posts--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
column->num_posts++;
|
||||
column->posts = Z_Realloc(column->posts, sizeof(post_t) * column->num_posts, PU_PATCH_DATA, NULL);
|
||||
|
||||
if (i != column->num_posts)
|
||||
memmove(&column->posts[i + 1], &column->posts[i], ((column->num_posts - 1) - i) * sizeof(post_t));
|
||||
|
||||
column->posts[i + 1].length = column->posts[i].length - resulting_post_length - 1;
|
||||
column->posts[i + 1].topdelta = y + 1;
|
||||
column->posts[i + 1].data_offset = column->posts[i + 1].topdelta;
|
||||
column->posts[i].length = resulting_post_length;
|
||||
}
|
||||
}
|
||||
else
|
||||
writePixelFunc(&column->pixels[post->data_offset + (y - post->topdelta)], pixel);
|
||||
|
||||
did_update_column = true;
|
||||
|
||||
break;
|
||||
}
|
||||
// After this post, but before the next one
|
||||
else if (y >= this_topdelta + (signed)post->length && y < next_topdelta)
|
||||
{
|
||||
if (!pixel_is_opaque)
|
||||
{
|
||||
// If the pixel is transparent, ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
post_t *dest_post = NULL;
|
||||
|
||||
column->posts = Z_Realloc(column->posts, sizeof(post_t) * (column->num_posts + 1), PU_PATCH_DATA, NULL);
|
||||
|
||||
if (i == column->num_posts - 1)
|
||||
dest_post = &column->posts[column->num_posts];
|
||||
else
|
||||
{
|
||||
memmove(&column->posts[i + 1], &column->posts[i], (column->num_posts - i) * sizeof(post_t));
|
||||
dest_post = &column->posts[i];
|
||||
}
|
||||
|
||||
column->num_posts++;
|
||||
|
||||
dest_post->topdelta = (unsigned)y;
|
||||
dest_post->length = 1;
|
||||
dest_post->data_offset = dest_post->topdelta;
|
||||
|
||||
writePixelFunc(&column->pixels[dest_post->data_offset], pixel);
|
||||
|
||||
did_update_column = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
dpatch->is_dirty = true;
|
||||
}
|
||||
|
||||
if (!did_update_column && column && column->num_posts == 0)
|
||||
{
|
||||
if (!pixel_is_opaque)
|
||||
{
|
||||
// If the pixel is transparent, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
column->num_posts = 1;
|
||||
column->posts = Z_Realloc(column->posts, sizeof(post_t) * column->num_posts, PU_PATCH_DATA, NULL);
|
||||
|
||||
post_t *post = &column->posts[0];
|
||||
post->topdelta = (unsigned)y;
|
||||
post->length = 1;
|
||||
post->data_offset = post->topdelta;
|
||||
|
||||
writePixelFunc(&column->pixels[post->data_offset], pixel);
|
||||
|
||||
did_update_column = true;
|
||||
}
|
||||
|
||||
if (did_update_column)
|
||||
{
|
||||
Patch_FreeMiscData(patch);
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (patch->hardware)
|
||||
HWR_UpdatePatch(patch);
|
||||
#endif
|
||||
}
|
||||
if (dpatch->is_dirty)
|
||||
Patch_MarkDirtyRect(dpatch, x, y, x + 1, y + 1);
|
||||
}
|
||||
|
||||
void Patch_Update(patch_t *patch,
|
||||
void Patch_UpdatePixels(patch_t *patch,
|
||||
void *pixels, INT32 src_img_width, INT32 src_img_height,
|
||||
pictureformat_t informat,
|
||||
INT32 sx, INT32 sy, INT32 sw, INT32 sh, INT32 dx, INT32 dy,
|
||||
|
@ -436,10 +350,6 @@ void Patch_Update(patch_t *patch,
|
|||
if (src_img_width <= 0 || src_img_height <= 0 || sw <= 0 || sh <= 0)
|
||||
return;
|
||||
|
||||
boolean did_update = false;
|
||||
|
||||
if (patch->columns == NULL)
|
||||
patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL);
|
||||
if (patch->pixels == NULL)
|
||||
patch->pixels = Z_Calloc(patch->width * patch->height, PU_PATCH_DATA, NULL);
|
||||
|
||||
|
@ -467,35 +377,34 @@ void Patch_Update(patch_t *patch,
|
|||
}
|
||||
}
|
||||
|
||||
if (readPixelFunc == NULL)
|
||||
I_Error("Patch_Update: unsupported input format");
|
||||
|
||||
INT32 inbpp = Picture_FormatBPP(informat);
|
||||
|
||||
if (inbpp == PICDEPTH_32BPP)
|
||||
switch (Picture_FormatBPP(informat))
|
||||
{
|
||||
case PICDEPTH_32BPP:
|
||||
getAlphaFunc = PicFmt_GetAlpha_32bpp;
|
||||
writePixelFunc = PicFmt_WritePixel_i32o8;
|
||||
}
|
||||
else if (inbpp == PICDEPTH_16BPP)
|
||||
{
|
||||
break;
|
||||
case PICDEPTH_16BPP:
|
||||
getAlphaFunc = PicFmt_GetAlpha_16bpp;
|
||||
writePixelFunc = PicFmt_WritePixel_i16o8;
|
||||
}
|
||||
else if (inbpp == PICDEPTH_8BPP)
|
||||
{
|
||||
break;
|
||||
case PICDEPTH_8BPP:
|
||||
getAlphaFunc = PicFmt_GetAlpha_8bpp;
|
||||
writePixelFunc = PicFmt_WritePixel_i8o8;
|
||||
break;
|
||||
}
|
||||
|
||||
UINT8 *is_opaque = malloc(patch->height * sizeof(UINT8));
|
||||
if (!is_opaque)
|
||||
{
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
if (readPixelFunc == NULL || writePixelFunc == NULL || getAlphaFunc == NULL)
|
||||
I_Error("Patch_UpdatePixels: unsupported input format");
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
|
||||
INT32 dest_x1 = max(0, dx);
|
||||
INT32 dest_x2 = min(dx + sw, patch->width);
|
||||
INT32 dest_y1 = max(0, dy);
|
||||
INT32 dest_y2 = min(dy + sh, patch->height);
|
||||
|
||||
Patch_MarkDirtyRect(dpatch, dest_x1, dest_y1, dest_x2, dest_y2);
|
||||
|
||||
// Write columns
|
||||
for (INT32 x = dx; x < dx + sw; x++, sx++)
|
||||
{
|
||||
if (x < 0 || sx < 0)
|
||||
|
@ -503,19 +412,6 @@ void Patch_Update(patch_t *patch,
|
|||
else if (x >= patch->width || sx >= src_img_width)
|
||||
break;
|
||||
|
||||
column_t *column = &patch->columns[x];
|
||||
column->pixels = &patch->pixels[patch->height * x];
|
||||
|
||||
memset(is_opaque, 0, patch->height * sizeof(UINT8));
|
||||
|
||||
for (unsigned i = 0; i < column->num_posts; i++)
|
||||
{
|
||||
post_t *post = &column->posts[i];
|
||||
memset(&is_opaque[post->topdelta], 1, post->length);
|
||||
}
|
||||
|
||||
boolean did_update_column = false;
|
||||
|
||||
INT32 src_y = sy;
|
||||
|
||||
for (INT32 y = dy; y < dy + sh; y++, src_y++)
|
||||
|
@ -534,39 +430,73 @@ void Patch_Update(patch_t *patch,
|
|||
if (input != NULL)
|
||||
opaque = getAlphaFunc(input, 0) > 0;
|
||||
|
||||
size_t position = (x * patch->height) + y;
|
||||
|
||||
if (!opaque)
|
||||
{
|
||||
if (transparent_overwrite)
|
||||
{
|
||||
is_opaque[y] = false;
|
||||
did_update = did_update_column = true;
|
||||
unset_bit_array(dpatch->pixels_opaque, position);
|
||||
dpatch->update_columns = dpatch->is_dirty = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
did_update = did_update_column = true;
|
||||
is_opaque[y] = true;
|
||||
writePixelFunc(&column->pixels[y], input);
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
writePixelFunc(&patch->pixels[position], input);
|
||||
dpatch->update_columns = dpatch->is_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!did_update_column)
|
||||
continue;
|
||||
boolean Patch_NeedsUpdate(patch_t *patch)
|
||||
{
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return false;
|
||||
|
||||
Patch_RebuildColumn(column, patch->height, is_opaque);
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
return dpatch->is_dirty;
|
||||
}
|
||||
|
||||
void Patch_DoDynamicUpdate(patch_t *patch)
|
||||
{
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
if (!dpatch->is_dirty)
|
||||
return;
|
||||
|
||||
if (patch->columns == NULL)
|
||||
Patch_InitDynamicColumns(patch);
|
||||
|
||||
if (dpatch->update_columns)
|
||||
{
|
||||
for (INT32 x = dpatch->rect_dirty[0]; x < dpatch->rect_dirty[2]; x++)
|
||||
Patch_RebuildColumn(&patch->columns[x], x, patch->height, dpatch->pixels_opaque);
|
||||
}
|
||||
|
||||
if (did_update)
|
||||
{
|
||||
Patch_FreeMiscData(patch);
|
||||
Patch_FreeMiscData(patch);
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (patch->hardware)
|
||||
HWR_UpdatePatch(patch);
|
||||
if (patch->hardware)
|
||||
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
free(is_opaque);
|
||||
dpatch->is_dirty = false;
|
||||
dpatch->update_columns = false;
|
||||
|
||||
Patch_ClearDirtyRect(dpatch);
|
||||
}
|
||||
|
||||
bitarray_t *Patch_GetOpaqueRegions(patch_t *patch)
|
||||
{
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return NULL;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
return dpatch->pixels_opaque;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -606,18 +536,21 @@ static void Patch_FreeData(patch_t *patch)
|
|||
|
||||
Patch_FreeMiscData(patch);
|
||||
|
||||
if (patch->type == PATCH_TYPE_DYNAMIC)
|
||||
if (patch->type == PATCH_TYPE_STATIC)
|
||||
{
|
||||
for (INT32 x = 0; x < patch->width; x++)
|
||||
Z_Free(patch->columns[x].posts);
|
||||
staticpatch_t *spatch = (staticpatch_t*)patch;
|
||||
Z_Free(spatch->posts);
|
||||
}
|
||||
else if (patch->type == PATCH_TYPE_DYNAMIC)
|
||||
{
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||
for (INT32 x = 0; x < dpatch->patch.width; x++)
|
||||
Z_Free(dpatch->patch.columns[x].posts);
|
||||
Z_Free(dpatch->pixels_opaque);
|
||||
}
|
||||
|
||||
if (patch->pixels)
|
||||
Z_Free(patch->pixels);
|
||||
if (patch->columns)
|
||||
Z_Free(patch->columns);
|
||||
if (patch->posts)
|
||||
Z_Free(patch->posts);
|
||||
Z_Free(patch->pixels);
|
||||
Z_Free(patch->columns);
|
||||
}
|
||||
|
||||
void Patch_Free(patch_t *patch)
|
||||
|
|
|
@ -29,12 +29,17 @@ patch_t *Patch_CreateDynamic(INT16 width, INT16 height);
|
|||
|
||||
void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y);
|
||||
void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32 x, INT32 y, boolean transparent_overwrite);
|
||||
void Patch_Update(patch_t *patch,
|
||||
void Patch_UpdatePixels(patch_t *patch,
|
||||
void *pixels, INT32 src_img_width, INT32 src_img_height,
|
||||
pictureformat_t informat,
|
||||
INT32 sx, INT32 sy, INT32 sw, INT32 sh, INT32 dx, INT32 dy,
|
||||
boolean transparent_overwrite);
|
||||
|
||||
boolean Patch_NeedsUpdate(patch_t *patch);
|
||||
void Patch_DoDynamicUpdate(patch_t *patch);
|
||||
|
||||
bitarray_t *Patch_GetOpaqueRegions(patch_t *patch);
|
||||
|
||||
void Patch_Free(patch_t *patch);
|
||||
void Patch_FreeMiscData(patch_t *patch);
|
||||
|
||||
|
|
|
@ -364,7 +364,6 @@ void *Picture_PatchConvert(
|
|||
|
||||
out->columns = Z_Calloc(sizeof(column_t) * out->width, PU_PATCH_DATA, NULL);
|
||||
out->pixels = Z_Calloc(max_pixels * (outbpp / 8), PU_PATCH_DATA, NULL);
|
||||
out->posts = NULL;
|
||||
|
||||
UINT8 *imgptr = out->pixels;
|
||||
|
||||
|
@ -407,8 +406,9 @@ void *Picture_PatchConvert(
|
|||
{
|
||||
num_posts++;
|
||||
|
||||
out->posts = Z_Realloc(out->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL);
|
||||
post = &out->posts[num_posts - 1];
|
||||
staticpatch_t *spatch = (staticpatch_t*)out;
|
||||
spatch->posts = Z_Realloc(spatch->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL);
|
||||
post = &spatch->posts[num_posts - 1];
|
||||
post->topdelta = (unsigned)y;
|
||||
post->length = 0;
|
||||
post->data_offset = post_data_offset;
|
||||
|
@ -437,7 +437,10 @@ void *Picture_PatchConvert(
|
|||
{
|
||||
column_t *column = &out->columns[x];
|
||||
if (column->num_posts > 0)
|
||||
column->posts = &out->posts[column_posts[x]];
|
||||
{
|
||||
staticpatch_t *spatch = (staticpatch_t*)out;
|
||||
column->posts = &spatch->posts[column_posts[x]];
|
||||
}
|
||||
if (old_pixels != out->pixels)
|
||||
column->pixels = out->pixels + (column->pixels - old_pixels);
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(ClearBuffer);
|
||||
GETFUNC(SetTexture);
|
||||
GETFUNC(UpdateTexture);
|
||||
GETFUNC(UpdateTextureRegion);
|
||||
GETFUNC(DeleteTexture);
|
||||
GETFUNC(ReadRect);
|
||||
GETFUNC(GClipRect);
|
||||
|
|
|
@ -1934,6 +1934,7 @@ void VID_StartupOpenGL(void)
|
|||
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
|
||||
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
|
||||
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
|
||||
HWD.pfnUpdateTextureRegion = hwSym("UpdateTextureRegion", NULL);
|
||||
HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
|
||||
HWD.pfnReadRect = hwSym("ReadRect",NULL);
|
||||
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
|
||||
|
|
|
@ -514,6 +514,9 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
|||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (Patch_NeedsUpdate(patch))
|
||||
Patch_DoDynamicUpdate(patch);
|
||||
|
||||
if (patch->columns == NULL || rendermode == render_none)
|
||||
return;
|
||||
|
||||
|
@ -798,6 +801,9 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
|||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (Patch_NeedsUpdate(patch))
|
||||
Patch_DoDynamicUpdate(patch);
|
||||
|
||||
if (patch->columns == NULL || rendermode == render_none)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in a new issue