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