2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 // THIS IS DEPRECATED. WILL GO EVENTUALLTY. NO NEED TO SUPPORT ANYMORE
7 #include "evas_common.h"
9 #ifdef BUILD_PIPE_RENDER
11 #ifdef EVAS_FRAME_QUEUING
13 static Evas_FrameQ gframeq; // global frameQ
16 evas_common_surface_alloc(void *surface, int x, int y, int w, int h)
18 Evas_Surface *e_surface;
20 e_surface = calloc(1, sizeof(Evas_Surface));
21 e_surface->im = surface;
22 LKL(e_surface->im->ref_fq_add);
23 e_surface->im->ref_fq[0]++;
24 LKU(e_surface->im->ref_fq_add);
34 evas_common_surface_dealloc(Evas_Surface *surface)
36 Evas_Surface *d_surface;
41 surface = (Evas_Surface *)eina_inlist_remove(EINA_INLIST_GET(surface), EINA_INLIST_GET(d_surface));
42 LKL(d_surface->im->ref_fq_del);
43 d_surface->im->ref_fq[1]++;
44 LKU(d_surface->im->ref_fq_del);
52 evas_common_surface_add(Evas_Frame *frame, Evas_Surface *surface)
54 frame->surfaces = (Evas_Surface *)eina_inlist_append(EINA_INLIST_GET(frame->surfaces), EINA_INLIST_GET(surface));
58 evas_common_frame_alloc()
62 frame = calloc(1, sizeof(Evas_Frame));
63 frame->surfaces = NULL;
68 evas_common_frame_dealloc(Evas_Frame *frame)
70 evas_common_surface_dealloc(frame->surfaces);
75 evas_common_frame_add(Evas_FrameQ *frameq, Evas_Frame *frame)
77 Evas_Frame *temp_frame;
80 while(eina_inlist_count(EINA_INLIST_GET(frameq->frames)) >= frameq->frameq_sz)
82 /* wait a worker thread finish previous frame */
83 pthread_cond_wait(&(frameq->cond_done), &(frameq->mutex));
85 frameq->frames = (Evas_Frame *) eina_inlist_append(EINA_INLIST_GET(frameq->frames), EINA_INLIST_GET(frame));
87 // this frame need not to be scheduled for flushing time
88 EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), temp_frame)
90 if (!temp_frame->ready)
95 if (temp_frame && temp_frame == frame)
96 frame->dont_schedule = 1;
100 pthread_cond_signal(&(frameq->cond_new));
104 evas_common_frameq_new_surface (void *surface, int x, int y, int w, int h)
106 return evas_common_surface_alloc(surface, x, y, w, h);
110 evas_common_frameq_add_surface(Evas_Surface *surface)
112 evas_common_surface_add(gframeq.cur_frame, surface);
116 evas_common_frameq_set_frame_data(void *data,
117 void (*fn_output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h),
118 void (*fn_output_flush) (void *data),
119 void (*fn_output_set_priv)(void *data, void *cur, void *prev))
121 if (gframeq.cur_frame)
123 gframeq.cur_frame->data = data;
124 gframeq.cur_frame->output_redraws_next_update_push = fn_output_redraws_next_update_push;
125 gframeq.cur_frame->output_flush = fn_output_flush;
126 gframeq.cur_frame->output_set_priv = fn_output_set_priv;
131 evas_common_frameq_prepare_frame()
133 if (!gframeq.cur_frame )
135 gframeq.cur_frame = evas_common_frame_alloc();
140 evas_common_frameq_ready_frame()
142 if (gframeq.cur_frame)
144 evas_common_frame_add(&gframeq, gframeq.cur_frame);
145 gframeq.cur_frame = NULL; // create a new frame for the next frame later
151 evas_common_frameq_init()
153 gframeq.frames = NULL;
154 pthread_cond_init(&(gframeq.cond_new), NULL);
155 pthread_cond_init(&(gframeq.cond_ready), NULL);
156 pthread_cond_init(&(gframeq.cond_done), NULL);
158 gframeq.initialised = 0; // worker thread are not created yet
159 gframeq.frameq_sz = 1; // this value ensures the first frame can be enqueued.
163 evas_common_frameq_destroy()
165 #if 0 // let them destroyed indirectly with program exit
167 pthread_cond_destroy(&(gframeq.cond_new));
168 pthread_cond_destroy(&(gframeq.cond_ready));
169 pthread_cond_destroy(&(gframeq.cond_done));
174 gframeq.frames = NULL;
175 gframeq.initialised = 0;
179 evas_common_frameq_flush()
181 if (! evas_common_frameq_enabled())
185 while(eina_inlist_count(EINA_INLIST_GET(gframeq.frames)) > 0)
187 /* wait a worker thread finish previous frame */
188 pthread_cond_wait(&(gframeq.cond_done), &(gframeq.mutex));
195 evas_common_frameq_flush_ready ()
201 evas_common_frameq_get_frameq_sz()
203 return gframeq.frameq_sz;
207 evas_common_frameq_enabled()
209 return gframeq.initialised;
213 static RGBA_Pipe *evas_common_pipe_add(RGBA_Pipe *pipe, RGBA_Pipe_Op **op);
214 static void evas_common_pipe_draw_context_copy(RGBA_Draw_Context *dc, RGBA_Pipe_Op *op);
215 static void evas_common_pipe_op_free(RGBA_Pipe_Op *op);
219 evas_common_pipe_add(RGBA_Pipe *pipe, RGBA_Pipe_Op **op)
227 p = calloc(1, sizeof(RGBA_Pipe));
229 pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
231 p = (RGBA_Pipe *)(EINA_INLIST_GET(pipe))->last;
232 if (p->op_num == PIPE_LEN)
234 p = calloc(1, sizeof(RGBA_Pipe));
236 pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
239 *op = &(p->op[p->op_num - 1]);
242 /* FIXME: PTHREAD init any thread locks etc */
248 evas_common_pipe_draw_context_copy(RGBA_Draw_Context *dc, RGBA_Pipe_Op *op)
250 memcpy(&(op->context), dc, sizeof(RGBA_Draw_Context));
251 if (op->context.cutout.active > 0)
253 op->context.cutout.rects = malloc(sizeof(Cutout_Rect) * op->context.cutout.active);
254 memcpy(op->context.cutout.rects, dc->cutout.rects, sizeof(Cutout_Rect) * op->context.cutout.active);
258 op->context.cutout.rects = NULL;
263 evas_common_pipe_op_free(RGBA_Pipe_Op *op)
265 evas_common_draw_context_apply_clean_cutouts(&op->context.cutout);
271 evas_common_pipe_thread(void *data)
275 // INF("TH [...........");
279 RGBA_Pipe_Thread_Info *info;
282 /* wait for start signal */
283 // INF(" TH %i START...", thinfo->thread_num);
284 pthread_barrier_wait(&(thinfo->barrier[0]));
288 // thinfo->info = NULL;
289 // INF(" TH %i GO", thinfo->thread_num);
290 EINA_INLIST_FOREACH(EINA_INLIST_GET(info->im->pipe), p)
294 for (i = 0; i < p->op_num; i++)
296 if (p->op[i].op_func)
297 p->op[i].op_func(info->im, &(p->op[i]), info);
302 // INF(" TH %i DONE", thinfo->thread_num);
303 /* send finished signal */
304 pthread_barrier_wait(&(thinfo->barrier[1]));
309 #ifdef EVAS_FRAME_QUEUING
311 evas_common_frameq_release(void *data)
314 Evas_Frameq_Thread_Info *fq_info;
318 fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
319 frameq = fq_info->frameq;
321 /* This thread may or may not own the mutex.
322 * But there's no way to determine the ownership of the mutex, so release it anyway
328 evas_common_frameq_thread(void *data)
332 Evas_Surface *surface;
335 Evas_Frameq_Thread_Info *fq_info;
336 RGBA_Pipe_Thread_Info p_info;
339 fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
340 frameq = fq_info->frameq;
342 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
343 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
344 /* install thread cancelation cleanup handler */
345 pthread_cleanup_push(evas_common_frameq_release, data);
351 /* 1. pick a frame to draw */
355 EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), frame)
357 if (!frame->in_process)
359 frame->in_process = 1;
367 pthread_testcancel();
368 pthread_cond_wait(&(frameq->cond_new), &(frameq->mutex));
372 /* 2. draw selected frame */
373 EINA_INLIST_FOREACH(EINA_INLIST_GET(frame->surfaces), surface)
375 p_info.im = surface->im;
378 p_info.w = surface->im->cache_entry.w;
379 p_info.h = surface->im->cache_entry.h;
381 EINA_INLIST_FOREACH(EINA_INLIST_GET(p_info.im->pipe), p)
385 for (i = 0; i < p->op_num; i++)
387 if (p->op[i].op_func)
389 p->op[i].op_func(p_info.im, &(p->op[i]), &p_info);
394 /* push surface out */
395 if (! surface->dontpush)
397 frame->output_redraws_next_update_push(frame->data,
398 surface->im, surface->x, surface->y, surface->w, surface->h);
402 // record frame ready time, will be used in post worker thread, evas_common_frameq_thread_post()
403 gettimeofday(&frame->ready_time, NULL);
407 pthread_cond_signal(&frameq->cond_ready);
411 // Remove cleanup handler
412 pthread_cleanup_pop(0);
417 #define INTERVAL_QSIZE 17 // Actual size is 'INTERVAL_QSIZE - 1' because of not using index
418 #define SATISFACTION_THRESHOLD 4 // 4 ms --> 250 FPS
419 #define RESET_RATIO 4 // RESET_RATIO * [Average Ready Gap | get_max_interval()] --> Reset Threshold
420 #define DOUBLE_RESET_TIME_INTERVAL_THRESHOLD 16000 // make it double in case of less 16ms
421 #define RESET_ABSOLUTE_INTERVAL 600000 // 600 msec
429 static struct iq_node _IQ[INTERVAL_QSIZE];
430 static int _IQ_head = 0, _IQ_tail = 0;
431 static int _IQ_length = 0;
432 static long long min_ready, max_ready;
433 static long long average_interval;
436 _IQ_next_index(int i)
438 return (i + 1) % INTERVAL_QSIZE;
442 _IQ_previous_index(int i)
444 if (--i < 0) i += INTERVAL_QSIZE;
451 _IQ_length = _IQ_head = _IQ_tail = 0;
452 min_ready = LLONG_MAX, max_ready = LLONG_MIN;
453 average_interval = 0;
459 return (_IQ_head == _IQ_tail) ? 1 : 0;
465 return (_IQ_head == ((_IQ_tail + 1) % INTERVAL_QSIZE)) ? 1 : 0;
469 _IQ_insert(long long ready_time, long long last_interval)
471 if (_IQ_full()) return;
475 if (last_interval < 0)
477 last_interval = -last_interval;
479 _IQ[_IQ_tail].rt = ready_time;
480 _IQ[_IQ_tail].ri = last_interval;
481 min_ready = ready_time - last_interval;
482 max_ready = ready_time;
483 _IQ_tail = _IQ_next_index(_IQ_tail);
488 if (max_ready < ready_time)
490 _IQ[_IQ_tail].rt = ready_time;
491 _IQ[_IQ_tail].ri = ready_time - max_ready;
492 _IQ_tail = _IQ_next_index(_IQ_tail);
494 max_ready = ready_time;
496 else if (ready_time < min_ready)
498 last_interval = _IQ[_IQ_head].ri;
499 _IQ[_IQ_head].ri = _IQ[_IQ_head].rt - ready_time;
500 _IQ_head = _IQ_previous_index(_IQ_head);
501 _IQ[_IQ_head].rt = ready_time;
502 _IQ[_IQ_head].ri = last_interval;
503 min_ready = ready_time;
509 for (i = _IQ_head; i != _IQ_tail; i = j)
511 j = _IQ_next_index(i);
512 if (_IQ[j].rt < ready_time)
518 for (k = _IQ_tail; k != j; k = l)
520 l = _IQ_previous_index(k);
523 i = _IQ_next_index(j);
524 _IQ[j].ri -= (_IQ[j].rt - ready_time);
525 _IQ[j].rt = ready_time;
526 _IQ[i].ri = _IQ[i].rt - ready_time;
527 _IQ_tail = _IQ_next_index(_IQ_tail);
531 average_interval = (max_ready - min_ready) / _IQ_length;
537 struct iq_node oldest;
538 if (_IQ_empty()) return 0;
539 oldest = _IQ[_IQ_head];
540 _IQ_head = ++_IQ_head % INTERVAL_QSIZE;
541 if (--_IQ_length == 0)
547 min_ready = _IQ[_IQ_head].rt;
548 average_interval = (max_ready - min_ready) / _IQ_length;
558 long long max = LLONG_MIN;
560 for ( i= _IQ_head ; i != _IQ_tail ; i = _IQ_next_index(i))
572 tv_to_long_long(struct timeval *tv)
579 return tv->tv_sec * 1000000LL + tv->tv_usec;
583 evas_common_frameq_schedule_flush_time(
584 int frameq_sz, int thread_no,
585 long long last_ready_time, long long current_ready_time,
586 long long last_flush_time, int ready_frames_num,
589 // to get each time and to do others
590 long long current_time = 0LL;
591 long long current_ready_interval = 0LL;
592 long long theshold_time = SATISFACTION_THRESHOLD * 1000LL; // ms -> usec
593 long long reset_time_interval;
594 long long sleep_time = 0LL;
595 long long saved_ready_time, saved_ready_interval;
596 long long time_slept = 0LL;
597 static long long time_lag = 0;
599 int frameq_full_threshold =0;
601 int need_schedule = 0;
603 frameq_full_threshold = frameq_sz -thread_no; // Qsize - threads#
605 /* 1.5 defer flush time of current frame if need */
606 // in case of the first time, just keep ready time only
607 if (last_ready_time == 0LL)
609 last_ready_time = current_ready_time;
613 /* 1.5.1 get current ready time & interval */
614 saved_ready_time = current_ready_time;
615 saved_ready_interval = current_ready_interval = current_ready_time - last_ready_time;
616 // compensate a case which current ready time is older than previous one,
617 // doesn't work on the interval queue
618 if (current_ready_interval < 0)
620 current_ready_time = last_ready_time;
621 current_ready_interval = 0;
624 /* 1.5.2 get the reset time interval before keeping a new one */
627 reset_time_interval = RESET_RATIO * average_interval;
628 if (average_interval < DOUBLE_RESET_TIME_INTERVAL_THRESHOLD)
630 reset_time_interval *= 2;
634 /* 1.5.3 reset - if too late, discard all saved interval and start from here */
635 if (current_ready_interval > RESET_ABSOLUTE_INTERVAL)
639 else if (_IQ_length >= thread_no * 2 && current_ready_interval > reset_time_interval)
643 else if (_IQ_length >= thread_no && _IQ_length < thread_no * 2
644 && current_ready_interval > get_max_interval() * RESET_RATIO)
655 /* 1.5.4 enqueue - keep a new interval for next average interval */
660 _IQ_insert(saved_ready_time, saved_ready_interval);
662 /* 1.5.5 schedule - if faster than average interval, figure out sleep time to meet it */
667 if (_IQ_length >= thread_no * 2 && average_interval > theshold_time)
671 // compensate the case that postworker blocks the workers from getting a new fresh frame
672 // It's actually occurred when during the wait time of postworker, the frame queue is full
673 // Consequently check the number of currently ready frames and apply some time drop to average time according to the number
674 if (ready_frames_num >= frameq_full_threshold)
680 gettimeofday(&now, NULL);
681 current_time = tv_to_long_long(&now);
682 time_lag += (current_time - last_flush_time);
683 sleep_time = (average_interval < time_lag) ? 0 : (average_interval - time_lag);
687 /* 1.5.6 sleep - actually sleep and get over-slept time (time_lag) for next frame */
690 sleep_time = sleep_time * 9 / 10;
691 usleep((unsigned int)sleep_time);
692 gettimeofday(&now, NULL);
693 time_slept = tv_to_long_long(&now) - current_time;
694 time_lag = time_slept - sleep_time;
701 last_ready_time = current_ready_time;
704 return last_ready_time;
708 evas_common_frameq_thread_post(void *data)
712 Evas_Surface *surface;
715 Evas_Frameq_Thread_Info *fq_info;
716 RGBA_Pipe_Thread_Info p_info;
717 Eina_List *pending_writes = NULL;
718 Eina_List *prev_pending_writes = NULL;
720 long long last_ready_time = 0LL;
721 long long current_ready_time;
722 Evas_Frame *temp_frame = NULL;
723 int ready_frames_num;
724 long long last_flush_time = 0LL;
726 int dont_schedule = 0;
729 fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
730 frameq = fq_info->frameq;
732 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
733 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
734 /* install thread cancelation cleanup handler */
735 pthread_cleanup_push(evas_common_frameq_release, data);
741 /* 1. wait the first frame being done */
743 while(!frameq->frames || !frameq->frames->ready)
745 pthread_cond_wait(&(frameq->cond_ready), &(frameq->mutex));
747 frame = frameq->frames;
749 /* 1.5. prepare to schedule flush time */
750 current_ready_time = tv_to_long_long(&frame->ready_time);
751 ready_frames_num = 0;
752 EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), temp_frame)
754 if (temp_frame->ready == 1)
759 dont_schedule = (frame->dont_schedule)?1:0;
762 /* 2. generate pending_writes */
763 EINA_INLIST_FOREACH(EINA_INLIST_GET(frame->surfaces), surface)
765 evas_common_pipe_flush(surface->im);
766 if (! surface->dontpush)
768 pending_writes = eina_list_append(pending_writes, surface->im);
772 /* 2.5. schedule flush time */
773 last_ready_time = evas_common_frameq_schedule_flush_time(
774 frameq->frameq_sz, frameq->thread_num,
775 last_ready_time, current_ready_time,
776 last_flush_time, ready_frames_num, dont_schedule);
778 /* 3. flush redraws */
779 frame->output_set_priv(frame->data, pending_writes, prev_pending_writes);
780 frame->output_flush(frame->data);
781 gettimeofday(&now, NULL);
782 // keep as the last flush time
783 last_flush_time = now.tv_sec * 1000000LL + now.tv_usec;
785 prev_pending_writes = pending_writes;
786 pending_writes = NULL;
788 /* 4. remove this frame from the frame queue */
791 (Evas_Frame *)eina_inlist_remove(EINA_INLIST_GET(frameq->frames),
792 EINA_INLIST_GET(frame));
795 pthread_cond_broadcast(&frameq->cond_done);
796 evas_common_frame_dealloc(frame);
799 // Remove cleanup handler
800 pthread_cleanup_pop(0);
804 #endif /* EVAS_FRAME_QUEUING */
808 static int thread_num = 0;
809 static Thinfo thinfo[TH_MAX];
810 static pthread_barrier_t thbarrier[2];
814 evas_common_pipe_begin(RGBA_Image *im)
819 #ifdef EVAS_FRAME_QUEUING
823 if (!im->pipe) return;
824 if (thread_num == 1) return;
826 h = im->cache_entry.h / thread_num;
828 for (i = 0; i < thread_num; i++)
830 RGBA_Pipe_Thread_Info *info;
832 // if (y >= im->cache_entry.h) break;
833 info = calloc(1, sizeof(RGBA_Pipe_Thread_Info));
837 info->w = im->cache_entry.w;
839 info->h = thread_num;
843 info->w = im->cache_entry.w;
844 if (i == (thread_num - 1))
846 info->h = im->cache_entry.h - y;
854 thinfo[i].info = info;
856 /* tell worker threads to start */
857 pthread_barrier_wait(&(thbarrier[0]));
861 #ifdef EVAS_FRAME_QUEUING
863 evas_common_frameq_begin()
867 Evas_Frameq_Thread_Info *fp_info;
871 int set_cpu_affinity=1;
873 if (!gframeq.initialised)
877 cpunum = eina_cpu_count();
878 gframeq.thread_num = cpunum;
879 gframeq.frameq_sz = cpunum * FRAMEQ_SZ_PER_THREAD;
881 for (i = 0; i < gframeq.thread_num; i++)
884 fp_info = calloc(1, sizeof(Evas_Frameq_Thread_Info));
885 fp_info->frameq = &gframeq;
887 gframeq.thinfo[i].thread_num = i;
888 gframeq.thinfo[i].fq_info = fp_info;
890 pthread_attr_init(&attr);
891 if (set_cpu_affinity)
894 CPU_SET((i+1) % cpunum, &cpu);
895 pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
898 pthread_create(&(gframeq.thinfo[i].thread_id), &attr,
899 evas_common_frameq_thread, &(gframeq.thinfo[i]));
901 pthread_attr_destroy(&attr);
902 pthread_detach(gframeq.thinfo[i].thread_id);
906 fp_info = calloc(1, sizeof(Evas_Frameq_Thread_Info));
907 fp_info->frameq = &gframeq;
909 gframeq.thinfo[i].thread_num = i;
910 gframeq.thinfo[i].fq_info = fp_info;
912 pthread_attr_init(&attr);
913 if (set_cpu_affinity)
916 CPU_SET((i+1) % cpunum, &cpu);
917 pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
920 pthread_create(&(gframeq.thinfo[i].thread_id), &attr,
921 evas_common_frameq_thread_post, &(gframeq.thinfo[i]));
922 pthread_attr_destroy(&attr);
923 pthread_detach(gframeq.thinfo[i].thread_id);
925 gframeq.initialised = 1; // now worker threads are created.
927 #endif /* BUILD_PTHREAD */
931 evas_common_frameq_finish()
935 /* 1. cancel all worker threads */
936 for (i = 0; i < gframeq.thread_num; i++)
938 pthread_cancel(gframeq.thinfo[i].thread_id);
940 // cancel post-worker thread
941 pthread_cancel(gframeq.thinfo[i].thread_id);
943 /* 2. send signal to worker threads so that they enter to the thread cancelation cleanup handler */
944 for (i = 0; i < gframeq.thread_num; i++)
946 pthread_cond_signal(&(gframeq.cond_new));
948 // send signal to post-worker thread
949 pthread_cond_signal(&(gframeq.cond_ready));
951 /* all the workers were created and detached before
952 * so don't need to join them here.
957 #endif /* EVAS_FRAME_QUEUING */
960 evas_common_pipe_flush(RGBA_Image *im)
966 if (!im->pipe) return;
968 #ifndef EVAS_FRAME_QUEUING
973 /* sync worker threads */
974 pthread_barrier_wait(&(thbarrier[1]));
979 /* process pipe - 1 thead */
980 for (p = im->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
982 for (i = 0; i < p->op_num; i++)
984 if (p->op[i].op_func)
986 p->op[i].op_func(im, &(p->op[i]), NULL);
991 #endif /* !EVAS_FRAME_QUEUING */
992 evas_common_cpu_end_opt();
993 evas_common_pipe_free(im);
997 evas_common_pipe_free(RGBA_Image *im)
1003 if (!im->pipe) return;
1004 /* FIXME: PTHREAD join all threads here (if not finished) */
1010 for (i = 0; i < p->op_num; i++)
1012 if (p->op[i].free_func)
1014 p->op[i].free_func(&(p->op[i]));
1017 im->pipe = (RGBA_Pipe *)eina_inlist_remove(EINA_INLIST_GET(im->pipe), EINA_INLIST_GET(p));
1025 /**************** RECT ******************/
1027 evas_common_pipe_rectangle_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1031 RGBA_Draw_Context context;
1033 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1035 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1037 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1039 evas_common_rectangle_draw(dst, &(context),
1040 op->op.rect.x, op->op.rect.y,
1041 op->op.rect.w, op->op.rect.h);
1045 evas_common_rectangle_draw(dst, &(op->context),
1046 op->op.rect.x, op->op.rect.y,
1047 op->op.rect.w, op->op.rect.h);
1052 evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1053 int x, int y, int w, int h)
1057 if ((w < 1) || (h < 1)) return;
1058 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1059 if (!dst->pipe) return;
1064 op->op_func = evas_common_pipe_rectangle_draw_do;
1065 op->free_func = evas_common_pipe_op_free;
1066 evas_common_pipe_draw_context_copy(dc, op);
1069 /**************** LINE ******************/
1071 evas_common_pipe_line_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1075 RGBA_Draw_Context context;
1077 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1079 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1081 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1083 evas_common_line_draw(dst, &(context),
1084 op->op.line.x0, op->op.line.y0,
1085 op->op.line.x1, op->op.line.y1);
1089 evas_common_line_draw(dst, &(op->context),
1090 op->op.line.x0, op->op.line.y0,
1091 op->op.line.x1, op->op.line.y1);
1096 evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1097 int x0, int y0, int x1, int y1)
1101 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1102 if (!dst->pipe) return;
1103 op->op.line.x0 = x0;
1104 op->op.line.y0 = y0;
1105 op->op.line.x1 = x1;
1106 op->op.line.y1 = y1;
1107 op->op_func = evas_common_pipe_line_draw_do;
1108 op->free_func = evas_common_pipe_op_free;
1109 evas_common_pipe_draw_context_copy(dc, op);
1112 /**************** POLY ******************/
1114 evas_common_pipe_op_poly_free(RGBA_Pipe_Op *op)
1116 RGBA_Polygon_Point *p;
1118 while (op->op.poly.points)
1120 p = op->op.poly.points;
1121 op->op.poly.points = (RGBA_Polygon_Point *)eina_inlist_remove(EINA_INLIST_GET(op->op.poly.points),
1122 EINA_INLIST_GET(p));
1125 evas_common_pipe_op_free(op);
1129 evas_common_pipe_poly_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1133 RGBA_Draw_Context context;
1135 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1137 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1139 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1141 evas_common_polygon_draw(dst, &(context),
1142 op->op.poly.points, 0, 0);
1146 evas_common_polygon_draw(dst, &(op->context),
1147 op->op.poly.points, 0, 0);
1152 evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1153 RGBA_Polygon_Point *points, int x, int y)
1156 RGBA_Polygon_Point *pts = NULL, *p, *pp;
1158 if (!points) return;
1159 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1160 if (!dst->pipe) return;
1161 /* FIXME: copy points - maybe we should refcount? */
1162 for (p = points; p; p = (RGBA_Polygon_Point *)(EINA_INLIST_GET(p))->next)
1164 pp = calloc(1, sizeof(RGBA_Polygon_Point));
1169 pts = (RGBA_Polygon_Point *)eina_inlist_append(EINA_INLIST_GET(pts), EINA_INLIST_GET(pp));
1172 op->op.poly.points = pts;
1173 op->op_func = evas_common_pipe_poly_draw_do;
1174 op->free_func = evas_common_pipe_op_poly_free;
1175 evas_common_pipe_draw_context_copy(dc, op);
1178 /**************** GRAD ******************/
1180 evas_common_pipe_op_grad_free(RGBA_Pipe_Op *op)
1182 #ifdef EVAS_FRAME_QUEUING
1183 LKL(op->op.grad.grad->ref_fq_del);
1184 op->op.grad.grad->ref_fq[1]++;
1185 LKU(op->op.grad.grad->ref_fq_del);
1186 pthread_cond_signal(&(op->op.grad.grad->cond_fq_del));
1188 evas_common_gradient_free(op->op.grad.grad);
1190 evas_common_pipe_op_free(op);
1193 #ifdef EVAS_FRAME_QUEUING
1195 evas_common_pipe_op_grad_flush(RGBA_Gradient *gr)
1197 if (! evas_common_frameq_enabled())
1200 LKL(gr->ref_fq_add);
1201 LKL(gr->ref_fq_del);
1203 while (gr->ref_fq[0] != gr->ref_fq[1])
1204 pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
1206 LKU(gr->ref_fq_del);
1207 LKU(gr->ref_fq_add);
1212 evas_common_pipe_grad_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1216 RGBA_Draw_Context context;
1218 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1220 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1222 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1224 evas_common_gradient_draw(dst, &(context),
1225 op->op.grad.x, op->op.grad.y,
1226 op->op.grad.w, op->op.grad.h,
1231 evas_common_gradient_draw(dst, &(op->context),
1232 op->op.grad.x, op->op.grad.y,
1233 op->op.grad.w, op->op.grad.h,
1239 evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1240 int x, int y, int w, int h, RGBA_Gradient *gr)
1245 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1246 if (!dst->pipe) return;
1251 #ifdef EVAS_FRAME_QUEUING
1252 LKL(gr->ref_fq_add);
1254 LKU(gr->ref_fq_add);
1258 op->op.grad.grad = gr;
1259 op->op_func = evas_common_pipe_grad_draw_do;
1260 op->free_func = evas_common_pipe_op_grad_free;
1261 evas_common_pipe_draw_context_copy(dc, op);
1264 /**************** GRAD2 ******************/
1266 evas_common_pipe_op_grad2_free(RGBA_Pipe_Op *op)
1268 #ifdef EVAS_FRAME_QUEUING
1269 LKL(op->op.grad2.grad->ref_fq_del);
1270 op->op.grad2.grad->ref_fq[1]++;
1271 LKU(op->op.grad2.grad->ref_fq_del);
1272 pthread_cond_signal(&(op->op.grad2.grad->cond_fq_del));
1274 evas_common_gradient2_free(op->op.grad2.grad);
1276 evas_common_pipe_op_free(op);
1279 #ifdef EVAS_FRAME_QUEUING
1281 evas_common_pipe_op_grad2_flush(RGBA_Gradient2 *gr)
1283 if (! evas_common_frameq_enabled())
1286 LKL(gr->ref_fq_add);
1287 LKL(gr->ref_fq_del);
1289 while (gr->ref_fq[0] != gr->ref_fq[1])
1290 pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
1292 LKU(gr->ref_fq_del);
1293 LKU(gr->ref_fq_add);
1298 evas_common_pipe_grad2_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1302 RGBA_Draw_Context context;
1304 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1306 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1308 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1310 evas_common_gradient2_draw(dst, &(context),
1311 op->op.grad2.x, op->op.grad2.y,
1312 op->op.grad2.w, op->op.grad2.h,
1317 evas_common_gradient2_draw(dst, &(op->context),
1318 op->op.grad2.x, op->op.grad2.y,
1319 op->op.grad2.w, op->op.grad2.h,
1325 evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1326 int x, int y, int w, int h, RGBA_Gradient2 *gr)
1331 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1332 if (!dst->pipe) return;
1337 #ifdef EVAS_FRAME_QUEUING
1338 LKL(gr->ref_fq_add);
1340 LKU(gr->ref_fq_add);
1344 op->op.grad2.grad = gr;
1345 op->op_func = evas_common_pipe_grad2_draw_do;
1346 op->free_func = evas_common_pipe_op_grad2_free;
1347 evas_common_pipe_draw_context_copy(dc, op);
1350 /**************** TEXT ******************/
1352 evas_common_pipe_op_text_free(RGBA_Pipe_Op *op)
1354 #ifdef EVAS_FRAME_QUEUING
1355 LKL(op->op.text.font->ref_fq_del);
1356 op->op.text.font->ref_fq[1]++;
1357 LKU(op->op.text.font->ref_fq_del);
1358 pthread_cond_signal(&(op->op.text.font->cond_fq_del));
1360 evas_common_font_free(op->op.text.font);
1362 free(op->op.text.text);
1363 evas_common_pipe_op_free(op);
1366 #ifdef EVAS_FRAME_QUEUING
1367 /* flush all op using @fn */
1369 evas_common_pipe_op_text_flush(RGBA_Font *fn)
1371 if (! evas_common_frameq_enabled())
1374 LKL(fn->ref_fq_add);
1375 LKL(fn->ref_fq_del);
1377 while (fn->ref_fq[0] != fn->ref_fq[1])
1378 pthread_cond_wait(&(fn->cond_fq_del), &(fn->ref_fq_del));
1380 LKU(fn->ref_fq_del);
1381 LKU(fn->ref_fq_add);
1386 evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1390 RGBA_Draw_Context context;
1392 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1394 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1396 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1398 evas_common_font_draw(dst, &(context),
1399 op->op.text.font, op->op.text.x, op->op.text.y,
1404 evas_common_font_draw(dst, &(op->context),
1405 op->op.text.font, op->op.text.x, op->op.text.y,
1411 evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
1412 RGBA_Font *fn, int x, int y, const char *text)
1416 if ((!fn) || (!text)) return;
1417 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1418 if (!dst->pipe) return;
1421 op->op.text.text = strdup(text);
1422 #ifdef EVAS_FRAME_QUEUING
1423 LKL(fn->ref_fq_add);
1425 LKU(fn->ref_fq_add);
1429 op->op.text.font = fn;
1430 op->op_func = evas_common_pipe_text_draw_do;
1431 op->free_func = evas_common_pipe_op_text_free;
1432 evas_common_pipe_draw_context_copy(dc, op);
1435 /**************** IMAGE *****************/
1437 evas_common_pipe_op_image_free(RGBA_Pipe_Op *op)
1439 #ifdef EVAS_FRAME_QUEUING
1440 LKL(op->op.image.src->ref_fq_del);
1441 op->op.image.src->ref_fq[1]++;
1442 LKU(op->op.image.src->ref_fq_del);
1443 pthread_cond_signal(&(op->op.image.src->cond_fq_del));
1445 op->op.image.src->ref--;
1446 if (op->op.image.src->ref == 0)
1448 evas_cache_image_drop(&op->op.image.src->cache_entry);
1451 evas_common_pipe_op_free(op);
1454 #ifdef EVAS_FRAME_QUEUING
1456 evas_common_pipe_op_image_flush(RGBA_Image *im)
1458 if (! evas_common_frameq_enabled())
1461 LKL(im->ref_fq_add);
1462 LKL(im->ref_fq_del);
1464 while (im->ref_fq[0] != im->ref_fq[1])
1465 pthread_cond_wait(&(im->cond_fq_del), &(im->ref_fq_del));
1467 LKU(im->ref_fq_del);
1468 LKU(im->ref_fq_add);
1473 evas_common_pipe_image_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1477 RGBA_Draw_Context context;
1479 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1481 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1483 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1487 evas_common_rgba_image_scalecache_do(op->op.image.src,
1489 op->op.image.smooth,
1499 if (op->op.image.smooth)
1501 evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
1514 evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
1530 evas_common_rgba_image_scalecache_do(op->op.image.src,
1531 dst, &(op->context),
1532 op->op.image.smooth,
1542 if (op->op.image.smooth)
1544 evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
1545 dst, &(op->context),
1557 evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
1558 dst, &(op->context),
1573 evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst,
1574 RGBA_Draw_Context *dc, int smooth,
1575 int src_region_x, int src_region_y,
1576 int src_region_w, int src_region_h,
1577 int dst_region_x, int dst_region_y,
1578 int dst_region_w, int dst_region_h)
1583 // evas_common_pipe_flush(src);
1584 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1585 if (!dst->pipe) return;
1586 op->op.image.smooth = smooth;
1587 op->op.image.sx = src_region_x;
1588 op->op.image.sy = src_region_y;
1589 op->op.image.sw = src_region_w;
1590 op->op.image.sh = src_region_h;
1591 op->op.image.dx = dst_region_x;
1592 op->op.image.dy = dst_region_y;
1593 op->op.image.dw = dst_region_w;
1594 op->op.image.dh = dst_region_h;
1595 #ifdef EVAS_FRAME_QUEUING
1596 LKL(src->ref_fq_add);
1598 LKU(src->ref_fq_add);
1602 op->op.image.src = src;
1603 op->op_func = evas_common_pipe_image_draw_do;
1604 op->free_func = evas_common_pipe_op_image_free;
1605 evas_common_pipe_draw_context_copy(dc, op);
1607 #ifdef EVAS_FRAME_QUEUING
1608 /* laod every src image here.
1609 * frameq utilize all cpu cores already by worker threads
1610 * so another threads and barrier waiting can't be of any benefit.
1611 * therefore, not instantiate loader threads.
1613 if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
1614 evas_cache_image_load_data(&src->cache_entry);
1615 evas_common_image_colorspace_normalize(src);
1617 evas_common_pipe_image_load(src);
1622 evas_common_pipe_op_map4_free(RGBA_Pipe_Op *op)
1624 #ifdef EVAS_FRAME_QUEUING
1625 LKL(op->op.image.src->ref_fq_del);
1626 op->op.image.src->ref_fq[1]++;
1627 LKU(op->op.image.src->ref_fq_del);
1629 op->op.map4.src->ref--;
1630 if (op->op.map4.src->ref == 0)
1631 evas_cache_image_drop(&op->op.map4.src->cache_entry);
1633 free(op->op.map4.p);
1634 evas_common_pipe_op_free(op);
1638 evas_common_pipe_map4_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
1642 RGBA_Draw_Context context;
1644 memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
1646 evas_common_draw_context_set_sli(&(context), info->y, info->h);
1648 evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
1651 evas_common_map4_rgba(op->op.map4.src, dst,
1652 &context, op->op.map4.p,
1653 op->op.map4.smooth, op->op.map4.level);
1657 evas_common_map4_rgba(op->op.map4.src, dst,
1658 &(op->context), op->op.map4.p,
1659 op->op.map4.smooth, op->op.map4.level);
1664 evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
1665 RGBA_Draw_Context *dc, RGBA_Map_Point *p,
1666 int smooth, int level)
1669 RGBA_Map_Point *pts_copy;
1673 pts_copy = malloc(sizeof (RGBA_Map_Point) * 4);
1674 if (!pts_copy) return;
1675 dst->pipe = evas_common_pipe_add(dst->pipe, &op);
1682 for (i = 0; i < 4; ++i)
1685 op->op.map4.smooth = smooth;
1686 op->op.map4.level = level;
1687 #ifdef EVAS_FRAME_QUEUING
1688 LKL(src->ref_fq_add);
1690 LKU(src->ref_fq_add);
1694 op->op.map4.src = src;
1695 op->op.map4.p = pts_copy;
1696 op->op_func = evas_common_pipe_map4_draw_do;
1697 op->free_func = evas_common_pipe_op_map4_free;
1698 evas_common_pipe_draw_context_copy(dc, op);
1700 #ifdef EVAS_FRAME_QUEUING
1701 /* laod every src image here.
1702 * frameq utilize all cpu cores already by worker threads
1703 * so another threads and barrier waiting can't be of any benefit.
1704 * therefore, not instantiate loader threads.
1706 if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
1707 evas_cache_image_load_data(&src->cache_entry);
1708 evas_common_image_colorspace_normalize(src);
1710 evas_common_pipe_image_load(src);
1715 evas_common_pipe_map4_render(RGBA_Image *root)
1720 /* Map imply that we need to process them recursively first. */
1721 for (p = root->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
1723 for (i = 0; i < p->op_num; i++)
1725 if (p->op[i].op_func == evas_common_pipe_map4_draw_do)
1727 if (p->op[i].op.map4.src->pipe)
1728 evas_common_pipe_map4_render(p->op[i].op.map4.src);
1730 else if (p->op[i].op_func == evas_common_pipe_image_draw_do)
1732 if (p->op[i].op.image.src->pipe)
1733 evas_common_pipe_map4_render(p->op[i].op.image.src);
1738 evas_common_pipe_begin(root);
1739 evas_common_pipe_flush(root);
1742 #ifdef BUILD_PTHREAD
1743 static Eina_List *task = NULL;
1744 static Thinfo task_thinfo[TH_MAX];
1745 static pthread_barrier_t task_thbarrier[2];
1746 static LK(task_mutext) = PTHREAD_MUTEX_INITIALIZER;
1749 #ifdef BUILD_PTHREAD
1751 evas_common_pipe_load(void *data)
1758 /* wait for start signal */
1759 pthread_barrier_wait(&(thinfo->barrier[0]));
1763 RGBA_Image *im = NULL;
1766 im = eina_list_data_get(task);
1767 task = eina_list_remove_list(task, task);
1772 if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
1773 evas_cache_image_load_data(&im->cache_entry);
1774 evas_common_image_colorspace_normalize(im);
1776 im->flags &= ~RGBA_IMAGE_TODO_LOAD;
1780 /* send finished signal */
1781 pthread_barrier_wait(&(thinfo->barrier[1]));
1789 evas_common_pipe_image_load_do(void)
1791 #ifdef BUILD_PTHREAD
1792 /* Notify worker thread. */
1793 pthread_barrier_wait(&(task_thbarrier[0]));
1795 /* sync worker threads */
1796 pthread_barrier_wait(&(task_thbarrier[1]));
1801 evas_common_pipe_init(void)
1803 #ifdef BUILD_PTHREAD
1804 if (thread_num == 0)
1809 cpunum = eina_cpu_count();
1810 thread_num = cpunum;
1811 if (thread_num == 1) return EINA_FALSE;
1813 pthread_barrier_init(&(thbarrier[0]), NULL, thread_num + 1);
1814 pthread_barrier_init(&(thbarrier[1]), NULL, thread_num + 1);
1815 for (i = 0; i < thread_num; i++)
1817 pthread_attr_t attr;
1820 pthread_attr_init(&attr);
1822 CPU_SET(i % cpunum, &cpu);
1823 pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
1824 thinfo[i].thread_num = i;
1825 thinfo[i].info = NULL;
1826 thinfo[i].barrier = thbarrier;
1827 /* setup initial locks */
1828 pthread_create(&(thinfo[i].thread_id), &attr,
1829 evas_common_pipe_thread, &(thinfo[i]));
1830 pthread_attr_destroy(&attr);
1833 pthread_barrier_init(&(task_thbarrier[0]), NULL, thread_num + 1);
1834 pthread_barrier_init(&(task_thbarrier[1]), NULL, thread_num + 1);
1835 for (i = 0; i < thread_num; i++)
1837 pthread_attr_t attr;
1840 pthread_attr_init(&attr);
1842 CPU_SET(i % cpunum, &cpu);
1843 pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
1844 task_thinfo[i].thread_num = i;
1845 task_thinfo[i].info = NULL;
1846 task_thinfo[i].barrier = task_thbarrier;
1847 /* setup initial locks */
1848 pthread_create(&(task_thinfo[i].thread_id), &attr,
1849 evas_common_pipe_load, &(task_thinfo[i]));
1850 pthread_attr_destroy(&attr);
1853 if (thread_num == 1) return EINA_FALSE;
1860 evas_common_pipe_image_load(RGBA_Image *im)
1862 if (im->flags & RGBA_IMAGE_TODO_LOAD)
1865 if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888
1866 && !evas_cache_image_is_loaded(&(im->cache_entry)))
1869 if ((!im->cs.data) || ((!im->cs.dirty) && (!(im->flags & RGBA_IMAGE_IS_DIRTY))))
1875 task = eina_list_append(task, im);
1876 im->flags |= RGBA_IMAGE_TODO_LOAD;
1880 evas_common_pipe_map4_begin(RGBA_Image *root)
1882 if (!evas_common_pipe_init())
1886 EINA_LIST_FREE(task, im)
1888 if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
1889 evas_cache_image_load_data(&im->cache_entry);
1890 evas_common_image_colorspace_normalize(im);
1892 im->flags &= ~RGBA_IMAGE_TODO_LOAD;
1896 evas_common_pipe_image_load_do();
1898 evas_common_pipe_map4_render(root);