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 /**   Application Interface (API)                                         */
18 /**                                                                       */
19 /**************************************************************************/
20 #include "gx_api.h"
21 #include "gx_system.h"
22 #include "gx_display.h"
23 #include "gx_validation_utility.h"
24 #include "gx_dave2d_simulation_display_driver.h"
25 
26 extern int gx_validation_record_frame;
27 extern TEST_PARAM test_parameter;
28 
29 static int   width, height;
30 static int   header_created = 0;
31 static char *color_format = COLOR_FORMAT_565RGB;
32 static USHORT *rotated_memory = GX_NULL;
33 
_gx_validation_rotate_canvas(GX_CANVAS * canvas)34 static void _gx_validation_rotate_canvas(GX_CANVAS *canvas)
35 {
36 /* first pass, just copy the entire canvas, ignoring the dirty
37    rectangle. Come back and apply dirty rectangle to improve
38    efficiency.
39  */
40 
41 USHORT *pReadStart;
42 USHORT *pWriteStart;
43 USHORT *pRead;
44 USHORT *pWrite;
45 INT     copy_width;
46 INT     copy_height;
47 INT     row;
48 INT     column;
49 INT     write_sign;
50 
51     /* copy left-to-right from source canvas
52        and top-to-bottom in destination bitmap (90 degree rotation)
53      */
54 
55     pReadStart = (USHORT *)canvas -> gx_canvas_memory;
56     pWriteStart = (USHORT *)rotated_memory;
57     copy_width = canvas -> gx_canvas_y_resolution;
58     copy_height = canvas -> gx_canvas_x_resolution;
59 
60     if (canvas -> gx_canvas_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
61     {
62         pWriteStart += copy_height - 1;
63         write_sign = -1;
64     }
65     else
66     {
67         pWriteStart += (copy_width - 1) * copy_height;
68         write_sign = 1;
69     }
70 
71     for (row = 0; row < copy_height; row++)
72     {
73         pRead = pReadStart;
74         pWrite = pWriteStart;
75 
76         for (column = 0; column < copy_width; column++)
77         {
78             *pWrite = *pRead++;
79             pWrite -= copy_height * write_sign;
80         }
81         pReadStart += copy_width;
82         pWriteStart += write_sign;
83     }
84 }
85 
86 /**********************************************************************************/
87 /*Define 16bpp screen toggle function                                             */
88 /**********************************************************************************/
_gx_validation_display_buffer_16bpp_toggle(GX_CANVAS * canvas,GX_RECTANGLE * dirty)89 VOID _gx_validation_display_buffer_16bpp_toggle(GX_CANVAS *canvas, GX_RECTANGLE *dirty)
90 {
91 
92     USHORT *memptr;
93     USHORT *frame_buffer;
94     GX_RECTANGLE overlap;
95     GX_RECTANGLE display_size;
96     int copy_width;
97     int y;
98 
99     if(header_created == 0)
100     {
101         if(test_parameter.x_start < 0)
102             test_parameter.x_start = 0;
103 
104 
105         if(test_parameter.y_start < 0)
106             test_parameter.y_start = 0;
107 
108         if((test_parameter.x_end < 0) || (test_parameter.x_end >= canvas -> gx_canvas_x_resolution))
109             test_parameter.x_end = canvas -> gx_canvas_x_resolution - 1;
110 
111         if((test_parameter.y_end < 0) || (test_parameter.y_end >= canvas -> gx_canvas_y_resolution))
112             test_parameter.y_end = canvas -> gx_canvas_y_resolution - 1;
113 
114         width = test_parameter.x_end - test_parameter.x_start + 1;
115         height = test_parameter.y_end - test_parameter.y_start + 1;
116 
117         width = width + (width & 1);
118 
119         gx_validation_create_output_file(color_format, width, height);
120         gx_validation_create_frame_buffer(width * height * sizeof(USHORT));
121 
122         if((canvas->gx_canvas_display->gx_display_rotation_angle != GX_SCREEN_ROTATION_NONE) &&
123            (canvas->gx_canvas_display->gx_display_rotation_angle != GX_SCREEN_ROTATION_FLIP))
124         {
125             /* Create padded memory. */
126             rotated_memory = (USHORT *)malloc(canvas->gx_canvas_x_resolution * canvas->gx_canvas_y_resolution * sizeof(USHORT));
127         }
128 
129         header_created = 1;
130     }
131 
132     if(!gx_validation_frame_buffer)
133     {
134         return;
135     }
136 
137     display_size.gx_rectangle_left = test_parameter.x_start;
138     display_size.gx_rectangle_right = test_parameter.x_end;
139     display_size.gx_rectangle_top = test_parameter.y_start;
140     display_size.gx_rectangle_bottom = test_parameter.y_end;
141 
142     /* Copy dirty area to validation frame buffer. */
143     if(gx_utility_rectangle_overlap_detect(dirty, &display_size, &overlap))
144     {
145         int xsrc = overlap.gx_rectangle_left;
146         int ysrc = overlap.gx_rectangle_top;
147         gx_utility_rectangle_shift(&overlap, canvas -> gx_canvas_display_offset_x, canvas -> gx_canvas_display_offset_y);
148 
149         if(gx_utility_rectangle_overlap_detect(&display_size, &overlap, &overlap))
150         {
151             if(rotated_memory)
152             {
153                 /* Rotate canvas memory to padded memory. */
154                 _gx_validation_rotate_canvas(canvas);
155                 memptr = (USHORT *)rotated_memory;
156             }
157             else
158             {
159                 memptr = (USHORT *)(canvas -> gx_canvas_memory);
160             }
161 
162 #if defined(GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER)
163             memptr += (ysrc - canvas->gx_canvas_memory_offset_y) * canvas -> gx_canvas_memory_width;
164             memptr += (xsrc - canvas->gx_canvas_memory_offset_x);
165 #else
166             memptr += ysrc * canvas -> gx_canvas_x_resolution;
167             memptr += xsrc;
168 #endif
169 
170             frame_buffer = (USHORT *)(gx_validation_frame_buffer);
171             frame_buffer += (overlap.gx_rectangle_top - test_parameter.y_start) * width;
172             frame_buffer += (overlap.gx_rectangle_left - test_parameter.x_start);
173 
174             copy_width = overlap.gx_rectangle_right - overlap.gx_rectangle_left + 1;
175 
176             for(y = overlap.gx_rectangle_top; y <= overlap.gx_rectangle_bottom; y++)
177             {
178                 memcpy((char *)frame_buffer, (char *)memptr, copy_width * sizeof(USHORT));
179                 frame_buffer += width;
180 #if defined(GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER)
181                 memptr += canvas -> gx_canvas_memory_width;
182 #else
183                 memptr += canvas -> gx_canvas_x_resolution;
184 #endif
185             }
186         }
187     }
188 
189     if(gx_validation_record_frame == 0)
190     {
191         return;
192     }
193 
194     gx_validation_record_frame = 0;
195 
196     /* Dump frame area */
197     gx_validation_write_frame_buffer();
198 }
199 
200 /**********************************************************************************/
201 /*Define 565rgb display driver setup function                                     */
202 /**********************************************************************************/
gx_validation_graphics_driver_setup_565rgb(GX_DISPLAY * display)203 UINT gx_validation_graphics_driver_setup_565rgb(GX_DISPLAY *display)
204 {
205 
206     /* Initialize the low-level drawing function pointers
207 
208        for windows, these are always just the generic functions,
209        but for some hardware, these will be customized,
210        optimized functions specific to that hardware
211      */
212     _gx_display_driver_565rgb_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
213 
214 
215     return(GX_SUCCESS);
216 }
217 
gx_validation_graphics_driver_cleanup_565rgb(GX_DISPLAY * display)218 VOID gx_validation_graphics_driver_cleanup_565rgb(GX_DISPLAY *display)
219 {
220 
221     /* Do nothing */
222     if(rotated_memory)
223     {
224         free(rotated_memory);
225     }
226 }
227 
228 /**********************************************************************************/
229 /*Define 565rgb display driver setup function                                     */
230 /**********************************************************************************/
gx_validation_graphics_driver_setup_565rgb_rotated(GX_DISPLAY * display)231 UINT gx_validation_graphics_driver_setup_565rgb_rotated(GX_DISPLAY *display)
232 {
233 
234     /* Initialize the low-level drawing function pointers
235 
236        for windows, these are always just the generic functions,
237        but for some hardware, these will be customized,
238        optimized functions specific to that hardware
239      */
240     _gx_display_driver_565rgb_rotated_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
241 
242 
243     return(GX_SUCCESS);
244 }
245 
246 /**********************************************************************************/
247 /*Define 565bgr display driver setup function                                     */
248 /**********************************************************************************/
gx_validation_graphics_driver_setup_565bgr(GX_DISPLAY * display)249 UINT gx_validation_graphics_driver_setup_565bgr(GX_DISPLAY *display)
250 {
251 
252     /* Initialize the low-level drawing function pointers
253 
254        for windows, these are always just the generic functions,
255        but for some hardware, these will be customized,
256        optimized functions specific to that hardware
257      */
258     color_format = COLOR_FORMAT_565BGR;
259     _gx_display_driver_565rgb_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
260 
261 
262     return(GX_SUCCESS);
263 }
264 
265 
266 /**********************************************************************************/
267 /*Define 4444argb display driver setup function                                   */
268 /**********************************************************************************/
gx_validation_graphics_driver_setup_4444argb(GX_DISPLAY * display)269 UINT gx_validation_graphics_driver_setup_4444argb(GX_DISPLAY *display)
270 {
271 
272     /* Initialize the low-level drawing function pointers
273 
274        for windows, these are always just the generic functions,
275        but for some hardware, these will be customized,
276        optimized functions specific to that hardware
277      */
278     color_format = COLOR_FORMAT_4444ARGB;
279     _gx_display_driver_4444argb_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
280 
281 
282     return(GX_SUCCESS);
283 }
284 
285 /**********************************************************************************/
286 /*Define 1555xrgb display driver setup function                                   */
287 /**********************************************************************************/
gx_validation_graphics_driver_setup_1555xrgb(GX_DISPLAY * display)288 UINT gx_validation_graphics_driver_setup_1555xrgb(GX_DISPLAY *display)
289 {
290 
291     /* Initialize the low-level drawing function pointers
292 
293        for windows, these are always just the generic functions,
294        but for some hardware, these will be customized,
295        optimized functions specific to that hardware
296      */
297     color_format = COLOR_FORMAT_1555XRGB;
298     _gx_display_driver_1555xrgb_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
299 
300 
301     return(GX_SUCCESS);
302 }
303 
304 /**********************************************************************************/
305 /*Define 565rgb dave2d simulation display driver setup function                  */
306 /**********************************************************************************/
gx_validation_dave2d_graphics_driver_setup_565rgb(GX_DISPLAY * display)307 UINT gx_validation_dave2d_graphics_driver_setup_565rgb(GX_DISPLAY *display)
308 {
309 
310     /* Initialize the low-level drawing function pointers
311 
312        for windows, these are always just the generic functions,
313        but for some hardware, these will be customized,
314        optimized functions specific to that hardware
315      */
316     _gx_dave2d_simulation_display_driver_565rgb_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
317 
318 
319     return(GX_SUCCESS);
320 }
321 
322 /**********************************************************************************/
323 /*Define 565rgb dave2d simulation display driver rotated setup function          */
324 /**********************************************************************************/
gx_validation_dave2d_graphics_driver_setup_565rgb_rotated(GX_DISPLAY * display)325 UINT gx_validation_dave2d_graphics_driver_setup_565rgb_rotated(GX_DISPLAY *display)
326 {
327 
328     /* Initialize the low-level drawing function pointers
329 
330        for windows, these are always just the generic functions,
331        but for some hardware, these will be customized,
332        optimized functions specific to that hardware
333      */
334     _gx_dave2d_simulation_display_driver_565rgb_rotated_setup(display, (VOID*)1, _gx_validation_display_buffer_16bpp_toggle);
335 
336 
337     return(GX_SUCCESS);
338 }
339