diff options
author | Jean-Philippe Andre <jp.andre@samsung.com> | 2014-11-13 10:47:29 +0900 |
---|---|---|
committer | Jean-Philippe Andre <jp.andre@samsung.com> | 2015-01-07 15:06:02 +0900 |
commit | 73919ea43708b4caa980ca59c3d4a2fa8864aef2 (patch) | |
tree | 459830234e6d2ac1692f183469d3ae2b7214527d /src/lib/evas/canvas | |
parent | 2a0201d571b0be656855c1d89c453d80bd17e8fe (diff) |
Evas masking: Implement mask support in evas_render
This implements supports for masking inside evas_render, which
means:
- Render the mask itself into a surface (ALPHA if possible)
- Pass this mask surface to the draw context
- Apply mask recursively in case a masked object is contained
by another masked object.
@feature
Diffstat (limited to 'src/lib/evas/canvas')
-rw-r--r-- | src/lib/evas/canvas/evas_render.c | 343 |
1 files changed, 325 insertions, 18 deletions
diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 4a340ee48f..896a3303a8 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c | |||
@@ -255,6 +255,7 @@ _evas_render_cur_clip_cache_del(Evas_Public_Data *e, Evas_Object_Protected_Data | |||
255 | y + e->framespace.y, w, h); | 255 | y + e->framespace.y, w, h); |
256 | } | 256 | } |
257 | 257 | ||
258 | /* sets the redraw flag for all the proxies depending on this obj as a source */ | ||
258 | static void | 259 | static void |
259 | _evas_proxy_redraw_set(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, | 260 | _evas_proxy_redraw_set(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, |
260 | Eina_Bool render) | 261 | Eina_Bool render) |
@@ -293,6 +294,59 @@ _evas_proxy_redraw_set(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, | |||
293 | } | 294 | } |
294 | } | 295 | } |
295 | 296 | ||
297 | /* sets the mask redraw flag for all the objects clipped by this mask */ | ||
298 | static void | ||
299 | _evas_mask_redraw_set(Evas_Public_Data *e EINA_UNUSED, | ||
300 | Evas_Object_Protected_Data *obj) | ||
301 | { | ||
302 | Evas_Object_Protected_Data *clippee; | ||
303 | Eina_List *l; | ||
304 | |||
305 | if (!(obj->mask->redraw && | ||
306 | obj->mask->x == obj->cur->geometry.x && | ||
307 | obj->mask->y == obj->cur->geometry.y && | ||
308 | obj->mask->w == obj->cur->geometry.w && | ||
309 | obj->mask->h == obj->cur->geometry.h)) | ||
310 | { | ||
311 | EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, | ||
312 | Evas_Object_Mask_Data, mask) | ||
313 | mask->redraw = EINA_TRUE; | ||
314 | mask->x = obj->cur->geometry.x; | ||
315 | mask->y = obj->cur->geometry.y; | ||
316 | mask->w = obj->cur->geometry.w; | ||
317 | mask->h = obj->cur->geometry.h; | ||
318 | EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mask); | ||
319 | } | ||
320 | |||
321 | if (!obj->cur->cache.clip.dirty) | ||
322 | { | ||
323 | EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) | ||
324 | state_write->cache.clip.dirty = EINA_TRUE; | ||
325 | EINA_COW_STATE_WRITE_END(obj, state_write, cur); | ||
326 | } | ||
327 | |||
328 | EINA_LIST_FOREACH(obj->clip.clipees, l, clippee) | ||
329 | { | ||
330 | evas_object_clip_recalc(clippee); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | static inline Eina_Bool | ||
335 | _evas_render_object_changed_get(Evas_Object_Protected_Data *obj) | ||
336 | { | ||
337 | if (obj->smart.smart) | ||
338 | return evas_object_smart_changed_get(obj->object); | ||
339 | else | ||
340 | return obj->changed; | ||
341 | } | ||
342 | |||
343 | static inline Eina_Bool | ||
344 | _evas_render_object_is_mask(Evas_Object_Protected_Data *obj) | ||
345 | { | ||
346 | if (!obj) return EINA_FALSE; | ||
347 | return (obj->mask->is_mask && obj->clip.clipees); | ||
348 | } | ||
349 | |||
296 | static void | 350 | static void |
297 | _evas_render_phase1_direct(Evas_Public_Data *e, | 351 | _evas_render_phase1_direct(Evas_Public_Data *e, |
298 | Eina_Array *active_objects, | 352 | Eina_Array *active_objects, |
@@ -302,7 +356,6 @@ _evas_render_phase1_direct(Evas_Public_Data *e, | |||
302 | { | 356 | { |
303 | unsigned int i; | 357 | unsigned int i; |
304 | Evas_Object *eo_obj; | 358 | Evas_Object *eo_obj; |
305 | Eina_Bool changed; | ||
306 | 359 | ||
307 | RD(" [--- PHASE 1 DIRECT\n"); | 360 | RD(" [--- PHASE 1 DIRECT\n"); |
308 | for (i = 0; i < active_objects->count; i++) | 361 | for (i = 0; i < active_objects->count; i++) |
@@ -311,13 +364,19 @@ _evas_render_phase1_direct(Evas_Public_Data *e, | |||
311 | eina_array_data_get(active_objects, i); | 364 | eina_array_data_get(active_objects, i); |
312 | 365 | ||
313 | if (obj->changed) evas_object_clip_recalc(obj); | 366 | if (obj->changed) evas_object_clip_recalc(obj); |
314 | if (!obj->proxy->proxies && !obj->proxy->proxy_textures) continue; | ||
315 | |||
316 | if (obj->smart.smart) | ||
317 | changed = evas_object_smart_changed_get(obj->object); | ||
318 | else changed = obj->changed; | ||
319 | 367 | ||
320 | if (changed) _evas_proxy_redraw_set(e, obj, EINA_FALSE); | 368 | if (obj->proxy->proxies || obj->proxy->proxy_textures) |
369 | { | ||
370 | /* is proxy source */ | ||
371 | if (_evas_render_object_changed_get(obj)) | ||
372 | _evas_proxy_redraw_set(e, obj, EINA_FALSE); | ||
373 | } | ||
374 | if (_evas_render_object_is_mask(obj)) | ||
375 | { | ||
376 | /* is image clipper */ | ||
377 | if (_evas_render_object_changed_get(obj)) | ||
378 | _evas_mask_redraw_set(e, obj); | ||
379 | } | ||
321 | } | 380 | } |
322 | for (i = 0; i < render_objects->count; i++) | 381 | for (i = 0; i < render_objects->count; i++) |
323 | { | 382 | { |
@@ -336,11 +395,14 @@ _evas_render_phase1_direct(Evas_Public_Data *e, | |||
336 | { | 395 | { |
337 | evas_object_clip_recalc(obj); | 396 | evas_object_clip_recalc(obj); |
338 | obj->func->render_pre(eo_obj, obj, obj->private_data); | 397 | obj->func->render_pre(eo_obj, obj, obj->private_data); |
339 | if (obj->proxy->redraw) | 398 | |
399 | if (obj->proxy->redraw || obj->mask->redraw) | ||
340 | _evas_render_prev_cur_clip_cache_add(e, obj); | 400 | _evas_render_prev_cur_clip_cache_add(e, obj); |
341 | if (obj->proxy->proxies || obj->proxy->proxy_textures) | 401 | |
402 | if (!obj->smart.smart || evas_object_smart_changed_get(eo_obj)) | ||
342 | { | 403 | { |
343 | if (!obj->smart.smart || evas_object_smart_changed_get(eo_obj)) | 404 | /* proxy sources */ |
405 | if (obj->proxy->proxies || obj->proxy->proxy_textures) | ||
344 | { | 406 | { |
345 | EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, | 407 | EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, |
346 | Evas_Object_Proxy_Data, proxy_write) | 408 | Evas_Object_Proxy_Data, proxy_write) |
@@ -349,6 +411,10 @@ _evas_render_phase1_direct(Evas_Public_Data *e, | |||
349 | proxy_write); | 411 | proxy_write); |
350 | _evas_proxy_redraw_set(e, obj, EINA_TRUE); | 412 | _evas_proxy_redraw_set(e, obj, EINA_TRUE); |
351 | } | 413 | } |
414 | |||
415 | /* clipper objects (image masks) */ | ||
416 | if (_evas_render_object_is_mask(obj)) | ||
417 | _evas_mask_redraw_set(e, obj); | ||
352 | } | 418 | } |
353 | 419 | ||
354 | RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n", | 420 | RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n", |
@@ -547,6 +613,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
547 | } | 613 | } |
548 | else | 614 | else |
549 | { | 615 | { |
616 | /* non smart object */ | ||
550 | if ((!obj->clip.clipees) && _evas_render_is_relevant(eo_obj)) | 617 | if ((!obj->clip.clipees) && _evas_render_is_relevant(eo_obj)) |
551 | { | 618 | { |
552 | if (is_active) | 619 | if (is_active) |
@@ -573,6 +640,20 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
573 | RD(" skip - not smart, not active or clippees or not relevant\n"); | 640 | RD(" skip - not smart, not active or clippees or not relevant\n"); |
574 | } | 641 | } |
575 | } | 642 | } |
643 | else if (is_active && _evas_render_object_is_mask(obj) && | ||
644 | (evas_object_is_visible(eo_obj, obj) || evas_object_was_visible(eo_obj, obj))) | ||
645 | { | ||
646 | if (obj->restack) | ||
647 | OBJ_ARRAY_PUSH(restack_objects, obj); | ||
648 | else | ||
649 | { | ||
650 | OBJ_ARRAY_PUSH(render_objects, obj); | ||
651 | obj->render_pre = EINA_TRUE; | ||
652 | } | ||
653 | |||
654 | RDI(level); | ||
655 | RD(" relevant + active: clipper image\n"); | ||
656 | } | ||
576 | else | 657 | else |
577 | { | 658 | { |
578 | RDI(level); | 659 | RDI(level); |
@@ -582,6 +663,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
582 | } | 663 | } |
583 | else | 664 | else |
584 | { | 665 | { |
666 | /* not changed */ | ||
585 | RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n", | 667 | RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n", |
586 | evas_object_is_visible(eo_obj, obj), | 668 | evas_object_is_visible(eo_obj, obj), |
587 | obj->cur->visible, obj->cur->cache.clip.visible, obj->smart.smart, | 669 | obj->cur->visible, obj->cur->cache.clip.visible, obj->smart.smart, |
@@ -615,6 +697,7 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
615 | } | 697 | } |
616 | else | 698 | else |
617 | { | 699 | { |
700 | /* not smart */ | ||
618 | if (evas_object_is_opaque(eo_obj, obj) && | 701 | if (evas_object_is_opaque(eo_obj, obj) && |
619 | evas_object_is_visible(eo_obj, obj)) | 702 | evas_object_is_visible(eo_obj, obj)) |
620 | { | 703 | { |
@@ -637,6 +720,14 @@ _evas_render_phase1_object_process(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
637 | } | 720 | } |
638 | } | 721 | } |
639 | } | 722 | } |
723 | else if (is_active && _evas_render_object_is_mask(obj) && | ||
724 | evas_object_is_visible(eo_obj, obj)) | ||
725 | { | ||
726 | RDI(level); | ||
727 | RD(" visible clipper image\n"); | ||
728 | OBJ_ARRAY_PUSH(render_objects, obj); | ||
729 | obj->render_pre = EINA_TRUE; | ||
730 | } | ||
640 | /* else if (obj->smart.smart) | 731 | /* else if (obj->smart.smart) |
641 | { | 732 | { |
642 | RDI(level); | 733 | RDI(level); |
@@ -1139,7 +1230,11 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
1139 | 1230 | ||
1140 | if (mapped) | 1231 | if (mapped) |
1141 | { | 1232 | { |
1142 | if (proxy_src_clip) | 1233 | if (_evas_render_object_is_mask(obj)) |
1234 | { | ||
1235 | // don't return; | ||
1236 | } | ||
1237 | else if (proxy_src_clip) | ||
1143 | { | 1238 | { |
1144 | if ((!evas_object_is_visible(eo_obj, obj)) || (obj->clip.clipees) | 1239 | if ((!evas_object_is_visible(eo_obj, obj)) || (obj->clip.clipees) |
1145 | || (obj->cur->have_clipees)) | 1240 | || (obj->cur->have_clipees)) |
@@ -1395,6 +1490,7 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
1395 | obj->cur->bounding_box.x, obj->cur->bounding_box.x, | 1490 | obj->cur->bounding_box.x, obj->cur->bounding_box.x, |
1396 | obj->cur->bounding_box.w, obj->cur->bounding_box.h); | 1491 | obj->cur->bounding_box.w, obj->cur->bounding_box.h); |
1397 | #endif | 1492 | #endif |
1493 | |||
1398 | if (mapped) | 1494 | if (mapped) |
1399 | { | 1495 | { |
1400 | RDI(level); | 1496 | RDI(level); |
@@ -1431,11 +1527,31 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
1431 | 1527 | ||
1432 | if (obj->cur->clipper) | 1528 | if (obj->cur->clipper) |
1433 | { | 1529 | { |
1434 | if (_evas_render_has_map(eo_obj, obj)) | 1530 | if (_evas_render_has_map(eo_obj, obj) || |
1531 | _evas_render_object_is_mask(obj->cur->clipper)) | ||
1435 | evas_object_clip_recalc(obj); | 1532 | evas_object_clip_recalc(obj); |
1436 | _evas_render_mapped_context_clip_set(e, eo_obj, obj, ctx, | 1533 | _evas_render_mapped_context_clip_set(e, eo_obj, obj, ctx, |
1437 | proxy_render_data, | 1534 | proxy_render_data, |
1438 | off_x, off_y); | 1535 | off_x, off_y); |
1536 | |||
1537 | /* Clipper masks */ | ||
1538 | if (_evas_render_object_is_mask(obj->cur->clipper)) | ||
1539 | { | ||
1540 | // This path can be hit when we're multiplying masks on top of each other... | ||
1541 | Evas_Object_Protected_Data *mask = | ||
1542 | (Evas_Object_Protected_Data *) obj->cur->clipper; | ||
1543 | if (mask->mask->redraw || !mask->mask->surface) | ||
1544 | evas_render_mask_subrender(obj->layer->evas, mask, NULL); | ||
1545 | |||
1546 | if (mask->mask->surface) | ||
1547 | { | ||
1548 | e->engine.func->context_clip_image_set | ||
1549 | (e->engine.data.output, ctx, | ||
1550 | mask->mask->surface, | ||
1551 | mask->mask->x + off_x, | ||
1552 | mask->mask->y + off_y); | ||
1553 | } | ||
1554 | } | ||
1439 | } | 1555 | } |
1440 | obj->func->render(eo_obj, obj, obj->private_data, | 1556 | obj->func->render(eo_obj, obj, obj->private_data, |
1441 | e->engine.data.output, ctx, | 1557 | e->engine.data.output, ctx, |
@@ -1448,19 +1564,21 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj, | |||
1448 | { | 1564 | { |
1449 | if (obj->cur->clipper) | 1565 | if (obj->cur->clipper) |
1450 | { | 1566 | { |
1567 | Evas_Object_Protected_Data *clipper = obj->cur->clipper; | ||
1451 | int x, y, w, h; | 1568 | int x, y, w, h; |
1452 | 1569 | ||
1453 | if (_evas_render_has_map(eo_obj, obj)) | 1570 | if (_evas_render_has_map(eo_obj, obj) || |
1571 | _evas_render_object_is_mask(obj->cur->clipper)) | ||
1454 | evas_object_clip_recalc(obj); | 1572 | evas_object_clip_recalc(obj); |
1455 | x = obj->cur->cache.clip.x; | 1573 | x = obj->cur->cache.clip.x; |
1456 | y = obj->cur->cache.clip.y; | 1574 | y = obj->cur->cache.clip.y; |
1457 | w = obj->cur->cache.clip.w; | 1575 | w = obj->cur->cache.clip.w; |
1458 | h = obj->cur->cache.clip.h; | 1576 | h = obj->cur->cache.clip.h; |
1459 | RECTS_CLIP_TO_RECT(x, y, w, h, | 1577 | RECTS_CLIP_TO_RECT(x, y, w, h, |
1460 | obj->cur->clipper->cur->cache.clip.x, | 1578 | clipper->cur->cache.clip.x, |
1461 | obj->cur->clipper->cur->cache.clip.y, | 1579 | clipper->cur->cache.clip.y, |
1462 | obj->cur->clipper->cur->cache.clip.w, | 1580 | clipper->cur->cache.clip.w, |
1463 | obj->cur->clipper->cur->cache.clip.h); | 1581 | clipper->cur->cache.clip.h); |
1464 | e->engine.func->context_clip_set(e->engine.data.output, | 1582 | e->engine.func->context_clip_set(e->engine.data.output, |
1465 | context, | 1583 | context, |
1466 | x + off_x, y + off_y, w, h); | 1584 | x + off_x, y + off_y, w, h); |
@@ -1558,6 +1676,161 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_ | |||
1558 | EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write); | 1676 | EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write); |
1559 | } | 1677 | } |
1560 | 1678 | ||
1679 | /* @internal | ||
1680 | * Synchronously render a mask image (or smart object) into a surface. | ||
1681 | * In SW the target surface will be ALPHA only (GRY8), after conversion. | ||
1682 | * In GL the target surface will be RGBA for now. TODO: Find out how to | ||
1683 | * render GL to alpha, if that's possible. | ||
1684 | */ | ||
1685 | void | ||
1686 | evas_render_mask_subrender(Evas_Public_Data *evas, | ||
1687 | Evas_Object_Protected_Data *mask, | ||
1688 | Evas_Object_Protected_Data *prev_mask) | ||
1689 | { | ||
1690 | int x, y, w, h, r, g, b, a; | ||
1691 | void *ctx; | ||
1692 | |||
1693 | if (!mask) return; | ||
1694 | if (!mask->mask->redraw && mask->mask->surface) | ||
1695 | { | ||
1696 | DBG("Requested mask redraw but the redraw flag is off."); | ||
1697 | return; | ||
1698 | } | ||
1699 | |||
1700 | x = mask->cur->geometry.x; | ||
1701 | y = mask->cur->geometry.y; | ||
1702 | w = mask->cur->geometry.w; | ||
1703 | h = mask->cur->geometry.h; | ||
1704 | |||
1705 | r = mask->cur->color.r; | ||
1706 | g = mask->cur->color.g; | ||
1707 | b = mask->cur->color.b; | ||
1708 | a = mask->cur->color.a; | ||
1709 | if ((r != 255) || (g != 255) || (b != 255) || (a != 255)) | ||
1710 | { | ||
1711 | EINA_COW_STATE_WRITE_BEGIN(mask, state_write, cur) | ||
1712 | { | ||
1713 | state_write->color.r = 255; | ||
1714 | state_write->color.g = 255; | ||
1715 | state_write->color.b = 255; | ||
1716 | state_write->color.a = 255; | ||
1717 | } | ||
1718 | EINA_COW_STATE_WRITE_END(mask, state_write, cur); | ||
1719 | } | ||
1720 | |||
1721 | if (prev_mask == mask) | ||
1722 | prev_mask = NULL; | ||
1723 | |||
1724 | if (prev_mask) | ||
1725 | { | ||
1726 | if (!prev_mask->mask->is_mask) | ||
1727 | { | ||
1728 | ERR("Passed invalid mask that is not a mask"); | ||
1729 | prev_mask = NULL; | ||
1730 | } | ||
1731 | else if (!prev_mask->mask->surface) | ||
1732 | { | ||
1733 | // FIXME? | ||
1734 | WRN("Mask render order may be invalid"); | ||
1735 | evas_render_mask_subrender(evas, prev_mask, NULL); | ||
1736 | } | ||
1737 | } | ||
1738 | |||
1739 | EINA_COW_WRITE_BEGIN(evas_object_mask_cow, mask->mask, Evas_Object_Mask_Data, mdata) | ||
1740 | mdata->redraw = EINA_FALSE; | ||
1741 | |||
1742 | /* delete render surface if changed or if already alpha | ||
1743 | * (we don't know how to render objects to alpha) */ | ||
1744 | if (mdata->surface && ((w != mdata->w) || (h != mdata->h) || mdata->is_alpha)) | ||
1745 | { | ||
1746 | ENFN->image_map_surface_free(ENDT, mdata->surface); | ||
1747 | mdata->surface = NULL; | ||
1748 | } | ||
1749 | |||
1750 | /* create new RGBA render surface if needed */ | ||
1751 | if (!mdata->surface) | ||
1752 | { | ||
1753 | mdata->surface = ENFN->image_map_surface_new(ENDT, w, h, EINA_TRUE); | ||
1754 | if (!mdata->surface) goto end; | ||
1755 | mdata->w = w; | ||
1756 | mdata->h = h; | ||
1757 | } | ||
1758 | |||
1759 | mdata->x = x; | ||
1760 | mdata->y = y; | ||
1761 | mdata->is_alpha = EINA_FALSE; | ||
1762 | |||
1763 | /* Clear surface with transparency */ | ||
1764 | ctx = ENFN->context_new(ENDT); | ||
1765 | ENFN->context_color_set(ENDT, ctx, 0, 0, 0, 0); | ||
1766 | ENFN->context_render_op_set(ENDT, ctx, EVAS_RENDER_COPY); | ||
1767 | ENFN->rectangle_draw(ENDT, ctx, mdata->surface, 0, 0, w, h, EINA_FALSE); | ||
1768 | ENFN->context_free(ENDT, ctx); | ||
1769 | |||
1770 | /* Render mask to RGBA surface */ | ||
1771 | ctx = ENFN->context_new(ENDT); | ||
1772 | if (prev_mask) | ||
1773 | { | ||
1774 | ENFN->context_clip_image_set(ENDT, ctx, | ||
1775 | prev_mask->mask->surface, | ||
1776 | prev_mask->mask->x - x, | ||
1777 | prev_mask->mask->y - y); | ||
1778 | } | ||
1779 | evas_render_mapped(evas, mask->object, mask, ctx, mdata->surface, | ||
1780 | -x, -y, 1, 0, 0, evas->output.w, evas->output.h, | ||
1781 | NULL, 1, EINA_TRUE, EINA_FALSE); | ||
1782 | ENFN->context_free(ENDT, ctx); | ||
1783 | |||
1784 | /* BEGIN HACK */ | ||
1785 | |||
1786 | /* Now we want to convert this RGBA surface to Alpha. | ||
1787 | * NOTE: So, this is not going to work with the GL engine but only with | ||
1788 | * the SW engine. Here's the detection hack: | ||
1789 | * FIXME: If you know of a way to support rendering to GL_ALPHA in GL, | ||
1790 | * then we should render directly to an ALPHA surface. A priori, | ||
1791 | * GLES FBO does not support this. | ||
1792 | */ | ||
1793 | if (!ENFN->gl_surface_read_pixels) | ||
1794 | { | ||
1795 | RGBA_Image *alpha_surface; | ||
1796 | DATA32 *rgba; | ||
1797 | DATA8* alpha; | ||
1798 | |||
1799 | alpha_surface = ENFN->image_new_from_copied_data | ||
1800 | (ENDT, w, h, NULL, EINA_TRUE, EVAS_COLORSPACE_GRY8); | ||
1801 | if (!alpha_surface) goto end; | ||
1802 | |||
1803 | /* Copy alpha channel */ | ||
1804 | rgba = ((RGBA_Image *) mdata->surface)->image.data; | ||
1805 | alpha = alpha_surface->image.data8; | ||
1806 | for (y = h; y; --y) | ||
1807 | for (x = w; x; --x, alpha++, rgba++) | ||
1808 | *alpha = (DATA8) A_VAL(rgba); | ||
1809 | |||
1810 | /* Now we can drop the original surface */ | ||
1811 | ENFN->image_map_surface_free(ENDT, mdata->surface); | ||
1812 | mdata->surface = alpha_surface; | ||
1813 | mdata->is_alpha = EINA_TRUE; | ||
1814 | } | ||
1815 | |||
1816 | /* END OF HACK */ | ||
1817 | |||
1818 | end: | ||
1819 | EINA_COW_WRITE_END(evas_object_mask_cow, mask->mask, mdata); | ||
1820 | |||
1821 | if ((r != 255) || (g != 255) || (b != 255) || (a != 255)) | ||
1822 | { | ||
1823 | EINA_COW_STATE_WRITE_BEGIN(mask, state_write, cur) | ||
1824 | { | ||
1825 | state_write->color.r = r; | ||
1826 | state_write->color.g = g; | ||
1827 | state_write->color.b = b; | ||
1828 | state_write->color.a = a; | ||
1829 | } | ||
1830 | EINA_COW_STATE_WRITE_END(mask, state_write, cur); | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1561 | static void | 1834 | static void |
1562 | _evas_render_cutout_add(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, int off_x, int off_y) | 1835 | _evas_render_cutout_add(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, int off_x, int off_y) |
1563 | { | 1836 | { |
@@ -1878,6 +2151,7 @@ evas_render_updates_internal(Evas *eo_e, | |||
1878 | if (UNLIKELY((evas_object_is_opaque(eo_obj, obj) || | 2151 | if (UNLIKELY((evas_object_is_opaque(eo_obj, obj) || |
1879 | ((obj->func->has_opaque_rect) && | 2152 | ((obj->func->has_opaque_rect) && |
1880 | (obj->func->has_opaque_rect(eo_obj, obj, obj->private_data)))) && | 2153 | (obj->func->has_opaque_rect(eo_obj, obj, obj->private_data)))) && |
2154 | (!obj->mask->is_mask) && | ||
1881 | evas_object_is_visible(eo_obj, obj) && | 2155 | evas_object_is_visible(eo_obj, obj) && |
1882 | (!obj->clip.clipees) && | 2156 | (!obj->clip.clipees) && |
1883 | (obj->cur->visible) && | 2157 | (obj->cur->visible) && |
@@ -1999,6 +2273,9 @@ evas_render_updates_internal(Evas *eo_e, | |||
1999 | x = cx; y = cy; w = cw; h = ch; | 2273 | x = cx; y = cy; w = cw; h = ch; |
2000 | if (((w > 0) && (h > 0)) || (obj->is_smart)) | 2274 | if (((w > 0) && (h > 0)) || (obj->is_smart)) |
2001 | { | 2275 | { |
2276 | Evas_Object_Protected_Data *prev_mask = NULL; | ||
2277 | Evas_Object_Protected_Data *mask = NULL; | ||
2278 | |||
2002 | if (!obj->is_smart) | 2279 | if (!obj->is_smart) |
2003 | { | 2280 | { |
2004 | RECTS_CLIP_TO_RECT(x, y, w, h, | 2281 | RECTS_CLIP_TO_RECT(x, y, w, h, |
@@ -2011,6 +2288,30 @@ evas_render_updates_internal(Evas *eo_e, | |||
2011 | e->engine.func->context_clip_set(e->engine.data.output, | 2288 | e->engine.func->context_clip_set(e->engine.data.output, |
2012 | e->engine.data.context, | 2289 | e->engine.data.context, |
2013 | x, y, w, h); | 2290 | x, y, w, h); |
2291 | |||
2292 | /* Clipper masks */ | ||
2293 | if (_evas_render_object_is_mask(obj->cur->clipper)) | ||
2294 | mask = (Evas_Object_Protected_Data *) obj->cur->clipper; // main object clipped by this mask | ||
2295 | else if (obj->cur->cache.clip.mask) | ||
2296 | mask = (Evas_Object_Protected_Data *) obj->cur->cache.clip.mask; // propagated clip | ||
2297 | prev_mask = (Evas_Object_Protected_Data *) obj->cur->cache.clip.prev_mask; | ||
2298 | |||
2299 | if (mask) | ||
2300 | { | ||
2301 | if (mask->mask->redraw || !mask->mask->surface) | ||
2302 | evas_render_mask_subrender(obj->layer->evas, mask, prev_mask); | ||
2303 | |||
2304 | if (mask->mask->surface) | ||
2305 | { | ||
2306 | e->engine.func->context_clip_image_set | ||
2307 | (e->engine.data.output, | ||
2308 | e->engine.data.context, | ||
2309 | mask->mask->surface, | ||
2310 | mask->mask->x + off_x, | ||
2311 | mask->mask->y + off_y); | ||
2312 | } | ||
2313 | } | ||
2314 | |||
2014 | #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */ | 2315 | #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */ |
2015 | for (j = offset; j < e->temporary_objects.count; ++j) | 2316 | for (j = offset; j < e->temporary_objects.count; ++j) |
2016 | { | 2317 | { |
@@ -2030,6 +2331,12 @@ evas_render_updates_internal(Evas *eo_e, | |||
2030 | do_async); | 2331 | do_async); |
2031 | e->engine.func->context_cutout_clear(e->engine.data.output, | 2332 | e->engine.func->context_cutout_clear(e->engine.data.output, |
2032 | e->engine.data.context); | 2333 | e->engine.data.context); |
2334 | |||
2335 | if (mask) | ||
2336 | { | ||
2337 | e->engine.func->context_clip_image_unset | ||
2338 | (e->engine.data.output, e->engine.data.context); | ||
2339 | } | ||
2033 | } | 2340 | } |
2034 | } | 2341 | } |
2035 | } | 2342 | } |