1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** System Management (System) */
19 /** */
20 /**************************************************************************/
21
22 #define GX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "gx_api.h"
28 #include "gx_system.h"
29 #include "gx_utility.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _gx_system_dirty_overlap_check PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Kenneth Maxwell, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function checks if it has overlapping dirty area with others. */
45 /* */
46 /* INPUT */
47 /* */
48 /* dirty Pointer to dirty area */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* None */
53 /* */
54 /* CALLS */
55 /* */
56 /* _gx_utility_rectangle_overlap_detect Detect overlap of rectangles */
57 /* */
58 /* CALLED BY */
59 /* */
60 /* _gx_system_dirty_list_trim Calculate and trim dirty list */
61 /* */
62 /* RELEASE HISTORY */
63 /* */
64 /* DATE NAME DESCRIPTION */
65 /* */
66 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
67 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
68 /* resulting in version 6.1 */
69 /* */
70 /**************************************************************************/
_gx_system_dirty_overlap_check(GX_DIRTY_AREA * dirty)71 static VOID _gx_system_dirty_overlap_check(GX_DIRTY_AREA *dirty)
72 {
73 GX_WIDGET *dirty_widget;
74 GX_WIDGET *sibling;
75 GX_WIDGET *parent;
76
77 dirty_widget = dirty -> gx_dirty_area_widget;
78 parent = dirty_widget -> gx_widget_parent;
79
80 while (parent)
81 {
82 /* check to see if this is a viewport owner */
83 if (dirty -> gx_dirty_area_widget -> gx_widget_type >= GX_TYPE_WINDOW)
84 {
85 if (parent -> gx_widget_type == GX_TYPE_ROOT_WINDOW)
86 {
87 /* this widget is a view owner, no need to go further */
88 return;
89 }
90 }
91
92 /* not a view owner, so check to see if it has overlapping siblings */
93 sibling = dirty_widget -> gx_widget_next;
94
95 while(sibling)
96 {
97 if (_gx_utility_rectangle_overlap_detect(&sibling -> gx_widget_size, &dirty -> gx_dirty_area_rectangle, NULL))
98 {
99 /* mark the parent as dirty, so that both children are drawn */
100 dirty_widget = parent;
101 dirty -> gx_dirty_area_widget = dirty_widget;
102 break;
103 }
104 sibling = sibling->gx_widget_next;
105 }
106 dirty_widget = parent;
107 parent = dirty_widget -> gx_widget_parent;
108 }
109 }
110
111 /**************************************************************************/
112 /* */
113 /* FUNCTION RELEASE */
114 /* */
115 /* _gx_system_dirty_list_trim PORTABLE C */
116 /* 6.1 */
117 /* AUTHOR */
118 /* */
119 /* Kenneth Maxwell, Microsoft Corporation */
120 /* */
121 /* DESCRIPTION */
122 /* */
123 /* This function trims the dirty list to reduce redundancy and */
124 /* eliminate invalid entries prior to refreshing the canvas. This */
125 /* function returns the sum of the remaining dirty areas */
126 /* */
127 /* INPUT */
128 /* */
129 /* dirty_area Pointer to return value */
130 /* root Point to the root window */
131 /* */
132 /* OUTPUT */
133 /* */
134 /* [GX_TRUE | GX_FALSE] GX_TRUE if dirty, otherwise */
135 /* GX_FALSE */
136 /* */
137 /* CALLS */
138 /* */
139 /* _gx_utility_rectangle_combine Combine two rectangles */
140 /* _gx_utility_rectangle_define Define a rectangle */
141 /* _gx_utility_rectangle_overlap_detect Detect overlap of rectangles */
142 /* _gx_system_dirty_overlap_check Detect overlapping children */
143 /* */
144 /* CALLED BY */
145 /* */
146 /* _gx_system_canvas_refresh Refresh the canvas */
147 /* */
148 /* RELEASE HISTORY */
149 /* */
150 /* DATE NAME DESCRIPTION */
151 /* */
152 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
153 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
154 /* resulting in version 6.1 */
155 /* */
156 /**************************************************************************/
_gx_system_dirty_list_trim(GX_RECTANGLE * dirty_area,GX_WINDOW_ROOT * root)157 UINT _gx_system_dirty_list_trim(GX_RECTANGLE *dirty_area, GX_WINDOW_ROOT *root)
158 {
159
160 UINT index_1;
161 UINT index_2;
162 GX_DIRTY_AREA *dirty;
163 GX_DIRTY_AREA *dirty2;
164 GX_CANVAS *canvas;
165 GX_WIDGET *parent;
166
167 /* pick up pointer to canvas */
168 canvas = root -> gx_window_root_canvas;
169
170 /* Initialize a dirty area rectangle. */
171 _gx_utility_rectangle_define(dirty_area, canvas -> gx_canvas_x_resolution,
172 canvas -> gx_canvas_y_resolution, -1, -1);
173
174 /* Setup pointer to start of dirty area list. */
175 dirty = canvas -> gx_canvas_dirty_list;
176
177 /* This loop looks for invalid entries (invisible) and
178 entries that have overlappers in the z order, in
179 which case we need to back up the drawing layer
180 */
181
182 for (index_1 = 0; index_1 < canvas -> gx_canvas_dirty_count; index_1++)
183 {
184 /* Is there a widget for this dirty area entry? */
185 if (dirty -> gx_dirty_area_widget == GX_NULL)
186 {
187 dirty++;
188 continue;
189 }
190
191 if (!(dirty -> gx_dirty_area_widget -> gx_widget_status & GX_STATUS_VISIBLE))
192 {
193 dirty -> gx_dirty_area_widget = GX_NULL;
194 dirty++;
195 continue;
196 }
197
198 /* check to see if we need to modify the drawing level because of overlapping
199 siblings
200 */
201 _gx_system_dirty_overlap_check(dirty);
202 dirty++;
203 }
204
205 /* This loop tests to see if a dirty entry also has a parent
206 that is marked as dirty. If the dirty rectangles overlap,
207 just combine the rectangles and get rid of the child entry
208 */
209
210 dirty = canvas -> gx_canvas_dirty_list;
211
212 for (index_1 = 0; index_1 < canvas -> gx_canvas_dirty_count; index_1++)
213 {
214 /* Is there a widget for this dirty area entry? */
215 if (dirty -> gx_dirty_area_widget == GX_NULL)
216 {
217 dirty++;
218 continue;
219 }
220
221 /* Yes, there is a widget. Loop through the dirty area array. */
222 for (index_2 = 0; index_2 < canvas -> gx_canvas_dirty_count; index_2++)
223 {
224 /* Pickup the next dirty area entry. */
225 dirty2 = &canvas -> gx_canvas_dirty_list[index_2];
226
227 /* Is is valid? */
228 if ((dirty2 -> gx_dirty_area_widget) && (dirty != dirty2))
229 {
230 parent = dirty2 -> gx_dirty_area_widget -> gx_widget_parent;
231
232 while (parent && (parent != dirty -> gx_dirty_area_widget))
233 {
234 parent = parent -> gx_widget_parent;
235 }
236
237 /* check to see if one is parent of the other */
238 if (parent == dirty -> gx_dirty_area_widget)
239 {
240 /* dirty1 is parent of dirty2, do the dirty
241 rectangles overlap? */
242 if (_gx_utility_rectangle_overlap_detect(&dirty -> gx_dirty_area_rectangle, &dirty2 -> gx_dirty_area_rectangle, NULL))
243 {
244 /* Yes, combine the two entries into one and NULL out the child entry. */
245 _gx_utility_rectangle_combine(&dirty -> gx_dirty_area_rectangle, &dirty2 -> gx_dirty_area_rectangle);
246
247 /* NULL out the child entry. */
248 dirty2 -> gx_dirty_area_widget = GX_NULL;
249 continue;
250 }
251 }
252
253 /* check to see if two entries for same widget */
254 if (dirty2 -> gx_dirty_area_widget == dirty -> gx_dirty_area_widget)
255 {
256 /* same widget marked twice */
257 /* do the dirty rectangles overlap? */
258 if (_gx_utility_rectangle_overlap_detect(&dirty -> gx_dirty_area_rectangle, &dirty2 -> gx_dirty_area_rectangle, NULL))
259 {
260 /* Yes, combine the two entries into one and NULL out the child entry. */
261 _gx_utility_rectangle_combine(&dirty -> gx_dirty_area_rectangle, &dirty2 -> gx_dirty_area_rectangle);
262
263 /* NULL out the second entry. */
264 dirty2 -> gx_dirty_area_widget = GX_NULL;
265 }
266 }
267 }
268 }
269
270 /* Add to our overall sum of dirty area. */
271 _gx_utility_rectangle_combine(dirty_area, &(dirty -> gx_dirty_area_rectangle));
272
273 /* Move to next dirty area entry. */
274 dirty++;
275 }
276
277 /* Do we have anything to draw? */
278 if ((dirty_area -> gx_rectangle_left <= dirty_area -> gx_rectangle_right) &&
279 (dirty_area -> gx_rectangle_top <= dirty_area -> gx_rectangle_bottom))
280 {
281
282 /* Yes, we have something to draw. */
283 return(GX_TRUE);
284 }
285 else
286 {
287
288 /* No, nothing left after trimming duplicates. */
289 return(GX_FALSE);
290 }
291 }
292
293