Refactored colormaps storage, management and xforms; colormaps are now stored as versioned refcounted objects and passed to rendering code by reference; SDL palettes are reset on images only when versions change; folded fades and xforms into single func; supporting several concurrent colormap xforms
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2063 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
+8
-170
@@ -55,11 +55,6 @@
|
||||
// XXX: was 32 picked experimentally?
|
||||
#define OSCILLOSCOPE_RATE 32
|
||||
|
||||
static void init_xform_control (void);
|
||||
static void uninit_xform_control (void);
|
||||
static void xform_complete (void);
|
||||
static void xform_PLUT_step (SIZE TDelta);
|
||||
static void FlushPLUTXForms (void);
|
||||
static int ambient_anim_task (void *data);
|
||||
|
||||
static BOOLEAN getLineWithinWidth(TEXT *pText,
|
||||
@@ -509,177 +504,21 @@ DrawAlienFrame (FRAME aframe, PSEQUENCE pSeq)
|
||||
UnbatchGraphics ();
|
||||
}
|
||||
|
||||
typedef struct xform_control
|
||||
{
|
||||
COLORMAPPTR CMapPtr;
|
||||
SIZE Ticks, TTotal, TOrig;
|
||||
UBYTE OldCMap[PLUT_BYTE_SIZE];
|
||||
} XFORM_CONTROL;
|
||||
|
||||
#define MAX_XFORMS 32
|
||||
static struct {
|
||||
XFORM_CONTROL TaskControl[MAX_XFORMS];
|
||||
volatile int XFormCurrent, XFormInsertPoint;
|
||||
volatile BOOLEAN XFormsPending;
|
||||
Mutex XFormLock;
|
||||
} XFormControl;
|
||||
|
||||
static void
|
||||
init_xform_control (void)
|
||||
{
|
||||
XFormControl.XFormCurrent = XFormControl.XFormInsertPoint = 0;
|
||||
XFormControl.XFormsPending = FALSE;
|
||||
XFormControl.XFormLock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
}
|
||||
|
||||
static void
|
||||
uninit_xform_control (void)
|
||||
{
|
||||
DestroyMutex (XFormControl.XFormLock);
|
||||
}
|
||||
|
||||
static void
|
||||
xform_complete (void)
|
||||
{
|
||||
LockMutex (XFormControl.XFormLock);
|
||||
if (XFormControl.XFormsPending)
|
||||
{
|
||||
SetColorMap (XFormControl.TaskControl[XFormControl.XFormCurrent].CMapPtr);
|
||||
if (++XFormControl.XFormCurrent >= MAX_XFORMS)
|
||||
{
|
||||
XFormControl.XFormCurrent = 0;
|
||||
}
|
||||
if (XFormControl.XFormCurrent == XFormControl.XFormInsertPoint)
|
||||
{
|
||||
XFormControl.XFormsPending = FALSE;
|
||||
}
|
||||
}
|
||||
UnlockMutex (XFormControl.XFormLock);
|
||||
}
|
||||
|
||||
void
|
||||
init_communication (void)
|
||||
{
|
||||
subtitle_mutex = CreateMutex ("Subtitle Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
init_xform_control ();
|
||||
}
|
||||
|
||||
void
|
||||
uninit_communication (void)
|
||||
{
|
||||
DestroyMutex (subtitle_mutex);
|
||||
uninit_xform_control ();
|
||||
}
|
||||
|
||||
static volatile BOOLEAN ColorChange;
|
||||
static volatile BOOLEAN SummaryChange;
|
||||
static volatile BOOLEAN ClearSubtitle;
|
||||
|
||||
/* Only one thread should ever be allowed to be calling this at any time */
|
||||
static void
|
||||
xform_PLUT_step (SIZE TDelta)
|
||||
{
|
||||
XFORM_CONTROL *control;
|
||||
COLORMAPPTR ColorMapPtr;
|
||||
int i;
|
||||
|
||||
if (!XFormControl.XFormsPending)
|
||||
return;
|
||||
|
||||
control = &XFormControl.TaskControl[XFormControl.XFormCurrent];
|
||||
|
||||
ColorMapPtr = control->CMapPtr;
|
||||
|
||||
if (TDelta > control->TTotal)
|
||||
TDelta = control->TTotal;
|
||||
|
||||
if (_varPLUTs && control->TOrig != 0)
|
||||
{
|
||||
#define XFORM_SCALE 0x10000
|
||||
UBYTE *pCurCMap, *pOldCMap, *pNewCMap;
|
||||
int frac;
|
||||
|
||||
pCurCMap = GET_VAR_PLUT (*ColorMapPtr);
|
||||
pOldCMap = control->OldCMap;
|
||||
pNewCMap = (UBYTE*)ColorMapPtr + 2;
|
||||
|
||||
frac = (int)(control->TOrig - control->TTotal) * XFORM_SCALE
|
||||
/ control->TOrig;
|
||||
|
||||
for (i = 0; i < PLUT_BYTE_SIZE; i++)
|
||||
{
|
||||
*pCurCMap = (UBYTE)(*pOldCMap + ((int)*pNewCMap - *pOldCMap)
|
||||
* frac / XFORM_SCALE);
|
||||
pOldCMap++;
|
||||
pCurCMap++;
|
||||
pNewCMap++;
|
||||
}
|
||||
ColorChange = TRUE;
|
||||
}
|
||||
else if (control->TOrig == 0)
|
||||
{ // asked for immediate xform
|
||||
ColorChange = TRUE;
|
||||
}
|
||||
control->TTotal -= TDelta;
|
||||
if (!control->TTotal)
|
||||
{
|
||||
xform_complete ();
|
||||
}
|
||||
}
|
||||
|
||||
/* This should be thread-safe without locking the XFormControl because
|
||||
* only one thread should be Flushing at any given time, constant
|
||||
* writes are atomic anyway, and Flush is the only routine that writes
|
||||
* XFormFlush. */
|
||||
|
||||
static void
|
||||
FlushPLUTXForms (void)
|
||||
{
|
||||
while (XFormControl.XFormsPending)
|
||||
{
|
||||
xform_complete ();
|
||||
}
|
||||
}
|
||||
|
||||
DWORD
|
||||
XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
if (ColorMapPtr)
|
||||
{
|
||||
XFORM_CONTROL *control;
|
||||
|
||||
// FlushPLUTXForms ();
|
||||
|
||||
LockMutex (XFormControl.XFormLock);
|
||||
while (XFormControl.XFormsPending
|
||||
&& (XFormControl.XFormInsertPoint == XFormControl.XFormCurrent))
|
||||
{
|
||||
UnlockMutex (XFormControl.XFormLock);
|
||||
FlushPLUTXForms ();
|
||||
LockMutex (XFormControl.XFormLock);
|
||||
}
|
||||
|
||||
control = &XFormControl.TaskControl[XFormControl.XFormInsertPoint];
|
||||
|
||||
memcpy (control->OldCMap, GET_VAR_PLUT (*ColorMapPtr), PLUT_BYTE_SIZE);
|
||||
|
||||
control->CMapPtr = ColorMapPtr;
|
||||
if ((control->Ticks = TimeInterval) <= 0)
|
||||
control->Ticks = 1; /* prevent divide by zero and negative fade */
|
||||
control->TTotal = control->TOrig = TimeInterval;
|
||||
|
||||
if (++XFormControl.XFormInsertPoint >= MAX_XFORMS)
|
||||
XFormControl.XFormInsertPoint = 0;
|
||||
|
||||
XFormControl.XFormsPending = TRUE;
|
||||
|
||||
UnlockMutex (XFormControl.XFormLock);
|
||||
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
RefreshResponses (PENCOUNTER_STATE pES)
|
||||
{
|
||||
@@ -867,6 +706,7 @@ ambient_anim_task (void *data)
|
||||
BOOLEAN TransitionDone = FALSE;
|
||||
BOOLEAN TalkFrameChanged = FALSE;
|
||||
BOOLEAN FrameChanged[MAX_ANIMATIONS];
|
||||
BOOLEAN ColorChange = FALSE;
|
||||
|
||||
while ((CommFrame = CommData.AlienFrame) == 0 && !Task_ReadState (task, TASK_EXIT))
|
||||
TaskSwitch ();
|
||||
@@ -963,7 +803,7 @@ ambient_anim_task (void *data)
|
||||
|
||||
if (pSeq->AnimType == COLOR_ANIM)
|
||||
{
|
||||
XFormPLUT (
|
||||
XFormColorMap (
|
||||
GetColorMapAddress (pSeq->AnimObj.CurCMap),
|
||||
(COUNT) (pSeq->Alarm - 1)
|
||||
);
|
||||
@@ -1208,7 +1048,7 @@ ambient_anim_task (void *data)
|
||||
if (!summary)
|
||||
{
|
||||
CONTEXT OldContext;
|
||||
BOOLEAN CheckSub = 0;
|
||||
BOOLEAN CheckSub = FALSE;
|
||||
BOOLEAN ClearSub;
|
||||
int sub_state;
|
||||
|
||||
@@ -1228,8 +1068,8 @@ ambient_anim_task (void *data)
|
||||
CommData.AlienFrame = CommFrame;
|
||||
DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]);
|
||||
CommData.AlienFrame = F;
|
||||
CheckSub = 1;
|
||||
ClearSub = SummaryChange ? TRUE : FALSE;
|
||||
CheckSub = TRUE;
|
||||
ClearSub = SummaryChange;
|
||||
ColorChange = SummaryChange = FALSE;
|
||||
}
|
||||
if (Change || ClearSub)
|
||||
@@ -1270,7 +1110,7 @@ ambient_anim_task (void *data)
|
||||
TalkFrameChanged = FALSE;
|
||||
}
|
||||
Change = FALSE;
|
||||
CheckSub = 1;
|
||||
CheckSub = TRUE;
|
||||
}
|
||||
|
||||
if (optSubtitles && CheckSub && sub_state >= SPACE_SUBTITLE)
|
||||
@@ -1290,7 +1130,7 @@ ambient_anim_task (void *data)
|
||||
}
|
||||
UnbatchGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
xform_PLUT_step(ElapsedTicks);
|
||||
ColorChange = XFormColorMap_step ();
|
||||
}
|
||||
FinishTask (task);
|
||||
return(0);
|
||||
@@ -1914,11 +1754,9 @@ DoCommunication (PENCOUNTER_STATE pES)
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
FlushPLUTXForms ();
|
||||
ColorChange = FALSE;
|
||||
FlushColorXForms ();
|
||||
ClearSubtitle = FALSE;
|
||||
|
||||
FlushColorXForms ();
|
||||
StopMusic ();
|
||||
StopSound ();
|
||||
StopTrack ();
|
||||
|
||||
@@ -588,7 +588,7 @@ GiveRadios (RESPONSE_REF R)
|
||||
CommData.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED;
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), ONE_SECOND / 2);
|
||||
|
||||
|
||||
@@ -1342,7 +1342,7 @@ NatureOfConversation (RESPONSE_REF R)
|
||||
/* Melnorme reports any news and turns purple */
|
||||
NPCPhrase (BUY_OR_SELL);
|
||||
AlienTalkSegue(1);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND / 2);
|
||||
AlienTalkSegue((COUNT)~0);
|
||||
@@ -1432,7 +1432,7 @@ DoBluster (RESPONSE_REF R)
|
||||
|
||||
if (PLAYER_SAID (R, trade_is_for_the_weak))
|
||||
{
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 2)
|
||||
), ONE_SECOND / 2);
|
||||
|
||||
@@ -1629,7 +1629,7 @@ DoFirstMeeting (RESPONSE_REF R)
|
||||
}
|
||||
else if (PLAYER_SAID (R, yes_really_testing))
|
||||
{
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), ONE_SECOND / 2);
|
||||
|
||||
@@ -1638,7 +1638,7 @@ DoFirstMeeting (RESPONSE_REF R)
|
||||
else if (PLAYER_SAID (R, we_apologize))
|
||||
{
|
||||
SET_GAME_STATE (MELNORME_ANGER, 0);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), ONE_SECOND / 2);
|
||||
|
||||
@@ -1677,7 +1677,7 @@ DoMelnormeMiffed (RESPONSE_REF R)
|
||||
}
|
||||
SET_GAME_STATE (MELNORME_MIFFED_COUNT, miffed_count);
|
||||
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 2)
|
||||
), ONE_SECOND / 2);
|
||||
}
|
||||
@@ -1749,7 +1749,7 @@ DoMelnormePissed (RESPONSE_REF R)
|
||||
}
|
||||
SET_GAME_STATE (MELNORME_PISSED_COUNT, pissed_count);
|
||||
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 2)
|
||||
), ONE_SECOND / 2);
|
||||
}
|
||||
@@ -1804,7 +1804,7 @@ DoMelnormeHate (RESPONSE_REF R)
|
||||
}
|
||||
SET_GAME_STATE (MELNORME_HATE_COUNT, hate_count);
|
||||
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 2)
|
||||
), ONE_SECOND / 2);
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ ExitConversation (RESPONSE_REF R)
|
||||
if (PLAYER_SAID (R, about_andro_3))
|
||||
ActivateStarShip (ORZ_SHIP, -1);
|
||||
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND / 2);
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ AllianceOffer (RESPONSE_REF R)
|
||||
if (PLAYER_SAID (R, misunderstanding))
|
||||
{
|
||||
NPCPhrase (JUST_MISUNDERSTANDING);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND / 4);
|
||||
|
||||
@@ -753,7 +753,7 @@ SpathiCouncil (RESPONSE_REF R)
|
||||
else if (PLAYER_SAID (R, good_password))
|
||||
{
|
||||
NPCPhrase (YES_GOOD_PASSWORD);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND / 4);
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ FriendlyExit (RESPONSE_REF R)
|
||||
|
||||
AlienTalkSegue (1);
|
||||
AlienTalkSegue (2);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), ONE_SECOND / 2);
|
||||
AlienTalkSegue ((COUNT)~0);
|
||||
@@ -279,7 +279,7 @@ Foreplay (RESPONSE_REF R)
|
||||
NPCPhrase (ABOUT_US);
|
||||
NPCPhrase (MORE_COMFORTABLE);
|
||||
AlienTalkSegue (1);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND);
|
||||
AlienTalkSegue ((COUNT)~0);
|
||||
|
||||
@@ -264,11 +264,11 @@ MindControlStrobe (void)
|
||||
|
||||
for (i = 0; i < NUM_STROBES; ++i)
|
||||
{
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), 0);
|
||||
SleepThread (ONE_SECOND / (STROBE_RATE * 2));
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), 0);
|
||||
SleepThread (ONE_SECOND / (STROBE_RATE * 2));
|
||||
|
||||
@@ -207,7 +207,7 @@ CombatIsInevitable (RESPONSE_REF R)
|
||||
NPCPhrase (FOOL_AIEE1);
|
||||
|
||||
AlienTalkSegue (1);
|
||||
XFormPLUT (GetColorMapAddress (
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), ONE_SECOND / 4);
|
||||
AlienTalkSegue ((COUNT)~0);
|
||||
|
||||
@@ -126,7 +126,5 @@ extern LOCDATAPTR init_zoqfot_comm (void);
|
||||
|
||||
extern LOCDATAPTR init_umgah_comm (void);
|
||||
|
||||
extern DWORD XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval);
|
||||
|
||||
#endif /* _COMMGLUE_H */
|
||||
|
||||
|
||||
@@ -30,37 +30,222 @@ static struct
|
||||
COUNT NumCycles;
|
||||
Task XFormTask;
|
||||
} tc;
|
||||
} TaskControl;
|
||||
} FadeControl;
|
||||
|
||||
typedef struct xform_control
|
||||
{
|
||||
int CMapIndex; // -1 means unused
|
||||
COLORMAPPTR CMapPtr;
|
||||
SIZE Ticks;
|
||||
DWORD StartTime;
|
||||
DWORD EndTime;
|
||||
TFB_Palette OldCMap[NUMBER_OF_PLUTVALS];
|
||||
} XFORM_CONTROL;
|
||||
|
||||
#define MAX_XFORMS 16
|
||||
static struct
|
||||
{
|
||||
XFORM_CONTROL TaskControl[MAX_XFORMS];
|
||||
volatile int Highest;
|
||||
// 'pending' is Highest >= 0
|
||||
Mutex Lock;
|
||||
} XFormControl;
|
||||
|
||||
volatile int FadeAmount = FADE_NORMAL_INTENSITY;
|
||||
static volatile int end, XForming;
|
||||
static volatile int FadeEnd, XForming;
|
||||
|
||||
UBYTE* _varPLUTs;
|
||||
static unsigned int varPLUTsize = 0;
|
||||
#define SPARE_COLORMAPS 20
|
||||
#define MAP_POOL_SIZE (MAX_COLORMAPS + SPARE_COLORMAPS)
|
||||
|
||||
static TFB_ColorMap mappool[MAP_POOL_SIZE];
|
||||
static TFB_ColorMap *poolhead;
|
||||
|
||||
static TFB_ColorMap * colormaps[MAX_COLORMAPS];
|
||||
static int mapcount;
|
||||
Mutex maplock;
|
||||
|
||||
|
||||
void TFB_ColorMapToRGB (TFB_Palette *pal, int colormap_index)
|
||||
void
|
||||
InitColorMaps (void)
|
||||
{
|
||||
int i;
|
||||
UBYTE *colors;
|
||||
|
||||
colors = GET_VAR_PLUT (colormap_index);
|
||||
// init colormaps
|
||||
maplock = CreateMutex ("Colormaps Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
// init static pool
|
||||
for (i = 0; i < MAP_POOL_SIZE - 1; ++i)
|
||||
mappool[i].next = mappool + i + 1;
|
||||
mappool[i].next = NULL;
|
||||
poolhead = mappool;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_PLUTVALS; i++)
|
||||
// init xform control
|
||||
XFormControl.Highest = -1;
|
||||
XFormControl.Lock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
for (i = 0; i < MAX_XFORMS; ++i)
|
||||
XFormControl.TaskControl[i].CMapIndex = -1;
|
||||
}
|
||||
|
||||
void
|
||||
UninitColorMaps (void)
|
||||
{
|
||||
// uninit xform control
|
||||
DestroyMutex (XFormControl.Lock);
|
||||
|
||||
// uninit colormaps
|
||||
DestroyMutex (maplock);
|
||||
}
|
||||
|
||||
static inline TFB_ColorMap *
|
||||
alloc_colormap (void)
|
||||
// returns an addrefed object
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
if (!poolhead)
|
||||
return NULL;
|
||||
|
||||
map = poolhead;
|
||||
poolhead = map->next;
|
||||
|
||||
map->next = NULL;
|
||||
map->index = -1;
|
||||
map->refcount = 1;
|
||||
map->version = 0;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static TFB_ColorMap *
|
||||
clone_colormap (TFB_ColorMap *from, int index)
|
||||
// returns an addrefed object
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
map = alloc_colormap ();
|
||||
if (!map)
|
||||
{
|
||||
pal[i].r = *colors++;
|
||||
pal[i].g = *colors++;
|
||||
pal[i].b = *colors++;
|
||||
static DWORD NextTime = 0;
|
||||
DWORD Now;
|
||||
|
||||
if (!from)
|
||||
{
|
||||
fprintf (stderr, "FATAL: clone_colormap(): no maps available\n");
|
||||
abort ();
|
||||
}
|
||||
|
||||
Now = GetTimeCounter ();
|
||||
if (Now >= NextTime)
|
||||
{
|
||||
fprintf (stderr, "clone_colormap(): static pool exhausted\n");
|
||||
NextTime = Now + ONE_SECOND;
|
||||
}
|
||||
|
||||
// just overwrite the current one -- better than aborting
|
||||
map = from;
|
||||
from->refcount++;
|
||||
}
|
||||
else
|
||||
{ // fresh new map
|
||||
map->index = index;
|
||||
if (from)
|
||||
map->version = from->version;
|
||||
}
|
||||
map->version++;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_colormap (TFB_ColorMap *map)
|
||||
{
|
||||
if (!map)
|
||||
{
|
||||
fprintf (stderr, "free_colormap(): tried to free a NULL map\n");
|
||||
return;
|
||||
}
|
||||
|
||||
map->next = poolhead;
|
||||
poolhead = map;
|
||||
}
|
||||
|
||||
static inline TFB_ColorMap *
|
||||
get_colormap (int index)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
map = colormaps[index];
|
||||
if (!map)
|
||||
{
|
||||
fprintf (stderr, "BUG: get_colormap(): map not present\n");
|
||||
abort ();
|
||||
}
|
||||
|
||||
map->refcount++;
|
||||
return map;
|
||||
}
|
||||
|
||||
static inline void
|
||||
release_colormap (TFB_ColorMap *map)
|
||||
{
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
if (map->refcount <= 0)
|
||||
{
|
||||
fprintf (stderr, "BUG: release_colormap(): refcount not >0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
map->refcount--;
|
||||
if (map->refcount == 0)
|
||||
free_colormap (map);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_ReturnColorMap (TFB_ColorMap *map)
|
||||
{
|
||||
LockMutex (maplock);
|
||||
release_colormap (map);
|
||||
UnlockMutex (maplock);
|
||||
}
|
||||
|
||||
TFB_ColorMap *
|
||||
TFB_GetColorMap (int index)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
LockMutex (maplock);
|
||||
map = get_colormap (index);
|
||||
UnlockMutex (maplock);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_ColorMapToRGB (TFB_Palette *pal, int index)
|
||||
{
|
||||
TFB_ColorMap *map = NULL;
|
||||
|
||||
if (index < mapcount)
|
||||
map = colormaps[index];
|
||||
|
||||
if (!map)
|
||||
{
|
||||
fprintf (stderr, "TFB_ColorMapToRGB(): "
|
||||
"requested non-present colormap %d\n", index);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (pal, map->colors, sizeof (map->colors));
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SetColorMap (COLORMAPPTR map)
|
||||
{
|
||||
int start, end;
|
||||
DWORD size, total_size;
|
||||
int total_size;
|
||||
UBYTE *colors = (UBYTE*)map;
|
||||
UBYTE *vp;
|
||||
TFB_ColorMap **mpp;
|
||||
|
||||
if (!map)
|
||||
return TRUE;
|
||||
@@ -68,46 +253,77 @@ SetColorMap (COLORMAPPTR map)
|
||||
start = *colors++;
|
||||
end = *colors++;
|
||||
if (start > end)
|
||||
return TRUE;
|
||||
|
||||
size = (end - start + 1) * PLUT_BYTE_SIZE;
|
||||
total_size = (end + 1) * PLUT_BYTE_SIZE;
|
||||
|
||||
if (!_varPLUTs)
|
||||
{
|
||||
_varPLUTs = (UBYTE *) HMalloc (total_size);
|
||||
varPLUTsize = total_size;
|
||||
fprintf (stderr, "ERROR: SetColorMap(): "
|
||||
"starting map (%d) not less or eq ending (%d)\n",
|
||||
start, end);
|
||||
return FALSE;
|
||||
}
|
||||
else if (total_size > varPLUTsize)
|
||||
if (start >= MAX_COLORMAPS)
|
||||
{
|
||||
_varPLUTs = (UBYTE *) HRealloc (_varPLUTs, total_size);
|
||||
varPLUTsize = total_size;
|
||||
fprintf (stderr, "ERROR: SetColorMap(): "
|
||||
"starting map (%d) beyond range (0-%d)\n",
|
||||
start, (int)MAX_COLORMAPS - 1);
|
||||
return FALSE;
|
||||
}
|
||||
if (!_varPLUTs)
|
||||
if (end >= MAX_COLORMAPS)
|
||||
{
|
||||
varPLUTsize = 0;
|
||||
return TRUE;
|
||||
fprintf (stderr, "SetColorMap(): "
|
||||
"ending map (%d) beyond range (0-%d)\n",
|
||||
end, (int)MAX_COLORMAPS - 1);
|
||||
end = MAX_COLORMAPS - 1;
|
||||
}
|
||||
|
||||
vp = GET_VAR_PLUT (start);
|
||||
memcpy (vp, colors, size);
|
||||
total_size = end + 1;
|
||||
|
||||
LockMutex (maplock);
|
||||
|
||||
if (total_size > mapcount)
|
||||
mapcount = total_size;
|
||||
|
||||
// parse the supplied PLUTs into our colormaps
|
||||
for (mpp = colormaps + start; start <= end; ++start, ++mpp)
|
||||
{
|
||||
int i;
|
||||
TFB_Palette *pal;
|
||||
TFB_ColorMap *newmap;
|
||||
TFB_ColorMap *oldmap;
|
||||
|
||||
oldmap = *mpp;
|
||||
newmap = clone_colormap (oldmap, start);
|
||||
|
||||
for (i = 0, pal = newmap->colors; i < NUMBER_OF_PLUTVALS; ++i, ++pal)
|
||||
{
|
||||
pal->r = *colors++;
|
||||
pal->g = *colors++;
|
||||
pal->b = *colors++;
|
||||
}
|
||||
|
||||
*mpp = newmap;
|
||||
release_colormap (oldmap);
|
||||
}
|
||||
|
||||
UnlockMutex (maplock);
|
||||
|
||||
//fprintf (stderr, "SetColorMap(): vp %x map %x bytes %d, start %d end %d\n", vp, map, bytes, start, end);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fade Transforms */
|
||||
|
||||
static int
|
||||
xform_clut_task (void *data)
|
||||
fade_xform_task (void *data)
|
||||
{
|
||||
SIZE TDelta, TTotal;
|
||||
DWORD CurTime;
|
||||
Task task = (Task)data;
|
||||
|
||||
XForming = TRUE;
|
||||
while (TaskControl.tc.XFormTask == 0 && (!Task_ReadState (task, TASK_EXIT)))
|
||||
while (FadeControl.tc.XFormTask == 0
|
||||
&& (!Task_ReadState (task, TASK_EXIT)))
|
||||
TaskSwitch ();
|
||||
TTotal = TaskControl.Ticks;
|
||||
TaskControl.tc.XFormTask = 0;
|
||||
TTotal = FadeControl.Ticks;
|
||||
FadeControl.tc.XFormTask = 0;
|
||||
|
||||
{
|
||||
CurTime = GetTimeCounter ();
|
||||
@@ -121,8 +337,8 @@ xform_clut_task (void *data)
|
||||
if (!XForming || (TDelta = (SIZE)(CurTime - StartTime)) > TTotal)
|
||||
TDelta = TTotal;
|
||||
|
||||
FadeAmount += (end - FadeAmount) * TDelta / TTotal;
|
||||
//fprintf (stderr, "xform_clut_task FadeAmount %d\n", FadeAmount);
|
||||
FadeAmount += (FadeEnd - FadeAmount) * TDelta / TTotal;
|
||||
//fprintf (stderr, "fade_xform_task FadeAmount %d\n", FadeAmount);
|
||||
} while ((TTotal -= TDelta) && (!Task_ReadState (task, TASK_EXIT)));
|
||||
}
|
||||
|
||||
@@ -132,58 +348,8 @@ xform_clut_task (void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
BYTE what;
|
||||
DWORD TimeOut;
|
||||
|
||||
FlushColorXForms ();
|
||||
|
||||
if (ColorMapPtr == (COLORMAPPTR)0)
|
||||
return (0);
|
||||
|
||||
what = *ColorMapPtr;
|
||||
switch (what)
|
||||
{
|
||||
case FadeAllToBlack:
|
||||
case FadeSomeToBlack:
|
||||
end = FADE_NO_INTENSITY;
|
||||
break;
|
||||
case FadeAllToColor:
|
||||
case FadeSomeToColor:
|
||||
end = FADE_NORMAL_INTENSITY;
|
||||
break;
|
||||
case FadeAllToWhite:
|
||||
case FadeSomeToWhite:
|
||||
end = FADE_FULL_INTENSITY;
|
||||
break;
|
||||
default:
|
||||
return (GetTimeCounter ());
|
||||
}
|
||||
|
||||
TaskControl.Ticks = TimeInterval;
|
||||
if (TaskControl.Ticks <= 0 ||
|
||||
(TaskControl.tc.XFormTask = AssignTask (xform_clut_task,
|
||||
1024, "transform colormap")) == 0)
|
||||
{
|
||||
FadeAmount = end;
|
||||
TimeOut = GetTimeCounter ();
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
TaskSwitch ();
|
||||
while (TaskControl.tc.XFormTask);
|
||||
|
||||
TimeOut = GetTimeCounter () + TimeInterval + 1;
|
||||
}
|
||||
|
||||
return (TimeOut);
|
||||
}
|
||||
|
||||
void
|
||||
FlushColorXForms()
|
||||
static void
|
||||
FlushFadeXForms (void)
|
||||
{
|
||||
if (XForming)
|
||||
{
|
||||
@@ -191,3 +357,266 @@ FlushColorXForms()
|
||||
TaskSwitch ();
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD
|
||||
XFormFade (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
BYTE what;
|
||||
DWORD TimeOut;
|
||||
|
||||
FlushFadeXForms ();
|
||||
|
||||
what = *ColorMapPtr;
|
||||
switch (what)
|
||||
{
|
||||
case FadeAllToBlack:
|
||||
case FadeSomeToBlack:
|
||||
FadeEnd = FADE_NO_INTENSITY;
|
||||
break;
|
||||
case FadeAllToColor:
|
||||
case FadeSomeToColor:
|
||||
FadeEnd = FADE_NORMAL_INTENSITY;
|
||||
break;
|
||||
case FadeAllToWhite:
|
||||
case FadeSomeToWhite:
|
||||
FadeEnd = FADE_FULL_INTENSITY;
|
||||
break;
|
||||
default:
|
||||
return (GetTimeCounter ());
|
||||
}
|
||||
|
||||
FadeControl.Ticks = TimeInterval;
|
||||
if (FadeControl.Ticks <= 0 ||
|
||||
(FadeControl.tc.XFormTask = AssignTask (fade_xform_task,
|
||||
1024, "fade transform")) == 0)
|
||||
{
|
||||
FadeAmount = FadeEnd;
|
||||
TimeOut = GetTimeCounter ();
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
TaskSwitch ();
|
||||
while (FadeControl.tc.XFormTask);
|
||||
|
||||
TimeOut = GetTimeCounter () + TimeInterval + 1;
|
||||
}
|
||||
|
||||
return (TimeOut);
|
||||
}
|
||||
|
||||
/* Colormap Transforms */
|
||||
|
||||
static void
|
||||
finish_colormap_xform (int which)
|
||||
{
|
||||
SetColorMap (XFormControl.TaskControl[which].CMapPtr);
|
||||
XFormControl.TaskControl[which].CMapIndex = -1;
|
||||
// check Highest ptr
|
||||
if (which == XFormControl.Highest)
|
||||
{
|
||||
do
|
||||
--which;
|
||||
while (which >= 0 && XFormControl.TaskControl[which].CMapIndex == -1);
|
||||
|
||||
XFormControl.Highest = which;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This gives the XFormColorMap task a timeslice to do its thing
|
||||
* Only one thread should ever be allowed to be calling this at any time
|
||||
*/
|
||||
BOOLEAN
|
||||
XFormColorMap_step ()
|
||||
{
|
||||
BOOLEAN Changed = FALSE;
|
||||
int x;
|
||||
DWORD Now = GetTimeCounter ();
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
for (x = 0; x <= XFormControl.Highest; ++x)
|
||||
{
|
||||
XFORM_CONTROL *control = &XFormControl.TaskControl[x];
|
||||
int index = control->CMapIndex;
|
||||
int TicksLeft = control->EndTime - Now;
|
||||
TFB_ColorMap *curmap;
|
||||
|
||||
if (index < 0)
|
||||
continue; // unused slot
|
||||
|
||||
LockMutex (maplock);
|
||||
|
||||
curmap = colormaps[index];
|
||||
if (!curmap)
|
||||
{
|
||||
UnlockMutex (maplock);
|
||||
fprintf (stderr, "BUG: XFormColorMap_step(): no current map\n");
|
||||
finish_colormap_xform (x);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TicksLeft > 0)
|
||||
{
|
||||
#define XFORM_SCALE 0x10000
|
||||
TFB_ColorMap *newmap = NULL;
|
||||
UBYTE *pNewCMap;
|
||||
TFB_Palette *pCurCMap, *pOldCMap;
|
||||
int frac;
|
||||
int i;
|
||||
|
||||
newmap = clone_colormap (curmap, index);
|
||||
|
||||
pCurCMap = newmap->colors;
|
||||
pOldCMap = control->OldCMap;
|
||||
pNewCMap = (UBYTE*)control->CMapPtr + 2;
|
||||
|
||||
frac = (int)(control->Ticks - TicksLeft) * XFORM_SCALE
|
||||
/ control->Ticks;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_PLUTVALS; i++, ++pCurCMap, ++pOldCMap)
|
||||
{
|
||||
|
||||
pCurCMap->r = (UBYTE)(pOldCMap->r + ((int)*pNewCMap - pOldCMap->r)
|
||||
* frac / XFORM_SCALE);
|
||||
pNewCMap++;
|
||||
|
||||
pCurCMap->g = (UBYTE)(pOldCMap->g + ((int)*pNewCMap - pOldCMap->g)
|
||||
* frac / XFORM_SCALE);
|
||||
pNewCMap++;
|
||||
|
||||
pCurCMap->b = (UBYTE)(pOldCMap->b + ((int)*pNewCMap - pOldCMap->b)
|
||||
* frac / XFORM_SCALE);
|
||||
pNewCMap++;
|
||||
}
|
||||
|
||||
colormaps[index] = newmap;
|
||||
release_colormap (curmap);
|
||||
}
|
||||
|
||||
UnlockMutex (maplock);
|
||||
|
||||
if (TicksLeft <= 0)
|
||||
{ // asked for immediate xform or already done
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
|
||||
Changed = TRUE;
|
||||
}
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushPLUTXForms (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
for (i = 0; i <= XFormControl.Highest; ++i)
|
||||
{
|
||||
if (XFormControl.TaskControl[i].CMapIndex >= 0)
|
||||
finish_colormap_xform (i);
|
||||
}
|
||||
XFormControl.Highest = -1; // all gone
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
}
|
||||
|
||||
static DWORD
|
||||
XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
XFORM_CONTROL *control;
|
||||
int index;
|
||||
int x;
|
||||
int first_avail = -1;
|
||||
DWORD EndTime;
|
||||
DWORD Now;
|
||||
|
||||
Now = GetTimeCounter ();
|
||||
index = *ColorMapPtr;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
// Find an available slot, or reuse if required
|
||||
for (x = 0; x <= XFormControl.Highest
|
||||
&& index != XFormControl.TaskControl[x].CMapIndex;
|
||||
++x)
|
||||
{
|
||||
if (first_avail == -1 && XFormControl.TaskControl[x].CMapIndex == -1)
|
||||
first_avail = x;
|
||||
}
|
||||
|
||||
if (index == XFormControl.TaskControl[x].CMapIndex)
|
||||
{ // already xforming this colormap -- cancel and reuse slot
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
else if (first_avail >= 0)
|
||||
{ // picked up a slot along the way
|
||||
x = first_avail;
|
||||
}
|
||||
else if (x >= MAX_XFORMS)
|
||||
{ // flush some xforms if the queue is full
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "WARNING: XFormPLUT(): no slots available\n");
|
||||
#endif
|
||||
x = XFormControl.Highest;
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
// take next unused one
|
||||
control = &XFormControl.TaskControl[x];
|
||||
if (x > XFormControl.Highest)
|
||||
XFormControl.Highest = x;
|
||||
|
||||
// make a copy of the current map
|
||||
LockMutex (maplock);
|
||||
map = colormaps[index];
|
||||
if (!map)
|
||||
{
|
||||
UnlockMutex (maplock);
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
fprintf (stderr, "BUG: XFormPLUT(): no current map\n");
|
||||
return (0);
|
||||
}
|
||||
memcpy (control->OldCMap, map->colors, sizeof (map->colors));
|
||||
UnlockMutex (maplock);
|
||||
|
||||
control->CMapIndex = index;
|
||||
control->CMapPtr = ColorMapPtr;
|
||||
control->Ticks = TimeInterval;
|
||||
if (control->Ticks < 0)
|
||||
control->Ticks = 0; /* prevent negative fade */
|
||||
control->StartTime = Now;
|
||||
control->EndTime = EndTime = Now + control->Ticks;
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return (EndTime);
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
int what;
|
||||
|
||||
if (!ColorMapPtr)
|
||||
return (0);
|
||||
|
||||
what = *ColorMapPtr;
|
||||
if (what >= (int)FadeAllToWhite && what <= (int)FadeSomeToColor)
|
||||
return XFormFade (ColorMapPtr, TimeInterval);
|
||||
else
|
||||
return XFormPLUT (ColorMapPtr, TimeInterval);
|
||||
}
|
||||
|
||||
void
|
||||
FlushColorXForms (void)
|
||||
{
|
||||
FlushFadeXForms ();
|
||||
FlushPLUTXForms ();
|
||||
}
|
||||
|
||||
@@ -21,12 +21,10 @@
|
||||
#ifndef CMAP_H
|
||||
#define CMAP_H
|
||||
|
||||
#define NUMBER_OF_VARPLUTS 256
|
||||
#define MAX_COLORMAPS 250
|
||||
#define PLUTVAL_BYTE_SIZE 3
|
||||
#define NUMBER_OF_PLUTVALS 256
|
||||
#define PLUT_BYTE_SIZE (PLUTVAL_BYTE_SIZE * NUMBER_OF_PLUTVALS)
|
||||
#define VARPLUTS_SIZE (NUMBER_OF_VARPLUTS * PLUT_BYTE_SIZE)
|
||||
#define GET_VAR_PLUT(i) (_varPLUTs + (i) * PLUT_BYTE_SIZE)
|
||||
|
||||
#define BUILD_FRAME (1 << 0)
|
||||
#define FIND_PAGE (1 << 1)
|
||||
@@ -40,9 +38,25 @@
|
||||
#define FADE_NORMAL_INTENSITY 255
|
||||
#define FADE_FULL_INTENSITY 510
|
||||
|
||||
extern UBYTE* _varPLUTs;
|
||||
typedef struct tfb_colormap
|
||||
{
|
||||
TFB_Palette colors[NUMBER_OF_PLUTVALS];
|
||||
int index;
|
||||
int version;
|
||||
int refcount;
|
||||
struct tfb_colormap *next;
|
||||
} TFB_ColorMap;
|
||||
|
||||
extern volatile int FadeAmount;
|
||||
|
||||
void TFB_ColorMapToRGB (TFB_Palette *pal, int colormap_index);
|
||||
extern void InitColorMaps (void);
|
||||
extern void UninitColorMaps (void);
|
||||
|
||||
extern void TFB_ColorMapToRGB (TFB_Palette *pal, int colormap_index);
|
||||
extern TFB_ColorMap * TFB_GetColorMap (int index);
|
||||
extern void TFB_ReturnColorMap (TFB_ColorMap *map);
|
||||
|
||||
extern BOOLEAN XFormColorMap_step ();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@ typedef struct tfb_dc_img
|
||||
TFB_Image *image;
|
||||
int x, y;
|
||||
SCREEN destBuffer;
|
||||
BOOLEAN UsePalette;
|
||||
TFB_ColorMap *colormap;
|
||||
int scale;
|
||||
} TFB_DrawCommand_Image;
|
||||
|
||||
|
||||
@@ -61,10 +61,12 @@ TFB_DrawCanvas_Rect (PRECT rect, int r, int g, int b, TFB_Canvas target)
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *palette, TFB_Canvas target)
|
||||
TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale,
|
||||
TFB_ColorMap *cmap, TFB_Canvas target)
|
||||
{
|
||||
SDL_Rect srcRect, targetRect, *pSrcRect;
|
||||
SDL_Surface *surf;
|
||||
TFB_Palette* palette;
|
||||
|
||||
if (img == 0)
|
||||
{
|
||||
@@ -74,18 +76,25 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
|
||||
|
||||
LockMutex (img->mutex);
|
||||
|
||||
if (palette == 0)
|
||||
if (cmap)
|
||||
palette = cmap->colors;
|
||||
else
|
||||
palette = img->Palette;
|
||||
|
||||
// only set the new palette if it changed
|
||||
if (((SDL_Surface *)img->NormalImg)->format->palette
|
||||
&& cmap && img->colormap_version != cmap->version)
|
||||
SDL_SetColors (img->NormalImg, (SDL_Color*)palette, 0, 256);
|
||||
|
||||
if (scale != 0 && scale != GSCALE_IDENTITY)
|
||||
{
|
||||
int type;
|
||||
if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg)
|
||||
{
|
||||
type = TFB_SCALE_TRILINEAR;
|
||||
if (((SDL_Surface *)img->NormalImg)->format->palette)
|
||||
SDL_SetColors (img->NormalImg, (SDL_Color*)palette, 0, 256);
|
||||
if (((SDL_Surface *)img->MipmapImg)->format->palette)
|
||||
// only set the new palette if it changed
|
||||
if (((SDL_Surface *)img->MipmapImg)->format->palette
|
||||
&& cmap && img->colormap_version != cmap->version)
|
||||
SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256);
|
||||
}
|
||||
else
|
||||
@@ -95,6 +104,9 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
|
||||
|
||||
TFB_DrawImage_FixScaling (img, scale, type);
|
||||
surf = img->ScaledImg;
|
||||
if (surf->format->palette)
|
||||
SDL_SetColors (surf, (SDL_Color*)palette, 0, 256);
|
||||
|
||||
srcRect.x = 0;
|
||||
srcRect.y = 0;
|
||||
srcRect.w = img->extent.width;
|
||||
@@ -113,8 +125,11 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
|
||||
targetRect.y = y - img->NormalHs.y;
|
||||
}
|
||||
|
||||
if (surf->format->palette)
|
||||
SDL_SetColors (surf, (SDL_Color*)palette, 0, 256);
|
||||
if (cmap)
|
||||
{
|
||||
img->colormap_version = cmap->version;
|
||||
TFB_ReturnColorMap (cmap);
|
||||
}
|
||||
|
||||
SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect);
|
||||
UnlockMutex (img->mutex);
|
||||
@@ -254,6 +269,8 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
|
||||
pal[i].b = b;
|
||||
}
|
||||
SDL_SetColors (surf, pal, 0, 256);
|
||||
// reflect the change in *actual* image palette
|
||||
img->colormap_version--;
|
||||
}
|
||||
else
|
||||
{ // fill the non-transparent parts of the image with fillcolor
|
||||
|
||||
@@ -152,7 +152,6 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
|
||||
|
||||
Init_DrawCommandQueue ();
|
||||
|
||||
TFB_FlushPaletteCache ();
|
||||
TFB_DrawCanvas_Initialize ();
|
||||
|
||||
RenderingCond = CreateCondVar ("DCQ empty",
|
||||
@@ -614,17 +613,12 @@ TFB_FlushGraphics () // Only call from main thread!!
|
||||
case TFB_DRAWCOMMANDTYPE_IMAGE:
|
||||
{
|
||||
TFB_Image *DC_image = DC.data.image.image;
|
||||
TFB_Palette *pal;
|
||||
TFB_ColorMap *cmap = DC.data.image.colormap;
|
||||
int x = DC.data.image.x;
|
||||
int y = DC.data.image.y;
|
||||
|
||||
if (DC.data.image.UsePalette)
|
||||
pal = palette;
|
||||
else
|
||||
pal = 0;
|
||||
|
||||
TFB_DrawCanvas_Image (DC_image, x, y,
|
||||
DC.data.image.scale, pal,
|
||||
DC.data.image.scale, cmap,
|
||||
SDL_Screens[DC.data.image.destBuffer]);
|
||||
|
||||
if (DC.data.image.destBuffer == 0)
|
||||
|
||||
@@ -78,67 +78,21 @@ TFB_DrawScreen_SetPalette (int paletteIndex, int r, int g, int b)
|
||||
TFB_EnqueueDrawCommand (&DC);
|
||||
}
|
||||
|
||||
/* This value is protected by the DCQ's lock. */
|
||||
static int _localpal[256][3];
|
||||
|
||||
void
|
||||
TFB_FlushPaletteCache ()
|
||||
{
|
||||
int i;
|
||||
Lock_DCQ (-1);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
_localpal[i][0] = -1;
|
||||
_localpal[i][1] = -1;
|
||||
_localpal[i][2] = -1;
|
||||
}
|
||||
Unlock_DCQ ();
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale,
|
||||
TFB_Palette *palette, SCREEN dest)
|
||||
TFB_ColorMap *cmap, SCREEN dest)
|
||||
{
|
||||
TFB_DrawCommand DC;
|
||||
|
||||
DC.Type = TFB_DRAWCOMMANDTYPE_IMAGE;
|
||||
DC.data.image.image = img;
|
||||
DC.data.image.colormap = cmap;
|
||||
DC.data.image.x = x;
|
||||
DC.data.image.y = y;
|
||||
DC.data.image.scale = (scale == GSCALE_IDENTITY) ? 0 : scale;
|
||||
|
||||
if (palette != NULL)
|
||||
{
|
||||
int i, changed;
|
||||
Lock_DCQ(257);
|
||||
changed = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if ((_localpal[i][0] != palette[i].r) ||
|
||||
(_localpal[i][1] != palette[i].g) ||
|
||||
(_localpal[i][2] != palette[i].b))
|
||||
{
|
||||
changed++;
|
||||
_localpal[i][0] = palette[i].r;
|
||||
_localpal[i][1] = palette[i].g;
|
||||
_localpal[i][2] = palette[i].b;
|
||||
TFB_DrawScreen_SetPalette (i, palette[i].r, palette[i].g,
|
||||
palette[i].b);
|
||||
}
|
||||
}
|
||||
// if (changed) { fprintf (stderr, "Actually changing palette! "); }
|
||||
DC.data.image.UsePalette = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Lock_DCQ (1);
|
||||
DC.data.image.UsePalette = FALSE;
|
||||
}
|
||||
|
||||
DC.data.image.destBuffer = dest;
|
||||
|
||||
TFB_EnqueueDrawCommand (&DC);
|
||||
Unlock_DCQ ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -296,10 +250,10 @@ TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image)
|
||||
|
||||
void
|
||||
TFB_DrawImage_Image (TFB_Image *img, int x, int y, int scale,
|
||||
TFB_Palette *palette, TFB_Image *target)
|
||||
TFB_ColorMap *cmap, TFB_Image *target)
|
||||
{
|
||||
LockMutex (target->mutex);
|
||||
TFB_DrawCanvas_Image (img, x, y, scale, palette, target->NormalImg);
|
||||
TFB_DrawCanvas_Image (img, x, y, scale, cmap, target->NormalImg);
|
||||
target->dirty = TRUE;
|
||||
UnlockMutex (target->mutex);
|
||||
}
|
||||
@@ -334,6 +288,7 @@ TFB_DrawImage_New (TFB_Canvas canvas)
|
||||
img->MipmapImg = NULL;
|
||||
img->FilledImg = NULL;
|
||||
img->colormap_index = -1;
|
||||
img->colormap_version = 0;
|
||||
img->NormalHs = NullHs;
|
||||
img->MipmapHs = NullHs;
|
||||
img->last_scale_hs = NullHs;
|
||||
@@ -363,6 +318,7 @@ TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha)
|
||||
img->MipmapImg = NULL;
|
||||
img->FilledImg = NULL;
|
||||
img->colormap_index = -1;
|
||||
img->colormap_version = 0;
|
||||
img->NormalHs = NullHs;
|
||||
img->MipmapHs = NullHs;
|
||||
img->last_scale_hs = NullHs;
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef struct tfb_palette
|
||||
} TFB_Palette;
|
||||
|
||||
#include "graphics/gfx_common.h"
|
||||
#include "cmap.h"
|
||||
|
||||
typedef struct tfb_image
|
||||
{
|
||||
@@ -56,6 +57,7 @@ typedef struct tfb_image
|
||||
TFB_Canvas FilledImg;
|
||||
TFB_Palette *Palette;
|
||||
int colormap_index;
|
||||
int colormap_version;
|
||||
HOT_SPOT NormalHs;
|
||||
HOT_SPOT MipmapHs;
|
||||
HOT_SPOT last_scale_hs;
|
||||
@@ -92,7 +94,7 @@ typedef struct tfb_pixelformat
|
||||
|
||||
void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2, int r, int g, int b, SCREEN dest);
|
||||
void TFB_DrawScreen_Rect (PRECT rect, int r, int g, int b, SCREEN dest);
|
||||
void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *palette, SCREEN dest);
|
||||
void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, SCREEN dest);
|
||||
void TFB_DrawScreen_Copy (PRECT r, SCREEN src, SCREEN dest);
|
||||
void TFB_DrawScreen_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, SCREEN dest);
|
||||
void TFB_DrawScreen_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, SCREEN dest);
|
||||
@@ -103,7 +105,6 @@ void TFB_DrawScreen_DeleteData (void *);
|
||||
void TFB_DrawScreen_WaitForSignal (void);
|
||||
void TFB_DrawScreen_ReinitVideo (int driver, int flags, int width, int height, int bpp);
|
||||
void TFB_DrawScreen_SetPalette (int paletteIndex, int r, int g, int b);
|
||||
void TFB_FlushPaletteCache (void);
|
||||
|
||||
TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas);
|
||||
TFB_Image *TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha);
|
||||
@@ -113,7 +114,7 @@ void TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type);
|
||||
|
||||
void TFB_DrawImage_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Image *dest);
|
||||
void TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image);
|
||||
void TFB_DrawImage_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *palette, TFB_Image *target);
|
||||
void TFB_DrawImage_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, TFB_Image *target);
|
||||
void TFB_DrawImage_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Image *target);
|
||||
void TFB_DrawImage_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, TFB_Image *target);
|
||||
|
||||
@@ -137,7 +138,7 @@ void TFB_DrawCanvas_Delete (TFB_Canvas canvas);
|
||||
|
||||
void TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Canvas dest);
|
||||
void TFB_DrawCanvas_Rect (PRECT rect, int r, int g, int b, TFB_Canvas image);
|
||||
void TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *palette, TFB_Canvas target);
|
||||
void TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, TFB_Canvas target);
|
||||
void TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Canvas target);
|
||||
void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, TFB_Canvas target);
|
||||
|
||||
|
||||
@@ -119,8 +119,7 @@ TFB_Prim_Stamp (PSTAMP stmp)
|
||||
int x, y;
|
||||
PFRAME_DESC SrcFramePtr;
|
||||
TFB_Image *img;
|
||||
BOOLEAN paletted;
|
||||
TFB_Palette palette[256];
|
||||
TFB_ColorMap *cmap = NULL;
|
||||
int gscale;
|
||||
|
||||
SrcFramePtr = (PFRAME_DESC)stmp->frame;
|
||||
@@ -143,25 +142,22 @@ TFB_Prim_Stamp (PSTAMP stmp)
|
||||
img->NormalHs = SrcFramePtr->HotSpot;
|
||||
x = stmp->origin.x - _CurFramePtr->HotSpot.x;
|
||||
y = stmp->origin.y - _CurFramePtr->HotSpot.y;
|
||||
paletted = FALSE;
|
||||
|
||||
if (TFB_DrawCanvas_IsPaletted(img->NormalImg) && img->colormap_index != -1)
|
||||
{
|
||||
TFB_ColorMapToRGB (palette, img->colormap_index);
|
||||
paletted = TRUE;
|
||||
// returned cmap is addrefed, must release later
|
||||
cmap = TFB_GetColorMap (img->colormap_index);
|
||||
}
|
||||
|
||||
UnlockMutex (img->mutex);
|
||||
|
||||
if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
|
||||
{
|
||||
TFB_DrawScreen_Image (img, x, y, gscale, (paletted ? palette : NULL),
|
||||
TFB_SCREEN_MAIN);
|
||||
TFB_DrawScreen_Image (img, x, y, gscale, cmap, TFB_SCREEN_MAIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
TFB_DrawImage_Image (img, x, y, gscale, (paletted ? palette : NULL),
|
||||
_CurFramePtr->image);
|
||||
TFB_DrawImage_Image (img, x, y, gscale, cmap, _CurFramePtr->image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user