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:
avolkov
2005-12-13 07:30:37 +00:00
parent 0daed2aa5b
commit 868199e570
17 changed files with 607 additions and 364 deletions
+8 -170
View File
@@ -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 ();
+1 -1
View File
@@ -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);
+7 -7
View File
@@ -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);
+1 -1
View File
@@ -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);
}
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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));
+1 -1
View File
@@ -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);
-2
View File
@@ -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 */
+521 -92
View File
@@ -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;
{
fprintf (stderr, "ERROR: SetColorMap(): "
"starting map (%d) not less or eq ending (%d)\n",
start, end);
return FALSE;
}
if (start >= MAX_COLORMAPS)
{
fprintf (stderr, "ERROR: SetColorMap(): "
"starting map (%d) beyond range (0-%d)\n",
start, (int)MAX_COLORMAPS - 1);
return FALSE;
}
if (end >= MAX_COLORMAPS)
{
fprintf (stderr, "SetColorMap(): "
"ending map (%d) beyond range (0-%d)\n",
end, (int)MAX_COLORMAPS - 1);
end = MAX_COLORMAPS - 1;
}
if (!_varPLUTs)
{
_varPLUTs = (UBYTE *) HMalloc (total_size);
varPLUTsize = total_size;
}
else if (total_size > varPLUTsize)
{
_varPLUTs = (UBYTE *) HRealloc (_varPLUTs, total_size);
varPLUTsize = total_size;
}
if (!_varPLUTs)
{
varPLUTsize = 0;
return TRUE;
}
total_size = end + 1;
LockMutex (maplock);
if (total_size > mapcount)
mapcount = total_size;
vp = GET_VAR_PLUT (start);
memcpy (vp, colors, 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 ();
}
+19 -5
View File
@@ -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
+1 -1
View File
@@ -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;
+24 -7
View File
@@ -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)
+6 -50
View File
@@ -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;
+5 -4
View File
@@ -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);
+5 -9
View File
@@ -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);
}
}