mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-28 15:11:55 +00:00
Implement RGBA image creation (WIP)
This commit is contained in:
parent
6d5f5a5247
commit
379c163bef
10 changed files with 935 additions and 441 deletions
|
@ -272,7 +272,6 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
|
||||||
fixed_t scale_y = FRACUNIT;
|
fixed_t scale_y = FRACUNIT;
|
||||||
|
|
||||||
INT32 bpp = format2bpp(mipmap->format);
|
INT32 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);
|
||||||
|
|
||||||
|
@ -294,6 +293,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,
|
||||||
|
@ -539,10 +571,10 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,16 +974,43 @@ static void HWR_UpdatePatchPixels(GLMipmap_t *mipmap, UINT8 *pixels, INT16 patch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
static void HWR_UpdateMipmapRegion(patch_t *patch, GLMipmap_t *grMipmap, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||||
{
|
{
|
||||||
GLPatch_t *grPatch = patch->hardware;
|
GLPatch_t *grPatch = patch->hardware;
|
||||||
|
|
||||||
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
|
if (grMipmap->width == 0 || grMipmap->data == NULL || patch->type == PATCH_TYPE_STATIC)
|
||||||
|
|
||||||
if (pixels_opaque == NULL || grMipmap->width == 0 || grMipmap->data == NULL)
|
|
||||||
HWR_MakePatch(patch, grPatch, grMipmap, true);
|
HWR_MakePatch(patch, grPatch, grMipmap, true);
|
||||||
else
|
else
|
||||||
HWR_UpdatePatchPixels(grMipmap, patch->pixels, patch->height, pixels_opaque, left, top, right, bottom);
|
{
|
||||||
|
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 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 it does have the texture, then call pfnUpdateTextureRegion to update it
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../m_misc.h" //FIL_WriteFile()
|
#include "../m_misc.h" //FIL_WriteFile()
|
||||||
#include "../r_draw.h" //viewborderlump
|
#include "../r_draw.h" //viewborderlump
|
||||||
#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"
|
||||||
|
@ -81,6 +82,9 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
||||||
float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
|
float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
|
||||||
float pdup = 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
|
// make patch ready in hardware cache
|
||||||
HWR_GetPatch(gpatch);
|
HWR_GetPatch(gpatch);
|
||||||
hwrPatch = ((GLPatch_t *)gpatch->hardware);
|
hwrPatch = ((GLPatch_t *)gpatch->hardware);
|
||||||
|
@ -138,6 +142,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);
|
||||||
|
@ -380,6 +387,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);
|
||||||
|
|
109
src/lua_hudlib.c
109
src/lua_hudlib.c
|
@ -301,6 +301,11 @@ static int lib_patch_getPixel(lua_State *L)
|
||||||
void *pixel = Patch_GetPixel(patch, x, y);
|
void *pixel = Patch_GetPixel(patch, x, y);
|
||||||
if (pixel == NULL)
|
if (pixel == NULL)
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
else if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
|
{
|
||||||
|
UINT32 px = *(UINT32 *)pixel;
|
||||||
|
lua_pushinteger(L, px);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UINT8 px = *(UINT8 *)pixel;
|
UINT8 px = *(UINT8 *)pixel;
|
||||||
|
@ -320,30 +325,40 @@ static int lib_patch_setPixel(lua_State *L)
|
||||||
int y = luaL_checkinteger(L, 3);
|
int y = luaL_checkinteger(L, 3);
|
||||||
int color = luaL_checkinteger(L, 4);
|
int color = luaL_checkinteger(L, 4);
|
||||||
|
|
||||||
UINT16 pixel = 0x0000;
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
if (color >= 0 && color <= 0xFF)
|
{
|
||||||
pixel = 0xFF00 | (UINT8)color;
|
UINT32 pixel = (UINT32)color;
|
||||||
|
Patch_SetPixel(patch, &pixel, PICFMT_FLAT32, x, y, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT16 pixel = 0x0000;
|
||||||
|
if (color >= 0 && color <= 0xFF)
|
||||||
|
pixel = 0xFF00 | (UINT8)color;
|
||||||
|
|
||||||
Patch_SetPixel(patch, &pixel, PICFMT_FLAT16, x, y, true);
|
Patch_SetPixel(patch, &pixel, PICFMT_FLAT16, x, y, true);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT16 *patch_update_buffer = NULL;
|
static void *patch_update_buffer = NULL;
|
||||||
static size_t patch_update_buffer_size = 0;
|
static size_t patch_update_buffer_size = 0;
|
||||||
|
|
||||||
static void img_prepare_buffer(size_t size)
|
static void img_prepare_buffer(size_t size)
|
||||||
{
|
{
|
||||||
if (size > patch_update_buffer_size)
|
if (size > patch_update_buffer_size)
|
||||||
{
|
{
|
||||||
patch_update_buffer = Z_Realloc(patch_update_buffer, size * sizeof(UINT16), PU_STATIC, NULL);
|
patch_update_buffer = Z_Realloc(patch_update_buffer, size, PU_STATIC, NULL);
|
||||||
patch_update_buffer_size = size;
|
patch_update_buffer_size = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void img_get_pixels_from_table(lua_State *L, size_t size)
|
static void img_get_pixels_from_table(lua_State *L, size_t size)
|
||||||
{
|
{
|
||||||
memset(patch_update_buffer, 0, patch_update_buffer_size);
|
UINT16 *buf = (UINT16 *)patch_update_buffer;
|
||||||
|
|
||||||
|
memset(buf, 0, patch_update_buffer_size);
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
|
@ -362,9 +377,30 @@ static void img_get_pixels_from_table(lua_State *L, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pal_idx != -1)
|
if (pal_idx != -1)
|
||||||
patch_update_buffer[i] = 0xFF00 | (UINT8)pal_idx;
|
buf[i] = 0xFF00 | (UINT8)pal_idx;
|
||||||
else
|
else
|
||||||
patch_update_buffer[i] = 0x0000;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,23 +458,41 @@ static int lib_patch_copy(lua_State *L)
|
||||||
{
|
{
|
||||||
size_t size = (unsigned)(src_img_width * src_img_height);
|
size_t size = (unsigned)(src_img_width * src_img_height);
|
||||||
|
|
||||||
img_prepare_buffer(size);
|
|
||||||
|
|
||||||
if (lua_objlen(L, 2) + 1 != size)
|
if (lua_objlen(L, 2) + 1 != size)
|
||||||
return luaL_error(L, "invalid table length");
|
return luaL_error(L, "invalid table length");
|
||||||
|
|
||||||
lua_pushvalue(L, 2);
|
lua_pushvalue(L, 2);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
|
||||||
img_get_pixels_from_table(L, size);
|
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);
|
lua_pop(L, 2);
|
||||||
|
|
||||||
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, PICFMT_FLAT16, sx, sy, sw, sh, dx, dy, copy_transparent);
|
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, format, sx, sy, sw, sh, dx, dy, copy_transparent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, copy_transparent);
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
|
{
|
||||||
|
// Unimplemented
|
||||||
|
}
|
||||||
|
else
|
||||||
|
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, copy_transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -665,15 +719,40 @@ static int camera_set(lua_State *L)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image lib
|
// Image lib
|
||||||
|
enum patch_fmt {
|
||||||
|
patch_fmt_palette,
|
||||||
|
patch_fmt_rgba
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const patch_fmt_opt[] = {
|
||||||
|
"palette",
|
||||||
|
"rgba",
|
||||||
|
NULL};
|
||||||
|
|
||||||
static int lib_image_create(lua_State *L)
|
static int lib_image_create(lua_State *L)
|
||||||
{
|
{
|
||||||
int w = luaL_checkinteger(L, 1);
|
int w = luaL_checkinteger(L, 1);
|
||||||
int h = luaL_checkinteger(L, 2);
|
int h = luaL_checkinteger(L, 2);
|
||||||
|
enum patch_fmt fmt = luaL_checkoption(L, 3, "palette", patch_fmt_opt);
|
||||||
|
|
||||||
if (w <= 0)
|
if (w <= 0)
|
||||||
return luaL_error(L, "invalid image width %d", w);
|
return luaL_error(L, "invalid image width %d", w);
|
||||||
if (h <= 0)
|
if (h <= 0)
|
||||||
return luaL_error(L, "invalid image width %d", h);
|
return luaL_error(L, "invalid image width %d", h);
|
||||||
LUA_PushUserdata(L, Patch_CreateDynamic(w, h), META_PATCH);
|
|
||||||
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -810,6 +810,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT8 type;
|
UINT8 type;
|
||||||
|
UINT8 format;
|
||||||
|
|
||||||
INT16 width, height;
|
INT16 width, height;
|
||||||
INT16 leftoffset, topoffset;
|
INT16 leftoffset, topoffset;
|
||||||
|
@ -841,6 +842,7 @@ typedef struct
|
||||||
boolean update_columns;
|
boolean update_columns;
|
||||||
|
|
||||||
INT16 rect_dirty[4]; // left, top, right, bottom
|
INT16 rect_dirty[4]; // left, top, right, bottom
|
||||||
|
INT16 column_dirty[2]; // left, right
|
||||||
|
|
||||||
bitarray_t *pixels_opaque;
|
bitarray_t *pixels_opaque;
|
||||||
} dynamicpatch_t;
|
} dynamicpatch_t;
|
||||||
|
|
413
src/r_patch.c
413
src/r_patch.c
|
@ -22,6 +22,9 @@
|
||||||
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch);
|
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch);
|
||||||
static void Patch_ClearDirtyRect(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_Create(INT16 width, INT16 height)
|
||||||
{
|
{
|
||||||
patch_t *patch = Z_Calloc(sizeof(staticpatch_t), PU_PATCH, NULL);
|
patch_t *patch = Z_Calloc(sizeof(staticpatch_t), PU_PATCH, NULL);
|
||||||
|
@ -29,24 +32,31 @@ patch_t *Patch_Create(INT16 width, INT16 height)
|
||||||
patch->width = width;
|
patch->width = width;
|
||||||
patch->height = height;
|
patch->height = height;
|
||||||
patch->type = PATCH_TYPE_STATIC;
|
patch->type = PATCH_TYPE_STATIC;
|
||||||
|
patch->format = PATCH_FORMAT_PALETTE;
|
||||||
|
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
patch_t *Patch_CreateDynamic(INT16 width, INT16 height)
|
patch_t *Patch_CreateDynamic(INT16 width, INT16 height, UINT8 format)
|
||||||
{
|
{
|
||||||
patch_t *patch = Z_Calloc(sizeof(dynamicpatch_t), PU_PATCH, NULL);
|
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->type = PATCH_TYPE_DYNAMIC;
|
||||||
|
patch->format = format;
|
||||||
|
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||||
dpatch->pixels_opaque = Z_Calloc(BIT_ARRAY_SIZE(width * height), PU_PATCH_DATA, NULL);
|
|
||||||
dpatch->is_dirty = false;
|
dpatch->is_dirty = false;
|
||||||
dpatch->update_columns = 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_ClearDirtyRect(dpatch);
|
||||||
|
Patch_ClearDirtyColumns(dpatch);
|
||||||
|
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +78,11 @@ void Patch_MarkDirtyRect(patch_t *patch, INT16 left, INT16 top, INT16 right, INT
|
||||||
dpatch->rect_dirty[2] = right;
|
dpatch->rect_dirty[2] = right;
|
||||||
if (bottom > dpatch->rect_dirty[3])
|
if (bottom > dpatch->rect_dirty[3])
|
||||||
dpatch->rect_dirty[3] = bottom;
|
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)
|
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch)
|
||||||
|
@ -109,15 +124,42 @@ static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch)
|
||||||
dpatch->rect_dirty[3] = 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)
|
static void Patch_InitDynamicColumns(patch_t *patch)
|
||||||
{
|
{
|
||||||
if (patch->columns == NULL)
|
if (patch->columns == NULL)
|
||||||
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);
|
||||||
|
|
||||||
|
size_t bpp = Patch_GetBpp(patch);
|
||||||
|
|
||||||
for (INT32 x = 0; x < patch->width; x++)
|
for (INT32 x = 0; x < patch->width; x++)
|
||||||
{
|
{
|
||||||
column_t *column = &patch->columns[x];
|
column_t *column = &patch->columns[x];
|
||||||
column->pixels = &patch->pixels[patch->height * x];
|
column->pixels = &patch->pixels[patch->height * x * bpp];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,12 +172,16 @@ void Patch_Clear(patch_t *patch)
|
||||||
|
|
||||||
memset(patch->pixels, 0, total_pixels * sizeof(UINT8));
|
memset(patch->pixels, 0, total_pixels * sizeof(UINT8));
|
||||||
|
|
||||||
for (INT32 x = 0; x < patch->width; x++)
|
if (patch->columns)
|
||||||
patch->columns[x].num_posts = 0;
|
{
|
||||||
|
for (INT32 x = 0; x < patch->width; x++)
|
||||||
|
patch->columns[x].num_posts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||||
|
|
||||||
memset(dpatch->pixels_opaque, 0, BIT_ARRAY_SIZE(total_pixels));
|
if (dpatch->pixels_opaque)
|
||||||
|
memset(dpatch->pixels_opaque, 0, BIT_ARRAY_SIZE(total_pixels));
|
||||||
|
|
||||||
dpatch->is_dirty = dpatch->update_columns = true;
|
dpatch->is_dirty = dpatch->update_columns = true;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +208,16 @@ void Patch_ClearRect(patch_t *patch, INT16 x, INT16 y, INT16 width, INT16 height
|
||||||
break;
|
break;
|
||||||
|
|
||||||
size_t position = (dx * patch->height) + dy;
|
size_t position = (dx * patch->height) + dy;
|
||||||
unset_bit_array(dpatch->pixels_opaque, position);
|
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;
|
dpatch->is_dirty = dpatch->update_columns = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,21 +321,47 @@ void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width,
|
||||||
// Other functions
|
// Other functions
|
||||||
//
|
//
|
||||||
|
|
||||||
static void Patch_RebuildColumn(column_t *column, INT32 x, INT16 height, bitarray_t *is_opaque)
|
unsigned Patch_GetBpp(patch_t *patch)
|
||||||
|
{
|
||||||
|
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;
|
post_t *post = NULL;
|
||||||
boolean was_opaque = false;
|
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;
|
unsigned post_count = column->num_posts;
|
||||||
column->num_posts = 0;
|
column->num_posts = 0;
|
||||||
|
|
||||||
for (INT32 y = 0; y < height; y++)
|
for (INT32 y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
|
size_t position = (x * height) + y;
|
||||||
|
|
||||||
// End span if we have a transparent pixel
|
// End span if we have a transparent pixel
|
||||||
if (!in_bit_array(is_opaque, (x * height) + y))
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
was_opaque = false;
|
UINT32 *pixels = (UINT32 *)patch->pixels;
|
||||||
continue;
|
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)
|
if (!was_opaque)
|
||||||
|
@ -296,7 +377,7 @@ static void Patch_RebuildColumn(column_t *column, INT32 x, INT16 height, bitarra
|
||||||
post = &column->posts[column->num_posts - 1];
|
post = &column->posts[column->num_posts - 1];
|
||||||
post->topdelta = (unsigned)y;
|
post->topdelta = (unsigned)y;
|
||||||
post->length = 0;
|
post->length = 0;
|
||||||
post->data_offset = post->topdelta;
|
post->data_offset = post->topdelta * bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
was_opaque = true;
|
was_opaque = true;
|
||||||
|
@ -323,21 +404,30 @@ void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y)
|
||||||
if (x < 0 || x >= patch->width || y < 0 || y >= patch->height)
|
if (x < 0 || x >= patch->width || y < 0 || y >= patch->height)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (Patch_NeedsUpdate(patch))
|
if (Patch_NeedsUpdate(patch, true))
|
||||||
Patch_DoDynamicUpdate(patch);
|
Patch_DoDynamicUpdate(patch, true);
|
||||||
|
|
||||||
if (patch->columns == NULL)
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
bitarray_t *pixels_opaque = Patch_GetOpaqueRegions(patch);
|
|
||||||
if (pixels_opaque)
|
|
||||||
{
|
{
|
||||||
|
// Well, that makes it easy
|
||||||
size_t position = (x * patch->height) + y;
|
size_t position = (x * patch->height) + y;
|
||||||
|
return &patch->pixels[position * 4];
|
||||||
if (!in_bit_array(pixels_opaque, position))
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (patch->columns == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return &patch->pixels[position];
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
column_t *column = &patch->columns[x];
|
column_t *column = &patch->columns[x];
|
||||||
|
@ -384,12 +474,25 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void *(*writePixelFunc)(void *, void *) = NULL;
|
void *(*writePixelFunc)(void *, void *) = NULL;
|
||||||
if (inbpp == PICDEPTH_32BPP)
|
|
||||||
writePixelFunc = PicFmt_WritePixel_i32o8;
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
else if (inbpp == PICDEPTH_16BPP)
|
{
|
||||||
writePixelFunc = PicFmt_WritePixel_i16o8;
|
if (inbpp == PICDEPTH_32BPP)
|
||||||
else if (inbpp == PICDEPTH_8BPP)
|
writePixelFunc = PicFmt_WritePixel_i32o32;
|
||||||
writePixelFunc = PicFmt_WritePixel_i8o8;
|
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 the patch is empty
|
||||||
if (!patch->pixels)
|
if (!patch->pixels)
|
||||||
|
@ -401,35 +504,65 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch->pixels == NULL)
|
if (patch->pixels == NULL)
|
||||||
patch->pixels = Z_Calloc(patch->width * patch->height, PU_PATCH_DATA, NULL);
|
patch->pixels = Z_Calloc(patch->width * patch->height * Patch_GetBpp(patch), PU_PATCH_DATA, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||||
|
|
||||||
size_t position = (x * patch->height) + y;
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
|
|
||||||
if (!pixel_is_opaque)
|
|
||||||
{
|
{
|
||||||
if (transparent_overwrite)
|
size_t position = (x * patch->height) + y;
|
||||||
|
|
||||||
|
RGBA_t *dest = (RGBA_t*)(&patch->pixels[position * 4]);
|
||||||
|
|
||||||
|
if (!pixel_is_opaque)
|
||||||
{
|
{
|
||||||
// No longer a pixel in this position, so columns need to be rebuilt
|
if (transparent_overwrite)
|
||||||
unset_bit_array(dpatch->pixels_opaque, position);
|
{
|
||||||
dpatch->update_columns = true;
|
// No longer a pixel in this position, so columns need to be rebuilt
|
||||||
|
dest->s.alpha = 0;
|
||||||
|
dpatch->update_columns = true;
|
||||||
|
dpatch->is_dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No 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;
|
dpatch->is_dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No pixel in this position, so columns need to be rebuilt
|
size_t position = (x * patch->height) + y;
|
||||||
if (!in_bit_array(dpatch->pixels_opaque, position))
|
|
||||||
|
if (!pixel_is_opaque)
|
||||||
{
|
{
|
||||||
set_bit_array(dpatch->pixels_opaque, position);
|
if (transparent_overwrite)
|
||||||
dpatch->update_columns = true;
|
{
|
||||||
|
// No longer a pixel in this position, so columns need to be rebuilt
|
||||||
|
unset_bit_array(dpatch->pixels_opaque, position);
|
||||||
|
dpatch->update_columns = true;
|
||||||
|
dpatch->is_dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No 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);
|
writePixelFunc(&patch->pixels[position], pixel);
|
||||||
|
|
||||||
dpatch->is_dirty = true;
|
dpatch->is_dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dpatch->is_dirty)
|
if (dpatch->is_dirty)
|
||||||
|
@ -449,7 +582,7 @@ void Patch_UpdatePixels(patch_t *patch,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (patch->pixels == NULL)
|
if (patch->pixels == NULL)
|
||||||
patch->pixels = Z_Calloc(patch->width * patch->height, PU_PATCH_DATA, 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;
|
void *(*readPixelFunc)(void *, pictureformat_t, INT32, INT32, INT32, INT32, pictureflags_t) = NULL;
|
||||||
UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL;
|
UINT8 (*getAlphaFunc)(void *, pictureflags_t) = NULL;
|
||||||
|
@ -475,20 +608,41 @@ void Patch_UpdatePixels(patch_t *patch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Picture_FormatBPP(informat))
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
case PICDEPTH_32BPP:
|
switch (Picture_FormatBPP(informat))
|
||||||
getAlphaFunc = PicFmt_GetAlpha_32bpp;
|
{
|
||||||
writePixelFunc = PicFmt_WritePixel_i32o8;
|
case PICDEPTH_32BPP:
|
||||||
break;
|
getAlphaFunc = PicFmt_GetAlpha_32bpp;
|
||||||
case PICDEPTH_16BPP:
|
writePixelFunc = PicFmt_WritePixel_i32o32;
|
||||||
getAlphaFunc = PicFmt_GetAlpha_16bpp;
|
break;
|
||||||
writePixelFunc = PicFmt_WritePixel_i16o8;
|
case PICDEPTH_16BPP:
|
||||||
break;
|
getAlphaFunc = PicFmt_GetAlpha_16bpp;
|
||||||
case PICDEPTH_8BPP:
|
writePixelFunc = PicFmt_WritePixel_i16o32;
|
||||||
getAlphaFunc = PicFmt_GetAlpha_8bpp;
|
break;
|
||||||
writePixelFunc = PicFmt_WritePixel_i8o8;
|
case PICDEPTH_8BPP:
|
||||||
break;
|
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)
|
if (readPixelFunc == NULL || writePixelFunc == NULL || getAlphaFunc == NULL)
|
||||||
|
@ -498,67 +652,120 @@ void Patch_UpdatePixels(patch_t *patch,
|
||||||
|
|
||||||
Patch_MarkDirtyRect(patch, dx, dy, dx + sw, dy + sh);
|
Patch_MarkDirtyRect(patch, dx, dy, dx + sw, dy + sh);
|
||||||
|
|
||||||
for (INT32 x = dx; x < dx + sw; x++, sx++)
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
if (x < 0 || sx < 0)
|
for (INT32 y = dy; y < dy + sh; y++, sy++)
|
||||||
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)
|
if (y < 0 || sy < 0)
|
||||||
continue;
|
continue;
|
||||||
else if (y >= patch->height || src_y >= src_img_height)
|
else if (y >= patch->height || sy >= src_img_height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
boolean opaque = false;
|
INT32 src_x = sx;
|
||||||
|
|
||||||
// Read pixel
|
for (INT32 x = dx; x < dx + sw; x++, src_x++)
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
unset_bit_array(dpatch->pixels_opaque, position);
|
if (transparent_overwrite)
|
||||||
dpatch->update_columns = dpatch->is_dirty = true;
|
{
|
||||||
|
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
|
}
|
||||||
|
}
|
||||||
|
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 (!in_bit_array(dpatch->pixels_opaque, position))
|
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)
|
||||||
{
|
{
|
||||||
set_bit_array(dpatch->pixels_opaque, position);
|
if (transparent_overwrite)
|
||||||
dpatch->update_columns = true;
|
{
|
||||||
|
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);
|
writePixelFunc(&patch->pixels[position], input);
|
||||||
|
|
||||||
dpatch->is_dirty = true;
|
dpatch->is_dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean Patch_NeedsUpdate(patch_t *patch)
|
boolean Patch_NeedsUpdate(patch_t *patch, boolean needs_columns)
|
||||||
{
|
{
|
||||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||||
return dpatch->is_dirty;
|
return dpatch->is_dirty || (needs_columns && dpatch->update_columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patch_DoDynamicUpdate(patch_t *patch)
|
void Patch_DoDynamicUpdate(patch_t *patch, boolean update_columns)
|
||||||
{
|
{
|
||||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||||
return;
|
return;
|
||||||
|
@ -572,22 +779,25 @@ void Patch_DoDynamicUpdate(patch_t *patch)
|
||||||
|
|
||||||
if (Patch_CheckDirtyRect(dpatch))
|
if (Patch_CheckDirtyRect(dpatch))
|
||||||
{
|
{
|
||||||
if (dpatch->update_columns)
|
|
||||||
{
|
|
||||||
for (INT32 x = dpatch->rect_dirty[0]; x < dpatch->rect_dirty[2]; x++)
|
|
||||||
Patch_RebuildColumn(&patch->columns[x], x, patch->height, dpatch->pixels_opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
if (patch->hardware)
|
if (patch->hardware)
|
||||||
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
|
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (update_columns && dpatch->update_columns && Patch_CheckDirtyColumns(dpatch))
|
||||||
|
{
|
||||||
|
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);
|
Patch_FreeMiscData(patch);
|
||||||
|
|
||||||
dpatch->is_dirty = false;
|
dpatch->is_dirty = false;
|
||||||
dpatch->update_columns = false;
|
|
||||||
|
|
||||||
Patch_ClearDirtyRect(dpatch);
|
Patch_ClearDirtyRect(dpatch);
|
||||||
}
|
}
|
||||||
|
@ -643,7 +853,7 @@ static void Patch_FreeData(patch_t *patch)
|
||||||
staticpatch_t *spatch = (staticpatch_t*)patch;
|
staticpatch_t *spatch = (staticpatch_t*)patch;
|
||||||
Z_Free(spatch->posts);
|
Z_Free(spatch->posts);
|
||||||
}
|
}
|
||||||
else if (patch->type == PATCH_TYPE_DYNAMIC)
|
else if (patch->type == PATCH_TYPE_DYNAMIC && patch->format == PATCH_FORMAT_PALETTE)
|
||||||
{
|
{
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||||
for (INT32 x = 0; x < dpatch->patch.width; x++)
|
for (INT32 x = 0; x < dpatch->patch.width; x++)
|
||||||
|
@ -684,7 +894,12 @@ 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->pixels, 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
|
||||||
|
|
|
@ -23,9 +23,15 @@ enum
|
||||||
PATCH_TYPE_DYNAMIC
|
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);
|
patch_t *Patch_CreateDynamic(INT16 width, INT16 height, UINT8 format);
|
||||||
|
|
||||||
void *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y);
|
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_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32 x, INT32 y, boolean transparent_overwrite);
|
||||||
|
@ -35,8 +41,10 @@ void Patch_UpdatePixels(patch_t *patch,
|
||||||
INT32 sx, INT32 sy, INT32 sw, INT32 sh, INT32 dx, INT32 dy,
|
INT32 sx, INT32 sy, INT32 sw, INT32 sh, INT32 dx, INT32 dy,
|
||||||
boolean transparent_overwrite);
|
boolean transparent_overwrite);
|
||||||
|
|
||||||
boolean Patch_NeedsUpdate(patch_t *patch);
|
unsigned Patch_GetBpp(patch_t *patch);
|
||||||
void Patch_DoDynamicUpdate(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_MarkDirtyRect(patch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom);
|
||||||
|
|
||||||
void Patch_Clear(patch_t *patch);
|
void Patch_Clear(patch_t *patch);
|
||||||
|
|
|
@ -160,7 +160,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;
|
||||||
|
|
||||||
|
@ -177,7 +177,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)
|
||||||
|
@ -205,89 +204,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);
|
||||||
|
|
||||||
|
patchformat = PICFMT_PATCH32;
|
||||||
|
|
||||||
|
for (dy = 0; dy < newheight; dy++)
|
||||||
{
|
{
|
||||||
x = (dx - (newwidth / 2)) * FRACUNIT;
|
for (dx = 0; dx < newwidth; dx++)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawdst = dest;
|
||||||
|
format = PICFMT_FLAT32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT16 *dest = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
|
||||||
|
|
||||||
|
patchformat = PICFMT_PATCH;
|
||||||
|
|
||||||
|
for (dy = 0; dy < newheight; dy++)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
sx >>= FRACBITS;
|
||||||
|
sy >>= FRACBITS;
|
||||||
|
|
||||||
|
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);
|
ox = (newwidth / 2) + (leftoffset - xpivot);
|
||||||
oy = (newheight / 2) + (patch->topoffset - ypivot);
|
oy = (newheight / 2) + (patch->topoffset - ypivot);
|
||||||
width = (maxx - minx);
|
|
||||||
height = (maxy - miny);
|
|
||||||
|
|
||||||
if ((unsigned)(width * height) > size)
|
|
||||||
{
|
|
||||||
UINT16 *src, *dest;
|
|
||||||
|
|
||||||
size = (width * height);
|
|
||||||
rawconv = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
src = &rawdst[(miny * newwidth) + minx];
|
|
||||||
dest = rawconv;
|
|
||||||
dy = height;
|
|
||||||
|
|
||||||
while (dy--)
|
|
||||||
{
|
|
||||||
M_Memcpy(dest, src, width * sizeof(UINT16));
|
|
||||||
dest += width;
|
|
||||||
src += newwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
ox -= minx;
|
|
||||||
oy -= miny;
|
|
||||||
|
|
||||||
Z_Free(rawdst);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rawconv = rawdst;
|
|
||||||
width = newwidth;
|
|
||||||
height = newheight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
|
@ -356,6 +356,7 @@ void *Picture_PatchConvert(
|
||||||
}
|
}
|
||||||
|
|
||||||
patch_t *out = Patch_Create(inwidth, inheight);
|
patch_t *out = Patch_Create(inwidth, inheight);
|
||||||
|
out->format = inbpp == PICDEPTH_32BPP ? PATCH_FORMAT_RGBA : PATCH_FORMAT_PALETTE;
|
||||||
out->leftoffset = inleftoffset;
|
out->leftoffset = inleftoffset;
|
||||||
out->topoffset = intopoffset;
|
out->topoffset = intopoffset;
|
||||||
|
|
||||||
|
@ -369,6 +370,8 @@ void *Picture_PatchConvert(
|
||||||
|
|
||||||
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++)
|
||||||
{
|
{
|
||||||
|
@ -377,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;
|
||||||
|
|
||||||
|
@ -420,18 +427,30 @@ 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 = writePixelFunc(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++)
|
||||||
{
|
{
|
||||||
|
|
587
src/v_video.c
587
src/v_video.c
|
@ -497,8 +497,141 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix
|
||||||
return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff));
|
return *(v_translevel + (((*(v_colormap + source[ofs>>FRACBITS]))<<8)&0xff00) + (*dest&0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
|
||||||
|
|
||||||
|
static void AdjustPositionByOffsets(patch_t *patch, fixed_t pscale, fixed_t vscale, INT32 scrn, fixed_t *x, fixed_t *y)
|
||||||
|
{
|
||||||
|
fixed_t offsetx = 0, offsety = 0;
|
||||||
|
|
||||||
|
// left offset
|
||||||
|
if (scrn & V_FLIP)
|
||||||
|
offsetx = FixedMul((patch->width - patch->leftoffset)<<FRACBITS, pscale) + 1;
|
||||||
|
else
|
||||||
|
offsetx = FixedMul(patch->leftoffset<<FRACBITS, pscale);
|
||||||
|
|
||||||
|
// top offset
|
||||||
|
offsety = FixedMul(patch->topoffset<<FRACBITS, vscale);
|
||||||
|
|
||||||
|
// Subtract the offsets from x/y positions
|
||||||
|
*x -= offsetx;
|
||||||
|
*y -= offsety;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT8 AdjustPositionForScreen(INT32 *scrn, fixed_t *x, fixed_t *y, fixed_t *fdup, fixed_t *colfrac, fixed_t *vdup, fixed_t *rowfrac)
|
||||||
|
{
|
||||||
|
UINT8 perplayershuffle = 0;
|
||||||
|
|
||||||
|
INT32 flags = *scrn;
|
||||||
|
|
||||||
|
fixed_t adjusty = ((flags & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
||||||
|
|
||||||
|
*vdup >>= 1;
|
||||||
|
*rowfrac <<= 1;
|
||||||
|
*y >>= 1;
|
||||||
|
|
||||||
|
#ifndef QUADS
|
||||||
|
(void)x;
|
||||||
|
(void)fdup;
|
||||||
|
(void)colfrac;
|
||||||
|
#else
|
||||||
|
if (splitscreen > 1) // 3 or 4 players
|
||||||
|
{
|
||||||
|
fixed_t adjustx = ((flags & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
||||||
|
|
||||||
|
*fdup >>= 1;
|
||||||
|
*colfrac <<= 1;
|
||||||
|
*x >>= 1;
|
||||||
|
|
||||||
|
if (stplyr == &players[displayplayer])
|
||||||
|
{
|
||||||
|
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle |= 1;
|
||||||
|
if (!(flags & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||||
|
perplayershuffle |= 4;
|
||||||
|
*scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||||
|
}
|
||||||
|
else if (stplyr == &players[secondarydisplayplayer])
|
||||||
|
{
|
||||||
|
if (!(flags & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle |= 1;
|
||||||
|
if (!(flags & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||||
|
perplayershuffle |= 8;
|
||||||
|
*x += adjustx;
|
||||||
|
*scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||||
|
}
|
||||||
|
else if (stplyr == &players[thirddisplayplayer])
|
||||||
|
{
|
||||||
|
if (!(flags & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle |= 2;
|
||||||
|
if (!(flags & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||||
|
perplayershuffle |= 4;
|
||||||
|
*y += adjusty;
|
||||||
|
*scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||||
|
}
|
||||||
|
else //if (stplyr == &players[fourthdisplayplayer])
|
||||||
|
{
|
||||||
|
if (!(flags & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle |= 2;
|
||||||
|
if (!(flags & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||||
|
perplayershuffle |= 8;
|
||||||
|
*x += adjustx;
|
||||||
|
*y += adjusty;
|
||||||
|
*scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
// 2 players
|
||||||
|
{
|
||||||
|
if (stplyr == &players[displayplayer])
|
||||||
|
{
|
||||||
|
if (!(flags & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle = 1;
|
||||||
|
*scrn &= ~V_SNAPTOBOTTOM;
|
||||||
|
}
|
||||||
|
else //if (stplyr == &players[secondarydisplayplayer])
|
||||||
|
{
|
||||||
|
if (!(flags & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||||
|
perplayershuffle = 2;
|
||||||
|
*y += adjusty;
|
||||||
|
*scrn &= ~V_SNAPTOTOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return perplayershuffle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AdjustPositionForVirtualRes(fixed_t dup, INT32 scrn, UINT8 perplayershuffle, fixed_t *x, fixed_t *y)
|
||||||
|
{
|
||||||
|
if (vid.width != BASEVIDWIDTH * dup)
|
||||||
|
{
|
||||||
|
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
||||||
|
// so center this imaginary screen
|
||||||
|
if (scrn & V_SNAPTORIGHT)
|
||||||
|
*x += (vid.width - (BASEVIDWIDTH * dup));
|
||||||
|
else if (!(scrn & V_SNAPTOLEFT))
|
||||||
|
*x += (vid.width - (BASEVIDWIDTH * dup)) / 2;
|
||||||
|
if (perplayershuffle & 4)
|
||||||
|
*x -= (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
||||||
|
else if (perplayershuffle & 8)
|
||||||
|
*x += (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
||||||
|
}
|
||||||
|
if (vid.height != BASEVIDHEIGHT * dup)
|
||||||
|
{
|
||||||
|
// same thing here
|
||||||
|
if (scrn & V_SNAPTOBOTTOM)
|
||||||
|
*y += (vid.height - (BASEVIDHEIGHT * dup));
|
||||||
|
else if (!(scrn & V_SNAPTOTOP))
|
||||||
|
*y += (vid.height - (BASEVIDHEIGHT * dup)) / 2;
|
||||||
|
if (perplayershuffle & 1)
|
||||||
|
*y -= (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
||||||
|
else if (perplayershuffle & 2)
|
||||||
|
*y += (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draws a patch scaled to arbitrary size.
|
// Draws a patch scaled to arbitrary size.
|
||||||
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap)
|
void V_DrawPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap)
|
||||||
{
|
{
|
||||||
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
||||||
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
|
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
|
||||||
|
@ -514,10 +647,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
||||||
|
|
||||||
UINT8 perplayershuffle = 0;
|
UINT8 perplayershuffle = 0;
|
||||||
|
|
||||||
if (Patch_NeedsUpdate(patch))
|
if (rendermode == render_none)
|
||||||
Patch_DoDynamicUpdate(patch);
|
|
||||||
|
|
||||||
if (patch->columns == NULL || rendermode == render_none)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
@ -528,6 +658,18 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (Patch_NeedsUpdate(patch, true))
|
||||||
|
Patch_DoDynamicUpdate(patch, true);
|
||||||
|
|
||||||
|
if (patch->columns == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (patch->format == PATCH_FORMAT_RGBA)
|
||||||
|
{
|
||||||
|
V_DrawPatchRGBA(x, y, pscale, vscale, scrn, patch, colormap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
patchdrawfunc = standardpdraw;
|
patchdrawfunc = standardpdraw;
|
||||||
|
|
||||||
v_translevel = NULL;
|
v_translevel = NULL;
|
||||||
|
@ -577,92 +719,10 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
||||||
colfrac = FixedDiv(FRACUNIT, fdup);
|
colfrac = FixedDiv(FRACUNIT, fdup);
|
||||||
rowfrac = FixedDiv(FRACUNIT, vdup);
|
rowfrac = FixedDiv(FRACUNIT, vdup);
|
||||||
|
|
||||||
{
|
AdjustPositionByOffsets(patch, pscale, vscale, scrn, &x, &y);
|
||||||
fixed_t offsetx = 0, offsety = 0;
|
|
||||||
|
|
||||||
// left offset
|
|
||||||
if (scrn & V_FLIP)
|
|
||||||
offsetx = FixedMul((patch->width - patch->leftoffset)<<FRACBITS, pscale) + 1;
|
|
||||||
else
|
|
||||||
offsetx = FixedMul(patch->leftoffset<<FRACBITS, pscale);
|
|
||||||
|
|
||||||
// top offset
|
|
||||||
offsety = FixedMul(patch->topoffset<<FRACBITS, vscale);
|
|
||||||
|
|
||||||
// Subtract the offsets from x/y positions
|
|
||||||
x -= offsetx;
|
|
||||||
y -= offsety;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitscreen && (scrn & V_PERPLAYER))
|
if (splitscreen && (scrn & V_PERPLAYER))
|
||||||
{
|
perplayershuffle = AdjustPositionForScreen(&scrn, &x, &y, &fdup, &colfrac, &vdup, &rowfrac);
|
||||||
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
|
||||||
vdup >>= 1;
|
|
||||||
rowfrac <<= 1;
|
|
||||||
y >>= 1;
|
|
||||||
#ifdef QUADS
|
|
||||||
if (splitscreen > 1) // 3 or 4 players
|
|
||||||
{
|
|
||||||
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
|
|
||||||
fdup >>= 1;
|
|
||||||
colfrac <<= 1;
|
|
||||||
x >>= 1;
|
|
||||||
if (stplyr == &players[displayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle |= 1;
|
|
||||||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
||||||
perplayershuffle |= 4;
|
|
||||||
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
|
||||||
}
|
|
||||||
else if (stplyr == &players[secondarydisplayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle |= 1;
|
|
||||||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
||||||
perplayershuffle |= 8;
|
|
||||||
x += adjustx;
|
|
||||||
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
|
||||||
}
|
|
||||||
else if (stplyr == &players[thirddisplayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle |= 2;
|
|
||||||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
||||||
perplayershuffle |= 4;
|
|
||||||
y += adjusty;
|
|
||||||
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
|
||||||
}
|
|
||||||
else //if (stplyr == &players[fourthdisplayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle |= 2;
|
|
||||||
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
|
||||||
perplayershuffle |= 8;
|
|
||||||
x += adjustx;
|
|
||||||
y += adjusty;
|
|
||||||
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
// 2 players
|
|
||||||
{
|
|
||||||
if (stplyr == &players[displayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle = 1;
|
|
||||||
scrn &= ~V_SNAPTOBOTTOM;
|
|
||||||
}
|
|
||||||
else //if (stplyr == &players[secondarydisplayplayer])
|
|
||||||
{
|
|
||||||
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
|
||||||
perplayershuffle = 2;
|
|
||||||
y += adjusty;
|
|
||||||
scrn &= ~V_SNAPTOTOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
desttop = screens[scrn&V_PARAMMASK];
|
desttop = screens[scrn&V_PARAMMASK];
|
||||||
|
|
||||||
|
@ -698,31 +758,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vid.width != BASEVIDWIDTH * dup)
|
AdjustPositionForVirtualRes(dup, scrn, perplayershuffle, &x, &y);
|
||||||
{
|
|
||||||
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
|
||||||
// so center this imaginary screen
|
|
||||||
if (scrn & V_SNAPTORIGHT)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup));
|
|
||||||
else if (!(scrn & V_SNAPTOLEFT))
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup)) / 2;
|
|
||||||
if (perplayershuffle & 4)
|
|
||||||
x -= (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
|
||||||
else if (perplayershuffle & 8)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
|
||||||
}
|
|
||||||
if (vid.height != BASEVIDHEIGHT * dup)
|
|
||||||
{
|
|
||||||
// same thing here
|
|
||||||
if (scrn & V_SNAPTOBOTTOM)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup));
|
|
||||||
else if (!(scrn & V_SNAPTOTOP))
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup)) / 2;
|
|
||||||
if (perplayershuffle & 1)
|
|
||||||
y -= (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
|
||||||
else if (perplayershuffle & 2)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
desttop += (y*vid.width) + x;
|
desttop += (y*vid.width) + x;
|
||||||
|
@ -779,6 +815,187 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draws a patch scaled to arbitrary size.
|
||||||
|
static void V_DrawPatchRGBA(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap)
|
||||||
|
{
|
||||||
|
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
|
||||||
|
UINT32 alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT);
|
||||||
|
UINT32 blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT);
|
||||||
|
|
||||||
|
fixed_t col, ofs, colfrac, rowfrac, fdup, vdup;
|
||||||
|
INT32 dup;
|
||||||
|
column_t *column;
|
||||||
|
UINT8 *desttop, *dest, *deststart, *destend;
|
||||||
|
const RGBA_t *source;
|
||||||
|
const UINT8 *deststop;
|
||||||
|
fixed_t pwidth; // patch width
|
||||||
|
fixed_t offx = 0; // x offset
|
||||||
|
|
||||||
|
UINT8 perplayershuffle = 0;
|
||||||
|
|
||||||
|
static colorlookup_t colorlookup;
|
||||||
|
|
||||||
|
if (Patch_NeedsUpdate(patch, true))
|
||||||
|
Patch_DoDynamicUpdate(patch, true);
|
||||||
|
|
||||||
|
if (patch->columns == NULL || rendermode == render_none)
|
||||||
|
return;
|
||||||
|
|
||||||
|
patchdrawfunc = standardpdraw;
|
||||||
|
|
||||||
|
v_translevel = NULL;
|
||||||
|
if (alphalevel || blendmode)
|
||||||
|
{
|
||||||
|
if (alphalevel == 10) // V_HUDTRANSHALF
|
||||||
|
alphalevel = hudminusalpha[st_translucency];
|
||||||
|
else if (alphalevel == 11) // V_HUDTRANS
|
||||||
|
alphalevel = 10 - st_translucency;
|
||||||
|
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
||||||
|
alphalevel = hudplusalpha[st_translucency];
|
||||||
|
|
||||||
|
if (alphalevel >= 10)
|
||||||
|
return; // invis
|
||||||
|
|
||||||
|
if (alphalevel || blendmode)
|
||||||
|
{
|
||||||
|
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||||
|
patchdrawfunc = translucentpdraw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v_colormap = NULL;
|
||||||
|
if (colormap)
|
||||||
|
{
|
||||||
|
v_colormap = colormap;
|
||||||
|
patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
dup = vid.dup;
|
||||||
|
if (scrn & V_SCALEPATCHMASK) switch (scrn & V_SCALEPATCHMASK)
|
||||||
|
{
|
||||||
|
case V_NOSCALEPATCH:
|
||||||
|
dup = 1;
|
||||||
|
break;
|
||||||
|
case V_SMALLSCALEPATCH:
|
||||||
|
dup = vid.smalldup;
|
||||||
|
break;
|
||||||
|
case V_MEDSCALEPATCH:
|
||||||
|
dup = vid.meddup;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdup = vdup = pscale * dup;
|
||||||
|
if (vscale != pscale)
|
||||||
|
vdup = vscale * dup;
|
||||||
|
colfrac = FixedDiv(FRACUNIT, fdup);
|
||||||
|
rowfrac = FixedDiv(FRACUNIT, vdup);
|
||||||
|
|
||||||
|
AdjustPositionByOffsets(patch, pscale, vscale, scrn, &x, &y);
|
||||||
|
|
||||||
|
if (splitscreen && (scrn & V_PERPLAYER))
|
||||||
|
perplayershuffle = AdjustPositionForScreen(&scrn, &x, &y, &fdup, &colfrac, &vdup, &rowfrac);
|
||||||
|
|
||||||
|
desttop = screens[scrn&V_PARAMMASK];
|
||||||
|
|
||||||
|
if (!desttop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
InitColorLUT(&colorlookup, pMasterPalette, false);
|
||||||
|
|
||||||
|
deststop = desttop + vid.rowbytes * vid.height;
|
||||||
|
|
||||||
|
if (scrn & V_NOSCALESTART)
|
||||||
|
{
|
||||||
|
x >>= FRACBITS;
|
||||||
|
y >>= FRACBITS;
|
||||||
|
desttop += (y*vid.width) + x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x *= dup;
|
||||||
|
y *= dup;
|
||||||
|
x >>= FRACBITS;
|
||||||
|
y >>= FRACBITS;
|
||||||
|
|
||||||
|
// Center it if necessary
|
||||||
|
if (!(scrn & V_SCALEPATCHMASK))
|
||||||
|
{
|
||||||
|
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
||||||
|
if (!v_translevel && x == 0 && patch->width == BASEVIDWIDTH && y == 0 && patch->height == BASEVIDHEIGHT)
|
||||||
|
{
|
||||||
|
column = &patch->columns[0];
|
||||||
|
if (column->num_posts && !column->posts[0].topdelta)
|
||||||
|
{
|
||||||
|
source = (RGBA_t*)column->pixels;
|
||||||
|
if (source->s.alpha)
|
||||||
|
{
|
||||||
|
UINT8 palidx = GetColorLUT(&colorlookup, source->s.red, source->s.green, source->s.blue);
|
||||||
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, palidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustPositionForVirtualRes(dup, scrn, perplayershuffle, &x, &y);
|
||||||
|
}
|
||||||
|
|
||||||
|
desttop += (y*vid.width) + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pscale != FRACUNIT) // scale width properly
|
||||||
|
{
|
||||||
|
pwidth = patch->width<<FRACBITS;
|
||||||
|
pwidth = FixedMul(pwidth, pscale);
|
||||||
|
pwidth *= dup;
|
||||||
|
pwidth >>= FRACBITS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pwidth = patch->width * dup;
|
||||||
|
|
||||||
|
deststart = desttop;
|
||||||
|
destend = desttop + pwidth;
|
||||||
|
|
||||||
|
for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++)
|
||||||
|
{
|
||||||
|
if (scrn & V_FLIP) // offx is measured from right edge instead of left
|
||||||
|
{
|
||||||
|
if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
||||||
|
break;
|
||||||
|
if (x+pwidth-offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x+offx < 0) // don't draw off the left of the screen (WRAP PREVENTION)
|
||||||
|
continue;
|
||||||
|
if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
column = &patch->columns[col>>FRACBITS];
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < column->num_posts; i++)
|
||||||
|
{
|
||||||
|
post_t *post = &column->posts[i];
|
||||||
|
source = (RGBA_t*)(column->pixels + post->data_offset);
|
||||||
|
dest = desttop;
|
||||||
|
if (scrn & V_FLIP)
|
||||||
|
dest = deststart + (destend - desttop);
|
||||||
|
dest += FixedInt(FixedMul(post->topdelta<<FRACBITS,vdup))*vid.width;
|
||||||
|
|
||||||
|
for (ofs = 0; dest < deststop && (size_t)(ofs>>FRACBITS) < post->length; ofs += rowfrac)
|
||||||
|
{
|
||||||
|
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
|
||||||
|
{
|
||||||
|
RGBA_t texel = source[ofs>>FRACBITS];
|
||||||
|
UINT8 palidx = GetColorLUT(&colorlookup, texel.s.red, texel.s.green, texel.s.blue);
|
||||||
|
*dest = patchdrawfunc(dest, &palidx, 0);
|
||||||
|
}
|
||||||
|
dest += vid.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draws a patch cropped and scaled to arbitrary size.
|
// Draws a patch cropped and scaled to arbitrary size.
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -794,9 +1011,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
||||||
|
|
||||||
UINT8 perplayershuffle = 0;
|
UINT8 perplayershuffle = 0;
|
||||||
|
|
||||||
if (Patch_NeedsUpdate(patch))
|
|
||||||
Patch_DoDynamicUpdate(patch);
|
|
||||||
|
|
||||||
if (patch->columns == NULL || rendermode == render_none)
|
if (patch->columns == NULL || rendermode == render_none)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -808,6 +1022,12 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (Patch_NeedsUpdate(patch, true))
|
||||||
|
Patch_DoDynamicUpdate(patch, true);
|
||||||
|
|
||||||
|
if (patch->columns == NULL || rendermode == render_none)
|
||||||
|
return;
|
||||||
|
|
||||||
patchdrawfunc = standardpdraw;
|
patchdrawfunc = standardpdraw;
|
||||||
|
|
||||||
v_translevel = NULL;
|
v_translevel = NULL;
|
||||||
|
@ -869,7 +1089,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
||||||
#ifdef QUADS
|
#ifdef QUADS
|
||||||
if (splitscreen > 1) // 3 or 4 players
|
if (splitscreen > 1) // 3 or 4 players
|
||||||
{
|
{
|
||||||
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
|
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
|
||||||
fdup >>= 1;
|
fdup >>= 1;
|
||||||
colfrac <<= 1;
|
colfrac <<= 1;
|
||||||
x >>= 1;
|
x >>= 1;
|
||||||
|
@ -952,36 +1172,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
||||||
|
|
||||||
// Center it if necessary
|
// Center it if necessary
|
||||||
if (!(scrn & V_SCALEPATCHMASK))
|
if (!(scrn & V_SCALEPATCHMASK))
|
||||||
{
|
AdjustPositionForVirtualRes(dup, scrn, perplayershuffle, &x, &y);
|
||||||
// if it's meant to cover the whole screen, black out the rest
|
|
||||||
// no the patch is cropped do not do this ever
|
|
||||||
|
|
||||||
if (vid.width != BASEVIDWIDTH * dup)
|
|
||||||
{
|
|
||||||
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
|
||||||
// so center this imaginary screen
|
|
||||||
if (scrn & V_SNAPTORIGHT)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup));
|
|
||||||
else if (!(scrn & V_SNAPTOLEFT))
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup)) / 2;
|
|
||||||
if (perplayershuffle & 4)
|
|
||||||
x -= (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
|
||||||
else if (perplayershuffle & 8)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * dup)) / 4;
|
|
||||||
}
|
|
||||||
if (vid.height != BASEVIDHEIGHT * dup)
|
|
||||||
{
|
|
||||||
// same thing here
|
|
||||||
if (scrn & V_SNAPTOBOTTOM)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup));
|
|
||||||
else if (!(scrn & V_SNAPTOTOP))
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup)) / 2;
|
|
||||||
if (perplayershuffle & 1)
|
|
||||||
y -= (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
|
||||||
else if (perplayershuffle & 2)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * dup)) / 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
desttop += (y*vid.width) + x;
|
desttop += (y*vid.width) + x;
|
||||||
}
|
}
|
||||||
|
@ -1057,8 +1248,8 @@ void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t
|
||||||
|
|
||||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)dest_patch;
|
dynamicpatch_t *dpatch = (dynamicpatch_t *)dest_patch;
|
||||||
|
|
||||||
if (Patch_NeedsUpdate(src_patch))
|
if (Patch_NeedsUpdate(src_patch, true))
|
||||||
Patch_DoDynamicUpdate(src_patch);
|
Patch_DoDynamicUpdate(src_patch, true);
|
||||||
|
|
||||||
if (src_patch->columns == NULL)
|
if (src_patch->columns == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -1110,23 +1301,7 @@ void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t
|
||||||
fixed_t colfrac = FixedDiv(FRACUNIT, fdup);
|
fixed_t colfrac = FixedDiv(FRACUNIT, fdup);
|
||||||
fixed_t rowfrac = FixedDiv(FRACUNIT, vdup);
|
fixed_t rowfrac = FixedDiv(FRACUNIT, vdup);
|
||||||
|
|
||||||
fixed_t offsetx = 0, offsety = 0;
|
AdjustPositionByOffsets(src_patch, pscale, vscale, flags, &x, &y);
|
||||||
|
|
||||||
// left offset
|
|
||||||
if (flags & V_FLIP)
|
|
||||||
offsetx = FixedMul((src_patch->width - src_patch->leftoffset)<<FRACBITS, pscale) + 1;
|
|
||||||
else
|
|
||||||
offsetx = FixedMul(src_patch->leftoffset<<FRACBITS, pscale);
|
|
||||||
|
|
||||||
// top offset
|
|
||||||
offsety = FixedMul(src_patch->topoffset<<FRACBITS, vscale);
|
|
||||||
|
|
||||||
// Subtract the offsets from x/y positions
|
|
||||||
x -= offsetx;
|
|
||||||
y -= offsety;
|
|
||||||
|
|
||||||
x >>= FRACBITS;
|
|
||||||
y >>= FRACBITS;
|
|
||||||
|
|
||||||
fixed_t pwidth = src_patch->width;
|
fixed_t pwidth = src_patch->width;
|
||||||
if (pscale != FRACUNIT)
|
if (pscale != FRACUNIT)
|
||||||
|
@ -1404,31 +1579,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
||||||
h *= vid.dup;
|
h *= vid.dup;
|
||||||
|
|
||||||
// Center it if necessary
|
// Center it if necessary
|
||||||
if (vid.width != BASEVIDWIDTH * vid.dup)
|
AdjustPositionForVirtualRes(vid.dup, c, perplayershuffle, &x, &y);
|
||||||
{
|
|
||||||
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
|
||||||
// so center this imaginary screen
|
|
||||||
if (c & V_SNAPTORIGHT)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOLEFT))
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 4)
|
|
||||||
x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 8)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
if (vid.height != BASEVIDHEIGHT * vid.dup)
|
|
||||||
{
|
|
||||||
// same thing here
|
|
||||||
if (c & V_SNAPTOBOTTOM)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOTOP))
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 1)
|
|
||||||
y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 2)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= vid.width || y >= vid.height)
|
if (x >= vid.width || y >= vid.height)
|
||||||
|
@ -1608,31 +1759,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
||||||
h *= vid.dup;
|
h *= vid.dup;
|
||||||
|
|
||||||
// Center it if necessary
|
// Center it if necessary
|
||||||
if (vid.width != BASEVIDWIDTH * vid.dup)
|
AdjustPositionForVirtualRes(vid.dup, c, perplayershuffle, &x, &y);
|
||||||
{
|
|
||||||
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
|
||||||
// so center this imaginary screen
|
|
||||||
if (c & V_SNAPTORIGHT)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOLEFT))
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 4)
|
|
||||||
x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 8)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
if (vid.height != BASEVIDHEIGHT * vid.dup)
|
|
||||||
{
|
|
||||||
// same thing here
|
|
||||||
if (c & V_SNAPTOBOTTOM)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOTOP))
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 1)
|
|
||||||
y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 2)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= vid.width || y >= vid.height)
|
if (x >= vid.width || y >= vid.height)
|
||||||
|
@ -1790,31 +1917,7 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
|
||||||
h *= vid.dup;
|
h *= vid.dup;
|
||||||
|
|
||||||
// Center it if necessary
|
// Center it if necessary
|
||||||
if (vid.width != BASEVIDWIDTH * vid.dup)
|
AdjustPositionForVirtualRes(vid.dup, c, perplayershuffle, &x, &y);
|
||||||
{
|
|
||||||
// dup adjustments pretend that screen width is BASEVIDWIDTH * dup,
|
|
||||||
// so center this imaginary screen
|
|
||||||
if (c & V_SNAPTORIGHT)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOLEFT))
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 4)
|
|
||||||
x -= (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 8)
|
|
||||||
x += (vid.width - (BASEVIDWIDTH * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
if (vid.height != BASEVIDHEIGHT * vid.dup)
|
|
||||||
{
|
|
||||||
// same thing here
|
|
||||||
if (c & V_SNAPTOBOTTOM)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup));
|
|
||||||
else if (!(c & V_SNAPTOTOP))
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2;
|
|
||||||
if (perplayershuffle & 1)
|
|
||||||
y -= (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
else if (perplayershuffle & 2)
|
|
||||||
y += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= vid.width || y >= vid.height)
|
if (x >= vid.width || y >= vid.height)
|
||||||
|
|
|
@ -155,7 +155,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)
|
||||||
|
@ -170,8 +169,10 @@ 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 copy_transparent);
|
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 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);
|
||||||
|
|
Loading…
Reference in a new issue