egl/main: Add bits for EGL_KHR_mutable_render_buffer
[mesa.git] / src / egl / main / eglsurface.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31 /**
32 * Surface-related functions.
33 */
34
35
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "egldisplay.h"
40 #include "egldriver.h"
41 #include "eglcontext.h"
42 #include "eglconfig.h"
43 #include "eglcurrent.h"
44 #include "egllog.h"
45 #include "eglsurface.h"
46
47
48 /**
49 * Parse the list of surface attributes and return the proper error code.
50 */
51 static EGLint
52 _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
53 {
54 _EGLDisplay *dpy = surf->Resource.Display;
55 EGLint type = surf->Type;
56 EGLint texture_type = EGL_PBUFFER_BIT;
57 EGLint i, err = EGL_SUCCESS;
58 EGLint attr = EGL_NONE;
59 EGLint val = EGL_NONE;
60
61 if (!attrib_list)
62 return EGL_SUCCESS;
63
64 if (dpy->Extensions.NOK_texture_from_pixmap)
65 texture_type |= EGL_PIXMAP_BIT;
66
67 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
68 attr = attrib_list[i++];
69 val = attrib_list[i];
70
71 switch (attr) {
72 /* common attributes */
73 case EGL_GL_COLORSPACE_KHR:
74 if (!dpy->Extensions.KHR_gl_colorspace) {
75 err = EGL_BAD_ATTRIBUTE;
76 break;
77 }
78 switch (val) {
79 case EGL_GL_COLORSPACE_SRGB_KHR:
80 case EGL_GL_COLORSPACE_LINEAR_KHR:
81 break;
82 default:
83 err = EGL_BAD_ATTRIBUTE;
84 }
85 if (err != EGL_SUCCESS)
86 break;
87 surf->GLColorspace = val;
88 break;
89 case EGL_VG_COLORSPACE:
90 switch (val) {
91 case EGL_VG_COLORSPACE_sRGB:
92 case EGL_VG_COLORSPACE_LINEAR:
93 break;
94 default:
95 err = EGL_BAD_ATTRIBUTE;
96 break;
97 }
98 if (err != EGL_SUCCESS)
99 break;
100 surf->VGColorspace = val;
101 break;
102 case EGL_VG_ALPHA_FORMAT:
103 switch (val) {
104 case EGL_VG_ALPHA_FORMAT_NONPRE:
105 case EGL_VG_ALPHA_FORMAT_PRE:
106 break;
107 default:
108 err = EGL_BAD_ATTRIBUTE;
109 break;
110 }
111 if (err != EGL_SUCCESS)
112 break;
113 surf->VGAlphaFormat = val;
114 break;
115 /* window surface attributes */
116 case EGL_RENDER_BUFFER:
117 if (type != EGL_WINDOW_BIT) {
118 err = EGL_BAD_ATTRIBUTE;
119 break;
120 }
121 if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
122 err = EGL_BAD_ATTRIBUTE;
123 break;
124 }
125 surf->RequestedRenderBuffer = val;
126 if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
127 /* Unlike normal EGLSurfaces, one with a mutable render buffer
128 * uses the application-chosen render buffer.
129 */
130 surf->ActiveRenderBuffer = val;
131 }
132 break;
133 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
134 if (!dpy->Extensions.NV_post_sub_buffer ||
135 type != EGL_WINDOW_BIT) {
136 err = EGL_BAD_ATTRIBUTE;
137 break;
138 }
139 if (val != EGL_TRUE && val != EGL_FALSE) {
140 err = EGL_BAD_PARAMETER;
141 break;
142 }
143 surf->PostSubBufferSupportedNV = val;
144 break;
145 /* pbuffer surface attributes */
146 case EGL_WIDTH:
147 if (type != EGL_PBUFFER_BIT) {
148 err = EGL_BAD_ATTRIBUTE;
149 break;
150 }
151 if (val < 0) {
152 err = EGL_BAD_PARAMETER;
153 break;
154 }
155 surf->Width = val;
156 break;
157 case EGL_HEIGHT:
158 if (type != EGL_PBUFFER_BIT) {
159 err = EGL_BAD_ATTRIBUTE;
160 break;
161 }
162 if (val < 0) {
163 err = EGL_BAD_PARAMETER;
164 break;
165 }
166 surf->Height = val;
167 break;
168 case EGL_LARGEST_PBUFFER:
169 if (type != EGL_PBUFFER_BIT) {
170 err = EGL_BAD_ATTRIBUTE;
171 break;
172 }
173 surf->LargestPbuffer = !!val;
174 break;
175 /* for eglBindTexImage */
176 case EGL_TEXTURE_FORMAT:
177 if (!(type & texture_type)) {
178 err = EGL_BAD_ATTRIBUTE;
179 break;
180 }
181
182 switch (val) {
183 case EGL_TEXTURE_RGB:
184 case EGL_TEXTURE_RGBA:
185 case EGL_NO_TEXTURE:
186 break;
187 default:
188 err = EGL_BAD_ATTRIBUTE;
189 break;
190 }
191 if (err != EGL_SUCCESS)
192 break;
193 surf->TextureFormat = val;
194 break;
195 case EGL_TEXTURE_TARGET:
196 if (!(type & texture_type)) {
197 err = EGL_BAD_ATTRIBUTE;
198 break;
199 }
200
201 switch (val) {
202 case EGL_TEXTURE_2D:
203 case EGL_NO_TEXTURE:
204 break;
205 default:
206 err = EGL_BAD_ATTRIBUTE;
207 break;
208 }
209 if (err != EGL_SUCCESS)
210 break;
211 surf->TextureTarget = val;
212 break;
213 case EGL_MIPMAP_TEXTURE:
214 if (!(type & texture_type)) {
215 err = EGL_BAD_ATTRIBUTE;
216 break;
217 }
218 surf->MipmapTexture = !!val;
219 break;
220 /* no pixmap surface specific attributes */
221 default:
222 err = EGL_BAD_ATTRIBUTE;
223 break;
224 }
225
226 if (err != EGL_SUCCESS)
227 break;
228 }
229
230 if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
231 if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) ||
232 (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) {
233 attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT;
234 err = EGL_BAD_MATCH;
235 }
236 }
237
238 if (err != EGL_SUCCESS)
239 _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
240
241 return err;
242 }
243
244
245 /**
246 * Do error check on parameters and initialize the given _EGLSurface object.
247 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
248 */
249 EGLBoolean
250 _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
251 _EGLConfig *conf, const EGLint *attrib_list)
252 {
253 const char *func;
254 EGLint renderBuffer = EGL_BACK_BUFFER;
255 EGLint swapBehavior = EGL_BUFFER_DESTROYED;
256 EGLint err;
257
258 /* Swap behavior can be preserved only if config supports this. */
259 if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
260 swapBehavior = EGL_BUFFER_PRESERVED;
261
262 switch (type) {
263 case EGL_WINDOW_BIT:
264 func = "eglCreateWindowSurface";
265 swapBehavior = EGL_BUFFER_DESTROYED;
266 break;
267 case EGL_PIXMAP_BIT:
268 func = "eglCreatePixmapSurface";
269 renderBuffer = EGL_SINGLE_BUFFER;
270 break;
271 case EGL_PBUFFER_BIT:
272 func = "eglCreatePBufferSurface";
273 break;
274 default:
275 _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
276 return EGL_FALSE;
277 }
278
279 if ((conf->SurfaceType & type) == 0)
280 /* The config can't be used to create a surface of this type */
281 return _eglError(EGL_BAD_MATCH, func);
282
283 _eglInitResource(&surf->Resource, sizeof(*surf), dpy);
284 surf->Type = type;
285 surf->Config = conf;
286 surf->Lost = EGL_FALSE;
287
288 surf->Width = 0;
289 surf->Height = 0;
290 surf->TextureFormat = EGL_NO_TEXTURE;
291 surf->TextureTarget = EGL_NO_TEXTURE;
292 surf->MipmapTexture = EGL_FALSE;
293 surf->LargestPbuffer = EGL_FALSE;
294 surf->RequestedRenderBuffer = renderBuffer;
295 surf->ActiveRenderBuffer = renderBuffer;
296 surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
297 surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
298 surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
299
300 surf->MipmapLevel = 0;
301 surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
302 surf->SwapBehavior = swapBehavior;
303
304 surf->HorizontalResolution = EGL_UNKNOWN;
305 surf->VerticalResolution = EGL_UNKNOWN;
306 surf->AspectRatio = EGL_UNKNOWN;
307
308 surf->PostSubBufferSupportedNV = EGL_FALSE;
309 surf->SetDamageRegionCalled = EGL_FALSE;
310 surf->BufferAgeRead = EGL_FALSE;
311
312 /* the default swap interval is 1 */
313 surf->SwapInterval = 1;
314
315 err = _eglParseSurfaceAttribList(surf, attrib_list);
316 if (err != EGL_SUCCESS)
317 return _eglError(err, func);
318
319 /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
320 if (surf->LargestPbuffer) {
321 surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
322 surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
323 }
324
325 return EGL_TRUE;
326 }
327
328
329 EGLBoolean
330 _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
331 EGLint attribute, EGLint *value)
332 {
333 switch (attribute) {
334 case EGL_WIDTH:
335 *value = surface->Width;
336 break;
337 case EGL_HEIGHT:
338 *value = surface->Height;
339 break;
340 case EGL_CONFIG_ID:
341 *value = surface->Config->ConfigID;
342 break;
343 case EGL_LARGEST_PBUFFER:
344 if (surface->Type == EGL_PBUFFER_BIT)
345 *value = surface->LargestPbuffer;
346 break;
347 case EGL_TEXTURE_FORMAT:
348 /* texture attributes: only for pbuffers, no error otherwise */
349 if (surface->Type == EGL_PBUFFER_BIT)
350 *value = surface->TextureFormat;
351 break;
352 case EGL_TEXTURE_TARGET:
353 if (surface->Type == EGL_PBUFFER_BIT)
354 *value = surface->TextureTarget;
355 break;
356 case EGL_MIPMAP_TEXTURE:
357 if (surface->Type == EGL_PBUFFER_BIT)
358 *value = surface->MipmapTexture;
359 break;
360 case EGL_MIPMAP_LEVEL:
361 if (surface->Type == EGL_PBUFFER_BIT)
362 *value = surface->MipmapLevel;
363 break;
364 case EGL_SWAP_BEHAVIOR:
365 *value = surface->SwapBehavior;
366 break;
367 case EGL_RENDER_BUFFER:
368 /* From the EGL_KHR_mutable_render_buffer spec (v12):
369 *
370 * Querying EGL_RENDER_BUFFER returns the buffer which client API
371 * rendering is requested to use. For a window surface, this is the
372 * attribute value specified when the surface was created or last set
373 * via eglSurfaceAttrib.
374 *
375 * In other words, querying a window surface returns the value most
376 * recently *requested* by the user.
377 *
378 * The paragraph continues in the EGL 1.5 spec (2014.08.27):
379 *
380 * For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
381 * surface, it is always EGL_SINGLE_BUFFER . To determine the actual
382 * buffer being rendered to by a context, call eglQueryContext.
383 */
384 switch (surface->Type) {
385 default:
386 unreachable("bad EGLSurface type");
387 case EGL_WINDOW_BIT:
388 *value = surface->RequestedRenderBuffer;
389 break;
390 case EGL_PBUFFER_BIT:
391 *value = EGL_BACK_BUFFER;
392 break;
393 case EGL_PIXMAP_BIT:
394 *value = EGL_SINGLE_BUFFER;
395 break;
396 }
397 break;
398 case EGL_PIXEL_ASPECT_RATIO:
399 *value = surface->AspectRatio;
400 break;
401 case EGL_HORIZONTAL_RESOLUTION:
402 *value = surface->HorizontalResolution;
403 break;
404 case EGL_VERTICAL_RESOLUTION:
405 *value = surface->VerticalResolution;
406 break;
407 case EGL_MULTISAMPLE_RESOLVE:
408 *value = surface->MultisampleResolve;
409 break;
410 case EGL_VG_ALPHA_FORMAT:
411 *value = surface->VGAlphaFormat;
412 break;
413 case EGL_VG_COLORSPACE:
414 *value = surface->VGColorspace;
415 break;
416 case EGL_GL_COLORSPACE_KHR:
417 if (!dpy->Extensions.KHR_gl_colorspace)
418 return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
419
420 *value = surface->GLColorspace;
421 break;
422 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
423 *value = surface->PostSubBufferSupportedNV;
424 break;
425 case EGL_BUFFER_AGE_EXT:
426 if (!dpy->Extensions.EXT_buffer_age)
427 return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
428
429 _EGLContext *ctx = _eglGetCurrentContext();
430 EGLint result = drv->API.QueryBufferAge(drv, dpy, surface);
431 /* error happened */
432 if (result < 0)
433 return EGL_FALSE;
434 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
435 ctx->DrawSurface != surface)
436 return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
437
438 *value = result;
439 surface->BufferAgeRead = EGL_TRUE;
440 break;
441 default:
442 return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
443 }
444
445 return EGL_TRUE;
446 }
447
448
449 /**
450 * Default fallback routine - drivers might override this.
451 */
452 EGLBoolean
453 _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
454 EGLint attribute, EGLint value)
455 {
456 EGLint confval;
457 EGLint err = EGL_SUCCESS;
458 EGLint all_es_bits = EGL_OPENGL_ES_BIT |
459 EGL_OPENGL_ES2_BIT |
460 EGL_OPENGL_ES3_BIT_KHR;
461
462 switch (attribute) {
463 case EGL_MIPMAP_LEVEL:
464 confval = surface->Config->RenderableType;
465 if (!(confval & all_es_bits)) {
466 err = EGL_BAD_PARAMETER;
467 break;
468 }
469 surface->MipmapLevel = value;
470 break;
471 case EGL_MULTISAMPLE_RESOLVE:
472 switch (value) {
473 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
474 break;
475 case EGL_MULTISAMPLE_RESOLVE_BOX:
476 confval = surface->Config->SurfaceType;
477 if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
478 err = EGL_BAD_MATCH;
479 break;
480 default:
481 err = EGL_BAD_ATTRIBUTE;
482 break;
483 }
484 if (err != EGL_SUCCESS)
485 break;
486 surface->MultisampleResolve = value;
487 break;
488 case EGL_RENDER_BUFFER:
489 if (!dpy->Extensions.KHR_mutable_render_buffer) {
490 err = EGL_BAD_ATTRIBUTE;
491 break;
492 }
493
494 if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
495 err = EGL_BAD_PARAMETER;
496 break;
497 }
498
499 /* From the EGL_KHR_mutable_render_buffer spec (v12):
500 *
501 * If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
502 * attribute of the EGLConfig used to create surface does not contain
503 * EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
504 * generated [...].
505 */
506 if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
507 err = EGL_BAD_MATCH;
508 break;
509 }
510
511 surface->RequestedRenderBuffer = value;
512 break;
513 case EGL_SWAP_BEHAVIOR:
514 switch (value) {
515 case EGL_BUFFER_DESTROYED:
516 break;
517 case EGL_BUFFER_PRESERVED:
518 confval = surface->Config->SurfaceType;
519 if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
520 err = EGL_BAD_MATCH;
521 break;
522 default:
523 err = EGL_BAD_ATTRIBUTE;
524 break;
525 }
526 if (err != EGL_SUCCESS)
527 break;
528 surface->SwapBehavior = value;
529 break;
530 default:
531 err = EGL_BAD_ATTRIBUTE;
532 break;
533 }
534
535 if (err != EGL_SUCCESS)
536 return _eglError(err, "eglSurfaceAttrib");
537 return EGL_TRUE;
538 }
539
540
541 EGLBoolean
542 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
543 EGLint buffer)
544 {
545 EGLint texture_type = EGL_PBUFFER_BIT;
546
547 /* Just do basic error checking and return success/fail.
548 * Drivers must implement the real stuff.
549 */
550
551 if (dpy->Extensions.NOK_texture_from_pixmap)
552 texture_type |= EGL_PIXMAP_BIT;
553
554 if (!(surface->Type & texture_type))
555 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
556
557 if (surface->TextureFormat == EGL_NO_TEXTURE)
558 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
559
560 if (surface->TextureTarget == EGL_NO_TEXTURE)
561 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
562
563 if (buffer != EGL_BACK_BUFFER)
564 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
565
566 surface->BoundToTexture = EGL_TRUE;
567
568 return EGL_TRUE;
569 }
570
571 EGLBoolean
572 _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
573 EGLint buffer)
574 {
575 /* Just do basic error checking and return success/fail.
576 * Drivers must implement the real stuff.
577 */
578
579 EGLint texture_type = EGL_PBUFFER_BIT;
580
581 if (surf == EGL_NO_SURFACE)
582 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
583
584 if (!surf->BoundToTexture)
585 {
586 /* Not an error, simply nothing to do */
587 return EGL_TRUE;
588 }
589
590 if (surf->TextureFormat == EGL_NO_TEXTURE)
591 return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
592
593 if (buffer != EGL_BACK_BUFFER)
594 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
595
596 if (dpy->Extensions.NOK_texture_from_pixmap)
597 texture_type |= EGL_PIXMAP_BIT;
598
599 if (!(surf->Type & texture_type))
600 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
601
602 surf->BoundToTexture = EGL_FALSE;
603
604 return EGL_TRUE;
605 }
606
607
608 EGLBoolean
609 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
610 EGLint interval)
611 {
612 return EGL_TRUE;
613 }
614
615 EGLBoolean
616 _eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
617 {
618 return surf->Type == EGL_WINDOW_BIT &&
619 surf->Config &&
620 (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
621 }
622
623 EGLBoolean
624 _eglSurfaceInSharedBufferMode(_EGLSurface *surf)
625 {
626 return _eglSurfaceHasMutableRenderBuffer(surf) &&
627 surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
628 }