xref: /aosp_15_r20/external/virglrenderer/src/vrend_formats.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1 /**************************************************************************
2  *
3  * Copyright (C) 2014 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 #include <epoxy/gl.h>
25 
26 #include "vrend_renderer.h"
27 #include "util/u_memory.h"
28 #include "util/u_format.h"
29 
30 #define SWIZZLE_INVALID 0xff
31 #define NO_SWIZZLE { SWIZZLE_INVALID, SWIZZLE_INVALID, SWIZZLE_INVALID, SWIZZLE_INVALID }
32 #define RRR1_SWIZZLE { PIPE_SWIZZLE_RED, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ONE }
33 #define RGB1_SWIZZLE { PIPE_SWIZZLE_RED, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_ONE }
34 #define OOOR_SWIZZLE { PIPE_SWIZZLE_ZERO, PIPE_SWIZZLE_ZERO, PIPE_SWIZZLE_ZERO, PIPE_SWIZZLE_RED  }
35 
36 #define BGR1_SWIZZLE { PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ONE }
37 #define BGRA_SWIZZLE { PIPE_SWIZZLE_BLUE, PIPE_SWIZZLE_GREEN, PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ALPHA }
38 
39 #ifdef __GNUC__
40 /* The warning missing-field-initializers is misleading: If at least one field
41  * is initialized, then the un-initialized fields will be filled with zero.
42  * Silencing the warning by manually adding the zeros that the compiler will add
43  * anyway doesn't improve the code, and initializing the files by using a named
44  * notation will make it worse, because then he remaining fields truely be
45  * un-initialized.
46  */
47 #ifdef __clang__
48 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
49 #else
50 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
51 #endif
52 #endif
53 
54 /* fill the format table */
55 static struct vrend_format_table base_rgba_formats[] =
56   {
57     { VIRGL_FORMAT_R8G8B8X8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
58     { VIRGL_FORMAT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
59 
60     { VIRGL_FORMAT_A8R8G8B8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NO_SWIZZLE },
61     { VIRGL_FORMAT_X8R8G8B8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NO_SWIZZLE },
62 
63     { VIRGL_FORMAT_A8B8G8R8_UNORM, GL_RGBA8, GL_ABGR_EXT, GL_UNSIGNED_BYTE, NO_SWIZZLE },
64 
65     { VIRGL_FORMAT_B4G4R4X4_UNORM, GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, RGB1_SWIZZLE },
66     { VIRGL_FORMAT_A4B4G4R4_UNORM, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NO_SWIZZLE },
67     { VIRGL_FORMAT_B5G5R5X1_UNORM, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, RGB1_SWIZZLE },
68 
69     { VIRGL_FORMAT_B5G6R5_UNORM, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NO_SWIZZLE },
70     { VIRGL_FORMAT_B2G3R3_UNORM, GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_3_3_2, NO_SWIZZLE },
71 
72     { VIRGL_FORMAT_R16G16B16X16_UNORM, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, RGB1_SWIZZLE },
73 
74     { VIRGL_FORMAT_R16G16B16A16_UNORM, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, NO_SWIZZLE },
75   };
76 
77 static struct vrend_format_table gl_base_rgba_formats[] =
78   {
79     { VIRGL_FORMAT_B4G4R4A4_UNORM, GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, NO_SWIZZLE },
80     { VIRGL_FORMAT_B5G5R5A1_UNORM, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NO_SWIZZLE },
81   };
82 
83 static struct vrend_format_table base_depth_formats[] =
84   {
85     { VIRGL_FORMAT_Z16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NO_SWIZZLE },
86     { VIRGL_FORMAT_Z32_UNORM, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NO_SWIZZLE },
87     { VIRGL_FORMAT_S8_UINT_Z24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NO_SWIZZLE },
88     { VIRGL_FORMAT_Z24X8_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NO_SWIZZLE },
89     { VIRGL_FORMAT_Z32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, NO_SWIZZLE },
90     /* this is probably a separate format */
91     { VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NO_SWIZZLE },
92     { VIRGL_FORMAT_X24S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, NO_SWIZZLE },
93   };
94 
95 static struct vrend_format_table base_la_formats[] = {
96   { VIRGL_FORMAT_A8_UNORM, GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
97   { VIRGL_FORMAT_L8_UNORM, GL_R8, GL_RED, GL_UNSIGNED_BYTE, RRR1_SWIZZLE },
98   { VIRGL_FORMAT_A16_UNORM, GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT, NO_SWIZZLE },
99   { VIRGL_FORMAT_L16_UNORM, GL_R16, GL_RED, GL_UNSIGNED_SHORT, RRR1_SWIZZLE },
100 };
101 
102 static struct vrend_format_table rg_base_formats[] = {
103   { VIRGL_FORMAT_R8_UNORM, GL_R8, GL_RED, GL_UNSIGNED_BYTE, NO_SWIZZLE },
104   { VIRGL_FORMAT_R8G8_UNORM, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, NO_SWIZZLE },
105   { VIRGL_FORMAT_R16_UNORM, GL_R16, GL_RED, GL_UNSIGNED_SHORT, NO_SWIZZLE },
106   { VIRGL_FORMAT_R16G16_UNORM, GL_RG16, GL_RG, GL_UNSIGNED_SHORT, NO_SWIZZLE },
107 };
108 
109 static struct vrend_format_table integer_base_formats[] = {
110   { VIRGL_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NO_SWIZZLE },
111   { VIRGL_FORMAT_R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, NO_SWIZZLE },
112 
113   { VIRGL_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, NO_SWIZZLE },
114   { VIRGL_FORMAT_R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, NO_SWIZZLE },
115 
116   { VIRGL_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, NO_SWIZZLE },
117   { VIRGL_FORMAT_R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, NO_SWIZZLE },
118 };
119 
120 static struct vrend_format_table integer_3comp_formats[] = {
121   { VIRGL_FORMAT_R8G8B8X8_UINT, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
122   { VIRGL_FORMAT_R8G8B8X8_SINT, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, RGB1_SWIZZLE },
123   { VIRGL_FORMAT_R16G16B16X16_UINT, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, RGB1_SWIZZLE },
124   { VIRGL_FORMAT_R16G16B16X16_SINT, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, RGB1_SWIZZLE },
125   { VIRGL_FORMAT_R32G32B32_UINT, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT, NO_SWIZZLE },
126   { VIRGL_FORMAT_R32G32B32_SINT, GL_RGB32I, GL_RGB_INTEGER, GL_INT, NO_SWIZZLE },
127 };
128 
129 static struct vrend_format_table float_base_formats[] = {
130   { VIRGL_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, NO_SWIZZLE },
131   { VIRGL_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA, GL_FLOAT, NO_SWIZZLE },
132 };
133 
134 static struct vrend_format_table float_la_formats[] = {
135   { VIRGL_FORMAT_A16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT, OOOR_SWIZZLE },
136   { VIRGL_FORMAT_L16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT, RRR1_SWIZZLE },
137   { VIRGL_FORMAT_L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, NO_SWIZZLE },
138 
139   { VIRGL_FORMAT_A32_FLOAT, GL_R32F, GL_RED, GL_FLOAT, OOOR_SWIZZLE },
140   { VIRGL_FORMAT_L32_FLOAT, GL_R32F, GL_RED, GL_FLOAT, RRR1_SWIZZLE },
141   { VIRGL_FORMAT_L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT, NO_SWIZZLE },
142 };
143 
144 static struct vrend_format_table integer_rg_formats[] = {
145   { VIRGL_FORMAT_R8_UINT, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NO_SWIZZLE },
146   { VIRGL_FORMAT_R8G8_UINT, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, NO_SWIZZLE },
147   { VIRGL_FORMAT_R8_SINT, GL_R8I, GL_RED_INTEGER, GL_BYTE, NO_SWIZZLE },
148   { VIRGL_FORMAT_R8G8_SINT, GL_RG8I, GL_RG_INTEGER, GL_BYTE, NO_SWIZZLE },
149 
150   { VIRGL_FORMAT_R16_UINT, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NO_SWIZZLE },
151   { VIRGL_FORMAT_R16G16_UINT, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, NO_SWIZZLE },
152   { VIRGL_FORMAT_R16_SINT, GL_R16I, GL_RED_INTEGER, GL_SHORT, NO_SWIZZLE },
153   { VIRGL_FORMAT_R16G16_SINT, GL_RG16I, GL_RG_INTEGER, GL_SHORT, NO_SWIZZLE },
154 
155   { VIRGL_FORMAT_R32_UINT, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, NO_SWIZZLE },
156   { VIRGL_FORMAT_R32G32_UINT, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, NO_SWIZZLE },
157   { VIRGL_FORMAT_R32_SINT, GL_R32I, GL_RED_INTEGER, GL_INT, NO_SWIZZLE },
158   { VIRGL_FORMAT_R32G32_SINT, GL_RG32I, GL_RG_INTEGER, GL_INT, NO_SWIZZLE },
159 };
160 
161 static struct vrend_format_table float_rg_formats[] = {
162   { VIRGL_FORMAT_R16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT, NO_SWIZZLE },
163   { VIRGL_FORMAT_R16G16_FLOAT, GL_RG16F, GL_RG, GL_HALF_FLOAT, NO_SWIZZLE },
164   { VIRGL_FORMAT_R32_FLOAT, GL_R32F, GL_RED, GL_FLOAT, NO_SWIZZLE },
165   { VIRGL_FORMAT_R32G32_FLOAT, GL_RG32F, GL_RG, GL_FLOAT, NO_SWIZZLE },
166 };
167 
168 static struct vrend_format_table float_3comp_formats[] = {
169   { VIRGL_FORMAT_R16G16B16X16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, RGB1_SWIZZLE },
170   { VIRGL_FORMAT_R32G32B32_FLOAT, GL_RGB32F, GL_RGB, GL_FLOAT, NO_SWIZZLE },
171 };
172 
173 
174 static struct vrend_format_table integer_la_formats[] = {
175   { VIRGL_FORMAT_A8_UINT, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, OOOR_SWIZZLE },
176   { VIRGL_FORMAT_L8_UINT, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, RRR1_SWIZZLE },
177   { VIRGL_FORMAT_L8A8_UINT, GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE, NO_SWIZZLE },
178   { VIRGL_FORMAT_A8_SINT, GL_R8I, GL_RED_INTEGER, GL_BYTE, OOOR_SWIZZLE },
179   { VIRGL_FORMAT_L8_SINT, GL_R8I, GL_RED_INTEGER, GL_BYTE, RRR1_SWIZZLE },
180   { VIRGL_FORMAT_L8A8_SINT, GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_BYTE, NO_SWIZZLE },
181 
182   { VIRGL_FORMAT_A16_UINT, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, OOOR_SWIZZLE },
183   { VIRGL_FORMAT_L16_UINT, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, RRR1_SWIZZLE },
184   { VIRGL_FORMAT_L16A16_UINT, GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT, NO_SWIZZLE },
185 
186   { VIRGL_FORMAT_A16_SINT, GL_R16I, GL_RED_INTEGER, GL_SHORT, OOOR_SWIZZLE },
187   { VIRGL_FORMAT_L16_SINT, GL_R16I, GL_RED_INTEGER, GL_SHORT, RRR1_SWIZZLE },
188   { VIRGL_FORMAT_L16A16_SINT, GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_SHORT, NO_SWIZZLE },
189 
190   { VIRGL_FORMAT_A32_UINT, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, OOOR_SWIZZLE },
191   { VIRGL_FORMAT_L32_UINT, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, RRR1_SWIZZLE },
192   { VIRGL_FORMAT_L32A32_UINT, GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, NO_SWIZZLE },
193 
194   { VIRGL_FORMAT_A32_SINT, GL_R32I, GL_RED_INTEGER, GL_INT, OOOR_SWIZZLE },
195   { VIRGL_FORMAT_L32_SINT, GL_R32I, GL_RED_INTEGER, GL_INT, RRR1_SWIZZLE },
196   { VIRGL_FORMAT_L32A32_SINT, GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_INT, NO_SWIZZLE },
197 
198 
199 };
200 
201 static struct vrend_format_table snorm_formats[] = {
202   { VIRGL_FORMAT_R8_SNORM, GL_R8_SNORM, GL_RED, GL_BYTE, NO_SWIZZLE },
203   { VIRGL_FORMAT_R8G8_SNORM, GL_RG8_SNORM, GL_RG, GL_BYTE, NO_SWIZZLE },
204 
205   { VIRGL_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, NO_SWIZZLE },
206   { VIRGL_FORMAT_R8G8B8X8_SNORM, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, RGB1_SWIZZLE },
207 
208   { VIRGL_FORMAT_R16_SNORM, GL_R16_SNORM, GL_RED, GL_SHORT, NO_SWIZZLE },
209   { VIRGL_FORMAT_R16G16_SNORM, GL_RG16_SNORM, GL_RG, GL_SHORT, NO_SWIZZLE },
210   { VIRGL_FORMAT_R16G16B16A16_SNORM, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, NO_SWIZZLE },
211 
212   { VIRGL_FORMAT_R16G16B16X16_SNORM, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, RGB1_SWIZZLE },
213 };
214 
215 static struct vrend_format_table snorm_la_formats[] = {
216   { VIRGL_FORMAT_A8_SNORM, GL_ALPHA8_SNORM, GL_ALPHA, GL_BYTE, NO_SWIZZLE },
217   { VIRGL_FORMAT_L8_SNORM, GL_R8_SNORM, GL_RED, GL_BYTE, RRR1_SWIZZLE },
218   { VIRGL_FORMAT_L8A8_SNORM, GL_LUMINANCE8_ALPHA8_SNORM, GL_LUMINANCE_ALPHA, GL_BYTE, NO_SWIZZLE },
219   { VIRGL_FORMAT_A16_SNORM, GL_ALPHA16_SNORM, GL_ALPHA, GL_SHORT, NO_SWIZZLE },
220   { VIRGL_FORMAT_L16_SNORM, GL_R16_SNORM, GL_RED, GL_SHORT, RRR1_SWIZZLE },
221   { VIRGL_FORMAT_L16A16_SNORM, GL_LUMINANCE16_ALPHA16_SNORM, GL_LUMINANCE_ALPHA, GL_SHORT, NO_SWIZZLE },
222 };
223 
224 static struct vrend_format_table dxtn_formats[] = {
225   { VIRGL_FORMAT_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE },
226   { VIRGL_FORMAT_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
227   { VIRGL_FORMAT_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
228   { VIRGL_FORMAT_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
229 };
230 
231 static struct vrend_format_table dxtn_srgb_formats[] = {
232   { VIRGL_FORMAT_DXT1_SRGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE },
233   { VIRGL_FORMAT_DXT1_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
234   { VIRGL_FORMAT_DXT3_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
235   { VIRGL_FORMAT_DXT5_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
236 };
237 
238 static struct vrend_format_table etc2_formats[] = {
239   {VIRGL_FORMAT_ETC2_RGB8, GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE },
240   {VIRGL_FORMAT_ETC2_SRGB8, GL_COMPRESSED_SRGB8_ETC2, GL_RGB, GL_BYTE, NO_SWIZZLE },
241   {VIRGL_FORMAT_ETC2_RGB8A1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
242   {VIRGL_FORMAT_ETC2_SRGB8A1, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_RGBA, GL_BYTE, NO_SWIZZLE },
243   {VIRGL_FORMAT_ETC2_RGBA8, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
244   {VIRGL_FORMAT_ETC2_SRGBA8, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_RGBA, GL_BYTE, NO_SWIZZLE },
245   {VIRGL_FORMAT_ETC2_R11_UNORM, GL_COMPRESSED_R11_EAC, GL_RED, GL_UNSIGNED_BYTE, NO_SWIZZLE},
246   {VIRGL_FORMAT_ETC2_R11_SNORM, GL_COMPRESSED_SIGNED_R11_EAC, GL_RED, GL_BYTE, NO_SWIZZLE},
247   {VIRGL_FORMAT_ETC2_RG11_UNORM, GL_COMPRESSED_RG11_EAC, GL_RG, GL_UNSIGNED_BYTE, NO_SWIZZLE},
248   {VIRGL_FORMAT_ETC2_RG11_SNORM, GL_COMPRESSED_SIGNED_RG11_EAC, GL_RG, GL_BYTE, NO_SWIZZLE},
249 };
250 static struct vrend_format_table astc_formats[] = {
251    {VIRGL_FORMAT_ASTC_4x4, GL_COMPRESSED_RGBA_ASTC_4x4, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
252    {VIRGL_FORMAT_ASTC_5x4, GL_COMPRESSED_RGBA_ASTC_5x4, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
253    {VIRGL_FORMAT_ASTC_5x5, GL_COMPRESSED_RGBA_ASTC_5x5, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
254    {VIRGL_FORMAT_ASTC_6x5, GL_COMPRESSED_RGBA_ASTC_6x5, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
255    {VIRGL_FORMAT_ASTC_6x6, GL_COMPRESSED_RGBA_ASTC_6x6, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
256    {VIRGL_FORMAT_ASTC_8x5, GL_COMPRESSED_RGBA_ASTC_8x5, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
257    {VIRGL_FORMAT_ASTC_8x6, GL_COMPRESSED_RGBA_ASTC_8x6, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
258    {VIRGL_FORMAT_ASTC_8x8, GL_COMPRESSED_RGBA_ASTC_8x8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
259    {VIRGL_FORMAT_ASTC_10x5, GL_COMPRESSED_RGBA_ASTC_10x5, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
260    {VIRGL_FORMAT_ASTC_10x6, GL_COMPRESSED_RGBA_ASTC_10x6, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
261    {VIRGL_FORMAT_ASTC_10x8, GL_COMPRESSED_RGBA_ASTC_10x8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
262    {VIRGL_FORMAT_ASTC_10x10, GL_COMPRESSED_RGBA_ASTC_10x10, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
263    {VIRGL_FORMAT_ASTC_12x10, GL_COMPRESSED_RGBA_ASTC_12x10, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
264    {VIRGL_FORMAT_ASTC_12x12, GL_COMPRESSED_RGBA_ASTC_12x12, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
265    {VIRGL_FORMAT_ASTC_4x4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4, GL_RGBA, GL_BYTE, NO_SWIZZLE },
266    {VIRGL_FORMAT_ASTC_5x4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4, GL_RGBA, GL_BYTE, NO_SWIZZLE },
267    {VIRGL_FORMAT_ASTC_5x5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5, GL_RGBA, GL_BYTE, NO_SWIZZLE },
268    {VIRGL_FORMAT_ASTC_6x5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5, GL_RGBA, GL_BYTE, NO_SWIZZLE },
269    {VIRGL_FORMAT_ASTC_6x6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6, GL_RGBA, GL_BYTE, NO_SWIZZLE },
270    {VIRGL_FORMAT_ASTC_8x5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5, GL_RGBA, GL_BYTE, NO_SWIZZLE },
271    {VIRGL_FORMAT_ASTC_8x6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6, GL_RGBA, GL_BYTE, NO_SWIZZLE },
272    {VIRGL_FORMAT_ASTC_8x8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8, GL_RGBA, GL_BYTE, NO_SWIZZLE },
273    {VIRGL_FORMAT_ASTC_10x5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5, GL_RGBA, GL_BYTE, NO_SWIZZLE },
274    {VIRGL_FORMAT_ASTC_10x6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6, GL_RGBA, GL_BYTE, NO_SWIZZLE },
275    {VIRGL_FORMAT_ASTC_10x8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8, GL_RGBA, GL_BYTE, NO_SWIZZLE },
276    {VIRGL_FORMAT_ASTC_10x10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10, GL_RGBA, GL_BYTE, NO_SWIZZLE },
277    {VIRGL_FORMAT_ASTC_12x10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10, GL_RGBA, GL_BYTE, NO_SWIZZLE },
278    {VIRGL_FORMAT_ASTC_12x12_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12, GL_RGBA, GL_BYTE, NO_SWIZZLE },
279 };
280 
281 static struct vrend_format_table rgtc_formats[] = {
282   { VIRGL_FORMAT_RGTC1_UNORM, GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, NO_SWIZZLE },
283   { VIRGL_FORMAT_RGTC1_SNORM, GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_BYTE, NO_SWIZZLE },
284 
285   { VIRGL_FORMAT_RGTC2_UNORM, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, NO_SWIZZLE },
286   { VIRGL_FORMAT_RGTC2_SNORM, GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_BYTE, NO_SWIZZLE },
287 };
288 
289 static struct vrend_format_table srgb_formats[] = {
290   { VIRGL_FORMAT_R8G8B8X8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
291   { VIRGL_FORMAT_R8G8B8A8_SRGB, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
292 
293   { VIRGL_FORMAT_L8_SRGB, GL_SR8_EXT, GL_RED, GL_UNSIGNED_BYTE, RRR1_SWIZZLE },
294   { VIRGL_FORMAT_R8_SRGB, GL_SR8_EXT, GL_RED, GL_UNSIGNED_BYTE, NO_SWIZZLE },
295 
296   { VIRGL_FORMAT_R8G8_SRGB, GL_SRG8_EXT, GL_RG, GL_UNSIGNED_BYTE, NO_SWIZZLE },
297 };
298 
299 static struct vrend_format_table bit10_formats[] = {
300   { VIRGL_FORMAT_B10G10R10X2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, RGB1_SWIZZLE },
301   { VIRGL_FORMAT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
302   { VIRGL_FORMAT_B10G10R10A2_UINT, GL_RGB10_A2UI, GL_BGRA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
303   { VIRGL_FORMAT_R10G10B10X2_UNORM, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, RGB1_SWIZZLE },
304   { VIRGL_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
305   { VIRGL_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
306 };
307 
308 static struct vrend_format_table packed_float_formats[] = {
309   { VIRGL_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, NO_SWIZZLE },
310 };
311 
312 static struct vrend_format_table exponent_float_formats[] = {
313   { VIRGL_FORMAT_R9G9B9E5_FLOAT, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, NO_SWIZZLE },
314 };
315 
316 static struct vrend_format_table bptc_formats[] = {
317    { VIRGL_FORMAT_BPTC_RGBA_UNORM, GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
318    { VIRGL_FORMAT_BPTC_SRGBA, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
319    { VIRGL_FORMAT_BPTC_RGB_FLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE },
320    { VIRGL_FORMAT_BPTC_RGB_UFLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, NO_SWIZZLE },
321 };
322 
323 static struct vrend_format_table gl_bgra_formats[] = {
324   { VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
325   { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
326   { VIRGL_FORMAT_B8G8R8X8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
327   { VIRGL_FORMAT_B8G8R8A8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, NO_SWIZZLE },
328 };
329 
330 static struct vrend_format_table gles_bgra_formats[] = {
331   { VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8,        GL_RGBA,     GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
332   { VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8,        GL_RGBA,     GL_UNSIGNED_BYTE, NO_SWIZZLE },
333   { VIRGL_FORMAT_B8G8R8X8_SRGB,  GL_SRGB8_ALPHA8, GL_RGBA,     GL_UNSIGNED_BYTE, RGB1_SWIZZLE },
334   { VIRGL_FORMAT_B8G8R8A8_SRGB,  GL_SRGB8_ALPHA8, GL_RGBA,     GL_UNSIGNED_BYTE, NO_SWIZZLE },
335 };
336 
337 
338 
339 static struct vrend_format_table gles_z32_format[] = {
340   { VIRGL_FORMAT_Z32_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NO_SWIZZLE },
341 };
342 
343 static struct vrend_format_table gles_bit10_formats[] = {
344   { VIRGL_FORMAT_B10G10R10X2_UNORM, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, RGB1_SWIZZLE },
345   { VIRGL_FORMAT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, NO_SWIZZLE },
346 };
347 
color_format_can_readback(struct vrend_format_table * virgl_format,int gles_ver)348 static bool color_format_can_readback(struct vrend_format_table *virgl_format, int gles_ver)
349 {
350    GLint imp = 0;
351 
352    if (virgl_format->format == VIRGL_FORMAT_R8G8B8A8_UNORM)
353       return true;
354 
355    if (gles_ver >= 30 &&
356         (virgl_format->format == VIRGL_FORMAT_R32G32B32A32_SINT ||
357          virgl_format->format == VIRGL_FORMAT_R32G32B32A32_UINT))
358        return true;
359 
360    if ((virgl_format->format == VIRGL_FORMAT_R32G32B32A32_FLOAT) &&
361        (gles_ver >= 32 || epoxy_has_gl_extension("GL_EXT_color_buffer_float")))
362       return true;
363 
364    /* Hotfix for the CI, on GLES these formats are defined like
365     * VIRGL_FORMAT_R10G10B10.2_UNORM, and seems to be incorrect for direct
366     * readback but the blit workaround seems to work, so disable the
367     * direct readback for these two formats. */
368    if (virgl_format->format == VIRGL_FORMAT_B10G10R10A2_UNORM ||
369        virgl_format->format == VIRGL_FORMAT_B10G10R10X2_UNORM)
370       return false;
371 
372 
373    /* Check implementation specific readback formats */
374    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &imp);
375    if (imp == (GLint)virgl_format->gltype) {
376       glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &imp);
377       if (imp == (GLint)virgl_format->glformat)
378          return true;
379    }
380    return false;
381 }
382 
depth_stencil_formats_can_readback(enum virgl_formats format)383 static bool depth_stencil_formats_can_readback(enum virgl_formats format)
384 {
385    switch (format) {
386    case VIRGL_FORMAT_Z16_UNORM:
387    case VIRGL_FORMAT_Z32_UNORM:
388    case VIRGL_FORMAT_Z32_FLOAT:
389    case VIRGL_FORMAT_Z24X8_UNORM:
390       return epoxy_has_gl_extension("GL_NV_read_depth");
391 
392    case VIRGL_FORMAT_Z24_UNORM_S8_UINT:
393    case VIRGL_FORMAT_S8_UINT_Z24_UNORM:
394    case VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT:
395       return epoxy_has_gl_extension("GL_NV_read_depth_stencil");
396 
397    case VIRGL_FORMAT_X24S8_UINT:
398    case VIRGL_FORMAT_S8X24_UINT:
399    case VIRGL_FORMAT_S8_UINT:
400       return epoxy_has_gl_extension("GL_NV_read_stencil");
401 
402    default:
403       return false;
404    }
405 }
406 
vrend_add_formats(struct vrend_format_table * table,int num_entries)407 static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
408 {
409   int i;
410 
411   const bool is_desktop_gl = epoxy_is_desktop_gl();
412   const int gles_ver = is_desktop_gl ? 0 : epoxy_gl_version();
413 
414   for (i = 0; i < num_entries; i++) {
415     GLenum status;
416     bool is_depth = false;
417     uint32_t flags = 0;
418     uint32_t binding = 0;
419     GLuint buffers;
420     GLuint tex_id, fb_id;
421 
422     /**/
423     glGenTextures(1, &tex_id);
424     glGenFramebuffers(1, &fb_id);
425 
426     glBindTexture(GL_TEXTURE_2D, tex_id);
427     glBindFramebuffer(GL_FRAMEBUFFER, fb_id);
428 
429     /* The error state should be clear here */
430     status = glGetError();
431     assert(status == GL_NO_ERROR);
432 
433     glTexImage2D(GL_TEXTURE_2D, 0, table[i].internalformat, 32, 32, 0, table[i].glformat, table[i].gltype, NULL);
434     status = glGetError();
435     /* Currently possible errors are:
436      *  * GL_INVALID_VALUE
437      *  * GL_INVALID_ENUM
438      *  * GL_INVALID_OPERATION
439      *  * GL_OUT_OF_MEMORY
440      */
441     if (status != GL_NO_ERROR) {
442       struct vrend_format_table *entry = NULL;
443       uint8_t swizzle[4];
444       binding = VIRGL_BIND_SAMPLER_VIEW | VIRGL_BIND_RENDER_TARGET;
445 
446       switch (table[i].format) {
447       case VIRGL_FORMAT_A8_UNORM:
448         entry = &rg_base_formats[0];
449         swizzle[0] = swizzle[1] = swizzle[2] = PIPE_SWIZZLE_ZERO;
450         swizzle[3] = PIPE_SWIZZLE_RED;
451         flags |= VIRGL_TEXTURE_NEED_SWIZZLE;
452         break;
453       case VIRGL_FORMAT_A16_UNORM:
454         entry = &rg_base_formats[2];
455         swizzle[0] = swizzle[1] = swizzle[2] = PIPE_SWIZZLE_ZERO;
456         swizzle[3] = PIPE_SWIZZLE_RED;
457         flags |= VIRGL_TEXTURE_NEED_SWIZZLE;
458         break;
459       default:
460         break;
461       }
462 
463       if (entry) {
464         vrend_insert_format_swizzle(table[i].format, entry, binding, swizzle, flags);
465       }
466       glDeleteTextures(1, &tex_id);
467       glDeleteFramebuffers(1, &fb_id);
468       continue;
469     }
470 
471     if (is_desktop_gl) {
472       glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, table[i].internalformat, 32, 32, 0, table[i].glformat, table[i].gltype, NULL);
473       status = glGetError();
474       if (status == GL_NO_ERROR) {
475         flags |= VIRGL_TEXTURE_CAN_TARGET_RECTANGLE;
476       }
477     }
478 
479     if (table[i].format < VIRGL_FORMAT_MAX  && util_format_is_depth_or_stencil(table[i].format)) {
480       GLenum attachment;
481 
482       if (table[i].format == VIRGL_FORMAT_Z24X8_UNORM || table[i].format == VIRGL_FORMAT_Z32_UNORM || table[i].format == VIRGL_FORMAT_Z16_UNORM || table[i].format == VIRGL_FORMAT_Z32_FLOAT)
483         attachment = GL_DEPTH_ATTACHMENT;
484       else
485         attachment = GL_DEPTH_STENCIL_ATTACHMENT;
486       glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex_id, 0);
487 
488       is_depth = true;
489 
490       buffers = GL_NONE;
491       glDrawBuffers(1, &buffers);
492     } else {
493       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id, 0);
494 
495       buffers = GL_COLOR_ATTACHMENT0;
496       glDrawBuffers(1, &buffers);
497     }
498 
499     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
500     binding = VIRGL_BIND_SAMPLER_VIEW;
501     if (status == GL_FRAMEBUFFER_COMPLETE)
502        binding |= is_depth ? VIRGL_BIND_DEPTH_STENCIL : VIRGL_BIND_RENDER_TARGET;
503 
504     /* On OpenGL all textures can be read back using glGetTexImage, but on GLES
505        we have to be able to bind textures to framebuffers, and use glReadPixels
506        to get the data. And apart from a few formats where support is required
507        (by the GLES version), we have to query the driver to identify additional
508        formats that are supported as destination formats by glReadPixels. */
509     if (is_desktop_gl ||
510         (status == GL_FRAMEBUFFER_COMPLETE &&
511          (is_depth ? depth_stencil_formats_can_readback(table[i].format) :
512                      color_format_can_readback(&table[i], gles_ver))))
513        flags |= VIRGL_TEXTURE_CAN_READBACK;
514 
515     glDeleteTextures(1, &tex_id);
516     glDeleteFramebuffers(1, &fb_id);
517 
518     if (table[i].swizzle[0] != SWIZZLE_INVALID)
519        vrend_insert_format_swizzle(table[i].format, &table[i], binding, table[i].swizzle, flags);
520     else
521        vrend_insert_format(&table[i], binding, flags);
522   }
523 }
524 
vrend_add_compressed_formats(struct vrend_format_table * table,int num_entries)525 static void vrend_add_compressed_formats(struct vrend_format_table *table, int num_entries)
526 {
527    int flags = epoxy_is_desktop_gl() ? VIRGL_TEXTURE_CAN_READBACK : 0;
528    for (int i = 0; i < num_entries; i++) {
529       vrend_insert_format(&table[i], VIRGL_BIND_SAMPLER_VIEW, flags);
530    }
531 }
532 
533 
534 #define add_formats(x) vrend_add_formats((x), ARRAY_SIZE((x)))
535 #define add_compressed_formats(x) vrend_add_compressed_formats((x), ARRAY_SIZE((x)))
536 
vrend_build_format_list_common(void)537 void vrend_build_format_list_common(void)
538 {
539   add_formats(base_rgba_formats);
540   add_formats(base_depth_formats);
541   add_formats(base_la_formats);
542 
543   /* float support */
544   add_formats(float_base_formats);
545   add_formats(float_la_formats);
546   add_formats(float_3comp_formats);
547 
548   /* texture integer support ? */
549   add_formats(integer_base_formats);
550   add_formats(integer_la_formats);
551   add_formats(integer_3comp_formats);
552 
553   /* RG support? */
554   add_formats(rg_base_formats);
555   /* integer + rg */
556   add_formats(integer_rg_formats);
557   /* float + rg */
558   add_formats(float_rg_formats);
559 
560   /* snorm */
561   add_formats(snorm_formats);
562   add_formats(snorm_la_formats);
563 
564   /* compressed */
565   if (epoxy_has_gl_extension("GL_S3_s3tc") ||
566       epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc") ||
567       epoxy_has_gl_extension("GL_ANGLE_texture_compression_dxt")) {
568      add_compressed_formats(dxtn_formats);
569      add_compressed_formats(dxtn_srgb_formats);
570   }
571 
572   if (epoxy_has_gl_extension("GL_ARB_texture_compression_rgtc") ||
573       epoxy_has_gl_extension("GL_EXT_texture_compression_rgtc") )
574      add_compressed_formats(rgtc_formats);
575 
576   if (epoxy_has_gl_extension("GL_ARB_texture_compression_bptc") ||
577       epoxy_has_gl_extension("GL_EXT_texture_compression_bptc"))
578      add_compressed_formats(bptc_formats);
579 
580   add_formats(srgb_formats);
581 
582   add_formats(bit10_formats);
583 
584   add_formats(packed_float_formats);
585   add_formats(exponent_float_formats);
586 }
587 
588 
vrend_build_format_list_gl(void)589 void vrend_build_format_list_gl(void)
590 {
591   /* GL_BGRA formats aren't as well supported in GLES as in GL, specially in
592    * transfer operations. So we only register support for it in GL.
593    */
594   add_formats(gl_base_rgba_formats);
595   add_formats(gl_bgra_formats);
596 }
597 
vrend_build_format_list_gles(void)598 void vrend_build_format_list_gles(void)
599 {
600   /* The BGR[A|X] formats is required but OpenGL ES does not
601    * support it as nicely as OpenGL. We could try to use BGRA_EXT from
602    * EXT_texture_format_BGRA8888, but it becomes error prone when mixed
603    * with BGR*_SRGB formats and framebuffer multisampling. Instead, on
604    * GLES hosts, we always emulate BGR* as GL_RGB* with a swizzle on
605    * transfers to/from the host.
606    */
607   add_formats(gles_bgra_formats);
608 
609   /* The Z32 format is required, but OpenGL ES does not support
610    * using it as a depth buffer. We just fake support with Z24
611    * and hope nobody notices.
612    */
613   add_formats(gles_z32_format);
614   add_formats(gles_bit10_formats);
615 
616   if (epoxy_has_gl_extension("GL_KHR_texture_compression_astc_ldr"))
617      add_compressed_formats(astc_formats);
618 
619   if (epoxy_gl_version() >= 30) {
620      add_compressed_formats(etc2_formats);
621   }
622 
623 }
624 
625 /* glTexStorage may not support all that is supported by glTexImage,
626  * so add a flag to indicate when it can be used.
627  */
vrend_check_texture_storage(struct vrend_format_table * table)628 void vrend_check_texture_storage(struct vrend_format_table *table)
629 {
630    int i;
631    GLuint tex_id;
632    for (i = 0; i < VIRGL_FORMAT_MAX_EXTENDED; i++) {
633 
634       if (table[i].internalformat != 0 &&
635           !(table[i].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE)) {
636          glGenTextures(1, &tex_id);
637          glBindTexture(GL_TEXTURE_2D, tex_id);
638          glTexStorage2D(GL_TEXTURE_2D, 1, table[i].internalformat, 32, 32);
639          if (glGetError() == GL_NO_ERROR)
640             table[i].flags |= VIRGL_TEXTURE_CAN_TEXTURE_STORAGE;
641          glDeleteTextures(1, &tex_id);
642       }
643    }
644 }
645 
vrend_check_texture_multisample(struct vrend_format_table * table,bool enable_storage)646 void vrend_check_texture_multisample(struct vrend_format_table *table,
647                                      bool enable_storage)
648 {
649    bool is_desktop_gl = epoxy_is_desktop_gl();
650    for (int i = 0; i < VIRGL_FORMAT_MAX_EXTENDED; i++) {
651       bool function_available =
652          (table[i].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE) ? enable_storage : is_desktop_gl;
653 
654       if (table[i].internalformat != 0 &&
655           !(table[i].flags & VIRGL_TEXTURE_CAN_MULTISAMPLE) &&
656           function_available) {
657          GLuint tex_id;
658          glGenTextures(1, &tex_id);
659          glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex_id);
660          if (table[i].flags & VIRGL_TEXTURE_CAN_TEXTURE_STORAGE) {
661             glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2,
662                                       table[i].internalformat, 32, 32, GL_TRUE);
663          } else {
664             glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2,
665                                     table[i].internalformat, 32, 32, GL_TRUE);
666          }
667          if (glGetError() == GL_NO_ERROR)
668             table[i].flags |= VIRGL_TEXTURE_CAN_MULTISAMPLE;
669          glDeleteTextures(1, &tex_id);
670       }
671    }
672 }
673 
vrend_check_framebuffer_mixed_color_attachements(void)674 bool vrend_check_framebuffer_mixed_color_attachements(void)
675 {
676    GLuint tex_id[2];
677    GLuint fb_id;
678    bool retval = false;
679 
680    glGenTextures(2, tex_id);
681    glGenFramebuffers(1, &fb_id);
682 
683    glBindTexture(GL_TEXTURE_2D, tex_id[0]);
684    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
685 
686    glBindFramebuffer(GL_FRAMEBUFFER, fb_id);
687    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id[0], 0);
688 
689    glBindTexture(GL_TEXTURE_2D, tex_id[1]);
690    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
691    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex_id[1], 0);
692 
693 
694    retval = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
695 
696    glDeleteFramebuffers(1, &fb_id);
697    glDeleteTextures(2, tex_id);
698 
699    return retval;
700 }
701 
702 
vrend_renderer_query_multisample_caps(unsigned max_samples,struct virgl_caps_v2 * caps)703 unsigned vrend_renderer_query_multisample_caps(unsigned max_samples, struct virgl_caps_v2 *caps)
704 {
705    GLuint tex;
706    GLuint fbo;
707    GLenum status;
708 
709    uint max_samples_confirmed = 1;
710    uint test_num_samples[4] = {2,4,8,16};
711    int out_buf_offsets[4] = {0,1,2,4};
712    int lowest_working_ms_count_idx = -1;
713 
714    assert(glGetError() == GL_NO_ERROR &&
715           "Stale error state detected, please check for failures in initialization");
716 
717    glGenFramebuffers( 1, &fbo );
718    memset(caps->sample_locations, 0, 8 * sizeof(uint32_t));
719 
720    for (int i = 3; i >= 0; i--) {
721       if (test_num_samples[i] > max_samples)
722          continue;
723       glGenTextures(1, &tex);
724       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
725       glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, test_num_samples[i], GL_RGBA32F, 64, 64, GL_TRUE);
726       status = glGetError();
727       if (status == GL_NO_ERROR) {
728          glBindFramebuffer(GL_FRAMEBUFFER, fbo);
729          glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
730          status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
731          if (status == GL_FRAMEBUFFER_COMPLETE) {
732             if (max_samples_confirmed < test_num_samples[i])
733                max_samples_confirmed = test_num_samples[i];
734 
735             for (uint k = 0; k < test_num_samples[i]; ++k) {
736                float msp[2];
737                uint32_t compressed;
738                glGetMultisamplefv(GL_SAMPLE_POSITION, k, msp);
739                compressed = ((unsigned)(floor(msp[0] * 16.0f)) & 0xf) << 4;
740                compressed |= ((unsigned)(floor(msp[1] * 16.0f)) & 0xf);
741                caps->sample_locations[out_buf_offsets[i] + (k >> 2)] |= compressed  << (8 * (k & 3));
742             }
743             lowest_working_ms_count_idx = i;
744          } else {
745             /* If a framebuffer doesn't support low sample counts,
746              * use the sample position from the last working larger count. */
747             if (lowest_working_ms_count_idx > 0) {
748                for (uint k = 0; k < test_num_samples[i]; ++k) {
749                   caps->sample_locations[out_buf_offsets[i] + (k >> 2)] =
750                         caps->sample_locations[out_buf_offsets[lowest_working_ms_count_idx]  + (k >> 2)];
751                }
752             }
753          }
754          glBindFramebuffer(GL_FRAMEBUFFER, 0);
755       }
756       glDeleteTextures(1, &tex);
757    }
758    glDeleteFramebuffers(1, &fbo);
759    return max_samples_confirmed;
760 }
761 
762 /* returns: 1 = compatible, -1 = not compatible, 0 = undecided */
format_uncompressed_compressed_copy_compatible(enum virgl_formats src,enum virgl_formats dst)763 static int format_uncompressed_compressed_copy_compatible(enum virgl_formats src,
764                                                           enum virgl_formats dst)
765 {
766 
767    switch (src) {
768    case VIRGL_FORMAT_R32G32B32A32_UINT:
769    case VIRGL_FORMAT_R32G32B32A32_SINT:
770    case VIRGL_FORMAT_R32G32B32A32_FLOAT:
771    case VIRGL_FORMAT_R32G32B32A32_SNORM:
772    case VIRGL_FORMAT_R32G32B32A32_UNORM:
773       switch (dst) {
774       case VIRGL_FORMAT_DXT3_RGBA:
775       case VIRGL_FORMAT_DXT3_SRGBA:
776       case VIRGL_FORMAT_DXT5_RGBA:
777       case VIRGL_FORMAT_DXT5_SRGBA:
778       case VIRGL_FORMAT_RGTC2_UNORM:
779       case VIRGL_FORMAT_RGTC2_SNORM:
780       case VIRGL_FORMAT_BPTC_RGBA_UNORM:
781       case VIRGL_FORMAT_BPTC_SRGBA:
782       case VIRGL_FORMAT_BPTC_RGB_FLOAT:
783       case VIRGL_FORMAT_BPTC_RGB_UFLOAT:
784       case VIRGL_FORMAT_ETC2_RGBA8:
785       case VIRGL_FORMAT_ETC2_SRGBA8:
786       case VIRGL_FORMAT_ETC2_RG11_UNORM:
787       case VIRGL_FORMAT_ETC2_RG11_SNORM:
788          return 1;
789       case VIRGL_FORMAT_ASTC_4x4:
790       case VIRGL_FORMAT_ASTC_5x4:
791       case VIRGL_FORMAT_ASTC_5x5:
792       case VIRGL_FORMAT_ASTC_6x5:
793       case VIRGL_FORMAT_ASTC_6x6:
794       case VIRGL_FORMAT_ASTC_8x5:
795       case VIRGL_FORMAT_ASTC_8x6:
796       case VIRGL_FORMAT_ASTC_8x8:
797       case VIRGL_FORMAT_ASTC_10x5:
798       case VIRGL_FORMAT_ASTC_10x6:
799       case VIRGL_FORMAT_ASTC_10x8:
800       case VIRGL_FORMAT_ASTC_10x10:
801       case VIRGL_FORMAT_ASTC_12x10:
802       case VIRGL_FORMAT_ASTC_12x12:
803       case VIRGL_FORMAT_ASTC_4x4_SRGB:
804       case VIRGL_FORMAT_ASTC_5x4_SRGB:
805       case VIRGL_FORMAT_ASTC_5x5_SRGB:
806       case VIRGL_FORMAT_ASTC_6x5_SRGB:
807       case VIRGL_FORMAT_ASTC_6x6_SRGB:
808       case VIRGL_FORMAT_ASTC_8x5_SRGB:
809       case VIRGL_FORMAT_ASTC_8x6_SRGB:
810       case VIRGL_FORMAT_ASTC_8x8_SRGB:
811       case VIRGL_FORMAT_ASTC_10x5_SRGB:
812       case VIRGL_FORMAT_ASTC_10x6_SRGB:
813       case VIRGL_FORMAT_ASTC_10x8_SRGB:
814       case VIRGL_FORMAT_ASTC_10x10_SRGB:
815       case VIRGL_FORMAT_ASTC_12x10_SRGB:
816       case VIRGL_FORMAT_ASTC_12x12_SRGB:
817          return epoxy_is_desktop_gl() ? -1 : 1;
818       default:
819          return -1;
820       }
821    case VIRGL_FORMAT_R16G16B16A16_UINT:
822    case VIRGL_FORMAT_R16G16B16A16_SINT:
823    case VIRGL_FORMAT_R16G16B16A16_FLOAT:
824    case VIRGL_FORMAT_R16G16B16A16_SNORM:
825    case VIRGL_FORMAT_R16G16B16A16_UNORM:
826    case VIRGL_FORMAT_R32G32_UINT:
827    case VIRGL_FORMAT_R32G32_SINT:
828    case VIRGL_FORMAT_R32G32_FLOAT:
829    case VIRGL_FORMAT_R32G32_UNORM:
830    case VIRGL_FORMAT_R32G32_SNORM:
831       switch (dst) {
832       case VIRGL_FORMAT_DXT1_RGBA:
833       case VIRGL_FORMAT_DXT1_SRGBA:
834       case VIRGL_FORMAT_DXT1_RGB:
835       case VIRGL_FORMAT_DXT1_SRGB:
836       case VIRGL_FORMAT_RGTC1_UNORM:
837       case VIRGL_FORMAT_RGTC1_SNORM:
838       case VIRGL_FORMAT_ETC2_RGB8:
839       case VIRGL_FORMAT_ETC2_SRGB8:
840       case VIRGL_FORMAT_ETC2_RGB8A1:
841       case VIRGL_FORMAT_ETC2_SRGB8A1:
842       case VIRGL_FORMAT_ETC2_R11_UNORM:
843       case VIRGL_FORMAT_ETC2_R11_SNORM:
844          return 1;
845       default:
846          return -1;
847       }
848    default:
849       return 0;
850    }
851 }
852 
format_compressed_compressed_copy_compatible(enum virgl_formats src,enum virgl_formats dst)853 static boolean format_compressed_compressed_copy_compatible(enum virgl_formats src, enum virgl_formats dst)
854 {
855    const bool is_desktop_gl = epoxy_is_desktop_gl();
856 
857    if(!is_desktop_gl) {
858       if((src == VIRGL_FORMAT_ASTC_4x4 && dst == VIRGL_FORMAT_ASTC_4x4_SRGB) ||
859         (src == VIRGL_FORMAT_ASTC_5x4 && dst == VIRGL_FORMAT_ASTC_5x4_SRGB) ||
860         (src == VIRGL_FORMAT_ASTC_5x5 && dst == VIRGL_FORMAT_ASTC_5x5_SRGB) ||
861         (src == VIRGL_FORMAT_ASTC_6x5 && dst == VIRGL_FORMAT_ASTC_6x5_SRGB) ||
862         (src == VIRGL_FORMAT_ASTC_6x6 && dst == VIRGL_FORMAT_ASTC_6x6_SRGB) ||
863         (src == VIRGL_FORMAT_ASTC_8x5 && dst == VIRGL_FORMAT_ASTC_8x5_SRGB) ||
864         (src == VIRGL_FORMAT_ASTC_8x6 && dst == VIRGL_FORMAT_ASTC_8x6_SRGB) ||
865         (src == VIRGL_FORMAT_ASTC_8x8 && dst == VIRGL_FORMAT_ASTC_8x8_SRGB) ||
866         (src == VIRGL_FORMAT_ASTC_10x5 && dst == VIRGL_FORMAT_ASTC_10x5_SRGB) ||
867         (src == VIRGL_FORMAT_ASTC_10x6 && dst == VIRGL_FORMAT_ASTC_10x6_SRGB) ||
868         (src == VIRGL_FORMAT_ASTC_10x8 && dst == VIRGL_FORMAT_ASTC_10x8_SRGB) ||
869         (src == VIRGL_FORMAT_ASTC_10x10 && dst == VIRGL_FORMAT_ASTC_10x10_SRGB) ||
870         (src == VIRGL_FORMAT_ASTC_12x10 && dst == VIRGL_FORMAT_ASTC_12x10_SRGB) ||
871         (src == VIRGL_FORMAT_ASTC_12x12 && dst == VIRGL_FORMAT_ASTC_12x12_SRGB) ||
872         (src == VIRGL_FORMAT_ETC2_R11_UNORM && dst == VIRGL_FORMAT_ETC2_R11_SNORM) ||
873         (src == VIRGL_FORMAT_ETC2_RG11_UNORM && dst == VIRGL_FORMAT_ETC2_RG11_SNORM) ||
874         (src == VIRGL_FORMAT_ETC2_RGBA8 && dst == VIRGL_FORMAT_ETC2_SRGBA8) ||
875         (src == VIRGL_FORMAT_ETC2_RGB8A1 && dst == VIRGL_FORMAT_ETC2_SRGB8A1) ||
876         (src == VIRGL_FORMAT_ETC2_RGB8 && dst == VIRGL_FORMAT_ETC2_SRGB8))
877          return true;
878    }
879 
880    if ((src == VIRGL_FORMAT_RGTC1_UNORM && dst == VIRGL_FORMAT_RGTC1_SNORM) ||
881        (src == VIRGL_FORMAT_RGTC2_UNORM && dst == VIRGL_FORMAT_RGTC2_SNORM) ||
882        (src == VIRGL_FORMAT_BPTC_RGBA_UNORM && dst == VIRGL_FORMAT_BPTC_SRGBA) ||
883        (src == VIRGL_FORMAT_BPTC_RGB_FLOAT && dst == VIRGL_FORMAT_BPTC_RGB_UFLOAT))
884        return true;
885 
886    return false;
887 }
888 
format_is_copy_compatible(enum virgl_formats src,enum virgl_formats dst,unsigned int flags)889 boolean format_is_copy_compatible(enum virgl_formats src, enum virgl_formats dst,
890                                   unsigned int flags)
891 {
892    int r;
893 
894    if (src == dst) {
895       /* When Mesa imports dma_buf VIRGL_FORMAT_B8G8R8X8_UNORM/DRM|GBM_FORMAT_XRGB8888
896        * it uses internal format GL_RGB8.
897        * But when virglrenderer creates VIRGL_FORMAT_B8G8R8X8_UNORM texture, it
898        * uses internal format GL_RGBA8.
899        * So the formats do not match when Mesa checks them internally.
900        */
901       if (flags & VREND_COPY_COMPAT_FLAG_ONE_IS_EGL_IMAGE &&
902           src == VIRGL_FORMAT_B8G8R8X8_UNORM)
903          return false;
904       return true;
905    }
906 
907    if (util_format_is_plain(src) && util_format_is_plain(dst))  {
908       const struct util_format_description *src_desc = util_format_description(src);
909       const struct util_format_description *dst_desc = util_format_description(dst);
910       return util_is_format_compatible(src_desc, dst_desc);
911    }
912 
913    if (!(flags & VREND_COPY_COMPAT_FLAG_ALLOW_COMPRESSED))
914       return false;
915 
916    /* compressed-uncompressed */
917    r = format_uncompressed_compressed_copy_compatible(src, dst);
918    if (r)
919       return r > 0;
920 
921    r = format_uncompressed_compressed_copy_compatible(dst, src);
922    if (r)
923       return r > 0;
924 
925    return format_compressed_compressed_copy_compatible(dst, src) ||
926           format_compressed_compressed_copy_compatible(src, dst);
927 }
928