1. gustavo';s fuzzy rect implementation for updates. fixed so del's work,

tuned for best performance on my core2 duo desktop - for now. will check
more. also make the yuv colorspace code be a bit more robust and fix leak in
gl engine with shaders.


SVN revision: 30192
This commit is contained in:
Carsten Haitzler 2007-06-02 15:30:59 +00:00
parent a4c53227fb
commit a730b4be5d
10 changed files with 987 additions and 44 deletions

View File

@ -1,8 +1,723 @@
#include "evas_common.h"
#ifdef EVAS_RECT_SPLIT
static const list_node_t list_node_zeroed = {.next = NULL};
static const list_t list_zeroed = {.head = NULL, .tail = NULL};
inline void
rect_init(rect_t *r, int x, int y, int w, int h)
{
r->area = w * h;
r->left = x;
r->top = y;
r->right = x + w;
r->bottom = y + h;
r->width = w;
r->height = h;
}
void
rect_print(const rect_t r)
{
printf("<rect(%d, %d, %d, %d)>", r.left, r.top, r.width, r.height);
}
void
rect_list_print(const list_t rects)
{
list_node_t *node;
int len;
len = 0;
for (node = rects.head; node != NULL; node = node->next) len++;
printf("[");
for (node = rects.head; node != NULL; node = node->next)
{
rect_print(((rect_node_t *)node)->rect);
if (node->next)
{
putchar(',');
if (len < 4) putchar(' ');
else
{
putchar('\n');
putchar(' ');
}
}
}
printf("]\n");
}
inline void
rect_list_append_node(list_t *rects, list_node_t *node)
{
if (rects->tail)
{
rects->tail->next = node;
rects->tail = node;
}
else
{
rects->head = node;
rects->tail = node;
}
}
inline void
rect_list_append(list_t *rects, const rect_t r)
{
rect_node_t *rect_node;
rect_node = malloc(sizeof(rect_node_t));
rect_node->rect = r;
rect_node->_lst = list_node_zeroed;
rect_list_append_node(rects, (list_node_t *)rect_node);
}
inline void
rect_list_append_xywh(list_t *rects, int x, int y, int w, int h)
{
rect_t r;
rect_init(&r, x, y, w, h);
rect_list_append(rects, r);
}
inline void
rect_list_concat(list_t *rects, list_t *other)
{
if (!other->head)
return;
if (rects->tail)
{
rects->tail->next = other->head;
rects->tail = other->tail;
}
else
{
rects->head = other->head;
rects->tail = other->tail;
}
*other = list_zeroed;
}
inline list_node_t *
rect_list_unlink_next(list_t *rects, list_node_t *parent_node)
{
list_node_t *node;
if (parent_node)
{
node = parent_node->next;
parent_node->next = node->next;
}
else
{
node = rects->head;
rects->head = node->next;
}
if (rects->tail == node) rects->tail = parent_node;
*node = list_node_zeroed;
return node;
}
inline void
rect_list_del_next(list_t *rects, list_node_t *parent_node)
{
list_node_t *node;
node = rect_list_unlink_next(rects, parent_node);
free(node);
}
void
rect_list_clear(list_t *rects)
{
list_node_t *node;
node = rects->head;
while (node)
{
list_node_t *aux;
aux = node->next;
free(node);
node = aux;
}
*rects = list_zeroed;
}
static inline void
_calc_intra_rect_area(const rect_t a, const rect_t b, int *width, int *height)
{
int max_left, min_right, max_top, min_bottom;
if (a.left < b.left) max_left = b.left;
else max_left = a.left;
if (a.right < b.right) min_right = a.right;
else min_right = b.right;
*width = min_right - max_left;
if (a.top < b.top) max_top = b.top;
else max_top = a.top;
if (a.bottom < b.bottom) min_bottom = a.bottom;
else min_bottom = b.bottom;
*height = min_bottom - max_top;
}
static inline void
_split_strict(list_t *dirty, const rect_t current, rect_t r)
{
int h_1, h_2, w_1, w_2;
h_1 = current.top - r.top;
h_2 = r.bottom - current.bottom;
w_1 = current.left - r.left;
w_2 = r.right - current.right;
if (h_1 > 0)
{
/* .--.r (b) .---.r2
* | | | |
* .-------.cur (a) .---.r '---'
* | | | | -> | | +
* | `--' | `---'
* `-------'
*/
rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1);
r.height -= h_1;
r.top = current.top;
}
if (h_2 > 0)
{
/* .-------.cur (a)
* | .---. | .---.r
* | | | | -> | |
* `-------' `---' + .---.r2
* | | | |
* `---'r (b) `---'
*/
rect_list_append_xywh(dirty, r.left, current.bottom, r.width, h_2);
r.height -= h_2;
}
if (w_1 > 0)
{
/* (b) r .----.cur (a)
* .--|-. | .--.r2 .-.r
* | | | | -> | | + | |
* `--|-' | `--' `-'
* `----'
*/
rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height);
/* not necessary to keep these, r (b) will be destroyed */
/* r.width -= w_1; */
/* r.left = current.left; */
}
if (w_2 > 0)
{
/* .----.cur (a)
* | |
* | .-|--.r (b) .-.r .--.r2
* | | | | -> | | + | |
* | `-|--' `-' `--'
* `----'
*/
rect_list_append_xywh(dirty, current.right, r.top, w_2, r.height);
/* not necessary to keep this, r (b) will be destroyed */
/* r.width -= w_2; */
}
}
void
rect_list_add_split_strict(list_t *rects, list_node_t *node)
{
list_t dirty = list_zeroed;
list_t new_dirty = list_zeroed;
list_node_t *cur_node;
if (!rects->head)
{
rect_list_append_node(rects, node);
return;
}
rect_list_append_node(&dirty, node);
cur_node = rects->head;
while (dirty.head)
{
rect_t current;
if (!cur_node)
{
rect_list_concat(rects, &dirty);
break;
}
current = ((rect_node_t*)cur_node)->rect;
while (dirty.head)
{
int intra_width, intra_height;
rect_t r;
r = ((rect_node_t *)dirty.head)->rect;
_calc_intra_rect_area(r, current, &intra_width, &intra_height);
if ((intra_width == r.width) && (intra_height == r.height))
/* .-------.cur
* | .---.r|
* | | | |
* | `---' |
* `-------'
*/
rect_list_del_next(&dirty, NULL);
else if ((intra_width <= 0) || (intra_height <= 0))
{
/* .---.cur .---.r
* | | | |
* `---+---.r `---+---.cur
* | | | |
* `---' `---'
*/
list_node_t *tmp;
tmp = rect_list_unlink_next(&dirty, NULL);
rect_list_append_node(&new_dirty, tmp);
}
else
{
_split_strict(&new_dirty, current, r);
rect_list_del_next(&dirty, NULL);
}
}
dirty = new_dirty;
new_dirty = list_zeroed;
cur_node = cur_node->next;
}
}
static inline void
_calc_intra_outer_rect_area(const rect_t a, const rect_t b,
rect_t *intra, rect_t *outer)
{
int min_left, max_left, min_right, max_right;
int min_top, max_top, min_bottom, max_bottom;
if (a.left < b.left)
{
max_left = b.left;
min_left = a.left;
}
else
{
max_left = a.left;
min_left = b.left;
}
if (a.right < b.right)
{
min_right = a.right;
max_right = b.right;
}
else
{
min_right = b.right;
max_right = a.right;
}
intra->left = max_left;
intra->right = min_right;
intra->width = min_right - max_left;
outer->left = min_left;
outer->right = max_right;
outer->width = max_right - min_left;
if (a.top < b.top)
{
max_top = b.top;
min_top = a.top;
}
else
{
max_top = a.top;
min_top = b.top;
}
if (a.bottom < b.bottom)
{
min_bottom = a.bottom;
max_bottom = b.bottom;
}
else
{
min_bottom = b.bottom;
max_bottom = a.bottom;
}
intra->top = max_top;
intra->bottom = min_bottom;
intra->height = min_bottom - max_top;
if ((intra->width > 0) && (intra->height > 0))
intra->area = intra->width * intra->height;
else
intra->area = 0;
outer->top = min_top;
outer->bottom = max_bottom;
outer->height = max_bottom - min_top;
outer->area = outer->width * outer->height;
}
enum
{
SPLIT_FUZZY_ACTION_NONE,
SPLIT_FUZZY_ACTION_SPLIT,
SPLIT_FUZZY_ACTION_MERGE
};
static inline int
_split_fuzzy(list_t *dirty, const rect_t a, rect_t *b)
{
int h_1, h_2, w_1, w_2, action;
h_1 = a.top - b->top;
h_2 = b->bottom - a.bottom;
w_1 = a.left - b->left;
w_2 = b->right - a.right;
action = SPLIT_FUZZY_ACTION_NONE;
if (h_1 > 0)
{
/* .--.r (b) .---.r2
* | | | |
* .-------.cur (a) .---.r '---'
* | | | | -> | | +
* | `--' | `---'
* `-------'
*/
rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1);
b->height -= h_1;
b->top = a.top;
action = SPLIT_FUZZY_ACTION_SPLIT;
}
if (h_2 > 0)
{
/* .-------.cur (a)
* | .---. | .---.r
* | | | | -> | |
* `-------' `---' + .---.r2
* | | | |
* `---'r (b) `---'
*/
rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2);
b->height -= h_2;
action = SPLIT_FUZZY_ACTION_SPLIT;
}
if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height))
return SPLIT_FUZZY_ACTION_MERGE;
if (w_1 > 0)
{
/* (b) r .----.cur (a)
* .--|-. | .--.r2 .-.r
* | | | | -> | | + | |
* `--|-' | `--' `-'
* `----'
*/
rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height);
/* not necessary to keep these, r (b) will be destroyed */
/* b->width -= w_1; */
/* b->left = a.left; */
action = SPLIT_FUZZY_ACTION_SPLIT;
}
if (w_2 > 0)
{
/* .----.cur (a)
* | |
* | .-|--.r (b) .-.r .--.r2
* | | | | -> | | + | |
* | `-|--' `-' `--'
* `----'
*/
rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height);
/* not necessary to keep these, r (b) will be destroyed */
/* b->width -= w_2; */
action = SPLIT_FUZZY_ACTION_SPLIT;
}
return action;
}
list_node_t *
rect_list_add_split_fuzzy(list_t *rects, const rect_t r, int accepted_error)
{
list_t dirty = list_zeroed;
list_node_t *old_last;
old_last = rects->tail;
if (!rects->head)
{
rect_list_append(rects, r);
return old_last;
}
rect_list_append(&dirty, r);
while (dirty.head)
{
list_node_t *d_node, *cur_node, *prev_cur_node;
int keep_dirty;
rect_t r;
d_node = rect_list_unlink_next(&dirty, NULL);
r = ((rect_node_t *)d_node)->rect;
prev_cur_node = NULL;
cur_node = rects->head;
keep_dirty = 1;
while (cur_node)
{
int area, action;
rect_t current, intra, outer;
current = ((rect_node_t *)cur_node)->rect;
_calc_intra_outer_rect_area(r, current, &intra, &outer);
area = current.area + r.area - intra.area;
if ((intra.width == r.width) && (intra.height == r.height))
{
/* .-------.cur
* | .---.r|
* | | | |
* | `---' |
* `-------'
*/
keep_dirty = 0;
break;
}
else if ((intra.width == current.width) &&
(intra.height == current.height))
{
/* .-------.r
* | .---.cur
* | | | |
* | `---' |
* `-------'
*/
if (old_last == cur_node)
old_last = prev_cur_node;
cur_node = cur_node->next;
rect_list_del_next(rects, prev_cur_node);
}
else if ((outer.area - area) <= accepted_error)
{
/* .-----------. bounding box (outer)
* |.---. .---.|
* ||cur| |r ||
* || | | ||
* |`---' `---'|
* `-----------'
* merge them, remove both and add merged
*/
rect_node_t *n;
if (old_last == cur_node)
old_last = prev_cur_node;
n = (rect_node_t *)rect_list_unlink_next(rects, prev_cur_node);
n->rect = outer;
rect_list_append_node(&dirty, (list_node_t *)n);
keep_dirty = 0;
break;
}
else if (intra.area <= accepted_error)
{
/* .---.cur .---.r
* | | | |
* `---+---.r `---+---.cur
* | | | |
* `---' `---'
* no split, no merge
*/
prev_cur_node = cur_node;
cur_node = cur_node->next;
}
else
{
/* split is required */
action = _split_fuzzy(&dirty, current, &r);
if (action == SPLIT_FUZZY_ACTION_MERGE)
{
/* horizontal merge is possible: remove both, add merged */
rect_node_t *n;
if (old_last == cur_node)
old_last = prev_cur_node;
n = (rect_node_t *)
rect_list_unlink_next(rects, prev_cur_node);
n->rect.left = outer.left;
n->rect.width = outer.width;
n->rect.right = outer.right;
n->rect.area = outer.width * r.height;
rect_list_append_node(&dirty, (list_node_t *)n);
}
else if (action == SPLIT_FUZZY_ACTION_NONE)
{
/*
* this rect check was totally useless,
* should never happen
*/
/* prev_cur_node = cur_node; */
/* cur_node = cur_node->next; */
printf("Should not get here!\n");
abort();
}
keep_dirty = 0;
break;
}
}
if (keep_dirty) rect_list_append_node(rects, d_node);
else free(d_node);
}
return old_last;
}
static inline void
_calc_outer_rect_area(const rect_t a, const rect_t b, rect_t *outer)
{
int min_left, max_right;
int min_top, max_bottom;
if (a.left < b.left) min_left = a.left;
else min_left = b.left;
if (a.right < b.right) max_right = b.right;
else max_right = a.right;
outer->left = min_left;
outer->right = max_right;
outer->width = max_right - min_left;
if (a.top < b.top) min_top = a.top;
else min_top = b.top;
if (a.bottom < b.bottom) max_bottom = b.bottom;
else max_bottom = a.bottom;
outer->top = min_top;
outer->bottom = max_bottom;
outer->height = max_bottom - min_top;
outer->area = outer->width * outer->height;
}
void
rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error)
{
while (to_merge->head)
{
list_node_t *node, *parent_node;
rect_t r1;
int merged;
r1 = ((rect_node_t *)to_merge->head)->rect;
merged = 0;
parent_node = NULL;
node = rects->head;
while (node != NULL)
{
rect_t r2, outer;
int area;
r2 = ((rect_node_t *)node)->rect;
_calc_outer_rect_area(r1, r2, &outer);
area = r1.area + r2.area; /* intra area is taken as 0 */
if (outer.area - area <= accepted_error)
{
/*
* remove both r1 and r2, create r3
* actually r3 uses r2 instance, saves memory
*/
rect_node_t *n;
n = (rect_node_t *)rect_list_unlink_next(rects, parent_node);
n->rect = outer;
rect_list_append_node(to_merge, (list_node_t *)n);
merged = 1;
break;
}
parent_node = node;
node = node->next;
}
if (!merged)
{
list_node_t *n;
n = rect_list_unlink_next(to_merge, NULL);
rect_list_append_node(rects, n);
}
else
rect_list_del_next(to_merge, NULL);
}
}
void
rect_list_add_split_fuzzy_and_merge(list_t *rects, const rect_t r,
int split_accepted_error,
int merge_accepted_error)
{
list_node_t *n;
n = rect_list_add_split_fuzzy(rects, r, split_accepted_error);
if (n && n->next)
{
list_t to_merge;
/* split list into 2 segments, already merged and to merge */
to_merge.head = n->next;
to_merge.tail = rects->tail;
rects->tail = n;
n->next = NULL;
rect_list_merge_rects(rects, &to_merge, merge_accepted_error);
}
}
#endif /* EVAS_RECT_SPLIT */
#define TILE(tb, x, y) ((tb)->tiles.tiles[((y) * (tb)->tiles.w) + (x)])
#ifdef RECTUPDATE
#elif defined(EVAS_RECT_SPLIT)
#else
static int tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill);
static int tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill);
@ -36,6 +751,8 @@ evas_common_tilebuf_free(Tilebuf *tb)
{
#ifdef RECTUPDATE
evas_common_regionbuf_free(tb->rb);
#elif defined(EVAS_RECT_SPLIT)
rect_list_clear(&tb->rects);
#else
if (tb->tiles.tiles) free(tb->tiles.tiles);
#endif
@ -69,6 +786,25 @@ evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h)
for (i = 0; i < h; i++)
evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i);
return 1;
#elif defined(EVAS_RECT_SPLIT)
rect_t r;
if ((w <= 0) || (h <= 0)) return 0;
RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h);
if ((w <= 0) || (h <= 0)) return 0;
x >>= 1;
y >>= 1;
w += 2;
w >>= 1;
h += 2;
h >>= 1;
rect_init(&r, x, y, w, h);
//fprintf(stderr, "ACCOUNTING: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h);
//testing on my core2 duo desktop - fuzz of 48 is best.
#define FUZZ 48
rect_list_add_split_fuzzy_and_merge(&tb->rects, r, FUZZ * FUZZ, FUZZ * FUZZ);
return 1;
#else
int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy;
int num;
@ -114,6 +850,50 @@ evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h)
for (i = 0; i < h; i++)
evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i);
#elif defined(EVAS_RECT_SPLIT)
list_node_t *lst;
rect_node_t n;
if (!tb->rects.head) return 0;
if ((w <= 0) || (h <= 0)) return 0;
RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h);
if ((w <= 0) || (h <= 0)) return 0;
x += 1;
y += 1;
x >>= 1;
y >>= 1;
w -= 1;
w >>= 1;
h -= 1;
h >>= 1;
if ((w <= 0) || (h <= 0)) return 0;
rect_init(&n.rect, x, y, w, h);
//fprintf(stderr, "ACCOUNTING: del_redraw: %4d,%4d %3dx%3d\n", x, y, w, h);
lst = tb->rects.head;
n._lst = list_node_zeroed;
tb->rects.head = (list_node_t *)&n;
tb->rects.tail = (list_node_t *)&n;
while (lst)
{
list_node_t *tmp;
rect_t r;
tmp = lst->next;
lst->next = NULL;
rect_list_add_split_strict(&tb->rects, lst);
lst = tmp;
}
/* remove deleted rectangle */
rect_list_unlink_next(&tb->rects, NULL);
return 0;
#else
int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy;
int num;
@ -170,6 +950,8 @@ evas_common_tilebuf_clear(Tilebuf *tb)
{
#ifdef RECTUPDATE
evas_common_regionbuf_clear(tb->rb);
#elif defined(EVAS_RECT_SPLIT)
rect_list_clear(&tb->rects);
#else
if (!tb->tiles.tiles) return;
memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile));
@ -181,6 +963,32 @@ evas_common_tilebuf_get_render_rects(Tilebuf *tb)
{
#ifdef RECTUPDATE
return evas_common_regionbuf_rects_get(tb->rb);
#elif defined(EVAS_RECT_SPLIT)
list_node_t *n;
Tilebuf_Rect *rects = NULL;
for (n = tb->rects.head; n != NULL; n = n->next) {
rect_t cur;
Tilebuf_Rect *r;
cur = ((rect_node_t *)n)->rect;
r = malloc(sizeof(Tilebuf_Rect));
r->_list_data.next = NULL;
r->_list_data.prev = NULL;
r->_list_data.last = NULL;
r->x = cur.left << 1;
r->y = cur.top << 1;
r->w = cur.width << 1;
r->h = cur.height << 1;
/* fprintf(stderr, "\tclear: %4d,%4d %3dx%3d\n", */
/* r->x, r->y, r->w, r->h); */
rects = evas_object_list_append(rects, r);
}
return rects;
#else
Tilebuf_Rect *rects = NULL;
Tilebuf_Tile *tbt;
@ -294,6 +1102,8 @@ tilebuf_setup(Tilebuf *tb)
if ((tb->outbuf_w <= 0) || (tb->outbuf_h <= 0)) return;
#ifdef RECTUPDATE
tb->rb = evas_common_regionbuf_new(tb->outbuf_w, tb->outbuf_h);
#elif defined(EVAS_RECT_SPLIT)
tb->rects = list_zeroed;
#else
if (tb->tiles.tiles) free(tb->tiles.tiles);
tb->tiles.tiles = NULL;
@ -314,6 +1124,7 @@ tilebuf_setup(Tilebuf *tb)
}
#ifdef RECTUPDATE
#elif defined(EVAS_RECT_SPLIT)
#else
static int
tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill)

