comparison src/redraw_man.c @ 537:3a7e3c1cd6e6 Android_Skia

[mq]: propagate_areas.diff
author Thinker K.F. Li <thinker@branda.to>
date Sat, 22 May 2010 22:31:18 +0800
parents b6b3dbeaedf3
children a1d49b6355c3
comparison
equal deleted inserted replaced
536:b6b3dbeaedf3 537:3a7e3c1cd6e6
469 coord_set_zeroing(coord); 469 coord_set_zeroing(coord);
470 ADD_DATA(coords, zeroing_coords, coord); 470 ADD_DATA(coords, zeroing_coords, coord);
471 return OK; 471 return OK;
472 } 472 }
473 473
474 static int add_dirty_pcache_area_coord(rdraw_man_t *rdman, coord_t *coord) { 474 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) {
475 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); 475 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA);
476 ADD_DATA(coords, dirty_pcache_area_coords, coord); 476 ADD_DATA(coords, dirty_pcache_area_coords, coord);
477 return OK; 477 return OK;
478 } 478 }
479 479
1244 1244
1245 if(coord->opacity != 1 || coord_is_cached(coord)) { 1245 if(coord->opacity != 1 || coord_is_cached(coord)) {
1246 if(!coord_is_cached(coord)) { 1246 if(!coord_is_cached(coord)) {
1247 /* canvas is assigned latter, in zeroing_coord() */ 1247 /* canvas is assigned latter, in zeroing_coord() */
1248 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); 1248 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL);
1249 coord_set_flags(coord->flags, COF_OWN_CANVAS); 1249 coord_set_flags(coord, COF_OWN_CANVAS);
1250 } 1250 }
1251 } else { 1251 } else {
1252 if(coord_is_cached(coord)) { 1252 if(coord_is_cached(coord)) {
1253 canvas_free(_coord_get_canvas(coord)); 1253 canvas_free(_coord_get_canvas(coord));
1254 coord_canvas_info_free(rdman, coord->canvas_info); 1254 coord_canvas_info_free(rdman, coord->canvas_info);
1306 */ 1306 */
1307 static void compute_pcache_area(coord_t *coord) { 1307 static void compute_pcache_area(coord_t *coord) {
1308 co_aix cached2pdev[6]; 1308 co_aix cached2pdev[6];
1309 int c_w, c_h; 1309 int c_w, c_h;
1310 canvas_t *canvas; 1310 canvas_t *canvas;
1311 coord_canvas_info_t *canvas_info;
1311 co_aix poses[4][2]; 1312 co_aix poses[4][2];
1312 1313
1314 canvas_info = coord->canvas_info;
1315 SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area,
1316 area_t *);
1313 compute_cached_2_pdev_matrix(coord, cached2pdev); 1317 compute_cached_2_pdev_matrix(coord, cached2pdev);
1314 1318
1315 canvas = _coord_get_canvas(coord); 1319 canvas = _coord_get_canvas(coord);
1316 canvas_get_size(canvas, &c_w, &c_h); 1320 canvas_get_size(canvas, &c_w, &c_h);
1317 1321
1327 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); 1331 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]);
1328 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); 1332 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]);
1329 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); 1333 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]);
1330 1334
1331 area_init(coord_get_pcache_area(coord), 4, poses); 1335 area_init(coord_get_pcache_area(coord), 4, poses);
1336
1337 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA);
1332 } 1338 }
1333 1339
1334 /*! \brief Compute area of a coord. 1340 /*! \brief Compute area of a coord.
1335 */ 1341 */
1336 static int 1342 static int
1404 */ 1410 */
1405 r = coord_clean_members_n_compute_area(coord); 1411 r = coord_clean_members_n_compute_area(coord);
1406 if(r != OK) 1412 if(r != OK)
1407 return ERR; 1413 return ERR;
1408 1414
1409 add_dirty_area(rdman, coord->cur_area); 1415 add_dirty_area(rdman, coord, coord->cur_area);
1410 add_dirty_area(rdman, coord->last_area); 1416 add_dirty_area(rdman, coord, coord->last_area);
1411 1417
1412 coord_clear_flags(coord, COF_DIRTY); 1418 coord_clear_flags(coord, COF_DIRTY);
1413 coord_set_flags(coord, COF_JUST_CLEAN); 1419 coord_set_flags(coord, COF_JUST_CLEAN);
1414 1420
1415 FORCHILDREN(coord, child) { 1421 FORCHILDREN(coord, child) {
1440 OFFSET(coord_t, order)); /* ascend order */ 1446 OFFSET(coord_t, order)); /* ascend order */
1441 for(i = 0; i < n_dirty_coords; i++) { 1447 for(i = 0; i < n_dirty_coords; i++) {
1442 coord = dirty_coords[i]; 1448 coord = dirty_coords[i];
1443 if(!coord_get_flags(coord, COF_DIRTY | COF_JUST_CLEAN)) 1449 if(!coord_get_flags(coord, COF_DIRTY | COF_JUST_CLEAN))
1444 continue; 1450 continue;
1445 SWAP(coord->cur_area, coord->last_area, coord_t *); 1451 SWAP(coord->cur_area, coord->last_area, area_t *);
1446 r = clean_coord(rdman, coord); 1452 r = clean_coord(rdman, coord);
1447 if(r != OK) 1453 if(r != OK)
1448 return ERR; 1454 return ERR;
1449 } 1455 }
1450 } 1456 }
1524 1530
1525 if(x > max_x) 1531 if(x > max_x)
1526 max_x = x; 1532 max_x = x;
1527 if(y > max_y) 1533 if(y > max_y)
1528 max_y = y; 1534 max_y = y;
1529 if(coord_is_cached(cur->flags)) 1535 if(coord_is_cached(cur))
1530 preorder_coord_skip_subtree(cur); 1536 preorder_coord_skip_subtree(cur);
1531 } 1537 }
1532 1538
1533 w = max_x - min_x; 1539 w = max_x - min_x;
1534 h = max_y - min_y; 1540 h = max_y - min_y;
1541 1547
1542 /* Without COF_JUST_CLEAN means the coordination system and matrix 1548 /* Without COF_JUST_CLEAN means the coordination system and matrix
1543 * of the coord have not changed since last time of zeroing. So, 1549 * of the coord have not changed since last time of zeroing. So,
1544 * if canvas box cover all descendants, we don't need rezeroing, 1550 * if canvas box cover all descendants, we don't need rezeroing,
1545 * and avoid redraw all descendants. 1551 * and avoid redraw all descendants.
1552 *
1553 * Width and height of actually drawing area should not be smaller
1554 * than half of canvas's width and height.
1546 */ 1555 */
1547 if(!coord_get_flags(coord, COF_JUST_CLEAN) && 1556 if(!coord_get_flags(coord, COF_JUST_CLEAN) &&
1548 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) 1557 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h &&
1558 h >= (c_h >> 2) && w >= (c_w >> 2)) {
1549 /* Canvas fully cover sub-graphic. */ 1559 /* Canvas fully cover sub-graphic. */
1560 coord_set_flags(coord, COF_SKIP_ZERO);
1550 return; 1561 return;
1562 }
1551 1563
1552 /* 1564 /*
1553 * Adjust matrics of descendants to align left-top corner of 1565 * Adjust matrics of descendants to align left-top corner of
1554 * minimum covering area with origin of space defined by 1566 * minimum covering area with origin of space defined by
1555 * zeroing coord. 1567 * zeroing coord.
1582 canvas_free(canvas); 1594 canvas_free(canvas);
1583 canvas = canvas_new(w, h); 1595 canvas = canvas_new(w, h);
1584 _coord_set_canvas(coord, canvas); 1596 _coord_set_canvas(coord, canvas);
1585 } 1597 }
1586 1598
1587 compute_pcache_area(coord);
1588
1589 /* Since aggregated matrix had been changed to make descendants
1590 * falling on the canvas, size or/and position of all descendants
1591 * are chagned, and new canvas was created. So, a dirty area that
1592 * covers all space of the canvas is created to force redrawing
1593 * all descendants.
1594 */
1595 area = &coord->canvas_info->cached_dirty_area;
1596 area->x = 0;
1597 area->y = 0;
1598 area->w = w;
1599 area->h = h;
1600 DARRAY_CLEAN(_coord_get_dirty_areas(coord));
1601 add_dirty_area(rdman, coord, area);
1602
1603 coord_set_flags(coord, COF_JUST_ZERO); 1599 coord_set_flags(coord, COF_JUST_ZERO);
1604 } 1600 }
1605 1601
1606 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. 1602 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords.
1607 * 1603 *
1668 int i; 1664 int i;
1669 coords_t *all_zeroing; 1665 coords_t *all_zeroing;
1670 coord_t *coord; 1666 coord_t *coord;
1671 1667
1672 all_zeroing = &rdman->zeroing_coords; 1668 all_zeroing = &rdman->zeroing_coords;
1673 for(i = 0; i < all_zeroing->num; i++) { 1669 /* From leaft to root.
1670 * REASON: The size of canvas is also effected by cached descedants.
1671 */
1672 for(i = all_zeroing->num - 1; i >= 0; i--) {
1674 coord = all_zeroing->ds[i]; 1673 coord = all_zeroing->ds[i];
1675 zeroing_coord(rdman, coord); 1674 zeroing_coord(rdman, coord);
1676 } 1675 compute_pcache_area(coord);
1677 1676 }
1677
1678 return OK;
1679 }
1680
1681 /*! \brief Compute pcache_area for coords whoes pcache_area is dirty.
1682 */
1683 static int
1684 compute_rdman_coords_pcache_area(redraw_man_t *rdman) {
1685 coords_t *all_coords;
1686 coord_t *coord;
1687 int i;
1688
1689 all_coords = &rdman->dirty_pcache_area_coords;
1690 for(i = 0; i < all_coords->num; i++) {
1691 coord = all_coords->ds[i];
1692 if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA))
1693 compute_pcache_area(coord);
1694 }
1678 return OK; 1695 return OK;
1679 } 1696 }
1680 1697
1681 /*! \brief Add aggregated dirty areas to ancestor. 1698 /*! \brief Add aggregated dirty areas to ancestor.
1682 * 1699 *
1784 if(coord_get_flags(coord, COF_JUST_CLEAN) && 1801 if(coord_get_flags(coord, COF_JUST_CLEAN) &&
1785 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) 1802 !coord_get_flags(pcached_coord, COF_JUST_CLEAN))
1786 add_dirty_area(rdman, pcached_coord, coord->last_area); 1803 add_dirty_area(rdman, pcached_coord, coord->last_area);
1787 } 1804 }
1788 1805
1806 /*! \brief To test if redrawing all elements on the canvas of a cached coord.
1807 */
1808 #define IS_CACHE_REDRAW_ALL(co) \
1809 (coord_get_flags((co), COF_JUST_CLEAN | COF_JUST_ZERO))
1810
1789 /* Aggregate dirty areas and propagate them to ancestor cached coord. 1811 /* Aggregate dirty areas and propagate them to ancestor cached coord.
1790 * 1812 *
1791 * The aggregation is performed from leaves to root. But, this 1813 * The aggregation is performed from leaves to root. But, this
1792 * function do not aggregate dirty areas for root coord. The dirty 1814 * function do not aggregate dirty areas for root coord. The dirty
1793 * areas of a cached coord are aggregated into two areas, one for old 1815 * areas of a cached coord are aggregated into two areas, one for old
1797 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { 1819 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) {
1798 int i; 1820 int i;
1799 int n_zeroing; 1821 int n_zeroing;
1800 coord_t **zeroings; 1822 coord_t **zeroings;
1801 coord_t *coord, *pcached_coord; 1823 coord_t *coord, *pcached_coord;
1802 1824 int n_dpca_coords; /* number of dirty pcache area coords */
1825 coord_t **dpca_coords; /* dirty pcache area coords */
1826
1827 /* Add aggregated areas to parent cached one for coords in zeroing
1828 * list
1829 */
1803 n_zeroing = rdman->zeroing_coords.num; 1830 n_zeroing = rdman->zeroing_coords.num;
1804 zeroings = rdman->zeroing_coords.ds; 1831 zeroings = rdman->zeroing_coords.ds;
1805 for(i = n_zeroing - 1; i >= 0; i--) { 1832 for(i = 0; i < n_zeroing; i++) {
1833 if(coord_get_flags(coord, COF_TEMP_MARK))
1834 continue;
1835 coord_set_flags(coord, COF_TEMP_MARK);
1836
1806 coord = zeroings[i]; 1837 coord = zeroings[i];
1807 pcached_coord = coord_get_cached(coord_get_parent(coord)); 1838 pcached_coord = coord_get_cached(coord_get_parent(coord));
1808 if(!coord_is_root(coord) && !coord_is_zeroing(pcached_coord)) 1839
1840 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1841 continue;
1842
1843 if(IS_CACHE_REDRAW_ALL(coord)) {
1844 add_dirty_area(rdman, pcached_coord,
1845 coord_get_pcache_area(coord));
1846 add_dirty_area(rdman, pcached_coord,
1847 coord_get_pcache_last_area(coord));
1848 } else {
1809 add_aggr_dirty_areas_to_ancestor(rdman, coord); 1849 add_aggr_dirty_areas_to_ancestor(rdman, coord);
1850 }
1851 }
1852
1853 /* Add pcache_areas to parent cached one for coord that is
1854 * non-zeroing and its parent is changed.
1855 */
1856 n_dpca_coords = rdman->dirty_pcache_area_coords.num;
1857 dpca_coords = rdman->dirty_pcache_area_coords.ds;
1858 for(i = 0; i < n_dpca_coords; i++) {
1859 if(coord_get_flags(coord, COF_TEMP_MARK))
1860 continue;
1861 coord_set_flags(coord, COF_TEMP_MARK);
1862
1863 coord = dpca_coords[i];
1864 pcached_coord = coord_get_cached(coord_get_parent(coord));
1865
1866 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord))
1867 continue;
1868
1869 add_dirty_area(rdman, pcached_coord,
1870 coord_get_pcache_area(coord));
1871 add_dirty_area(rdman, pcached_coord,
1872 coord_get_pcache_last_area(coord));
1873 }
1874
1875 /* Remove temporary mark */
1876 for(i = 0; i < n_zeroing; i++) {
1877 coord_clear_flags(zeroing[i], COF_TEMP_MARK);
1878 }
1879 for(i = 0; i < n_dpca_coords; i++) {
1880 coord_clear_flags(dpca_coords[i], COF_TEMP_MARK);
1810 } 1881 }
1811 1882
1812 return OK; 1883 return OK;
1813 } 1884 }
1814 1885
1914 1985
1915 r = zeroing_rdman_coords(rdman); 1986 r = zeroing_rdman_coords(rdman);
1916 if(r != OK) 1987 if(r != OK)
1917 return ERR; 1988 return ERR;
1918 1989
1990 r = compute_rdman_coords_pcache_area(rdman);
1991 if(r != OK)
1992 return ERR;
1993
1919 r = add_rdman_aggr_dirty_areas(rdman); 1994 r = add_rdman_aggr_dirty_areas(rdman);
1920 if(r != OK) 1995 if(r != OK)
1921 return ERR; 1996 return ERR;
1922 1997
1923 r = add_rdman_cached_dirty_areas(rdman); 1998 r = add_rdman_cached_dirty_areas(rdman);