diff --git a/AUTHORS b/AUTHORS index d40a8fdb88..000723eb40 100644 --- a/AUTHORS +++ b/AUTHORS @@ -130,6 +130,7 @@ Paulo Cavalcanti Jean-Philippe Andre Yury Usischev Youngbok Shin +Rajeev Ranjan (Rajeev) Ecore ----- diff --git a/src/lib/eina/eina_rectangle.c b/src/lib/eina/eina_rectangle.c index 5ae680b7df..972755fad3 100644 --- a/src/lib/eina/eina_rectangle.c +++ b/src/lib/eina/eina_rectangle.c @@ -61,9 +61,13 @@ struct _Eina_Rectangle_Pool 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; @@ -109,18 +113,40 @@ static int _eina_rectangle_log_dom = -1; #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 Eina_List * -_eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle *r) +static int +_eina_rectangle_cmp_asc(const void *data1, const void *data2) { - Eina_Rectangle *match; + 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_Packing type, Eina_Rectangle *r) +{ + Eina_Rectangle *match, *r1; Eina_List *l; int xw; int yh; + int x2 ,y2 ,w2 ,h2; if (r->w == 0 || r->h == 0) { @@ -164,6 +190,34 @@ start_again: r = match; + 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; } } @@ -172,7 +226,7 @@ start_again: } 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; @@ -211,7 +265,7 @@ _eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y) /* 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; @@ -221,16 +275,21 @@ _eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y) 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 */ } @@ -243,6 +302,216 @@ _eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y) 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 */ @@ -376,6 +645,8 @@ eina_rectangle_pool_new(int w, int h) 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); @@ -387,10 +658,17 @@ EAPI void 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; @@ -440,11 +718,13 @@ eina_rectangle_pool_request(Eina_Rectangle_Pool *pool, int w, int h) 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; @@ -466,6 +746,9 @@ eina_rectangle_pool_request(Eina_Rectangle_Pool *pool, int w, int h) 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++; @@ -482,7 +765,9 @@ EAPI void 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); @@ -498,8 +783,20 @@ eina_rectangle_pool_release(Eina_Rectangle *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) @@ -531,6 +828,29 @@ eina_rectangle_pool_get(Eina_Rectangle *rect) return era->pool; } +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) { diff --git a/src/lib/eina/eina_rectangle.h b/src/lib/eina/eina_rectangle.h index d3e2443a95..8f5eead1de 100644 --- a/src/lib/eina/eina_rectangle.h +++ b/src/lib/eina/eina_rectangle.h @@ -61,6 +61,19 @@ typedef struct _Eina_Rectangle */ 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); @@ -238,6 +251,17 @@ EAPI Eina_Rectangle *eina_rectangle_new(int x, int y, int w, int h) EINA_MALLOC */ 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" /** diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 4e45df0089..da30a8eddc 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -391,11 +391,11 @@ struct _Evas_GL_Shared #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 @@ -403,10 +403,6 @@ struct _Evas_GL_Shared #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; @@ -419,14 +415,13 @@ struct _Evas_GL_Shared 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; @@ -572,6 +567,7 @@ struct _Evas_GL_Texture_Pool int checked_out; } dyn; Eina_List *allocations; + Eina_Rectangle_Pool *eina_pool; Eina_Bool whole : 1; Eina_Bool render : 1; Eina_Bool native : 1; @@ -590,7 +586,6 @@ struct _Evas_GL_Texture 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; @@ -604,6 +599,7 @@ struct _Evas_GL_Texture } double_buffer; Eina_List *targets; + Eina_Rectangle *apt, *aptt; Eina_Bool alpha : 1; Eina_Bool dyn : 1; diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 21d14120f4..1f4db9474d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -674,7 +674,6 @@ evas_gl_common_context_new(void) 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); @@ -711,7 +710,6 @@ evas_gl_common_context_new(void) 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) { @@ -775,7 +773,6 @@ evas_gl_common_context_new(void) "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, @@ -793,8 +790,7 @@ evas_gl_common_context_new(void) (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); @@ -939,14 +935,11 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc) 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); diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c index 29a559493f..87c1346ae3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_texture.c +++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c @@ -172,14 +172,6 @@ _tex_adjust(Evas_Engine_GL_Context *gc, int *w, int *h) *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) @@ -314,7 +306,6 @@ _pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, GLenum intformat, GLenum if (!no_rounding) { - h = _tex_round_slot(gc, h) * gc->shared->info.tune.atlas.slot_size; _tex_adjust(gc, &w, &h); } pt->gc = gc; @@ -324,6 +315,7 @@ _pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, GLenum intformat, GLenum 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__, ""); @@ -343,6 +335,8 @@ _pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, GLenum intformat, GLenum if (!ok) { glDeleteTextures(1, &(pt->texture)); + if (pt->eina_pool) + eina_rectangle_pool_free(pt->eina_pool); free(pt); return NULL; } @@ -366,59 +360,30 @@ _pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, GLenum intformat, GLenum 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; @@ -429,32 +394,35 @@ _pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h, 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); @@ -495,7 +463,7 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im) 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, @@ -508,7 +476,6 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im) evas_gl_common_texture_light_free(tex); return NULL; } - tex->apt->tex = tex; tex->x = u + 1; tex->y = v + yoffset; @@ -542,6 +509,7 @@ _pool_tex_render_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, in 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 @@ -587,6 +555,8 @@ _pool_tex_render_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, in if (!ok) { glDeleteTextures(1, &(pt->texture)); + if (pt->eina_pool) + eina_rectangle_pool_free(pt->eina_pool); free(pt); return NULL; } @@ -630,6 +600,7 @@ _pool_tex_native_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, in 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); @@ -698,7 +669,6 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i 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; @@ -708,6 +678,7 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i 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; @@ -744,6 +715,8 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i 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; } @@ -788,6 +761,8 @@ error: 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 @@ -796,7 +771,7 @@ error: void evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt) { - Evas_GL_Texture_Alloca *apt; + Eina_Rectangle *apt; if (!pt->gc) return; @@ -858,9 +833,8 @@ evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt) 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; @@ -881,10 +855,12 @@ pt_unref(Evas_GL_Texture_Pool *pt) 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); } @@ -892,7 +868,6 @@ static void 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++; @@ -1010,6 +985,28 @@ evas_gl_common_texture_upload(Evas_GL_Texture *tex, RGBA_Image *im, unsigned int 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); @@ -1083,8 +1080,8 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) 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. @@ -1238,7 +1235,6 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) 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; @@ -1327,14 +1323,16 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force EINA_UNUSED) 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); } @@ -1366,7 +1364,6 @@ evas_gl_common_texture_alpha_new(Evas_Engine_GL_Context *gc, DATA8 *pixels, evas_gl_common_texture_light_free(tex); return NULL; } - tex->apt->tex = tex; tex->x = u + 1; tex->y = v; tex->pt->references++; @@ -1435,7 +1432,6 @@ evas_gl_common_texture_yuv_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigne 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++;