eglsurface.c revision b8e80941
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 "egldefines.h"
40#include "egldisplay.h"
41#include "egldriver.h"
42#include "eglcontext.h"
43#include "eglconfig.h"
44#include "eglcurrent.h"
45#include "egllog.h"
46#include "eglsurface.h"
47
48#include "util/macros.h"
49
50/**
51 * Parse the list of surface attributes and return the proper error code.
52 */
53static EGLint
54_eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
55{
56   _EGLDisplay *disp = surf->Resource.Display;
57   EGLint type = surf->Type;
58   EGLint texture_type = EGL_PBUFFER_BIT;
59   EGLint i, err = EGL_SUCCESS;
60   EGLint attr = EGL_NONE;
61   EGLint val = EGL_NONE;
62
63   if (!attrib_list)
64      return EGL_SUCCESS;
65
66   if (disp->Extensions.NOK_texture_from_pixmap)
67      texture_type |= EGL_PIXMAP_BIT;
68
69   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
70      attr = attrib_list[i++];
71      val = attrib_list[i];
72
73      switch (attr) {
74      /* common attributes */
75      case EGL_GL_COLORSPACE_KHR:
76         if (!disp->Extensions.KHR_gl_colorspace) {
77            err = EGL_BAD_ATTRIBUTE;
78            break;
79         }
80         switch (val) {
81         case EGL_GL_COLORSPACE_SRGB_KHR:
82         case EGL_GL_COLORSPACE_LINEAR_KHR:
83            break;
84         default:
85            err = EGL_BAD_ATTRIBUTE;
86         }
87         if (err != EGL_SUCCESS)
88            break;
89         surf->GLColorspace = val;
90         break;
91      case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
92         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
93            err = EGL_BAD_ATTRIBUTE;
94            break;
95         }
96         surf->HdrMetadata.display_primary_r.x = val;
97         break;
98      case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
99         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
100            err = EGL_BAD_ATTRIBUTE;
101            break;
102         }
103         surf->HdrMetadata.display_primary_r.y = val;
104         break;
105      case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
106         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
107            err = EGL_BAD_ATTRIBUTE;
108            break;
109         }
110         surf->HdrMetadata.display_primary_g.x = val;
111         break;
112      case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
113         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
114            err = EGL_BAD_ATTRIBUTE;
115            break;
116         }
117         surf->HdrMetadata.display_primary_g.y = val;
118         break;
119      case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
120         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
121            err = EGL_BAD_ATTRIBUTE;
122            break;
123         }
124         surf->HdrMetadata.display_primary_b.x = val;
125         break;
126      case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
127         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
128            err = EGL_BAD_ATTRIBUTE;
129            break;
130         }
131         surf->HdrMetadata.display_primary_b.y = val;
132         break;
133      case EGL_SMPTE2086_WHITE_POINT_X_EXT:
134         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
135            err = EGL_BAD_ATTRIBUTE;
136            break;
137         }
138         surf->HdrMetadata.white_point.x = val;
139         break;
140      case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
141         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
142            err = EGL_BAD_ATTRIBUTE;
143            break;
144         }
145         surf->HdrMetadata.white_point.y = val;
146         break;
147      case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
148         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
149            err = EGL_BAD_ATTRIBUTE;
150            break;
151         }
152         surf->HdrMetadata.max_luminance = val;
153         break;
154      case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
155         if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
156            err = EGL_BAD_ATTRIBUTE;
157            break;
158         }
159         surf->HdrMetadata.min_luminance = val;
160         break;
161      case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
162         if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
163            err = EGL_BAD_ATTRIBUTE;
164            break;
165         }
166         surf->HdrMetadata.max_cll = val;
167         break;
168      case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
169         if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
170            err = EGL_BAD_ATTRIBUTE;
171            break;
172         }
173         surf->HdrMetadata.max_fall = val;
174         break;
175      case EGL_VG_COLORSPACE:
176         switch (val) {
177         case EGL_VG_COLORSPACE_sRGB:
178         case EGL_VG_COLORSPACE_LINEAR:
179            break;
180         default:
181            err = EGL_BAD_ATTRIBUTE;
182            break;
183         }
184         if (err != EGL_SUCCESS)
185            break;
186         surf->VGColorspace = val;
187         break;
188      case EGL_VG_ALPHA_FORMAT:
189         switch (val) {
190         case EGL_VG_ALPHA_FORMAT_NONPRE:
191         case EGL_VG_ALPHA_FORMAT_PRE:
192            break;
193         default:
194            err = EGL_BAD_ATTRIBUTE;
195            break;
196         }
197         if (err != EGL_SUCCESS)
198            break;
199         surf->VGAlphaFormat = val;
200         break;
201      /* window surface attributes */
202      case EGL_RENDER_BUFFER:
203         if (type != EGL_WINDOW_BIT) {
204            err = EGL_BAD_ATTRIBUTE;
205            break;
206         }
207         if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
208            err = EGL_BAD_ATTRIBUTE;
209            break;
210         }
211         surf->RequestedRenderBuffer = val;
212         if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
213            /* Unlike normal EGLSurfaces, one with a mutable render buffer
214             * uses the application-chosen render buffer.
215             */
216            surf->ActiveRenderBuffer = val;
217         }
218         break;
219      case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
220         if (!disp->Extensions.NV_post_sub_buffer ||
221             type != EGL_WINDOW_BIT) {
222            err = EGL_BAD_ATTRIBUTE;
223            break;
224         }
225         if (val != EGL_TRUE && val != EGL_FALSE) {
226            err = EGL_BAD_PARAMETER;
227            break;
228         }
229         surf->PostSubBufferSupportedNV = val;
230         break;
231      /* pbuffer surface attributes */
232      case EGL_WIDTH:
233         if (type != EGL_PBUFFER_BIT) {
234            err = EGL_BAD_ATTRIBUTE;
235            break;
236         }
237         if (val < 0) {
238            err = EGL_BAD_PARAMETER;
239            break;
240         }
241         surf->Width = val;
242         break;
243      case EGL_HEIGHT:
244         if (type != EGL_PBUFFER_BIT) {
245            err = EGL_BAD_ATTRIBUTE;
246            break;
247         }
248         if (val < 0) {
249            err = EGL_BAD_PARAMETER;
250            break;
251         }
252         surf->Height = val;
253         break;
254      case EGL_LARGEST_PBUFFER:
255         if (type != EGL_PBUFFER_BIT) {
256            err = EGL_BAD_ATTRIBUTE;
257            break;
258         }
259         surf->LargestPbuffer = !!val;
260         break;
261      /* for eglBindTexImage */
262      case EGL_TEXTURE_FORMAT:
263         if (!(type & texture_type)) {
264            err = EGL_BAD_ATTRIBUTE;
265            break;
266         }
267
268         switch (val) {
269         case EGL_TEXTURE_RGB:
270         case EGL_TEXTURE_RGBA:
271         case EGL_NO_TEXTURE:
272            break;
273         default:
274            err = EGL_BAD_ATTRIBUTE;
275            break;
276         }
277         if (err != EGL_SUCCESS)
278            break;
279         surf->TextureFormat = val;
280         break;
281      case EGL_TEXTURE_TARGET:
282         if (!(type & texture_type)) {
283            err = EGL_BAD_ATTRIBUTE;
284            break;
285         }
286
287         switch (val) {
288         case EGL_TEXTURE_2D:
289         case EGL_NO_TEXTURE:
290            break;
291         default:
292            err = EGL_BAD_ATTRIBUTE;
293            break;
294         }
295         if (err != EGL_SUCCESS)
296            break;
297         surf->TextureTarget = val;
298         break;
299      case EGL_MIPMAP_TEXTURE:
300         if (!(type & texture_type)) {
301            err = EGL_BAD_ATTRIBUTE;
302            break;
303         }
304         surf->MipmapTexture = !!val;
305         break;
306      /* no pixmap surface specific attributes */
307      default:
308         err = EGL_BAD_ATTRIBUTE;
309         break;
310      }
311
312      if (err != EGL_SUCCESS)
313         break;
314   }
315
316   if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
317      if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) ||
318          (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) {
319         attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT;
320         err = EGL_BAD_MATCH;
321      }
322   }
323
324   if (err != EGL_SUCCESS)
325      _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
326
327   return err;
328}
329
330
331/**
332 * Do error check on parameters and initialize the given _EGLSurface object.
333 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
334 */
335EGLBoolean
336_eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
337                _EGLConfig *conf, const EGLint *attrib_list)
338{
339   const char *func;
340   EGLint renderBuffer = EGL_BACK_BUFFER;
341   EGLint swapBehavior = EGL_BUFFER_DESTROYED;
342   EGLint err;
343
344   /* Swap behavior can be preserved only if config supports this. */
345   if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
346      swapBehavior = EGL_BUFFER_PRESERVED;
347
348   switch (type) {
349   case EGL_WINDOW_BIT:
350      func = "eglCreateWindowSurface";
351      swapBehavior = EGL_BUFFER_DESTROYED;
352      break;
353   case EGL_PIXMAP_BIT:
354      func = "eglCreatePixmapSurface";
355      renderBuffer = EGL_SINGLE_BUFFER;
356      break;
357   case EGL_PBUFFER_BIT:
358      func = "eglCreatePBufferSurface";
359      break;
360   default:
361      _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
362      return EGL_FALSE;
363   }
364
365   if ((conf->SurfaceType & type) == 0)
366      /* The config can't be used to create a surface of this type */
367      return _eglError(EGL_BAD_MATCH, func);
368
369   _eglInitResource(&surf->Resource, sizeof(*surf), disp);
370   surf->Type = type;
371   surf->Config = conf;
372   surf->Lost = EGL_FALSE;
373
374   surf->Width = 0;
375   surf->Height = 0;
376   surf->TextureFormat = EGL_NO_TEXTURE;
377   surf->TextureTarget = EGL_NO_TEXTURE;
378   surf->MipmapTexture = EGL_FALSE;
379   surf->LargestPbuffer = EGL_FALSE;
380   surf->RequestedRenderBuffer = renderBuffer;
381   surf->ActiveRenderBuffer = renderBuffer;
382   surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
383   surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
384   surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
385
386   surf->MipmapLevel = 0;
387   surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
388   surf->SwapBehavior = swapBehavior;
389
390   surf->HorizontalResolution = EGL_UNKNOWN;
391   surf->VerticalResolution = EGL_UNKNOWN;
392   surf->AspectRatio = EGL_UNKNOWN;
393
394   surf->PostSubBufferSupportedNV = EGL_FALSE;
395   surf->SetDamageRegionCalled = EGL_FALSE;
396   surf->BufferAgeRead = EGL_FALSE;
397
398   /* the default swap interval is 1 */
399   surf->SwapInterval = 1;
400
401   surf->HdrMetadata.display_primary_r.x = EGL_DONT_CARE;
402   surf->HdrMetadata.display_primary_r.y = EGL_DONT_CARE;
403   surf->HdrMetadata.display_primary_g.x = EGL_DONT_CARE;
404   surf->HdrMetadata.display_primary_g.y = EGL_DONT_CARE;
405   surf->HdrMetadata.display_primary_b.x = EGL_DONT_CARE;
406   surf->HdrMetadata.display_primary_b.y = EGL_DONT_CARE;
407   surf->HdrMetadata.white_point.x = EGL_DONT_CARE;
408   surf->HdrMetadata.white_point.y = EGL_DONT_CARE;
409   surf->HdrMetadata.max_luminance = EGL_DONT_CARE;
410   surf->HdrMetadata.min_luminance = EGL_DONT_CARE;
411   surf->HdrMetadata.max_cll = EGL_DONT_CARE;
412   surf->HdrMetadata.max_fall = EGL_DONT_CARE;
413
414   err = _eglParseSurfaceAttribList(surf, attrib_list);
415   if (err != EGL_SUCCESS)
416      return _eglError(err, func);
417
418   /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
419   if (surf->LargestPbuffer) {
420      surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
421      surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
422   }
423
424   return EGL_TRUE;
425}
426
427
428EGLBoolean
429_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface,
430                 EGLint attribute, EGLint *value)
431{
432   switch (attribute) {
433   case EGL_WIDTH:
434      *value = surface->Width;
435      break;
436   case EGL_HEIGHT:
437      *value = surface->Height;
438      break;
439   case EGL_CONFIG_ID:
440      *value = surface->Config->ConfigID;
441      break;
442   case EGL_LARGEST_PBUFFER:
443      if (surface->Type == EGL_PBUFFER_BIT)
444         *value = surface->LargestPbuffer;
445      break;
446   case EGL_TEXTURE_FORMAT:
447      /* texture attributes: only for pbuffers, no error otherwise */
448      if (surface->Type == EGL_PBUFFER_BIT)
449         *value = surface->TextureFormat;
450      break;
451   case EGL_TEXTURE_TARGET:
452      if (surface->Type == EGL_PBUFFER_BIT)
453         *value = surface->TextureTarget;
454      break;
455   case EGL_MIPMAP_TEXTURE:
456      if (surface->Type == EGL_PBUFFER_BIT)
457         *value = surface->MipmapTexture;
458      break;
459   case EGL_MIPMAP_LEVEL:
460      if (surface->Type == EGL_PBUFFER_BIT)
461         *value = surface->MipmapLevel;
462      break;
463   case EGL_SWAP_BEHAVIOR:
464      *value = surface->SwapBehavior;
465      break;
466   case EGL_RENDER_BUFFER:
467      /* From the EGL_KHR_mutable_render_buffer spec (v12):
468       *
469       *    Querying EGL_RENDER_BUFFER returns the buffer which client API
470       *    rendering is requested to use. For a window surface, this is the
471       *    attribute value specified when the surface was created or last set
472       *    via eglSurfaceAttrib.
473       *
474       * In other words, querying a window surface returns the value most
475       * recently *requested* by the user.
476       *
477       * The paragraph continues in the EGL 1.5 spec (2014.08.27):
478       *
479       *    For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
480       *    surface, it is always EGL_SINGLE_BUFFER . To determine the actual
481       *    buffer being rendered to by a context, call eglQueryContext.
482       */
483      switch (surface->Type) {
484      default:
485         unreachable("bad EGLSurface type");
486      case EGL_WINDOW_BIT:
487         *value = surface->RequestedRenderBuffer;
488         break;
489      case EGL_PBUFFER_BIT:
490         *value = EGL_BACK_BUFFER;
491         break;
492      case EGL_PIXMAP_BIT:
493         *value = EGL_SINGLE_BUFFER;
494         break;
495      }
496      break;
497   case EGL_PIXEL_ASPECT_RATIO:
498      *value = surface->AspectRatio;
499      break;
500   case EGL_HORIZONTAL_RESOLUTION:
501      *value = surface->HorizontalResolution;
502      break;
503   case EGL_VERTICAL_RESOLUTION:
504      *value = surface->VerticalResolution;
505      break;
506   case EGL_MULTISAMPLE_RESOLVE:
507      *value = surface->MultisampleResolve;
508      break;
509   case EGL_VG_ALPHA_FORMAT:
510      *value = surface->VGAlphaFormat;
511      break;
512   case EGL_VG_COLORSPACE:
513      *value = surface->VGColorspace;
514      break;
515   case EGL_GL_COLORSPACE_KHR:
516      if (!disp->Extensions.KHR_gl_colorspace)
517         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
518
519      *value = surface->GLColorspace;
520      break;
521   case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
522      *value = surface->PostSubBufferSupportedNV;
523      break;
524   case EGL_BUFFER_AGE_EXT:
525      /* Both EXT_buffer_age and KHR_partial_update accept EGL_BUFFER_AGE_EXT.
526       * To be precise, the KHR one accepts EGL_BUFFER_AGE_KHR which is an
527       * alias with the same numeric value.
528       */
529      if (!disp->Extensions.EXT_buffer_age &&
530          !disp->Extensions.KHR_partial_update)
531         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
532
533      _EGLContext *ctx = _eglGetCurrentContext();
534      EGLint result = drv->API.QueryBufferAge(drv, disp, surface);
535      /* error happened */
536      if (result < 0)
537         return EGL_FALSE;
538      if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
539          ctx->DrawSurface != surface)
540         return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
541
542      *value = result;
543      surface->BufferAgeRead = EGL_TRUE;
544      break;
545   case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
546      *value = surface->HdrMetadata.display_primary_r.x;
547      break;
548   case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
549      *value = surface->HdrMetadata.display_primary_r.y;
550      break;
551   case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
552      *value = surface->HdrMetadata.display_primary_g.x;
553      break;
554   case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
555      *value = surface->HdrMetadata.display_primary_g.y;
556      break;
557   case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
558      *value = surface->HdrMetadata.display_primary_b.x;
559      break;
560   case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
561      *value = surface->HdrMetadata.display_primary_b.y;
562      break;
563   case EGL_SMPTE2086_WHITE_POINT_X_EXT:
564      *value = surface->HdrMetadata.white_point.x;
565      break;
566   case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
567      *value = surface->HdrMetadata.white_point.y;
568      break;
569   case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
570      *value = surface->HdrMetadata.max_luminance;
571      break;
572   case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
573      *value = surface->HdrMetadata.min_luminance;
574      break;
575   case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
576      *value = surface->HdrMetadata.max_cll;
577      break;
578   case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
579      *value = surface->HdrMetadata.max_fall;
580      break;
581   default:
582      return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
583   }
584
585   return EGL_TRUE;
586}
587
588
589/**
590 * Default fallback routine - drivers might override this.
591 */
592EGLBoolean
593_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface,
594                  EGLint attribute, EGLint value)
595{
596   EGLint confval;
597   EGLint err = EGL_SUCCESS;
598   EGLint all_es_bits = EGL_OPENGL_ES_BIT |
599                        EGL_OPENGL_ES2_BIT |
600                        EGL_OPENGL_ES3_BIT_KHR;
601
602   switch (attribute) {
603   case EGL_MIPMAP_LEVEL:
604      confval = surface->Config->RenderableType;
605      if (!(confval & all_es_bits)) {
606         err = EGL_BAD_PARAMETER;
607         break;
608      }
609      surface->MipmapLevel = value;
610      break;
611   case EGL_MULTISAMPLE_RESOLVE:
612      switch (value) {
613      case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
614         break;
615      case EGL_MULTISAMPLE_RESOLVE_BOX:
616         confval = surface->Config->SurfaceType;
617         if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
618            err = EGL_BAD_MATCH;
619         break;
620      default:
621         err = EGL_BAD_ATTRIBUTE;
622         break;
623      }
624      if (err != EGL_SUCCESS)
625         break;
626      surface->MultisampleResolve = value;
627      break;
628   case EGL_RENDER_BUFFER:
629      if (!disp->Extensions.KHR_mutable_render_buffer) {
630         err = EGL_BAD_ATTRIBUTE;
631         break;
632      }
633
634      if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
635         err = EGL_BAD_PARAMETER;
636         break;
637      }
638
639      /* From the EGL_KHR_mutable_render_buffer spec (v12):
640       *
641       *    If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
642       *    attribute of the EGLConfig used to create surface does not contain
643       *    EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
644       *    generated [...].
645       */
646      if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
647         err = EGL_BAD_MATCH;
648         break;
649      }
650
651      surface->RequestedRenderBuffer = value;
652      break;
653   case EGL_SWAP_BEHAVIOR:
654      switch (value) {
655      case EGL_BUFFER_DESTROYED:
656         break;
657      case EGL_BUFFER_PRESERVED:
658         confval = surface->Config->SurfaceType;
659         if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
660            err = EGL_BAD_MATCH;
661         break;
662      default:
663         err = EGL_BAD_ATTRIBUTE;
664         break;
665      }
666      if (err != EGL_SUCCESS)
667         break;
668      surface->SwapBehavior = value;
669      break;
670   case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
671      surface->HdrMetadata.display_primary_r.x = value;
672      break;
673   case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
674      surface->HdrMetadata.display_primary_r.y = value;
675      break;
676   case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
677      surface->HdrMetadata.display_primary_g.x = value;
678      break;
679   case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
680      surface->HdrMetadata.display_primary_g.y = value;
681      break;
682   case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
683      surface->HdrMetadata.display_primary_b.x = value;
684      break;
685   case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
686      surface->HdrMetadata.display_primary_b.y = value;
687      break;
688   case EGL_SMPTE2086_WHITE_POINT_X_EXT:
689      surface->HdrMetadata.white_point.x = value;
690      break;
691   case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
692      surface->HdrMetadata.white_point.y = value;
693      break;
694   case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
695      surface->HdrMetadata.max_luminance = value;
696      break;
697   case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
698      surface->HdrMetadata.min_luminance = value;
699      break;
700   case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
701      surface->HdrMetadata.max_cll = value;
702      break;
703   case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
704      surface->HdrMetadata.max_fall = value;
705      break;
706   default:
707      err = EGL_BAD_ATTRIBUTE;
708      break;
709   }
710
711   if (err != EGL_SUCCESS)
712      return _eglError(err, "eglSurfaceAttrib");
713   return EGL_TRUE;
714}
715
716
717EGLBoolean
718_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface,
719                 EGLint buffer)
720{
721   EGLint texture_type = EGL_PBUFFER_BIT;
722
723   /* Just do basic error checking and return success/fail.
724    * Drivers must implement the real stuff.
725    */
726
727   if (disp->Extensions.NOK_texture_from_pixmap)
728      texture_type |= EGL_PIXMAP_BIT;
729
730   if (!(surface->Type & texture_type))
731      return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
732
733   if (surface->TextureFormat == EGL_NO_TEXTURE)
734      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
735
736   if (surface->TextureTarget == EGL_NO_TEXTURE)
737      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
738
739   if (buffer != EGL_BACK_BUFFER)
740      return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
741
742   surface->BoundToTexture = EGL_TRUE;
743
744   return EGL_TRUE;
745}
746
747EGLBoolean
748_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
749                    EGLint buffer)
750{
751   /* Just do basic error checking and return success/fail.
752    * Drivers must implement the real stuff.
753    */
754
755   EGLint texture_type = EGL_PBUFFER_BIT;
756
757   if (surf == EGL_NO_SURFACE)
758      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
759
760   if (!surf->BoundToTexture)
761   {
762      /* Not an error, simply nothing to do */
763      return EGL_TRUE;
764   }
765
766   if (surf->TextureFormat == EGL_NO_TEXTURE)
767      return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
768
769   if (buffer != EGL_BACK_BUFFER)
770      return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
771
772   if (disp->Extensions.NOK_texture_from_pixmap)
773      texture_type |= EGL_PIXMAP_BIT;
774
775   if (!(surf->Type & texture_type))
776      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
777
778   surf->BoundToTexture = EGL_FALSE;
779
780   return EGL_TRUE;
781}
782
783
784EGLBoolean
785_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
786                 EGLint interval)
787{
788   return EGL_TRUE;
789}
790
791EGLBoolean
792_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
793{
794   return surf->Type == EGL_WINDOW_BIT &&
795          surf->Config &&
796          (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
797}
798
799EGLBoolean
800_eglSurfaceInSharedBufferMode(_EGLSurface *surf)
801{
802   return _eglSurfaceHasMutableRenderBuffer(surf) &&
803          surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
804}
805