SDL_Surface refcount: destination surface keep track of surfaces
that are mapped to it and automatically invalidate them when it is freed - refcount is kept so that an external application can still create a reference to SDL_Surface. - lock_data was un-used and is now renamed and used as a list keep track of the blitmap
parent
cce6c60518
commit
ebc12a2fd2
|
@ -80,7 +80,9 @@ typedef struct SDL_Surface
|
||||||
|
|
||||||
/** information needed for surfaces requiring locks */
|
/** information needed for surfaces requiring locks */
|
||||||
int locked; /**< Read-only */
|
int locked; /**< Read-only */
|
||||||
void *lock_data; /**< Read-only */
|
|
||||||
|
/** list of BlitMap that hold a reference to this surface */
|
||||||
|
void *list_blitmap; /**< Private */
|
||||||
|
|
||||||
/** clipping information */
|
/** clipping information */
|
||||||
SDL_Rect clip_rect; /**< Read-only */
|
SDL_Rect clip_rect; /**< Read-only */
|
||||||
|
|
|
@ -1023,6 +1023,62 @@ SDL_AllocBlitMap(void)
|
||||||
return (map);
|
return (map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SDL_ListNode
|
||||||
|
{
|
||||||
|
void *entry;
|
||||||
|
struct SDL_ListNode *next;
|
||||||
|
} SDL_ListNode;
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_InvalidateAllBlitMap(SDL_Surface *surface)
|
||||||
|
{
|
||||||
|
SDL_ListNode *l = surface->list_blitmap;
|
||||||
|
|
||||||
|
surface->list_blitmap = NULL;
|
||||||
|
|
||||||
|
while (l) {
|
||||||
|
SDL_ListNode *tmp = l;
|
||||||
|
SDL_InvalidateMap((SDL_BlitMap *)l->entry);
|
||||||
|
l = l->next;
|
||||||
|
SDL_free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SDL_ListAdd(SDL_ListNode **head, void *ent);
|
||||||
|
static void SDL_ListRemove(SDL_ListNode **head, void *ent);
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_ListAdd(SDL_ListNode **head, void *ent)
|
||||||
|
{
|
||||||
|
SDL_ListNode *node = SDL_malloc(sizeof (*node));
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->entry = ent;
|
||||||
|
node->next = *head;
|
||||||
|
*head = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_ListRemove(SDL_ListNode **head, void *ent)
|
||||||
|
{
|
||||||
|
SDL_ListNode **ptr = head;
|
||||||
|
|
||||||
|
while (*ptr) {
|
||||||
|
if ((*ptr)->entry == ent) {
|
||||||
|
SDL_ListNode *tmp = *ptr;
|
||||||
|
*ptr = (*ptr)->next;
|
||||||
|
SDL_free(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = &(*ptr)->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SDL_InvalidateMap(SDL_BlitMap * map)
|
SDL_InvalidateMap(SDL_BlitMap * map)
|
||||||
{
|
{
|
||||||
|
@ -1030,10 +1086,8 @@ SDL_InvalidateMap(SDL_BlitMap * map)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (map->dst) {
|
if (map->dst) {
|
||||||
/* Release our reference to the surface - see the note below */
|
/* Un-register from the destination surface */
|
||||||
if (--map->dst->refcount <= 0) {
|
SDL_ListRemove((SDL_ListNode **)&(map->dst->list_blitmap), map);
|
||||||
SDL_FreeSurface(map->dst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
map->dst = NULL;
|
map->dst = NULL;
|
||||||
map->src_palette_version = 0;
|
map->src_palette_version = 0;
|
||||||
|
@ -1104,14 +1158,8 @@ SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
|
||||||
map->dst = dst;
|
map->dst = dst;
|
||||||
|
|
||||||
if (map->dst) {
|
if (map->dst) {
|
||||||
/* Keep a reference to this surface so it doesn't get deleted
|
/* Register BlitMap to the destination surface, to be invalidated when needed */
|
||||||
while we're still pointing at it.
|
SDL_ListAdd((SDL_ListNode **)&(map->dst->list_blitmap), map);
|
||||||
|
|
||||||
A better method would be for the destination surface to keep
|
|
||||||
track of surfaces that are mapped to it and automatically
|
|
||||||
invalidate them when it is freed, but this will do for now.
|
|
||||||
*/
|
|
||||||
++map->dst->refcount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dstfmt->palette) {
|
if (dstfmt->palette) {
|
||||||
|
|
|
@ -37,6 +37,8 @@ extern void SDL_InvalidateMap(SDL_BlitMap * map);
|
||||||
extern int SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst);
|
extern int SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst);
|
||||||
extern void SDL_FreeBlitMap(SDL_BlitMap * map);
|
extern void SDL_FreeBlitMap(SDL_BlitMap * map);
|
||||||
|
|
||||||
|
extern void SDL_InvalidateAllBlitMap(SDL_Surface *surface);
|
||||||
|
|
||||||
/* Miscellaneous functions */
|
/* Miscellaneous functions */
|
||||||
extern void SDL_DitherColors(SDL_Color * colors, int bpp);
|
extern void SDL_DitherColors(SDL_Color * colors, int bpp);
|
||||||
extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||||
|
|
|
@ -1328,6 +1328,8 @@ SDL_FreeSurface(SDL_Surface * surface)
|
||||||
}
|
}
|
||||||
SDL_InvalidateMap(surface->map);
|
SDL_InvalidateMap(surface->map);
|
||||||
|
|
||||||
|
SDL_InvalidateAllBlitMap(surface);
|
||||||
|
|
||||||
if (--surface->refcount > 0) {
|
if (--surface->refcount > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue