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  */
53 static EGLint
_eglParseSurfaceAttribList(_EGLSurface * surf,const EGLint * attrib_list)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  */
358 EGLBoolean
_eglInitSurface(_EGLSurface * surf,_EGLDisplay * disp,EGLint type,_EGLConfig * conf,const EGLint * attrib_list,void * native_surface)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 
456 EGLBoolean
_eglQuerySurface(_EGLDisplay * disp,_EGLSurface * surface,EGLint attribute,EGLint * value)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  */
630 EGLBoolean
_eglSurfaceAttrib(_EGLDisplay * disp,_EGLSurface * surface,EGLint attribute,EGLint value)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 
755 EGLBoolean
_eglBindTexImage(_EGLDisplay * disp,_EGLSurface * surface,EGLint buffer)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 
784 EGLBoolean
_eglReleaseTexImage(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)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 
819 EGLBoolean
_eglSurfaceHasMutableRenderBuffer(_EGLSurface * surf)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 
827 EGLBoolean
_eglSurfaceInSharedBufferMode(_EGLSurface * surf)828 _eglSurfaceInSharedBufferMode(_EGLSurface *surf)
829 {
830    return _eglSurfaceHasMutableRenderBuffer(surf) &&
831           surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
832 }
833