Jean-Philippe Andre <jp.andre@samsung.com>
Yury Usischev <y.usishchev@samsung.com>
Youngbok Shin <youngb.shin@samsung.com>
+Rajeev Ranjan (Rajeev) <rajeev.r@samsung.com> <rajeev.jnnce@gmail.com>
Ecore
-----
Eina_List *empty;
void *data;
+ Eina_Compare_Cb eina_rectangle_compare_func;
+
Eina_Trash *bucket;
unsigned int bucket_count;
+ Eina_Rectangle_Packing type;
+
unsigned int references;
int w;
int h;
#define DBG(...) EINA_LOG_DOM_DBG(_eina_rectangle_log_dom, __VA_ARGS__)
static int
-_eina_rectangle_cmp(const Eina_Rectangle *r1, const Eina_Rectangle *r2)
+_eina_rectangle_cmp(const void *data1, const void *data2)
{
+ Eina_Rectangle *r1 = (Eina_Rectangle *) data1;
+ Eina_Rectangle *r2 = (Eina_Rectangle *) data2;
return (r2->w * r2->h) - (r1->w * r1->h);
}
+static int
+_eina_rectangle_cmp_asc(const void *data1, const void *data2)
+{
+ Eina_Rectangle *r1 = (Eina_Rectangle *) data1;
+ Eina_Rectangle *r2 = (Eina_Rectangle *) data2;
+ return (r1->w * r1->h) - (r2->w * r2->h);
+}
+
+static int
+_eina_rectangle_cmp_bl(const void *data1, const void *data2)
+{
+ Eina_Rectangle *r1 = (Eina_Rectangle *) data1;
+ Eina_Rectangle *r2 = (Eina_Rectangle *) data2;
+ if (r1->y != r2->y)
+ return (r1->y) - (r2->y);
+ else
+ return (r1->x) - (r2->x);
+}
+
static Eina_List *
-_eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle *r)
+_eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle_Packing type, Eina_Rectangle *r)
{
- Eina_Rectangle *match;
+ Eina_Rectangle *match, *r1;
Eina_List *l;
int xw;
int yh;
+ int x2 ,y2 ,w2 ,h2;
if (r->w == 0 || r->h == 0)
{
goto start_again;
}
+ else if (match->y > r->y && type == Eina_Packing_Bottom_Left_Skyline
+ && (match->y + match->h == r->y + r->h) &&
+ (match->x + match->w == r->x || r->x + r->w == match->x))
+ {
+
+ if (r->x < match->x)
+ match->x = r->x;
+
+ match->w += r->w;
+
+ x2 = r->x;
+ y2 = r->y;
+ w2 = r->w;
+ h2 = match->y - r->y;
+
+ eina_rectangle_free(r);
+
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+
+ empty = eina_list_remove_list(empty, l);
+
+ if (r1)
+ empty = eina_list_append(empty, r1);
+
+ r = match;
+
+ goto start_again;
+ }
}
return eina_list_append(empty, r);
}
static Eina_List *
-_eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y)
+_eina_rectangle_empty_space_find(Eina_List *empty, Eina_Rectangle_Packing type, int w, int h, int *x, int *y)
{
Eina_Rectangle *r;
Eina_List *l;
/* w2 could be w or r->w */
h2 = r->h - h;
- if (rw1 * r->h > h2 * r->w)
+ if ((rw1 * r->h > h2 * r->w) || type == Eina_Packing_Bottom_Left || type == Eina_Packing_Bottom_Left_Skyline)
{
rh1 = r->h;
w2 = w;
rh1 = h;
w2 = r->w;
}
+ if (type == Eina_Packing_Bottom_Left_Skyline_Improved)
+ {
+ rh1 = r->h;
+ w2 = r->w;
+ }
EINA_RECTANGLE_SET(r, rx1, ry1, rw1, rh1);
- empty = _eina_rectangle_merge_list(empty, r);
+ empty = _eina_rectangle_merge_list(empty, type, r);
r = eina_rectangle_new(x2, y2, w2, h2);
}
if (r)
{
- empty = _eina_rectangle_merge_list(empty, r); /* Return empty */
+ empty = _eina_rectangle_merge_list(empty, type, r); /* Return empty */
}
return empty;
}
+static Eina_List *
+_eina_rectangle_skyline_merge_list(Eina_List *empty, Eina_Rectangle *r)
+{
+ Eina_Rectangle *match;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(empty, l, match)
+ {
+ if (match->x == r->x + r->w)
+ {
+ match->x = r->x;
+ match->w = r->w + match->w;
+ }
+ else if (match->y == r->y + r->h)
+ {
+ match->y = r->y;
+ match->h = r->h + match->h;
+ }
+ else if (match->x + match->w == r->x)
+ {
+ match->w = r->w + match->w;
+ }
+ else if (match->y + match->h == r->y )
+ {
+ match->h = r->h + match->h;
+ }
+ }
+ return empty;
+}
+
+static Eina_List *
+_eina_rectangle_skyline_list_update(Eina_List *empty, Eina_Rectangle *rect)
+{
+ Eina_Rectangle *r, *r1;
+ Eina_List *l;
+ int x2, y2, w2, h2;
+
+start_again :
+ EINA_LIST_FOREACH(empty, l, r)
+ {
+ if (eina_rectangles_intersect(rect, r))
+ {
+ /* Remove l from empty */
+ empty = eina_list_remove_list(empty, l);
+
+ if (r->y > rect->y)
+ {
+ if (r->y + r->h > rect->y + rect->h)
+ {
+ w2 = r->w;
+ h2 = (r->y +r->h) - (rect->y + rect->h);
+ x2 = r->x;
+ y2 = (r->y +r->h) - h2;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ if ( r->x + r->w > rect->x + rect->w )
+ {
+ w2 = (r->x +r->w) - (rect->x + rect->w);
+ h2 = r->h;
+ x2 = rect->x + rect->w;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ if ( rect->x - r->x)
+ {
+ w2 = rect->x - r->x;
+ h2 = r->h;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ }
+ else if (r->x > rect->x)
+ {
+ if (r->x + r->w > rect->x + rect->w)
+ {
+ w2 = (r->x + r->w) - (rect->x + rect->w);
+ h2 = r->h;
+ x2 = (r->x +r->w) - w2;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ if ( r->y + r->h > rect->y + rect->y )
+ {
+ w2 = r->w;
+ h2 = (r->y +r->h) - (rect->y + rect->h);
+ x2 = r->x;
+ y2 = rect->y + rect->h;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ if ( rect->y > r->y)
+ {
+ w2 = r->w;;
+ h2 = rect->y - r->y;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ }
+ else if (r->x == rect->x && r->y < rect->y)
+ {
+ if (rect->y + rect->h < r->y + r->h)
+ {
+ w2 = r->w;
+ h2 = (r->y +r->h) - (rect->y + rect->h);
+ x2 = r->x;
+ y2 = rect->y + rect->h;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ w2 = r->w;
+ h2 = rect->y - r->y;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ else if (r->y == rect->y && r->x < rect->x)
+ {
+ if (rect->w + rect->x < r->w + r->x)
+ {
+ w2 = (r->x + r->w) - (rect->x + rect->w);
+ h2 = r->h;
+ x2 = rect->x + rect->w;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ w2 = rect->x - r->x;
+ h2 = r->h;;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ else if (r->x < rect->x && r->y < rect->y)
+ {
+ w2 = rect->x - r->x;
+ h2 = r->h;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ w2 = r->w;
+ h2 = rect->y - r->y;
+ x2 = r->x;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ else if (r->x == rect->x && r->y == rect->y)
+ {
+ if (r->w > rect->w )
+ {
+ w2 = r->w - rect->w;
+ h2 = r->h;
+ x2 = rect->x + rect->w;
+ y2 = r->y;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ if (r->h > rect->h )
+ {
+ w2 = r->w;
+ h2 = r->h - rect->h;
+ x2 = r->x;
+ y2 = rect->y + rect->h;
+ r1 = eina_rectangle_new(x2, y2, w2, h2);
+ empty = eina_list_prepend(empty, r1);
+ }
+ }
+ goto start_again;
+ }
+ }
+ return empty;
+}
+
+static Eina_List *
+_eina_rectangle_skyline_list_update_duplicate(Eina_List *empty)
+{
+ Eina_Rectangle *r, *r1;
+ Eina_List *l, *l1, *l2;
+
+start_again:
+ EINA_LIST_FOREACH(empty, l, r)
+ {
+ l1 = eina_list_next(l);
+ EINA_LIST_FOREACH(l1, l2, r1)
+ {
+ if ((r->x <= r1->x) && (r->y <= r1->y) && (r->x + r->w >= r1->x + r1->w) && (r->y + r->h >= r1->y + r1->h))
+ {
+ empty = eina_list_remove_list(empty, l2);
+ goto start_again;
+ }
+ else if ((r->x >= r1->x) && (r->y >= r1->y) && (r->x + r->w <= r1->x + r1->w) && (r->y + r->h <= r1->y + r1->h))
+ {
+ empty = eina_list_remove_list(empty, l);
+ goto start_again;
+ }
+ }
+ }
+ return empty;
+}
+
/**
* @endcond
*/
new->h = h;
new->bucket = NULL;
new->bucket_count = 0;
+ new->eina_rectangle_compare_func = _eina_rectangle_cmp;
+ new->type = Eina_Packing_Ascending;
EINA_MAGIC_SET(new, EINA_RECTANGLE_POOL_MAGIC);
DBG("pool=%p, size=(%d, %d)", new, w, h);
eina_rectangle_pool_free(Eina_Rectangle_Pool *pool)
{
Eina_Rectangle_Alloc *del;
+ Eina_List *l;
+ Eina_Rectangle *r;
EINA_SAFETY_ON_NULL_RETURN(pool);
DBG("pool=%p, size=(%d, %d), references=%u",
pool, pool->w, pool->h, pool->references);
+ EINA_LIST_FOREACH(pool->empty, l, r)
+ {
+ eina_rectangle_free(r);
+ pool->empty = eina_list_remove_list(pool->empty, l);
+ }
while (pool->head)
{
del = (Eina_Rectangle_Alloc *)pool->head;
if (!pool->sorted)
{
pool->empty =
- eina_list_sort(pool->empty, 0, EINA_COMPARE_CB(_eina_rectangle_cmp));
+ eina_list_sort(pool->empty, 0, pool->eina_rectangle_compare_func);
pool->sorted = EINA_TRUE;
}
- pool->empty = _eina_rectangle_empty_space_find(pool->empty, w, h, &x, &y);
+ if (pool->type == Eina_Packing_Bottom_Left_Skyline_Improved)
+ pool->empty = _eina_rectangle_skyline_list_update_duplicate(pool->empty);
+ pool->empty = _eina_rectangle_empty_space_find(pool->empty, pool->type, w, h, &x, &y);
if (x == -1)
return NULL;
rect = (Eina_Rectangle *)(new + 1);
eina_rectangle_coords_from(rect, x, y, w, h);
+ if (pool->type == Eina_Packing_Bottom_Left_Skyline_Improved)
+ pool->empty = _eina_rectangle_skyline_list_update(pool->empty, rect);
+
pool->head = eina_inlist_prepend(pool->head, EINA_INLIST_GET(new));
pool->references++;
eina_rectangle_pool_release(Eina_Rectangle *rect)
{
Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1;
+ Eina_Rectangle_Alloc *new;
Eina_Rectangle *r;
+ Eina_Rectangle *match;
EINA_SAFETY_ON_NULL_RETURN(rect);
r = eina_rectangle_new(rect->x, rect->y, rect->w, rect->h);
if (r)
{
- era->pool->empty = _eina_rectangle_merge_list(era->pool->empty, r);
- era->pool->sorted = EINA_FALSE;
+ if (era->pool->type == Eina_Packing_Bottom_Left_Skyline_Improved)
+ {
+ era->pool->empty = _eina_rectangle_skyline_merge_list(era->pool->empty, r);
+ era->pool->empty = _eina_rectangle_skyline_list_update_duplicate(era->pool->empty);
+ EINA_INLIST_FOREACH(era->pool->head, new)
+ {
+ match =(Eina_Rectangle *) (new + 1);
+ if (match)
+ era->pool->empty = _eina_rectangle_skyline_list_update(era->pool->empty, match);
+ }
+ }
+ else
+ era->pool->empty = _eina_rectangle_merge_list(era->pool->empty, era->pool->type, r);
+ era->pool->sorted = EINA_FALSE;
}
if (era->pool->bucket_count < BUCKET_THRESHOLD)
}
EAPI void
+eina_rectangle_pool_packing_set(Eina_Rectangle_Pool *pool, Eina_Rectangle_Packing type)
+{
+ EINA_MAGIC_CHECK_RECTANGLE_POOL(pool);
+ EINA_SAFETY_ON_NULL_RETURN(pool);
+
+ DBG("type=%d pool=%p, size=(%d, %d), references=%u",
+ type, pool, pool->w, pool->h, pool->references);
+ pool->type =type;
+
+ switch (type)
+ {
+ case Eina_Packing_Ascending:
+ pool->eina_rectangle_compare_func = _eina_rectangle_cmp_asc;
+ break;
+ case Eina_Packing_Descending:
+ pool->eina_rectangle_compare_func = _eina_rectangle_cmp;
+ break;
+ default:
+ pool->eina_rectangle_compare_func = _eina_rectangle_cmp_bl;
+ }
+}
+
+EAPI void
eina_rectangle_pool_data_set(Eina_Rectangle_Pool *pool, const void *data)
{
EINA_MAGIC_CHECK_RECTANGLE_POOL(pool);
*/
typedef struct _Eina_Rectangle_Pool Eina_Rectangle_Pool;
+/**
+ * @typedef Eina_Rectangle_Pool_Type
+ * Type for an Eina Pool based on packing algorithm.
+ * @since 1.11
+ */
+typedef enum {
+ Eina_Packing_Descending, /**< Current */
+ Eina_Packing_Ascending, /**< sorting in assending order */
+ Eina_Packing_Bottom_Left, /**< sorting in bottemleft fasion */
+ Eina_Packing_Bottom_Left_Skyline, /**< bottemleft skyline */
+ Eina_Packing_Bottom_Left_Skyline_Improved /**< optimized bottemleft skyline */
+} Eina_Rectangle_Packing;
+
static inline int eina_spans_intersect(int c1, int l1, int c2, int l2) EINA_WARN_UNUSED_RESULT;
static inline Eina_Bool eina_rectangle_is_empty(const Eina_Rectangle *r) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
static inline void eina_rectangle_coords_from(Eina_Rectangle *r, int x, int y, int w, int h) EINA_ARG_NONNULL(1);
*/
EAPI void eina_rectangle_free(Eina_Rectangle *rect) EINA_ARG_NONNULL(1);
+/**
+ * @brief Sets the type of given rectangle pool.
+ *
+ * @param pool The rectangle pool for which type is to be set.
+ *
+ * This function sets @p type of @p pool.
+ * @see Eina_Rectangle_Packing
+ * @since 1.11
+ */
+EAPI void eina_rectangle_pool_packing_set(Eina_Rectangle_Pool *pool,Eina_Rectangle_Packing type) EINA_ARG_NONNULL(1);
+
#include "eina_inline_rectangle.x"
/**
#define MIN_ATLAS_ALLOC 16
#define MAX_ATLAS_ALLOC 1024
-#define DEF_ATLAS_ALLOC 1024
+#define DEF_ATLAS_ALLOC 256
#define MIN_ATLAS_ALLOC_ALPHA 16
#define MAX_ATLAS_ALLOC_ALPHA 4096
-#define DEF_ATLAS_ALLOC_ALPHA 4096
+#define DEF_ATLAS_ALLOC_ALPHA 512
#define MAX_ATLAS_W 512
#define DEF_ATLAS_W 512
#define MAX_ATLAS_H 512
#define DEF_ATLAS_H 512
-#define MIN_ATLAS_SLOT 16
-#define MAX_ATLAS_SLOT 512
-#define DEF_ATLAS_SLOT 16
-
struct {
struct {
int max;
int max_alloc_alpha_size;
int max_w;
int max_h;
- int slot_size;
} atlas;
} tune;
} info;
struct {
Eina_List *whole;
- Eina_List *atlas[33][6];
+ Eina_List *atlas[6];
} tex;
Eina_Hash *native_pm_hash;
int checked_out;
} dyn;
Eina_List *allocations;
+ Eina_Rectangle_Pool *eina_pool;
Eina_Bool whole : 1;
Eina_Bool render : 1;
Eina_Bool native : 1;
Evas_Engine_GL_Context *gc;
Evas_GL_Image *im;
Evas_GL_Texture_Pool *pt, *ptu, *ptv, *ptuv, *ptt;
- Evas_GL_Texture_Alloca *apt, *aptt;
RGBA_Font_Glyph *fglyph;
int x, y, w, h;
int tx, ty;
} double_buffer;
Eina_List *targets;
+ Eina_Rectangle *apt, *aptt;
Eina_Bool alpha : 1;
Eina_Bool dyn : 1;
shared->info.tune.atlas.max_alloc_alpha_size = DEF_ATLAS_ALLOC_ALPHA;
shared->info.tune.atlas.max_w = DEF_ATLAS_W;
shared->info.tune.atlas.max_h = DEF_ATLAS_H;
- shared->info.tune.atlas.slot_size = DEF_ATLAS_SLOT;
// per gpu hacks. based on impirical measurement of some known gpu's
s = (const char *)glGetString(GL_RENDERER);
GETENVOPT("EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE", atlas.max_alloc_alpha_size, MIN_ATLAS_ALLOC_ALPHA, MAX_ATLAS_ALLOC_ALPHA);
GETENVOPT("EVAS_GL_ATLAS_MAX_W", atlas.max_w, 0, MAX_ATLAS_W);
GETENVOPT("EVAS_GL_ATLAS_MAX_H", atlas.max_h, 0, MAX_ATLAS_H);
- GETENVOPT("EVAS_GL_ATLAS_SLOT_SIZE", atlas.slot_size, MIN_ATLAS_SLOT, MAX_ATLAS_SLOT);
s = (const char *)getenv("EVAS_GL_GET_PROGRAM_BINARY");
if (s)
{
"EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
"EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
"EVAS_GL_ATLAS_MAX_W x EVAS_GL_ATLAS_MAX_H: %i x %i\n"
- "EVAS_GL_ATLAS_SLOT_SIZE: %i\n"
,
(int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
(int)shared->info.max_texture_units,
(int)shared->info.tune.pipes.max,
(int)shared->info.tune.atlas.max_alloc_size,
(int)shared->info.tune.atlas.max_alloc_alpha_size,
- (int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h,
- (int)shared->info.tune.atlas.slot_size
+ (int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h
);
glDisable(GL_DEPTH_TEST);
evas_gl_common_image_free(gc->shared->images->data);
}
- for (i = 0; i < 33; i++)
+ for (j = 0; j < 6; j++)
{
- for (j = 0; j < 3; j++)
- {
- EINA_LIST_FOREACH(gc->shared->tex.atlas[i][j], l, pt)
- evas_gl_texture_pool_empty(pt);
- eina_list_free(gc->shared->tex.atlas[i][j]);
- }
+ EINA_LIST_FOREACH(gc->shared->tex.atlas[j], l, pt)
+ evas_gl_texture_pool_empty(pt);
+ eina_list_free(gc->shared->tex.atlas[j]);
}
EINA_LIST_FOREACH(gc->shared->tex.whole, l, pt)
evas_gl_texture_pool_empty(pt);
*h = _nearest_pow2(*h);
}
-static int
-_tex_round_slot(Evas_Engine_GL_Context *gc, int h)
-{
- if (!gc->shared->info.tex_npo2)
- h = _nearest_pow2(h);
- return (h + gc->shared->info.tune.atlas.slot_size - 1) /
- gc->shared->info.tune.atlas.slot_size;
-}
static int
_tex_format_index(GLuint format)
if (!no_rounding)
{
- h = _tex_round_slot(gc, h) * gc->shared->info.tune.atlas.slot_size;
_tex_adjust(gc, &w, &h);
}
pt->gc = gc;
pt->format = format;
pt->dataformat = GL_UNSIGNED_BYTE;
pt->references = 0;
+ pt->eina_pool = eina_rectangle_pool_new(w, h);
glGenTextures(1, &(pt->texture));
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (!ok)
{
glDeleteTextures(1, &(pt->texture));
+ if (pt->eina_pool)
+ eina_rectangle_pool_free(pt->eina_pool);
free(pt);
return NULL;
}
return pt;
}
-static Evas_GL_Texture_Alloca *
-_pool_tex_define(Evas_GL_Texture_Pool *pt, int lastx, int w, int *u, Eina_List *l)
+static Eina_Rectangle *
+_pool_tex_alloc(Evas_GL_Texture_Pool *pt, int w, int h, int *u, int *v)
{
- Evas_GL_Texture_Alloca *napt;
-
- *u = lastx;
-
- napt = malloc(sizeof (Evas_GL_Texture_Alloca));
- if (!napt) return NULL;
-
- napt->tex = NULL;
- napt->x = lastx;
- napt->w = w;
-
- if (l == NULL)
- pt->allocations = eina_list_append(pt->allocations, napt);
- else
- pt->allocations = eina_list_prepend_relative_list(pt->allocations, napt, l);
-
- return napt;
-}
-
-static Evas_GL_Texture_Alloca *
-_pool_tex_alloc(Evas_GL_Texture_Pool *pt, int w, int h EINA_UNUSED, int *u, int *v)
-{
- Evas_GL_Texture_Alloca *apt;
- Eina_List *l;
- int lastx = 0;
-
- *v = 0;
-
- EINA_LIST_FOREACH(pt->allocations, l, apt)
+ Eina_Rectangle *r;
+ r = eina_rectangle_pool_request( pt->eina_pool, w, h);
+ if (r)
{
- if (apt->x - lastx >= w)
- return _pool_tex_define(pt, lastx, w, u, l);
-
- lastx = apt->x + apt->w;
+ *v = r->y;
+ *u = r->x;
+ pt->allocations = eina_list_prepend(pt->allocations, r);
}
- if (pt->w - lastx >= w)
- return _pool_tex_define(pt, lastx, w, u, NULL);
-
- return NULL;
+ return r;
}
static Evas_GL_Texture_Pool *
_pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h,
GLenum intformat, GLenum format, int *u, int *v,
- Evas_GL_Texture_Alloca **apt, int atlas_w)
+ Eina_Rectangle **apt, int atlas_w)
{
Evas_GL_Texture_Pool *pt = NULL;
Eina_List *l;
- int th, th2;
+ int th2;
+ int pool_h;
if (atlas_w > gc->shared->info.max_texture_size)
atlas_w = gc->shared->info.max_texture_size;
pt = _pool_tex_new(gc, w, h, intformat, format);
if (!pt) return NULL;
gc->shared->tex.whole = eina_list_prepend(gc->shared->tex.whole, pt);
- pt->slot = -1;
pt->fslot = -1;
pt->whole = 1;
*apt = _pool_tex_alloc(pt, w, h, u, v);
return pt;
}
- th = _tex_round_slot(gc, h);
th2 = _tex_format_index(intformat);
- EINA_LIST_FOREACH(gc->shared->tex.atlas[th][th2], l, pt)
+ EINA_LIST_FOREACH(gc->shared->tex.atlas[th2], l, pt)
{
if ((*apt = _pool_tex_alloc(pt, w, h, u, v)) != NULL)
{
- gc->shared->tex.atlas[th][th2] =
- eina_list_remove_list(gc->shared->tex.atlas[th][th2], l);
- gc->shared->tex.atlas[th][th2] =
- eina_list_prepend(gc->shared->tex.atlas[th][th2], pt);
+ gc->shared->tex.atlas[th2] =
+ eina_list_remove_list(gc->shared->tex.atlas[th2], l);
+ gc->shared->tex.atlas[th2] =
+ eina_list_prepend(gc->shared->tex.atlas[th2], pt);
return pt;
}
}
+ pool_h = atlas_w;
+ if ( h > pool_h || w > atlas_w )
+ {
+ atlas_w = gc->shared->info.tune.atlas.max_w;
+ pool_h = gc->shared->info.tune.atlas.max_h;
+ }
+ pt = _pool_tex_new(gc, atlas_w, pool_h, intformat, format);
- pt = _pool_tex_new(gc, atlas_w, h, intformat, format);
if (!pt) return NULL;
- gc->shared->tex.atlas[th][th2] =
- eina_list_prepend(gc->shared->tex.atlas[th][th2], pt);
- pt->slot = th;
+ gc->shared->tex.atlas[th2] =
+ eina_list_prepend(gc->shared->tex.atlas[th2], pt);
pt->fslot = th2;
*apt = _pool_tex_alloc(pt, w, h, u, v);
default:
/* This need to be adjusted if we do something else than strip allocation */
w = im->cache_entry.w + TEX_HREP + 2; /* one pixel stop gap and two pixels for the border */
- h = im->cache_entry.h + TEX_VREP; /* only one added border for security down */
+ h = im->cache_entry.h + TEX_VREP + 2; /* only one added border for security down */
}
tex->pt = _pool_tex_find(gc, w, h,
evas_gl_common_texture_light_free(tex);
return NULL;
}
- tex->apt->tex = tex;
tex->x = u + 1;
tex->y = v + yoffset;
pt->dataformat = GL_UNSIGNED_BYTE;
pt->render = 1;
pt->references = 0;
+ pt->eina_pool = eina_rectangle_pool_new(w, h);
#ifdef GL_GLES
# ifndef GL_FRAMEBUFFER
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
if (!ok)
{
glDeleteTextures(1, &(pt->texture));
+ if (pt->eina_pool)
+ eina_rectangle_pool_free(pt->eina_pool);
free(pt);
return NULL;
}
pt->dataformat = GL_UNSIGNED_BYTE;
pt->references = 0;
pt->native = 1;
+ pt->eina_pool = eina_rectangle_pool_new(w, h);
glGenTextures(1, &(pt->texture));
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(im->native.target, pt->texture);
pt = calloc(1, sizeof(Evas_GL_Texture_Pool));
if (!pt) return NULL;
- h = _tex_round_slot(gc, h) * gc->shared->info.tune.atlas.slot_size;
_tex_adjust(gc, &w, &h);
pt->gc = gc;
pt->w = w;
pt->dataformat = GL_UNSIGNED_BYTE;
pt->render = 1;
pt->references = 0;
+ pt->eina_pool = eina_rectangle_pool_new(w, h);
texinfo.d.num++;
texinfo.d.pix += pt->w * pt->h;
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDeleteTextures(1, &(pt->texture));
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+ if (pt->eina_pool)
+ eina_rectangle_pool_free(pt->eina_pool);
free(pt);
return NULL;
}
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDeleteTextures(1, &(pt->texture));
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+ if (pt->eina_pool)
+ eina_rectangle_pool_free(pt->eina_pool);
free(pt);
return NULL;
#endif
void
evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt)
{
- Evas_GL_Texture_Alloca *apt;
+ Eina_Rectangle *apt;
if (!pt->gc) return;
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
pt->fb = 0;
}
-
- EINA_LIST_FREE(pt->allocations, apt)
- free(apt);
+ EINA_LIST_FREE(pt->allocations, apt)
+ eina_rectangle_pool_release(apt);
pt->texture = 0;
pt->gc = NULL;
pt->w = 0;
pt->gc->shared->tex.whole =
eina_list_remove(pt->gc->shared->tex.whole, pt);
else
- pt->gc->shared->tex.atlas [pt->slot][pt->fslot] =
- eina_list_remove(pt->gc->shared->tex.atlas[pt->slot][pt->fslot], pt);
+ pt->gc->shared->tex.atlas [pt->fslot] =
+ eina_list_remove(pt->gc->shared->tex.atlas[pt->fslot], pt);
}
evas_gl_texture_pool_empty(pt);
+ if (pt->eina_pool)
+ eina_rectangle_pool_free(pt->eina_pool);
free(pt);
}
pt_link(Evas_Engine_GL_Context *gc, Evas_GL_Texture_Pool *pt)
{
gc->shared->tex.whole = eina_list_prepend(gc->shared->tex.whole, pt);
- pt->slot = -1;
pt->fslot = -1;
pt->whole = 1;
pt->references++;
1, 1,
fmt, tex->pt->dataformat,
(unsigned char *) im->image.data + (((im->cache_entry.h - 1) * im->cache_entry.w) + (im->cache_entry.w - 1)) * bytes_count);
+ //2D packing
+ // ---
+ // xxx
+ // xxx
+ _tex_sub_2d(tex->gc, tex->x, tex->y - 1,
+ im->cache_entry.w, 1,
+ fmt, tex->pt->dataformat,
+ im->image.data);
+ // o
+ // xxx
+ // xxx
+ _tex_sub_2d(tex->gc, tex->x - 1, tex->y - 1,
+ 1, 1,
+ fmt, tex->pt->dataformat,
+ im->image.data);
+ // o
+ // xxx
+ // xxx
+ _tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y - 1,
+ 1, 1,
+ fmt, tex->pt->dataformat,
+ im->image.data + (im->cache_entry.w - 1) * bytes_count);
if (tex->gc->shared->info.unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, im->cache_entry.w);
int lformat;
tex->pt->allocations = eina_list_remove(tex->pt->allocations, tex->apt);
- pt_unref(tex->pt);
- tex->alpha = im->cache_entry.flags.alpha;
+ if (tex->apt)
+ eina_rectangle_pool_release(tex->apt);
lformat = _evas_gl_texture_search_format(tex->alpha, tex->gc->shared->info.bgra, im->cache_entry.space);
// FIXME: why a 'render' new here ??? Should already have been allocated, quite a weird path.
tex->gc->shared->info.tune.atlas.max_alloc_size);
if (!tex->ptt)
goto upload;
- tex->aptt->tex = tex;
tex->tx = u + 1;
tex->ty = v;
if (tex->pt)
{
tex->pt->allocations = eina_list_remove(tex->pt->allocations, tex->apt);
- free(tex->apt);
+ if (tex->apt)
+ eina_rectangle_pool_release(tex->apt);
tex->apt = NULL;
pt_unref(tex->pt);
}
if (tex->ptt)
{
- tex->ptt->allocations = eina_list_remove(tex->ptt->allocations, tex->aptt);
- free(tex->aptt);
+ tex->ptt->allocations = eina_list_remove(tex->pt->allocations, tex->aptt);
+ if (tex->aptt)
+ eina_rectangle_pool_release(tex->aptt);
tex->aptt = NULL;
pt_unref(tex->ptt);
}
evas_gl_common_texture_light_free(tex);
return NULL;
}
- tex->apt->tex = tex;
tex->x = u + 1;
tex->y = v;
tex->pt->references++;
return NULL;
}
gc->shared->tex.whole = eina_list_prepend(gc->shared->tex.whole, tex->pt);
- tex->pt->slot = -1;
tex->pt->fslot = -1;
tex->pt->whole = 1;
tex->pt->references++;