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