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_system.h"
29 #include "gx_utility.h"
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _gx_display_driver_4bpp_block_move PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* 4-bpp display driver block moving function. */
44 /* */
45 /* INPUT */
46 /* */
47 /* context Draw context */
48 /* block The rectangle to be moved */
49 /* xshift Amount to move on X-axis */
50 /* yshift Amount to move on Y-axis */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* memmove Move a block of 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_block_move(GX_DRAW_CONTEXT * context,GX_RECTANGLE * block,INT xshift,INT yshift)73 VOID _gx_display_driver_4bpp_block_move(GX_DRAW_CONTEXT *context,
74 GX_RECTANGLE *block, INT xshift, INT yshift)
75 {
76 GX_UBYTE *putrow;
77 GX_UBYTE *getrow;
78 GX_UBYTE *pGet;
79 GX_UBYTE *pPut;
80 INT width;
81 INT column;
82 INT y;
83 INT height;
84 INT stride;
85 GX_UBYTE putmask;
86 GX_UBYTE getmask;
87 INT move_width;
88
89 putrow = (GX_UBYTE *)context -> gx_draw_context_memory;
90
91 stride = (context -> gx_draw_context_pitch + 1) >> 1;
92
93 if (xshift)
94 {
95 if (xshift > 0)
96 {
97 /* Copy from right to left. */
98 width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
99 width -= xshift;
100
101 putrow += block -> gx_rectangle_top * stride;
102 getrow = putrow;
103
104 putrow += block -> gx_rectangle_right >> 1;
105 getrow += (block -> gx_rectangle_left + width - 1) >> 1;
106
107 for (y = block -> gx_rectangle_top; y <= block -> gx_rectangle_bottom; y++)
108 {
109 pPut = putrow;
110 pGet = getrow;
111
112 if (block -> gx_rectangle_right & 0x01)
113 {
114 putmask = 0x0f;
115 }
116 else
117 {
118 putmask = 0xf0;
119 }
120
121 if ((block -> gx_rectangle_left + width - 1) & 0x01)
122 {
123 getmask = 0x0f;
124 }
125 else
126 {
127 getmask = 0xf0;
128 }
129
130 for (column = 0; column < width; column++)
131 {
132 /* Set bits to 0. */
133 *pPut &= (GX_UBYTE)(~putmask);
134
135 if ((*pGet) & getmask)
136 {
137 if (getmask == putmask)
138 {
139 *pPut |= ((*pGet) & getmask);
140 }
141 else
142 {
143 if (getmask == 0xf0)
144 {
145 *pPut |= (GX_UBYTE)((((*pGet) & getmask) >> 4) & 0x0f);
146 }
147 else
148 {
149 *pPut |= (GX_UBYTE)((GX_UBYTE)(((*pGet) & getmask) << 4) & 0xf0);
150 }
151 }
152 }
153
154 if (getmask == 0xf0)
155 {
156 getmask = 0x0f;
157 pGet--;
158 }
159 else
160 {
161 getmask = 0xf0;
162 }
163
164 if (putmask == 0xf0)
165 {
166 putmask = 0x0f;
167 pPut--;
168 }
169 else
170 {
171 putmask = 0xf0;
172 }
173 }
174
175 putrow += stride;
176 getrow += stride;
177 }
178 }
179 else
180 {
181 /* Copy from right to left. */
182 width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
183 width += xshift;
184
185 putrow += block -> gx_rectangle_top * stride;
186 getrow = putrow;
187
188 putrow += block -> gx_rectangle_left >> 1;
189 getrow += (block -> gx_rectangle_left - xshift) >> 1;
190
191 for (y = block -> gx_rectangle_top; y <= block -> gx_rectangle_bottom; y++)
192 {
193 pPut = putrow;
194 pGet = getrow;
195
196 if (block -> gx_rectangle_left & 0x01)
197 {
198 putmask = 0x0f;
199 }
200 else
201 {
202 putmask = 0xf0;
203 }
204
205 if ((block -> gx_rectangle_left - xshift) & 0x01)
206 {
207 getmask = 0x0f;
208 }
209 else
210 {
211 getmask = 0xf0;
212 }
213
214 for (column = 0; column < width; column++)
215 {
216 /* Set bits to 0. */
217 *pPut &= (GX_UBYTE)(~putmask);
218
219 if ((*pGet) & getmask)
220 {
221 if (getmask == putmask)
222 {
223 *pPut |= ((*pGet) & getmask);
224 }
225 else
226 {
227 if (getmask == 0xf0)
228 {
229 *pPut |= (GX_UBYTE)((((*pGet) & getmask) >> 4) & 0x0f);
230 }
231 else
232 {
233 *pPut |= (GX_UBYTE)((GX_UBYTE)(((*pGet) & getmask) << 4) & 0xf0);
234 }
235 }
236 }
237
238 getmask >>= 4;
239 if (getmask == 0)
240 {
241 getmask = 0xf0;
242 pGet++;
243 }
244
245 putmask >>= 4;
246 if (putmask == 0)
247 {
248 putmask = 0xf0;
249 pPut++;
250 }
251 }
252
253 putrow += stride;
254 getrow += stride;
255 }
256 }
257 }
258 else
259 {
260 width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
261
262 if (yshift > 0)
263 {
264 /* Copy from top to bottom. */
265 putrow += (block -> gx_rectangle_bottom * stride);
266 putrow += (block -> gx_rectangle_left >> 1);
267
268 getrow = putrow;
269 getrow -= yshift * stride;
270
271 height = block -> gx_rectangle_bottom - block -> gx_rectangle_top + 1;
272 height -= yshift;
273
274 for (y = 0; y < height; y++)
275 {
276 pPut = putrow;
277 pGet = getrow;
278
279 if (block -> gx_rectangle_left & 0x01)
280 {
281 putmask = 0x0f;
282 }
283 else
284 {
285 putmask = 0xf0;
286 }
287
288 column = 0;
289 while (column < width)
290 {
291 if ((putmask == 0xf0) && (width - column >= 2))
292 {
293 move_width = (width - column) >> 1;
294 memmove(pPut, pGet, (size_t)move_width);
295 pPut += move_width;
296 pGet += move_width;
297 column += (move_width << 1);
298 }
299 else
300 {
301 *pPut &= (GX_UBYTE)(~putmask);
302 if ((*pGet) & putmask)
303 {
304 *pPut |= (GX_UBYTE)((*pGet) & putmask);
305 }
306
307
308 putmask >>= 4;
309
310 if (putmask == 0)
311 {
312 putmask = 0xf0;
313 pPut++;
314 pGet++;
315 }
316
317 column++;
318 }
319 }
320
321 putrow -= stride;
322 getrow -= stride;
323 }
324 }
325 else
326 {
327 /* Copy from bottom to top. */
328 putrow += (block -> gx_rectangle_top * stride);
329 putrow += (block -> gx_rectangle_left >> 1);
330
331 getrow = putrow;
332 getrow -= yshift * stride;
333
334 height = block -> gx_rectangle_bottom - block -> gx_rectangle_top + 1;
335 height += yshift;
336
337 for (y = 0; y < height; y++)
338 {
339 pPut = putrow;
340 pGet = getrow;
341
342 if (block -> gx_rectangle_left & 0x01)
343 {
344 putmask = 0x0f;
345 }
346 else
347 {
348 putmask = 0xf0;
349 }
350
351 column = 0;
352
353 while (column < width)
354 {
355 if ((putmask == 0xf0) && (width - column >= 2))
356 {
357 move_width = (width - column) >> 1;
358 memmove(pPut, pGet, (size_t)move_width);
359 pPut += move_width;
360 pGet += move_width;
361 column += (move_width << 1);
362 }
363 else
364 {
365 *pPut &= (GX_UBYTE)(~putmask);
366 if ((*pGet) & putmask)
367 {
368 *pPut |= (GX_UBYTE)((*pGet) & putmask);
369 }
370
371 putmask >>= 4;
372
373 if (putmask == 0)
374 {
375 putmask = 0xf0;
376 pPut++;
377 pGet++;
378 }
379
380 column++;
381 }
382 }
383
384 putrow += stride;
385 getrow += stride;
386 }
387 }
388 }
389 }
390
391