2 * This file is part of the libpayload project.
4 * Copyright (C) 2015 Google, Inc.
7 #include <libpayload.h>
11 * 'canvas' is the drawing area located in the center of the screen. It's a
12 * square area, stretching vertically to the edges of the screen, leaving
13 * non-drawing areas on the left and right. The screen is assumed to be
16 static struct vector canvas
;
17 static uint32_t canvas_offset
; /* horizontal position of canvas */
20 * Framebuffer is assumed to assign a higher coordinate (larger x, y) to
23 static struct cb_framebuffer
*fbinfo
;
24 static uint8_t *fbaddr
;
26 static char initialized
= 0;
27 #define LOG(x...) printf("CBGFX: " x)
29 static void add_vectors(struct vector
*out
,
30 const struct vector
*v1
, const struct vector
*v2
)
32 out
->x
= v1
->x
+ v2
->x
;
33 out
->y
= v1
->y
+ v2
->y
;
36 static void to_canvas(const struct vector
*relative
, struct vector
*absolute
)
38 absolute
->x
= canvas
.width
* relative
->x
/ CANVAS_SCALE
;
39 absolute
->y
= canvas
.height
* relative
->y
/ CANVAS_SCALE
;
42 static int within_canvas(const struct vector
*v
)
44 return v
->x
< canvas
.width
&& v
->y
< canvas
.height
;
47 static inline uint32_t calculate_color(const struct rgb_color
*rgb
)
50 color
|= (rgb
->red
>> (8 - fbinfo
->red_mask_size
))
51 << fbinfo
->red_mask_pos
;
52 color
|= (rgb
->green
>> (8 - fbinfo
->green_mask_size
))
53 << fbinfo
->green_mask_pos
;
54 color
|= (rgb
->blue
>> (8 - fbinfo
->blue_mask_size
))
55 << fbinfo
->blue_mask_pos
;
60 * Plot a pixel in a framebuffer. This is called from tight loops. Keep it slim
61 * and do the validation at callers' site.
63 static inline void set_pixel(struct vector
*coord
, uint32_t color
)
65 const int bpp
= fbinfo
->bits_per_pixel
;
67 uint8_t * const pixel
= fbaddr
+ (coord
->x
+ canvas_offset
+
68 coord
->y
* fbinfo
->x_resolution
) * bpp
/ 8;
69 for (i
= 0; i
< bpp
/ 8; i
++)
70 pixel
[i
] = (color
>> (i
* 8));
74 * Initializes the library. Automatically called by APIs. It sets up
75 * the canvas and the framebuffer.
77 static int cbgfx_init(void)
82 fbinfo
= lib_sysinfo
.framebuffer
;
86 fbaddr
= phys_to_virt((uint8_t *)(uintptr_t)(fbinfo
->physical_address
));
90 /* calculate canvas size, assuming the screen is landscape */
91 canvas
.height
= fbinfo
->y_resolution
;
92 canvas
.width
= canvas
.height
;
93 canvas_offset
= (fbinfo
->x_resolution
- canvas
.width
) / 2;
94 if (canvas_offset
< 0) {
95 LOG("Portrait screens are not supported\n");
100 LOG("cbgfx initialized: canvas width=%d, height=%d, offset=%d\n",
101 canvas
.width
, canvas
.height
, canvas_offset
);
106 int draw_box(const struct vector
*top_left_rel
,
107 const struct vector
*size_rel
,
108 const struct rgb_color
*rgb
)
110 struct vector top_left
;
113 const uint32_t color
= calculate_color(rgb
);
116 return CBGFX_ERROR_INIT
;
118 to_canvas(top_left_rel
, &top_left
);
119 to_canvas(size_rel
, &size
);
120 add_vectors(&t
, &top_left
, &size
);
121 if (!within_canvas(&t
)) {
122 LOG("Box exceeds canvas boundary\n");
123 return CBGFX_ERROR_BOUNDARY
;
126 for (p
.y
= top_left
.y
; p
.y
< t
.y
; p
.y
++)
127 for (p
.x
= top_left
.x
; p
.x
< t
.x
; p
.x
++)
128 set_pixel(&p
, color
);
130 return CBGFX_SUCCESS
;
133 int clear_canvas(struct rgb_color
*rgb
)
135 const struct vector coord
= {
139 const struct vector size
= {
140 .width
= CANVAS_SCALE
,
141 .height
= CANVAS_SCALE
,
145 return CBGFX_ERROR_INIT
;
147 return draw_box(&coord
, &size
, rgb
);