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 /** Display Management (Display) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_display.h"
28 #include "gx_utility.h"
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _gx_display_driver_4bpp_canvas_copy PORTABLE C */
35 /* 6.1 */
36 /* AUTHOR */
37 /* */
38 /* Kenneth Maxwell, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* Generic 4bpp canvas copy function. */
43 /* */
44 /* INPUT */
45 /* */
46 /* canvas The canvas to copy from */
47 /* composite The canvas to copy to */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* None */
52 /* */
53 /* CALLS */
54 /* */
55 /* _gx_utility_rectangle_shift Move the rectangle */
56 /* _gx_utility_rectangle_overlap_detect Detect two rectangles being */
57 /* overlap to each other */
58 /* memcpy Move canvas data */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* GUIX Internal Code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
69 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* */
72 /**************************************************************************/
_gx_display_driver_4bpp_canvas_copy(GX_CANVAS * canvas,GX_CANVAS * composite)73 VOID _gx_display_driver_4bpp_canvas_copy(GX_CANVAS *canvas, GX_CANVAS *composite)
74 {
75 GX_RECTANGLE dirty;
76 GX_RECTANGLE overlap;
77 GX_UBYTE *read;
78 GX_UBYTE *write;
79 GX_UBYTE color;
80 INT row;
81 INT column;
82 UINT read_pos;
83 UINT write_pos;
84 GX_UBYTE read_mask;
85 GX_UBYTE write_mask;
86 INT readstride;
87 INT writestride;
88 INT offset;
89
90 dirty.gx_rectangle_left = dirty.gx_rectangle_top = 0;
91 dirty.gx_rectangle_right = (GX_VALUE)(canvas -> gx_canvas_x_resolution - 1);
92 dirty.gx_rectangle_bottom = (GX_VALUE)(canvas -> gx_canvas_y_resolution - 1);
93 readstride = (canvas->gx_canvas_x_resolution + 1) >> 1;
94 writestride = (composite->gx_canvas_x_resolution + 1) >> 1;
95
96 _gx_utility_rectangle_shift(&dirty, canvas -> gx_canvas_display_offset_x, canvas -> gx_canvas_display_offset_y);
97
98 if (_gx_utility_rectangle_overlap_detect(&dirty, &composite -> gx_canvas_dirty_area, &overlap))
99 {
100 offset = overlap.gx_rectangle_left - dirty.gx_rectangle_left;
101 read_pos = (UINT)((overlap.gx_rectangle_top - dirty.gx_rectangle_top) * readstride + (offset >> 1));
102 write_pos = (UINT)(overlap.gx_rectangle_top * writestride + (overlap.gx_rectangle_left >> 1));
103
104 for (row = overlap.gx_rectangle_top; row <= overlap.gx_rectangle_bottom; row++)
105 {
106 read = (GX_UBYTE *)canvas->gx_canvas_memory;
107 write = (GX_UBYTE *)composite->gx_canvas_memory;
108
109 read += read_pos;
110 write += write_pos;
111 /* If position is odd, it means the low bits. */
112 if (offset & 0x01)
113 {
114 read_mask = 0x0f;
115 }
116 else
117 {
118 read_mask = 0xf0;
119 }
120
121 if (overlap.gx_rectangle_left & 0x01)
122 {
123 write_mask = 0x0f;
124 }
125 else
126 {
127 write_mask = 0xf0;
128 }
129
130 for (column = overlap.gx_rectangle_left; column <= overlap.gx_rectangle_right; column++)
131 {
132 color = (*read) & read_mask;
133 *write = (GX_UBYTE)((*write) & (~write_mask));
134
135 if (color)
136 {
137 /* Read and write have same mask bits. */
138 if (read_mask & write_mask)
139 {
140 *write |= color;
141 }
142 else
143 {
144 /* Read and write are malposed. */
145 /* If position is odd, it means the low bits. */
146 if (write_mask & 0x01)
147 {
148 *write |= (GX_UBYTE)(color >> 4);
149 }
150 else
151 {
152 *write |= (GX_UBYTE)(color << 4);
153 }
154 }
155 }
156
157 read_mask >>= 4;
158 write_mask >>= 4;
159 if (!read_mask)
160 {
161 read++;
162 read_mask = 0xf0;
163 }
164 if (!write_mask)
165 {
166 write++;
167 write_mask = 0xf0;
168 }
169 }
170 write_pos = (UINT)((INT)write_pos + writestride);
171 read_pos = (UINT)((INT)read_pos + readstride);
172 }
173 }
174 }
175
176