1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 extern "C" {
18 #include "drm_fourcc.h"
19 #include "virgl_hw.h"
20 } // extern "C"
21
22 namespace gfxstream {
23 namespace host {
24
25 #define VIRGL_FORMAT_NV12 166
26 #define VIRGL_FORMAT_YV12 163
27 #define VIRGL_FORMAT_P010 314
28
29 const uint32_t kGlBgra = 0x80e1;
30 const uint32_t kGlRgba = 0x1908;
31 const uint32_t kGlRgba16f = 0x881A;
32 const uint32_t kGlRgb565 = 0x8d62;
33 const uint32_t kGlRgba1010102 = 0x8059;
34 const uint32_t kGlR8 = 0x8229;
35 const uint32_t kGlR16 = 0x822A;
36 const uint32_t kGlRg8 = 0x822b;
37 const uint32_t kGlRgb8 = 0x8051;
38 const uint32_t kGlLuminance = 0x1909;
39 const uint32_t kGlLuminanceAlpha = 0x190a;
40 const uint32_t kGlUnsignedByte = 0x1401;
41 const uint32_t kGlUnsignedShort = 0x1403;
42 const uint32_t kGlUnsignedShort565 = 0x8363;
43 const uint32_t kGlDepth16 = 0x81A5;
44 const uint32_t kGlDepth24 = 0x81A6;
45 const uint32_t kGlDepth24Stencil8 = 0x88F0;
46 const uint32_t kGlDepth32f = 0x8CAC;
47 const uint32_t kGlDepth32fStencil8 = 0x8CAD;
48
49 constexpr uint32_t kFwkFormatGlCompat = 0;
50 constexpr uint32_t kFwkFormatYV12 = 1;
51 // constexpr uint32_t kFwkFormatYUV420888 = 2;
52 constexpr uint32_t kFwkFormatNV12 = 3;
53 constexpr uint32_t kFwkFormatP010 = 4;
54
virgl_format_is_yuv(uint32_t format)55 static inline bool virgl_format_is_yuv(uint32_t format) {
56 switch (format) {
57 case VIRGL_FORMAT_B8G8R8X8_UNORM:
58 case VIRGL_FORMAT_B5G6R5_UNORM:
59 case VIRGL_FORMAT_B8G8R8A8_UNORM:
60 case VIRGL_FORMAT_R10G10B10A2_UNORM:
61 case VIRGL_FORMAT_R16_UNORM:
62 case VIRGL_FORMAT_R16G16B16A16_FLOAT:
63 case VIRGL_FORMAT_R8_UNORM:
64 case VIRGL_FORMAT_R8G8_UNORM:
65 case VIRGL_FORMAT_R8G8B8_UNORM:
66 case VIRGL_FORMAT_R8G8B8A8_UNORM:
67 case VIRGL_FORMAT_R8G8B8X8_UNORM:
68 case VIRGL_FORMAT_Z16_UNORM:
69 case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
70 case VIRGL_FORMAT_Z24X8_UNORM:
71 case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
72 case VIRGL_FORMAT_Z32_FLOAT:
73 return false;
74 case VIRGL_FORMAT_NV12:
75 case VIRGL_FORMAT_P010:
76 case VIRGL_FORMAT_YV12:
77 return true;
78 default:
79 stream_renderer_error("Unknown virgl format 0x%x", format);
80 return false;
81 }
82 }
83
virgl_format_to_gl(uint32_t virgl_format)84 static inline uint32_t virgl_format_to_gl(uint32_t virgl_format) {
85 switch (virgl_format) {
86 case VIRGL_FORMAT_B8G8R8X8_UNORM:
87 case VIRGL_FORMAT_B8G8R8A8_UNORM:
88 return kGlBgra;
89 case VIRGL_FORMAT_R8G8B8X8_UNORM:
90 case VIRGL_FORMAT_R8G8B8A8_UNORM:
91 return kGlRgba;
92 case VIRGL_FORMAT_B5G6R5_UNORM:
93 return kGlRgb565;
94 case VIRGL_FORMAT_R16_UNORM:
95 return kGlR16;
96 case VIRGL_FORMAT_R16G16B16A16_FLOAT:
97 return kGlRgba16f;
98 case VIRGL_FORMAT_R8_UNORM:
99 return kGlR8;
100 case VIRGL_FORMAT_R8G8_UNORM:
101 return kGlRg8;
102 case VIRGL_FORMAT_R8G8B8_UNORM:
103 return kGlRgb8;
104 case VIRGL_FORMAT_NV12:
105 case VIRGL_FORMAT_P010:
106 case VIRGL_FORMAT_YV12:
107 // emulated as RGBA8888
108 return kGlRgba;
109 case VIRGL_FORMAT_R10G10B10A2_UNORM:
110 return kGlRgba1010102;
111 case VIRGL_FORMAT_Z16_UNORM:
112 return kGlDepth16;
113 case VIRGL_FORMAT_Z24X8_UNORM:
114 return kGlDepth24;
115 case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
116 return kGlDepth24Stencil8;
117 case VIRGL_FORMAT_Z32_FLOAT:
118 return kGlDepth32f;
119 case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
120 return kGlDepth32fStencil8;
121 default:
122 return kGlRgba;
123 }
124 }
125
virgl_format_to_fwk_format(uint32_t virgl_format)126 static inline uint32_t virgl_format_to_fwk_format(uint32_t virgl_format) {
127 switch (virgl_format) {
128 case VIRGL_FORMAT_NV12:
129 return kFwkFormatNV12;
130 case VIRGL_FORMAT_P010:
131 return kFwkFormatP010;
132 case VIRGL_FORMAT_YV12:
133 return kFwkFormatYV12;
134 case VIRGL_FORMAT_R8_UNORM:
135 case VIRGL_FORMAT_R16_UNORM:
136 case VIRGL_FORMAT_R16G16B16A16_FLOAT:
137 case VIRGL_FORMAT_R8G8_UNORM:
138 case VIRGL_FORMAT_R8G8B8_UNORM:
139 case VIRGL_FORMAT_B8G8R8X8_UNORM:
140 case VIRGL_FORMAT_B8G8R8A8_UNORM:
141 case VIRGL_FORMAT_R8G8B8X8_UNORM:
142 case VIRGL_FORMAT_R8G8B8A8_UNORM:
143 case VIRGL_FORMAT_B5G6R5_UNORM:
144 case VIRGL_FORMAT_R10G10B10A2_UNORM:
145 case VIRGL_FORMAT_Z16_UNORM:
146 case VIRGL_FORMAT_Z24X8_UNORM:
147 case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
148 case VIRGL_FORMAT_Z32_FLOAT:
149 case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
150 default: // kFwkFormatGlCompat: No extra conversions needed
151 return kFwkFormatGlCompat;
152 }
153 }
154
gl_format_to_natural_type(uint32_t format)155 static inline uint32_t gl_format_to_natural_type(uint32_t format) {
156 switch (format) {
157 case kGlBgra:
158 case kGlRgba:
159 case kGlLuminance:
160 case kGlLuminanceAlpha:
161 return kGlUnsignedByte;
162 case kGlRgb565:
163 return kGlUnsignedShort565;
164 case kGlDepth16:
165 return kGlUnsignedShort;
166 default:
167 return kGlUnsignedByte;
168 }
169 }
170
171 #ifndef DRM_FORMAT_DEPTH16
172 #define DRM_FORMAT_DEPTH16 fourcc_code('D', '1', '6', ' ')
173 #define DRM_FORMAT_DEPTH24 fourcc_code('D', '2', '4', 'X')
174 #define DRM_FORMAT_DEPTH24_STENCIL8 fourcc_code('D', '2', '4', 'S')
175 #define DRM_FORMAT_DEPTH32 fourcc_code('D', '3', '2', 'F')
176 #define DRM_FORMAT_DEPTH32_STENCIL8 fourcc_code('D', 'F', 'S', '8')
177 #endif
178
drm_format_to_virgl_format(uint32_t format)179 static inline uint32_t drm_format_to_virgl_format(uint32_t format) {
180 switch (format) {
181 case DRM_FORMAT_DEPTH16:
182 return VIRGL_FORMAT_Z16_UNORM;
183 case DRM_FORMAT_DEPTH24:
184 return VIRGL_FORMAT_Z24X8_UNORM;
185 case DRM_FORMAT_DEPTH24_STENCIL8:
186 return VIRGL_FORMAT_Z24_UNORM_S8_UINT;
187 case DRM_FORMAT_DEPTH32:
188 return VIRGL_FORMAT_Z32_FLOAT;
189 case DRM_FORMAT_DEPTH32_STENCIL8:
190 return VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT;
191 default:
192 stream_renderer_error("Unknown drm format for virgl conversion 0x%x", format);
193 return 0;
194 }
195 }
196
set_virgl_format_supported(uint32_t * mask,uint32_t virgl_format,bool supported)197 static inline void set_virgl_format_supported(uint32_t* mask, uint32_t virgl_format,
198 bool supported) {
199 uint32_t index = virgl_format / 32;
200 uint32_t bit_offset = 1 << (virgl_format & 31);
201 if (supported) {
202 mask[index] |= bit_offset;
203 } else {
204 mask[index] &= ~bit_offset;
205 }
206 }
207
set_drm_format_supported(uint32_t * mask,uint32_t drm_format,bool supported)208 static inline void set_drm_format_supported(uint32_t* mask, uint32_t drm_format, bool supported) {
209 uint32_t virgl_format = drm_format_to_virgl_format(drm_format);
210 set_virgl_format_supported(mask, virgl_format, supported);
211 }
212
is_drm_format_supported(uint32_t * mask,uint32_t drm_format)213 static inline bool is_drm_format_supported(uint32_t* mask, uint32_t drm_format) {
214 uint32_t virgl_format = drm_format_to_virgl_format(drm_format);
215 uint32_t index = virgl_format / 32;
216 uint32_t bit_offset = 1 << (virgl_format & 31);
217 return (mask[index] & bit_offset) ? true : false;
218 }
219
virgl_format_to_linear_base(uint32_t format,uint32_t totalWidth,uint32_t totalHeight,uint32_t x,uint32_t y,uint32_t w,uint32_t h)220 static inline size_t virgl_format_to_linear_base(uint32_t format, uint32_t totalWidth,
221 uint32_t totalHeight, uint32_t x, uint32_t y,
222 uint32_t w, uint32_t h) {
223 if (virgl_format_is_yuv(format)) {
224 return 0;
225 } else {
226 uint32_t bpp = 4;
227 switch (format) {
228 case VIRGL_FORMAT_R16G16B16A16_FLOAT:
229 case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
230 bpp = 8;
231 break;
232 case VIRGL_FORMAT_B8G8R8X8_UNORM:
233 case VIRGL_FORMAT_B8G8R8A8_UNORM:
234 case VIRGL_FORMAT_R8G8B8X8_UNORM:
235 case VIRGL_FORMAT_R8G8B8A8_UNORM:
236 case VIRGL_FORMAT_R10G10B10A2_UNORM:
237 case VIRGL_FORMAT_Z24X8_UNORM:
238 case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
239 case VIRGL_FORMAT_Z32_FLOAT:
240 bpp = 4;
241 break;
242 case VIRGL_FORMAT_R8G8B8_UNORM:
243 bpp = 3;
244 break;
245 case VIRGL_FORMAT_B5G6R5_UNORM:
246 case VIRGL_FORMAT_R8G8_UNORM:
247 case VIRGL_FORMAT_R16_UNORM:
248 case VIRGL_FORMAT_Z16_UNORM:
249 bpp = 2;
250 break;
251 case VIRGL_FORMAT_R8_UNORM:
252 bpp = 1;
253 break;
254 default:
255 stream_renderer_error("Unknown virgl format: 0x%x", format);
256 return 0;
257 }
258
259 uint32_t stride = totalWidth * bpp;
260 return y * stride + x * bpp;
261 }
262 return 0;
263 }
264
align_up_power_of_2(uint32_t n,uint32_t a)265 static inline uint32_t align_up_power_of_2(uint32_t n, uint32_t a) {
266 return (n + (a - 1)) & ~(a - 1);
267 }
268
virgl_format_to_total_xfer_len(uint32_t format,uint32_t totalWidth,uint32_t totalHeight,uint32_t x,uint32_t y,uint32_t w,uint32_t h)269 static inline size_t virgl_format_to_total_xfer_len(uint32_t format, uint32_t totalWidth,
270 uint32_t totalHeight, uint32_t x, uint32_t y,
271 uint32_t w, uint32_t h) {
272 if (virgl_format_is_yuv(format)) {
273 uint32_t bpp = format == VIRGL_FORMAT_P010 ? 2 : 1;
274
275 uint32_t yWidth = totalWidth;
276 uint32_t yHeight = totalHeight;
277 uint32_t yStridePixels;
278 if (format == VIRGL_FORMAT_NV12) {
279 yStridePixels = yWidth;
280 } else if (format == VIRGL_FORMAT_P010) {
281 yStridePixels = yWidth;
282 } else if (format == VIRGL_FORMAT_YV12) {
283 yStridePixels = align_up_power_of_2(yWidth, 32);
284 } else {
285 stream_renderer_error("Unknown virgl format: 0x%x", format);
286 return 0;
287 }
288 uint32_t yStrideBytes = yStridePixels * bpp;
289 uint32_t ySize = yStrideBytes * yHeight;
290
291 uint32_t uvStridePixels;
292 uint32_t uvPlaneCount;
293 if (format == VIRGL_FORMAT_NV12) {
294 uvStridePixels = yStridePixels;
295 uvPlaneCount = 1;
296 } else if (format == VIRGL_FORMAT_P010) {
297 uvStridePixels = yStridePixels;
298 uvPlaneCount = 1;
299 } else if (format == VIRGL_FORMAT_YV12) {
300 uvStridePixels = yStridePixels / 2;
301 uvPlaneCount = 2;
302 } else {
303 stream_renderer_error("Unknown virgl yuv format: 0x%x", format);
304 return 0;
305 }
306 uint32_t uvStrideBytes = uvStridePixels * bpp;
307 uint32_t uvHeight = totalHeight / 2;
308 uint32_t uvSize = uvStrideBytes * uvHeight * uvPlaneCount;
309
310 uint32_t dataSize = ySize + uvSize;
311 return dataSize;
312 } else {
313 uint32_t bpp = 4;
314 switch (format) {
315 case VIRGL_FORMAT_R16G16B16A16_FLOAT:
316 case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
317 bpp = 8;
318 break;
319 case VIRGL_FORMAT_B8G8R8X8_UNORM:
320 case VIRGL_FORMAT_B8G8R8A8_UNORM:
321 case VIRGL_FORMAT_R8G8B8X8_UNORM:
322 case VIRGL_FORMAT_R8G8B8A8_UNORM:
323 case VIRGL_FORMAT_R10G10B10A2_UNORM:
324 case VIRGL_FORMAT_Z24X8_UNORM:
325 case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
326 case VIRGL_FORMAT_Z32_FLOAT:
327 bpp = 4;
328 break;
329 case VIRGL_FORMAT_R8G8B8_UNORM:
330 bpp = 3;
331 break;
332 case VIRGL_FORMAT_B5G6R5_UNORM:
333 case VIRGL_FORMAT_R16_UNORM:
334 case VIRGL_FORMAT_R8G8_UNORM:
335 case VIRGL_FORMAT_Z16_UNORM:
336 bpp = 2;
337 break;
338 case VIRGL_FORMAT_R8_UNORM:
339 bpp = 1;
340 break;
341 default:
342 stream_renderer_error("Unknown virgl format: 0x%x", format);
343 return 0;
344 }
345
346 uint32_t stride = totalWidth * bpp;
347 return (h - 1U) * stride + w * bpp;
348 }
349 return 0;
350 }
351
352 } // namespace host
353 } // namespace gfxstream