xref: /linux/drivers/gpu/drm/drm_draw.c (revision c0d6f52f9b62479d61f8cd4faf9fb2f8bce6e301)
1 // SPDX-License-Identifier: GPL-2.0 or MIT
2 /*
3  * Copyright (c) 2023 Red Hat.
4  * Author: Jocelyn Falempe <jfalempe@redhat.com>
5  */
6 
7 #include <linux/bits.h>
8 #include <linux/bug.h>
9 #include <linux/export.h>
10 #include <linux/iosys-map.h>
11 #include <linux/types.h>
12 
13 #include <drm/drm_fourcc.h>
14 
15 #include "drm_draw_internal.h"
16 #include "drm_format_internal.h"
17 
18 /**
19  * drm_draw_can_convert_from_xrgb8888 - check if xrgb8888 can be converted to the desired format
20  * @format: format
21  *
22  * Returns:
23  * True if XRGB8888 can be converted to the specified format, false otherwise.
24  */
25 bool drm_draw_can_convert_from_xrgb8888(u32 format)
26 {
27 	switch (format) {
28 	case DRM_FORMAT_RGB565:
29 	case DRM_FORMAT_RGBA5551:
30 	case DRM_FORMAT_XRGB1555:
31 	case DRM_FORMAT_ARGB1555:
32 	case DRM_FORMAT_RGB888:
33 	case DRM_FORMAT_XRGB8888:
34 	case DRM_FORMAT_ARGB8888:
35 	case DRM_FORMAT_XBGR8888:
36 	case DRM_FORMAT_ABGR8888:
37 	case DRM_FORMAT_XRGB2101010:
38 	case DRM_FORMAT_ARGB2101010:
39 	case DRM_FORMAT_ABGR2101010:
40 		return true;
41 	default:
42 		return false;
43 	}
44 }
45 EXPORT_SYMBOL(drm_draw_can_convert_from_xrgb8888);
46 
47 /**
48  * drm_draw_color_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format
49  * @color: input color, in xrgb8888 format
50  * @format: output format
51  *
52  * Returns:
53  * Color in the format specified, casted to u32.
54  * Or 0 if the format is not supported.
55  */
56 u32 drm_draw_color_from_xrgb8888(u32 color, u32 format)
57 {
58 	switch (format) {
59 	case DRM_FORMAT_RGB565:
60 		return drm_pixel_xrgb8888_to_rgb565(color);
61 	case DRM_FORMAT_RGBA5551:
62 		return drm_pixel_xrgb8888_to_rgba5551(color);
63 	case DRM_FORMAT_XRGB1555:
64 		return drm_pixel_xrgb8888_to_xrgb1555(color);
65 	case DRM_FORMAT_ARGB1555:
66 		return drm_pixel_xrgb8888_to_argb1555(color);
67 	case DRM_FORMAT_RGB888:
68 	case DRM_FORMAT_XRGB8888:
69 		return color;
70 	case DRM_FORMAT_ARGB8888:
71 		return drm_pixel_xrgb8888_to_argb8888(color);
72 	case DRM_FORMAT_XBGR8888:
73 		return drm_pixel_xrgb8888_to_xbgr8888(color);
74 	case DRM_FORMAT_ABGR8888:
75 		return drm_pixel_xrgb8888_to_abgr8888(color);
76 	case DRM_FORMAT_XRGB2101010:
77 		return drm_pixel_xrgb8888_to_xrgb2101010(color);
78 	case DRM_FORMAT_ARGB2101010:
79 		return drm_pixel_xrgb8888_to_argb2101010(color);
80 	case DRM_FORMAT_ABGR2101010:
81 		return drm_pixel_xrgb8888_to_abgr2101010(color);
82 	default:
83 		WARN_ONCE(1, "Can't convert to %p4cc\n", &format);
84 		return 0;
85 	}
86 }
87 EXPORT_SYMBOL(drm_draw_color_from_xrgb8888);
88 
89 /*
90  * Blit functions
91  */
92 void drm_draw_blit16(struct iosys_map *dmap, unsigned int dpitch,
93 		     const u8 *sbuf8, unsigned int spitch,
94 		     unsigned int height, unsigned int width,
95 		     unsigned int scale, u16 fg16)
96 {
97 	unsigned int y, x;
98 
99 	for (y = 0; y < height; y++)
100 		for (x = 0; x < width; x++)
101 			if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale))
102 				iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, fg16);
103 }
104 EXPORT_SYMBOL(drm_draw_blit16);
105 
106 void drm_draw_blit24(struct iosys_map *dmap, unsigned int dpitch,
107 		     const u8 *sbuf8, unsigned int spitch,
108 		     unsigned int height, unsigned int width,
109 		     unsigned int scale, u32 fg32)
110 {
111 	unsigned int y, x;
112 
113 	for (y = 0; y < height; y++) {
114 		for (x = 0; x < width; x++) {
115 			u32 off = y * dpitch + x * 3;
116 
117 			if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale)) {
118 				/* write blue-green-red to output in little endianness */
119 				iosys_map_wr(dmap, off, u8, (fg32 & 0x000000FF) >> 0);
120 				iosys_map_wr(dmap, off + 1, u8, (fg32 & 0x0000FF00) >> 8);
121 				iosys_map_wr(dmap, off + 2, u8, (fg32 & 0x00FF0000) >> 16);
122 			}
123 		}
124 	}
125 }
126 EXPORT_SYMBOL(drm_draw_blit24);
127 
128 void drm_draw_blit32(struct iosys_map *dmap, unsigned int dpitch,
129 		     const u8 *sbuf8, unsigned int spitch,
130 		     unsigned int height, unsigned int width,
131 		     unsigned int scale, u32 fg32)
132 {
133 	unsigned int y, x;
134 
135 	for (y = 0; y < height; y++)
136 		for (x = 0; x < width; x++)
137 			if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale))
138 				iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, fg32);
139 }
140 EXPORT_SYMBOL(drm_draw_blit32);
141 
142 /*
143  * Fill functions
144  */
145 void drm_draw_fill16(struct iosys_map *dmap, unsigned int dpitch,
146 		     unsigned int height, unsigned int width,
147 		     u16 color)
148 {
149 	unsigned int y, x;
150 
151 	for (y = 0; y < height; y++)
152 		for (x = 0; x < width; x++)
153 			iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, color);
154 }
155 EXPORT_SYMBOL(drm_draw_fill16);
156 
157 void drm_draw_fill24(struct iosys_map *dmap, unsigned int dpitch,
158 		     unsigned int height, unsigned int width,
159 		     u32 color)
160 {
161 	unsigned int y, x;
162 
163 	for (y = 0; y < height; y++) {
164 		for (x = 0; x < width; x++) {
165 			unsigned int off = y * dpitch + x * 3;
166 
167 			/* write blue-green-red to output in little endianness */
168 			iosys_map_wr(dmap, off, u8, (color & 0x000000FF) >> 0);
169 			iosys_map_wr(dmap, off + 1, u8, (color & 0x0000FF00) >> 8);
170 			iosys_map_wr(dmap, off + 2, u8, (color & 0x00FF0000) >> 16);
171 		}
172 	}
173 }
174 EXPORT_SYMBOL(drm_draw_fill24);
175 
176 void drm_draw_fill32(struct iosys_map *dmap, unsigned int dpitch,
177 		     unsigned int height, unsigned int width,
178 		     u32 color)
179 {
180 	unsigned int y, x;
181 
182 	for (y = 0; y < height; y++)
183 		for (x = 0; x < width; x++)
184 			iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color);
185 }
186 EXPORT_SYMBOL(drm_draw_fill32);
187