summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCedric Bail <cedric@osg.samsung.com>2017-09-16 23:23:36 -0700
committerCedric Bail <cedric@osg.samsung.com>2017-09-17 11:49:48 -0700
commite380ddb742384546ad05a5f8f5472ecdce795538 (patch)
tree58cd8ea6ccf9ae8d170f1f6aa8995f085f29ef25 /src/lib
parent560e5c8e0f071d2cbaec0649bc1e8100d9e7f82e (diff)
ector: move RLE shape/stroke computation to a pool of thread.
This has been a long standing plan for improving performance in rendering vector object. Depending on the test, you will get an improvement between 10 to 35% when rendering vector based object. We are still maintaining the Cairo backend as the default one at the moment due to a lack of result comparison tests between the two engine. Hopefully we should get that covered and we can all enjoy a backend that is 4 times faster by default.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ector/software/ector_renderer_software_shape.c188
-rw-r--r--src/lib/ector/software/ector_software_private.h8
-rw-r--r--src/lib/ector/software/ector_software_rasterizer.c42
-rw-r--r--src/lib/ector/software/ector_software_surface.c9
4 files changed, 163 insertions, 84 deletions
diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c
index 5bbdbf1..25da9ca 100644
--- a/src/lib/ector/software/ector_renderer_software_shape.c
+++ b/src/lib/ector/software/ector_renderer_software_shape.c
@@ -13,16 +13,32 @@
13#include "ector_software_private.h" 13#include "ector_software_private.h"
14 14
15typedef struct _Ector_Renderer_Software_Shape_Data Ector_Renderer_Software_Shape_Data; 15typedef struct _Ector_Renderer_Software_Shape_Data Ector_Renderer_Software_Shape_Data;
16typedef struct _Ector_Software_Shape_Task Ector_Software_Shape_Task;
17
18struct _Ector_Software_Shape_Task
19{
20 Ector_Renderer_Software_Shape_Data *pd;
21
22 const Efl_Gfx_Path_Command *cmds;
23 const double *pts;
24
25 Efl_Gfx_Fill_Rule fill_rule;
26};
27
16struct _Ector_Renderer_Software_Shape_Data 28struct _Ector_Renderer_Software_Shape_Data
17{ 29{
18 Efl_Gfx_Shape_Public *public_shape; 30 Efl_Gfx_Shape_Public *public_shape;
19 31
20 Ector_Software_Surface_Data *surface; 32 Ector_Software_Surface_Data *surface;
21 Ector_Renderer_Shape_Data *shape; 33 Ector_Renderer_Shape_Data *shape;
22 Ector_Renderer_Data *base; 34 Ector_Renderer_Data *base;
23 35
24 Shape_Rle_Data *shape_data; 36 Shape_Rle_Data *shape_data;
25 Shape_Rle_Data *outline_data; 37 Shape_Rle_Data *outline_data;
38
39 Ector_Software_Shape_Task *task;
40
41 Eina_Bool done;
26}; 42};
27 43
28typedef struct _Outline 44typedef struct _Outline
@@ -511,70 +527,110 @@ _generate_shape_data(Ector_Renderer_Software_Shape_Data *pd)
511 return EINA_TRUE; 527 return EINA_TRUE;
512} 528}
513 529
514static void 530static Ector_Software_Shape_Task *
515_update_rle(Eo *obj, Ector_Renderer_Software_Shape_Data *pd) 531_need_update_rle(Eo *obj, Ector_Renderer_Software_Shape_Data *pd)
516{ 532{
517 const Efl_Gfx_Path_Command *cmds = NULL; 533 Ector_Software_Shape_Task *r;
518 const double *pts = NULL; 534 const Efl_Gfx_Path_Command *cmds;
519 Eina_Bool close_path; 535 const double *pts;
520 Efl_Gfx_Fill_Rule fill_rule; 536 Efl_Gfx_Fill_Rule fill_rule;
521 Outline *outline, *dash_outline; 537
538 if (!pd->done && pd->task) return pd->task;
539
540 if (!_generate_stroke_data(pd) &&
541 !_generate_shape_data(pd))
542 return NULL;
522 543
523 efl_gfx_path_get(obj, &cmds, &pts); 544 efl_gfx_path_get(obj, &cmds, &pts);
524 fill_rule = efl_gfx_shape_fill_rule_get(obj); 545 fill_rule = efl_gfx_shape_fill_rule_get(obj);
525 if (cmds && (_generate_stroke_data(pd) || _generate_shape_data(pd)))
526 {
527 outline = _outline_create();
528 close_path = _generate_outline(cmds, pts, outline);
529 if (fill_rule == EFL_GFX_FILL_RULE_ODD_EVEN)
530 outline->ft_outline.flags = SW_FT_OUTLINE_EVEN_ODD_FILL;
531 else
532 outline->ft_outline.flags = SW_FT_OUTLINE_NONE; // default is winding fill
533 546
534 _outline_transform(outline, pd->base->m); 547 if (!cmds) return NULL;
548
549 r = pd->task;
550 if (!r) r = malloc(sizeof (Ector_Software_Shape_Task));
551 if (!r) return NULL;
552
553 r->pd = pd;
554 r->cmds = cmds;
555 r->pts = pts;
556 r->fill_rule = fill_rule;
557
558 pd->done = EINA_FALSE;
559 pd->task = r;
535 560
536 //shape data generation 561 return r;
537 if (_generate_shape_data(pd)) 562}
538 pd->shape_data = ector_software_rasterizer_generate_rle_data(pd->surface->rasterizer, 563
539 &outline->ft_outline); 564static void
565_done_rle(void *data)
566{
567 Ector_Software_Shape_Task *task = data;
568
569 task->pd->done = EINA_TRUE;
570}
540 571
541 //stroke data generation 572static void
542 if ( _generate_stroke_data(pd)) 573_update_rle(void *data, Ector_Software_Thread *thread)
574{
575 Ector_Software_Shape_Task *task = data;
576 Eina_Bool close_path;
577 Outline *outline, *dash_outline;
578
579 outline = _outline_create();
580 close_path = _generate_outline(task->cmds, task->pts, outline);
581 if (task->fill_rule == EFL_GFX_FILL_RULE_ODD_EVEN)
582 outline->ft_outline.flags = SW_FT_OUTLINE_EVEN_ODD_FILL;
583 else
584 outline->ft_outline.flags = SW_FT_OUTLINE_NONE; // default is winding fill
585
586 _outline_transform(outline, task->pd->base->m);
587
588 //shape data generation
589 if (_generate_shape_data(task->pd))
590 task->pd->shape_data = ector_software_rasterizer_generate_rle_data(thread,
591 task->pd->surface->rasterizer,
592 &outline->ft_outline);
593
594 //stroke data generation
595 if (_generate_stroke_data(task->pd))
596 {
597 ector_software_rasterizer_stroke_set(thread, task->pd->surface->rasterizer,
598 (task->pd->public_shape->stroke.width *
599 task->pd->public_shape->stroke.scale),
600 task->pd->public_shape->stroke.cap,
601 task->pd->public_shape->stroke.join,
602 task->pd->base->m);
603
604 if (task->pd->public_shape->stroke.dash)
543 { 605 {
544 ector_software_rasterizer_stroke_set(pd->surface->rasterizer, 606 dash_outline = _outline_create();
545 (pd->public_shape->stroke.width * 607 close_path = _generate_dashed_outline(task->cmds, task->pts, dash_outline,
546 pd->public_shape->stroke.scale), 608 task->pd->public_shape->stroke.dash,
547 pd->public_shape->stroke.cap, 609 task->pd->public_shape->stroke.dash_length);
548 pd->public_shape->stroke.join, 610 _outline_transform(dash_outline, task->pd->base->m);
549 pd->base->m); 611 task->pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(thread,
550 612 task->pd->surface->rasterizer,
551 if (pd->public_shape->stroke.dash) 613 &dash_outline->ft_outline,
552 { 614 close_path);
553 dash_outline = _outline_create(); 615 _outline_destroy(dash_outline);
554 close_path = _generate_dashed_outline(cmds, pts, dash_outline, 616 }
555 pd->public_shape->stroke.dash, 617 else
556 pd->public_shape->stroke.dash_length); 618 {
557 _outline_transform(dash_outline, pd->base->m); 619 task->pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(thread,
558 pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->rasterizer, 620 task->pd->surface->rasterizer,
559 &dash_outline->ft_outline, 621 &outline->ft_outline,
560 close_path); 622 close_path);
561 _outline_destroy(dash_outline);
562 }
563 else
564 {
565 pd->outline_data = ector_software_rasterizer_generate_stroke_rle_data(pd->surface->rasterizer,
566 &outline->ft_outline,
567 close_path);
568 }
569 } 623 }
570 _outline_destroy(outline);
571 } 624 }
625 _outline_destroy(outline);
572} 626}
573 627
574static Eina_Bool 628static Eina_Bool
575_ector_renderer_software_shape_ector_renderer_prepare(Eo *obj, 629_ector_renderer_software_shape_ector_renderer_prepare(Eo *obj,
576 Ector_Renderer_Software_Shape_Data *pd) 630 Ector_Renderer_Software_Shape_Data *pd)
577{ 631{
632 Ector_Software_Shape_Task *task;
633
578 // FIXME: shouldn't this be part of the shape generic implementation? 634 // FIXME: shouldn't this be part of the shape generic implementation?
579 if (pd->shape->fill) 635 if (pd->shape->fill)
580 ector_renderer_prepare(pd->shape->fill); 636 ector_renderer_prepare(pd->shape->fill);
@@ -587,19 +643,25 @@ _ector_renderer_software_shape_ector_renderer_prepare(Eo *obj,
587 if (!pd->surface) 643 if (!pd->surface)
588 pd->surface = efl_data_xref(pd->base->surface, ECTOR_SOFTWARE_SURFACE_CLASS, obj); 644 pd->surface = efl_data_xref(pd->base->surface, ECTOR_SOFTWARE_SURFACE_CLASS, obj);
589 645
646 // Asynchronously lazy build of the RLE data for this shape
647 task = _need_update_rle(obj, pd);
648 if (task) ector_software_schedule(_update_rle, _done_rle, task);
649
590 return EINA_TRUE; 650 return EINA_TRUE;
591} 651}
592 652
593static Eina_Bool 653static Eina_Bool
594_ector_renderer_software_shape_ector_renderer_draw(Eo *obj, 654_ector_renderer_software_shape_ector_renderer_draw(Eo *obj,
595 Ector_Renderer_Software_Shape_Data *pd, 655 Ector_Renderer_Software_Shape_Data *pd,
596 Efl_Gfx_Render_Op op, Eina_Array *clips, 656 Efl_Gfx_Render_Op op, Eina_Array *clips,
597 unsigned int mul_col) 657 unsigned int mul_col)
598{ 658{
659 Ector_Software_Shape_Task *task;
599 int x, y; 660 int x, y;
600 661
601 // do lazy creation of rle 662 // check if RLE data are ready
602 _update_rle(obj, pd); 663 task = _need_update_rle(obj, pd);
664 if (task) ector_software_wait(_update_rle, _done_rle, task);
603 665
604 // adjust the offset 666 // adjust the offset
605 x = pd->surface->x + (int)pd->base->origin.x; 667 x = pd->surface->x + (int)pd->base->origin.x;
@@ -684,10 +746,10 @@ static void
684_ector_renderer_software_shape_path_changed(void *data, const Efl_Event *event EINA_UNUSED) 746_ector_renderer_software_shape_path_changed(void *data, const Efl_Event *event EINA_UNUSED)
685{ 747{
686 Ector_Renderer_Software_Shape_Data *pd = data; 748 Ector_Renderer_Software_Shape_Data *pd = data;
687 749
688 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data); 750 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
689 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data); 751 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
690 752
691 pd->shape_data = NULL; 753 pd->shape_data = NULL;
692 pd->outline_data = NULL; 754 pd->outline_data = NULL;
693} 755}
@@ -698,6 +760,8 @@ _ector_renderer_software_shape_efl_object_constructor(Eo *obj, Ector_Renderer_So
698 obj = efl_constructor(efl_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS)); 760 obj = efl_constructor(efl_super(obj, ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS));
699 if (!obj) return NULL; 761 if (!obj) return NULL;
700 762
763 pd->task = NULL;
764 pd->done = EINA_FALSE;
701 pd->public_shape = efl_data_xref(obj, EFL_GFX_SHAPE_MIXIN, obj); 765 pd->public_shape = efl_data_xref(obj, EFL_GFX_SHAPE_MIXIN, obj);
702 pd->shape = efl_data_xref(obj, ECTOR_RENDERER_SHAPE_MIXIN, obj); 766 pd->shape = efl_data_xref(obj, ECTOR_RENDERER_SHAPE_MIXIN, obj);
703 pd->base = efl_data_xref(obj, ECTOR_RENDERER_CLASS, obj); 767 pd->base = efl_data_xref(obj, ECTOR_RENDERER_CLASS, obj);
@@ -711,10 +775,14 @@ _ector_renderer_software_shape_efl_object_destructor(Eo *obj, Ector_Renderer_Sof
711{ 775{
712 // FIXME: As base class, destructor can't call destructor of mixin class. 776 // FIXME: As base class, destructor can't call destructor of mixin class.
713 // Call explicit API to free shape data. 777 // Call explicit API to free shape data.
778 if (!pd->done && pd->task)
779 ector_software_wait(_update_rle, _done_rle, pd->task);
780
714 efl_gfx_path_reset(obj); 781 efl_gfx_path_reset(obj);
715 782
716 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data); 783 if (pd->shape_data) ector_software_rasterizer_destroy_rle_data(pd->shape_data);
717 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data); 784 if (pd->outline_data) ector_software_rasterizer_destroy_rle_data(pd->outline_data);
785 free(pd->task);
718 786
719 efl_data_xunref(pd->base->surface, pd->surface, obj); 787 efl_data_xunref(pd->base->surface, pd->surface, obj);
720 efl_data_xunref(obj, pd->shape, obj); 788 efl_data_xunref(obj, pd->shape, obj);
diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h
index a255fd3..e35f681 100644
--- a/src/lib/ector/software/ector_software_private.h
+++ b/src/lib/ector/software/ector_software_private.h
@@ -95,13 +95,9 @@ typedef struct _Span_Data
95 95
96typedef struct _Software_Rasterizer 96typedef struct _Software_Rasterizer
97{ 97{
98 SW_FT_Raster raster;
99 SW_FT_Stroker stroker;
100
101 Span_Data fill_data; 98 Span_Data fill_data;
102 Eina_Matrix3 *transform; 99 Eina_Matrix3 *transform;
103 Eina_Rectangle system_clip; 100 Eina_Rectangle system_clip;
104
105} Software_Rasterizer; 101} Software_Rasterizer;
106 102
107struct _Ector_Software_Surface_Data 103struct _Ector_Software_Surface_Data
@@ -114,9 +110,9 @@ struct _Ector_Software_Surface_Data
114 110
115int ector_software_gradient_init(void); 111int ector_software_gradient_init(void);
116void ector_software_rasterizer_init(Software_Rasterizer *rasterizer); 112void ector_software_rasterizer_init(Software_Rasterizer *rasterizer);
117void ector_software_rasterizer_done(Software_Rasterizer *rasterizer);
118 113
119void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width, 114void ector_software_rasterizer_stroke_set(Ector_Software_Thread *thread, Software_Rasterizer *rasterizer,
115 double width,
120 Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style, Eina_Matrix3 *m); 116 Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style, Eina_Matrix3 *m);
121 117
122void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Eina_Matrix3 *t); 118void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Eina_Matrix3 *t);
diff --git a/src/lib/ector/software/ector_software_rasterizer.c b/src/lib/ector/software/ector_software_rasterizer.c
index 02f24df..fcbd3d0 100644
--- a/src/lib/ector/software/ector_software_rasterizer.c
+++ b/src/lib/ector/software/ector_software_rasterizer.c
@@ -300,14 +300,18 @@ _adjust_span_fill_methods(Span_Data *spdata)
300 } 300 }
301} 301}
302 302
303void ector_software_rasterizer_init(Software_Rasterizer *rasterizer) 303void ector_software_thread_init(Ector_Software_Thread *thread)
304{ 304{
305 // initialize the rasterizer and stroker 305 // initialize the rasterizer and stroker
306 sw_ft_grays_raster.raster_new(&rasterizer->raster); 306 sw_ft_grays_raster.raster_new(&thread->raster);
307 307
308 SW_FT_Stroker_New(&rasterizer->stroker); 308 SW_FT_Stroker_New(&thread->stroker);
309 SW_FT_Stroker_Set(rasterizer->stroker, 1<<6,SW_FT_STROKER_LINECAP_BUTT,SW_FT_STROKER_LINEJOIN_MITER,0); 309 SW_FT_Stroker_Set(thread->stroker, 1 << 6,
310 SW_FT_STROKER_LINECAP_BUTT, SW_FT_STROKER_LINEJOIN_MITER, 0);
311}
310 312
313void ector_software_rasterizer_init(Software_Rasterizer *rasterizer)
314{
311 //initialize the span data. 315 //initialize the span data.
312 rasterizer->fill_data.clip.enabled = EINA_FALSE; 316 rasterizer->fill_data.clip.enabled = EINA_FALSE;
313 rasterizer->fill_data.unclipped_blend = 0; 317 rasterizer->fill_data.unclipped_blend = 0;
@@ -316,13 +320,14 @@ void ector_software_rasterizer_init(Software_Rasterizer *rasterizer)
316 ector_software_gradient_init(); 320 ector_software_gradient_init();
317} 321}
318 322
319void ector_software_rasterizer_done(Software_Rasterizer *rasterizer) 323void ector_software_thread_shutdown(Ector_Software_Thread *thread)
320{ 324{
321 sw_ft_grays_raster.raster_done(rasterizer->raster); 325 sw_ft_grays_raster.raster_done(thread->raster);
322 SW_FT_Stroker_Done(rasterizer->stroker); 326 SW_FT_Stroker_Done(thread->stroker);
323} 327}
324 328
325void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, double width, 329void ector_software_rasterizer_stroke_set(Ector_Software_Thread *thread,
330 Software_Rasterizer *rasterizer EINA_UNUSED, double width,
326 Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style, 331 Efl_Gfx_Cap cap_style, Efl_Gfx_Join join_style,
327 Eina_Matrix3 *m) 332 Eina_Matrix3 *m)
328{ 333{
@@ -366,7 +371,7 @@ void ector_software_rasterizer_stroke_set(Software_Rasterizer *rasterizer, doubl
366 join = SW_FT_STROKER_LINEJOIN_MITER; 371 join = SW_FT_STROKER_LINEJOIN_MITER;
367 break; 372 break;
368 } 373 }
369 SW_FT_Stroker_Set(rasterizer->stroker, stroke_width, cap, join, 0); 374 SW_FT_Stroker_Set(thread->stroker, stroke_width, cap, join, 0);
370} 375}
371 376
372static void 377static void
@@ -393,7 +398,9 @@ _rle_generation_cb( int count, const SW_FT_Span* spans,void *user)
393} 398}
394 399
395Shape_Rle_Data * 400Shape_Rle_Data *
396ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline) 401ector_software_rasterizer_generate_rle_data(Ector_Software_Thread *thread,
402 Software_Rasterizer *rasterizer EINA_UNUSED,
403 SW_FT_Outline *outline)
397{ 404{
398 int i, rle_size; 405 int i, rle_size;
399 int l = 0, t = 0, r = 0, b = 0; 406 int l = 0, t = 0, r = 0, b = 0;
@@ -406,7 +413,7 @@ ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_
406 params.user = rle_data; 413 params.user = rle_data;
407 params.source = outline; 414 params.source = outline;
408 415
409 sw_ft_grays_raster.raster_render(rasterizer->raster, &params); 416 sw_ft_grays_raster.raster_render(thread->raster, &params);
410 417
411 // update RLE bounding box. 418 // update RLE bounding box.
412 span = rle_data->spans; 419 span = rle_data->spans;
@@ -429,22 +436,25 @@ ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_
429} 436}
430 437
431Shape_Rle_Data * 438Shape_Rle_Data *
432ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath) 439ector_software_rasterizer_generate_stroke_rle_data(Ector_Software_Thread *thread,
440 Software_Rasterizer *rasterizer,
441 SW_FT_Outline *outline,
442 Eina_Bool closePath)
433{ 443{
434 uint32_t points,contors; 444 uint32_t points,contors;
435 Shape_Rle_Data *rle_data; 445 Shape_Rle_Data *rle_data;
436 SW_FT_Outline strokeOutline = { 0, 0, NULL, NULL, NULL, 0 }; 446 SW_FT_Outline strokeOutline = { 0, 0, NULL, NULL, NULL, 0 };
437 447
438 SW_FT_Stroker_ParseOutline(rasterizer->stroker, outline, !closePath); 448 SW_FT_Stroker_ParseOutline(thread->stroker, outline, !closePath);
439 SW_FT_Stroker_GetCounts(rasterizer->stroker,&points, &contors); 449 SW_FT_Stroker_GetCounts(thread->stroker,&points, &contors);
440 450
441 strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector)); 451 strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
442 strokeOutline.tags = (char *) calloc(points, sizeof(char)); 452 strokeOutline.tags = (char *) calloc(points, sizeof(char));
443 strokeOutline.contours = (short *) calloc(contors, sizeof(short)); 453 strokeOutline.contours = (short *) calloc(contors, sizeof(short));
444 454
445 SW_FT_Stroker_Export(rasterizer->stroker, &strokeOutline); 455 SW_FT_Stroker_Export(thread->stroker, &strokeOutline);
446 456
447 rle_data = ector_software_rasterizer_generate_rle_data(rasterizer, &strokeOutline); 457 rle_data = ector_software_rasterizer_generate_rle_data(thread, rasterizer, &strokeOutline);
448 458
449 // cleanup the outline data. 459 // cleanup the outline data.
450 free(strokeOutline.points); 460 free(strokeOutline.points);
diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c
index 016b267..e3e72fb 100644
--- a/src/lib/ector/software/ector_software_surface.c
+++ b/src/lib/ector/software/ector_software_surface.c
@@ -90,6 +90,7 @@ _ector_software_init(void)
90 90
91 t = &ths[i]; 91 t = &ths[i];
92 t->queue = eina_thread_queue_new(); 92 t->queue = eina_thread_queue_new();
93 ector_software_thread_init(t);
93 if (!eina_thread_create(&t->thread, EINA_THREAD_NORMAL, -1, 94 if (!eina_thread_create(&t->thread, EINA_THREAD_NORMAL, -1,
94 _prepare_process, t)) 95 _prepare_process, t))
95 { 96 {
@@ -107,7 +108,11 @@ _ector_software_shutdown(void)
107 108
108 if (!--count_init) return ; 109 if (!--count_init) return ;
109 110
110 if (!ths) return ; 111 if (!ths)
112 {
113 ector_software_thread_shutdown(&render_thread);
114 return ;
115 }
111 116
112 for (i = 0; i < cpu_core; i++) 117 for (i = 0; i < cpu_core; i++)
113 { 118 {
@@ -123,6 +128,7 @@ _ector_software_shutdown(void)
123 128
124 eina_thread_join(t->thread); 129 eina_thread_join(t->thread);
125 eina_thread_queue_free(t->queue); 130 eina_thread_queue_free(t->queue);
131 ector_software_thread_shutdown(t);
126 } 132 }
127 133
128 eina_thread_queue_free(render_queue); 134 eina_thread_queue_free(render_queue);
@@ -220,7 +226,6 @@ _ector_software_surface_efl_object_constructor(Eo *obj, Ector_Software_Surface_D
220static void 226static void
221_ector_software_surface_efl_object_destructor(Eo *obj, Ector_Software_Surface_Data *pd) 227_ector_software_surface_efl_object_destructor(Eo *obj, Ector_Software_Surface_Data *pd)
222{ 228{
223 ector_software_rasterizer_done(pd->rasterizer);
224 efl_data_unref(obj, pd->rasterizer->fill_data.raster_buffer); 229 efl_data_unref(obj, pd->rasterizer->fill_data.raster_buffer);
225 free(pd->rasterizer); 230 free(pd->rasterizer);
226 pd->rasterizer = NULL; 231 pd->rasterizer = NULL;