Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
Show changes
Commits on Source (23)
...@@ -276,22 +276,18 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, ...@@ -276,22 +276,18 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
INT32 pwidth, INT32 pheight, INT32 pwidth, INT32 pheight,
const patch_t *realpatch) const patch_t *realpatch)
{ {
INT32 ncols;
fixed_t xfrac, xfracstep; fixed_t xfrac, xfracstep;
fixed_t yfracstep, scale_y; fixed_t yfracstep, scale_y;
const column_t *patchcol;
UINT8 *block = mipmap->data; UINT8 *block = mipmap->data;
INT32 bpp; INT32 bpp;
INT32 blockmodulo; INT32 blockmodulo;
RGBA_t *palette; RGBA_t *palette;
if (pwidth <= 0 || pheight <= 0) if (pwidth <= 0 || pheight <= 0 || realpatch->columns == NULL)
return; return;
palette = HWR_GetTexturePalette(); palette = HWR_GetTexturePalette();
ncols = pwidth;
// source advance // source advance
xfrac = 0; xfrac = 0;
xfracstep = FRACUNIT; xfracstep = FRACUNIT;
...@@ -299,7 +295,6 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, ...@@ -299,7 +295,6 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
scale_y = FRACUNIT; scale_y = FRACUNIT;
bpp = format2bpp(mipmap->format); bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4) if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
...@@ -307,9 +302,11 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, ...@@ -307,9 +302,11 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
blockmodulo = pblockwidth*bpp; blockmodulo = pblockwidth*bpp;
// Draw each column to the block cache // Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep) 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, HWR_DrawColumnInCache(patchcol, block, mipmap,
pblockheight, blockmodulo, pblockheight, blockmodulo,
...@@ -319,6 +316,39 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, ...@@ -319,6 +316,39 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
} }
} }
static void HWR_DrawPatchInCacheRGBA(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight,
INT32 pwidth, INT32 pheight,
const patch_t *realpatch)
{
if (pwidth <= 0 || pheight <= 0)
return;
INT32 bpp = format2bpp(mipmap->format);
if (bpp != 4)
I_Error("HWR_DrawPatchInCacheRGBA: invalid bpp (%d)\n",bpp);
fixed_t stepx = (pwidth << FRACBITS) / pblockwidth;
fixed_t stepy = (pheight << FRACBITS) / pblockheight;
fixed_t posy = 0;
RGBA_t *block = (RGBA_t*)mipmap->data;
const RGBA_t *source = (RGBA_t*)realpatch->pixels;
for (int j = 0; j < pblockheight; j++)
{
fixed_t posx = 0;
RGBA_t *dest = &block[j * mipmap->width];
for (int i = 0; i < pblockwidth; i++)
{
size_t position = ((posx >> FRACBITS) * pheight) + (posy >> FRACBITS);
*dest++ = source[position];
posx += stepx;
}
posy += stepy;
}
}
// This function we use for caching patches that belong to textures // This function we use for caching patches that belong to textures
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight, INT32 pblockwidth, INT32 pblockheight,
...@@ -511,7 +541,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t ...@@ -511,7 +541,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
} }
// patch may be NULL if grMipmap has been initialised already and makebitmap is false // patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) void HWR_MakePatch (patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{ {
if (grMipmap->width == 0) if (grMipmap->width == 0)
{ {
...@@ -530,16 +560,15 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm ...@@ -530,16 +560,15 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
} }
Z_Free(grMipmap->data); Z_Free(grMipmap->data);
grMipmap->data = NULL;
if (makebitmap) if (makebitmap)
{ {
MakeBlock(grMipmap); MakeBlock(grMipmap);
HWR_DrawPatchInCache(grMipmap, if (patch->format == PATCH_FORMAT_RGBA)
grMipmap->width, grMipmap->height, HWR_DrawPatchInCacheRGBA(grMipmap, grMipmap->width, grMipmap->height, patch->width, patch->height, patch);
patch->width, patch->height, else
patch); HWR_DrawPatchInCache(grMipmap, grMipmap->width, grMipmap->height, patch->width, patch->height, patch);
} }
} }
...@@ -564,8 +593,8 @@ void HWR_FreeTextureData(patch_t *patch) ...@@ -564,8 +593,8 @@ void HWR_FreeTextureData(patch_t *patch)
if (vid.glstate == VID_GL_LIBRARY_LOADED) if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnDeleteTexture(grPatch->mipmap); HWD.pfnDeleteTexture(grPatch->mipmap);
if (grPatch->mipmap->data)
Z_Free(grPatch->mipmap->data); Z_Free(grPatch->mipmap->data);
} }
void HWR_FreeTexture(patch_t *patch) void HWR_FreeTexture(patch_t *patch)
...@@ -919,6 +948,115 @@ static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap) ...@@ -919,6 +948,115 @@ static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); 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_UpdatePatchPixelsRGBA(GLMipmap_t *mipmap, RGBA_t *pixels, INT16 patchheight, INT16 left, INT16 top, INT16 right, INT16 bottom)
{
INT32 bpp = format2bpp(mipmap->format);
if (bpp != 4)
I_Error("HWR_UpdatePatchPixelsRGBA: invalid 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++)
{
RGBA_t texel = pixels[(x * patchheight) + y];
memcpy(dest, &texel, sizeof(RGBA_t));
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;
if (grMipmap->width == 0 || grMipmap->data == NULL || patch->type == PATCH_TYPE_STATIC)
HWR_MakePatch(patch, grPatch, grMipmap, true);
else
{
if (patch->format == PATCH_FORMAT_RGBA)
HWR_UpdatePatchPixelsRGBA(grMipmap, (RGBA_t*)patch->pixels, patch->width, left, top, right, bottom);
else
{
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
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 // HWR_GetPatch : Downloads a patch to the hardware cache and make it ready for use
// -----------------+ // -----------------+
...@@ -929,6 +1067,14 @@ void HWR_GetPatch(patch_t *patch) ...@@ -929,6 +1067,14 @@ void HWR_GetPatch(patch_t *patch)
HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap); HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
} }
void HWR_UpdatePatchRegion(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom)
{
if (!patch->hardware)
Patch_CreateGL(patch);
HWR_UpdateMipmapRegion(patch, ((GLPatch_t *)patch->hardware)->mipmap, left, top, right, bottom);
}
// -------------------+ // -------------------+
// HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color // HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color
// -------------------+ // -------------------+
...@@ -941,7 +1087,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap) ...@@ -941,7 +1087,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap)
Patch_CreateGL(patch); Patch_CreateGL(patch);
grPatch = patch->hardware; grPatch = patch->hardware;
if (colormap == colormaps || colormap == NULL) if (colormap == colormaps || colormap == NULL || patch->format == PATCH_FORMAT_RGBA)
{ {
// Load the default (green) color in hardware cache // Load the default (green) color in hardware cache
HWR_GetPatch(patch); HWR_GetPatch(patch);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "../m_misc.h" //FIL_WriteFile() #include "../m_misc.h" //FIL_WriteFile()
#include "../r_main.h" #include "../r_main.h"
#include "../r_patch.h"
#include "../w_wad.h" #include "../w_wad.h"
#include "../z_zone.h" #include "../z_zone.h"
#include "../v_video.h" #include "../v_video.h"
...@@ -58,6 +59,66 @@ static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229 ...@@ -58,6 +59,66 @@ static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127};
//
// -----------------+
// HWR_DrawPatch : Draw a 'tile' graphic
// Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar
// -----------------+
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
{
FOutVector v[4];
FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2
// | /|
// |/ |
// 0--1
float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
if (Patch_NeedsUpdate(gpatch, false))
Patch_DoDynamicUpdate(gpatch, false);
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK)
{
case V_NOSCALEPATCH:
pdup = 2.0f;
break;
case V_SMALLSCALEPATCH:
pdup = 2.0f * FIXED_TO_FLOAT(vid.fsmalldup);
break;
case V_MEDSCALEPATCH:
pdup = 2.0f * FIXED_TO_FLOAT(vid.fmeddup);
break;
}
if (option & V_NOSCALESTART)
sdup = 2.0f;
v[0].x = v[3].x = (x*sdup-(gpatch->leftoffset)*pdup)/vid.width - 1;
v[2].x = v[1].x = (x*sdup+(gpatch->width-gpatch->leftoffset)*pdup)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdup-(gpatch->topoffset)*pdup)/vid.height;
v[2].y = v[3].y = 1-(y*sdup+(gpatch->height-gpatch->topoffset)*pdup)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = hwrPatch->max_s;
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
// clip it since it is used for bunny scroll in doom I
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{ {
FOutVector v[4]; FOutVector v[4];
...@@ -77,6 +138,9 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p ...@@ -77,6 +138,9 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
UINT8 perplayershuffle = 0; UINT8 perplayershuffle = 0;
if (Patch_NeedsUpdate(gpatch, false))
Patch_DoDynamicUpdate(gpatch, false);
// make patch ready in hardware cache // make patch ready in hardware cache
if (!colormap) if (!colormap)
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
...@@ -319,6 +383,9 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, ...@@ -319,6 +383,9 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
UINT8 perplayershuffle = 0; UINT8 perplayershuffle = 0;
if (Patch_NeedsUpdate(gpatch, false))
Patch_DoDynamicUpdate(gpatch, false);
// make patch ready in hardware cache // make patch ready in hardware cache
if (!colormap) if (!colormap)
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
......
...@@ -39,6 +39,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); ...@@ -39,6 +39,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo); EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (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(DeleteTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data); EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
...@@ -93,6 +94,7 @@ struct hwdriver_s ...@@ -93,6 +94,7 @@ struct hwdriver_s
ClearBuffer pfnClearBuffer; ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture; SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture; UpdateTexture pfnUpdateTexture;
UpdateTextureRegion pfnUpdateTextureRegion;
DeleteTexture pfnDeleteTexture; DeleteTexture pfnDeleteTexture;
ReadScreenTexture pfnReadScreenTexture; ReadScreenTexture pfnReadScreenTexture;
GClipRect pfnGClipRect; GClipRect pfnGClipRect;
......
...@@ -117,6 +117,7 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); ...@@ -117,6 +117,7 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *patch); void HWR_GetPatch(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_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum); void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
......
...@@ -37,9 +37,10 @@ void HWR_ClearSkyDome(void); ...@@ -37,9 +37,10 @@ void HWR_ClearSkyDome(void);
void HWR_BuildSkyDome(void); void HWR_BuildSkyDome(void);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_SetViewSize(void); void HWR_SetViewSize(void);
void HWR_DrawPatch( patch_t *gpatch, INT32 x, INT32 y, INT32 option );
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_MakePatch(patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
......
...@@ -1083,18 +1083,15 @@ void Flush(void) ...@@ -1083,18 +1083,15 @@ void Flush(void)
while (TexCacheHead) while (TexCacheHead)
{ {
FTextureInfo *pTexInfo = TexCacheHead; FTextureInfo *pTexInfo = TexCacheHead;
GLMipmap_t *texture = pTexInfo->texture; TexCacheHead = pTexInfo->next;
if (pTexInfo->downloaded) if (pTexInfo->downloaded)
{
pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded); pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
pTexInfo->downloaded = 0;
}
GLMipmap_t *texture = pTexInfo->texture;
if (texture) if (texture)
texture->downloaded = 0; texture->downloaded = 0;
TexCacheHead = pTexInfo->next;
free(pTexInfo); free(pTexInfo);
} }
...@@ -1479,9 +1476,9 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) ...@@ -1479,9 +1476,9 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
CurrentPolyFlags = 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) if (size > textureBufferSize)
{ {
textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t)); textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t));
...@@ -1489,116 +1486,143 @@ static void AllocTextureBuffer(GLMipmap_t *pTexInfo) ...@@ -1489,116 +1486,143 @@ static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t))); I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t)));
textureBufferSize = size; textureBufferSize = size;
} }
return textureBuffer;
} }
// -----------------+ // -----------------+
// UpdateTexture : Updates texture data. // 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; boolean update = true;
INT32 w = pTexInfo->width, h = pTexInfo->height; INT32 i, j, dy;
INT32 i, j;
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
const GLvoid *ptex = NULL; const GLvoid *ptex = NULL;
RGBA_t *tex = NULL;
// Generate a new texture name. // Generate a new texture ID if there is none
if (!num) if (pTexInfo->downloaded == 0)
{ {
pglGenTextures(1, &num); GLuint id = 0;
pTexInfo->downloaded = num; pglGenTextures(1, &id);
pTexInfo->downloaded = id;
update = false; 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 = AllocTextureBuffer(width, height);
ptex = tex = textureBuffer;
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)) (pTexInfo->flags & TF_CHROMAKEYED))
{ {
tex[w*j+i].s.red = 0; tex->s.red = 0;
tex[w*j+i].s.green = 0; tex->s.green = 0;
tex[w*j+i].s.blue = 0; tex->s.blue = 0;
tex[w*j+i].s.alpha = 0; tex->s.alpha = 0;
pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
} }
else else
{ {
tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; tex->s.red = myPaletteData[*src].s.red;
tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; tex->s.green = myPaletteData[*src].s.green;
tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; tex->s.blue = myPaletteData[*src].s.blue;
tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; tex->s.alpha = myPaletteData[*src].s.alpha;
} }
pImgData++; src++;
if (pTexInfo->format == GL_TEXFMT_AP_88) if (pTexInfo->format == GL_TEXFMT_AP_88)
{ {
if (!(pTexInfo->flags & TF_CHROMAKEYED)) if (!(pTexInfo->flags & TF_CHROMAKEYED))
tex[w*j+i].s.alpha = *pImgData; tex->s.alpha = *src;
pImgData++; src++;
} }
tex++;
} }
} }
} }
else if (pTexInfo->format == GL_TEXFMT_RGBA) else if (pTexInfo->format == GL_TEXFMT_RGBA)
{ {
// Directly upload the texture data without any kind of conversion. if (x == 0 && y == 0 && width == pTexInfo->width && height == pTexInfo->height)
ptex = pImgData; {
// 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) else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
{ {
AllocTextureBuffer(pTexInfo); ptex = AllocTextureBuffer(width, height);
ptex = tex = textureBuffer;
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->s.red = *src;
tex[w*j+i].s.green = *pImgData; tex->s.green = *src;
tex[w*j+i].s.blue = *pImgData; tex->s.blue = *src;
pImgData++; src++;
tex[w*j+i].s.alpha = *pImgData; tex->s.alpha = *src;
pImgData++; src++;
tex++;
} }
} }
} }
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks
{ {
AllocTextureBuffer(pTexInfo); ptex = AllocTextureBuffer(width, height);
ptex = tex = textureBuffer;
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 // 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->s.red = 255;
tex[w*j+i].s.blue = 255; tex->s.green = 255;
tex[w*j+i].s.alpha = *pImgData; tex->s.blue = 255;
pImgData++; tex->s.alpha = *src;
src++;
tex++;
} }
} }
} }
else else
GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format); GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format);
pglBindTexture(GL_TEXTURE_2D, num); pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
tex_downloaded = num; tex_downloaded = pTexInfo->downloaded;
// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
if (pTexInfo->flags & TF_TRANSPARENT) if (pTexInfo->flags & TF_TRANSPARENT)
...@@ -1614,64 +1638,60 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) ...@@ -1614,64 +1638,60 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) 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) 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); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
if (pTexInfo->flags & TF_TRANSPARENT) 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 else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
} }
else else
{ {
if (update) 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 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) 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) 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); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
if (pTexInfo->flags & TF_TRANSPARENT) 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 else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
} }
else else
{ {
if (update) 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 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 else
{ {
if (MipMap) 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 // 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) 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 else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
} }
else else
{ {
if (update) 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 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);
} }
} }
...@@ -1689,6 +1709,11 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) ...@@ -1689,6 +1709,11 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); 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 // SetTexture : The mipmap becomes the current texture source
// -----------------+ // -----------------+
......
...@@ -92,7 +92,13 @@ enum patch { ...@@ -92,7 +92,13 @@ enum patch {
patch_width, patch_width,
patch_height, patch_height,
patch_leftoffset, patch_leftoffset,
patch_topoffset patch_topoffset,
patch_iseditable,
// Methods
patch_getPixel,
patch_setPixel,
patch_copy,
patch_clear
}; };
static const char *const patch_opt[] = { static const char *const patch_opt[] = {
"valid", "valid",
...@@ -100,6 +106,12 @@ static const char *const patch_opt[] = { ...@@ -100,6 +106,12 @@ static const char *const patch_opt[] = {
"height", "height",
"leftoffset", "leftoffset",
"topoffset", "topoffset",
"is_editable",
// Methods
"getPixel",
"setPixel",
"copy",
"clear",
NULL}; NULL};
static int patch_fields_ref = LUA_NOREF; static int patch_fields_ref = LUA_NOREF;
...@@ -286,6 +298,225 @@ static int colormap_get(lua_State *L) ...@@ -286,6 +298,225 @@ static int colormap_get(lua_State *L)
return 1; return 1;
} }
static int lib_patch_getPixel(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
int x = luaL_checkinteger(L, 2);
int y = luaL_checkinteger(L, 3);
void *pixel = Patch_GetPixel(patch, x, y);
if (pixel == NULL)
lua_pushnil(L);
else if (patch->format == PATCH_FORMAT_RGBA)
{
UINT32 px = *(UINT32 *)pixel;
lua_pushinteger(L, px);
}
else
{
UINT8 px = *(UINT8 *)pixel;
lua_pushinteger(L, px);
}
return 1;
}
static int lib_patch_setPixel(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
int x = luaL_checkinteger(L, 2);
int y = luaL_checkinteger(L, 3);
int color = luaL_checkinteger(L, 4);
if (patch->format == PATCH_FORMAT_RGBA)
{
UINT32 pixel = (UINT32)color;
Patch_SetPixel(patch, &pixel, PICFMT_FLAT32, x, y, true);
}
else if (color >= 0 && color <= 0xFF)
{
UINT16 pixel_u8 = (UINT8)color;
Patch_SetPixel(patch, &pixel_u8, PICFMT_FLAT, x, y, true);
}
else
{
UINT16 empty_px = 0x0000;
Patch_SetPixel(patch, &empty_px, PICFMT_FLAT16, x, y, true);
}
return 0;
}
static void *patch_update_buffer = NULL;
static size_t patch_update_buffer_size = 0;
static void img_prepare_buffer(size_t size)
{
if (size > patch_update_buffer_size)
{
patch_update_buffer = Z_Realloc(patch_update_buffer, size, PU_STATIC, NULL);
patch_update_buffer_size = size;
}
}
static void img_get_pixels_from_table(lua_State *L, size_t size)
{
UINT16 *buf = (UINT16 *)patch_update_buffer;
memset(buf, 0, patch_update_buffer_size);
for (size_t i = 0; i < size; i++)
{
int pal_idx = -1;
if (lua_next(L, -2) != 0)
{
if (lua_isnumber(L,-1))
{
int value = luaL_checkinteger(L, -1);
if (value >= 0 && value <= 0xFF)
pal_idx = value;
}
lua_pop(L, 1);
}
if (pal_idx != -1)
buf[i] = 0xFF00 | (UINT8)pal_idx;
else
buf[i] = 0x0000;
}
}
static void img_get_rgba_pixels_from_table(lua_State *L, size_t size)
{
UINT32 *buf = (UINT32 *)patch_update_buffer;
memset(buf, 0, patch_update_buffer_size);
for (size_t i = 0; i < size; i++)
{
UINT32 color = 0;
if (lua_next(L, -2) != 0)
{
if (lua_isnumber(L,-1))
color = (UINT32)luaL_checkinteger(L, -1);
lua_pop(L, 1);
}
buf[i] = color;
}
}
static int lib_patch_copy(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
if (patch->type != PATCH_TYPE_DYNAMIC)
return luaL_error(L, "cannot modify a static patch");
int src_img_width = -1;
int src_img_height = -1;
patch_t *src_patch = NULL;
if (!lua_istable(L, 2))
{
src_patch = *((patch_t **)luaL_checkudata(L, 2, META_PATCH));
if (!src_patch)
return LUA_ErrInvalid(L, "patch_t");
src_img_width = src_patch->width;
src_img_height = src_patch->height;
}
else
{
src_img_width = luaL_optinteger(L, 3, patch->width);
src_img_height = luaL_optinteger(L, 4, patch->height);
lua_remove(L, 3);
lua_remove(L, 3);
if (src_img_width <= 0)
return luaL_error(L, "invalid source image width");
if (src_img_height <= 0)
return luaL_error(L, "invalid source image height");
}
int sx = luaL_optinteger(L, 3, 0);
int sy = luaL_optinteger(L, 4, 0);
int sw = luaL_optinteger(L, 5, src_img_width);
int sh = luaL_optinteger(L, 6, src_img_height);
int dx = luaL_optinteger(L, 7, 0);
int dy = luaL_optinteger(L, 8, 0);
boolean copy_transparent = lua_optboolean(L, 9);
boolean use_pixel_alpha = lua_optboolean(L, 10);
if (sw <= 0)
return luaL_error(L, "invalid copy rect width");
if (sh <= 0)
return luaL_error(L, "invalid copy rect height");
if (lua_istable(L, 2))
{
size_t size = (unsigned)(src_img_width * src_img_height);
if (lua_objlen(L, 2) + 1 != size)
return luaL_error(L, "invalid table length");
lua_pushvalue(L, 2);
lua_pushnil(L);
int format;
if (patch->format == PATCH_FORMAT_RGBA)
{
img_prepare_buffer(size * 4);
img_get_rgba_pixels_from_table(L, size);
format = PICFMT_FLAT32;
}
else
{
img_prepare_buffer(size * 2);
img_get_pixels_from_table(L, size);
format = PICFMT_FLAT16;
}
lua_pop(L, 2);
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, format, sx, sy, sw, sh, dx, dy, copy_transparent);
}
else
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, use_pixel_alpha, copy_transparent);
return 0;
}
static int lib_patch_clear(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
if (patch->type != PATCH_TYPE_DYNAMIC)
return luaL_error(L, "cannot modify a static patch");
Patch_Clear(patch);
return 0;
}
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
...@@ -316,13 +547,56 @@ static int patch_get(lua_State *L) ...@@ -316,13 +547,56 @@ static int patch_get(lua_State *L)
case patch_topoffset: case patch_topoffset:
lua_pushinteger(L, patch->topoffset); lua_pushinteger(L, patch->topoffset);
break; break;
case patch_iseditable:
lua_pushboolean(L, patch->type == PATCH_TYPE_STATIC ? true : false);
break;
case patch_getPixel:
lua_pushcfunction(L, lib_patch_getPixel);
break;
case patch_setPixel:
lua_pushcfunction(L, lib_patch_setPixel);
break;
case patch_copy:
lua_pushcfunction(L, lib_patch_copy);
break;
case patch_clear:
lua_pushcfunction(L, lib_patch_clear);
break;
} }
return 1; return 1;
} }
static int patch_set(lua_State *L) static int patch_set(lua_State *L)
{ {
return luaL_error(L, LUA_QL("patch_t") " struct cannot be edited by Lua."); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
if (patch->type == PATCH_TYPE_STATIC)
return luaL_error(L, "cannot modify a static patch");
enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref);
switch (field)
{
case patch_leftoffset:
patch->leftoffset = luaL_checkinteger(L, 3);
break;
case patch_topoffset:
patch->topoffset = luaL_checkinteger(L, 3);
break;
default:
return luaL_error(L, "cannot set " LUA_QL("patch_t") " field " LUA_QS ".", lua_tostring(L, 2));
}
return 0;
}
static int patch_gc(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
if (patch->type == PATCH_TYPE_DYNAMIC)
Patch_Free(patch);
return 0;
} }
static int camera_get(lua_State *L) static int camera_get(lua_State *L)
...@@ -455,33 +729,64 @@ static int camera_set(lua_State *L) ...@@ -455,33 +729,64 @@ static int camera_set(lua_State *L)
return 0; return 0;
} }
// // Image lib
// lib_draw enum patch_fmt {
// patch_fmt_palette,
patch_fmt_rgba
};
static int libd_patchExists(lua_State *L) static const char *const patch_fmt_opt[] = {
"palette",
"rgba",
NULL};
static int lib_image_create(lua_State *L)
{
int w = luaL_checkinteger(L, 1);
int h = luaL_checkinteger(L, 2);
enum patch_fmt fmt = luaL_checkoption(L, 3, "palette", patch_fmt_opt);
if (w <= 0)
return luaL_error(L, "invalid image width %d", w);
if (h <= 0)
return luaL_error(L, "invalid image width %d", h);
UINT8 format = 0;
switch(fmt)
{
case patch_fmt_palette:
format = PATCH_FORMAT_PALETTE;
break;
case patch_fmt_rgba:
format = PATCH_FORMAT_RGBA;
break;
}
LUA_PushUserdata(L, Patch_CreateDynamic(w, h, format), META_PATCH);
return 1;
}
static int lib_image_patchExists(lua_State *L)
{ {
HUDONLY
lua_pushboolean(L, W_LumpExists(luaL_checkstring(L, 1))); lua_pushboolean(L, W_LumpExists(luaL_checkstring(L, 1)));
return 1; return 1;
} }
static int libd_cachePatch(lua_State *L) static int lib_image_getPatch(lua_State *L)
{ {
HUDONLY
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
return 1; return 1;
} }
// v.getSpritePatch(sprite, [frame, [angle, [rollangle]]]) // image.getSpritePatch(sprite, [frame, [angle, [rollangle]]])
static int libd_getSpritePatch(lua_State *L) static int lib_image_getSpritePatch(lua_State *L)
{ {
UINT32 i; // sprite prefix UINT32 i; // sprite prefix
UINT32 frame = 0; // 'A' UINT32 frame = 0; // 'A'
UINT8 angle = 0; UINT8 angle = 0;
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
HUDONLY
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK
{ {
...@@ -539,14 +844,14 @@ static int libd_getSpritePatch(lua_State *L) ...@@ -539,14 +844,14 @@ static int libd_getSpritePatch(lua_State *L)
} }
#endif #endif
// push both the patch and it's "flip" value // push both the patch and its "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]]) // image.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]])
static int libd_getSprite2Patch(lua_State *L) static int lib_image_getSprite2Patch(lua_State *L)
{ {
INT32 i; // skin number INT32 i; // skin number
playersprite_t j; // sprite2 prefix playersprite_t j; // sprite2 prefix
...@@ -650,12 +955,51 @@ static int libd_getSprite2Patch(lua_State *L) ...@@ -650,12 +955,51 @@ static int libd_getSprite2Patch(lua_State *L)
} }
#endif #endif
// push both the patch and it's "flip" value // push both the patch and its "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
static luaL_Reg lib_image[] = {
{"create", lib_image_create},
{"patchExists", lib_image_patchExists},
{"getPatch", lib_image_getPatch},
{"getSpritePatch", lib_image_getSpritePatch},
{"getSprite2Patch", lib_image_getSprite2Patch},
{NULL, NULL}
};
//
// lib_draw
//
static int libd_patchExists(lua_State *L)
{
HUDONLY
return lib_image_patchExists(L);
}
static int libd_cachePatch(lua_State *L)
{
HUDONLY
return lib_image_getPatch(L);
}
// v.getSpritePatch(sprite, [frame, [angle, [rollangle]]])
static int libd_getSpritePatch(lua_State *L)
{
HUDONLY
return lib_image_getSpritePatch(L);
}
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]])
static int libd_getSprite2Patch(lua_State *L)
{
HUDONLY
return lib_image_getSprite2Patch(L);
}
static int libd_draw(lua_State *L) static int libd_draw(lua_State *L)
{ {
INT32 x, y, flags; INT32 x, y, flags;
...@@ -1465,15 +1809,28 @@ int LUA_HudLib(lua_State *L) ...@@ -1465,15 +1809,28 @@ int LUA_HudLib(lua_State *L)
LUA_RegisterUserdataMetatable(L, META_HUDINFO, hudinfo_get, hudinfo_set, hudinfo_num); LUA_RegisterUserdataMetatable(L, META_HUDINFO, hudinfo_get, hudinfo_set, hudinfo_num);
LUA_RegisterUserdataMetatable(L, META_COLORMAP, colormap_get, NULL, NULL); LUA_RegisterUserdataMetatable(L, META_COLORMAP, colormap_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_PATCH, patch_get, patch_set, NULL);
LUA_RegisterUserdataMetatable(L, META_CAMERA, camera_get, camera_set, NULL); LUA_RegisterUserdataMetatable(L, META_CAMERA, camera_get, camera_set, NULL);
luaL_newmetatable(L, META_PATCH);
lua_pushcfunction(L, patch_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, patch_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, patch_gc);
lua_setfield(L, -2, "__gc");
lua_pop(L,1);
patch_fields_ref = Lua_CreateFieldTable(L, patch_opt); patch_fields_ref = Lua_CreateFieldTable(L, patch_opt);
camera_fields_ref = Lua_CreateFieldTable(L, camera_opt); camera_fields_ref = Lua_CreateFieldTable(L, camera_opt);
LUA_RegisterGlobalUserdata(L, "hudinfo", lib_getHudInfo, NULL, lib_hudinfolen); LUA_RegisterGlobalUserdata(L, "hudinfo", lib_getHudInfo, NULL, lib_hudinfolen);
luaL_register(L, "hud", lib_hud); luaL_register(L, "hud", lib_hud);
luaL_register(L, "image", lib_image);
return 0; return 0;
} }
......
...@@ -51,54 +51,42 @@ sprcache_t *spritecachedinfo; ...@@ -51,54 +51,42 @@ sprcache_t *spritecachedinfo;
lighttable_t *colormaps; lighttable_t *colormaps;
lighttable_t *fadecolormap; lighttable_t *fadecolormap;
colorlookup_t r_colorlookup;
// for debugging/info purposes // for debugging/info purposes
size_t flatmemory, spritememory, texturememory; size_t flatmemory, spritememory, texturememory;
// highcolor stuff
INT16 color8to16[256]; // remap color index to highcolor rgb value
INT16 *hicolormaps; // test a 32k colormap remaps high -> high
// Blends two pixels together, using the equation // Blends two pixels together, using the equation
// that matches the specified alpha style. // that matches the specified alpha style.
UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{ {
RGBA_t output; RGBA_t output;
INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
#define clamp(c) max(min((c), 0xFF), 0x00)
INT16 fullalpha = clamp(((INT16)foreground.s.alpha) - (0xFF - alpha));
if (style == AST_TRANSLUCENT) if (style == AST_TRANSLUCENT)
{ {
if (fullalpha <= 0) UINT8 beta = 0xFF - fullalpha;
output.rgba = background.rgba; output.s.red = ((background.s.red * beta) + (foreground.s.red * fullalpha)) / 0xFF;
else output.s.green = ((background.s.green * beta) + (foreground.s.green * fullalpha)) / 0xFF;
{ output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * fullalpha)) / 0xFF;
// don't go too high output.s.alpha = clamp(((INT16)background.s.alpha) + fullalpha);
if (fullalpha >= 0xFF)
fullalpha = 0xFF;
alpha = (UINT8)fullalpha;
// if the background pixel is empty,
// match software and don't blend anything
if (!background.s.alpha)
{
// ...unless the foreground pixel ISN'T actually translucent.
if (alpha == 0xFF)
output.rgba = foreground.rgba;
else
output.rgba = 0;
}
else
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = 0xFF;
}
}
return output.rgba;
} }
#define clamp(c) max(min(c, 0xFF), 0x00);
else else
{ {
float falpha = ((float)alpha / 256.0f); float falpha = ((float)fullalpha / 255.0f);
float fr = ((float)foreground.s.red * falpha); float fr = ((float)foreground.s.red * falpha);
float fg = ((float)foreground.s.green * falpha); float fg = ((float)foreground.s.green * falpha);
float fb = ((float)foreground.s.blue * falpha); float fb = ((float)foreground.s.blue * falpha);
output.s.alpha = clamp(((INT16)background.s.alpha) + fullalpha);
if (style == AST_ADD) if (style == AST_ADD)
{ {
output.s.red = clamp((int)(background.s.red + fr)); output.s.red = clamp((int)(background.s.red + fr));
...@@ -119,22 +107,68 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph ...@@ -119,22 +107,68 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph
} }
else if (style == AST_MODULATE) else if (style == AST_MODULATE)
{ {
fr = ((float)foreground.s.red / 256.0f); fr = ((float)foreground.s.red / 255.0f);
fg = ((float)foreground.s.green / 256.0f); fg = ((float)foreground.s.green / 255.0f);
fb = ((float)foreground.s.blue / 256.0f); fb = ((float)foreground.s.blue / 255.0f);
output.s.red = clamp((int)(background.s.red * fr)); output.s.red = clamp((int)(background.s.red * fr));
output.s.green = clamp((int)(background.s.green * fg)); output.s.green = clamp((int)(background.s.green * fg));
output.s.blue = clamp((int)(background.s.blue * fb)); output.s.blue = clamp((int)(background.s.blue * fb));
} }
// just copy the pixel // just copy the pixel
else if (style == AST_COPY) else
output.rgba = foreground.rgba; {
if (foreground.s.alpha == 0x00)
output.rgba = background.rgba;
else
{
if (foreground.s.alpha != 0x00)
foreground.s.alpha = 0xFF;
output.rgba = foreground.rgba;
}
}
}
#undef clamp
return output.rgba;
}
static UINT32 BlendPixelForTexture(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{
RGBA_t output;
if (style == AST_TRANSLUCENT)
{
INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
if (fullalpha <= 0)
output.rgba = background.rgba;
else
{
// don't go too high
if (fullalpha >= 0xFF)
fullalpha = 0xFF;
alpha = (UINT8)fullalpha;
// if the background pixel is empty, match software and don't blend anything
if (!background.s.alpha)
{
// ...unless the foreground pixel ISN'T actually translucent.
if (alpha == 0xFF)
output.rgba = foreground.rgba;
else
output.rgba = 0;
}
else
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = 0xFF;
}
}
output.s.alpha = 0xFF;
return output.rgba; return output.rgba;
} }
#undef clamp
return 0; return ASTBlendPixel(background, foreground, style, alpha);
} }
INT32 ASTTextureBlendingThreshold[2] = {255/11, (10*255/11)}; INT32 ASTTextureBlendingThreshold[2] = {255/11, (10*255/11)};
...@@ -152,13 +186,13 @@ UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UIN ...@@ -152,13 +186,13 @@ UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UIN
if (alpha < ASTTextureBlendingThreshold[0]) if (alpha < ASTTextureBlendingThreshold[0])
return background.rgba; return background.rgba;
return ASTBlendPixel(background, foreground, style, alpha); return BlendPixelForTexture(background, foreground, style, alpha);
} }
else // just copy the pixel else // just copy the pixel
return foreground.rgba; return foreground.rgba;
} }
else else
return ASTBlendPixel(background, foreground, style, alpha); return BlendPixelForTexture(background, foreground, style, alpha);
} }
// Blends two palette indexes for a texture patch, then // Blends two palette indexes for a texture patch, then
...@@ -190,18 +224,16 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT ...@@ -190,18 +224,16 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
// just copy the pixel // just copy the pixel
else if (style == AST_COPY) else if (style == AST_COPY)
return foreground; return foreground;
// use ASTBlendPixel for all other blend modes // use ASTBlendPixel for all other blend modes and find the nearest color in the palette
// and find the nearest colour in the palette
else if (style != AST_TRANSLUCENT) else if (style != AST_TRANSLUCENT)
{ {
RGBA_t texel; RGBA_t texel;
RGBA_t bg = V_GetMasterColor(background); RGBA_t bg = V_GetMasterColor(background);
RGBA_t fg = V_GetMasterColor(foreground); RGBA_t fg = V_GetMasterColor(foreground);
texel.rgba = ASTBlendPixel(bg, fg, style, alpha); texel.rgba = BlendPixelForTexture(bg, fg, style, alpha);
return NearestColor(texel.s.red, texel.s.green, texel.s.blue); return NearestColor(texel.s.red, texel.s.green, texel.s.blue);
} }
// fallback if all above fails, somehow
// return the background pixel
return background; return background;
} }
......
...@@ -866,12 +866,14 @@ typedef struct ...@@ -866,12 +866,14 @@ typedef struct
// //
typedef struct typedef struct
{ {
UINT8 type;
UINT8 format;
INT16 width, height; INT16 width, height;
INT16 leftoffset, topoffset; INT16 leftoffset, topoffset;
UINT8 *pixels; UINT8 *pixels;
column_t *columns; column_t *columns;
post_t *posts;
void *hardware; // OpenGL patch, allocated whenever necessary void *hardware; // OpenGL patch, allocated whenever necessary
void *flats[4]; // The patch as flats void *flats[4]; // The patch as flats
...@@ -881,6 +883,26 @@ typedef struct ...@@ -881,6 +883,26 @@ typedef struct
#endif #endif
} patch_t; } 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
INT16 column_dirty[2]; // left, right
bitarray_t *pixels_opaque;
} dynamicpatch_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif #endif
......
...@@ -19,21 +19,213 @@ ...@@ -19,21 +19,213 @@
#include "hardware/hw_glob.h" #include "hardware/hw_glob.h"
#endif #endif
// static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch);
// Creates a patch. static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch);
//
static boolean Patch_CheckDirtyColumns(dynamicpatch_t *dpatch);
static void Patch_ClearDirtyColumns(dynamicpatch_t *dpatch);
patch_t *Patch_Create(INT16 width, INT16 height) 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;
patch->type = PATCH_TYPE_STATIC;
patch->format = PATCH_FORMAT_PALETTE;
return patch;
}
patch_t *Patch_CreateDynamic(INT16 width, INT16 height, UINT8 format)
{
patch_t *patch = Z_Calloc(sizeof(dynamicpatch_t), PU_PATCH, NULL);
patch->width = width; patch->width = width;
patch->height = height; patch->height = height;
patch->type = PATCH_TYPE_DYNAMIC;
patch->format = format;
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
dpatch->is_dirty = false;
dpatch->update_columns = false;
if (format == PATCH_FORMAT_PALETTE)
dpatch->pixels_opaque = Z_Calloc(BIT_ARRAY_SIZE(width * height), PU_PATCH_DATA, NULL);
else if (format == PATCH_FORMAT_RGBA)
patch->pixels = Z_Calloc(patch->width * patch->height * Patch_GetBpp(patch), PU_PATCH_DATA, NULL);
Patch_ClearDirtyRect(dpatch);
Patch_ClearDirtyColumns(dpatch);
return patch; return patch;
} }
void Patch_MarkDirtyRect(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom)
{
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
left = max(0, left);
right = min(right, patch->width);
top = max(0, top);
bottom = min(bottom, patch->height);
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;
if (left < dpatch->column_dirty[0])
dpatch->column_dirty[0] = left;
if (right > dpatch->column_dirty[1])
dpatch->column_dirty[1] = right;
}
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch)
{
patch_t *patch = (patch_t*)dpatch;
// left
if (dpatch->rect_dirty[0] < 0
|| dpatch->rect_dirty[0] > patch->width
|| dpatch->rect_dirty[0] >= dpatch->rect_dirty[2]) // right
return false;
// top
if (dpatch->rect_dirty[1] < 0
|| dpatch->rect_dirty[1] > patch->height
|| dpatch->rect_dirty[1] >= dpatch->rect_dirty[3]) // bottom
return false;
// right
if (dpatch->rect_dirty[2] > patch->width
|| dpatch->rect_dirty[2] < 0
|| dpatch->rect_dirty[2] <= dpatch->rect_dirty[0]) // left
return false;
// bottom
if (dpatch->rect_dirty[3] > patch->height
|| dpatch->rect_dirty[3] < 0
|| dpatch->rect_dirty[3] <= dpatch->rect_dirty[1]) // top
return false;
return true;
}
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 boolean Patch_CheckDirtyColumns(dynamicpatch_t *dpatch)
{
patch_t *patch = (patch_t*)dpatch;
// left
if (dpatch->column_dirty[0] < 0
|| dpatch->column_dirty[0] > patch->width
|| dpatch->column_dirty[0] >= dpatch->column_dirty[1]) // right
return false;
// right
if (dpatch->column_dirty[1] > patch->width
|| dpatch->column_dirty[1] < 0
|| dpatch->column_dirty[1] <= dpatch->column_dirty[0]) // left
return false;
return true;
}
static void Patch_ClearDirtyColumns(dynamicpatch_t *dpatch)
{
dpatch->column_dirty[0] = INT16_MAX;
dpatch->column_dirty[1] = 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);
size_t bpp = Patch_GetBpp(patch);
for (INT32 x = 0; x < patch->width; x++)
{
column_t *column = &patch->columns[x];
column->pixels = &patch->pixels[patch->height * x * bpp];
}
}
void Patch_Clear(patch_t *patch)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return;
size_t total_pixels = patch->width * patch->height;
memset(patch->pixels, 0, total_pixels * sizeof(UINT8));
if (patch->columns)
{
for (INT32 x = 0; x < patch->width; x++)
patch->columns[x].num_posts = 0;
}
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
if (dpatch->pixels_opaque)
memset(dpatch->pixels_opaque, 0, BIT_ARRAY_SIZE(total_pixels));
dpatch->is_dirty = dpatch->update_columns = true;
}
void Patch_ClearRect(patch_t *patch, INT16 x, INT16 y, INT16 width, INT16 height)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return;
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
for (INT16 dy = y; dy < y + height; dy++)
{
if (dy < 0)
continue;
else if (dy >= patch->height)
break;
for (INT16 dx = x; dx < x + width; dx++)
{
if (dx < 0)
continue;
else if (dx >= patch->width)
break;
size_t position = (dx * patch->height) + dy;
if (patch->format == PATCH_FORMAT_RGBA)
{
UINT32 *pixels = (UINT32 *)patch->pixels;
pixels[position] = 0;
}
else if (dpatch->pixels_opaque)
{
unset_bit_array(dpatch->pixels_opaque, position);
}
dpatch->is_dirty = dpatch->update_columns = true;
}
}
}
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source) 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) if (!source)
return patch; return patch;
...@@ -48,10 +240,12 @@ patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source) ...@@ -48,10 +240,12 @@ patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source)
Patch_CalcDataSizes(source, &total_pixels, &total_posts); Patch_CalcDataSizes(source, &total_pixels, &total_posts);
patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL); 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->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; return patch;
} }
...@@ -119,22 +313,494 @@ void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, ...@@ -119,22 +313,494 @@ void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width,
} }
// //
// Frees a patch from memory. // Other functions
// //
static void Patch_FreeData(patch_t *patch) unsigned Patch_GetBpp(patch_t *patch)
{ {
INT32 i; if (patch->format == PATCH_FORMAT_RGBA)
return 4;
else
return 1;
}
static void Patch_RebuildColumn(patch_t *patch, INT32 x, bitarray_t *is_opaque)
{
post_t *post = NULL;
boolean was_opaque = false;
column_t *column = &patch->columns[x];
INT16 height = patch->height;
size_t bpp = Patch_GetBpp(patch);
unsigned post_count = column->num_posts;
column->num_posts = 0;
for (INT32 y = 0; y < height; y++)
{
size_t position = (x * height) + y;
// End span if we have a transparent pixel
if (patch->format == PATCH_FORMAT_RGBA)
{
UINT32 *pixels = (UINT32 *)patch->pixels;
if (R_GetRgbaA(pixels[position]) == 0)
{
was_opaque = false;
continue;
}
}
else
{
if (!in_bit_array(is_opaque, position))
{
was_opaque = false;
continue;
}
}
if (!was_opaque)
{
column->num_posts++;
if (column->num_posts > post_count)
{
column->posts = Z_Realloc(column->posts, sizeof(post_t) * column->num_posts, PU_PATCH_DATA, NULL);
post_count = column->num_posts;
}
post = &column->posts[column->num_posts - 1];
post->topdelta = (unsigned)y;
post->length = 0;
post->data_offset = post->topdelta * bpp;
}
was_opaque = true;
post->length++;
}
}
void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
{
if (x < 0 || x >= patch->width || y < 0 || y >= patch->height)
return NULL;
if (patch->format == PATCH_FORMAT_RGBA)
{
// Well, that makes it easy
size_t position = (x * patch->height) + y;
return &patch->pixels[position * 4];
}
else
{
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
if (pixels_opaque)
{
size_t position = (x * patch->height) + y;
if (!in_bit_array(pixels_opaque, position))
return NULL;
return &patch->pixels[position];
}
}
if (Patch_NeedsUpdate(patch, true))
Patch_DoDynamicUpdate(patch, true);
if (patch->columns == NULL)
return NULL;
column_t *column = &patch->columns[x];
for (unsigned i = 0; i < column->num_posts; i++)
{
post_t *post = &column->posts[i];
size_t ofs = y - post->topdelta;
if (y >= (INT32)post->topdelta && ofs < post->length)
{
UINT8 *pixels = &column->pixels[post->data_offset];
return &pixels[ofs];
}
}
return NULL;
}
void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32 x, INT32 y, boolean transparent_overwrite)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return;
if (x < 0 || x >= patch->width || y < 0 || y >= patch->height)
return;
INT32 inbpp = Picture_FormatBPP(informat);
boolean pixel_is_opaque = false;
if (pixel)
{
if (inbpp == PICDEPTH_32BPP)
pixel_is_opaque = PicFmt_GetAlpha_32bpp(pixel, 0) > 0;
else if (inbpp == PICDEPTH_16BPP)
pixel_is_opaque = PicFmt_GetAlpha_16bpp(pixel, 0) > 0;
else if (inbpp == PICDEPTH_8BPP)
pixel_is_opaque = PicFmt_GetAlpha_8bpp(pixel, 0) > 0;
}
if (!pixel_is_opaque && !transparent_overwrite)
return;
void *(*writePixelFunc)(void *, void *) = NULL;
if (patch->format == PATCH_FORMAT_RGBA)
{
if (inbpp == PICDEPTH_32BPP)
writePixelFunc = PicFmt_WritePixel_i32o32;
else if (inbpp == PICDEPTH_16BPP)
writePixelFunc = PicFmt_WritePixel_i16o32;
else if (inbpp == PICDEPTH_8BPP)
writePixelFunc = PicFmt_WritePixel_i8o32;
}
else
{
if (inbpp == PICDEPTH_32BPP)
writePixelFunc = PicFmt_WritePixel_i32o8;
else if (inbpp == PICDEPTH_16BPP)
writePixelFunc = PicFmt_WritePixel_i16o8;
else if (inbpp == PICDEPTH_8BPP)
writePixelFunc = PicFmt_WritePixel_i8o8;
}
// If the patch is empty
if (!patch->pixels)
{
if (!pixel_is_opaque)
{
// If the pixel is transparent, do nothing
return;
}
if (patch->pixels == NULL)
patch->pixels = Z_Calloc(patch->width * patch->height * Patch_GetBpp(patch), PU_PATCH_DATA, NULL);
}
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
size_t position = (x * patch->height) + y;
if (patch->format == PATCH_FORMAT_RGBA)
{
RGBA_t *dest = (RGBA_t*)(&patch->pixels[position * 4]);
if (!pixel_is_opaque)
{
if (transparent_overwrite)
{
dest->s.alpha = 0;
dpatch->is_dirty = true;
// No longer a pixel in this position, so columns need to be rebuilt
dpatch->update_columns = true;
}
}
else
{
// No longer a pixel in this position, so columns need to be rebuilt
if (dest->s.alpha == 0)
dpatch->update_columns = true;
writePixelFunc(dest, pixel);
dpatch->is_dirty = true;
}
}
else
{
if (!pixel_is_opaque)
{
if (transparent_overwrite)
{
unset_bit_array(dpatch->pixels_opaque, position);
dpatch->is_dirty = true;
// No longer a pixel in this position, so columns need to be rebuilt
dpatch->update_columns = true;
}
}
else
{
// No longer a pixel in this position, so columns need to be rebuilt
if (!in_bit_array(dpatch->pixels_opaque, position))
{
set_bit_array(dpatch->pixels_opaque, position);
dpatch->update_columns = true;
}
writePixelFunc(&patch->pixels[position], pixel);
dpatch->is_dirty = true;
}
}
if (dpatch->is_dirty)
Patch_MarkDirtyRect(patch, x, y, x + 1, y + 1);
}
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)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return;
if (src_img_width <= 0 || src_img_height <= 0 || sw <= 0 || sh <= 0)
return;
if (patch->pixels == NULL)
patch->pixels = Z_Calloc(patch->width * patch->height * Patch_GetBpp(patch), PU_PATCH_DATA, NULL);
void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL;
UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL;
void *(*writePixelFunc)(void *, void *) = NULL;
if (Picture_IsPatchFormat(informat))
readPixelFunc = PicFmt_ReadPixel_Patch;
else if (Picture_IsFlatFormat(informat))
{
switch (informat)
{
case PICFMT_FLAT32:
readPixelFunc = PicFmt_ReadPixel_Flat_32bpp;
break;
case PICFMT_FLAT16:
readPixelFunc = PicFmt_ReadPixel_Flat_16bpp;
break;
case PICFMT_FLAT:
readPixelFunc = PicFmt_ReadPixel_Flat_8bpp;
break;
default:
break;
}
}
if (patch->format == PATCH_FORMAT_RGBA)
{
switch (Picture_FormatBPP(informat))
{
case PICDEPTH_32BPP:
getAlphaFunc = PicFmt_GetAlpha_32bpp;
writePixelFunc = PicFmt_WritePixel_i32o32;
break;
case PICDEPTH_16BPP:
getAlphaFunc = PicFmt_GetAlpha_16bpp;
writePixelFunc = PicFmt_WritePixel_i16o32;
break;
case PICDEPTH_8BPP:
getAlphaFunc = PicFmt_GetAlpha_8bpp;
writePixelFunc = PicFmt_WritePixel_i8o32;
break;
}
}
else
{
switch (Picture_FormatBPP(informat))
{
case PICDEPTH_32BPP:
getAlphaFunc = PicFmt_GetAlpha_32bpp;
writePixelFunc = PicFmt_WritePixel_i32o8;
break;
case PICDEPTH_16BPP:
getAlphaFunc = PicFmt_GetAlpha_16bpp;
writePixelFunc = PicFmt_WritePixel_i16o8;
break;
case PICDEPTH_8BPP:
getAlphaFunc = PicFmt_GetAlpha_8bpp;
writePixelFunc = PicFmt_WritePixel_i8o8;
break;
}
}
if (readPixelFunc == NULL || writePixelFunc == NULL || getAlphaFunc == NULL)
I_Error("Patch_UpdatePixels: unsupported input format");
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
Patch_MarkDirtyRect(patch, dx, dy, dx + sw, dy + sh);
if (patch->format == PATCH_FORMAT_RGBA)
{
for (INT32 y = dy; y < dy + sh; y++, sy++)
{
if (y < 0 || sy < 0)
continue;
else if (y >= patch->height || sy >= src_img_height)
break;
INT32 src_x = sx;
for (INT32 x = dx; x < dx + sw; x++, src_x++)
{
if (x < 0 || src_x < 0)
continue;
else if (x >= patch->width || src_x >= src_img_width)
break;
boolean opaque = false;
// Read pixel
void *input = readPixelFunc(pixels, informat, src_x, sy, src_img_width, src_img_height, 0);
// Determine opacity
if (input != NULL)
opaque = getAlphaFunc(input, 0) > 0;
size_t position = (x * patch->height) + y;
RGBA_t *dest = (RGBA_t*)(&patch->pixels[position * 4]);
if (!opaque)
{
if (transparent_overwrite)
{
dest->s.alpha = 0;
dpatch->update_columns = dpatch->is_dirty = true;
}
}
else
{
if (dest->s.alpha == 0)
dpatch->update_columns = true;
writePixelFunc(dest, input);
dpatch->is_dirty = true;
}
}
}
}
else
{
for (INT32 x = dx; x < dx + sw; x++, sx++)
{
if (x < 0 || sx < 0)
continue;
else if (x >= patch->width || sx >= src_img_width)
break;
INT32 src_y = sy;
for (INT32 y = dy; y < dy + sh; y++, src_y++)
{
if (y < 0 || src_y < 0)
continue;
else if (y >= patch->height || src_y >= src_img_height)
break;
boolean opaque = false;
// Read pixel
void *input = readPixelFunc(pixels, informat, sx, src_y, src_img_width, src_img_height, 0);
// Determine opacity
if (input != NULL)
opaque = getAlphaFunc(input, 0) > 0;
size_t position = (x * patch->height) + y;
if (!opaque)
{
if (transparent_overwrite)
{
unset_bit_array(dpatch->pixels_opaque, position);
dpatch->update_columns = dpatch->is_dirty = true;
}
}
else
{
if (!in_bit_array(dpatch->pixels_opaque, position))
{
set_bit_array(dpatch->pixels_opaque, position);
dpatch->update_columns = true;
}
writePixelFunc(&patch->pixels[position], input);
dpatch->is_dirty = true;
}
}
}
}
}
boolean Patch_NeedsUpdate(patch_t *patch, boolean needs_columns)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return false;
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
return dpatch->is_dirty || (needs_columns && dpatch->update_columns);
}
void Patch_DoDynamicUpdate(patch_t *patch, boolean update_columns)
{
if (patch->type != PATCH_TYPE_DYNAMIC)
return;
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
if (Patch_CheckDirtyRect(dpatch))
{
#ifdef HWRENDER #ifdef HWRENDER
if (patch->hardware) if (patch->hardware)
HWR_FreeTexture(patch); HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
#endif #endif
}
for (i = 0; i < 4; i++) if (update_columns && dpatch->update_columns && Patch_CheckDirtyColumns(dpatch))
{ {
if (patch->flats[i]) if (patch->columns == NULL)
Z_Free(patch->flats[i]); Patch_InitDynamicColumns(patch);
for (INT32 x = dpatch->column_dirty[0]; x < dpatch->column_dirty[1]; x++)
Patch_RebuildColumn(patch, x, dpatch->pixels_opaque);
dpatch->update_columns = false;
Patch_ClearDirtyColumns(dpatch);
}
Patch_FreeMiscData(patch);
dpatch->is_dirty = 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;
}
//
// Frees a patch from memory.
//
void Patch_FreeMiscData(patch_t *patch)
{
for (INT32 i = 0; i < 4; i++)
{
Z_Free(patch->flats[i]);
patch->flats[i] = NULL;
} }
#ifdef ROTSPRITE #ifdef ROTSPRITE
...@@ -142,27 +808,48 @@ static void Patch_FreeData(patch_t *patch) ...@@ -142,27 +808,48 @@ static void Patch_FreeData(patch_t *patch)
{ {
rotsprite_t *rotsprite = patch->rotated; rotsprite_t *rotsprite = patch->rotated;
for (i = 0; i < rotsprite->angles; i++) for (INT32 i = 0; i < rotsprite->angles; i++)
{ Patch_Free(rotsprite->patches[i]);
if (rotsprite->patches[i])
Patch_Free(rotsprite->patches[i]);
}
Z_Free(rotsprite->patches); Z_Free(rotsprite->patches);
Z_Free(rotsprite); Z_Free(rotsprite);
patch->rotated = NULL;
} }
#endif #endif
}
if (patch->pixels) static void Patch_FreeData(patch_t *patch)
Z_Free(patch->pixels); {
if (patch->columns) #ifdef HWRENDER
Z_Free(patch->columns); if (patch->hardware)
if (patch->posts) HWR_FreeTexture(patch);
Z_Free(patch->posts); #endif
Patch_FreeMiscData(patch);
if (patch->type == PATCH_TYPE_STATIC)
{
staticpatch_t *spatch = (staticpatch_t*)patch;
Z_Free(spatch->posts);
}
else if (patch->type == PATCH_TYPE_DYNAMIC && patch->format == PATCH_FORMAT_PALETTE)
{
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);
}
Z_Free(patch->pixels);
Z_Free(patch->columns);
} }
void Patch_Free(patch_t *patch) void Patch_Free(patch_t *patch)
{ {
if (patch == NULL)
return;
Patch_FreeData(patch); Patch_FreeData(patch);
Z_Free(patch); Z_Free(patch);
} }
...@@ -185,9 +872,14 @@ void Patch_FreeTags(INT32 lowtag, INT32 hightag) ...@@ -185,9 +872,14 @@ void Patch_FreeTags(INT32 lowtag, INT32 hightag)
void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags) void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags)
{ {
UINT8 flip = (flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP)); UINT8 flip = flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP);
if (patch->flats[flip] == NULL) if (patch->flats[flip] == NULL)
patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags); {
if (patch->format == PATCH_FORMAT_RGBA)
patch->flats[flip] = Picture_Convert(PICFMT_PATCH32, patch, PICFMT_FLAT32, 0, NULL, 0, 0, 0, 0, flags);
else
patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags);
}
} }
#ifdef HWRENDER #ifdef HWRENDER
......
...@@ -17,12 +17,47 @@ ...@@ -17,12 +17,47 @@
#include "r_fps.h" #include "r_fps.h"
#include "doomdef.h" #include "doomdef.h"
enum
{
PATCH_TYPE_STATIC,
PATCH_TYPE_DYNAMIC
};
enum
{
PATCH_FORMAT_PALETTE,
PATCH_FORMAT_RGBA
};
// Patch functions // Patch functions
patch_t *Patch_Create(INT16 width, INT16 height); patch_t *Patch_Create(INT16 width, INT16 height);
patch_t *Patch_CreateDynamic(INT16 width, INT16 height, UINT8 format);
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_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);
unsigned Patch_GetBpp(patch_t *patch);
boolean Patch_NeedsUpdate(patch_t *patch, boolean needs_columns);
void Patch_DoDynamicUpdate(patch_t *patch, boolean update_columns);
void Patch_MarkDirtyRect(patch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom);
void Patch_Clear(patch_t *patch);
void Patch_ClearRect(patch_t *patch, INT16 x, INT16 y, INT16 width, INT16 height);
bitarray_t *Patch_GetOpaqueRegions(patch_t *patch);
void Patch_Free(patch_t *patch);
void Patch_FreeMiscData(patch_t *patch);
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source); patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source);
void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts); void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts);
void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip); void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip);
void Patch_Free(patch_t *patch);
#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) #define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum)
void Patch_FreeTags(INT32 lowtag, INT32 hightag); void Patch_FreeTags(INT32 lowtag, INT32 hightag);
......
...@@ -153,7 +153,7 @@ static void RotatedPatch_CalculateDimensions( ...@@ -153,7 +153,7 @@ static void RotatedPatch_CalculateDimensions(
void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip) void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip)
{ {
patch_t *rotated; patch_t *rotated;
UINT16 *rawdst, *rawconv; void *rawdst;
size_t size; size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
...@@ -170,7 +170,6 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle ...@@ -170,7 +170,6 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
INT32 sx, sy; INT32 sx, sy;
INT32 dx, dy; INT32 dx, dy;
INT32 ox, oy; INT32 ox, oy;
INT32 minx, miny, maxx, maxy;
// Don't cache angle = 0 // Don't cache angle = 0
if (angle < 1 || angle >= ROTANGLES) if (angle < 1 || angle >= ROTANGLES)
...@@ -198,89 +197,88 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle ...@@ -198,89 +197,88 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
newheight *= 2; newheight *= 2;
} }
minx = newwidth;
miny = newheight;
maxx = 0;
maxy = 0;
// Draw the rotated sprite to a temporary buffer. // Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight); size = (newwidth * newheight);
if (!size) if (!size)
size = (width * height); size = (width * height);
rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (dy = 0; dy < newheight; dy++) int format;
int patchformat;
if (patch->format == PATCH_FORMAT_RGBA)
{ {
for (dx = 0; dx < newwidth; dx++) UINT32 *dest = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
{
x = (dx - (newwidth / 2)) * FRACUNIT;
y = (dy - (newheight / 2)) * FRACUNIT;
sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter;
sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter;
sx >>= FRACBITS; patchformat = PICFMT_PATCH32;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height) for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{ {
void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); x = (dx - (newwidth / 2)) * FRACUNIT;
if (input != NULL) y = (dy - (newheight / 2)) * FRACUNIT;
sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter;
sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter;
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{ {
rawdst[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input)); void *input = Picture_GetPatchPixel(patch, patchformat, sx, sy, bflip);
if (dx < minx) if (input != NULL)
minx = dx; {
if (dy < miny) dest[(dy * newwidth) + dx] = *(UINT32 *)input;
miny = dy; }
if (dx > maxx)
maxx = dx;
if (dy > maxy)
maxy = dy;
} }
} }
} }
}
ox = (newwidth / 2) + (leftoffset - xpivot); rawdst = dest;
oy = (newheight / 2) + (patch->topoffset - ypivot); format = PICFMT_FLAT32;
width = (maxx - minx); }
height = (maxy - miny); else
if ((unsigned)(width * height) > size)
{ {
UINT16 *src, *dest; UINT16 *dest = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
size = (width * height);
rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
src = &rawdst[(miny * newwidth) + minx]; patchformat = PICFMT_PATCH;
dest = rawconv;
dy = height;
while (dy--) for (dy = 0; dy < newheight; dy++)
{ {
M_Memcpy(dest, src, width * sizeof(UINT16)); for (dx = 0; dx < newwidth; dx++)
dest += width; {
src += newwidth; x = (dx - (newwidth / 2)) * FRACUNIT;
} y = (dy - (newheight / 2)) * FRACUNIT;
sx = FixedMul(x, ca) + FixedMul(y, sa) + xcenter;
sy = -FixedMul(x, sa) + FixedMul(y, ca) + ycenter;
ox -= minx; sx >>= FRACBITS;
oy -= miny; sy >>= FRACBITS;
Z_Free(rawdst); if (sx >= 0 && sy >= 0 && sx < width && sy < height)
} {
else void *input = Picture_GetPatchPixel(patch, patchformat, sx, sy, bflip);
{ if (input != NULL)
rawconv = rawdst; {
width = newwidth; dest[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input));
height = newheight; }
}
}
}
rawdst = dest;
format = PICFMT_FLAT16;
} }
ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot);
// make patch // make patch
rotated = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawconv, PICFMT_PATCH, 0, NULL, width, height, 0, 0, 0); rotated = (patch_t *)Picture_Convert(format, rawdst, patchformat, 0, NULL, newwidth, newheight, 0, 0, 0);
Z_ChangeTag(rotated, PU_PATCH_ROTATED); Z_ChangeTag(rotated, PU_PATCH_ROTATED);
Z_SetUser(rotated, (void **)(&rotsprite->patches[idx])); Z_SetUser(rotated, (void **)(&rotsprite->patches[idx]));
Z_Free(rawconv); Z_Free(rawdst);
rotated->leftoffset = ox; rotated->leftoffset = ox;
rotated->topoffset = oy; rotated->topoffset = oy;
......
...@@ -96,14 +96,14 @@ void *Picture_Convert( ...@@ -96,14 +96,14 @@ void *Picture_Convert(
return NULL; return NULL;
} }
static void *ReadPixelFunc_Patch(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) void *PicFmt_ReadPixel_Patch(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags)
{ {
(void)inwidth; (void)inwidth;
(void)inheight; (void)inheight;
return Picture_GetPatchPixel((patch_t*)picture, informat, x, y, flags); return Picture_GetPatchPixel((patch_t*)picture, informat, x, y, flags);
} }
static void *ReadPixelFunc_Flat_8bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) void *PicFmt_ReadPixel_Flat_8bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags)
{ {
(void)informat; (void)informat;
(void)flags; (void)flags;
...@@ -111,7 +111,7 @@ static void *ReadPixelFunc_Flat_8bpp(void *picture, pictureformat_t informat, IN ...@@ -111,7 +111,7 @@ static void *ReadPixelFunc_Flat_8bpp(void *picture, pictureformat_t informat, IN
return (UINT8 *)picture + ((y * inwidth) + x); return (UINT8 *)picture + ((y * inwidth) + x);
} }
static void *ReadPixelFunc_Flat_16bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) void *PicFmt_ReadPixel_Flat_16bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags)
{ {
(void)informat; (void)informat;
(void)flags; (void)flags;
...@@ -119,7 +119,7 @@ static void *ReadPixelFunc_Flat_16bpp(void *picture, pictureformat_t informat, I ...@@ -119,7 +119,7 @@ static void *ReadPixelFunc_Flat_16bpp(void *picture, pictureformat_t informat, I
return (UINT16 *)picture + ((y * inwidth) + x); return (UINT16 *)picture + ((y * inwidth) + x);
} }
static void *ReadPixelFunc_Flat_32bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags) void *PicFmt_ReadPixel_Flat_32bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags)
{ {
(void)informat; (void)informat;
(void)flags; (void)flags;
...@@ -127,21 +127,21 @@ static void *ReadPixelFunc_Flat_32bpp(void *picture, pictureformat_t informat, I ...@@ -127,21 +127,21 @@ static void *ReadPixelFunc_Flat_32bpp(void *picture, pictureformat_t informat, I
return (UINT32 *)picture + ((y * inwidth) + x); return (UINT32 *)picture + ((y * inwidth) + x);
} }
static UINT8 GetAlphaFunc_32bpp(void *input, pictureflags_t flags) UINT8 PicFmt_GetAlpha_32bpp(void *input, pictureflags_t flags)
{ {
(void)flags; (void)flags;
RGBA_t px = *(RGBA_t *)input; RGBA_t px = *(RGBA_t *)input;
return px.s.alpha; return px.s.alpha;
} }
static UINT8 GetAlphaFunc_16bpp(void *input, pictureflags_t flags) UINT8 PicFmt_GetAlpha_16bpp(void *input, pictureflags_t flags)
{ {
(void)flags; (void)flags;
UINT16 px = *(UINT16 *)input; UINT16 px = *(UINT16 *)input;
return (px & 0xFF00) >> 8; return (px & 0xFF00) >> 8;
} }
static UINT8 GetAlphaFunc_8bpp(void *input, pictureflags_t flags) UINT8 PicFmt_GetAlpha_8bpp(void *input, pictureflags_t flags)
{ {
UINT8 px = *(UINT8 *)input; UINT8 px = *(UINT8 *)input;
if (px == TRANSPARENTPIXEL && (flags & PICFLAGS_USE_TRANSPARENTPIXEL)) if (px == TRANSPARENTPIXEL && (flags & PICFLAGS_USE_TRANSPARENTPIXEL))
...@@ -151,7 +151,7 @@ static UINT8 GetAlphaFunc_8bpp(void *input, pictureflags_t flags) ...@@ -151,7 +151,7 @@ static UINT8 GetAlphaFunc_8bpp(void *input, pictureflags_t flags)
} }
// input 32bpp output 32bpp // input 32bpp output 32bpp
static void *WritePatchPixel_i32o32(void *ptr, void *input) void *PicFmt_WritePixel_i32o32(void *ptr, void *input)
{ {
RGBA_t px = *(RGBA_t *)input; RGBA_t px = *(RGBA_t *)input;
WRITEUINT32(ptr, px.rgba); WRITEUINT32(ptr, px.rgba);
...@@ -159,7 +159,7 @@ static void *WritePatchPixel_i32o32(void *ptr, void *input) ...@@ -159,7 +159,7 @@ static void *WritePatchPixel_i32o32(void *ptr, void *input)
} }
// input 16bpp output 32bpp // input 16bpp output 32bpp
static void *WritePatchPixel_i16o32(void *ptr, void *input) void *PicFmt_WritePixel_i16o32(void *ptr, void *input)
{ {
RGBA_t px = pMasterPalette[*((UINT16 *)input) & 0xFF]; RGBA_t px = pMasterPalette[*((UINT16 *)input) & 0xFF];
WRITEUINT32(ptr, px.rgba); WRITEUINT32(ptr, px.rgba);
...@@ -167,7 +167,7 @@ static void *WritePatchPixel_i16o32(void *ptr, void *input) ...@@ -167,7 +167,7 @@ static void *WritePatchPixel_i16o32(void *ptr, void *input)
} }
// input 8bpp output 32bpp // input 8bpp output 32bpp
static void *WritePatchPixel_i8o32(void *ptr, void *input) void *PicFmt_WritePixel_i8o32(void *ptr, void *input)
{ {
RGBA_t px = pMasterPalette[*((UINT8 *)input) & 0xFF]; RGBA_t px = pMasterPalette[*((UINT8 *)input) & 0xFF];
WRITEUINT32(ptr, px.rgba); WRITEUINT32(ptr, px.rgba);
...@@ -175,7 +175,7 @@ static void *WritePatchPixel_i8o32(void *ptr, void *input) ...@@ -175,7 +175,7 @@ static void *WritePatchPixel_i8o32(void *ptr, void *input)
} }
// input 32bpp output 16bpp // input 32bpp output 16bpp
static void *WritePatchPixel_i32o16(void *ptr, void *input) void *PicFmt_WritePixel_i32o16(void *ptr, void *input)
{ {
RGBA_t in = *(RGBA_t *)input; RGBA_t in = *(RGBA_t *)input;
UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue); UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue);
...@@ -184,21 +184,21 @@ static void *WritePatchPixel_i32o16(void *ptr, void *input) ...@@ -184,21 +184,21 @@ static void *WritePatchPixel_i32o16(void *ptr, void *input)
} }
// input 16bpp output 16bpp // input 16bpp output 16bpp
static void *WritePatchPixel_i16o16(void *ptr, void *input) void *PicFmt_WritePixel_i16o16(void *ptr, void *input)
{ {
WRITEUINT16(ptr, *(UINT16 *)input); WRITEUINT16(ptr, *(UINT16 *)input);
return ptr; return ptr;
} }
// input 8bpp output 16bpp // input 8bpp output 16bpp
static void *WritePatchPixel_i8o16(void *ptr, void *input) void *PicFmt_WritePixel_i8o16(void *ptr, void *input)
{ {
WRITEUINT16(ptr, (0xFF00 | (*(UINT8 *)input))); WRITEUINT16(ptr, (0xFF00 | (*(UINT8 *)input)));
return ptr; return ptr;
} }
// input 32bpp output 8bpp // input 32bpp output 8bpp
static void *WritePatchPixel_i32o8(void *ptr, void *input) void *PicFmt_WritePixel_i32o8(void *ptr, void *input)
{ {
RGBA_t in = *(RGBA_t *)input; RGBA_t in = *(RGBA_t *)input;
UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue); UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue);
...@@ -207,7 +207,7 @@ static void *WritePatchPixel_i32o8(void *ptr, void *input) ...@@ -207,7 +207,7 @@ static void *WritePatchPixel_i32o8(void *ptr, void *input)
} }
// input 16bpp output 8bpp // input 16bpp output 8bpp
static void *WritePatchPixel_i16o8(void *ptr, void *input) void *PicFmt_WritePixel_i16o8(void *ptr, void *input)
{ {
UINT16 px = *(UINT16 *)input; UINT16 px = *(UINT16 *)input;
WRITEUINT8(ptr, (px & 0xFF)); WRITEUINT8(ptr, (px & 0xFF));
...@@ -215,7 +215,7 @@ static void *WritePatchPixel_i16o8(void *ptr, void *input) ...@@ -215,7 +215,7 @@ static void *WritePatchPixel_i16o8(void *ptr, void *input)
} }
// input 8bpp output 8bpp // input 8bpp output 8bpp
static void *WritePatchPixel_i8o8(void *ptr, void *input) void *PicFmt_WritePixel_i8o8(void *ptr, void *input)
{ {
WRITEUINT8(ptr, *(UINT8 *)input); WRITEUINT8(ptr, *(UINT8 *)input);
return ptr; return ptr;
...@@ -289,22 +289,22 @@ void *Picture_PatchConvert( ...@@ -289,22 +289,22 @@ void *Picture_PatchConvert(
void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL; void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL;
UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL; UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL;
void *(*writePatchPixel)(void *, void *) = NULL; void *(*writePixelFunc)(void *, void *) = NULL;
if (Picture_IsPatchFormat(informat)) if (Picture_IsPatchFormat(informat))
readPixelFunc = ReadPixelFunc_Patch; readPixelFunc = PicFmt_ReadPixel_Patch;
else if (Picture_IsFlatFormat(informat)) else if (Picture_IsFlatFormat(informat))
{ {
switch (informat) switch (informat)
{ {
case PICFMT_FLAT32: case PICFMT_FLAT32:
readPixelFunc = ReadPixelFunc_Flat_32bpp; readPixelFunc = PicFmt_ReadPixel_Flat_32bpp;
break; break;
case PICFMT_FLAT16: case PICFMT_FLAT16:
readPixelFunc = ReadPixelFunc_Flat_16bpp; readPixelFunc = PicFmt_ReadPixel_Flat_16bpp;
break; break;
case PICFMT_FLAT: case PICFMT_FLAT:
readPixelFunc = ReadPixelFunc_Flat_8bpp; readPixelFunc = PicFmt_ReadPixel_Flat_8bpp;
break; break;
default: default:
I_Error("Picture_PatchConvert: unsupported flat input format!"); I_Error("Picture_PatchConvert: unsupported flat input format!");
...@@ -315,11 +315,11 @@ void *Picture_PatchConvert( ...@@ -315,11 +315,11 @@ void *Picture_PatchConvert(
I_Error("Picture_PatchConvert: unsupported input format!"); I_Error("Picture_PatchConvert: unsupported input format!");
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
getAlphaFunc = GetAlphaFunc_32bpp; getAlphaFunc = PicFmt_GetAlpha_32bpp;
else if (inbpp == PICDEPTH_16BPP) else if (inbpp == PICDEPTH_16BPP)
getAlphaFunc = GetAlphaFunc_16bpp; getAlphaFunc = PicFmt_GetAlpha_16bpp;
else if (inbpp == PICDEPTH_8BPP) else if (inbpp == PICDEPTH_8BPP)
getAlphaFunc = GetAlphaFunc_8bpp; getAlphaFunc = PicFmt_GetAlpha_8bpp;
switch (outformat) switch (outformat)
{ {
...@@ -327,38 +327,36 @@ void *Picture_PatchConvert( ...@@ -327,38 +327,36 @@ void *Picture_PatchConvert(
case PICFMT_DOOMPATCH32: case PICFMT_DOOMPATCH32:
{ {
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o32; writePixelFunc = PicFmt_WritePixel_i32o32;
else if (inbpp == PICDEPTH_16BPP) else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o32; writePixelFunc = PicFmt_WritePixel_i16o32;
else // PICFMT_PATCH else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o32; writePixelFunc = PicFmt_WritePixel_i8o32;
break; break;
} }
case PICFMT_PATCH16: case PICFMT_PATCH16:
case PICFMT_DOOMPATCH16: case PICFMT_DOOMPATCH16:
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o16; writePixelFunc = PicFmt_WritePixel_i32o16;
else if (inbpp == PICDEPTH_16BPP) else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o16; writePixelFunc = PicFmt_WritePixel_i16o16;
else // PICFMT_PATCH else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o16; writePixelFunc = PicFmt_WritePixel_i8o16;
break; break;
default: // PICFMT_PATCH default: // PICFMT_PATCH
{ {
if (inbpp == PICDEPTH_32BPP) if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o8; writePixelFunc = PicFmt_WritePixel_i32o8;
else if (inbpp == PICDEPTH_16BPP) else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o8; writePixelFunc = PicFmt_WritePixel_i16o8;
else // PICFMT_PATCH else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o8; writePixelFunc = PicFmt_WritePixel_i8o8;
break; break;
} }
} }
patch_t *out = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL); patch_t *out = Patch_Create(inwidth, inheight);
out->format = inbpp == PICDEPTH_32BPP ? PATCH_FORMAT_RGBA : PATCH_FORMAT_PALETTE;
out->width = inwidth;
out->height = inheight;
out->leftoffset = inleftoffset; out->leftoffset = inleftoffset;
out->topoffset = intopoffset; out->topoffset = intopoffset;
...@@ -367,12 +365,13 @@ void *Picture_PatchConvert( ...@@ -367,12 +365,13 @@ void *Picture_PatchConvert(
out->columns = Z_Calloc(sizeof(column_t) * out->width, PU_PATCH_DATA, NULL); 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->pixels = Z_Calloc(max_pixels * (outbpp / 8), PU_PATCH_DATA, NULL);
out->posts = NULL;
UINT8 *imgptr = out->pixels; UINT8 *imgptr = out->pixels;
unsigned *column_posts = Z_Calloc(sizeof(unsigned) * inwidth, PU_STATIC, NULL); unsigned *column_posts = Z_Calloc(sizeof(unsigned) * inwidth, PU_STATIC, NULL);
size_t bpp = Patch_GetBpp(out);
// Write columns // Write columns
for (INT32 x = 0; x < inwidth; x++) for (INT32 x = 0; x < inwidth; x++)
{ {
...@@ -381,7 +380,11 @@ void *Picture_PatchConvert( ...@@ -381,7 +380,11 @@ void *Picture_PatchConvert(
boolean was_opaque = false; boolean was_opaque = false;
column_t *column = &out->columns[x]; column_t *column = &out->columns[x];
column->pixels = imgptr; if (out->format == PATCH_FORMAT_RGBA)
column->pixels = &out->pixels[out->height * x * bpp];
else
column->pixels = imgptr;
column->posts = NULL; column->posts = NULL;
column->num_posts = 0; column->num_posts = 0;
...@@ -410,9 +413,10 @@ void *Picture_PatchConvert( ...@@ -410,9 +413,10 @@ void *Picture_PatchConvert(
{ {
num_posts++; num_posts++;
out->posts = Z_Realloc(out->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL); staticpatch_t *spatch = (staticpatch_t*)out;
post = &out->posts[num_posts - 1]; spatch->posts = Z_Realloc(spatch->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL);
post->topdelta = (size_t)y; post = &spatch->posts[num_posts - 1];
post->topdelta = (unsigned)y;
post->length = 0; post->length = 0;
post->data_offset = post_data_offset; post->data_offset = post_data_offset;
if (column_posts[x] == (unsigned)-1) if (column_posts[x] == (unsigned)-1)
...@@ -423,24 +427,39 @@ void *Picture_PatchConvert( ...@@ -423,24 +427,39 @@ void *Picture_PatchConvert(
was_opaque = true; was_opaque = true;
// Write the pixel // Write the pixel
UINT8 *last_ptr = imgptr; if (out->format == PATCH_FORMAT_RGBA)
imgptr = writePatchPixel(last_ptr, input); {
writePixelFunc(&column->pixels[y * bpp], input);
post_data_offset += bpp;
}
else
{
UINT8 *last_ptr = imgptr;
imgptr = writePixelFunc(last_ptr, input);
post_data_offset += imgptr - last_ptr;
}
post->length++; post->length++;
post_data_offset += imgptr - last_ptr;
} }
} }
UINT8 *old_pixels = out->pixels; UINT8 *old_pixels = out->pixels;
size_t total_pixels = imgptr - out->pixels;
if (total_pixels != max_pixels) if (out->format != PATCH_FORMAT_RGBA)
out->pixels = Z_Realloc(out->pixels, total_pixels, PU_PATCH_DATA, NULL); {
size_t total_pixels = imgptr - out->pixels;
if (total_pixels != max_pixels)
out->pixels = Z_Realloc(out->pixels, total_pixels, PU_PATCH_DATA, NULL);
}
for (INT16 x = 0; x < inwidth; x++) for (INT16 x = 0; x < inwidth; x++)
{ {
column_t *column = &out->columns[x]; column_t *column = &out->columns[x];
if (column->num_posts > 0) 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) if (old_pixels != out->pixels)
column->pixels = out->pixels + (column->pixels - old_pixels); column->pixels = out->pixels + (column->pixels - old_pixels);
} }
......
...@@ -85,6 +85,25 @@ boolean Picture_IsDoomPatchFormat(pictureformat_t format); ...@@ -85,6 +85,25 @@ boolean Picture_IsDoomPatchFormat(pictureformat_t format);
boolean Picture_IsFlatFormat(pictureformat_t format); boolean Picture_IsFlatFormat(pictureformat_t format);
boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size); boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size);
void *PicFmt_ReadPixel_Patch(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags);
void *PicFmt_ReadPixel_Flat_8bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags);
void *PicFmt_ReadPixel_Flat_16bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags);
void *PicFmt_ReadPixel_Flat_32bpp(void *picture, pictureformat_t informat, INT32 x, INT32 y, INT32 inwidth, INT32 inheight, pictureflags_t flags);
void *PicFmt_WritePixel_i32o32(void *ptr, void *input);
void *PicFmt_WritePixel_i16o32(void *ptr, void *input);
void *PicFmt_WritePixel_i8o32(void *ptr, void *input);
void *PicFmt_WritePixel_i32o16(void *ptr, void *input);
void *PicFmt_WritePixel_i16o16(void *ptr, void *input);
void *PicFmt_WritePixel_i8o16(void *ptr, void *input);
void *PicFmt_WritePixel_i32o8(void *ptr, void *input);
void *PicFmt_WritePixel_i16o8(void *ptr, void *input);
void *PicFmt_WritePixel_i8o8(void *ptr, void *input);
UINT8 PicFmt_GetAlpha_32bpp(void *input, pictureflags_t flags);
UINT8 PicFmt_GetAlpha_16bpp(void *input, pictureflags_t flags);
UINT8 PicFmt_GetAlpha_8bpp(void *input, pictureflags_t flags);
// Structs // Structs
typedef enum typedef enum
{ {
......
...@@ -867,6 +867,7 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) ...@@ -867,6 +867,7 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
dc_source = column->pixels + post->data_offset; dc_source = column->pixels + post->data_offset;
dc_texturemid = basetexturemid - (post->topdelta<<FRACBITS); dc_texturemid = basetexturemid - (post->topdelta<<FRACBITS);
// Drawn by R_DrawColumn.
colfunc(); colfunc();
} }
} }
......
...@@ -86,6 +86,7 @@ void *hwSym(const char *funcName,void *handle) ...@@ -86,6 +86,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(ClearBuffer); GETFUNC(ClearBuffer);
GETFUNC(SetTexture); GETFUNC(SetTexture);
GETFUNC(UpdateTexture); GETFUNC(UpdateTexture);
GETFUNC(UpdateTextureRegion);
GETFUNC(DeleteTexture); GETFUNC(DeleteTexture);
GETFUNC(ReadScreenTexture); GETFUNC(ReadScreenTexture);
GETFUNC(GClipRect); GETFUNC(GClipRect);
......
...@@ -1872,6 +1872,7 @@ void VID_StartupOpenGL(void) ...@@ -1872,6 +1872,7 @@ void VID_StartupOpenGL(void)
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
HWD.pfnUpdateTextureRegion = hwSym("UpdateTextureRegion", NULL);
HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL); HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL);
......
This diff is collapsed.
...@@ -54,6 +54,8 @@ void InitColorLUT(colorlookup_t *lut, RGBA_t *palette, boolean makecolors); ...@@ -54,6 +54,8 @@ void InitColorLUT(colorlookup_t *lut, RGBA_t *palette, boolean makecolors);
UINT8 GetColorLUT(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b); UINT8 GetColorLUT(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b);
UINT8 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b); UINT8 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b);
extern colorlookup_t r_colorlookup;
// Set the current RGB palette lookup to use for palettized graphics // Set the current RGB palette lookup to use for palettized graphics
void V_SetPalette(INT32 palettenum); void V_SetPalette(INT32 palettenum);
...@@ -156,7 +158,6 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); ...@@ -156,7 +158,6 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
#define V_PERPLAYER 0x80000000 // automatically adjust coordinates/scaling for splitscreen mode #define V_PERPLAYER 0x80000000 // automatically adjust coordinates/scaling for splitscreen mode
// defines for old functions // defines for old functions
#define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s|V_NOSCALESTART|V_NOSCALEPATCH, p, NULL)
#define V_DrawTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s, p, c) #define V_DrawTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s, p, c)
#define V_DrawSmallTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, s, p, c) #define V_DrawSmallTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, s, p, c)
#define V_DrawTinyTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, s, p, c) #define V_DrawTinyTranslucentMappedPatch(x,y,s,p,c) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, s, p, c)
...@@ -171,9 +172,12 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); ...@@ -171,9 +172,12 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
#define V_DrawTinyTranslucentPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, s, p, NULL) #define V_DrawTinyTranslucentPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT/4, s, p, NULL)
#define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL) #define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL)
#define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c) #define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c)
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap); #define V_DrawStretchyFixedPatch(x,y,xs,ys,s,p,c) V_DrawPatch(x,y,xs,ys,s,p,c)
void V_DrawPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 flags, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h, boolean use_pixel_alpha, boolean copy_transparent);
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor); void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor);
// Draw a linear block of pixels into the view buffer. // Draw a linear block of pixels into the view buffer.
......