GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_canvas_composite_create.c Lines: 55 55 100.0 %
Date: 2026-03-06 19:21:09 Branches: 36 36 100.0 %

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

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

12296
                if (canvas_count == 0 || canvas -> gx_canvas_alpha == GX_ALPHA_VALUE_OPAQUE)
178
                {
179
                    /* copy the canvas data */
180
9962
                    canvas -> gx_canvas_display -> gx_display_driver_canvas_copy(canvas, composite);
181
                }
182
                else
183
                {
184
                    /* here if the canvas is not first and not opaque. Blend it into
185
                       composite unless it is fully transparent
186
                     */
187

2334
                    if ((canvas->gx_canvas_alpha != 0) && (canvas->gx_canvas_display -> gx_display_driver_canvas_blend))
188
                    {
189
                        /* blend the canvas data */
190
2321
                        canvas -> gx_canvas_display -> gx_display_driver_canvas_blend(canvas, composite);
191
                    }
192
                }
193
12296
                canvas_count++;
194
            }
195
18733
            canvas -> gx_canvas_dirty_count = 0;
196
18733
            canvas -> gx_canvas_draw_count = 0;
197
18733
            canvas = canvas -> gx_canvas_created_previous;
198
        }
199
200
        /* return pointer to composite */
201
6148
        *return_composite = composite;
202
6148
        composite -> gx_canvas_draw_count = (UINT)dirty_canvas_count;
203
6148
        return GX_TRUE;
204
    }
205
206
140354
    *return_composite = GX_NULL;
207
140354
    return GX_FALSE;
208
}
209