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 
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _gx_display_driver_32xrgb_pixelmap_alpha_write      PORTABLE C      */
35 /*                                                           6.1.7        */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Kenneth Maxwell, Microsoft Corporation                              */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    Internal helper function that handles writing of uncompressed       */
43 /*    pixlemap file with alpha channel.                                   */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    context                               Drawing context               */
48 /*    xpos                                  x-coord of top-left draw point*/
49 /*    ypos                                  y-coord of top-left draw point*/
50 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*     _gx_display_driver_32argb_pixel_blend                              */
59 /*                                          Display driver basic pixel    */
60 /*                                            blend function              */
61 /*     _gx_display_driver_32bpp_pixel_write                               */
62 /*                                          Display driver basic pixel    */
63 /*                                            write function              */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _gx_display_driver_32argb_pixelmap_draw                             */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
74 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
75 /*                                            resulting in version 6.1    */
76 /*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
77 /*                                            removed unused variable     */
78 /*                                            assignment,                 */
79 /*                                            resulting in version 6.1.7  */
80 /*                                                                        */
81 /**************************************************************************/
_gx_display_driver_32argb_pixelmap_alpha_write(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap)82 static VOID _gx_display_driver_32argb_pixelmap_alpha_write(GX_DRAW_CONTEXT *context,
83                                                            INT xpos, INT ypos, GX_PIXELMAP *pixelmap)
84 {
85 INT           xval;
86 INT           yval;
87 GX_COLOR      color;
88 INT           width;
89 ULONG        *get;
90 UCHAR         alpha_value;
91 
92 GX_RECTANGLE *clip = context -> gx_draw_context_clip;
93 
94     get = (ULONG *)((ULONG)pixelmap -> gx_pixelmap_data + (sizeof(GX_COLOR) * (UINT)(pixelmap -> gx_pixelmap_width) * (UINT)(((INT)(clip -> gx_rectangle_top) - ypos))));
95     get += (clip -> gx_rectangle_left - xpos);
96 
97     width = clip -> gx_rectangle_right - clip -> gx_rectangle_left + 1;
98 
99     for (yval = clip -> gx_rectangle_top; yval <= clip -> gx_rectangle_bottom; yval++)
100     {
101         for (xval = clip -> gx_rectangle_left; xval <= clip -> gx_rectangle_right; xval++)
102         {
103             color = *get;
104             alpha_value = (UCHAR)(color >> 24);
105             if (alpha_value == 255)
106             {
107                 _gx_display_driver_32bpp_pixel_write(context, xval, yval, color);
108             }
109             else
110             {
111                 _gx_display_driver_32argb_pixel_blend(context, xval, yval, color, 0xff);
112             }
113             get++;
114         }
115         get += pixelmap -> gx_pixelmap_width - width;
116     }
117 }
118 
119 /**************************************************************************/
120 /*                                                                        */
121 /*  FUNCTION                                               RELEASE        */
122 /*                                                                        */
123 /*    _gx_display_driver_32xrgb_pixelmap_compressed_alpha_write           */
124 /*                                                        PORTABLE C      */
125 /*                                                           6.1.12       */
126 /*  AUTHOR                                                                */
127 /*                                                                        */
128 /*    Kenneth Maxwell, Microsoft Corporation                              */
129 /*                                                                        */
130 /*  DESCRIPTION                                                           */
131 /*                                                                        */
132 /*    Internal helper function that handles writing of compressed         */
133 /*    pixlemap file with alpha channel.                                   */
134 /*                                                                        */
135 /*  INPUT                                                                 */
136 /*                                                                        */
137 /*    context                               Drawing context               */
138 /*    xpos                                  x-coord of top-left draw point*/
139 /*    ypos                                  y-coord of top-left draw point*/
140 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
141 /*                                                                        */
142 /*  OUTPUT                                                                */
143 /*                                                                        */
144 /*    None                                                                */
145 /*                                                                        */
146 /*  CALLS                                                                 */
147 /*                                                                        */
148 /*     _gx_display_driver_32argb_pixel_blend                              */
149 /*                                          Display driver basic pixel    */
150 /*                                            blend function              */
151 /*                                                                        */
152 /*  CALLED BY                                                             */
153 /*                                                                        */
154 /*    GUIX Internal Code                                                  */
155 /*                                                                        */
156 /*  RELEASE HISTORY                                                       */
157 /*                                                                        */
158 /*    DATE              NAME                      DESCRIPTION             */
159 /*                                                                        */
160 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
161 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
162 /*                                            resulting in version 6.1    */
163 /*  07-29-2022     Kenneth Maxwell          Modified comment(s),          */
164 /*                                            resulting in version 6.1.12 */
165 /*                                                                        */
166 /**************************************************************************/
_gx_display_driver_32argb_pixelmap_compressed_alpha_write(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap)167 static VOID _gx_display_driver_32argb_pixelmap_compressed_alpha_write(GX_DRAW_CONTEXT *context,
168                                                                       INT xpos, INT ypos, GX_PIXELMAP *pixelmap)
169 {
170 INT                yval;
171 INT                xval;
172 GX_CONST GX_COLOR *get;
173 GX_UBYTE           count;
174 GX_COLOR           pixel;
175 GX_CONST GX_UBYTE *get_count;
176 GX_UBYTE           brush_alpha;
177 GX_UBYTE           alpha;
178 
179 GX_RECTANGLE      *clip = context -> gx_draw_context_clip;
180 
181     brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
182 
183     get = (GX_CONST GX_COLOR *)pixelmap -> gx_pixelmap_data;
184     get_count = (GX_CONST GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
185 
186     /* first, skip to the starting row */
187     for (yval = ypos; yval < clip -> gx_rectangle_top; yval++)
188     {
189         xval = 0;
190         while (xval < pixelmap -> gx_pixelmap_width)
191         {
192             count = *get_count++;
193 
194             if (count & 0x80)
195             {
196                 count = (GX_UBYTE)((count & 0x7f) + 1u);
197                 get++;      /* skip repeated pixel value */
198             }
199             else
200             {
201                 count++;
202                 get += count;   /* skip raw pixel values */
203             }
204             xval += count;
205         }
206     }
207 
208     /* now we are on the first visible row, copy pixels until we get
209        to the end of the last visible row
210      */
211 
212     while (yval <= clip -> gx_rectangle_bottom)
213     {
214         xval = xpos;
215 
216         while (xval < xpos + pixelmap -> gx_pixelmap_width)
217         {
218             count = *get_count++;
219 
220             if (count & 0x80)
221             {
222                 /* repeated value */
223                 count = (GX_UBYTE)((count & 0x7f) + 1u);
224                 alpha = (GX_UBYTE)((*get) >> 24);
225                 pixel = *get++;
226 
227                 if (alpha)
228                 {
229                     while (count--)
230                     {
231                         if (xval >= clip -> gx_rectangle_left &&
232                             xval <= clip -> gx_rectangle_right)
233                         {
234                             _gx_display_driver_32argb_pixel_blend(context, xval, yval, pixel, brush_alpha);
235                         }
236                         xval++;
237                     }
238                 }
239                 else
240                 {
241                     xval += count;
242                 }
243             }
244             else
245             {
246                 /* string of non-repeated values */
247                 count++;
248 
249                 while (count--)
250                 {
251                     if (xval >= clip -> gx_rectangle_left &&
252                         xval <= clip -> gx_rectangle_right)
253                     {
254                         pixel = *get;
255 
256                         _gx_display_driver_32argb_pixel_blend(context, xval, yval, pixel, brush_alpha);
257                     }
258                     get++;
259                     xval++;
260                 }
261             }
262         }
263         yval++;
264     }
265 }
266 
267 /**************************************************************************/
268 /*                                                                        */
269 /*  FUNCTION                                               RELEASE        */
270 /*                                                                        */
271 /*    _gx_display_driver_32argb_pixelmap_compressed_write                 */
272 /*                                                        PORTABLE C      */
273 /*                                                           6.1          */
274 /*  AUTHOR                                                                */
275 /*                                                                        */
276 /*    Kenneth Maxwell, Microsoft Corporation                              */
277 /*                                                                        */
278 /*  DESCRIPTION                                                           */
279 /*                                                                        */
280 /*    Internal helper function that handles writing of compressed         */
281 /*    pixlemap file without alpha channel.                                */
282 /*                                                                        */
283 /*  INPUT                                                                 */
284 /*                                                                        */
285 /*    context                               Drawing context               */
286 /*    xpos                                  x-coord of top-left draw point*/
287 /*    ypos                                  y-coord of top-left draw point*/
288 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
289 /*                                                                        */
290 /*  OUTPUT                                                                */
291 /*                                                                        */
292 /*    None                                                                */
293 /*                                                                        */
294 /*  CALLS                                                                 */
295 /*                                                                        */
296 /*     _gx_display_driver_32argb_pixel_blend                              */
297 /*                                          Display driver basic pixel    */
298 /*                                            blend function              */
299 /*                                                                        */
300 /*  CALLED BY                                                             */
301 /*                                                                        */
302 /*    _gx_display_driver_32argb_pixelmap_draw                             */
303 /*                                                                        */
304 /*  RELEASE HISTORY                                                       */
305 /*                                                                        */
306 /*    DATE              NAME                      DESCRIPTION             */
307 /*                                                                        */
308 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
309 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
310 /*                                            resulting in version 6.1    */
311 /*                                                                        */
312 /**************************************************************************/
_gx_display_driver_32argb_pixelmap_compressed_write(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap)313 static VOID _gx_display_driver_32argb_pixelmap_compressed_write(GX_DRAW_CONTEXT *context,
314                                                                 INT xpos, INT ypos, GX_PIXELMAP *pixelmap)
315 {
316 INT                yval;
317 INT                xval;
318 GX_CONST GX_COLOR *get;
319 GX_COLOR          *put;
320 GX_COLOR          *putrow;
321 GX_UBYTE           count;
322 GX_COLOR           pixel;
323 GX_CONST GX_UBYTE *get_count;
324 GX_UBYTE           brush_alpha;
325 
326 GX_RECTANGLE      *clip = context -> gx_draw_context_clip;
327 
328     brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
329 
330     get = (GX_CONST GX_COLOR *)pixelmap -> gx_pixelmap_data;
331     get_count = (GX_CONST GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
332 
333     /* first, skip to the starting row */
334     for (yval = ypos; yval < clip -> gx_rectangle_top; yval++)
335     {
336         xval = 0;
337         while (xval < pixelmap -> gx_pixelmap_width)
338         {
339             count = *get_count++;
340 
341             if (count & 0x80)
342             {
343                 count = (GX_UBYTE)((count & 0x7f) + 1u);
344                 get++;      /* skip repeated pixel value */
345             }
346             else
347             {
348                 count++;
349                 get += count;   /* skip raw pixel values */
350             }
351             xval += count;
352         }
353     }
354 
355     /* now we are on the first visible row, copy pixels until we get
356        to the enf of the last visible row
357      */
358     putrow = (GX_COLOR *)context -> gx_draw_context_memory;
359     putrow += yval * context -> gx_draw_context_pitch;
360     putrow += xpos;
361 
362     while (yval <= clip -> gx_rectangle_bottom)
363     {
364         put = putrow;
365         xval = xpos;
366 
367         while (xval < xpos + pixelmap -> gx_pixelmap_width)
368         {
369             count = *get_count++;
370 
371             if (count & 0x80)
372             {
373                 /* repeated value */
374                 count = (GX_UBYTE)((count & 0x7f) + 1u);
375                 pixel = *get++;
376 
377                 if (brush_alpha == 0xff)
378                 {
379                     while (count--)
380                     {
381                         if (xval >= clip -> gx_rectangle_left &&
382                             xval <= clip -> gx_rectangle_right)
383                         {
384                             *put = pixel;
385                         }
386                         put++;
387                         xval++;
388                     }
389                 }
390                 else
391                 {
392                     while (count--)
393                     {
394                         if (xval >= clip -> gx_rectangle_left &&
395                             xval <= clip -> gx_rectangle_right)
396                         {
397                             _gx_display_driver_32argb_pixel_blend(context, xval, yval, pixel, brush_alpha);
398                         }
399                         xval++;
400                     }
401                 }
402             }
403             else
404             {
405                 /* string of non-repeated values */
406                 count++;
407 
408                 if (brush_alpha == 0xff)
409                 {
410                     while (count--)
411                     {
412                         if (xval >= clip -> gx_rectangle_left &&
413                             xval <= clip -> gx_rectangle_right)
414                         {
415                             *put = *get;
416                         }
417                         put++;
418                         get++;
419                         xval++;
420                     }
421                 }
422                 else
423                 {
424                     while (count--)
425                     {
426                         if (xval >= clip -> gx_rectangle_left &&
427                             xval <= clip -> gx_rectangle_right)
428                         {
429                             _gx_display_driver_32argb_pixel_blend(context, xval, yval, *get, brush_alpha);
430                         }
431                         get++;
432                         xval++;
433                     }
434                 }
435             }
436         }
437         putrow += context -> gx_draw_context_pitch;
438         yval++;
439     }
440 }
441 
442 /**************************************************************************/
443 /*                                                                        */
444 /*  FUNCTION                                               RELEASE        */
445 /*                                                                        */
446 /*    _gx_display_driver_32argb_pixelmap_raw_write        PORTABLE C      */
447 /*                                                           6.1          */
448 /*  AUTHOR                                                                */
449 /*                                                                        */
450 /*    Kenneth Maxwell, Microsoft Corporation                              */
451 /*                                                                        */
452 /*  DESCRIPTION                                                           */
453 /*                                                                        */
454 /*    Internal helper function that handles writing of uncompressed       */
455 /*    pixlemap file without alpha channel.                                */
456 /*                                                                        */
457 /*  INPUT                                                                 */
458 /*                                                                        */
459 /*    context                               Drawing context               */
460 /*    xpos                                  x-coord of top-left draw point*/
461 /*    ypos                                  y-coord of top-left draw point*/
462 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
463 /*                                                                        */
464 /*  OUTPUT                                                                */
465 /*                                                                        */
466 /*    None                                                                */
467 /*                                                                        */
468 /*  CALLS                                                                 */
469 /*                                                                        */
470 /*    None                                                                */
471 /*                                                                        */
472 /*  CALLED BY                                                             */
473 /*                                                                        */
474 /*    _gx_display_driver_32argb_pixelmap_draw                             */
475 /*                                                                        */
476 /*  RELEASE HISTORY                                                       */
477 /*                                                                        */
478 /*    DATE              NAME                      DESCRIPTION             */
479 /*                                                                        */
480 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
481 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
482 /*                                            resulting in version 6.1    */
483 /*                                                                        */
484 /**************************************************************************/
_gx_display_driver_32argb_pixelmap_raw_write(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap)485 static VOID _gx_display_driver_32argb_pixelmap_raw_write(GX_DRAW_CONTEXT *context,
486                                                          INT xpos, INT ypos, GX_PIXELMAP *pixelmap)
487 {
488 INT           xval;
489 INT           yval;
490 INT           width;
491 GX_COLOR     *putrow;
492 GX_COLOR     *getrow;
493 GX_COLOR     *put;
494 GX_COLOR     *get;
495 
496 GX_RECTANGLE *clip = context -> gx_draw_context_clip;
497 
498     getrow = (GX_COLOR *)(pixelmap -> gx_pixelmap_data);
499     getrow += pixelmap -> gx_pixelmap_width * (clip -> gx_rectangle_top - ypos);
500     getrow += (clip -> gx_rectangle_left - xpos);
501 
502     /* brush alpha is 0xff means draw pixelmap to memory directly. */
503     putrow = context -> gx_draw_context_memory;
504     putrow += clip -> gx_rectangle_top * context -> gx_draw_context_pitch;
505     putrow += clip -> gx_rectangle_left;
506 
507     width = clip -> gx_rectangle_right - clip -> gx_rectangle_left + 1;
508 
509     for (yval = clip -> gx_rectangle_top; yval <= clip -> gx_rectangle_bottom; yval++)
510     {
511         put = putrow;
512         get = getrow;
513 
514         for (xval = 0; xval < width; xval++)
515         {
516             *put++ = *get++;
517         }
518         putrow += context -> gx_draw_context_pitch;
519         getrow += pixelmap -> gx_pixelmap_width;
520     }
521 }
522 
523 /**************************************************************************/
524 /*                                                                        */
525 /*  FUNCTION                                               RELEASE        */
526 /*                                                                        */
527 /*    _gx_display_driver_32xrgb_pixelmap_draw             PORTABLE C      */
528 /*                                                           6.1          */
529 /*  AUTHOR                                                                */
530 /*                                                                        */
531 /*    Kenneth Maxwell, Microsoft Corporation                              */
532 /*                                                                        */
533 /*  DESCRIPTION                                                           */
534 /*                                                                        */
535 /*    32xrgb format screen driver pixelmap drawing function that handles  */
536 /*    compressed or uncompress, with or without alpha channel.            */
537 /*                                                                        */
538 /*  INPUT                                                                 */
539 /*                                                                        */
540 /*    context                               Drawing context               */
541 /*    xpos                                  x-coord of top-left draw point*/
542 /*    ypos                                  y-coord of top-left draw point*/
543 /*    pixelmap                              Pointer to GX_PIXELMAP struct */
544 /*                                                                        */
545 /*  OUTPUT                                                                */
546 /*                                                                        */
547 /*    None                                                                */
548 /*                                                                        */
549 /*  CALLS                                                                 */
550 /*                                                                        */
551 /*     _gx_display_driver_32argb_pixelmap_compressed_alpha_write          */
552 /*                                          Real Pixelmap draw function   */
553 /*     _gx_display_driver_32argb_pixelmap_alpha_write                     */
554 /*                                          Real Pixelmap draw function   */
555 /*     _gx_display_driver_32argb_pixelmap_compressed_write                */
556 /*                                          Real Pixelmap draw function   */
557 /*     _gx_display_driver_32argb_pixelmap_raw_write                       */
558 /*                                          Real Pixelmap draw function   */
559 /*     _gx_display_driver_32argb_pixelmap_blend                           */
560 /*                                          Basic display driver function */
561 /*  CALLED BY                                                             */
562 /*                                                                        */
563 /*    GUIX Internal Code                                                  */
564 /*                                                                        */
565 /*  RELEASE HISTORY                                                       */
566 /*                                                                        */
567 /*    DATE              NAME                      DESCRIPTION             */
568 /*                                                                        */
569 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
570 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
571 /*                                            resulting in version 6.1    */
572 /*                                                                        */
573 /**************************************************************************/
_gx_display_driver_32argb_pixelmap_draw(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap)574 VOID _gx_display_driver_32argb_pixelmap_draw(GX_DRAW_CONTEXT *context,
575                                              INT xpos, INT ypos, GX_PIXELMAP *pixelmap)
576 {
577 GX_BOOL  drawn = GX_FALSE;
578 GX_UBYTE brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
579 
580     if (brush_alpha == 0)
581     {
582         /* Draw nothing here. Just return. */
583         return;
584     }
585 
586     if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_TRANSPARENT)
587     {
588         /* Not supported yet. */
589         return;
590     }
591 
592     if (pixelmap -> gx_pixelmap_format != GX_COLOR_FORMAT_32ARGB)
593     {
594         /* wrong color format for this driver */
595         return;
596     }
597 
598     if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
599     {
600         if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
601         {
602             /* has both compression and alpha */
603             _gx_display_driver_32argb_pixelmap_compressed_alpha_write(context, xpos, ypos, pixelmap);
604             drawn = GX_TRUE;
605         }
606         else
607         {
608             if (brush_alpha == 0xff)
609             {
610                 /* alpha, no compression */
611                 _gx_display_driver_32argb_pixelmap_alpha_write(context, xpos, ypos, pixelmap);
612                 drawn = GX_TRUE;
613             }
614         }
615     }
616     else
617     {
618         if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
619         {
620             /* compressed with no alpha */
621             _gx_display_driver_32argb_pixelmap_compressed_write(context, xpos, ypos, pixelmap);
622             drawn = GX_TRUE;
623         }
624         else
625         {
626             /* no compression or alpha */
627             if (brush_alpha == 0xff)
628             {
629                 _gx_display_driver_32argb_pixelmap_raw_write(context, xpos, ypos, pixelmap);
630                 drawn = GX_TRUE;
631             }
632         }
633     }
634 
635     if (!drawn)
636     {
637         _gx_display_driver_32argb_pixelmap_blend(context, xpos, ypos, pixelmap, brush_alpha);
638     }
639 }
640 
641