summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_scale_sample.c
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2015-02-20 17:11:44 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-02-20 17:11:44 +0100
commit6bb4ecd65db4cb674ca3dc6ef30ceb1a22445a90 (patch)
tree4d8dc9dd2b9f741c8bddf27e35052a6b2e9139d2 /src/lib/evas/common/evas_scale_sample.c
parentbc584cd59bab1af3654e194128436e6aba124f7e (diff)
evas: use two thread when scaling image.
This is for now just a small experiment. It was based on the experiment made with OpenMP. I prefered to only use Eina here as we have already all the infrastructure to do this nicely and simply. As a result I get a 65% speed improved on average for the involved scaling operation. The secondary CPU is on my laptop running with a load of 75% percent. I don't have right now the time to do power consumption analysis, but I think it shouldn't be to bad. I am also not throwing more core at this as we are not able to use the second core at its max already, so additional core may result in a bigger energy loss without enough gain.
Diffstat (limited to '')
-rw-r--r--src/lib/evas/common/evas_scale_sample.c300
1 files changed, 267 insertions, 33 deletions
diff --git a/src/lib/evas/common/evas_scale_sample.c b/src/lib/evas/common/evas_scale_sample.c
index 940ccbacfa..09a063110e 100644
--- a/src/lib/evas/common/evas_scale_sample.c
+++ b/src/lib/evas/common/evas_scale_sample.c
@@ -3,6 +3,42 @@
3 3
4static Eina_Bool scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h); 4static Eina_Bool scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
5 5
6typedef struct _Evas_Scale_Thread Evas_Scale_Thread;
7typedef struct _Evas_Scale_Msg Evas_Scale_Msg;
8
9struct _Evas_Scale_Msg
10{
11 Eina_Thread_Queue_Msg head;
12 Evas_Scale_Thread *task;
13};
14
15struct _Evas_Scale_Thread
16{
17 RGBA_Image *mask8;
18 DATA32 **row_ptr;
19 DATA32 *dptr;
20 int *lin_ptr;
21
22 RGBA_Gfx_Func func;
23 RGBA_Gfx_Func func2;
24
25 int dst_clip_x;
26 int dst_clip_y;
27 int dst_clip_h;
28 int dst_clip_w;
29 int dst_w;
30
31 int mask_x;
32 int mask_y;
33
34 unsigned int mul_col;
35};
36
37static Eina_Bool use_thread = EINA_FALSE;
38static Eina_Thread scaling_thread;
39static Eina_Thread_Queue *thread_queue = NULL;
40static Eina_Thread_Queue *main_queue = NULL;
41
6EAPI Eina_Bool 42EAPI Eina_Bool
7evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst, 43evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst,
8 RGBA_Draw_Context *dc, 44 RGBA_Draw_Context *dc,
@@ -58,6 +94,80 @@ evas_common_scale_rgba_in_to_out_clip_sample_do(const Cutout_Rects *reuse,
58 } 94 }
59} 95}
60 96
97static void
98_evas_common_scale_rgba_sample_scale_nomask(int y,
99 int dst_clip_w, int dst_clip_h, int dst_w,
100 DATA32 **row_ptr, int *lin_ptr,
101 DATA32 *dptr, RGBA_Gfx_Func func, unsigned int mul_col)
102{
103 DATA32 *buf, *dst_ptr;
104 int x;
105
106 /* a scanline buffer */
107 buf = alloca(dst_clip_w * sizeof(DATA32));
108
109 dptr = dptr + dst_w * y;
110 for (; y < dst_clip_h; y++)
111 {
112 dst_ptr = buf;
113 for (x = 0; x < dst_clip_w; x++)
114 {
115 DATA32 *ptr;
116
117 ptr = row_ptr[y] + lin_ptr[x];
118 *dst_ptr = *ptr;
119 dst_ptr++;
120 }
121
122 /* * blend here [clip_w *] buf -> dptr * */
123 func(buf, NULL, mul_col, dptr, dst_clip_w);
124
125 dptr += dst_w;
126 }
127}
128
129static void
130_evas_common_scale_rgba_sample_scale_mask(int y,
131 int dst_clip_x, int dst_clip_y,
132 int dst_clip_w, int dst_clip_h, int dst_w,
133 int mask_x, int mask_y,
134 DATA32 **row_ptr, int *lin_ptr, RGBA_Image *im,
135 DATA32 *dptr, RGBA_Gfx_Func func, RGBA_Gfx_Func func2,
136 unsigned int mul_col)
137{
138 DATA32 *buf, *dst_ptr;
139 int x;
140
141 /* a scanline buffer */
142 buf = alloca(dst_clip_w * sizeof(DATA32));
143
144 dptr = dptr + dst_w * y;
145 for (; y < dst_clip_h; y++)
146 {
147 DATA8 *mask;
148
149 dst_ptr = buf;
150 mask = im->image.data8
151 + ((dst_clip_y - mask_y + y) * im->cache_entry.w)
152 + (dst_clip_x - mask_x);
153
154 for (x = 0; x < dst_clip_w; x++)
155 {
156 DATA32 *ptr;
157
158 ptr = row_ptr[y] + lin_ptr[x];
159 *dst_ptr = *ptr;
160 dst_ptr++;
161 }
162
163 /* * blend here [clip_w *] buf -> dptr * */
164 if (mul_col != 0xFFFFFFFF) func2(buf, NULL, mul_col, buf, dst_clip_w);
165 func(buf, mask, 0, dptr, dst_clip_w);
166
167 dptr += dst_w;
168 }
169}
170
61EAPI void 171EAPI void
62evas_common_scale_rgba_sample_draw(RGBA_Image *src, RGBA_Image *dst, int dst_clip_x, int dst_clip_y, int dst_clip_w, int dst_clip_h, DATA32 mul_col, int render_op, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h, RGBA_Image *mask_ie, int mask_x, int mask_y) 172evas_common_scale_rgba_sample_draw(RGBA_Image *src, RGBA_Image *dst, int dst_clip_x, int dst_clip_y, int dst_clip_w, int dst_clip_h, DATA32 mul_col, int render_op, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h, RGBA_Image *mask_ie, int mask_x, int mask_y)
63{ 173{
@@ -587,51 +697,83 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
587 else 697 else
588#endif 698#endif
589 { 699 {
700 unsigned int mul_col;
701
590 /* a scanline buffer */ 702 /* a scanline buffer */
591 buf = alloca(dst_clip_w * sizeof(DATA32)); 703 buf = alloca(dst_clip_w * sizeof(DATA32));
592 704
593 /* image masking */ 705 mul_col = dc->mul.use ? dc->mul.col : 0xFFFFFFFF;
594 if (dc->clip.mask)
595 {
596 RGBA_Image *im = dc->clip.mask;
597 706
598 for (y = 0; y < dst_clip_h; y++) 707 /* do we have enough data to start some additional thread ? */
708 if (use_thread && dst_clip_h > 32 && dst_clip_w * dst_clip_h > 4096)
709 {
710 /* Yes, we do ! */
711 Evas_Scale_Msg *msg;
712 void *ref;
713 Evas_Scale_Thread local;
714
715 local.mask8 = dc->clip.mask;
716 local.row_ptr = row_ptr;
717 local.dptr = dptr;
718 local.lin_ptr = lin_ptr;
719 local.func = func;
720 local.func2 = func2;
721 local.dst_clip_x = dst_clip_x;
722 local.dst_clip_y = dst_clip_y;
723 local.dst_clip_h = dst_clip_h;
724 local.dst_clip_w = dst_clip_w;
725 local.dst_w = dst_w;
726 local.mask_x = dc->clip.mask_x;
727 local.mask_y = dc->clip.mask_y;
728 local.mul_col = mul_col;
729
730 msg = eina_thread_queue_send(thread_queue, sizeof (Evas_Scale_Msg), &ref);
731 msg->task = &local;
732 eina_thread_queue_send_done(thread_queue, ref);
733
734 /* image masking */
735 if (dc->clip.mask)
599 { 736 {
600 dst_ptr = buf; 737 _evas_common_scale_rgba_sample_scale_mask(0,
601 mask = im->image.data8 738 dst_clip_x, dst_clip_y,
602 + ((dst_clip_y - dc->clip.mask_y + y) * im->cache_entry.w) 739 dst_clip_w, dst_clip_h >> 1, dst_w,
603 + (dst_clip_x - dc->clip.mask_x); 740 dc->clip.mask_x, dc->clip.mask_y,
604 741 row_ptr, lin_ptr, dc->clip.mask,
605 for (x = 0; x < dst_clip_w; x++) 742 dptr, func, func2, mul_col);
606 {
607 ptr = row_ptr[y] + lin_ptr[x];
608 *dst_ptr = *ptr;
609 dst_ptr++;
610 }
611
612 /* * blend here [clip_w *] buf -> dptr * */
613 if (dc->mul.use) func2(buf, NULL, dc->mul.col, buf, dst_clip_w);
614 func(buf, mask, 0, dptr, dst_clip_w);
615 743
616 dptr += dst_w;
617 } 744 }
745 else
746 {
747 _evas_common_scale_rgba_sample_scale_nomask(0,
748 dst_clip_w, dst_clip_h >> 1, dst_w,
749 row_ptr, lin_ptr,
750 dptr, func, mul_col);
751 }
752
753 msg = eina_thread_queue_wait(main_queue, &ref);
754 if (msg) eina_thread_queue_wait_done(main_queue, ref);
618 } 755 }
619 else 756 else
620 { 757 {
621 for (y = 0; y < dst_clip_h; y++) 758 /* No we don't ! */
622 {
623 dst_ptr = buf;
624 for (x = 0; x < dst_clip_w; x++)
625 {
626 ptr = row_ptr[y] + lin_ptr[x];
627 *dst_ptr = *ptr;
628 dst_ptr++;
629 }
630 759
631 /* * blend here [clip_w *] buf -> dptr * */ 760 /* image masking */
632 func(buf, NULL, dc->mul.col, dptr, dst_clip_w); 761 if (dc->clip.mask)
762 {
763 _evas_common_scale_rgba_sample_scale_mask(0,
764 dst_clip_x, dst_clip_y,
765 dst_clip_w, dst_clip_h, dst_w,
766 dc->clip.mask_x, dc->clip.mask_y,
767 row_ptr, lin_ptr, dc->clip.mask,
768 dptr, func, func2, mul_col);
633 769
634 dptr += dst_w; 770 }
771 else
772 {
773 _evas_common_scale_rgba_sample_scale_nomask(0,
774 dst_clip_w, dst_clip_h, dst_w,
775 row_ptr, lin_ptr,
776 dptr, func, mul_col);
635 } 777 }
636 } 778 }
637 } 779 }
@@ -639,3 +781,95 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
639 781
640 return EINA_TRUE; 782 return EINA_TRUE;
641} 783}
784
785static void *
786_evas_common_scale_sample_thread(void *data EINA_UNUSED,
787 Eina_Thread t EINA_UNUSED)
788{
789 Evas_Scale_Msg *msg;
790 Evas_Scale_Thread *todo = NULL;
791
792 do
793 {
794 void *ref;
795
796 todo = NULL;
797
798 msg = eina_thread_queue_wait(thread_queue, &ref);
799 if (msg)
800 {
801 int h;
802
803 todo = msg->task;
804 eina_thread_queue_wait_done(thread_queue, &ref);
805
806 if (!todo) goto end;
807
808 h = todo->dst_clip_h >> 1;
809
810 if (todo->mask8)
811 _evas_common_scale_rgba_sample_scale_mask(h,
812 todo->dst_clip_x, todo->dst_clip_y,
813 todo->dst_clip_w, todo->dst_clip_h,
814 todo->dst_w,
815 todo->mask_x, todo->mask_y,
816 todo->row_ptr, todo->lin_ptr, todo->mask8,
817 todo->dptr, todo->func, todo->func2,
818 todo->mul_col);
819 else
820 _evas_common_scale_rgba_sample_scale_nomask(h,
821 todo->dst_clip_w, todo->dst_clip_h,
822 todo->dst_w,
823 todo->row_ptr, todo->lin_ptr,
824 todo->dptr, todo->func, todo->mul_col);
825 }
826
827 end:
828 msg = eina_thread_queue_send(main_queue, sizeof (Evas_Scale_Msg), &ref);
829 msg->task = NULL;
830 eina_thread_queue_send_done(main_queue, ref);
831 }
832 while (todo);
833
834 return NULL;
835}
836
837EAPI void
838evas_common_scale_sample_init(void)
839{
840 if (eina_cpu_count() <= 2) return ;
841
842 thread_queue = eina_thread_queue_new();
843 main_queue = eina_thread_queue_new();
844
845 if (!eina_thread_create(&scaling_thread, EINA_THREAD_NORMAL, -1,
846 _evas_common_scale_sample_thread, NULL))
847 {
848 return;
849 }
850
851 use_thread = EINA_TRUE;
852}
853
854EAPI void
855evas_common_scale_sample_shutdown(void)
856{
857 Evas_Scale_Msg *msg;
858 void *ref;
859
860 if (!use_thread) return ;
861
862 msg = eina_thread_queue_send(thread_queue, sizeof (Evas_Scale_Msg), &ref);
863 msg->task = NULL;
864 eina_thread_queue_send_done(thread_queue, ref);
865
866 /* Here is the thread commiting succide*/
867
868 msg = eina_thread_queue_wait(main_queue, &ref);
869 if (msg) eina_thread_queue_wait_done(main_queue, ref);
870
871 eina_thread_join(scaling_thread);
872
873 eina_thread_queue_free(thread_queue);
874 eina_thread_queue_free(main_queue);
875}