aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@nokia.com>2010-06-09 08:09:30 -0400
committerTomi Valkeinen <tomi.valkeinen@nokia.com>2010-08-03 08:18:45 -0400
commit8cab90fdb4c71f9a92c09c015aee42ff2149b317 (patch)
tree76d367e62d5bc784f10a74c62da45376f8723580 /drivers/video
parent75c7d59daf502a4eb040e181120fb83b4a8c0719 (diff)
OMAP: DSS2: Fix update area calculations with multiple scaled overlays
When there are multiple scaled overlays simply checking whether the update area intersects any of them in order is not enough. If eg. VID1 starts out completely outside the update area but VID2 causes the update area to increase in such a way that VID1 now falls partially within the increased update area VID1 should be rechecked and the update area possibly increased even further to fully encompass VID1. So simply keep looping over the overlays until such time that none of the overlays caused the update area to change. Signed-off-by: Ville Syrjälä <ville.syrjala@nokia.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/manager.c141
1 files changed, 78 insertions, 63 deletions
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 7e1ec5af6c70..a1d84ef65904 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -972,6 +972,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
972 int i; 972 int i;
973 u16 x, y, w, h; 973 u16 x, y, w, h;
974 unsigned long flags; 974 unsigned long flags;
975 bool area_changed;
975 976
976 x = *xi; 977 x = *xi;
977 y = *yi; 978 y = *yi;
@@ -992,70 +993,84 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
992 993
993 spin_lock_irqsave(&dss_cache.lock, flags); 994 spin_lock_irqsave(&dss_cache.lock, flags);
994 995
995 /* We need to show the whole overlay if it is scaled. So look for 996 /*
996 * those, and make the update area larger if found. 997 * Execute the outer loop until the inner loop has completed
997 * Also mark the overlay cache dirty */ 998 * once without increasing the update area. This will ensure that
998 for (i = 0; i < num_ovls; ++i) { 999 * all scaled overlays end up completely within the update area.
999 unsigned x1, y1, x2, y2; 1000 */
1000 unsigned outw, outh; 1001 do {
1001 1002 area_changed = false;
1002 oc = &dss_cache.overlay_cache[i]; 1003
1003 1004 /* We need to show the whole overlay if it is scaled. So look
1004 if (oc->channel != mgr->id) 1005 * for those, and make the update area larger if found.
1005 continue; 1006 * Also mark the overlay cache dirty */
1006 1007 for (i = 0; i < num_ovls; ++i) {
1007 oc->dirty = true; 1008 unsigned x1, y1, x2, y2;
1008 1009 unsigned outw, outh;
1009 if (!oc->enabled) 1010
1010 continue; 1011 oc = &dss_cache.overlay_cache[i];
1011 1012
1012 if (!dispc_is_overlay_scaled(oc)) 1013 if (oc->channel != mgr->id)
1013 continue; 1014 continue;
1014 1015
1015 outw = oc->out_width == 0 ? oc->width : oc->out_width; 1016 oc->dirty = true;
1016 outh = oc->out_height == 0 ? oc->height : oc->out_height; 1017
1017 1018 if (!oc->enabled)
1018 /* is the overlay outside the update region? */ 1019 continue;
1019 if (!rectangle_intersects(x, y, w, h, 1020
1020 oc->pos_x, oc->pos_y, 1021 if (!dispc_is_overlay_scaled(oc))
1021 outw, outh)) 1022 continue;
1022 continue; 1023
1023 1024 outw = oc->out_width == 0 ?
1024 /* if the overlay totally inside the update region? */ 1025 oc->width : oc->out_width;
1025 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, 1026 outh = oc->out_height == 0 ?
1026 x, y, w, h)) 1027 oc->height : oc->out_height;
1027 continue; 1028
1028 1029 /* is the overlay outside the update region? */
1029 if (x > oc->pos_x) 1030 if (!rectangle_intersects(x, y, w, h,
1030 x1 = oc->pos_x; 1031 oc->pos_x, oc->pos_y,
1031 else 1032 outw, outh))
1032 x1 = x; 1033 continue;
1033 1034
1034 if (y > oc->pos_y) 1035 /* if the overlay totally inside the update region? */
1035 y1 = oc->pos_y; 1036 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
1036 else 1037 x, y, w, h))
1037 y1 = y; 1038 continue;
1038 1039
1039 if ((x + w) < (oc->pos_x + outw)) 1040 if (x > oc->pos_x)
1040 x2 = oc->pos_x + outw; 1041 x1 = oc->pos_x;
1041 else 1042 else
1042 x2 = x + w; 1043 x1 = x;
1043 1044
1044 if ((y + h) < (oc->pos_y + outh)) 1045 if (y > oc->pos_y)
1045 y2 = oc->pos_y + outh; 1046 y1 = oc->pos_y;
1046 else 1047 else
1047 y2 = y + h; 1048 y1 = y;
1048 1049
1049 x = x1; 1050 if ((x + w) < (oc->pos_x + outw))
1050 y = y1; 1051 x2 = oc->pos_x + outw;
1051 w = x2 - x1; 1052 else
1052 h = y2 - y1; 1053 x2 = x + w;
1053 1054
1054 make_even(&x, &w); 1055 if ((y + h) < (oc->pos_y + outh))
1055 1056 y2 = oc->pos_y + outh;
1056 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", 1057 else
1058 y2 = y + h;
1059
1060 x = x1;
1061 y = y1;
1062 w = x2 - x1;
1063 h = y2 - y1;
1064
1065 make_even(&x, &w);
1066
1067 DSSDBG("changing upd area due to ovl(%d) "
1068 "scaling %d,%d %dx%d\n",
1057 i, x, y, w, h); 1069 i, x, y, w, h);
1058 } 1070
1071 area_changed = true;
1072 }
1073 } while (area_changed);
1059 1074
1060 mc = &dss_cache.manager_cache[mgr->id]; 1075 mc = &dss_cache.manager_cache[mgr->id];
1061 mc->do_manual_update = true; 1076 mc->do_manual_update = true;