comparison src/redraw_man.c @ 840:048cc704bef7

Merge dirty_pcache_area_coords and zeroing_coords. Also interleave zeroing and updating pcache_area tasks. To zeroing a cached coord, pcache_area of descendants cached coords must be updated before zeroing. But, updating pcache_area of a cached coord must be performed after zeroing the coord. So, they are interleaved. dirty_pcache_area_coords are removed from redraw_man_t. It is merged to zeroing_coords.
author Thinker K.F. Li <thinker@codemud.net>
date Fri, 17 Sep 2010 12:21:36 +0800
parents a3be0162bf44
children ce6cd06adccf
comparison
equal deleted inserted replaced
839:a3be0162bf44 840:048cc704bef7
474 } 474 }
475 475
476 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { 476 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) {
477 if(!coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) { 477 if(!coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) {
478 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); 478 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA);
479 ADD_DATA(coords, dirty_pcache_area_coords, coord); 479 ADD_DATA(coords, zeroing_coords, coord);
480 } 480 }
481 return OK; 481 return OK;
482 } 482 }
483 483
484 static int add_free_obj(redraw_man_t *rdman, void *obj, 484 static int add_free_obj(redraw_man_t *rdman, void *obj,
644 extern void addrm_monitor_hdlr(event_t *evt, void *arg); 644 extern void addrm_monitor_hdlr(event_t *evt, void *arg);
645 645
646 memset(rdman, 0, sizeof(redraw_man_t)); 646 memset(rdman, 0, sizeof(redraw_man_t));
647 647
648 DARRAY_INIT(&rdman->dirty_coords); 648 DARRAY_INIT(&rdman->dirty_coords);
649 DARRAY_INIT(&rdman->dirty_pcache_area_coords);
650 DARRAY_INIT(&rdman->dirty_geos); 649 DARRAY_INIT(&rdman->dirty_geos);
651 DARRAY_INIT(&rdman->gen_geos); 650 DARRAY_INIT(&rdman->gen_geos);
652 DARRAY_INIT(&rdman->zeroing_coords); 651 DARRAY_INIT(&rdman->zeroing_coords);
653 652
654 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); 653 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128);
730 if(rdman->pent_pool) 729 if(rdman->pent_pool)
731 elmpool_free(rdman->pent_pool); 730 elmpool_free(rdman->pent_pool);
732 if(rdman->coord_canvas_pool) 731 if(rdman->coord_canvas_pool)
733 elmpool_free(rdman->coord_canvas_pool); 732 elmpool_free(rdman->coord_canvas_pool);
734 DARRAY_DESTROY(&rdman->dirty_coords); 733 DARRAY_DESTROY(&rdman->dirty_coords);
735 DARRAY_DESTROY(&rdman->dirty_pcache_area_coords);
736 DARRAY_DESTROY(&rdman->dirty_geos); 734 DARRAY_DESTROY(&rdman->dirty_geos);
737 DARRAY_DESTROY(&rdman->gen_geos); 735 DARRAY_DESTROY(&rdman->gen_geos);
738 DARRAY_DESTROY(&rdman->zeroing_coords); 736 DARRAY_DESTROY(&rdman->zeroing_coords);
739 return ERR; 737 return ERR;
740 } 738 }
751 749
752 /* Mark rdman clean that shapes and coords can be freed 750 /* Mark rdman clean that shapes and coords can be freed
753 * successfully. 751 * successfully.
754 */ 752 */
755 DARRAY_CLEAN(&rdman->dirty_coords); 753 DARRAY_CLEAN(&rdman->dirty_coords);
756 DARRAY_CLEAN(&rdman->dirty_pcache_area_coords);
757 DARRAY_CLEAN(&rdman->dirty_geos); 754 DARRAY_CLEAN(&rdman->dirty_geos);
758 755
759 coord = postorder_coord_subtree(rdman->root_coord, NULL); 756 coord = postorder_coord_subtree(rdman->root_coord, NULL);
760 while(coord) { 757 while(coord) {
761 saved_coord = coord; 758 saved_coord = coord;
787 elmpool_free(rdman->paint_color_pool); 784 elmpool_free(rdman->paint_color_pool);
788 elmpool_free(rdman->pent_pool); 785 elmpool_free(rdman->pent_pool);
789 elmpool_free(rdman->coord_canvas_pool); 786 elmpool_free(rdman->coord_canvas_pool);
790 787
791 DARRAY_DESTROY(&rdman->dirty_coords); 788 DARRAY_DESTROY(&rdman->dirty_coords);
792 DARRAY_DESTROY(&rdman->dirty_pcache_area_coords);
793 DARRAY_DESTROY(&rdman->dirty_geos); 789 DARRAY_DESTROY(&rdman->dirty_geos);
794 DARRAY_DESTROY(&rdman->gen_geos); 790 DARRAY_DESTROY(&rdman->gen_geos);
795 DARRAY_DESTROY(&rdman->zeroing_coords); 791 DARRAY_DESTROY(&rdman->zeroing_coords);
796 } 792 }
797 793
1419 * normal one. (see compute_aggr_of_cached_coord()). 1415 * normal one. (see compute_aggr_of_cached_coord()).
1420 * 1416 *
1421 * \note coords their opacity != 1 are also traded as cached ones. 1417 * \note coords their opacity != 1 are also traded as cached ones.
1422 */ 1418 */
1423 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { 1419 static int clean_coord(redraw_man_t *rdman, coord_t *coord) {
1424 coord_t *child;
1425 int r; 1420 int r;
1426 1421
1427 setup_canvas_info(rdman, coord); 1422 setup_canvas_info(rdman, coord);
1428 1423
1429 compute_aggr(coord); 1424 compute_aggr(coord);
1538 max_y = min_y + area->h; 1533 max_y = min_y + area->h;
1539 1534
1540 for(cur = preorder_coord_subtree(coord, coord); 1535 for(cur = preorder_coord_subtree(coord, coord);
1541 cur != NULL; 1536 cur != NULL;
1542 cur = preorder_coord_subtree(coord, cur)) { 1537 cur = preorder_coord_subtree(coord, cur)) {
1543 area = coord_get_area(cur); 1538 if(coord_is_cached(cur)) {
1539 preorder_coord_skip_subtree(cur);
1540 /* This means pcache_area of descendants must be computed
1541 * before zeroing ancestor cached one.
1542 * (See add_rdman_zeroing_n_pcache_coords())
1543 */
1544 area = coord_get_pcache_area(cur);
1545 } else
1546 area = coord_get_area(cur);
1547
1544 if(area->x < min_x) 1548 if(area->x < min_x)
1545 min_x = area->x; 1549 min_x = area->x;
1546 if(area->y < min_y) 1550 if(area->y < min_y)
1547 min_y = area->y; 1551 min_y = area->y;
1548 1552
1551 1555
1552 if(x > max_x) 1556 if(x > max_x)
1553 max_x = x; 1557 max_x = x;
1554 if(y > max_y) 1558 if(y > max_y)
1555 max_y = y; 1559 max_y = y;
1556 if(coord_is_cached(cur))
1557 preorder_coord_skip_subtree(cur);
1558 } 1560 }
1559 1561
1560 w = max_x - min_x; 1562 w = max_x - min_x;
1561 h = max_y - min_y; 1563 h = max_y - min_y;
1562 1564
1623 } 1625 }
1624 1626
1625 coord_set_flags(coord, COF_JUST_ZERO); 1627 coord_set_flags(coord, COF_JUST_ZERO);
1626 } 1628 }
1627 1629
1628 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. 1630 /*! \brief Add coords that need to perform zeroing or re-compute pcache_area.
1629 * 1631 *
1630 * All possible coords that need a zeroing have at least one dirty geo. 1632 * A coord that need to perform zeroing has one or more dirty members
1631 */ 1633 * in its descendants.
1632 static int add_rdman_zeroing_coords(redraw_man_t *rdman) { 1634 *
1635 * To zeroing a coord, pcache_area of first level cached descendants
1636 * must be updated. To update the pcache_area of a cached coord, the
1637 * cached coord also need to perform zeroing. So, zeroing and
1638 * re-computing pcache_area are interleaved.
1639 *
1640 * The pcache_area of a cached coord must be re-computed if its
1641 * parent/ancestors is dirty/just cleaned, or it must be zeroed. It
1642 * means cached coord with jsut cleaned parent should also re-compute
1643 * pcache_area. So, this function also check and add coords for this
1644 * situation.
1645 */
1646 static int add_rdman_zeroing_n_pcache_coords(redraw_man_t *rdman) {
1633 int i; 1647 int i;
1634 int n_dirty_geos; 1648 int n_dirty_geos;
1635 geo_t **dirty_geos, *geo; 1649 geo_t **dirty_geos, *geo;
1636 int n_dirty_coords; 1650 int n_dirty_coords;
1637 coord_t **dirty_coords, *coord; 1651 coord_t **dirty_coords, *coord;
1652 coord_t *parent_coord;
1638 1653
1639 /* Mark all cached ancestral coords of dirty geos */ 1654 /* Mark all cached ancestral coords of dirty geos */
1640 n_dirty_geos = rdman->dirty_geos.num; 1655 n_dirty_geos = rdman->dirty_geos.num;
1641 dirty_geos = rdman->dirty_geos.ds; 1656 dirty_geos = rdman->dirty_geos.ds;
1642 for(i = 0; i < n_dirty_geos; i++) { 1657 for(i = 0; i < n_dirty_geos; i++) {
1667 FOR_COORDS_PREORDER(rdman->root_coord, coord) { 1682 FOR_COORDS_PREORDER(rdman->root_coord, coord) {
1668 if(!coord_is_cached(coord) || coord_is_root(coord)) 1683 if(!coord_is_cached(coord) || coord_is_root(coord))
1669 continue; /* skip coords that is not cached */ 1684 continue; /* skip coords that is not cached */
1670 1685
1671 if(!coord_get_flags(coord, COF_TEMP_MARK)) { 1686 if(!coord_get_flags(coord, COF_TEMP_MARK)) {
1687 parent_coord = coord_get_parent(coord);
1688 /* The pcache_area of a cached coord that is a child of a
1689 * just cleaned one must be recomputed.
1690 */
1691 if(coord_get_flags(parent_coord, COF_JUST_CLEAN))
1692 add_dirty_pcache_area_coord(rdman, coord);
1693
1672 preorder_coord_skip_subtree(coord); 1694 preorder_coord_skip_subtree(coord);
1673 continue; 1695 continue;
1674 } 1696 }
1675 add_zeroing_coord(rdman, coord); 1697 add_zeroing_coord(rdman, coord);
1676 1698
1703 * performed before zeroing. It means ancestors of a 1725 * performed before zeroing. It means ancestors of a
1704 * cached coord would not effect it when zeroing. 1726 * cached coord would not effect it when zeroing.
1705 */ 1727 */
1706 for(i = all_zeroing->num - 1; i >= 0; i--) { 1728 for(i = all_zeroing->num - 1; i >= 0; i--) {
1707 coord = all_zeroing->ds[i]; 1729 coord = all_zeroing->ds[i];
1708 zeroing_coord(rdman, coord); 1730 if(coord_is_zeroing(coord))
1709 } 1731 zeroing_coord(rdman, coord);
1710 1732 /* This is required by ancester cached ones to perform
1711 return OK; 1733 * zeroing.
1712 } 1734 */
1713 1735 compute_pcache_area(coord);
1714 /*! \brief Compute pcache_area for coords whoes pcache_area is dirty. 1736 }
1715 * 1737
1716 * coord_t::dirty_pcache_area_coords also includes part of coords in
1717 * coord_t::zeroing_coords. The pcache_area of coords that is in
1718 * coord_t::dirty_pcache_area_coords, but is not in
1719 * coord_t::zeroing_coords should be computed here.
1720 * zeroing_rdman_coords() is responsible for computing pcache_area for
1721 * zeroing ones.
1722 */
1723 static int
1724 compute_rdman_coords_pcache_area(redraw_man_t *rdman) {
1725 coords_t *all_coords;
1726 coord_t *coord;
1727 int i;
1728
1729 all_coords = &rdman->dirty_pcache_area_coords;
1730 for(i = 0; i < all_coords->num; i++) {
1731 coord = all_coords->ds[i];
1732 if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA))
1733 compute_pcache_area(coord);
1734 }
1735 return OK; 1738 return OK;
1736 } 1739 }
1737 1740
1738 /*! \brief Add aggregated dirty areas to ancestor. 1741 /*! \brief Add aggregated dirty areas to ancestor.
1739 * 1742 *
1854 * areas and one or new areas. Both aggregation areas are add into 1857 * areas and one or new areas. Both aggregation areas are add into
1855 * dirty_areas list of closet ancestral cached coord. 1858 * dirty_areas list of closet ancestral cached coord.
1856 */ 1859 */
1857 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { 1860 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) {
1858 int i; 1861 int i;
1859 int n_zeroing; 1862 coord_t *coord, *parent_coord, *pcached_coord;
1860 coord_t **zeroings; 1863 int n_zeroing_coords; /* number of dirty pcache area coords */
1861 coord_t *coord, *pcached_coord; 1864 coord_t **zeroing_coords; /* dirty pcache area coords */
1862 int n_dpca_coords; /* number of dirty pcache area coords */ 1865
1863 coord_t **dpca_coords; /* dirty pcache area coords */ 1866 n_zeroing_coords = rdman->zeroing_coords.num;
1864 1867 zeroing_coords = rdman->zeroing_coords.ds;
1865 /* Add aggregated areas to parent cached one for coords in zeroing 1868 for(i = n_zeroing_coords - 1; i >= 0; i--) {
1866 * list 1869 coord = zeroing_coords[i];
1867 */
1868 n_zeroing = rdman->zeroing_coords.num;
1869 zeroings = rdman->zeroing_coords.ds;
1870 for(i = 0; i < n_zeroing; i++) {
1871 coord = zeroings[i];
1872
1873 if(coord_get_flags(coord, COF_TEMP_MARK))
1874 continue;
1875 coord_set_flags(coord, COF_TEMP_MARK);
1876
1877 pcached_coord = coord_get_cached(coord_get_parent(coord));
1878
1879 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1880 continue;
1881
1882 if(IS_CACHE_REDRAW_ALL(coord)) { 1870 if(IS_CACHE_REDRAW_ALL(coord)) {
1871 parent_coord = coord_get_parent(coord);
1872 pcached_coord = coord_get_cached(parent_coord);
1873
1883 add_dirty_area(rdman, pcached_coord, 1874 add_dirty_area(rdman, pcached_coord,
1884 coord_get_pcache_area(coord)); 1875 coord_get_pcache_area(coord));
1885 add_dirty_area(rdman, pcached_coord, 1876 add_dirty_area(rdman, pcached_coord,
1886 coord_get_pcache_last_area(coord)); 1877 coord_get_pcache_last_area(coord));
1887 } else { 1878 } else {
1888 add_aggr_dirty_areas_to_ancestor(rdman, coord); 1879 add_aggr_dirty_areas_to_ancestor(rdman, coord);
1889 } 1880 }
1890 } 1881 }
1891 1882
1892 /* Add pcache_areas to parent cached one for coord that is
1893 * non-zeroing and its parent is changed.
1894 */
1895 n_dpca_coords = rdman->dirty_pcache_area_coords.num;
1896 dpca_coords = rdman->dirty_pcache_area_coords.ds;
1897 for(i = 0; i < n_dpca_coords; i++) {
1898 coord = dpca_coords[i];
1899
1900 if(coord_get_flags(coord, COF_TEMP_MARK))
1901 continue;
1902 coord_set_flags(coord, COF_TEMP_MARK);
1903
1904 pcached_coord = coord_get_cached(coord_get_parent(coord));
1905
1906 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1907 continue;
1908
1909 add_dirty_area(rdman, pcached_coord,
1910 coord_get_pcache_area(coord));
1911 add_dirty_area(rdman, pcached_coord,
1912 coord_get_pcache_last_area(coord));
1913 }
1914
1915 /* Remove temporary mark */
1916 for(i = 0; i < n_zeroing; i++) {
1917 coord_clear_flags(zeroings[i], COF_TEMP_MARK);
1918 }
1919 for(i = 0; i < n_dpca_coords; i++) {
1920 coord_clear_flags(dpca_coords[i], COF_TEMP_MARK);
1921 }
1922
1923 return OK; 1883 return OK;
1924 }
1925
1926 static int
1927 add_rdman_coords_pcache_area(redraw_man_t *rdman) {
1928 coord_t *root, *cur;
1929 coord_t *parent;
1930
1931 root = rdman->root_coord;
1932 FOR_COORDS_POSTORDER(root, cur) {
1933 if(coord_is_root(cur))
1934 continue;
1935 if(!coord_is_cached(cur))
1936 continue;
1937 if(!coord_get_flags(cur, COF_JUST_ZERO | COF_JUST_CLEAN)) {
1938 parent = coord_get_parent(cur);
1939 if(!coord_get_flags(parent, COF_JUST_CLEAN))
1940 continue;
1941 }
1942 add_dirty_pcache_area_coord(rdman, cur);
1943 }
1944 } 1884 }
1945 1885
1946 /*! \brief Swap geo_t::cur_area and geo_t::last_area for a geo_t. 1886 /*! \brief Swap geo_t::cur_area and geo_t::last_area for a geo_t.
1947 * 1887 *
1948 * It is call by rdman_clean_dirties() to swap areas for members of 1888 * It is call by rdman_clean_dirties() to swap areas for members of
2041 return ERR; 1981 return ERR;
2042 1982
2043 /* Zeroing must be performed after clearing to get latest position 1983 /* Zeroing must be performed after clearing to get latest position
2044 * of shapes for computing new bounding box 1984 * of shapes for computing new bounding box
2045 */ 1985 */
2046 r = add_rdman_zeroing_coords(rdman); 1986 r = add_rdman_zeroing_n_pcache_coords(rdman);
2047 if(r != OK) 1987 if(r != OK)
2048 return ERR; 1988 return ERR;
2049 1989
2050 r = zeroing_rdman_coords(rdman); 1990 r = zeroing_rdman_coords(rdman);
2051 if(r != OK)
2052 return ERR;
2053
2054 r = add_rdman_coords_pcache_area(rdman);
2055 if(r != OK)
2056 return ERR;
2057
2058 r = compute_rdman_coords_pcache_area(rdman);
2059 if(r != OK) 1991 if(r != OK)
2060 return ERR; 1992 return ERR;
2061 1993
2062 r = add_rdman_aggr_dirty_areas(rdman); 1994 r = add_rdman_aggr_dirty_areas(rdman);
2063 if(r != OK) 1995 if(r != OK)
2077 } 2009 }
2078 coords = rdman->zeroing_coords.ds; 2010 coords = rdman->zeroing_coords.ds;
2079 for(i = 0; i < rdman->zeroing_coords.num; i++) 2011 for(i = 0; i < rdman->zeroing_coords.num; i++)
2080 coord_clear_flags(coords[i], 2012 coord_clear_flags(coords[i],
2081 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); 2013 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO);
2082 coords = rdman->dirty_pcache_area_coords.ds; 2014
2083 for(i = 0; i < rdman->dirty_pcache_area_coords.num; i++)
2084 coord_clear_flags(coords[i],
2085 COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO);
2086
2087 /* \see GEO_SWAP() */ 2015 /* \see GEO_SWAP() */
2088 for(i = 0; i < rdman->dirty_geos.num; i++) { 2016 for(i = 0; i < rdman->dirty_geos.num; i++) {
2089 geo = geos[i]; 2017 geo = geos[i];
2090 geo_clear_flags(geo, GEF_SWAP); 2018 geo_clear_flags(geo, GEF_SWAP);
2091 } 2019 }
2287 child = FIRST_CHILD(coord); 2215 child = FIRST_CHILD(coord);
2288 while(child != NULL || member != NULL) { 2216 while(child != NULL || member != NULL) {
2289 if(child && child->before_pmem == mem_idx) { 2217 if(child && child->before_pmem == mem_idx) {
2290 if(coord_is_cached(child)) { 2218 if(coord_is_cached(child)) {
2291 if(!(child->flags & COF_HIDDEN) && 2219 if(!(child->flags & COF_HIDDEN) &&
2292 is_area_in_areas(coord_get_area(child), n_areas, areas)) { 2220 is_area_in_areas(coord_get_pcache_area(child),
2221 n_areas, areas)) {
2293 update_cached_canvas_2_parent(rdman, child); 2222 update_cached_canvas_2_parent(rdman, child);
2294 dirty = 1; 2223 dirty = 1;
2295 } 2224 }
2296 } else { 2225 } else {
2297 r = draw_coord_shapes_in_dirty_areas(rdman, child); 2226 r = draw_coord_shapes_in_dirty_areas(rdman, child);
2448 } 2377 }
2449 2378
2450 DARRAY_CLEAN(&rdman->dirty_coords); 2379 DARRAY_CLEAN(&rdman->dirty_coords);
2451 DARRAY_CLEAN(&rdman->dirty_geos); 2380 DARRAY_CLEAN(&rdman->dirty_geos);
2452 DARRAY_CLEAN(&rdman->zeroing_coords); 2381 DARRAY_CLEAN(&rdman->zeroing_coords);
2453 DARRAY_CLEAN(&rdman->dirty_pcache_area_coords);
2454 2382
2455 /* Free postponsed removing */ 2383 /* Free postponsed removing */
2456 free_free_objs(rdman); 2384 free_free_objs(rdman);
2457 2385
2458 redraw = rdman_get_redraw_subject(rdman); 2386 redraw = rdman_get_redraw_subject(rdman);