forked from enlightenment/efl
807 lines
18 KiB
C
807 lines
18 KiB
C
#include "evas_engine_dfb.h"
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
static Evas_Hash * images = NULL;
|
|
static Evas_Object_List * cache = NULL;
|
|
static int cache_size = 0;
|
|
static int cache_usage = 0;
|
|
|
|
static RGBA_Image *_dfb_image_create(Render_Engine *, int w, int h);
|
|
static void _dfb_image_free(RGBA_Image *im);
|
|
static void _dfb_image_unref(RGBA_Image *im);
|
|
static void _dfb_image_dirty(RGBA_Image *im);
|
|
static void _dfb_image_set_cache(int size);
|
|
static int _dfb_image_get_cache();
|
|
static void _dfb_image_flush_cache();
|
|
static void _dfb_image_cache(RGBA_Image *im);
|
|
static void _dfb_image_uncache(RGBA_Image *im);
|
|
static void _dfb_image_store(RGBA_Image *im);
|
|
static void _dfb_image_unstore(RGBA_Image *im);
|
|
static void _dfb_image_ref(RGBA_Image *im);
|
|
static void _dfb_image_unref(RGBA_Image *im);
|
|
|
|
static RGBA_Image *_dfb_image_find(const char *filename, const char *key, DATA64 timestamp);
|
|
|
|
/*
|
|
* Image objects
|
|
*/
|
|
|
|
void *
|
|
evas_engine_directfb_image_load(void *data, char *file, char *key, int *error)
|
|
{
|
|
Render_Engine *re;
|
|
DFBSurfaceDescription dsc;
|
|
DFBImageDescription img_desc;
|
|
IDirectFBImageProvider *provider;
|
|
IDirectFBSurface *image;
|
|
RGBA_Image *im = NULL;
|
|
DFBResult err;
|
|
DATA64 mod_time;
|
|
|
|
re = (Render_Engine *) data;
|
|
*error = 0;
|
|
|
|
mod_time = evas_file_modified_time(file);
|
|
im = _dfb_image_find(file, key, mod_time);
|
|
if (im)
|
|
{
|
|
_dfb_image_ref(im);
|
|
return im;
|
|
}
|
|
|
|
/* Image is not in cache or not already used -> create it */
|
|
re->dfb->CreateImageProvider(re->dfb, file, &provider);
|
|
provider->GetSurfaceDescription(provider, &dsc);
|
|
provider->GetImageDescription(provider, &img_desc);
|
|
|
|
dsc.flags |= DSDESC_PIXELFORMAT;
|
|
dsc.pixelformat = DSPF_ARGB;
|
|
|
|
re->dfb->CreateSurface(re->dfb, &dsc, &image);
|
|
provider->RenderTo(provider, image, NULL);
|
|
provider->Release(provider);
|
|
|
|
im = evas_common_image_new();
|
|
im->image = evas_common_image_surface_new();
|
|
if (!im->image)
|
|
{
|
|
_dfb_image_free(im);
|
|
return NULL;
|
|
}
|
|
im->image->w = dsc.width;
|
|
im->image->h = dsc.height;
|
|
im->image->data = (void *)image;
|
|
im->image->no_free = 0;
|
|
if (img_desc.caps & DICAPS_ALPHACHANNEL)
|
|
im->flags |= RGBA_IMAGE_HAS_ALPHA;
|
|
|
|
im->timestamp = mod_time;
|
|
if (file)
|
|
im->info.file = strdup(file);
|
|
if (key)
|
|
im->info.key = strdup(key);
|
|
_dfb_image_ref(im);
|
|
|
|
return im;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_new_from_data(void *data, int w, int h,
|
|
DATA32 * image_data)
|
|
{
|
|
/* FIXME document this peculiarity */
|
|
return evas_engine_directfb_image_new_from_copied_data(data, w, h, image_data);
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_new_from_copied_data(void *data, int w, int h,
|
|
DATA32 * image_data)
|
|
{
|
|
|
|
Render_Engine *re;
|
|
RGBA_Image *im = NULL;
|
|
IDirectFBSurface *surf;
|
|
void *p;
|
|
int pitch;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = _dfb_image_create(re, w, h);
|
|
|
|
if (im)
|
|
{
|
|
surf = (IDirectFBSurface *) im->image->data;
|
|
if (surf->Lock(surf, DSLF_WRITE, &p, &pitch) == DFB_OK)
|
|
{
|
|
memcpy(p, image_data, w * h * sizeof(DATA32));
|
|
surf->Unlock(surf);
|
|
}
|
|
}
|
|
/* FIXME */
|
|
free(image_data);
|
|
return im;
|
|
}
|
|
|
|
void
|
|
evas_engine_directfb_image_free(void *data, void *image)
|
|
{
|
|
Render_Engine *re;
|
|
|
|
re = (Render_Engine *) data;
|
|
_dfb_image_unref(image);
|
|
}
|
|
|
|
void
|
|
evas_engine_directfb_image_size_get(void *data, void *image, int *w, int *h)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = image;
|
|
if (w)
|
|
*w = im->image->w;
|
|
if (h)
|
|
*h = im->image->h;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_size_set(void *data, void *image, int w, int h)
|
|
{
|
|
Render_Engine *re;
|
|
IDirectFBSurface *old_surf;
|
|
IDirectFBSurface *new_surf;
|
|
DFBRectangle outrect;
|
|
RGBA_Image *im, *im_old;
|
|
|
|
re = (Render_Engine *) data;
|
|
im_old = image;
|
|
im = _dfb_image_create(re, w,h);
|
|
old_surf = (IDirectFBSurface *) im_old->image->data;
|
|
if (im)
|
|
{
|
|
outrect.x = 0;
|
|
outrect.y = 0;
|
|
outrect.w = w;
|
|
outrect.h = h;
|
|
new_surf = (IDirectFBSurface *) im->image->data;
|
|
new_surf->StretchBlit(new_surf, old_surf, NULL, &outrect);
|
|
}
|
|
evas_common_cpu_end_opt;
|
|
_dfb_image_unref(im_old);
|
|
|
|
return im;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_dirty_region(void *data, void *image, int x, int y,
|
|
int w, int h)
|
|
{
|
|
_dfb_image_dirty(image);
|
|
return image;
|
|
x = 0;
|
|
y = 0;
|
|
w = 0;
|
|
h = 0;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_data_get(void *data, void *image, int to_write,
|
|
DATA32 ** image_data)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
IDirectFBSurface *surf;
|
|
void *p;
|
|
int pitch;
|
|
int *buf = NULL;
|
|
int size, i, tmp;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = image;
|
|
surf = (IDirectFBSurface *) im->image->data;
|
|
size = im->image->w * im->image->h * sizeof(DATA32);
|
|
surf->Lock(surf, DSLF_READ, &p, &pitch);
|
|
|
|
if (buf = malloc(size))
|
|
buf = memcpy(buf, p, size);
|
|
*image_data = buf;
|
|
|
|
surf->Unlock(surf);
|
|
return im;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_data_put(void *data, void *image,
|
|
DATA32 * image_data)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
|
|
re = (Render_Engine *)data;
|
|
im = image;
|
|
if (image_data != im->image->data)
|
|
{
|
|
int w, h;
|
|
|
|
w = im->image->w;
|
|
h = im->image->h;
|
|
_dfb_image_unref(im);
|
|
return evas_engine_directfb_image_new_from_data(data, w, h, image_data);
|
|
}
|
|
_dfb_image_dirty(im);
|
|
|
|
return im;
|
|
}
|
|
|
|
void *
|
|
evas_engine_directfb_image_alpha_set(void *data, void *image, int has_alpha)
|
|
{
|
|
RGBA_Image *im;
|
|
|
|
im = image;
|
|
if (has_alpha)
|
|
im->flags |= RGBA_IMAGE_HAS_ALPHA;
|
|
else
|
|
im->flags &= ~RGBA_IMAGE_HAS_ALPHA;
|
|
}
|
|
|
|
int
|
|
evas_engine_directfb_image_alpha_get(void *data, void *image)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = image;
|
|
if (im->flags & RGBA_IMAGE_HAS_ALPHA)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
evas_engine_directfb_image_draw(void *data, void *context, void *surface,
|
|
void *image, int src_region_x, int src_region_y,
|
|
int src_region_w, int src_region_h,
|
|
int dst_region_x, int dst_region_y,
|
|
int dst_region_w, int dst_region_h, int smooth)
|
|
{
|
|
int src_w, src_h, dst_w, dst_h;
|
|
int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
|
|
double horiz_stretch, vert_stretch;
|
|
|
|
Render_Engine *re = (Render_Engine *) data;
|
|
DFBRectangle inrect;
|
|
DFBRectangle outrect;
|
|
RGBA_Image *im = (RGBA_Image *) image;
|
|
RGBA_Draw_Context *dc = (RGBA_Draw_Context *) context;
|
|
IDirectFBSurface *img = (IDirectFBSurface *) im->image->data;
|
|
DFBSurfaceDescription dsc;
|
|
|
|
src_w = im->image->w;
|
|
src_h = im->image->h;
|
|
dst_w = re->tb->outbuf_w;
|
|
dst_h = re->tb->outbuf_h;
|
|
|
|
if (!
|
|
(RECTS_INTERSECT
|
|
(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst_w,
|
|
dst_h)))
|
|
return;
|
|
if (!
|
|
(RECTS_INTERSECT
|
|
(src_region_x, src_region_y, src_region_w, src_region_h, 0, 0, src_w,
|
|
src_h)))
|
|
return;
|
|
if (dc->clip.use)
|
|
{
|
|
dst_clip_x = dc->clip.x;
|
|
dst_clip_y = dc->clip.y;
|
|
dst_clip_w = dc->clip.w;
|
|
dst_clip_h = dc->clip.h;
|
|
if (dst_clip_x < 0)
|
|
{
|
|
dst_clip_w += dst_clip_x;
|
|
dst_clip_x = 0;
|
|
}
|
|
if (dst_clip_y < 0)
|
|
{
|
|
dst_clip_h += dst_clip_y;
|
|
dst_clip_y = 0;
|
|
}
|
|
if ((dst_clip_x + dst_clip_w) > dst_w)
|
|
dst_clip_w = dst_w - dst_clip_x;
|
|
if ((dst_clip_y + dst_clip_h) > dst_h)
|
|
dst_clip_h = dst_h - dst_clip_y;
|
|
}
|
|
else
|
|
{
|
|
dst_clip_x = 0;
|
|
dst_clip_y = 0;
|
|
dst_clip_w = dst_w;
|
|
dst_clip_h = dst_h;
|
|
}
|
|
|
|
if (dst_clip_x < dst_region_x)
|
|
{
|
|
dst_clip_w += dst_clip_x - dst_region_x;
|
|
dst_clip_x = dst_region_x;
|
|
}
|
|
if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w))
|
|
dst_clip_w = dst_region_x + dst_region_w - dst_clip_x;
|
|
if (dst_clip_y < dst_region_y)
|
|
{
|
|
dst_clip_h += dst_clip_y - dst_region_y;
|
|
dst_clip_y = dst_region_y;
|
|
}
|
|
if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h))
|
|
dst_clip_h = dst_region_y + dst_region_h - dst_clip_y;
|
|
|
|
if ((src_region_w <= 0) || (src_region_h <= 0) ||
|
|
(dst_region_w <= 0) || (dst_region_h <= 0) ||
|
|
(dst_clip_w <= 0) || (dst_clip_h <= 0))
|
|
return;
|
|
/* sanitise x */
|
|
if (src_region_x < 0)
|
|
{
|
|
dst_region_x -= (src_region_x * dst_region_w) / src_region_w;
|
|
dst_region_w += (src_region_x * dst_region_w) / src_region_w;
|
|
src_region_w += src_region_x;
|
|
src_region_x = 0;
|
|
}
|
|
if (src_region_x >= src_w)
|
|
return;
|
|
if ((src_region_x + src_region_w) > src_w)
|
|
{
|
|
dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w);
|
|
src_region_w = src_w - src_region_x;
|
|
}
|
|
if (dst_region_w <= 0)
|
|
return;
|
|
if (src_region_w <= 0)
|
|
return;
|
|
if (dst_clip_x < 0)
|
|
{
|
|
dst_clip_w += dst_clip_x;
|
|
dst_clip_x = 0;
|
|
}
|
|
if (dst_clip_w <= 0)
|
|
return;
|
|
if (dst_clip_x >= dst_w)
|
|
return;
|
|
if (dst_clip_x < dst_region_x)
|
|
{
|
|
dst_clip_w += (dst_clip_x - dst_region_x);
|
|
dst_clip_x = dst_region_x;
|
|
}
|
|
if ((dst_clip_x + dst_clip_w) > dst_w)
|
|
{
|
|
dst_clip_w = dst_w - dst_clip_x;
|
|
}
|
|
if (dst_clip_w <= 0)
|
|
return;
|
|
|
|
/* sanitise y */
|
|
if (src_region_y < 0)
|
|
{
|
|
dst_region_y -= (src_region_y * dst_region_h) / src_region_h;
|
|
dst_region_h += (src_region_y * dst_region_h) / src_region_h;
|
|
src_region_h += src_region_y;
|
|
src_region_y = 0;
|
|
}
|
|
if (src_region_y >= src_h)
|
|
return;
|
|
if ((src_region_y + src_region_h) > src_h)
|
|
{
|
|
dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h);
|
|
src_region_h = src_h - src_region_y;
|
|
}
|
|
if (dst_region_h <= 0)
|
|
return;
|
|
if (src_region_h <= 0)
|
|
return;
|
|
if (dst_clip_y < 0)
|
|
{
|
|
dst_clip_h += dst_clip_y;
|
|
dst_clip_y = 0;
|
|
}
|
|
if (dst_clip_h <= 0)
|
|
return;
|
|
if (dst_clip_y >= dst_h)
|
|
return;
|
|
if (dst_clip_y < dst_region_y)
|
|
{
|
|
dst_clip_h += (dst_clip_y - dst_region_y);
|
|
dst_clip_y = dst_region_y;
|
|
}
|
|
if ((dst_clip_y + dst_clip_h) > dst_h)
|
|
{
|
|
dst_clip_h = dst_h - dst_clip_y;
|
|
}
|
|
if (dst_clip_h <= 0)
|
|
return;
|
|
|
|
/* Figure out scale ratios */
|
|
horiz_stretch = (double)dst_region_w / (double)src_region_w;
|
|
vert_stretch = (double)dst_region_h / (double)src_region_h;
|
|
|
|
inrect.x = src_region_x + floor((dst_clip_x - dst_region_x) / horiz_stretch);
|
|
inrect.y = src_region_y + floor((dst_clip_y - dst_region_y) / vert_stretch);
|
|
inrect.w = floor(src_region_w * dst_clip_w / dst_region_w);
|
|
inrect.h = floor(src_region_h * dst_clip_h / dst_region_h);
|
|
|
|
outrect.x = dst_clip_x;
|
|
outrect.y = dst_clip_y;
|
|
outrect.w = dst_clip_w;
|
|
outrect.h = dst_clip_h;
|
|
|
|
{
|
|
int r, g, b, a;
|
|
int mulr, mulg, mulb, mula;
|
|
int flags;
|
|
|
|
if (im->flags & RGBA_IMAGE_HAS_ALPHA)
|
|
flags = DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL;
|
|
else
|
|
flags = DSBLIT_NOFX;
|
|
|
|
evas_engine_directfb_context_color_get(data, context, &r, &g, &b, &a);
|
|
if (evas_engine_directfb_context_multiplier_get
|
|
(data, context, &mulr, &mulg, &mulb, &mula))
|
|
{
|
|
re->backbuf->SetColor(re->backbuf, mulr, mulg, mulb, mula);
|
|
flags |= DSBLIT_COLORIZE;
|
|
}
|
|
else
|
|
{
|
|
re->backbuf->SetColor(re->backbuf, r, g, b, a);
|
|
}
|
|
|
|
re->backbuf->SetBlittingFlags(re->backbuf, flags);
|
|
re->backbuf->StretchBlit(re->backbuf, img, &inrect, &outrect);
|
|
}
|
|
|
|
evas_common_cpu_end_opt();
|
|
}
|
|
|
|
void
|
|
evas_engine_directfb_image_cache_flush(void *data)
|
|
{
|
|
Render_Engine *re;
|
|
int tmp_size;
|
|
|
|
re = (Render_Engine *) data;
|
|
tmp_size = cache_size;
|
|
cache_size = 0;
|
|
_dfb_image_set_cache(0);
|
|
_dfb_image_set_cache(tmp_size);
|
|
}
|
|
|
|
void
|
|
evas_engine_directfb_image_cache_set(void *data, int bytes)
|
|
{
|
|
_dfb_image_set_cache(bytes);
|
|
}
|
|
|
|
int
|
|
evas_engine_directfb_image_cache_get(void *data)
|
|
{
|
|
return _dfb_image_get_cache();
|
|
}
|
|
|
|
char *
|
|
evas_engine_directfb_image_comment_get(void *data, void *image, char *key)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = image;
|
|
return im->info.comment;
|
|
}
|
|
|
|
char *
|
|
evas_engine_directfb_image_format_get(void *data, void *image)
|
|
{
|
|
Render_Engine *re;
|
|
RGBA_Image *im;
|
|
|
|
re = (Render_Engine *) data;
|
|
im = image;
|
|
if (im->info.format == 1)
|
|
return "png";
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Private routines. These are slightly modified versions of the ones in
|
|
* engines/common/evas_image_main.c
|
|
*/
|
|
|
|
static void
|
|
_dfb_image_surface_free(RGBA_Surface *is)
|
|
{
|
|
IDirectFBSurface *surf;
|
|
if ( (is->data) && (!is->no_free) )
|
|
{
|
|
surf = (IDirectFBSurface *)is->data;
|
|
surf->Release(surf);
|
|
is->data = NULL;
|
|
}
|
|
free(is);
|
|
}
|
|
|
|
|
|
static RGBA_Image *
|
|
_dfb_image_create(Render_Engine *re, int w, int h)
|
|
{
|
|
RGBA_Image *im;
|
|
DFBSurfaceDescription dsc;
|
|
IDirectFBSurface *surf;
|
|
|
|
im = evas_common_image_new();
|
|
if (!im) return NULL;
|
|
im->image = evas_common_image_surface_new();
|
|
if (!im->image)
|
|
{
|
|
_dfb_image_free(im);
|
|
return NULL;
|
|
}
|
|
im->image->w = w;
|
|
im->image->h = h;
|
|
|
|
dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
|
|
dsc.width = w;
|
|
dsc.height = h;
|
|
dsc.pixelformat = DSPF_ARGB;
|
|
|
|
if (re->dfb->CreateSurface(re->dfb, &dsc, &surf) != DFB_OK)
|
|
{
|
|
_dfb_image_free(im);
|
|
return NULL;
|
|
}
|
|
im->image->data = (void*) surf;
|
|
im->flags = RGBA_IMAGE_IS_DIRTY;
|
|
im->references = 1;
|
|
return im;
|
|
}
|
|
|
|
|
|
static void
|
|
_dfb_image_free(RGBA_Image *im)
|
|
{
|
|
int i;
|
|
|
|
if (im->image) _dfb_image_surface_free(im->image);
|
|
/* FIXME what about mipmaps? */
|
|
for (i = 0; i < im->mipmaps.num; i++)
|
|
{
|
|
if (im->mipmaps.levels[i])
|
|
_dfb_image_surface_free(im->mipmaps.levels[i]);
|
|
}
|
|
if (im->mipmaps.levels) free(im->mipmaps.levels);
|
|
if (im->info.file) free(im->info.file);
|
|
if (im->info.key) free(im->info.key);
|
|
if (im->info.comment) free(im->info.comment);
|
|
free(im);
|
|
}
|
|
|
|
static void
|
|
_dfb_image_ref(RGBA_Image *im)
|
|
{
|
|
im->references++;
|
|
if (im->references == 1) /* we were in cache - take us out */
|
|
{
|
|
_dfb_image_uncache(im);
|
|
_dfb_image_store(im);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_dfb_image_unref(RGBA_Image *im)
|
|
{
|
|
im->references--;
|
|
if (im->references <= 0) /* we were are now in cache - put us in */
|
|
{
|
|
_dfb_image_unstore(im);
|
|
if ((cache_size > 0) &&
|
|
(!(im->flags & RGBA_IMAGE_IS_DIRTY)))
|
|
{
|
|
_dfb_image_cache(im);
|
|
_dfb_image_flush_cache();
|
|
}
|
|
else
|
|
{
|
|
_dfb_image_free(im);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_dfb_image_set_cache(int size)
|
|
{
|
|
cache_size = size;
|
|
_dfb_image_flush_cache();
|
|
}
|
|
|
|
static int
|
|
_dfb_image_get_cache(void)
|
|
{
|
|
return cache_size;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
_dfb_image_cache(RGBA_Image *im)
|
|
{
|
|
int ram;
|
|
|
|
if (im->flags & RGBA_IMAGE_INDEXED) return;
|
|
im->flags |= RGBA_IMAGE_INDEXED;
|
|
cache = evas_object_list_prepend(cache, im);
|
|
ram = evas_common_image_ram_usage(im);
|
|
cache_usage += ram;
|
|
_dfb_image_flush_cache();
|
|
}
|
|
|
|
static void
|
|
_dfb_image_uncache(RGBA_Image *im)
|
|
{
|
|
int ram;
|
|
|
|
if (!(im->flags & RGBA_IMAGE_INDEXED)) return;
|
|
im->flags &= ~RGBA_IMAGE_INDEXED;
|
|
cache = evas_object_list_remove(cache, im);
|
|
ram = evas_common_image_ram_usage(im);
|
|
cache_usage -= ram;
|
|
}
|
|
|
|
|
|
static void
|
|
_dfb_image_flush_cache(void)
|
|
{
|
|
Evas_Object_List *l, *l_next;
|
|
|
|
if (!cache) return;
|
|
if (cache_usage < cache_size) return;
|
|
|
|
for (l = cache->last; l;)
|
|
{
|
|
RGBA_Image *im;
|
|
|
|
l_next = l->prev;
|
|
im = (RGBA_Image *)l;
|
|
_dfb_image_uncache(im);
|
|
_dfb_image_free(im);
|
|
if (cache_usage <= cache_size) return;
|
|
l = l_next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_dfb_image_dirty(RGBA_Image *im)
|
|
{
|
|
int i;
|
|
|
|
_dfb_image_unstore(im);
|
|
im->flags |= RGBA_IMAGE_IS_DIRTY;
|
|
for (i = 0; i < im->mipmaps.num; i++)
|
|
_dfb_image_surface_free(im->mipmaps.levels[i]);
|
|
}
|
|
|
|
|
|
static void
|
|
_dfb_image_store(RGBA_Image *im)
|
|
{
|
|
char *key;
|
|
int l1, l2, l3;
|
|
char buf[256];
|
|
|
|
if (im->flags & RGBA_IMAGE_IS_DIRTY) return;
|
|
if (im->flags & RGBA_IMAGE_INDEXED) return;
|
|
if ((!im->info.file) && (!im->info.key)) return;
|
|
l1 = 0;
|
|
if (im->info.file) l1 = strlen(im->info.file);
|
|
l2 = 0;
|
|
if (im->info.key) l2 = strlen(im->info.key);
|
|
snprintf(buf, sizeof(buf), "%llx", im->timestamp);
|
|
l3 = strlen(buf);
|
|
key = malloc(l1 + 3 + l2 + 3 + l3 +1);
|
|
if (!key) return;
|
|
key[0] = 0;
|
|
if (im->info.file) strcpy(key, im->info.file);
|
|
strcat(key, "/:/");
|
|
if (im->info.key) strcat(key, im->info.key);
|
|
strcat(key, "/:/");
|
|
strcat(key, buf);
|
|
images = evas_hash_add(images, key, im);
|
|
free(key);
|
|
im->flags |= RGBA_IMAGE_INDEXED;
|
|
}
|
|
|
|
static void
|
|
_dfb_image_unstore(RGBA_Image *im)
|
|
{
|
|
char *key;
|
|
int l1, l2, l3;
|
|
char buf[256];
|
|
|
|
if (!(im->flags & RGBA_IMAGE_INDEXED)) return;
|
|
if ((!im->info.file) && (!im->info.key)) return;
|
|
l1 = 0;
|
|
if (im->info.file) l1 = strlen(im->info.file);
|
|
l2 = 0;
|
|
if (im->info.key) l2 = strlen(im->info.key);
|
|
snprintf(buf, sizeof(buf), "%llx", im->timestamp);
|
|
l3 = strlen(buf);
|
|
key = malloc(l1 + 3 + l2 + 3 + l3 +1);
|
|
if (!key) return;
|
|
key[0] = 0;
|
|
if (im->info.file) strcpy(key, im->info.file);
|
|
strcat(key, "/:/");
|
|
if (im->info.key) strcat(key, im->info.key);
|
|
strcat(key, "/:/");
|
|
strcat(key, buf);
|
|
images = evas_hash_del(images, key, im);
|
|
free(key);
|
|
im->flags &= ~RGBA_IMAGE_INDEXED;
|
|
}
|
|
|
|
|
|
static RGBA_Image *
|
|
_dfb_image_find(const char *filename, const char *key, DATA64 timestamp)
|
|
{
|
|
Evas_Object_List *l;
|
|
RGBA_Image *im;
|
|
char *str;
|
|
int l1, l2, l3;
|
|
char buf[256];
|
|
|
|
if ((!filename) && (!key)) return NULL;
|
|
l1 = 0;
|
|
if (filename) l1 = strlen(filename);
|
|
l2 = 0;
|
|
if (key) l2 = strlen(key);
|
|
sprintf(buf, "%llx", timestamp);
|
|
l3 = strlen(buf);
|
|
str = malloc(l1 + 3 + l2 + 3 + l3 +1);
|
|
if (!str) return NULL;
|
|
str[0] = 0;
|
|
if (filename) strcpy(str, filename);
|
|
strcat(str, "/:/");
|
|
if (key) strcat(str, key);
|
|
strcat(str, "/:/");
|
|
strcat(str, buf);
|
|
im = evas_hash_find(images, str);
|
|
free(str);
|
|
if (im) return im;
|
|
|
|
for (l = cache; l; l = l->next)
|
|
{
|
|
int ok;
|
|
|
|
im = (RGBA_Image *)l;
|
|
ok = 0;
|
|
if ((filename) && (im->info.file) &&
|
|
(!strcmp(filename, im->info.file)))
|
|
ok++;
|
|
if ((!filename) && (!im->info.file))
|
|
ok++;
|
|
if ((key) && (im->info.key) &&
|
|
(!strcmp(key, im->info.key)))
|
|
ok++;
|
|
if ((!key) && (!im->info.key))
|
|
ok++;
|
|
if (im->timestamp == timestamp)
|
|
ok++;
|
|
if (ok >= 3) return im;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|