View File

@ -531,6 +531,58 @@ struct _RGBA_Gfx_Compositor
RGBA_Gfx_Pt_Func (*composite_pixel_mask_pt_get)(int src_flags, RGBA_Image *dst);
};
#define EVAS_RECT_SPLIT 1
#ifdef EVAS_RECT_SPLIT
typedef struct list_node list_node_t;
typedef struct list list_t;
typedef struct rect rect_t;
typedef struct rect_node rect_node_t;
struct list_node
{
struct list_node *next;
};
struct list
{
struct list_node *head;
struct list_node *tail;
};
struct rect
{
short left;
short top;
short right;
short bottom;
short width;
short height;
int area;
};
struct rect_node
{
struct list_node _lst;
struct rect rect;
};
void rect_init(rect_t *r, int x, int y, int w, int h);
void rect_list_append_node(list_t *rects, list_node_t *node);
void rect_list_append(list_t *rects, const rect_t r);
void rect_list_append_xywh(list_t *rects, int x, int y, int w, int h);
void rect_list_concat(list_t *rects, list_t *other);
list_node_t *rect_list_unlink_next(list_t *rects, list_node_t *parent_node);
void rect_list_del_next(list_t *rects, list_node_t *parent_node);
void rect_list_clear(list_t *rects);
void rect_list_add_split_strict(list_t *rects, list_node_t *node);
list_node_t *rect_list_add_split_fuzzy(list_t *rects, const rect_t r, int accepted_error);
void rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error);void rect_list_add_split_fuzzy_and_merge(list_t *rects, const rect_t r, int split_accepted_error, int merge_accepted_error);
void rect_print(const rect_t r);
void rect_list_print(const list_t rects);
#endif /* EVAS_RECT_SPLIT */
struct _Tilebuf
{
int outbuf_w;
@ -542,6 +594,8 @@ struct _Tilebuf
#ifdef RECTUPDATE
Regionbuf *rb;
#elif defined(EVAS_RECT_SPLIT)
list_t rects;
#else
struct {
int w, h;

View File

@ -86,6 +86,10 @@ struct _Evas_GL_Context
Evas_List *tex_pool;
RGBA_Draw_Context *dc;
struct {
GLhandleARB prog, fshad;
} yuv422p;
};
struct _Evas_GL_Texture
@ -96,7 +100,6 @@ struct _Evas_GL_Texture
int uw, uh;
GLuint texture, texture2, texture3;
GLhandleARB prog;
unsigned char smooth : 1;
unsigned char changed : 1;
@ -106,6 +109,7 @@ struct _Evas_GL_Texture
unsigned char opt : 1;
int references;
GLhandleARB prog;
};
struct _Evas_GL_Image

