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
  • Jisk/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
117 results
Select Git revision
Show changes
Commits on Source (23)
......@@ -276,22 +276,18 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
INT32 pwidth, INT32 pheight,
const patch_t *realpatch)
{
INT32 ncols;
fixed_t xfrac, xfracstep;
fixed_t yfracstep, scale_y;
const column_t *patchcol;
UINT8 *block = mipmap->data;
INT32 bpp;
INT32 blockmodulo;
RGBA_t *palette;
if (pwidth <= 0 || pheight <= 0)
if (pwidth <= 0 || pheight <= 0 || realpatch->columns == NULL)
return;
palette = HWR_GetTexturePalette();
ncols = pwidth;
// source advance
xfrac = 0;
xfracstep = FRACUNIT;
......@@ -299,7 +295,6 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
scale_y = FRACUNIT;
bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp);
......@@ -307,9 +302,11 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
blockmodulo = pblockwidth*bpp;
// 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,
pblockheight, blockmodulo,
......@@ -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
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight,
......@@ -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
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)
{
......@@ -530,16 +560,15 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
}
Z_Free(grMipmap->data);
grMipmap->data = NULL;
if (makebitmap)
{
MakeBlock(grMipmap);
HWR_DrawPatchInCache(grMipmap,
grMipmap->width, grMipmap->height,
patch->width, patch->height,
patch);
if (patch->format == PATCH_FORMAT_RGBA)
HWR_DrawPatchInCacheRGBA(grMipmap, grMipmap->width, grMipmap->height, patch->width, patch->height, patch);
else
HWR_DrawPatchInCache(grMipmap, grMipmap->width, grMipmap->height, patch->width, patch->height, patch);
}
}
......@@ -564,8 +593,8 @@ void HWR_FreeTextureData(patch_t *patch)
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnDeleteTexture(grPatch->mipmap);
if (grPatch->mipmap->data)
Z_Free(grPatch->mipmap->data);
Z_Free(grPatch->mipmap->data);
}
void HWR_FreeTexture(patch_t *patch)
......@@ -919,6 +948,115 @@ static void HWR_UpdatePatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
}
static void HWR_UpdatePatchPixels(GLMipmap_t *mipmap, UINT8 *pixels, INT16 patchheight, bitarray_t *pixels_opaque, INT16 left, INT16 top, INT16 right, INT16 bottom)
{
INT32 bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4)
I_Error("HWR_UpdatePatchPixels: no drawer defined for this bpp (%d)\n",bpp);
UINT8 *dest_pixels = (UINT8*)mipmap->data;
for (INT16 y = top; y < bottom; y++)
{
UINT8 *dest = &dest_pixels[(y * (mipmap->width * bpp)) + (left * bpp)];
for (INT16 x = left; x < right; x++)
{
UINT8 texel = 0x00;
UINT8 alpha = 0x00;
size_t position = (x * patchheight) + y;
if (in_bit_array(pixels_opaque, position))
{
texel = pixels[position];
alpha = 0xFF;
// Make pixel transparent if chroma keyed
if ((mipmap->flags & TF_CHROMAKEYED) && texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)
alpha = 0x00;
}
UINT16 texelu16;
RGBA_t colortemp;
switch (bpp)
{
case 2:
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3:
colortemp = V_GetColor(texel);
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4:
colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default:
*dest = texel;
break;
}
dest += bpp;
}
}
}
static void HWR_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
// -----------------+
......@@ -929,6 +1067,14 @@ void HWR_GetPatch(patch_t *patch)
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
// -------------------+
......@@ -941,7 +1087,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap)
Patch_CreateGL(patch);
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
HWR_GetPatch(patch);
......
......@@ -23,6 +23,7 @@
#include "../m_misc.h" //FIL_WriteFile()
#include "../r_main.h"
#include "../r_patch.h"
#include "../w_wad.h"
#include "../z_zone.h"
#include "../v_video.h"
......@@ -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_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)
{
FOutVector v[4];
......@@ -77,6 +138,9 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
UINT8 perplayershuffle = 0;
if (Patch_NeedsUpdate(gpatch, false))
Patch_DoDynamicUpdate(gpatch, false);
// make patch ready in hardware cache
if (!colormap)
HWR_GetPatch(gpatch);
......@@ -319,6 +383,9 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
UINT8 perplayershuffle = 0;
if (Patch_NeedsUpdate(gpatch, false))
Patch_DoDynamicUpdate(gpatch, false);
// make patch ready in hardware cache
if (!colormap)
HWR_GetPatch(gpatch);
......
......@@ -39,6 +39,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTextureRegion) (GLMipmap_t *TexInfo, INT32 x, INT32 y, INT32 width, INT32 height);
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
......@@ -93,6 +94,7 @@ struct hwdriver_s
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
UpdateTextureRegion pfnUpdateTextureRegion;
DeleteTexture pfnDeleteTexture;
ReadScreenTexture pfnReadScreenTexture;
GClipRect pfnGClipRect;
......
......@@ -117,6 +117,7 @@ patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *patch);
void HWR_UpdatePatchRegion(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
......
......@@ -37,9 +37,10 @@ void HWR_ClearSkyDome(void);
void HWR_BuildSkyDome(void);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_SetViewSize(void);
void HWR_DrawPatch( patch_t *gpatch, INT32 x, INT32 y, INT32 option );
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_MakePatch(patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
......
......@@ -1083,18 +1083,15 @@ void Flush(void)
while (TexCacheHead)
{
FTextureInfo *pTexInfo = TexCacheHead;
GLMipmap_t *texture = pTexInfo->texture;
TexCacheHead = pTexInfo->next;
if (pTexInfo->downloaded)
{
pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
pTexInfo->downloaded = 0;
}
GLMipmap_t *texture = pTexInfo->texture;
if (texture)
texture->downloaded = 0;
TexCacheHead = pTexInfo->next;
free(pTexInfo);
}
......@@ -1479,9 +1476,9 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
CurrentPolyFlags = PolyFlags;
}
static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
static RGBA_t *AllocTextureBuffer(unsigned width, unsigned height)
{
size_t size = pTexInfo->width * pTexInfo->height;
size_t size = width * height;
if (size > textureBufferSize)
{
textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t));
......@@ -1489,116 +1486,143 @@ static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t)));
textureBufferSize = size;
}
return textureBuffer;
}
// -----------------+
// UpdateTexture : Updates texture data.
// -----------------+
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
EXPORT void HWRAPI(UpdateTextureRegion) (GLMipmap_t *pTexInfo, INT32 x, INT32 y, INT32 width, INT32 height)
{
// Upload a texture
GLuint num = pTexInfo->downloaded;
boolean update = true;
INT32 w = pTexInfo->width, h = pTexInfo->height;
INT32 i, j;
INT32 i, j, dy;
const GLubyte *pImgData = (const GLubyte *)pTexInfo->data;
const GLvoid *ptex = NULL;
RGBA_t *tex = NULL;
// Generate a new texture name.
if (!num)
// Generate a new texture ID if there is none
if (pTexInfo->downloaded == 0)
{
pglGenTextures(1, &num);
pTexInfo->downloaded = num;
GLuint id = 0;
pglGenTextures(1, &id);
pTexInfo->downloaded = id;
update = false;
}
//GL_DBG_Printf("UpdateTexture %d %x\n", (INT32)num, pImgData);
if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88))
if (pTexInfo->format == GL_TEXFMT_P_8 || pTexInfo->format == GL_TEXFMT_AP_88)
{
AllocTextureBuffer(pTexInfo);
ptex = tex = textureBuffer;
ptex = AllocTextureBuffer(width, height);
for (j = 0; j < h; j++)
for (j = y, dy = 0; j < y + height; j++, dy++)
{
for (i = 0; i < w; i++)
const GLubyte *src = &pImgData[pTexInfo->width*j+x];
RGBA_t *tex = &textureBuffer[width*dy];
for (i = x; i < x + width; i++)
{
if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) &&
if ((*src == HWR_PATCHES_CHROMAKEY_COLORINDEX) &&
(pTexInfo->flags & TF_CHROMAKEYED))
{
tex[w*j+i].s.red = 0;
tex[w*j+i].s.green = 0;
tex[w*j+i].s.blue = 0;
tex[w*j+i].s.alpha = 0;
tex->s.red = 0;
tex->s.green = 0;
tex->s.blue = 0;
tex->s.alpha = 0;
pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
}
else
{
tex[w*j+i].s.red = myPaletteData[*pImgData].s.red;
tex[w*j+i].s.green = myPaletteData[*pImgData].s.green;
tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue;
tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha;
tex->s.red = myPaletteData[*src].s.red;
tex->s.green = myPaletteData[*src].s.green;
tex->s.blue = myPaletteData[*src].s.blue;
tex->s.alpha = myPaletteData[*src].s.alpha;
}
pImgData++;
src++;
if (pTexInfo->format == GL_TEXFMT_AP_88)
{
if (!(pTexInfo->flags & TF_CHROMAKEYED))
tex[w*j+i].s.alpha = *pImgData;
pImgData++;
tex->s.alpha = *src;
src++;
}
tex++;
}
}
}
else if (pTexInfo->format == GL_TEXFMT_RGBA)
{
// Directly upload the texture data without any kind of conversion.
ptex = pImgData;
if (x == 0 && y == 0 && width == pTexInfo->width && height == pTexInfo->height)
{
// Directly upload the texture data without any kind of conversion.
ptex = pImgData;
}
else
{
RGBA_t *src_pixels = (RGBA_t *)pTexInfo->data;
ptex = AllocTextureBuffer(width, height);
for (j = y, dy = 0; j < y + height; j++, dy++)
{
RGBA_t *src = &src_pixels[pTexInfo->width*j+x];
RGBA_t *tex = &textureBuffer[width*dy];
for (i = x; i < x + width; i++)
{
*tex = *src;
tex++;
src++;
}
}
}
}
else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
{
AllocTextureBuffer(pTexInfo);
ptex = tex = textureBuffer;
ptex = AllocTextureBuffer(width, height);
for (j = 0; j < h; j++)
for (j = y, dy = 0; j < y + height; j++, dy++)
{
for (i = 0; i < w; i++)
const GLubyte *src = &pImgData[pTexInfo->width*j+x];
RGBA_t *tex = &textureBuffer[width*dy];
for (i = x; i < x + width; i++)
{
tex[w*j+i].s.red = *pImgData;
tex[w*j+i].s.green = *pImgData;
tex[w*j+i].s.blue = *pImgData;
pImgData++;
tex[w*j+i].s.alpha = *pImgData;
pImgData++;
tex->s.red = *src;
tex->s.green = *src;
tex->s.blue = *src;
src++;
tex->s.alpha = *src;
src++;
tex++;
}
}
}
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks
{
AllocTextureBuffer(pTexInfo);
ptex = tex = textureBuffer;
ptex = AllocTextureBuffer(width, height);
for (j = 0; j < h; j++)
for (j = y, dy = 0; j < y + height; j++, dy++)
{
for (i = 0; i < w; i++)
const GLubyte *src = &pImgData[width*j+x];
RGBA_t *tex = &textureBuffer[width*dy];
for (i = x; i < x + width; i++)
{
tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't
tex[w*j+i].s.green = 255;
tex[w*j+i].s.blue = 255;
tex[w*j+i].s.alpha = *pImgData;
pImgData++;
// 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't
tex->s.red = 255;
tex->s.green = 255;
tex->s.blue = 255;
tex->s.alpha = *src;
src++;
tex++;
}
}
}
else
GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format);
pglBindTexture(GL_TEXTURE_2D, num);
tex_downloaded = num;
pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
tex_downloaded = pTexInfo->downloaded;
// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
if (pTexInfo->flags & TF_TRANSPARENT)
......@@ -1614,64 +1638,60 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
{
//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
if (MipMap)
{
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
if (pTexInfo->flags & TF_TRANSPARENT)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
if (update)
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
else
pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
}
}
else if (pTexInfo->format == GL_TEXFMT_ALPHA_8)
{
//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
if (MipMap)
{
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
if (pTexInfo->flags & TF_TRANSPARENT)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
if (update)
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
else
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
}
}
else
{
if (MipMap)
{
pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, pTexInfo->width, pTexInfo->height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
// Control the mipmap level of detail
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higher the detail
if (pTexInfo->flags & TF_TRANSPARENT)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mipmaps on transparent stuff
else
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
}
else
{
if (update)
pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
else
pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, pTexInfo->width, pTexInfo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
}
}
......@@ -1689,6 +1709,11 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter);
}
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
{
UpdateTextureRegion(pTexInfo, 0, 0, pTexInfo->width, pTexInfo->height);
}
// -----------------+
// SetTexture : The mipmap becomes the current texture source
// -----------------+
......
......@@ -92,7 +92,13 @@ enum patch {
patch_width,
patch_height,
patch_leftoffset,
patch_topoffset
patch_topoffset,
patch_iseditable,
// Methods
patch_getPixel,
patch_setPixel,
patch_copy,
patch_clear
};
static const char *const patch_opt[] = {
"valid",
......@@ -100,6 +106,12 @@ static const char *const patch_opt[] = {
"height",
"leftoffset",
"topoffset",
"is_editable",
// Methods
"getPixel",
"setPixel",
"copy",
"clear",
NULL};
static int patch_fields_ref = LUA_NOREF;
......@@ -286,6 +298,225 @@ static int colormap_get(lua_State *L)
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)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
......@@ -316,13 +547,56 @@ static int patch_get(lua_State *L)
case patch_topoffset:
lua_pushinteger(L, patch->topoffset);
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;
}
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)
......@@ -455,33 +729,64 @@ static int camera_set(lua_State *L)
return 0;
}
//
// lib_draw
//
// Image lib
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)));
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);
return 1;
}
// v.getSpritePatch(sprite, [frame, [angle, [rollangle]]])
static int libd_getSpritePatch(lua_State *L)
// image.getSpritePatch(sprite, [frame, [angle, [rollangle]]])
static int lib_image_getSpritePatch(lua_State *L)
{
UINT32 i; // sprite prefix
UINT32 frame = 0; // 'A'
UINT8 angle = 0;
spritedef_t *sprdef;
spriteframe_t *sprframe;
HUDONLY
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK
{
......@@ -539,14 +844,14 @@ static int libd_getSpritePatch(lua_State *L)
}
#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_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]])
static int libd_getSprite2Patch(lua_State *L)
// image.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]])
static int lib_image_getSprite2Patch(lua_State *L)
{
INT32 i; // skin number
playersprite_t j; // sprite2 prefix
......@@ -650,12 +955,51 @@ static int libd_getSprite2Patch(lua_State *L)
}
#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_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
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)
{
INT32 x, y, flags;
......@@ -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_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);
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);
camera_fields_ref = Lua_CreateFieldTable(L, camera_opt);
LUA_RegisterGlobalUserdata(L, "hudinfo", lib_getHudInfo, NULL, lib_hudinfolen);
luaL_register(L, "hud", lib_hud);
luaL_register(L, "image", lib_image);
return 0;
}
......
......@@ -51,54 +51,42 @@ sprcache_t *spritecachedinfo;
lighttable_t *colormaps;
lighttable_t *fadecolormap;
colorlookup_t r_colorlookup;
// for debugging/info purposes
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
// that matches the specified alpha style.
UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
{
RGBA_t output;
INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
#define clamp(c) max(min((c), 0xFF), 0x00)
INT16 fullalpha = clamp(((INT16)foreground.s.alpha) - (0xFF - alpha));
if (style == AST_TRANSLUCENT)
{
if (fullalpha <= 0)
output.rgba = background.rgba;
else
{
// don't go too high
if (fullalpha >= 0xFF)
fullalpha = 0xFF;
alpha = (UINT8)fullalpha;
// if the background pixel is empty,
// match software and don't blend anything
if (!background.s.alpha)
{
// ...unless the foreground pixel ISN'T actually translucent.
if (alpha == 0xFF)
output.rgba = foreground.rgba;
else
output.rgba = 0;
}
else
{
UINT8 beta = (0xFF - alpha);
output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
output.s.alpha = 0xFF;
}
}
return output.rgba;
UINT8 beta = 0xFF - fullalpha;
output.s.red = ((background.s.red * beta) + (foreground.s.red * fullalpha)) / 0xFF;
output.s.green = ((background.s.green * beta) + (foreground.s.green * fullalpha)) / 0xFF;
output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * fullalpha)) / 0xFF;
output.s.alpha = clamp(((INT16)background.s.alpha) + fullalpha);
}
#define clamp(c) max(min(c, 0xFF), 0x00);
else
{
float falpha = ((float)alpha / 256.0f);
float falpha = ((float)fullalpha / 255.0f);
float fr = ((float)foreground.s.red * falpha);
float fg = ((float)foreground.s.green * falpha);
float fb = ((float)foreground.s.blue * falpha);
output.s.alpha = clamp(((INT16)background.s.alpha) + fullalpha);
if (style == AST_ADD)
{
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
}
else if (style == AST_MODULATE)
{
fr = ((float)foreground.s.red / 256.0f);
fg = ((float)foreground.s.green / 256.0f);
fb = ((float)foreground.s.blue / 256.0f);
fr = ((float)foreground.s.red / 255.0f);
fg = ((float)foreground.s.green / 255.0f);
fb = ((float)foreground.s.blue / 255.0f);
output.s.red = clamp((int)(background.s.red * fr));
output.s.green = clamp((int)(background.s.green * fg));
output.s.blue = clamp((int)(background.s.blue * fb));
}
// just copy the pixel
else if (style == AST_COPY)
output.rgba = foreground.rgba;
else
{
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;
}
#undef clamp
return 0;
return ASTBlendPixel(background, foreground, style, alpha);
}
INT32 ASTTextureBlendingThreshold[2] = {255/11, (10*255/11)};
......@@ -152,13 +186,13 @@ UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UIN
if (alpha < ASTTextureBlendingThreshold[0])
return background.rgba;
return ASTBlendPixel(background, foreground, style, alpha);
return BlendPixelForTexture(background, foreground, style, alpha);
}
else // just copy the pixel
return foreground.rgba;
}
else
return ASTBlendPixel(background, foreground, style, alpha);
return BlendPixelForTexture(background, foreground, style, alpha);
}
// Blends two palette indexes for a texture patch, then
......@@ -190,18 +224,16 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
// just copy the pixel
else if (style == AST_COPY)
return foreground;
// use ASTBlendPixel for all other blend modes
// and find the nearest colour in the palette
// use ASTBlendPixel for all other blend modes and find the nearest color in the palette
else if (style != AST_TRANSLUCENT)
{
RGBA_t texel;
RGBA_t bg = V_GetMasterColor(background);
RGBA_t fg = V_GetMasterColor(foreground);
texel.rgba = ASTBlendPixel(bg, fg, style, alpha);
texel.rgba = BlendPixelForTexture(bg, fg, style, alpha);
return NearestColor(texel.s.red, texel.s.green, texel.s.blue);
}
// fallback if all above fails, somehow
// return the background pixel
return background;
}
......
......@@ -866,12 +866,14 @@ typedef struct
//
typedef struct
{
UINT8 type;
UINT8 format;
INT16 width, height;
INT16 leftoffset, topoffset;
UINT8 *pixels;
column_t *columns;
post_t *posts;
void *hardware; // OpenGL patch, allocated whenever necessary
void *flats[4]; // The patch as flats
......@@ -881,6 +883,26 @@ typedef struct
#endif
} patch_t;
typedef struct
{
patch_t patch;
post_t *posts;
} staticpatch_t;
typedef struct
{
patch_t patch;
boolean is_dirty;
boolean update_columns;
INT16 rect_dirty[4]; // left, top, right, bottom
INT16 column_dirty[2]; // left, right
bitarray_t *pixels_opaque;
} dynamicpatch_t;
#if defined(_MSC_VER)
#pragma pack(1)
#endif
......
......@@ -19,21 +19,213 @@
#include "hardware/hw_glob.h"
#endif
//
// Creates a patch.
//
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch);
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 = 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->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;
}
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 = Patch_Create(0, 0);
patch_t *patch = (patch_t*)Patch_Create(0, 0);
if (!source)
return patch;
......@@ -48,10 +240,12 @@ patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source)
Patch_CalcDataSizes(source, &total_pixels, &total_posts);
patch->columns = Z_Calloc(sizeof(column_t) * patch->width, PU_PATCH_DATA, NULL);
patch->posts = Z_Calloc(sizeof(post_t) * total_posts, PU_PATCH_DATA, NULL);
patch->pixels = Z_Calloc(sizeof(UINT8) * total_pixels, PU_PATCH_DATA, NULL);
Patch_MakeColumns(source, patch->width, patch->width, patch->pixels, patch->columns, patch->posts, false);
staticpatch_t *spatch = (staticpatch_t*)patch;
spatch->posts = Z_Calloc(sizeof(post_t) * total_posts, PU_PATCH_DATA, NULL);
Patch_MakeColumns(source, patch->width, patch->width, patch->pixels, patch->columns, spatch->posts, false);
return patch;
}
......@@ -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
if (patch->hardware)
HWR_FreeTexture(patch);
if (patch->hardware)
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
#endif
}
for (i = 0; i < 4; i++)
if (update_columns && dpatch->update_columns && Patch_CheckDirtyColumns(dpatch))
{
if (patch->flats[i])
Z_Free(patch->flats[i]);
if (patch->columns == NULL)
Patch_InitDynamicColumns(patch);
for (INT32 x = dpatch->column_dirty[0]; x < dpatch->column_dirty[1]; x++)
Patch_RebuildColumn(patch, x, dpatch->pixels_opaque);
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
......@@ -142,27 +808,48 @@ static void Patch_FreeData(patch_t *patch)
{
rotsprite_t *rotsprite = patch->rotated;
for (i = 0; i < rotsprite->angles; i++)
{
if (rotsprite->patches[i])
Patch_Free(rotsprite->patches[i]);
}
for (INT32 i = 0; i < rotsprite->angles; i++)
Patch_Free(rotsprite->patches[i]);
Z_Free(rotsprite->patches);
Z_Free(rotsprite);
patch->rotated = NULL;
}
#endif
}
if (patch->pixels)
Z_Free(patch->pixels);
if (patch->columns)
Z_Free(patch->columns);
if (patch->posts)
Z_Free(patch->posts);
static void Patch_FreeData(patch_t *patch)
{
#ifdef HWRENDER
if (patch->hardware)
HWR_FreeTexture(patch);
#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)
{
if (patch == NULL)
return;
Patch_FreeData(patch);
Z_Free(patch);
}
......@@ -185,9 +872,14 @@ void Patch_FreeTags(INT32 lowtag, INT32 hightag)
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)
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
......
......@@ -17,12 +17,47 @@
#include "r_fps.h"
#include "doomdef.h"
enum
{
PATCH_TYPE_STATIC,
PATCH_TYPE_DYNAMIC
};
enum
{
PATCH_FORMAT_PALETTE,
PATCH_FORMAT_RGBA
};
// Patch functions
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);
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_Free(patch_t *patch);
#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum)
void Patch_FreeTags(INT32 lowtag, INT32 hightag);
......
......@@ -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)
{
patch_t *rotated;
UINT16 *rawdst, *rawconv;
void *rawdst;
size_t size;
pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0;
......@@ -170,7 +170,6 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
INT32 sx, sy;
INT32 dx, dy;
INT32 ox, oy;
INT32 minx, miny, maxx, maxy;
// Don't cache angle = 0
if (angle < 1 || angle >= ROTANGLES)
......@@ -198,89 +197,88 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
newheight *= 2;
}
minx = newwidth;
miny = newheight;
maxx = 0;
maxy = 0;
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
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++)
{
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;
UINT32 *dest = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
sx >>= FRACBITS;
sy >>= FRACBITS;
patchformat = PICFMT_PATCH32;
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);
if (input != 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;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
rawdst[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input));
if (dx < minx)
minx = dx;
if (dy < miny)
miny = dy;
if (dx > maxx)
maxx = dx;
if (dy > maxy)
maxy = dy;
void *input = Picture_GetPatchPixel(patch, patchformat, sx, sy, bflip);
if (input != NULL)
{
dest[(dy * newwidth) + dx] = *(UINT32 *)input;
}
}
}
}
}
ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot);
width = (maxx - minx);
height = (maxy - miny);
if ((unsigned)(width * height) > size)
rawdst = dest;
format = PICFMT_FLAT32;
}
else
{
UINT16 *src, *dest;
size = (width * height);
rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
UINT16 *dest = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
src = &rawdst[(miny * newwidth) + minx];
dest = rawconv;
dy = height;
patchformat = PICFMT_PATCH;
while (dy--)
for (dy = 0; dy < newheight; dy++)
{
M_Memcpy(dest, src, width * sizeof(UINT16));
dest += width;
src += newwidth;
}
for (dx = 0; dx < newwidth; dx++)
{
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;
oy -= miny;
sx >>= FRACBITS;
sy >>= FRACBITS;
Z_Free(rawdst);
}
else
{
rawconv = rawdst;
width = newwidth;
height = newheight;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
{
void *input = Picture_GetPatchPixel(patch, patchformat, sx, sy, bflip);
if (input != NULL)
{
dest[(dy * newwidth) + dx] = (0xFF00 | (*(UINT8 *)input));
}
}
}
}
rawdst = dest;
format = PICFMT_FLAT16;
}
ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot);
// 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_SetUser(rotated, (void **)(&rotsprite->patches[idx]));
Z_Free(rawconv);
Z_Free(rawdst);
rotated->leftoffset = ox;
rotated->topoffset = oy;
......
......@@ -96,14 +96,14 @@ void *Picture_Convert(
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)inheight;
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)flags;
......@@ -111,7 +111,7 @@ static void *ReadPixelFunc_Flat_8bpp(void *picture, pictureformat_t informat, IN
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)flags;
......@@ -119,7 +119,7 @@ static void *ReadPixelFunc_Flat_16bpp(void *picture, pictureformat_t informat, I
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)flags;
......@@ -127,21 +127,21 @@ static void *ReadPixelFunc_Flat_32bpp(void *picture, pictureformat_t informat, I
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;
RGBA_t px = *(RGBA_t *)input;
return px.s.alpha;
}
static UINT8 GetAlphaFunc_16bpp(void *input, pictureflags_t flags)
UINT8 PicFmt_GetAlpha_16bpp(void *input, pictureflags_t flags)
{
(void)flags;
UINT16 px = *(UINT16 *)input;
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;
if (px == TRANSPARENTPIXEL && (flags & PICFLAGS_USE_TRANSPARENTPIXEL))
......@@ -151,7 +151,7 @@ static UINT8 GetAlphaFunc_8bpp(void *input, pictureflags_t flags)
}
// 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;
WRITEUINT32(ptr, px.rgba);
......@@ -159,7 +159,7 @@ static void *WritePatchPixel_i32o32(void *ptr, void *input)
}
// 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];
WRITEUINT32(ptr, px.rgba);
......@@ -167,7 +167,7 @@ static void *WritePatchPixel_i16o32(void *ptr, void *input)
}
// 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];
WRITEUINT32(ptr, px.rgba);
......@@ -175,7 +175,7 @@ static void *WritePatchPixel_i8o32(void *ptr, void *input)
}
// 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;
UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue);
......@@ -184,21 +184,21 @@ static void *WritePatchPixel_i32o16(void *ptr, void *input)
}
// input 16bpp output 16bpp
static void *WritePatchPixel_i16o16(void *ptr, void *input)
void *PicFmt_WritePixel_i16o16(void *ptr, void *input)
{
WRITEUINT16(ptr, *(UINT16 *)input);
return ptr;
}
// 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)));
return ptr;
}
// 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;
UINT8 px = NearestColor(in.s.red, in.s.green, in.s.blue);
......@@ -207,7 +207,7 @@ static void *WritePatchPixel_i32o8(void *ptr, void *input)
}
// input 16bpp output 8bpp
static void *WritePatchPixel_i16o8(void *ptr, void *input)
void *PicFmt_WritePixel_i16o8(void *ptr, void *input)
{
UINT16 px = *(UINT16 *)input;
WRITEUINT8(ptr, (px & 0xFF));
......@@ -215,7 +215,7 @@ static void *WritePatchPixel_i16o8(void *ptr, void *input)
}
// input 8bpp output 8bpp
static void *WritePatchPixel_i8o8(void *ptr, void *input)
void *PicFmt_WritePixel_i8o8(void *ptr, void *input)
{
WRITEUINT8(ptr, *(UINT8 *)input);
return ptr;
......@@ -289,22 +289,22 @@ void *Picture_PatchConvert(
void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL;
UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL;
void *(*writePatchPixel)(void *, void *) = NULL;
void *(*writePixelFunc)(void *, void *) = NULL;
if (Picture_IsPatchFormat(informat))
readPixelFunc = ReadPixelFunc_Patch;
readPixelFunc = PicFmt_ReadPixel_Patch;
else if (Picture_IsFlatFormat(informat))
{
switch (informat)
{
case PICFMT_FLAT32:
readPixelFunc = ReadPixelFunc_Flat_32bpp;
readPixelFunc = PicFmt_ReadPixel_Flat_32bpp;
break;
case PICFMT_FLAT16:
readPixelFunc = ReadPixelFunc_Flat_16bpp;
readPixelFunc = PicFmt_ReadPixel_Flat_16bpp;
break;
case PICFMT_FLAT:
readPixelFunc = ReadPixelFunc_Flat_8bpp;
readPixelFunc = PicFmt_ReadPixel_Flat_8bpp;
break;
default:
I_Error("Picture_PatchConvert: unsupported flat input format!");
......@@ -315,11 +315,11 @@ void *Picture_PatchConvert(
I_Error("Picture_PatchConvert: unsupported input format!");
if (inbpp == PICDEPTH_32BPP)
getAlphaFunc = GetAlphaFunc_32bpp;
getAlphaFunc = PicFmt_GetAlpha_32bpp;
else if (inbpp == PICDEPTH_16BPP)
getAlphaFunc = GetAlphaFunc_16bpp;
getAlphaFunc = PicFmt_GetAlpha_16bpp;
else if (inbpp == PICDEPTH_8BPP)
getAlphaFunc = GetAlphaFunc_8bpp;
getAlphaFunc = PicFmt_GetAlpha_8bpp;
switch (outformat)
{
......@@ -327,38 +327,36 @@ void *Picture_PatchConvert(
case PICFMT_DOOMPATCH32:
{
if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o32;
writePixelFunc = PicFmt_WritePixel_i32o32;
else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o32;
writePixelFunc = PicFmt_WritePixel_i16o32;
else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o32;
writePixelFunc = PicFmt_WritePixel_i8o32;
break;
}
case PICFMT_PATCH16:
case PICFMT_DOOMPATCH16:
if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o16;
writePixelFunc = PicFmt_WritePixel_i32o16;
else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o16;
writePixelFunc = PicFmt_WritePixel_i16o16;
else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o16;
writePixelFunc = PicFmt_WritePixel_i8o16;
break;
default: // PICFMT_PATCH
{
if (inbpp == PICDEPTH_32BPP)
writePatchPixel = WritePatchPixel_i32o8;
writePixelFunc = PicFmt_WritePixel_i32o8;
else if (inbpp == PICDEPTH_16BPP)
writePatchPixel = WritePatchPixel_i16o8;
writePixelFunc = PicFmt_WritePixel_i16o8;
else // PICFMT_PATCH
writePatchPixel = WritePatchPixel_i8o8;
writePixelFunc = PicFmt_WritePixel_i8o8;
break;
}
}
patch_t *out = Z_Calloc(sizeof(patch_t), PU_PATCH, NULL);
out->width = inwidth;
out->height = inheight;
patch_t *out = Patch_Create(inwidth, inheight);
out->format = inbpp == PICDEPTH_32BPP ? PATCH_FORMAT_RGBA : PATCH_FORMAT_PALETTE;
out->leftoffset = inleftoffset;
out->topoffset = intopoffset;
......@@ -367,12 +365,13 @@ void *Picture_PatchConvert(
out->columns = Z_Calloc(sizeof(column_t) * out->width, PU_PATCH_DATA, NULL);
out->pixels = Z_Calloc(max_pixels * (outbpp / 8), PU_PATCH_DATA, NULL);
out->posts = NULL;
UINT8 *imgptr = out->pixels;
unsigned *column_posts = Z_Calloc(sizeof(unsigned) * inwidth, PU_STATIC, NULL);
size_t bpp = Patch_GetBpp(out);
// Write columns
for (INT32 x = 0; x < inwidth; x++)
{
......@@ -381,7 +380,11 @@ void *Picture_PatchConvert(
boolean was_opaque = false;
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->num_posts = 0;
......@@ -410,9 +413,10 @@ void *Picture_PatchConvert(
{
num_posts++;
out->posts = Z_Realloc(out->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL);
post = &out->posts[num_posts - 1];
post->topdelta = (size_t)y;
staticpatch_t *spatch = (staticpatch_t*)out;
spatch->posts = Z_Realloc(spatch->posts, sizeof(post_t) * num_posts, PU_PATCH_DATA, NULL);
post = &spatch->posts[num_posts - 1];
post->topdelta = (unsigned)y;
post->length = 0;
post->data_offset = post_data_offset;
if (column_posts[x] == (unsigned)-1)
......@@ -423,24 +427,39 @@ void *Picture_PatchConvert(
was_opaque = true;
// Write the pixel
UINT8 *last_ptr = imgptr;
imgptr = writePatchPixel(last_ptr, input);
if (out->format == PATCH_FORMAT_RGBA)
{
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_data_offset += imgptr - last_ptr;
}
}
UINT8 *old_pixels = out->pixels;
size_t total_pixels = imgptr - out->pixels;
if (total_pixels != max_pixels)
out->pixels = Z_Realloc(out->pixels, total_pixels, PU_PATCH_DATA, NULL);
if (out->format != PATCH_FORMAT_RGBA)
{
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++)
{
column_t *column = &out->columns[x];
if (column->num_posts > 0)
column->posts = &out->posts[column_posts[x]];
{
staticpatch_t *spatch = (staticpatch_t*)out;
column->posts = &spatch->posts[column_posts[x]];
}
if (old_pixels != out->pixels)
column->pixels = out->pixels + (column->pixels - old_pixels);
}
......
......@@ -85,6 +85,25 @@ boolean Picture_IsDoomPatchFormat(pictureformat_t format);
boolean Picture_IsFlatFormat(pictureformat_t format);
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
typedef enum
{
......
......@@ -867,6 +867,7 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
dc_source = column->pixels + post->data_offset;
dc_texturemid = basetexturemid - (post->topdelta<<FRACBITS);
// Drawn by R_DrawColumn.
colfunc();
}
}
......
......@@ -86,6 +86,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(ClearBuffer);
GETFUNC(SetTexture);
GETFUNC(UpdateTexture);
GETFUNC(UpdateTextureRegion);
GETFUNC(DeleteTexture);
GETFUNC(ReadScreenTexture);
GETFUNC(GClipRect);
......
......@@ -1872,6 +1872,7 @@ void VID_StartupOpenGL(void)
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
HWD.pfnUpdateTextureRegion = hwSym("UpdateTextureRegion", NULL);
HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
......
This diff is collapsed.
......@@ -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 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b);
extern colorlookup_t r_colorlookup;
// Set the current RGB palette lookup to use for palettized graphics
void V_SetPalette(INT32 palettenum);
......@@ -156,7 +158,6 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
#define V_PERPLAYER 0x80000000 // automatically adjust coordinates/scaling for splitscreen mode
// 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_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)
......@@ -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_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)
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_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);
// Draw a linear block of pixels into the view buffer.
......