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_PRESENT_OPAQUE_EXT:
220         if (!disp->Extensions.EXT_present_opaque) {
221            err = EGL_BAD_ATTRIBUTE;
222            break;
223         }
224         if (type != EGL_WINDOW_BIT) {
225            err = EGL_BAD_ATTRIBUTE;
226            break;
227         }
228         if (val != EGL_TRUE && val != EGL_FALSE) {
229            err = EGL_BAD_PARAMETER;
230            break;
231         }
232         surf->PresentOpaque = val;
233         break;
234      case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
235         if (!disp->Extensions.NV_post_sub_buffer ||
236             type != EGL_WINDOW_BIT) {
237            err = EGL_BAD_ATTRIBUTE;
238            break;
239         }
240         if (val != EGL_TRUE && val != EGL_FALSE) {
241            err = EGL_BAD_PARAMETER;
242            break;
243         }
244         surf->PostSubBufferSupportedNV = val;
245         break;
246      /* pbuffer surface attributes */
247      case EGL_WIDTH:
248         if (type != EGL_PBUFFER_BIT) {
249            err = EGL_BAD_ATTRIBUTE;
250            break;
251         }
252         if (val < 0) {
253            err = EGL_BAD_PARAMETER;
254            break;
255         }
256         surf->Width = val;
257         break;
258      case EGL_HEIGHT:
259         if (type != EGL_PBUFFER_BIT) {
260            err = EGL_BAD_ATTRIBUTE;
261            break;
262         }
263         if (val < 0) {
264            err = EGL_BAD_PARAMETER;
265            break;
266         }
267         surf->Height = val;
268         break;
269      case EGL_LARGEST_PBUFFER:
270         if (type != EGL_PBUFFER_BIT) {
271            err = EGL_BAD_ATTRIBUTE;
272            break;
273         }
274         surf->LargestPbuffer = !!val;
275         break;
276      /* for eglBindTexImage */
277      case EGL_TEXTURE_FORMAT:
278         if (!(type & texture_type)) {
279            err = EGL_BAD_ATTRIBUTE;
280            break;
281         }
282
283         switch (val) {
284         case EGL_TEXTURE_RGB:
285         case EGL_TEXTURE_RGBA:
286         case EGL_NO_TEXTURE:
287            break;
288         default:
289            err = EGL_BAD_ATTRIBUTE;
290            break;
291         }
292         if (err != EGL_SUCCESS)
293            break;
294         surf->TextureFormat = val;
295         break;
296      case EGL_TEXTURE_TARGET:
297         if (!(type & texture_type)) {
298            err = EGL_BAD_ATTRIBUTE;
299            break;
300         }
301
302         switch (val) {
303         case EGL_TEXTURE_2D:
304         case EGL_NO_TEXTURE:
305            break;
306         default:
307            err = EGL_BAD_ATTRIBUTE;
308            break;
309         }
310         if (err != EGL_SUCCESS)
311            break;
312         surf->TextureTarget = val;
313         break;
314      case EGL_MIPMAP_TEXTURE:
315         if (!(type & texture_type)) {
316            err = EGL_BAD_ATTRIBUTE;
317            break;
318         }
319         surf->MipmapTexture = !!val;
320         break;
321      case EGL_PROTECTED_CONTENT_EXT:
322         if (!disp->Extensions.EXT_protected_surface) {
323            err = EGL_BAD_ATTRIBUTE;
324            break;
325         }
326         surf->ProtectedContent = val;
327         break;
328
329      /* no pixmap surface specific attributes */
330      default:
331         err = EGL_BAD_ATTRIBUTE;
332         break;
333      }
334
335      if (err != EGL_SUCCESS)
336         break;
337   }
338
339   if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
340      if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) ||
341          (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) {
342         attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT;
343         err = EGL_BAD_MATCH;
344      }
345   }
346
347   if (err != EGL_SUCCESS)
348      _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
349
350   return err;
351}
352
353
354/**
355 * Do error check on parameters and initialize the given _EGLSurface object.
356 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
357 */
358EGLBoolean
359_eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
360                _EGLConfig *conf, const EGLint *attrib_list,
361                void *native_surface)
362{
363   const char *func;
364   EGLint renderBuffer = EGL_BACK_BUFFER;
365   EGLint swapBehavior = EGL_BUFFER_DESTROYED;
366   EGLint err;
367
368   /* Swap behavior can be preserved only if config supports this. */
369   if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
370      swapBehavior = EGL_BUFFER_PRESERVED;
371
372   switch (type) {
373   case EGL_WINDOW_BIT:
374      func = "eglCreateWindowSurface";
375      swapBehavior = EGL_BUFFER_DESTROYED;
376      break;
377   case EGL_PIXMAP_BIT:
378      func = "eglCreatePixmapSurface";
379      renderBuffer = EGL_SINGLE_BUFFER;
380      break;
381   case EGL_PBUFFER_BIT:
382      func = "eglCreatePBufferSurface";
383      break;
384   default:
385      _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
386      return EGL_FALSE;
387   }
388
389   if ((conf->SurfaceType & type) == 0)
390      /* The config can't be used to create a surface of this type */
391      return _eglError(EGL_BAD_MATCH, func);
392
393   _eglInitResource(&surf->Resource, sizeof(*surf), disp);
394   surf->Type = type;
395   surf->Config = conf;
396   surf->Lost = EGL_FALSE;
397
398   surf->Width = 0;
399   surf->Height = 0;
400   surf->TextureFormat = EGL_NO_TEXTURE;
401   surf->TextureTarget = EGL_NO_TEXTURE;
402   surf->MipmapTexture = EGL_FALSE;
403   surf->LargestPbuffer = EGL_FALSE;
404   surf->RequestedRenderBuffer = renderBuffer;
405   surf->ActiveRenderBuffer = renderBuffer;
406   surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
407   surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
408   surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
409   surf->ProtectedContent = EGL_FALSE;
410   surf->PresentOpaque = EGL_FALSE;
411
412   surf->MipmapLevel = 0;
413   surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
414   surf->SwapBehavior = swapBehavior;
415
416   surf->HorizontalResolution = EGL_UNKNOWN;
417   surf->VerticalResolution = EGL_UNKNOWN;
418   surf->AspectRatio = EGL_UNKNOWN;
419
420   surf->PostSubBufferSupportedNV = EGL_FALSE;
421   surf->SetDamageRegionCalled = EGL_FALSE;
422   surf->BufferAgeRead = EGL_FALSE;
423
424   /* the default swap interval is 1 */
425   surf->SwapInterval = 1;
426
427   surf->HdrMetadata.display_primary_r.x = EGL_DONT_CARE;
428   surf->HdrMetadata.display_primary_r.y = EGL_DONT_CARE;
429   surf->HdrMetadata.display_primary_g.x = EGL_DONT_CARE;
430   surf->HdrMetadata.display_primary_g.y = EGL_DONT_CARE;
431   surf->HdrMetadata.display_primary_b.x = EGL_DONT_CARE;
432   surf->HdrMetadata.display_primary_b.y = EGL_DONT_CARE;
433   surf->HdrMetadata.white_point.x = EGL_DONT_CARE;
434   surf->HdrMetadata.white_point.y = EGL_DONT_CARE;
435   surf->HdrMetadata.max_luminance = EGL_DONT_CARE;
436   surf->HdrMetadata.min_luminance = EGL_DONT_CARE;
437   surf->HdrMetadata.max_cll = EGL_DONT_CARE;
438   surf->HdrMetadata.max_fall = EGL_DONT_CARE;
439
440   err = _eglParseSurfaceAttribList(surf, attrib_list);
441   if (err != EGL_SUCCESS)
442      return _eglError(err, func);
443
444   /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
445   if (surf->LargestPbuffer) {
446      surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
447      surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
448   }
449
450   surf->NativeSurface = native_surface;
451
452   return EGL_TRUE;
453}
454
455
456EGLBoolean
457_eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface,
458                 EGLint attribute, EGLint *value)
459{
460   switch (attribute) {
461   case EGL_WIDTH:
462      *value = surface->Width;
463      break;
464   case EGL_HEIGHT:
465      *value = surface->Height;
466      break;
467   case EGL_CONFIG_ID:
468      *value = surface->Config->ConfigID;
469      break;
470   case EGL_LARGEST_PBUFFER:
471      if (surface->Type == EGL_PBUFFER_BIT)
472         *value = surface->LargestPbuffer;
473      break;
474   case EGL_TEXTURE_FORMAT:
475      /* texture attributes: only for pbuffers, no error otherwise */
476      if (surface->Type == EGL_PBUFFER_BIT)
477         *value = surface->TextureFormat;
478      break;
479   case EGL_TEXTURE_TARGET:
480      if (surface->Type == EGL_PBUFFER_BIT)
481         *value = surface->TextureTarget;
482      break;
483   case EGL_MIPMAP_TEXTURE:
484      if (surface->Type == EGL_PBUFFER_BIT)
485         *value = surface->MipmapTexture;
486      break;
487   case EGL_MIPMAP_LEVEL:
488      if (surface->Type == EGL_PBUFFER_BIT)
489         *value = surface->MipmapLevel;
490      break;
491   case EGL_SWAP_BEHAVIOR:
492      *value = surface->SwapBehavior;
493      break;
494   case EGL_RENDER_BUFFER:
495      /* From the EGL_KHR_mutable_render_buffer spec (v12):
496       *
497       *    Querying EGL_RENDER_BUFFER returns the buffer which client API
498       *    rendering is requested to use. For a window surface, this is the
499       *    attribute value specified when the surface was created or last set
500       *    via eglSurfaceAttrib.
501       *
502       * In other words, querying a window surface returns the value most
503       * recently *requested* by the user.
504       *
505       * The paragraph continues in the EGL 1.5 spec (2014.08.27):
506       *
507       *    For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
508       *    surface, it is always EGL_SINGLE_BUFFER . To determine the actual
509       *    buffer being rendered to by a context, call eglQueryContext.
510       */
511      switch (surface->Type) {
512      default:
513         unreachable("bad EGLSurface type");
514      case EGL_WINDOW_BIT:
515         *value = surface->RequestedRenderBuffer;
516         break;
517      case EGL_PBUFFER_BIT:
518         *value = EGL_BACK_BUFFER;
519         break;
520      case EGL_PIXMAP_BIT:
521         *value = EGL_SINGLE_BUFFER;
522         break;
523      }
524      break;
525   case EGL_PIXEL_ASPECT_RATIO:
526      *value = surface->AspectRatio;
527      break;
528   case EGL_HORIZONTAL_RESOLUTION:
529      *value = surface->HorizontalResolution;
530      break;
531   case EGL_VERTICAL_RESOLUTION:
532      *value = surface->VerticalResolution;
533      break;
534   case EGL_MULTISAMPLE_RESOLVE:
535      *value = surface->MultisampleResolve;
536      break;
537   case EGL_VG_ALPHA_FORMAT:
538      *value = surface->VGAlphaFormat;
539      break;
540   case EGL_VG_COLORSPACE:
541      *value = surface->VGColorspace;
542      break;
543   case EGL_GL_COLORSPACE_KHR:
544      if (!disp->Extensions.KHR_gl_colorspace)
545         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
546
547      *value = surface->GLColorspace;
548      break;
549   case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
550      *value = surface->PostSubBufferSupportedNV;
551      break;
552   case EGL_BUFFER_AGE_EXT:
553      /* Both EXT_buffer_age and KHR_partial_update accept EGL_BUFFER_AGE_EXT.
554       * To be precise, the KHR one accepts EGL_BUFFER_AGE_KHR which is an
555       * alias with the same numeric value.
556       */
557      if (!disp->Extensions.EXT_buffer_age &&
558          !disp->Extensions.KHR_partial_update)
559         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
560
561      _EGLContext *ctx = _eglGetCurrentContext();
562      EGLint result = disp->Driver->QueryBufferAge(disp, surface);
563      /* error happened */
564      if (result < 0)
565         return EGL_FALSE;
566      if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
567          ctx->DrawSurface != surface)
568         return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
569
570      *value = result;
571      surface->BufferAgeRead = EGL_TRUE;
572      break;
573   case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
574      *value = surface->HdrMetadata.display_primary_r.x;
575      break;
576   case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
577      *value = surface->HdrMetadata.display_primary_r.y;
578      break;
579   case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
580      *value = surface->HdrMetadata.display_primary_g.x;
581      break;
582   case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
583      *value = surface->HdrMetadata.display_primary_g.y;
584      break;
585   case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
586      *value = surface->HdrMetadata.display_primary_b.x;
587      break;
588   case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
589      *value = surface->HdrMetadata.display_primary_b.y;
590      break;
591   case EGL_SMPTE2086_WHITE_POINT_X_EXT:
592      *value = surface->HdrMetadata.white_point.x;
593      break;
594   case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
595      *value = surface->HdrMetadata.white_point.y;
596      break;
597   case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
598      *value = surface->HdrMetadata.max_luminance;
599      break;
600   case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
601      *value = surface->HdrMetadata.min_luminance;
602      break;
603   case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
604      *value = surface->HdrMetadata.max_cll;
605      break;
606   case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
607      *value = surface->HdrMetadata.max_fall;
608      break;
609   case EGL_PROTECTED_CONTENT_EXT:
610      if (!disp->Extensions.EXT_protected_surface)
611         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
612      *value = surface->ProtectedContent;
613      break;
614   case EGL_PRESENT_OPAQUE_EXT:
615      if (!disp->Extensions.EXT_present_opaque)
616         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
617      *value = surface->PresentOpaque;
618      break;
619   default:
620      return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
621   }
622
623   return EGL_TRUE;
624}
625
626
627/**
628 * Default fallback routine - drivers might override this.
629 */
630EGLBoolean
631_eglSurfaceAttrib(_EGLDisplay *disp, _EGLSurface *surface,
632                  EGLint attribute, EGLint value)
633{
634   EGLint confval;
635   EGLint err = EGL_SUCCESS;
636   EGLint all_es_bits = EGL_OPENGL_ES_BIT |
637                        EGL_OPENGL_ES2_BIT |
638                        EGL_OPENGL_ES3_BIT_KHR;
639
640   switch (attribute) {
641   case EGL_MIPMAP_LEVEL:
642      confval = surface->Config->RenderableType;
643      if (!(confval & all_es_bits)) {
644         err = EGL_BAD_PARAMETER;
645         break;
646      }
647      surface->MipmapLevel = value;
648      break;
649   case EGL_MULTISAMPLE_RESOLVE:
650      switch (value) {
651      case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
652         break;
653      case EGL_MULTISAMPLE_RESOLVE_BOX:
654         confval = surface->Config->SurfaceType;
655         if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
656            err = EGL_BAD_MATCH;
657         break;
658      default:
659         err = EGL_BAD_ATTRIBUTE;
660         break;
661      }
662      if (err != EGL_SUCCESS)
663         break;
664      surface->MultisampleResolve = value;
665      break;
666   case EGL_RENDER_BUFFER:
667      if (!disp->Extensions.KHR_mutable_render_buffer) {
668         err = EGL_BAD_ATTRIBUTE;
669         break;
670      }
671
672      if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
673         err = EGL_BAD_PARAMETER;
674         break;
675      }
676
677      /* From the EGL_KHR_mutable_render_buffer spec (v12):
678       *
679       *    If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
680       *    attribute of the EGLConfig used to create surface does not contain
681       *    EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
682       *    generated [...].
683       */
684      if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
685         err = EGL_BAD_MATCH;
686         break;
687      }
688
689      surface->RequestedRenderBuffer = value;
690      break;
691   case EGL_SWAP_BEHAVIOR:
692      switch (value) {
693      case EGL_BUFFER_DESTROYED:
694         break;
695      case EGL_BUFFER_PRESERVED:
696         confval = surface->Config->SurfaceType;
697         if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
698            err = EGL_BAD_MATCH;
699         break;
700      default:
701         err = EGL_BAD_ATTRIBUTE;
702         break;
703      }
704      if (err != EGL_SUCCESS)
705         break;
706      surface->SwapBehavior = value;
707      break;
708   case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
709      surface->HdrMetadata.display_primary_r.x = value;
710      break;
711   case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
712      surface->HdrMetadata.display_primary_r.y = value;
713      break;
714   case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
715      surface->HdrMetadata.display_primary_g.x = value;
716      break;
717   case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
718      surface->HdrMetadata.display_primary_g.y = value;
719      break;
720   case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
721      surface->HdrMetadata.display_primary_b.x = value;
722      break;
723   case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
724      surface->HdrMetadata.display_primary_b.y = value;
725      break;
726   case EGL_SMPTE2086_WHITE_POINT_X_EXT:
727      surface->HdrMetadata.white_point.x = value;
728      break;
729   case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
730      surface->HdrMetadata.white_point.y = value;
731      break;
732   case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
733      surface->HdrMetadata.max_luminance = value;
734      break;
735   case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
736      surface->HdrMetadata.min_luminance = value;
737      break;
738   case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
739      surface->HdrMetadata.max_cll = value;
740      break;
741   case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
742      surface->HdrMetadata.max_fall = value;
743      break;
744   default:
745      err = EGL_BAD_ATTRIBUTE;
746      break;
747   }
748
749   if (err != EGL_SUCCESS)
750      return _eglError(err, "eglSurfaceAttrib");
751   return EGL_TRUE;
752}
753
754
755EGLBoolean
756_eglBindTexImage(_EGLDisplay *disp, _EGLSurface *surface, EGLint buffer)
757{
758   EGLint texture_type = EGL_PBUFFER_BIT;
759
760   /* Just do basic error checking and return success/fail.
761    * Drivers must implement the real stuff.
762    */
763
764   if (disp->Extensions.NOK_texture_from_pixmap)
765      texture_type |= EGL_PIXMAP_BIT;
766
767   if (!(surface->Type & texture_type))
768      return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
769
770   if (surface->TextureFormat == EGL_NO_TEXTURE)
771      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
772
773   if (surface->TextureTarget == EGL_NO_TEXTURE)
774      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
775
776   if (buffer != EGL_BACK_BUFFER)
777      return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
778
779   surface->BoundToTexture = EGL_TRUE;
780
781   return EGL_TRUE;
782}
783
784EGLBoolean
785_eglReleaseTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
786{
787   /* Just do basic error checking and return success/fail.
788    * Drivers must implement the real stuff.
789    */
790
791   EGLint texture_type = EGL_PBUFFER_BIT;
792
793   if (surf == EGL_NO_SURFACE)
794      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
795
796   if (!surf->BoundToTexture)
797   {
798      /* Not an error, simply nothing to do */
799      return EGL_TRUE;
800   }
801
802   if (surf->TextureFormat == EGL_NO_TEXTURE)
803      return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
804
805   if (buffer != EGL_BACK_BUFFER)
806      return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
807
808   if (disp->Extensions.NOK_texture_from_pixmap)
809      texture_type |= EGL_PIXMAP_BIT;
810
811   if (!(surf->Type & texture_type))
812      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
813
814   surf->BoundToTexture = EGL_FALSE;
815
816   return EGL_TRUE;
817}
818
819EGLBoolean
820_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
821{
822   return surf->Type == EGL_WINDOW_BIT &&
823          surf->Config &&
824          (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
825}
826
827EGLBoolean
828_eglSurfaceInSharedBufferMode(_EGLSurface *surf)
829{
830   return _eglSurfaceHasMutableRenderBuffer(surf) &&
831          surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
832}
833