View File

@ -39,6 +39,41 @@ evas_gl_common_context_new(void)
gc->change.clip = 1;
gc->change.buf = 1;
gc->change.other = 1;
gc->yuv422p.prog = glCreateProgramObjectARB();
// on an nv 6600gt this is fast - but on a 5500fx its DEAD SLOW!!!!!
// if (!gc->ext.arb_texture_non_power_of_two) return NULL;
/* BEGIN LEAK */
gc->yuv422p.fshad = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
{
const char *code =
"uniform sampler2D ytex, utex, vtex;\n"
"void main(void) {\n"
" float r, g, b, y, u, v;\n"
" y = texture2D(ytex, gl_TexCoord[0].st).r;\n"
" u = texture2D(utex, gl_TexCoord[0].st).r;\n"
" v = texture2D(vtex, gl_TexCoord[0].st).r;\n"
" y = (y - 0.0625) * 1.164;\n"
" u = u - 0.5;\n"
" v = v - 0.5;\n"
" r = y + (1.402 * v);\n"
" g = y - (0.34414 * u) - (0.71414 * v);\n"
" b = y + (1.772 * u);\n"
" gl_FragColor = vec4(r * gl_Color.r * gl_Color.a, g * gl_Color.g * gl_Color.a, b * gl_Color.b * gl_Color.a, gl_Color.a);\n"
"}\n";
glShaderSourceARB(gc->yuv422p.fshad, 1, &code, NULL);
}
glCompileShaderARB(gc->yuv422p.fshad);
glAttachObjectARB(gc->yuv422p.prog, gc->yuv422p.fshad);
/* END LEAK - something in the above leaks... beats me what. */
glLinkProgramARB(gc->yuv422p.prog);
glUseProgramObjectARB(gc->yuv422p.prog);
glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "ytex"), 0);
glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "utex"), 1);
glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "vtex"), 2);
glUseProgramObjectARB(0);
return gc;
}
@ -47,7 +82,15 @@ evas_gl_common_context_free(Evas_GL_Context *gc)
{
gc->references--;
if (gc->references > 0) return;
if (gc->yuv422p.fshad)
{
glDeleteObjectARB(gc->yuv422p.fshad);
}
if (gc->yuv422p.prog)
{
glDeleteObjectARB(gc->yuv422p.prog);
}
if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
free(gc);
}

