summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Ranjan <rajeev.r@samsung.com>2014-06-19 14:35:37 +0200
committerCedric BAIL <c.bail@partner.samsung.com>2014-06-19 16:48:45 +0200
commitbd65b5db5ddcada0255c5ccbaaa1280279ea5679 (patch)
treee5e733fd84babdcc9a3cbfc17af666401271302b
parent2cebf6785eed26e3f4eda7b6d3d77954a19d3bfc (diff)
downloadefl-bd65b5db5ddcada0255c5ccbaaa1280279ea5679.tar.gz
evas: improvement of Eina Rectangle Pool and integration with Evas GL backend.
Summary: This patch introduce various new logic for packing/unpacking of Eina Rectangle in a pool. It is then used by Evas GL backend texture allocation to improve how efficiently we pack image in texture atlas. This lead to improved memory usage and reduced power consumption with usually a more stable higher FPS (as it use less texture to do the same task, their is less texture switch, so saving memory and speed at the same time). This patch was developped on Cedric's suggestions to optimize the packing logic using Skyline algorithm. This patch is based on master and is a new submission for earlier phab link https://phab.enlightenment.org/D774. Signed-off-by: Sanjay Nirankari <sanjay.n1@samsung.com> Signed-off-by: Rajeev Ranjan <rajeev.r@samsung.com> Signed-off-by: Sreedeep Moulik <sreedeep.m@samsung.com> Reviewers: cedric, raster CC: wonsik, jpeg, sreedeep.m, sanjay, govi Differential Revision: https://phab.enlightenment.org/D1063 Signed-off-by: Cedric BAIL <c.bail@partner.samsung.com>
-rw-r--r--AUTHORS1
-rw-r--r--src/lib/eina/eina_rectangle.c342
-rw-r--r--src/lib/eina/eina_rectangle.h24
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_common.h14
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_context.c17
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_texture.c154
6 files changed, 441 insertions, 111 deletions
diff --git a/AUTHORS b/AUTHORS
index d40a8fdb88..000723eb40 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -130,6 +130,7 @@ Paulo Cavalcanti <paulo.cavalcanti@linux.intel.com>
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
-----
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 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)
{
@@ -166,13 +192,41 @@ start_again:
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;
@@ -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)
@@ -532,6 +829,29 @@ eina_rectangle_pool_get(Eina_Rectangle *rect)
}
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);
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++;