GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_canvas_composite_create.c Lines: 55 55 100.0 %
Date: 2024-12-05 08:52:37 Branches: 36 36 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** GUIX Component                                                        */
16
/**                                                                       */
17
/**   Canvas Management (Canvas)                                          */
18
/**                                                                       */
19
/**************************************************************************/
20
21
#define GX_SOURCE_CODE
22
23
24
/* Include necessary system files.  */
25
26
#include "gx_api.h"
27
#include "gx_system.h"
28
#include "gx_utility.h"
29
#include "gx_canvas.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_canvas_composite_create                         PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function checks to see if we have a composite canvas created,  */
45
/*    and if we have an overlay canvas visible. If both are true, the     */
46
/*    function invokes display driver functions to build the composite    */
47
/*    canvas and returns a pointer to the resulting composite.            */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    return_composite                      Return pointer                */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    TRUE/FALSE                            composite created             */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    [gx_display_driver_canvas_copy]       copy canvas                   */
60
/*    [gx_display_driver_canvas_blend]      blend canvas                  */
61
/*    gx_utility_rectangle_shift            move a rectangle              */
62
/*    gx_utility_rectangle_combine          combine (add) two rectangles  */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    _gx_system_canvas_refresh                                           */
67
/*                                                                        */
68
/*  RELEASE HISTORY                                                       */
69
/*                                                                        */
70
/*    DATE              NAME                      DESCRIPTION             */
71
/*                                                                        */
72
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
73
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
74
/*                                            resulting in version 6.1    */
75
/*                                                                        */
76
/**************************************************************************/
77
148532
GX_BOOL  _gx_canvas_composite_create(GX_CANVAS **return_composite)
78
{
79
148532
GX_CANVAS   *composite = GX_NULL;
80
GX_CANVAS   *canvas;
81
148532
GX_CANVAS   *last = GX_NULL;
82
148532
INT          canvas_count = 0;
83
148532
INT          dirty_canvas_count = 0;
84
GX_RECTANGLE invalid_sum;
85
GX_RECTANGLE dirty;
86
87
    /* pick up start of canvas list */
88
148532
    canvas = _gx_system_canvas_created_list;
89
90
    /* initialize the invalid_sum to a NULL rectangle */
91
92
148532
    invalid_sum.gx_rectangle_left = GX_VALUE_MAX;
93
148532
    invalid_sum.gx_rectangle_right = -1;
94
148532
    invalid_sum.gx_rectangle_top = GX_VALUE_MAX;
95
148532
    invalid_sum.gx_rectangle_bottom = -1;
96
97
    /* look for a composite canvas and multiple visible managed cavases.
98
       Sum the the invalid areas along the way */
99
100
398052
    while (canvas)
101
    {
102
        /* is this canvas the composite? */
103
249520
        if (canvas -> gx_canvas_status & GX_CANVAS_COMPOSITE)
104
        {
105
            /* yes, we found the canvas on which to build composite */
106
91355
            composite = canvas;
107
        }
108
        else
109
        {
110
            /* is this a visible managed canvas? */
111
158165
            if ((canvas -> gx_canvas_status & GX_CANVAS_MANAGED_VISIBLE) == GX_CANVAS_MANAGED_VISIBLE)
112
            {
113
                /* yes, add this canvas invalid area to our sum */
114
156769
                if (canvas -> gx_canvas_draw_count > 0)
115
                {
116
122781
                    dirty = canvas -> gx_canvas_dirty_area;
117
122781
                    _gx_utility_rectangle_shift(&dirty, canvas -> gx_canvas_display_offset_x,
118
122781
                                                canvas -> gx_canvas_display_offset_y);
119
122781
                    _gx_utility_rectangle_combine(&invalid_sum, &dirty);
120
122781
                    dirty_canvas_count++;
121
                }
122
                /* increment number of visible canvases */
123
156769
                canvas_count++;
124
            }
125
        }
126
        /* keep pointer to last canvas */
127
249520
        last = canvas;
128
129
        /* move to the next */
130
249520
        canvas = canvas -> gx_canvas_created_next;
131
    }
132
133
    /* if we have found both a comosite canvas a multiple visible managed canvases,
134
       then build the composite */
135
136

148532
    if (composite && canvas_count > 1)
137
    {
138
8237
        if (dirty_canvas_count == 0)
139
        {
140
            /* nothing has changed, just return */
141
2089
            *return_composite = composite;
142
2089
            composite -> gx_canvas_draw_count = 0;
143
2089
            return GX_TRUE;
144
        }
145
146
        /* make sure the invalid left is not off the screen */
147
6148
        if (invalid_sum.gx_rectangle_left < 0)
148
        {
149
136
            invalid_sum.gx_rectangle_left = 0;
150
        }
151
        /* make sure the invalid top is not off the screen */
152
6148
        if (invalid_sum.gx_rectangle_top < 0)
153
        {
154
31
            invalid_sum.gx_rectangle_top = 0;
155
        }
156
        /* make sure the invalid right is not off the screen */
157
6148
        if (invalid_sum.gx_rectangle_right >= composite -> gx_canvas_x_resolution)
158
        {
159
14
            invalid_sum.gx_rectangle_right = (GX_VALUE)(composite -> gx_canvas_x_resolution - 1);
160
        }
161
        /* make sure the invalid bottom is not off the screen */
162
6148
        if (invalid_sum.gx_rectangle_bottom >= composite -> gx_canvas_y_resolution)
163
        {
164
143
            invalid_sum.gx_rectangle_bottom = (GX_VALUE)(composite -> gx_canvas_y_resolution - 1);
165
        }
166
167
        /* save the invalid_sum into composite dirty rectangle */
168
6148
        composite -> gx_canvas_dirty_area = invalid_sum;
169
170
        /* start at the last (lowest) canvas */
171
6148
        canvas = last;
172
6148
        canvas_count = 0;
173
174
        /* copy canvases into composite, moving back to front */
175
24881
        while (canvas)
176
        {
177
            /* is this a visible, managed, overlay canvas? */
178
18733
            if ((canvas -> gx_canvas_status & GX_CANVAS_MANAGED_VISIBLE) == GX_CANVAS_MANAGED_VISIBLE &&
179
12297
                ((canvas -> gx_canvas_status & GX_CANVAS_COMPOSITE) == 0))
180
            {
181
                /* if this canvas is first to draw into composite, or if this canvas
182
                   is not blended, copy it into the composite
183
                 */
184

12296
                if (canvas_count == 0 || canvas -> gx_canvas_alpha == GX_ALPHA_VALUE_OPAQUE)
185
                {
186
                    /* copy the canvas data */
187
9962
                    canvas -> gx_canvas_display -> gx_display_driver_canvas_copy(canvas, composite);
188
                }
189
                else
190
                {
191
                    /* here if the canvas is not first and not opaque. Blend it into
192
                       composite unless it is fully transparent
193
                     */
194

2334
                    if ((canvas->gx_canvas_alpha != 0) && (canvas->gx_canvas_display -> gx_display_driver_canvas_blend))
195
                    {
196
                        /* blend the canvas data */
197
2321
                        canvas -> gx_canvas_display -> gx_display_driver_canvas_blend(canvas, composite);
198
                    }
199
                }
200
12296
                canvas_count++;
201
            }
202
18733
            canvas -> gx_canvas_dirty_count = 0;
203
18733
            canvas -> gx_canvas_draw_count = 0;
204
18733
            canvas = canvas -> gx_canvas_created_previous;
205
        }
206
207
        /* return pointer to composite */
208
6148
        *return_composite = composite;
209
6148
        composite -> gx_canvas_draw_count = (UINT)dirty_canvas_count;
210
6148
        return GX_TRUE;
211
    }
212
213
140295
    *return_composite = GX_NULL;
214
140295
    return GX_FALSE;
215
}
216