View File

@ -105,6 +105,7 @@ evas_gl_common_image_new_from_data(Evas_GL_Context *gc, int w, int h, int *data,
im->cached = 1;
gc->images = evas_list_prepend(gc->images, im);
*/
printf("new im cs = %i\n", im->cs.space);
return im;
}
@ -166,6 +167,33 @@ evas_gl_common_image_new(Evas_GL_Context *gc, int w, int h, int alpha, int cspac
free(im);
return NULL;
}
im->gc = gc;
im->cs.space = cspace;
if (alpha)
im->im->flags |= RGBA_IMAGE_HAS_ALPHA;
else
im->im->flags &= ~RGBA_IMAGE_HAS_ALPHA;
switch (cspace)
{
case EVAS_COLORSPACE_ARGB8888:
// if (data)
// memcpy(im->im->image->data, data, w * h * sizeof(DATA32));
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
evas_common_image_surface_dealloc(im->im->image);
im->im->image->data = NULL;
// if (im->tex) evas_gl_common_texture_free(im->tex);
im->tex = NULL;
im->cs.no_free = 0;
im->cs.data = calloc(1, im->im->image->h * sizeof(unsigned char *) * 2);
// if ((data) && (im->cs.data))
// memcpy(im->cs.data, data, im->im->image->h * sizeof(unsigned char *) * 2);
break;
default:
abort();
break;
}
return im;
}
@ -215,6 +243,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy
r = g = b = a = 255;
}
evas_common_load_image_data_from_file(im->im);
/* leak in this switch */
switch (im->cs.space)
{
case EVAS_COLORSPACE_ARGB8888:
@ -251,7 +280,9 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy
im->dirty = 0;
}
if ((!im->tex) && (im->cs.data) && (*((unsigned char **)im->cs.data)))
im->tex = evas_gl_common_ycbcr601pl_texture_new(gc, im->cs.data, im->im->image->w, im->im->image->h, smooth);
{
im->tex = evas_gl_common_ycbcr601pl_texture_new(gc, im->cs.data, im->im->image->w, im->im->image->h, smooth);
}
if (!im->tex) return;
ow = (dw * im->tex->tw) / sw;
oh = (dh * im->tex->th) / sh;
@ -270,11 +301,13 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy
ty2 = (double)(sy + sh) / (double)(im->tex->h);
}
evas_gl_common_context_texture_set(gc, im->tex, smooth, ow, oh);
break;
default:
abort();
break;
}
// if ((!im->tex->have_mipmaps) && (smooth) &&
// ((im->tex->uw < im->tex->tw) || (im->tex->uh < im->tex->th)) &&
// (!gc->ext.sgis_generate_mipmap))

