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? // XXX: was 32 picked experimentally?
#define OSCILLOSCOPE_RATE 32 #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 int ambient_anim_task (void *data);
static BOOLEAN getLineWithinWidth(TEXT *pText, static BOOLEAN getLineWithinWidth(TEXT *pText,
@@ -509,177 +504,21 @@ DrawAlienFrame (FRAME aframe, PSEQUENCE pSeq)
UnbatchGraphics (); 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 void
init_communication (void) init_communication (void)
{ {
subtitle_mutex = CreateMutex ("Subtitle Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); subtitle_mutex = CreateMutex ("Subtitle Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
init_xform_control ();
} }
void void
uninit_communication (void) uninit_communication (void)
{ {
DestroyMutex (subtitle_mutex); DestroyMutex (subtitle_mutex);
uninit_xform_control ();
} }
static volatile BOOLEAN ColorChange;
static volatile BOOLEAN SummaryChange; static volatile BOOLEAN SummaryChange;
static volatile BOOLEAN ClearSubtitle; 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 static void
RefreshResponses (PENCOUNTER_STATE pES) RefreshResponses (PENCOUNTER_STATE pES)
{ {
@@ -867,6 +706,7 @@ ambient_anim_task (void *data)
BOOLEAN TransitionDone = FALSE; BOOLEAN TransitionDone = FALSE;
BOOLEAN TalkFrameChanged = FALSE; BOOLEAN TalkFrameChanged = FALSE;
BOOLEAN FrameChanged[MAX_ANIMATIONS]; BOOLEAN FrameChanged[MAX_ANIMATIONS];
BOOLEAN ColorChange = FALSE;
while ((CommFrame = CommData.AlienFrame) == 0 && !Task_ReadState (task, TASK_EXIT)) while ((CommFrame = CommData.AlienFrame) == 0 && !Task_ReadState (task, TASK_EXIT))
TaskSwitch (); TaskSwitch ();
@@ -963,7 +803,7 @@ ambient_anim_task (void *data)
if (pSeq->AnimType == COLOR_ANIM) if (pSeq->AnimType == COLOR_ANIM)
{ {
XFormPLUT ( XFormColorMap (
GetColorMapAddress (pSeq->AnimObj.CurCMap), GetColorMapAddress (pSeq->AnimObj.CurCMap),
(COUNT) (pSeq->Alarm - 1) (COUNT) (pSeq->Alarm - 1)
); );
@@ -1208,7 +1048,7 @@ ambient_anim_task (void *data)
if (!summary) if (!summary)
{ {
CONTEXT OldContext; CONTEXT OldContext;
BOOLEAN CheckSub = 0; BOOLEAN CheckSub = FALSE;
BOOLEAN ClearSub; BOOLEAN ClearSub;
int sub_state; int sub_state;
@@ -1228,8 +1068,8 @@ ambient_anim_task (void *data)
CommData.AlienFrame = CommFrame; CommData.AlienFrame = CommFrame;
DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]); DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]);
CommData.AlienFrame = F; CommData.AlienFrame = F;
CheckSub = 1; CheckSub = TRUE;
ClearSub = SummaryChange ? TRUE : FALSE; ClearSub = SummaryChange;
ColorChange = SummaryChange = FALSE; ColorChange = SummaryChange = FALSE;
} }
if (Change || ClearSub) if (Change || ClearSub)
@@ -1270,7 +1110,7 @@ ambient_anim_task (void *data)
TalkFrameChanged = FALSE; TalkFrameChanged = FALSE;
} }
Change = FALSE; Change = FALSE;
CheckSub = 1; CheckSub = TRUE;
} }
if (optSubtitles && CheckSub && sub_state >= SPACE_SUBTITLE) if (optSubtitles && CheckSub && sub_state >= SPACE_SUBTITLE)
@@ -1290,7 +1130,7 @@ ambient_anim_task (void *data)
} }
UnbatchGraphics (); UnbatchGraphics ();
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
xform_PLUT_step(ElapsedTicks); ColorChange = XFormColorMap_step ();
} }
FinishTask (task); FinishTask (task);
return(0); return(0);
@@ -1914,11 +1754,9 @@ DoCommunication (PENCOUNTER_STATE pES)
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
FlushPLUTXForms (); FlushColorXForms ();
ColorChange = FALSE;
ClearSubtitle = FALSE; ClearSubtitle = FALSE;
FlushColorXForms ();
StopMusic (); StopMusic ();
StopSound (); StopSound ();
StopTrack (); StopTrack ();
+1 -1
View File
@@ -588,7 +588,7 @@ GiveRadios (RESPONSE_REF R)
CommData.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED; CommData.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED;
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 0) SetAbsColorMapIndex (CommData.AlienColorMap, 0)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
+7 -7
View File
@@ -1342,7 +1342,7 @@ NatureOfConversation (RESPONSE_REF R)
/* Melnorme reports any news and turns purple */ /* Melnorme reports any news and turns purple */
NPCPhrase (BUY_OR_SELL); NPCPhrase (BUY_OR_SELL);
AlienTalkSegue(1); AlienTalkSegue(1);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
AlienTalkSegue((COUNT)~0); AlienTalkSegue((COUNT)~0);
@@ -1432,7 +1432,7 @@ DoBluster (RESPONSE_REF R)
if (PLAYER_SAID (R, trade_is_for_the_weak)) if (PLAYER_SAID (R, trade_is_for_the_weak))
{ {
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 2) SetAbsColorMapIndex (CommData.AlienColorMap, 2)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
@@ -1629,7 +1629,7 @@ DoFirstMeeting (RESPONSE_REF R)
} }
else if (PLAYER_SAID (R, yes_really_testing)) else if (PLAYER_SAID (R, yes_really_testing))
{ {
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 0) SetAbsColorMapIndex (CommData.AlienColorMap, 0)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
@@ -1638,7 +1638,7 @@ DoFirstMeeting (RESPONSE_REF R)
else if (PLAYER_SAID (R, we_apologize)) else if (PLAYER_SAID (R, we_apologize))
{ {
SET_GAME_STATE (MELNORME_ANGER, 0); SET_GAME_STATE (MELNORME_ANGER, 0);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 0) SetAbsColorMapIndex (CommData.AlienColorMap, 0)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
@@ -1677,7 +1677,7 @@ DoMelnormeMiffed (RESPONSE_REF R)
} }
SET_GAME_STATE (MELNORME_MIFFED_COUNT, miffed_count); SET_GAME_STATE (MELNORME_MIFFED_COUNT, miffed_count);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 2) SetAbsColorMapIndex (CommData.AlienColorMap, 2)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
} }
@@ -1749,7 +1749,7 @@ DoMelnormePissed (RESPONSE_REF R)
} }
SET_GAME_STATE (MELNORME_PISSED_COUNT, pissed_count); SET_GAME_STATE (MELNORME_PISSED_COUNT, pissed_count);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 2) SetAbsColorMapIndex (CommData.AlienColorMap, 2)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
} }
@@ -1804,7 +1804,7 @@ DoMelnormeHate (RESPONSE_REF R)
} }
SET_GAME_STATE (MELNORME_HATE_COUNT, hate_count); SET_GAME_STATE (MELNORME_HATE_COUNT, hate_count);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 2) SetAbsColorMapIndex (CommData.AlienColorMap, 2)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
+1 -1
View File
@@ -228,7 +228,7 @@ ExitConversation (RESPONSE_REF R)
if (PLAYER_SAID (R, about_andro_3)) if (PLAYER_SAID (R, about_andro_3))
ActivateStarShip (ORZ_SHIP, -1); ActivateStarShip (ORZ_SHIP, -1);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
} }
+2 -2
View File
@@ -575,7 +575,7 @@ AllianceOffer (RESPONSE_REF R)
if (PLAYER_SAID (R, misunderstanding)) if (PLAYER_SAID (R, misunderstanding))
{ {
NPCPhrase (JUST_MISUNDERSTANDING); NPCPhrase (JUST_MISUNDERSTANDING);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND / 4); ), ONE_SECOND / 4);
@@ -753,7 +753,7 @@ SpathiCouncil (RESPONSE_REF R)
else if (PLAYER_SAID (R, good_password)) else if (PLAYER_SAID (R, good_password))
{ {
NPCPhrase (YES_GOOD_PASSWORD); NPCPhrase (YES_GOOD_PASSWORD);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND / 4); ), ONE_SECOND / 4);
+2 -2
View File
@@ -214,7 +214,7 @@ FriendlyExit (RESPONSE_REF R)
AlienTalkSegue (1); AlienTalkSegue (1);
AlienTalkSegue (2); AlienTalkSegue (2);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 0) SetAbsColorMapIndex (CommData.AlienColorMap, 0)
), ONE_SECOND / 2); ), ONE_SECOND / 2);
AlienTalkSegue ((COUNT)~0); AlienTalkSegue ((COUNT)~0);
@@ -279,7 +279,7 @@ Foreplay (RESPONSE_REF R)
NPCPhrase (ABOUT_US); NPCPhrase (ABOUT_US);
NPCPhrase (MORE_COMFORTABLE); NPCPhrase (MORE_COMFORTABLE);
AlienTalkSegue (1); AlienTalkSegue (1);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND); ), ONE_SECOND);
AlienTalkSegue ((COUNT)~0); AlienTalkSegue ((COUNT)~0);
+2 -2
View File
@@ -264,11 +264,11 @@ MindControlStrobe (void)
for (i = 0; i < NUM_STROBES; ++i) for (i = 0; i < NUM_STROBES; ++i)
{ {
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), 0); ), 0);
SleepThread (ONE_SECOND / (STROBE_RATE * 2)); SleepThread (ONE_SECOND / (STROBE_RATE * 2));
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 0) SetAbsColorMapIndex (CommData.AlienColorMap, 0)
), 0); ), 0);
SleepThread (ONE_SECOND / (STROBE_RATE * 2)); SleepThread (ONE_SECOND / (STROBE_RATE * 2));
+1 -1
View File
@@ -207,7 +207,7 @@ CombatIsInevitable (RESPONSE_REF R)
NPCPhrase (FOOL_AIEE1); NPCPhrase (FOOL_AIEE1);
AlienTalkSegue (1); AlienTalkSegue (1);
XFormPLUT (GetColorMapAddress ( XFormColorMap (GetColorMapAddress (
SetAbsColorMapIndex (CommData.AlienColorMap, 1) SetAbsColorMapIndex (CommData.AlienColorMap, 1)
), ONE_SECOND / 4); ), ONE_SECOND / 4);
AlienTalkSegue ((COUNT)~0); AlienTalkSegue ((COUNT)~0);
-2
View File
@@ -126,7 +126,5 @@ extern LOCDATAPTR init_zoqfot_comm (void);
extern LOCDATAPTR init_umgah_comm (void); extern LOCDATAPTR init_umgah_comm (void);
extern DWORD XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval);
#endif /* _COMMGLUE_H */ #endif /* _COMMGLUE_H */
+517 -88
View File
@@ -30,37 +30,222 @@ static struct
COUNT NumCycles; COUNT NumCycles;
Task XFormTask; Task XFormTask;
} tc; } 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; volatile int FadeAmount = FADE_NORMAL_INTENSITY;
static volatile int end, XForming; static volatile int FadeEnd, XForming;
UBYTE* _varPLUTs; #define SPARE_COLORMAPS 20
static unsigned int varPLUTsize = 0; #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; 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;
pal[i].r = *colors++; XFormControl.Lock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
pal[i].g = *colors++; for (i = 0; i < MAX_XFORMS; ++i)
pal[i].b = *colors++; 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)
{
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 BOOLEAN
SetColorMap (COLORMAPPTR map) SetColorMap (COLORMAPPTR map)
{ {
int start, end; int start, end;
DWORD size, total_size; int total_size;
UBYTE *colors = (UBYTE*)map; UBYTE *colors = (UBYTE*)map;
UBYTE *vp; TFB_ColorMap **mpp;
if (!map) if (!map)
return TRUE; return TRUE;
@@ -68,46 +253,77 @@ SetColorMap (COLORMAPPTR map)
start = *colors++; start = *colors++;
end = *colors++; end = *colors++;
if (start > end) 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); fprintf (stderr, "ERROR: SetColorMap(): "
varPLUTsize = total_size; "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); fprintf (stderr, "ERROR: SetColorMap(): "
varPLUTsize = total_size; "starting map (%d) beyond range (0-%d)\n",
start, (int)MAX_COLORMAPS - 1);
return FALSE;
} }
if (!_varPLUTs) if (end >= MAX_COLORMAPS)
{ {
varPLUTsize = 0; fprintf (stderr, "SetColorMap(): "
return TRUE; "ending map (%d) beyond range (0-%d)\n",
end, (int)MAX_COLORMAPS - 1);
end = MAX_COLORMAPS - 1;
} }
vp = GET_VAR_PLUT (start); total_size = end + 1;
memcpy (vp, colors, size);
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); //fprintf (stderr, "SetColorMap(): vp %x map %x bytes %d, start %d end %d\n", vp, map, bytes, start, end);
return TRUE; return TRUE;
} }
/* Fade Transforms */
static int static int
xform_clut_task (void *data) fade_xform_task (void *data)
{ {
SIZE TDelta, TTotal; SIZE TDelta, TTotal;
DWORD CurTime; DWORD CurTime;
Task task = (Task)data; Task task = (Task)data;
XForming = TRUE; XForming = TRUE;
while (TaskControl.tc.XFormTask == 0 && (!Task_ReadState (task, TASK_EXIT))) while (FadeControl.tc.XFormTask == 0
&& (!Task_ReadState (task, TASK_EXIT)))
TaskSwitch (); TaskSwitch ();
TTotal = TaskControl.Ticks; TTotal = FadeControl.Ticks;
TaskControl.tc.XFormTask = 0; FadeControl.tc.XFormTask = 0;
{ {
CurTime = GetTimeCounter (); CurTime = GetTimeCounter ();
@@ -121,8 +337,8 @@ xform_clut_task (void *data)
if (!XForming || (TDelta = (SIZE)(CurTime - StartTime)) > TTotal) if (!XForming || (TDelta = (SIZE)(CurTime - StartTime)) > TTotal)
TDelta = TTotal; TDelta = TTotal;
FadeAmount += (end - FadeAmount) * TDelta / TTotal; FadeAmount += (FadeEnd - FadeAmount) * TDelta / TTotal;
//fprintf (stderr, "xform_clut_task FadeAmount %d\n", FadeAmount); //fprintf (stderr, "fade_xform_task FadeAmount %d\n", FadeAmount);
} while ((TTotal -= TDelta) && (!Task_ReadState (task, TASK_EXIT))); } while ((TTotal -= TDelta) && (!Task_ReadState (task, TASK_EXIT)));
} }
@@ -132,58 +348,8 @@ xform_clut_task (void *data)
return 0; return 0;
} }
DWORD static void
XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) FlushFadeXForms (void)
{
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()
{ {
if (XForming) if (XForming)
{ {
@@ -191,3 +357,266 @@ FlushColorXForms()
TaskSwitch (); 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 #ifndef CMAP_H
#define CMAP_H #define CMAP_H
#define NUMBER_OF_VARPLUTS 256 #define MAX_COLORMAPS 250
#define PLUTVAL_BYTE_SIZE 3 #define PLUTVAL_BYTE_SIZE 3
#define NUMBER_OF_PLUTVALS 256 #define NUMBER_OF_PLUTVALS 256
#define PLUT_BYTE_SIZE (PLUTVAL_BYTE_SIZE * NUMBER_OF_PLUTVALS) #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 BUILD_FRAME (1 << 0)
#define FIND_PAGE (1 << 1) #define FIND_PAGE (1 << 1)
@@ -40,9 +38,25 @@
#define FADE_NORMAL_INTENSITY 255 #define FADE_NORMAL_INTENSITY 255
#define FADE_FULL_INTENSITY 510 #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; 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 #endif
+1 -1
View File
@@ -62,7 +62,7 @@ typedef struct tfb_dc_img
TFB_Image *image; TFB_Image *image;
int x, y; int x, y;
SCREEN destBuffer; SCREEN destBuffer;
BOOLEAN UsePalette; TFB_ColorMap *colormap;
int scale; int scale;
} TFB_DrawCommand_Image; } 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 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_Rect srcRect, targetRect, *pSrcRect;
SDL_Surface *surf; SDL_Surface *surf;
TFB_Palette* palette;
if (img == 0) 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); LockMutex (img->mutex);
if (palette == 0) if (cmap)
palette = cmap->colors;
else
palette = img->Palette; 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) if (scale != 0 && scale != GSCALE_IDENTITY)
{ {
int type; int type;
if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg) if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg)
{ {
type = TFB_SCALE_TRILINEAR; type = TFB_SCALE_TRILINEAR;
if (((SDL_Surface *)img->NormalImg)->format->palette) // only set the new palette if it changed
SDL_SetColors (img->NormalImg, (SDL_Color*)palette, 0, 256); if (((SDL_Surface *)img->MipmapImg)->format->palette
if (((SDL_Surface *)img->MipmapImg)->format->palette) && cmap && img->colormap_version != cmap->version)
SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256); SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256);
} }
else 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); TFB_DrawImage_FixScaling (img, scale, type);
surf = img->ScaledImg; surf = img->ScaledImg;
if (surf->format->palette)
SDL_SetColors (surf, (SDL_Color*)palette, 0, 256);
srcRect.x = 0; srcRect.x = 0;
srcRect.y = 0; srcRect.y = 0;
srcRect.w = img->extent.width; 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; targetRect.y = y - img->NormalHs.y;
} }
if (surf->format->palette) if (cmap)
SDL_SetColors (surf, (SDL_Color*)palette, 0, 256); {
img->colormap_version = cmap->version;
TFB_ReturnColorMap (cmap);
}
SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect); SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect);
UnlockMutex (img->mutex); 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; pal[i].b = b;
} }
SDL_SetColors (surf, pal, 0, 256); SDL_SetColors (surf, pal, 0, 256);
// reflect the change in *actual* image palette
img->colormap_version--;
} }
else else
{ // fill the non-transparent parts of the image with fillcolor { // 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 (); Init_DrawCommandQueue ();
TFB_FlushPaletteCache ();
TFB_DrawCanvas_Initialize (); TFB_DrawCanvas_Initialize ();
RenderingCond = CreateCondVar ("DCQ empty", RenderingCond = CreateCondVar ("DCQ empty",
@@ -614,17 +613,12 @@ TFB_FlushGraphics () // Only call from main thread!!
case TFB_DRAWCOMMANDTYPE_IMAGE: case TFB_DRAWCOMMANDTYPE_IMAGE:
{ {
TFB_Image *DC_image = DC.data.image.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 x = DC.data.image.x;
int y = DC.data.image.y; int y = DC.data.image.y;
if (DC.data.image.UsePalette)
pal = palette;
else
pal = 0;
TFB_DrawCanvas_Image (DC_image, x, y, TFB_DrawCanvas_Image (DC_image, x, y,
DC.data.image.scale, pal, DC.data.image.scale, cmap,
SDL_Screens[DC.data.image.destBuffer]); SDL_Screens[DC.data.image.destBuffer]);
if (DC.data.image.destBuffer == 0) 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); 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 void
TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, 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; TFB_DrawCommand DC;
DC.Type = TFB_DRAWCOMMANDTYPE_IMAGE; DC.Type = TFB_DRAWCOMMANDTYPE_IMAGE;
DC.data.image.image = img; DC.data.image.image = img;
DC.data.image.colormap = cmap;
DC.data.image.x = x; DC.data.image.x = x;
DC.data.image.y = y; DC.data.image.y = y;
DC.data.image.scale = (scale == GSCALE_IDENTITY) ? 0 : scale; 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; DC.data.image.destBuffer = dest;
TFB_EnqueueDrawCommand (&DC); TFB_EnqueueDrawCommand (&DC);
Unlock_DCQ ();
} }
void void
@@ -296,10 +250,10 @@ TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image)
void void
TFB_DrawImage_Image (TFB_Image *img, int x, int y, int scale, 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); 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; target->dirty = TRUE;
UnlockMutex (target->mutex); UnlockMutex (target->mutex);
} }
@@ -334,6 +288,7 @@ TFB_DrawImage_New (TFB_Canvas canvas)
img->MipmapImg = NULL; img->MipmapImg = NULL;
img->FilledImg = NULL; img->FilledImg = NULL;
img->colormap_index = -1; img->colormap_index = -1;
img->colormap_version = 0;
img->NormalHs = NullHs; img->NormalHs = NullHs;
img->MipmapHs = NullHs; img->MipmapHs = NullHs;
img->last_scale_hs = NullHs; img->last_scale_hs = NullHs;
@@ -363,6 +318,7 @@ TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha)
img->MipmapImg = NULL; img->MipmapImg = NULL;
img->FilledImg = NULL; img->FilledImg = NULL;
img->colormap_index = -1; img->colormap_index = -1;
img->colormap_version = 0;
img->NormalHs = NullHs; img->NormalHs = NullHs;
img->MipmapHs = NullHs; img->MipmapHs = NullHs;
img->last_scale_hs = NullHs; img->last_scale_hs = NullHs;
+5 -4
View File
@@ -47,6 +47,7 @@ typedef struct tfb_palette
} TFB_Palette; } TFB_Palette;
#include "graphics/gfx_common.h" #include "graphics/gfx_common.h"
#include "cmap.h"
typedef struct tfb_image typedef struct tfb_image
{ {
@@ -56,6 +57,7 @@ typedef struct tfb_image
TFB_Canvas FilledImg; TFB_Canvas FilledImg;
TFB_Palette *Palette; TFB_Palette *Palette;
int colormap_index; int colormap_index;
int colormap_version;
HOT_SPOT NormalHs; HOT_SPOT NormalHs;
HOT_SPOT MipmapHs; HOT_SPOT MipmapHs;
HOT_SPOT last_scale_hs; 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_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_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_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_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); 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_WaitForSignal (void);
void TFB_DrawScreen_ReinitVideo (int driver, int flags, int width, int height, int bpp); 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_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_New (TFB_Canvas canvas);
TFB_Image *TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha); 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_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_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_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); 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_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_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_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); 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; int x, y;
PFRAME_DESC SrcFramePtr; PFRAME_DESC SrcFramePtr;
TFB_Image *img; TFB_Image *img;
BOOLEAN paletted; TFB_ColorMap *cmap = NULL;
TFB_Palette palette[256];
int gscale; int gscale;
SrcFramePtr = (PFRAME_DESC)stmp->frame; SrcFramePtr = (PFRAME_DESC)stmp->frame;
@@ -143,25 +142,22 @@ TFB_Prim_Stamp (PSTAMP stmp)
img->NormalHs = SrcFramePtr->HotSpot; img->NormalHs = SrcFramePtr->HotSpot;
x = stmp->origin.x - _CurFramePtr->HotSpot.x; x = stmp->origin.x - _CurFramePtr->HotSpot.x;
y = stmp->origin.y - _CurFramePtr->HotSpot.y; y = stmp->origin.y - _CurFramePtr->HotSpot.y;
paletted = FALSE;
if (TFB_DrawCanvas_IsPaletted(img->NormalImg) && img->colormap_index != -1) if (TFB_DrawCanvas_IsPaletted(img->NormalImg) && img->colormap_index != -1)
{ {
TFB_ColorMapToRGB (palette, img->colormap_index); // returned cmap is addrefed, must release later
paletted = TRUE; cmap = TFB_GetColorMap (img->colormap_index);
} }
UnlockMutex (img->mutex); UnlockMutex (img->mutex);
if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
{ {
TFB_DrawScreen_Image (img, x, y, gscale, (paletted ? palette : NULL), TFB_DrawScreen_Image (img, x, y, gscale, cmap, TFB_SCREEN_MAIN);
TFB_SCREEN_MAIN);
} }
else else
{ {
TFB_DrawImage_Image (img, x, y, gscale, (paletted ? palette : NULL), TFB_DrawImage_Image (img, x, y, gscale, cmap, _CurFramePtr->image);
_CurFramePtr->image);
} }
} }