summaryrefslogtreecommitdiff
path: root/src/lib/evas/common
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-10-05 18:41:00 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-10-05 18:41:00 +0900
commit5801013ad4be24baf55e88dcd8cefd89ac57f5e6 (patch)
tree9f841fd5180cae06be0be36e039f8e9e872486ae /src/lib/evas/common
parent966b3c8f2335b04145061b0dbba9689a4d5eabae (diff)
evas - region updates - go back to tiler as its faster
the overhead didnt show up in y tests. do show up with certain expedite tests. hmmm. last time i messed with region code it was actually same speed as tiler. bonus was it was fully accurate.
Diffstat (limited to 'src/lib/evas/common')
-rw-r--r--src/lib/evas/common/evas_tiler.c914
1 files changed, 914 insertions, 0 deletions
diff --git a/src/lib/evas/common/evas_tiler.c b/src/lib/evas/common/evas_tiler.c
index d645d52..0aff533 100644
--- a/src/lib/evas/common/evas_tiler.c
+++ b/src/lib/evas/common/evas_tiler.c
@@ -1,6 +1,8 @@
1#include "evas_common_private.h" 1#include "evas_common_private.h"
2#include "region.h" 2#include "region.h"
3 3
4
5#ifdef NEWTILER
4EAPI void 6EAPI void
5evas_common_tilebuf_init(void) 7evas_common_tilebuf_init(void)
6{ 8{
@@ -147,3 +149,915 @@ evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects)
147{ 149{
148 free(rects); 150 free(rects);
149} 151}
152
153#else
154
155#define FUZZ 32
156#define MAXREG 24
157#define MAX_NODES 1024
158
159static inline void rect_list_node_pool_flush(void);
160static inline list_node_t *rect_list_node_pool_get(void);
161static inline void rect_list_node_pool_put(list_node_t *node);
162static inline void rect_init(rect_t *r, int x, int y, int w, int h);
163static inline void rect_list_append_node(list_t *rects, list_node_t *node);
164static inline void rect_list_append(list_t *rects, const rect_t r);
165static inline void rect_list_append_xywh(list_t *rects, int x, int y, int w, int h);
166static inline void rect_list_concat(list_t *rects, list_t *other);
167static inline list_node_t *rect_list_unlink_next(list_t *rects, list_node_t *parent_node);
168static inline void rect_list_del_next(list_t *rects, list_node_t *parent_node);
169static inline void rect_list_clear(list_t *rects);
170static inline void rect_list_del_split_strict(list_t *rects, const rect_t del_r);
171static inline list_node_t *rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error);
172static inline void rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error);
173static inline void rect_list_add_split_fuzzy_and_merge(list_t *rects, list_node_t *node, int split_accepted_error, int merge_accepted_error);
174
175static const list_node_t list_node_zeroed = { NULL };
176static const list_t list_zeroed = { NULL, NULL };
177
178typedef struct list_node_pool
179{
180 list_node_t *node;
181 int len;
182 int max;
183} list_node_pool_t;
184
185static list_node_pool_t list_node_pool = { NULL, 0, MAX_NODES };
186
187static inline void
188rect_list_node_pool_flush(void)
189{
190 while (list_node_pool.node)
191 {
192 list_node_t *node = list_node_pool.node;
193 list_node_pool.node = node->next;
194 list_node_pool.len--;
195 free(node);
196 }
197}
198
199static inline list_node_t *
200rect_list_node_pool_get(void)
201{
202 if (list_node_pool.node)
203 {
204 list_node_t *node = list_node_pool.node;
205 list_node_pool.node = node->next;
206 list_node_pool.len--;
207 return node;
208 }
209 else return (list_node_t *)malloc(sizeof(rect_node_t));
210}
211
212static inline void
213rect_list_node_pool_put(list_node_t *node)
214{
215 if (list_node_pool.len < list_node_pool.max)
216 {
217 node->next = list_node_pool.node;
218 list_node_pool.node = node;
219 list_node_pool.len++;
220 }
221 else free(node);
222}
223
224static inline void
225rect_init(rect_t *r, int x, int y, int w, int h)
226{
227 r->area = w * h;
228 r->left = x;
229 r->top = y;
230 r->right = x + w;
231 r->bottom = y + h;
232 r->width = w;
233 r->height = h;
234}
235
236static inline void
237rect_list_append_node(list_t *rects, list_node_t *node)
238{
239 if (rects->tail)
240 {
241 rects->tail->next = node;
242 rects->tail = node;
243 }
244 else
245 {
246 rects->head = node;
247 rects->tail = node;
248 }
249}
250
251static inline void
252rect_list_append(list_t *rects, const rect_t r)
253{
254 rect_node_t *rect_node = (rect_node_t *)rect_list_node_pool_get();
255 rect_node->rect = r;
256 rect_node->_lst = list_node_zeroed;
257 rect_list_append_node(rects, (list_node_t *)rect_node);
258}
259
260static inline void
261rect_list_append_xywh(list_t *rects, int x, int y, int w, int h)
262{
263 rect_t r;
264 rect_init(&r, x, y, w, h);
265 rect_list_append(rects, r);
266}
267
268static inline void
269rect_list_concat(list_t *rects, list_t *other)
270{
271 if (!other->head) return;
272 if (rects->tail)
273 {
274 rects->tail->next = other->head;
275 rects->tail = other->tail;
276 }
277 else
278 {
279 rects->head = other->head;
280 rects->tail = other->tail;
281 }
282 *other = list_zeroed;
283}
284
285static inline list_node_t *
286rect_list_unlink_next(list_t *rects, list_node_t *parent_node)
287{
288 list_node_t *node;
289
290 if (parent_node)
291 {
292 node = parent_node->next;
293 parent_node->next = node->next;
294 }
295 else
296 {
297 node = rects->head;
298 rects->head = node->next;
299 }
300 if (rects->tail == node) rects->tail = parent_node;
301 *node = list_node_zeroed;
302 return node;
303}
304
305static inline void
306rect_list_del_next(list_t *rects, list_node_t *parent_node)
307{
308 list_node_t *node = rect_list_unlink_next(rects, parent_node);
309 rect_list_node_pool_put(node);
310}
311
312static inline void
313rect_list_clear(list_t *rects)
314{
315 list_node_t *node = rects->head;
316 while (node)
317 {
318 list_node_t *aux;
319
320 aux = node->next;
321 rect_list_node_pool_put(node);
322 node = aux;
323 }
324 *rects = list_zeroed;
325}
326
327static inline void
328_calc_intra_rect_area(const rect_t a, const rect_t b, int *width, int *height)
329{
330 int max_left, min_right, max_top, min_bottom;
331
332 if (a.left < b.left) max_left = b.left;
333 else max_left = a.left;
334 if (a.right < b.right) min_right = a.right;
335 else min_right = b.right;
336 *width = min_right - max_left;
337
338 if (a.top < b.top) max_top = b.top;
339 else max_top = a.top;
340 if (a.bottom < b.bottom) min_bottom = a.bottom;
341 else min_bottom = b.bottom;
342 *height = min_bottom - max_top;
343}
344
345static inline void
346_split_strict(list_t *dirty, const rect_t current, rect_t r)
347{
348 int h_1, h_2, w_1, w_2;
349
350 h_1 = current.top - r.top;
351 h_2 = r.bottom - current.bottom;
352 w_1 = current.left - r.left;
353 w_2 = r.right - current.right;
354 if (h_1 > 0)
355 {
356 /* .--.r (b) .---.r2
357 * | | | |
358 * .-------.cur (a) .---.r '---'
359 * | | | | -> | | +
360 * | `--' | `---'
361 * `-------'
362 */
363 rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1);
364 r.height -= h_1;
365 r.top = current.top;
366 }
367 if (h_2 > 0)
368 {
369 /* .-------.cur (a)
370 * | .---. | .---.r
371 * | | | | -> | |
372 * `-------' `---' + .---.r2
373 * | | | |
374 * `---'r (b) `---'
375 */
376 rect_list_append_xywh(dirty, r.left, current.bottom, r.width, h_2);
377 r.height -= h_2;
378 }
379 if (w_1 > 0)
380 {
381 /* (b) r .----.cur (a)
382 * .--|-. | .--.r2 .-.r
383 * | | | | -> | | + | |
384 * `--|-' | `--' `-'
385 * `----'
386 */
387 rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height);
388 /* not necessary to keep these, r (b) will be destroyed */
389 /* r.width -= w_1; */
390 /* r.left = current.left; */
391 }
392 if (w_2 > 0)
393 {
394 /* .----.cur (a)
395 * | |
396 * | .-|--.r (b) .-.r .--.r2
397 * | | | | -> | | + | |
398 * | `-|--' `-' `--'
399 * `----'
400 */
401 rect_list_append_xywh(dirty, current.right, r.top, w_2, r.height);
402 /* not necessary to keep this, r (b) will be destroyed */
403 /* r.width -= w_2; */
404 }
405}
406
407static inline void
408rect_list_del_split_strict(list_t *rects, const rect_t del_r)
409{
410 list_t modified = list_zeroed;
411 list_node_t *cur_node, *prev_node;
412 int intra_width, intra_height;
413 rect_t current;
414
415 prev_node = NULL;
416 cur_node = rects->head;
417 while (cur_node)
418 {
419 current = ((rect_node_t*)cur_node)->rect;
420 _calc_intra_rect_area(del_r, current, &intra_width, &intra_height);
421 if ((intra_width <= 0) || (intra_height <= 0))
422 {
423 /* .---.current .---.del_r
424 * | | | |
425 * `---+---.del_r `---+---.current
426 * | | | |
427 * `---' `---'
428 * no interception, nothing to do
429 */
430 prev_node = cur_node;
431 cur_node = cur_node->next;
432 }
433 else if ((intra_width == current.width) &&
434 (intra_height == current.height))
435 {
436 /* .-------.del_r
437 * | .---. |
438 * | | | |
439 * | `---'current
440 * `-------'
441 * current is contained, remove from rects
442 */
443 cur_node = cur_node->next;
444 rect_list_del_next(rects, prev_node);
445 }
446 else
447 {
448 _split_strict(&modified, del_r, current);
449 cur_node = cur_node->next;
450 rect_list_del_next(rects, prev_node);
451 }
452 }
453
454 rect_list_concat(rects, &modified);
455}
456
457static inline void
458_calc_intra_outer_rect_area(const rect_t a, const rect_t b,
459 rect_t *intra, rect_t *outer)
460{
461 int min_left, max_left, min_right, max_right;
462 int min_top, max_top, min_bottom, max_bottom;
463
464 if (a.left < b.left)
465 {
466 max_left = b.left;
467 min_left = a.left;
468 }
469 else
470 {
471 max_left = a.left;
472 min_left = b.left;
473 }
474 if (a.right < b.right)
475 {
476 min_right = a.right;
477 max_right = b.right;
478 }
479 else
480 {
481 min_right = b.right;
482 max_right = a.right;
483 }
484 intra->left = max_left;
485 intra->right = min_right;
486 intra->width = min_right - max_left;
487 outer->left = min_left;
488 outer->right = max_right;
489 outer->width = max_right - min_left;
490 if (a.top < b.top)
491 {
492 max_top = b.top;
493 min_top = a.top;
494 }
495 else
496 {
497 max_top = a.top;
498 min_top = b.top;
499 }
500 if (a.bottom < b.bottom)
501 {
502 min_bottom = a.bottom;
503 max_bottom = b.bottom;
504 }
505 else
506 {
507 min_bottom = b.bottom;
508 max_bottom = a.bottom;
509 }
510 intra->top = max_top;
511 intra->bottom = min_bottom;
512 intra->height = min_bottom - max_top;
513 if ((intra->width > 0) && (intra->height > 0))
514 intra->area = intra->width * intra->height;
515 else
516 intra->area = 0;
517 outer->top = min_top;
518 outer->bottom = max_bottom;
519 outer->height = max_bottom - min_top;
520 outer->area = outer->width * outer->height;
521}
522
523enum
524{
525 SPLIT_FUZZY_ACTION_NONE,
526 SPLIT_FUZZY_ACTION_SPLIT,
527 SPLIT_FUZZY_ACTION_MERGE
528};
529
530static inline int
531_split_fuzzy(list_t *dirty, const rect_t a, rect_t *b)
532{
533 int h_1, h_2, w_1, w_2, action;
534
535 h_1 = a.top - b->top;
536 h_2 = b->bottom - a.bottom;
537 w_1 = a.left - b->left;
538 w_2 = b->right - a.right;
539
540 action = SPLIT_FUZZY_ACTION_NONE;
541 if (h_1 > 0)
542 {
543 /* .--.r (b) .---.r2
544 * | | | |
545 * .-------.cur (a) .---.r '---'
546 * | | | | -> | | +
547 * | `--' | `---'
548 * `-------'
549 */
550 rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1);
551 b->height -= h_1;
552 b->top = a.top;
553 action = SPLIT_FUZZY_ACTION_SPLIT;
554 }
555 if (h_2 > 0)
556 {
557 /* .-------.cur (a)
558 * | .---. | .---.r
559 * | | | | -> | |
560 * `-------' `---' + .---.r2
561 * | | | |
562 * `---'r (b) `---'
563 */
564 rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2);
565 b->height -= h_2;
566 action = SPLIT_FUZZY_ACTION_SPLIT;
567 }
568 if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height))
569 return SPLIT_FUZZY_ACTION_MERGE;
570 if (w_1 > 0)
571 {
572 /* (b) r .----.cur (a)
573 * .--|-. | .--.r2 .-.r
574 * | | | | -> | | + | |
575 * `--|-' | `--' `-'
576 * `----'
577 */
578 rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height);
579 /* not necessary to keep these, r (b) will be destroyed */
580 /* b->width -= w_1; */
581 /* b->left = a.left; */
582 action = SPLIT_FUZZY_ACTION_SPLIT;
583 }
584 if (w_2 > 0)
585 {
586 /* .----.cur (a)
587 * | |
588 * | .-|--.r (b) .-.r .--.r2
589 * | | | | -> | | + | |
590 * | `-|--' `-' `--'
591 * `----'
592 */
593 rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height);
594 /* not necessary to keep these, r (b) will be destroyed */
595 /* b->width -= w_2; */
596 action = SPLIT_FUZZY_ACTION_SPLIT;
597 }
598 return action;
599}
600
601static inline list_node_t *
602rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error)
603{
604 list_t dirty = list_zeroed;
605 list_node_t *old_last = rects->tail;
606
607 if (!rects->head)
608 {
609 rect_list_append_node(rects, node);
610 return old_last;
611 }
612 rect_list_append_node(&dirty, node);
613 while (dirty.head)
614 {
615 list_node_t *d_node, *cur_node, *prev_cur_node;
616 int keep_dirty;
617 rect_t r;
618
619 d_node = rect_list_unlink_next(&dirty, NULL);
620 r = ((rect_node_t *)d_node)->rect;
621 prev_cur_node = NULL;
622 cur_node = rects->head;
623 keep_dirty = 1;
624 while (cur_node)
625 {
626 int area, action;
627 rect_t current, intra, outer;
628
629 current = ((rect_node_t *)cur_node)->rect;
630 _calc_intra_outer_rect_area(r, current, &intra, &outer);
631 area = current.area + r.area - intra.area;
632 if ((intra.width == r.width) && (intra.height == r.height))
633 {
634 /* .-------.cur
635 * | .---.r|
636 * | | | |
637 * | `---' |
638 * `-------'
639 */
640 keep_dirty = 0;
641 break;
642 }
643 else if ((intra.width == current.width) &&
644 (intra.height == current.height))
645 {
646 /* .-------.r
647 * | .---.cur
648 * | | | |
649 * | `---' |
650 * `-------'
651 */
652 if (old_last == cur_node)
653 old_last = prev_cur_node;
654 cur_node = cur_node->next;
655 rect_list_del_next(rects, prev_cur_node);
656 }
657 else if ((outer.area - area) <= accepted_error)
658 {
659 /* .-----------. bounding box (outer)
660 * |.---. .---.|
661 * ||cur| |r ||
662 * || | | ||
663 * |`---' `---'|
664 * `-----------'
665 * merge them, remove both and add merged
666 */
667 rect_node_t *n;
668
669 if (old_last == cur_node)
670 old_last = prev_cur_node;
671
672 n = (rect_node_t *)rect_list_unlink_next(rects, prev_cur_node);
673 n->rect = outer;
674 rect_list_append_node(&dirty, (list_node_t *)n);
675
676 keep_dirty = 0;
677 break;
678 }
679 else if ((intra.area - area) <= accepted_error)
680 {
681 /* .---.cur .---.r
682 * | | | |
683 * `---+---.r `---+---.cur
684 * | | | |
685 * `---' `---'
686 * no split, no merge
687 */
688 prev_cur_node = cur_node;
689 cur_node = cur_node->next;
690 }
691 else
692 {
693 /* split is required */
694 action = _split_fuzzy(&dirty, current, &r);
695 if (action == SPLIT_FUZZY_ACTION_MERGE)
696 {
697 /* horizontal merge is possible: remove both, add merged */
698 rect_node_t *n;
699
700 if (old_last == cur_node)
701 old_last = prev_cur_node;
702
703 n = (rect_node_t *)
704 rect_list_unlink_next(rects, prev_cur_node);
705
706 n->rect.left = outer.left;
707 n->rect.width = outer.width;
708 n->rect.right = outer.right;
709 n->rect.area = outer.width * r.height;
710 rect_list_append_node(&dirty, (list_node_t *)n);
711 }
712 else if (action == SPLIT_FUZZY_ACTION_NONE)
713 {
714 /* this rect check was totally useless,
715 * should never happen */
716 /* prev_cur_node = cur_node; */
717 /* cur_node = cur_node->next; */
718 WRN("Should not get here!");
719 abort();
720 }
721 keep_dirty = 0;
722 break;
723 }
724 }
725 if (UNLIKELY(keep_dirty)) rect_list_append_node(rects, d_node);
726 else rect_list_node_pool_put(d_node);
727 }
728 return old_last;
729}
730
731static inline void
732_calc_outer_rect_area(const rect_t a, const rect_t b, rect_t *outer)
733{
734 int min_left, max_right;
735 int min_top, max_bottom;
736
737 if (a.left < b.left) min_left = a.left;
738 else min_left = b.left;
739 if (a.right < b.right) max_right = b.right;
740 else max_right = a.right;
741 outer->left = min_left;
742 outer->right = max_right;
743 outer->width = max_right - min_left;
744 if (a.top < b.top) min_top = a.top;
745 else min_top = b.top;
746 if (a.bottom < b.bottom) max_bottom = b.bottom;
747 else max_bottom = a.bottom;
748 outer->top = min_top;
749 outer->bottom = max_bottom;
750 outer->height = max_bottom - min_top;
751 outer->area = outer->width * outer->height;
752}
753
754static inline void
755rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error)
756{
757 while (to_merge->head)
758 {
759 list_node_t *node, *parent_node;
760 rect_t r1;
761 int merged;
762
763 r1 = ((rect_node_t *)to_merge->head)->rect;
764 merged = 0;
765 parent_node = NULL;
766 node = rects->head;
767 while (node)
768 {
769 rect_t r2, outer;
770 int area;
771
772 r2 = ((rect_node_t *)node)->rect;
773 _calc_outer_rect_area(r1, r2, &outer);
774 area = r1.area + r2.area; /* intra area is taken as 0 */
775 if (outer.area - area <= accepted_error)
776 {
777 /* remove both r1 and r2, create r3
778 * actually r3 uses r2 instance, saves memory */
779 rect_node_t *n;
780
781 n = (rect_node_t *)rect_list_unlink_next(rects, parent_node);
782 n->rect = outer;
783 rect_list_append_node(to_merge, (list_node_t *)n);
784 merged = 1;
785 break;
786 }
787 parent_node = node;
788 node = node->next;
789 }
790 if (!merged)
791 {
792 list_node_t *n;
793 n = rect_list_unlink_next(to_merge, NULL);
794 rect_list_append_node(rects, n);
795 }
796 else
797 rect_list_del_next(to_merge, NULL);
798 }
799}
800
801static inline void
802rect_list_add_split_fuzzy_and_merge(list_t *rects,
803 list_node_t *node,
804 int split_accepted_error,
805 int merge_accepted_error)
806{
807 list_node_t *n;
808
809 n = rect_list_add_split_fuzzy(rects, node, split_accepted_error);
810 if (n && n->next)
811 {
812 list_t to_merge;
813 /* split list into 2 segments, already merged and to merge */
814 to_merge.head = n->next;
815 to_merge.tail = rects->tail;
816 rects->tail = n;
817 n->next = NULL;
818 rect_list_merge_rects(rects, &to_merge, merge_accepted_error);
819 }
820}
821
822static inline int
823_add_redraw(list_t *rects, int x, int y, int w, int h, int fuzz)
824{
825 rect_node_t *rn;
826 rn = (rect_node_t *)rect_list_node_pool_get();
827 rn->_lst = list_node_zeroed;
828 rect_init(&rn->rect, x, y, w, h);
829 rect_list_add_split_fuzzy_and_merge(rects, (list_node_t *)rn, fuzz, fuzz);
830 return 1;
831}
832
833/////////////////////////////////////////////////////////////////
834
835EAPI void
836evas_common_tilebuf_init(void)
837{
838}
839
840EAPI Tilebuf *
841evas_common_tilebuf_new(int w, int h)
842{
843 Tilebuf *tb;
844
845 tb = calloc(1, sizeof(Tilebuf));
846 if (!tb) return NULL;
847 tb->tile_size.w = 8;
848 tb->tile_size.h = 8;
849 tb->outbuf_w = w;
850 tb->outbuf_h = h;
851 return tb;
852}
853
854EAPI void
855evas_common_tilebuf_free(Tilebuf *tb)
856{
857 rect_list_clear(&tb->rects);
858 rect_list_node_pool_flush();
859 free(tb);
860}
861
862EAPI void
863evas_common_tilebuf_set_tile_size(Tilebuf *tb, int tw, int th)
864{
865 tb->tile_size.w = tw;
866 tb->tile_size.h = th;
867}
868
869EAPI void
870evas_common_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th)
871{
872 if (tw) *tw = tb->tile_size.w;
873 if (th) *th = tb->tile_size.h;
874}
875
876EAPI void
877evas_common_tilebuf_tile_strict_set(Tilebuf *tb, Eina_Bool strict)
878{
879 tb->strict_tiles = strict;
880}
881
882EAPI int
883evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h)
884{
885 if ((w <= 0) || (h <= 0)) return 0;
886 RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h);
887 if ((w <= 0) || (h <= 0)) return 0;
888 // optimize a common case -> adding the exact same rect 2x in a row
889 if ((tb->prev_add.x == x) && (tb->prev_add.y == y) &&
890 (tb->prev_add.w == w) && (tb->prev_add.h == h)) return 1;
891 tb->prev_add.x = x; tb->prev_add.y = y;
892 tb->prev_add.w = w; tb->prev_add.h = h;
893 tb->prev_del.w = 0; tb->prev_del.h = 0;
894 return _add_redraw(&tb->rects, x, y, w, h, FUZZ * FUZZ);
895}
896
897EAPI int
898evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h)
899{
900 rect_t r;
901
902 if (!tb->rects.head) return 0;
903 if ((w <= 0) || (h <= 0)) return 0;
904 RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h);
905 if ((w <= 0) || (h <= 0)) return 0;
906 // optimize a common case -> deleting the exact same rect 2x in a row
907 if ((tb->prev_del.x == x) && (tb->prev_del.y == y) &&
908 (tb->prev_del.w == w) && (tb->prev_del.h == h)) return 1;
909 tb->prev_del.x = x; tb->prev_del.y = y;
910 tb->prev_del.w = w; tb->prev_del.h = h;
911 tb->prev_add.w = 0; tb->prev_add.h = 0;
912 rect_init(&r, x, y, w, h);
913 rect_list_del_split_strict(&tb->rects, r);
914 tb->need_merge = 1;
915 return 0;
916}
917
918EAPI int
919evas_common_tilebuf_add_motion_vector(Tilebuf *tb EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED, int dx EINA_UNUSED, int dy EINA_UNUSED, int alpha EINA_UNUSED)
920{
921 return 0;
922}
923
924EAPI void
925evas_common_tilebuf_clear(Tilebuf *tb)
926{
927 tb->prev_add.x = tb->prev_add.y = tb->prev_add.w = tb->prev_add.h = 0;
928 tb->prev_del.x = tb->prev_del.y = tb->prev_del.w = tb->prev_del.h = 0;
929 rect_list_clear(&tb->rects);
930 tb->need_merge = 0;
931}
932
933EAPI Tilebuf_Rect *
934evas_common_tilebuf_get_render_rects(Tilebuf *tb)
935{
936 list_node_t *n;
937 list_t to_merge;
938 Tilebuf_Rect *rects = NULL, *rbuf, *r;
939 int bx1 = 0, bx2 = 0, by1 = 0, by2 = 0, num = 0, x1, x2, y1, y2, i;
940
941/* don't need this since the below is now always on
942 if (tb->need_merge)
943 {
944 to_merge = tb->rects;
945 tb->rects = list_zeroed;
946 rect_list_merge_rects(&tb->rects, &to_merge, 0);
947 tb->need_merge = 0;
948 }
949 */
950 if (1)
951// always fuzz merge for optimal perf
952// if (!tb->strict_tiles)
953 {
954 // round up rects to tb->tile_size.w and tb->tile_size.h
955 to_merge = list_zeroed;
956 for (n = tb->rects.head; n; n = n->next)
957 {
958 x1 = ((rect_node_t *)n)->rect.left;
959 x2 = x1 + ((rect_node_t *)n)->rect.width;
960 y1 = ((rect_node_t *)n)->rect.top;
961 y2 = y1 + ((rect_node_t *)n)->rect.height;
962 x1 = tb->tile_size.w * (x1 / tb->tile_size.w);
963 y1 = tb->tile_size.h * (y1 / tb->tile_size.h);
964 x2 = tb->tile_size.w * ((x2 + tb->tile_size.w - 1) / tb->tile_size.w);
965 y2 = tb->tile_size.h * ((y2 + tb->tile_size.h - 1) / tb->tile_size.h);
966 _add_redraw(&to_merge, x1, y1, x2 - x1, y2 - y1, 0);
967 }
968 rect_list_clear(&tb->rects);
969 rect_list_merge_rects(&tb->rects, &to_merge, 0);
970 }
971 n = tb->rects.head;
972 if (n)
973 {
974 RECTS_CLIP_TO_RECT(((rect_node_t *)n)->rect.left,
975 ((rect_node_t *)n)->rect.top,
976 ((rect_node_t *)n)->rect.width,
977 ((rect_node_t *)n)->rect.height,
978 0, 0, tb->outbuf_w, tb->outbuf_h);
979 num = 1;
980 bx1 = ((rect_node_t *)n)->rect.left;
981 bx2 = bx1 + ((rect_node_t *)n)->rect.width;
982 by1 = ((rect_node_t *)n)->rect.top;
983 by2 = by1 + ((rect_node_t *)n)->rect.height;
984 n = n->next;
985 for (; n; n = n->next)
986 {
987 RECTS_CLIP_TO_RECT(((rect_node_t *)n)->rect.left,
988 ((rect_node_t *)n)->rect.top,
989 ((rect_node_t *)n)->rect.width,
990 ((rect_node_t *)n)->rect.height,
991 0, 0, tb->outbuf_w, tb->outbuf_h);
992 x1 = ((rect_node_t *)n)->rect.left;
993 if (x1 < bx1) bx1 = x1;
994 x2 = x1 + ((rect_node_t *)n)->rect.width;
995 if (x2 > bx2) bx2 = x2;
996
997 y1 = ((rect_node_t *)n)->rect.top;
998 if (y1 < by1) by1 = y1;
999 y2 = y1 + ((rect_node_t *)n)->rect.height;
1000 if (y2 > by2) by2 = y2;
1001 num++;
1002 }
1003 }
1004 else
1005 return NULL;
1006
1007 /* magic number - if we have > MAXREG regions to update, take bounding */
1008 if (num > MAXREG)
1009 {
1010 r = malloc(sizeof(Tilebuf_Rect));
1011 if (r)
1012 {
1013 EINA_INLIST_GET(r)->next = NULL;
1014 EINA_INLIST_GET(r)->prev = NULL;
1015 EINA_INLIST_GET(r)->last = NULL;
1016 r->x = bx1;
1017 r->y = by1;
1018 r->w = bx2 - bx1;
1019 r->h = by2 - by1;
1020 rects = (Tilebuf_Rect *)
1021 eina_inlist_append(EINA_INLIST_GET(rects),
1022 EINA_INLIST_GET(r));
1023 }
1024 return rects;
1025 }
1026
1027 rbuf = malloc(sizeof(Tilebuf_Rect) * num);
1028 if (!rbuf) return NULL;
1029
1030 for (i = 0, n = tb->rects.head; n; n = n->next)
1031 {
1032 rect_t cur;
1033
1034 cur = ((rect_node_t *)n)->rect;
1035 if ((cur.width > 0) && (cur.height > 0))
1036 {
1037 r = &(rbuf[i]);
1038 EINA_INLIST_GET(r)->next = NULL;
1039 EINA_INLIST_GET(r)->prev = NULL;
1040 EINA_INLIST_GET(r)->last = NULL;
1041 r->x = cur.left;
1042 r->y = cur.top;
1043 r->w = cur.width;
1044 r->h = cur.height;
1045 rects = (Tilebuf_Rect *)
1046 eina_inlist_append(EINA_INLIST_GET(rects),
1047 EINA_INLIST_GET(r));
1048 i++;
1049 }
1050 }
1051
1052 // It is possible that due to the clipping we do not return any rectangle here.
1053 if (!rects) free(rbuf);
1054
1055 return rects;
1056}
1057
1058EAPI void
1059evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects)
1060{
1061 free(rects);
1062}
1063#endif