View File

@ -296,8 +296,16 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex)
glDeleteTextures(1, &tex->texture);
if (tex->texture2) glDeleteTextures(1, &tex->texture2);
if (tex->texture3) glDeleteTextures(1, &tex->texture3);
/*
if (tex->fshad)
{
glDeleteObjectARB(tex->fshad);
}
if (tex->prog)
glDeleteObjectARB(tex->prog);
{
glDeleteObjectARB(tex->prog);
}
*/
free(tex);
}
@ -418,7 +426,6 @@ evas_gl_common_ycbcr601pl_texture_new(Evas_GL_Context *gc, unsigned char **rows,
Evas_GL_Texture *tex;
int im_w, im_h, tw, th, y;
GLenum texfmt;
GLhandleARB fshad;
// on an nv 6600gt this is fast - but on a 5500fx its DEAD SLOW!!!!!
// if (!gc->ext.arb_texture_non_power_of_two) return NULL;
@ -436,40 +443,13 @@ evas_gl_common_ycbcr601pl_texture_new(Evas_GL_Context *gc, unsigned char **rows,
tex->references = 0;
tex->smooth = 0;
tex->changed = 1;
tex->prog = glCreateProgramObjectARB();
fshad = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
{
const char *code =
"uniform sampler2D ytex, utex, vtex;\n"
"void main(void) {\n"
" float r, g, b, y, u, v;\n"
" y = texture2D(ytex, gl_TexCoord[0].st).r;\n"
" u = texture2D(utex, gl_TexCoord[0].st).r;\n"
" v = texture2D(vtex, gl_TexCoord[0].st).r;\n"
" y = (y - 0.0625) * 1.164;\n"
" u = u - 0.5;\n"
" v = v - 0.5;\n"
" r = y + (1.402 * v);\n"
" g = y - (0.34414 * u) - (0.71414 * v);\n"
" b = y + (1.772 * u);\n"
" gl_FragColor = vec4(r * gl_Color.r * gl_Color.a, g * gl_Color.g * gl_Color.a, b * gl_Color.b * gl_Color.a, gl_Color.a);\n"
"}\n";
glShaderSourceARB(fshad, 1, &code, NULL);
}
glCompileShaderARB(fshad);
glAttachObjectARB(tex->prog, fshad);
glLinkProgramARB(tex->prog);
tex->prog = gc->yuv422p.prog;
glEnable(GL_TEXTURE_2D);
texfmt = GL_LUMINANCE;
glUseProgramObjectARB(tex->prog);
glUniform1iARB(glGetUniformLocationARB(tex->prog, "ytex"), 0);
glUniform1iARB(glGetUniformLocationARB(tex->prog, "utex"), 1);
glUniform1iARB(glGetUniformLocationARB(tex->prog, "vtex"), 2);
glGenTextures(1, &(tex->texture));
glBindTexture(GL_TEXTURE_2D, tex->texture);

View File

@ -718,6 +718,9 @@ eng_image_size_set(void *data, void *image, int w, int h)
if (!image) return NULL;
eng_window_use(re->win);
im_old = image;
if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
if ((im_old) && (im_old->im->image->w == w) && (im_old->im->image->h == h))
return image;
if (im_old)

View File

@ -512,6 +512,7 @@ eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha,
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
w &= ~0x1;
im->image->w = w;
im->image->h = h;
evas_common_image_surface_alloc(im->image);
@ -546,6 +547,7 @@ eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
w &= ~0x1;
im = evas_common_image_create(w, h);
im->cs.data = calloc(1, im->image->h * sizeof(unsigned char *) * 2);
if ((image_data) && (im->cs.data))
@ -582,13 +584,22 @@ eng_image_size_set(void *data, void *image, int w, int h)
RGBA_Image *im, *im_old;
im_old = image;
if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
if ((im_old) && (im_old->image->w == w) && (im_old->image->h == h))
return image;
im = evas_common_image_create(w, h);
if (!im) return im_old;
if (im_old)
{
im->cs.space = im_old->cs.space;
im->flags = im_old->flags;
/*
im->cs.no_free = 0;
if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL))
im->cs.data = calloc(1, im->image->h * sizeof(unsigned char *) * 2);
/*
evas_common_load_image_data_from_file(im_old);
evas_common_image_colorspace_normalize(im);
if (im_old->image->data)
@ -596,8 +607,9 @@ eng_image_size_set(void *data, void *image, int w, int h)
evas_common_blit_rectangle(im_old, im, 0, 0, w, h, 0, 0);
evas_common_cpu_end_opt();
}
*/
*/
evas_common_image_unref(im_old);
evas_common_image_colorspace_dirty(im);
}
return im;
}

View File

@ -559,7 +559,7 @@ evas_software_x11_outbuf_debug_show(Outbuf * buf, Drawable draw, int x, int y, i
XGetWindowAttributes(buf->priv.x.disp, root, &wattr);
screen_num = XScreenNumberOfScreen(wattr.screen);
}
for (i = 0; i < 10; i++)
for (i = 0; i < 20; i++)
{
XImage *xim;
@ -567,19 +567,19 @@ evas_software_x11_outbuf_debug_show(Outbuf * buf, Drawable draw, int x, int y, i
BlackPixel(buf->priv.x.disp, screen_num));
XFillRectangle(buf->priv.x.disp, draw, buf->priv.x.gc, x, y, w, h);
XSync(buf->priv.x.disp, False);
xim =
XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap);
if (xim)
XDestroyImage(xim);
// xim =
// XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap);
// if (xim)
// XDestroyImage(xim);
XSync(buf->priv.x.disp, False);
XSetForeground(buf->priv.x.disp, buf->priv.x.gc,
WhitePixel(buf->priv.x.disp, screen_num));
XFillRectangle(buf->priv.x.disp, draw, buf->priv.x.gc, x, y, w, h);
XSync(buf->priv.x.disp, False);
xim =
XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap);
if (xim)
XDestroyImage(xim);
// xim =
// XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap);
// if (xim)
// XDestroyImage(xim);
XSync(buf->priv.x.disp, False);
}
}

View File

@ -645,6 +645,9 @@ eng_image_size_set(void *data, void *image, int w, int h)
if (!image) return NULL;
im_old = image;
if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
if ((im_old) && (im_old->w == w) && (im_old->h == h))
return image;
if ((w <= 0) || (h <= 0))