1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | #include "interface/khronos/common/khrn_int_common.h" |
29 | #include "interface/khronos/common/khrn_client_platform.h" |
30 | #include "interface/khronos/include/EGL/eglext.h" |
31 | |
32 | #include "interface/khronos/egl/egl_client_config.h" |
33 | |
34 | //#define BGR_FB |
35 | |
36 | typedef uint32_t FEATURES_T; |
37 | |
38 | #define FEATURES_PACK(r, g, b, a, d, s, m, mask, lockable) ((FEATURES_T)((((uint32_t)(r)) << 28 | (g) << 24 | (b) << 20 | (a) << 16 | (d) << 8 | (s) << 4 | (m) << 3 | ((mask) >> 3) << 2) | (lockable) << 1)) |
39 | |
40 | typedef struct { |
41 | FEATURES_T features; |
42 | KHRN_IMAGE_FORMAT_T color, depth, multisample, mask; |
43 | } FEATURES_AND_FORMATS_T; |
44 | |
45 | /* |
46 | formats |
47 | |
48 | For 0 <= id < EGL_MAX_CONFIGS: |
49 | formats[id].features is valid |
50 | */ |
51 | |
52 | static FEATURES_AND_FORMATS_T formats[EGL_MAX_CONFIGS] = { |
53 | // LOCKABLE |
54 | // MASK | |
55 | // R G B A D S M | | COLOR DEPTH MULTISAMPLE MASK |
56 | {FEATURES_PACK(8, 8, 8, 8, 24, 8, 0, 0, 0), ABGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
57 | {FEATURES_PACK(8, 8, 8, 0, 24, 8, 0, 0, 0), XBGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
58 | {FEATURES_PACK(8, 8, 8, 8, 24, 0, 0, 0, 0), ABGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
59 | {FEATURES_PACK(8, 8, 8, 0, 24, 0, 0, 0, 0), XBGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
60 | {FEATURES_PACK(8, 8, 8, 8, 0, 8, 0, 0, 0), ABGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
61 | {FEATURES_PACK(8, 8, 8, 0, 0, 8, 0, 0, 0), XBGR_8888, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
62 | {FEATURES_PACK(8, 8, 8, 8, 0, 0, 0, 0, 0), ABGR_8888, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
63 | {FEATURES_PACK(8, 8, 8, 0, 0, 0, 0, 0, 0), XBGR_8888, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
64 | |
65 | {FEATURES_PACK(8, 8, 8, 8, 24, 8, 1, 0, 0), ABGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
66 | {FEATURES_PACK(8, 8, 8, 0, 24, 8, 1, 0, 0), XBGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
67 | {FEATURES_PACK(8, 8, 8, 8, 24, 0, 1, 0, 0), ABGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
68 | {FEATURES_PACK(8, 8, 8, 0, 24, 0, 1, 0, 0), XBGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
69 | {FEATURES_PACK(8, 8, 8, 8, 0, 8, 1, 0, 0), ABGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
70 | {FEATURES_PACK(8, 8, 8, 0, 0, 8, 1, 0, 0), XBGR_8888, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
71 | {FEATURES_PACK(8, 8, 8, 8, 0, 0, 1, 0, 0), ABGR_8888, IMAGE_FORMAT_INVALID, COL_32_TLBD, IMAGE_FORMAT_INVALID}, |
72 | {FEATURES_PACK(8, 8, 8, 0, 0, 0, 1, 0, 0), XBGR_8888, IMAGE_FORMAT_INVALID, COL_32_TLBD, IMAGE_FORMAT_INVALID}, |
73 | |
74 | {FEATURES_PACK(5, 6, 5, 0, 24, 8, 0, 0, 0), RGB_565, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
75 | {FEATURES_PACK(5, 6, 5, 0, 24, 0, 0, 0, 0), RGB_565, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
76 | {FEATURES_PACK(5, 6, 5, 0, 0, 8, 0, 0, 0), RGB_565, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
77 | {FEATURES_PACK(5, 6, 5, 0, 0, 0, 0, 0, 0), RGB_565, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
78 | |
79 | {FEATURES_PACK(5, 6, 5, 0, 24, 8, 1, 0, 0), RGB_565, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
80 | {FEATURES_PACK(5, 6, 5, 0, 24, 0, 1, 0, 0), RGB_565, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
81 | {FEATURES_PACK(5, 6, 5, 0, 0, 8, 1, 0, 0), RGB_565, DEPTH_32_TLBD /*?*/, DEPTH_COL_64_TLBD, IMAGE_FORMAT_INVALID}, |
82 | {FEATURES_PACK(5, 6, 5, 0, 0, 0, 1, 0, 0), RGB_565, IMAGE_FORMAT_INVALID, COL_32_TLBD, IMAGE_FORMAT_INVALID}, |
83 | |
84 | #ifndef EGL_NO_ALPHA_MASK_CONFIGS |
85 | {FEATURES_PACK(8, 8, 8, 8, 0, 0, 0, 8, 0), ABGR_8888, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, A_8_RSO}, |
86 | {FEATURES_PACK(8, 8, 8, 0, 0, 0, 0, 8, 0), XBGR_8888, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, A_8_RSO}, |
87 | {FEATURES_PACK(5, 6, 5, 0, 0, 0, 0, 8, 0), RGB_565, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID, A_8_RSO}, |
88 | #endif |
89 | |
90 | {FEATURES_PACK(5, 6, 5, 0, 16, 0, 0, 0, 0), RGB_565, DEPTH_32_TLBD, IMAGE_FORMAT_INVALID, IMAGE_FORMAT_INVALID}, |
91 | |
92 | }; |
93 | |
94 | void egl_config_install_configs(int type) |
95 | { |
96 | uint32_t i; |
97 | for (i = 0; i != ARR_COUNT(formats); ++i) { |
98 | formats[i].color = (type == 0) ? |
99 | khrn_image_to_rso_format(formats[i].color) : |
100 | khrn_image_to_tf_format(formats[i].color); |
101 | } |
102 | } |
103 | |
104 | static bool bindable_rgb(FEATURES_T features); |
105 | static bool bindable_rgba(FEATURES_T features); |
106 | |
107 | #include "interface/khronos/egl/egl_client_config_cr.c" |
108 | |
109 | /* |
110 | KHRN_IMAGE_FORMAT_T egl_config_get_color_format(int id) |
111 | |
112 | Implementation notes: |
113 | |
114 | We may return an image format which cannot be rendered to. |
115 | |
116 | Preconditions: |
117 | |
118 | 0 <= id < EGL_MAX_CONFIGS |
119 | |
120 | Postconditions: |
121 | |
122 | Return value is a hardware framebuffer-supported uncompressed color KHRN_IMAGE_FORMAT_T |
123 | */ |
124 | |
125 | KHRN_IMAGE_FORMAT_T egl_config_get_color_format(int id) |
126 | { |
127 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
128 | |
129 | return formats[id].color; |
130 | } |
131 | |
132 | /* |
133 | KHRN_IMAGE_FORMAT_T egl_config_get_depth_format(int id) |
134 | |
135 | Preconditions: |
136 | |
137 | 0 <= id < EGL_MAX_CONFIGS |
138 | |
139 | Postconditions: |
140 | |
141 | Return value is a hardware framebuffer-supported depth KHRN_IMAGE_FORMAT_T or IMAGE_FORMAT_INVALID |
142 | */ |
143 | |
144 | KHRN_IMAGE_FORMAT_T egl_config_get_depth_format(int id) |
145 | { |
146 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
147 | |
148 | return formats[id].depth; |
149 | } |
150 | |
151 | /* |
152 | KHRN_IMAGE_FORMAT_T egl_config_get_mask_format(int id) |
153 | |
154 | Preconditions: |
155 | |
156 | 0 <= id < EGL_MAX_CONFIGS |
157 | |
158 | Postconditions: |
159 | |
160 | Return value is a hardware framebuffer-supported mask KHRN_IMAGE_FORMAT_T or IMAGE_FORMAT_INVALID |
161 | */ |
162 | |
163 | KHRN_IMAGE_FORMAT_T egl_config_get_mask_format(int id) |
164 | { |
165 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
166 | |
167 | return formats[id].mask; |
168 | } |
169 | |
170 | /* |
171 | KHRN_IMAGE_FORMAT_T egl_config_get_multisample_format(int id) |
172 | |
173 | Preconditions: |
174 | |
175 | 0 <= id < EGL_MAX_CONFIGS |
176 | |
177 | Postconditions: |
178 | |
179 | Return value is a hardware framebuffer-supported multisample color format or IMAGE_FORMAT_INVALID |
180 | */ |
181 | |
182 | KHRN_IMAGE_FORMAT_T egl_config_get_multisample_format(int id) |
183 | { |
184 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
185 | |
186 | return formats[id].multisample; |
187 | } |
188 | |
189 | /* |
190 | bool egl_config_get_multisample(int id) |
191 | |
192 | Preconditions: |
193 | |
194 | 0 <= id < EGL_MAX_CONFIGS |
195 | |
196 | Postconditions: |
197 | |
198 | - |
199 | */ |
200 | |
201 | bool egl_config_get_multisample(int id) |
202 | { |
203 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
204 | |
205 | return FEATURES_UNPACK_MULTI(formats[id].features); |
206 | } |
207 | |
208 | /* |
209 | bool bindable_rgb(FEATURES_T features) |
210 | bool bindable_rgba(FEATURES_T features) |
211 | |
212 | Preconditions: |
213 | |
214 | features is a valid FEATURES_T |
215 | |
216 | Postconditions: |
217 | |
218 | - |
219 | */ |
220 | |
221 | static bool bindable_rgb(FEATURES_T features) |
222 | { |
223 | return !FEATURES_UNPACK_MULTI(features) && !FEATURES_UNPACK_ALPHA(features); |
224 | } |
225 | |
226 | static bool bindable_rgba(FEATURES_T features) |
227 | { |
228 | return !FEATURES_UNPACK_MULTI(features); |
229 | } |
230 | |
231 | bool egl_config_bindable(int id, EGLenum format) |
232 | { |
233 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
234 | switch (format) { |
235 | case EGL_NO_TEXTURE: |
236 | return true; |
237 | case EGL_TEXTURE_RGB: |
238 | return bindable_rgb(formats[id].features); |
239 | case EGL_TEXTURE_RGBA: |
240 | return bindable_rgba(formats[id].features); |
241 | default: |
242 | UNREACHABLE(); |
243 | return false; |
244 | } |
245 | } |
246 | |
247 | /* |
248 | bool egl_config_match_pixmap_info(int id, KHRN_IMAGE_WRAP_T *image) |
249 | |
250 | TODO: decide how tolerant we should be when matching to native pixmaps. |
251 | At present they match if the red, green, blue and alpha channels |
252 | all have the same bit depths. |
253 | |
254 | Preconditions: |
255 | |
256 | 0 <= id < EGL_MAX_CONFIGS |
257 | image is a pointer to a valid KHRN_IMAGE_WRAP_T, possibly with null data pointer |
258 | match is a bitmask which is a subset of PLATFORM_PIXMAP_MATCH_NONRENDERABLE|PLATFORM_PIXMAP_MATCH_RENDERABLE |
259 | |
260 | Postconditions: |
261 | |
262 | - |
263 | */ |
264 | |
265 | bool egl_config_match_pixmap_info(int id, KHRN_IMAGE_WRAP_T *image) |
266 | { |
267 | FEATURES_T features = formats[id].features; |
268 | KHRN_IMAGE_FORMAT_T format = image->format; |
269 | |
270 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
271 | |
272 | return |
273 | khrn_image_get_red_size(format) == FEATURES_UNPACK_RED(features) && |
274 | khrn_image_get_green_size(format) == FEATURES_UNPACK_GREEN(features) && |
275 | khrn_image_get_blue_size(format) == FEATURES_UNPACK_BLUE(features) && |
276 | khrn_image_get_alpha_size(format) == FEATURES_UNPACK_ALPHA(features); |
277 | } |
278 | |
279 | /* |
280 | uint32_t egl_config_get_api_support(int id) |
281 | |
282 | Preconditions: |
283 | |
284 | 0 <= id < EGL_MAX_CONFIGS |
285 | |
286 | Postconditions: |
287 | |
288 | Result is a bitmap which is a subset of (EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT) |
289 | */ |
290 | |
291 | uint32_t egl_config_get_api_support(int id) |
292 | { |
293 | /* no configs are api-specific (ie if you can use a config with gl, you can |
294 | * use it with vg too, and vice-versa). however, some configs have color |
295 | * buffer formats that are incompatible with the hardware, and so can't be |
296 | * used with any api. such configs may still be useful eg with the surface |
297 | * locking extension... */ |
298 | |
299 | #if EGL_KHR_lock_surface |
300 | /* to reduce confusion, just say no for all lockable configs. this #if can be |
301 | * safely commented out -- the color buffer format check below will catch |
302 | * lockable configs we actually can't use */ |
303 | if (egl_config_is_lockable(id)) { |
304 | return 0; |
305 | } |
306 | #endif |
307 | |
308 | switch (egl_config_get_color_format(id)) { |
309 | case ABGR_8888_RSO: case ABGR_8888_TF: case ABGR_8888_LT: |
310 | case XBGR_8888_RSO: case XBGR_8888_TF: case XBGR_8888_LT: |
311 | case ARGB_8888_RSO: case ARGB_8888_TF: case ARGB_8888_LT: |
312 | case XRGB_8888_RSO: case XRGB_8888_TF: case XRGB_8888_LT: |
313 | case RGB_565_RSO: case RGB_565_TF: case RGB_565_LT: |
314 | #ifndef NO_OPENVG |
315 | return (uint32_t)(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT); |
316 | #else |
317 | return (uint32_t)(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); |
318 | #endif |
319 | default: |
320 | break; |
321 | } |
322 | return 0; |
323 | } |
324 | |
325 | /* |
326 | uint32_t egl_config_get_api_conformance(int id) |
327 | |
328 | Preconditions: |
329 | |
330 | 0 <= id < EGL_MAX_CONFIGS |
331 | |
332 | Postconditions: |
333 | |
334 | Result is a bitmap which is a subset of (EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT) |
335 | */ |
336 | |
337 | uint32_t egl_config_get_api_conformance(int id) |
338 | { |
339 | /* vg doesn't support multisampled surfaces properly */ |
340 | return egl_config_get_api_support(id) & ~(FEATURES_UNPACK_MULTI(formats[id].features) ? EGL_OPENVG_BIT : 0); |
341 | } |
342 | |
343 | bool egl_config_bpps_match(int id0, int id1) /* bpps of all buffers match */ |
344 | { |
345 | FEATURES_T config0 = formats[id0].features; |
346 | FEATURES_T config1 = formats[id1].features; |
347 | |
348 | return |
349 | FEATURES_UNPACK_RED(config0) == FEATURES_UNPACK_RED(config1) && |
350 | FEATURES_UNPACK_GREEN(config0) == FEATURES_UNPACK_GREEN(config1) && |
351 | FEATURES_UNPACK_BLUE(config0) == FEATURES_UNPACK_BLUE(config1) && |
352 | FEATURES_UNPACK_ALPHA(config0) == FEATURES_UNPACK_ALPHA(config1) && |
353 | FEATURES_UNPACK_DEPTH(config0) == FEATURES_UNPACK_DEPTH(config1) && |
354 | FEATURES_UNPACK_STENCIL(config0) == FEATURES_UNPACK_STENCIL(config1) && |
355 | FEATURES_UNPACK_MASK(config0) == FEATURES_UNPACK_MASK(config1); |
356 | } |
357 | |
358 | #if EGL_KHR_lock_surface |
359 | |
360 | /* |
361 | KHRN_IMAGE_FORMAT_T egl_config_get_mapped_format(int id) |
362 | |
363 | Returns the format of the mapped buffer when an EGL surface is locked. |
364 | |
365 | Preconditions: |
366 | |
367 | 0 <= id < EGL_MAX_CONFIGS |
368 | egl_config_is_lockable(id) |
369 | |
370 | Postconditions: |
371 | |
372 | Return value is RGB_565_RSO or ARGB_8888_RSO |
373 | */ |
374 | |
375 | KHRN_IMAGE_FORMAT_T egl_config_get_mapped_format(int id) |
376 | { |
377 | KHRN_IMAGE_FORMAT_T result; |
378 | |
379 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
380 | vcos_assert(FEATURES_UNPACK_LOCKABLE(formats[id].features)); |
381 | |
382 | /* If any t-format images were lockable, we would convert to raster format here */ |
383 | result = egl_config_get_color_format(id); |
384 | vcos_assert(khrn_image_is_rso(result)); |
385 | return result; |
386 | } |
387 | |
388 | /* |
389 | bool egl_config_is_lockable(int id) |
390 | |
391 | Preconditions: |
392 | |
393 | 0 <= id < EGL_MAX_CONFIGS |
394 | |
395 | Postconditions: |
396 | |
397 | - |
398 | */ |
399 | |
400 | bool egl_config_is_lockable(int id) |
401 | { |
402 | vcos_assert(id >= 0 && id < EGL_MAX_CONFIGS); |
403 | return FEATURES_UNPACK_LOCKABLE(formats[id].features); |
404 | } |
405 | |
406 | #endif |
407 | |
408 | |
409 | |
410 | |
411 | |