• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Surface-related functions.
32  */
33 
34 #include "eglsurface.h"
35 #include <assert.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "eglconfig.h"
39 #include "eglcontext.h"
40 #include "eglcurrent.h"
41 #include "egldefines.h"
42 #include "egldisplay.h"
43 #include "egldriver.h"
44 #include "egllog.h"
45 
46 #include "util/macros.h"
47 
48 /**
49  * Parse the list of surface attributes and return the proper error code.
50  */
51 static EGLint
_eglParseSurfaceAttribList(_EGLSurface * surf,const EGLint * attrib_list)52 _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
53 {
54    _EGLDisplay *disp = 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 (disp->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 (!disp->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_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
90          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
91             err = EGL_BAD_ATTRIBUTE;
92             break;
93          }
94          surf->HdrMetadata.display_primary_r.x = val;
95          break;
96       case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
97          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
98             err = EGL_BAD_ATTRIBUTE;
99             break;
100          }
101          surf->HdrMetadata.display_primary_r.y = val;
102          break;
103       case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
104          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
105             err = EGL_BAD_ATTRIBUTE;
106             break;
107          }
108          surf->HdrMetadata.display_primary_g.x = val;
109          break;
110       case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
111          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
112             err = EGL_BAD_ATTRIBUTE;
113             break;
114          }
115          surf->HdrMetadata.display_primary_g.y = val;
116          break;
117       case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
118          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
119             err = EGL_BAD_ATTRIBUTE;
120             break;
121          }
122          surf->HdrMetadata.display_primary_b.x = val;
123          break;
124       case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
125          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
126             err = EGL_BAD_ATTRIBUTE;
127             break;
128          }
129          surf->HdrMetadata.display_primary_b.y = val;
130          break;
131       case EGL_SMPTE2086_WHITE_POINT_X_EXT:
132          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
133             err = EGL_BAD_ATTRIBUTE;
134             break;
135          }
136          surf->HdrMetadata.white_point.x = val;
137          break;
138       case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
139          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
140             err = EGL_BAD_ATTRIBUTE;
141             break;
142          }
143          surf->HdrMetadata.white_point.y = val;
144          break;
145       case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
146          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
147             err = EGL_BAD_ATTRIBUTE;
148             break;
149          }
150          surf->HdrMetadata.max_luminance = val;
151          break;
152       case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
153          if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
154             err = EGL_BAD_ATTRIBUTE;
155             break;
156          }
157          surf->HdrMetadata.min_luminance = val;
158          break;
159       case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
160          if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
161             err = EGL_BAD_ATTRIBUTE;
162             break;
163          }
164          surf->HdrMetadata.max_cll = val;
165          break;
166       case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
167          if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
168             err = EGL_BAD_ATTRIBUTE;
169             break;
170          }
171          surf->HdrMetadata.max_fall = val;
172          break;
173       case EGL_VG_COLORSPACE:
174          switch (val) {
175          case EGL_VG_COLORSPACE_sRGB:
176          case EGL_VG_COLORSPACE_LINEAR:
177             break;
178          default:
179             err = EGL_BAD_ATTRIBUTE;
180             break;
181          }
182          if (err != EGL_SUCCESS)
183             break;
184          surf->VGColorspace = val;
185          break;
186       case EGL_VG_ALPHA_FORMAT:
187          switch (val) {
188          case EGL_VG_ALPHA_FORMAT_NONPRE:
189          case EGL_VG_ALPHA_FORMAT_PRE:
190             break;
191          default:
192             err = EGL_BAD_ATTRIBUTE;
193             break;
194          }
195          if (err != EGL_SUCCESS)
196             break;
197          surf->VGAlphaFormat = val;
198          break;
199       /* window surface attributes */
200       case EGL_RENDER_BUFFER:
201          if (type != EGL_WINDOW_BIT) {
202             err = EGL_BAD_ATTRIBUTE;
203             break;
204          }
205          if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
206             err = EGL_BAD_ATTRIBUTE;
207             break;
208          }
209          surf->RequestedRenderBuffer = val;
210          if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
211             /* Unlike normal EGLSurfaces, one with a mutable render buffer
212              * uses the application-chosen render buffer.
213              */
214             surf->ActiveRenderBuffer = val;
215          }
216          break;
217       case EGL_PRESENT_OPAQUE_EXT:
218          if (!disp->Extensions.EXT_present_opaque) {
219             err = EGL_BAD_ATTRIBUTE;
220             break;
221          }
222          if (type != EGL_WINDOW_BIT) {
223             err = EGL_BAD_ATTRIBUTE;
224             break;
225          }
226          if (val != EGL_TRUE && val != EGL_FALSE) {
227             err = EGL_BAD_PARAMETER;
228             break;
229          }
230          surf->PresentOpaque = val;
231          break;
232       case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
233          if (!disp->Extensions.NV_post_sub_buffer || type != EGL_WINDOW_BIT) {
234             err = EGL_BAD_ATTRIBUTE;
235             break;
236          }
237          if (val != EGL_TRUE && val != EGL_FALSE) {
238             err = EGL_BAD_PARAMETER;
239             break;
240          }
241          surf->PostSubBufferSupportedNV = val;
242          break;
243       /* pbuffer surface attributes */
244       case EGL_WIDTH:
245          if (type != EGL_PBUFFER_BIT) {
246             err = EGL_BAD_ATTRIBUTE;
247             break;
248          }
249          if (val < 0) {
250             err = EGL_BAD_PARAMETER;
251             break;
252          }
253          surf->Width = val;
254          break;
255       case EGL_HEIGHT:
256          if (type != EGL_PBUFFER_BIT) {
257             err = EGL_BAD_ATTRIBUTE;
258             break;
259          }
260          if (val < 0) {
261             err = EGL_BAD_PARAMETER;
262             break;
263          }
264          surf->Height = val;
265          break;
266       case EGL_LARGEST_PBUFFER:
267          if (type != EGL_PBUFFER_BIT) {
268             err = EGL_BAD_ATTRIBUTE;
269             break;
270          }
271          surf->LargestPbuffer = !!val;
272          break;
273       /* for eglBindTexImage */
274       case EGL_TEXTURE_FORMAT:
275          if (!(type & texture_type)) {
276             err = EGL_BAD_ATTRIBUTE;
277             break;
278          }
279 
280          switch (val) {
281          case EGL_TEXTURE_RGB:
282          case EGL_TEXTURE_RGBA:
283          case EGL_NO_TEXTURE:
284             break;
285          default:
286             err = EGL_BAD_ATTRIBUTE;
287             break;
288          }
289          if (err != EGL_SUCCESS)
290             break;
291          surf->TextureFormat = val;
292          break;
293       case EGL_TEXTURE_TARGET:
294          if (!(type & texture_type)) {
295             err = EGL_BAD_ATTRIBUTE;
296             break;
297          }
298 
299          switch (val) {
300          case EGL_TEXTURE_2D:
301          case EGL_NO_TEXTURE:
302             break;
303          default:
304             err = EGL_BAD_ATTRIBUTE;
305             break;
306          }
307          if (err != EGL_SUCCESS)
308             break;
309          surf->TextureTarget = val;
310          break;
311       case EGL_MIPMAP_TEXTURE:
312          if (!(type & texture_type)) {
313             err = EGL_BAD_ATTRIBUTE;
314             break;
315          }
316          surf->MipmapTexture = !!val;
317          break;
318       case EGL_PROTECTED_CONTENT_EXT:
319          if (!disp->Extensions.EXT_protected_content &&
320              !disp->Extensions.EXT_protected_surface) {
321             err = EGL_BAD_ATTRIBUTE;
322             break;
323          }
324          surf->ProtectedContent = val;
325          break;
326 
327       /* no pixmap surface specific attributes */
328       default:
329          err = EGL_BAD_ATTRIBUTE;
330          break;
331       }
332 
333       if (err != EGL_SUCCESS)
334          break;
335    }
336 
337    if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
338       if ((surf->TextureTarget == EGL_NO_TEXTURE &&
339            surf->TextureFormat != EGL_NO_TEXTURE) ||
340           (surf->TextureFormat == EGL_NO_TEXTURE &&
341            surf->TextureTarget != EGL_NO_TEXTURE)) {
342          attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET
343                                                       : EGL_TEXTURE_FORMAT;
344          err = EGL_BAD_MATCH;
345       }
346    }
347 
348    if (err != EGL_SUCCESS)
349       _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
350 
351    return err;
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 EGLBoolean
_eglQuerySurface(_EGLDisplay * disp,_EGLSurface * surface,EGLint attribute,EGLint * value)456 _eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface, EGLint attribute,
457                  EGLint *value)
458 {
459    switch (attribute) {
460    case EGL_WIDTH:
461       *value = surface->Width;
462       break;
463    case EGL_HEIGHT:
464       *value = surface->Height;
465       break;
466    case EGL_CONFIG_ID:
467       *value = surface->Config->ConfigID;
468       break;
469    case EGL_LARGEST_PBUFFER:
470       if (surface->Type == EGL_PBUFFER_BIT)
471          *value = surface->LargestPbuffer;
472       break;
473    case EGL_TEXTURE_FORMAT:
474       /* texture attributes: only for pbuffers, no error otherwise */
475       if (surface->Type == EGL_PBUFFER_BIT)
476          *value = surface->TextureFormat;
477       break;
478    case EGL_TEXTURE_TARGET:
479       if (surface->Type == EGL_PBUFFER_BIT)
480          *value = surface->TextureTarget;
481       break;
482    case EGL_MIPMAP_TEXTURE:
483       if (surface->Type == EGL_PBUFFER_BIT)
484          *value = surface->MipmapTexture;
485       break;
486    case EGL_MIPMAP_LEVEL:
487       if (surface->Type == EGL_PBUFFER_BIT)
488          *value = surface->MipmapLevel;
489       break;
490    case EGL_SWAP_BEHAVIOR:
491       *value = surface->SwapBehavior;
492       break;
493    case EGL_RENDER_BUFFER:
494       /* From the EGL_KHR_mutable_render_buffer spec (v12):
495        *
496        *    Querying EGL_RENDER_BUFFER returns the buffer which client API
497        *    rendering is requested to use. For a window surface, this is the
498        *    attribute value specified when the surface was created or last set
499        *    via eglSurfaceAttrib.
500        *
501        * In other words, querying a window surface returns the value most
502        * recently *requested* by the user.
503        *
504        * The paragraph continues in the EGL 1.5 spec (2014.08.27):
505        *
506        *    For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
507        *    surface, it is always EGL_SINGLE_BUFFER . To determine the actual
508        *    buffer being rendered to by a context, call eglQueryContext.
509        */
510       switch (surface->Type) {
511       default:
512          unreachable("bad EGLSurface type");
513       case EGL_WINDOW_BIT:
514          *value = surface->RequestedRenderBuffer;
515          break;
516       case EGL_PBUFFER_BIT:
517          *value = EGL_BACK_BUFFER;
518          break;
519       case EGL_PIXMAP_BIT:
520          *value = EGL_SINGLE_BUFFER;
521          break;
522       }
523       break;
524    case EGL_PIXEL_ASPECT_RATIO:
525       *value = surface->AspectRatio;
526       break;
527    case EGL_HORIZONTAL_RESOLUTION:
528       *value = surface->HorizontalResolution;
529       break;
530    case EGL_VERTICAL_RESOLUTION:
531       *value = surface->VerticalResolution;
532       break;
533    case EGL_MULTISAMPLE_RESOLVE:
534       *value = surface->MultisampleResolve;
535       break;
536    case EGL_VG_ALPHA_FORMAT:
537       *value = surface->VGAlphaFormat;
538       break;
539    case EGL_VG_COLORSPACE:
540       *value = surface->VGColorspace;
541       break;
542    case EGL_GL_COLORSPACE_KHR:
543       if (!disp->Extensions.KHR_gl_colorspace)
544          return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
545 
546       *value = surface->GLColorspace;
547       break;
548    case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
549       *value = surface->PostSubBufferSupportedNV;
550       break;
551    case EGL_BUFFER_AGE_EXT:
552       /* Both EXT_buffer_age and KHR_partial_update accept EGL_BUFFER_AGE_EXT.
553        * To be precise, the KHR one accepts EGL_BUFFER_AGE_KHR which is an
554        * alias with the same numeric value.
555        */
556       if (!disp->Extensions.EXT_buffer_age &&
557           !disp->Extensions.KHR_partial_update)
558          return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
559 
560       _EGLContext *ctx = _eglGetCurrentContext();
561       if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
562           ctx->DrawSurface != surface)
563          return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
564 
565       EGLint result = disp->Driver->QueryBufferAge(disp, surface);
566       if (result < 0)
567          return EGL_FALSE;
568 
569       if (disp->Options.GalliumHudWarn && result > 0) {
570          _eglLog(_EGL_WARNING,
571                  "GALLIUM_HUD is not accounted for when querying "
572                  "buffer age, possibly causing artifacts, try running with "
573                  "MESA_EXTENSION_OVERRIDE=\"-EGL_EXT_buffer_age "
574                  "-EGL_KHR_partial_update\"");
575          disp->Options.GalliumHudWarn = EGL_FALSE;
576       }
577 
578       *value = result;
579       surface->BufferAgeRead = EGL_TRUE;
580       break;
581    case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
582       *value = surface->HdrMetadata.display_primary_r.x;
583       break;
584    case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
585       *value = surface->HdrMetadata.display_primary_r.y;
586       break;
587    case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
588       *value = surface->HdrMetadata.display_primary_g.x;
589       break;
590    case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
591       *value = surface->HdrMetadata.display_primary_g.y;
592       break;
593    case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
594       *value = surface->HdrMetadata.display_primary_b.x;
595       break;
596    case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
597       *value = surface->HdrMetadata.display_primary_b.y;
598       break;
599    case EGL_SMPTE2086_WHITE_POINT_X_EXT:
600       *value = surface->HdrMetadata.white_point.x;
601       break;
602    case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
603       *value = surface->HdrMetadata.white_point.y;
604       break;
605    case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
606       *value = surface->HdrMetadata.max_luminance;
607       break;
608    case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
609       *value = surface->HdrMetadata.min_luminance;
610       break;
611    case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
612       *value = surface->HdrMetadata.max_cll;
613       break;
614    case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
615       *value = surface->HdrMetadata.max_fall;
616       break;
617    case EGL_PROTECTED_CONTENT_EXT:
618       if (!disp->Extensions.EXT_protected_content &&
619           !disp->Extensions.EXT_protected_surface)
620          return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
621       *value = surface->ProtectedContent;
622       break;
623    case EGL_PRESENT_OPAQUE_EXT:
624       if (!disp->Extensions.EXT_present_opaque)
625          return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
626       *value = surface->PresentOpaque;
627       break;
628    default:
629       return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
630    }
631 
632    return EGL_TRUE;
633 }
634 
635 /**
636  * Default fallback routine - drivers might override this.
637  */
638 EGLBoolean
_eglSurfaceAttrib(_EGLDisplay * disp,_EGLSurface * surface,EGLint attribute,EGLint value)639 _eglSurfaceAttrib(_EGLDisplay *disp, _EGLSurface *surface, EGLint attribute,
640                   EGLint value)
641 {
642    EGLint confval;
643    EGLint err = EGL_SUCCESS;
644    EGLint all_es_bits =
645       EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
646 
647    switch (attribute) {
648    case EGL_MIPMAP_LEVEL:
649       confval = surface->Config->RenderableType;
650       if (!(confval & all_es_bits)) {
651          err = EGL_BAD_PARAMETER;
652          break;
653       }
654       surface->MipmapLevel = value;
655       break;
656    case EGL_MULTISAMPLE_RESOLVE:
657       switch (value) {
658       case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
659          break;
660       case EGL_MULTISAMPLE_RESOLVE_BOX:
661          confval = surface->Config->SurfaceType;
662          if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
663             err = EGL_BAD_MATCH;
664          break;
665       default:
666          err = EGL_BAD_ATTRIBUTE;
667          break;
668       }
669       if (err != EGL_SUCCESS)
670          break;
671       surface->MultisampleResolve = value;
672       break;
673    case EGL_RENDER_BUFFER:
674       if (!disp->Extensions.KHR_mutable_render_buffer) {
675          err = EGL_BAD_ATTRIBUTE;
676          break;
677       }
678 
679       if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
680          err = EGL_BAD_PARAMETER;
681          break;
682       }
683 
684       /* From the EGL_KHR_mutable_render_buffer spec (v12):
685        *
686        *    If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
687        *    attribute of the EGLConfig used to create surface does not contain
688        *    EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
689        *    generated [...].
690        */
691       if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
692          err = EGL_BAD_MATCH;
693          break;
694       }
695 
696       surface->RequestedRenderBuffer = value;
697       break;
698    case EGL_SWAP_BEHAVIOR:
699       switch (value) {
700       case EGL_BUFFER_DESTROYED:
701          break;
702       case EGL_BUFFER_PRESERVED:
703          confval = surface->Config->SurfaceType;
704          if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
705             err = EGL_BAD_MATCH;
706          break;
707       default:
708          err = EGL_BAD_ATTRIBUTE;
709          break;
710       }
711       if (err != EGL_SUCCESS)
712          break;
713       surface->SwapBehavior = value;
714       break;
715    case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
716       surface->HdrMetadata.display_primary_r.x = value;
717       break;
718    case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
719       surface->HdrMetadata.display_primary_r.y = value;
720       break;
721    case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
722       surface->HdrMetadata.display_primary_g.x = value;
723       break;
724    case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
725       surface->HdrMetadata.display_primary_g.y = value;
726       break;
727    case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
728       surface->HdrMetadata.display_primary_b.x = value;
729       break;
730    case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
731       surface->HdrMetadata.display_primary_b.y = value;
732       break;
733    case EGL_SMPTE2086_WHITE_POINT_X_EXT:
734       surface->HdrMetadata.white_point.x = value;
735       break;
736    case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
737       surface->HdrMetadata.white_point.y = value;
738       break;
739    case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
740       surface->HdrMetadata.max_luminance = value;
741       break;
742    case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
743       surface->HdrMetadata.min_luminance = value;
744       break;
745    case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
746       surface->HdrMetadata.max_cll = value;
747       break;
748    case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
749       surface->HdrMetadata.max_fall = value;
750       break;
751    default:
752       err = EGL_BAD_ATTRIBUTE;
753       break;
754    }
755 
756    if (err != EGL_SUCCESS)
757       return _eglError(err, "eglSurfaceAttrib");
758    return EGL_TRUE;
759 }
760 
761 EGLBoolean
_eglBindTexImage(_EGLDisplay * disp,_EGLSurface * surface,EGLint buffer)762 _eglBindTexImage(_EGLDisplay *disp, _EGLSurface *surface, EGLint buffer)
763 {
764    EGLint texture_type = EGL_PBUFFER_BIT;
765 
766    /* Just do basic error checking and return success/fail.
767     * Drivers must implement the real stuff.
768     */
769 
770    if (disp->Extensions.NOK_texture_from_pixmap)
771       texture_type |= EGL_PIXMAP_BIT;
772 
773    if (!(surface->Type & texture_type))
774       return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
775 
776    if (surface->TextureFormat == EGL_NO_TEXTURE)
777       return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
778 
779    if (surface->TextureTarget == EGL_NO_TEXTURE)
780       return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
781 
782    if (buffer != EGL_BACK_BUFFER)
783       return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
784 
785    surface->BoundToTexture = EGL_TRUE;
786 
787    return EGL_TRUE;
788 }
789 
790 EGLBoolean
_eglReleaseTexImage(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)791 _eglReleaseTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
792 {
793    /* Just do basic error checking and return success/fail.
794     * Drivers must implement the real stuff.
795     */
796 
797    EGLint texture_type = EGL_PBUFFER_BIT;
798 
799    if (surf == EGL_NO_SURFACE)
800       return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
801 
802    if (!surf->BoundToTexture) {
803       /* Not an error, simply nothing to do */
804       return EGL_TRUE;
805    }
806 
807    if (surf->TextureFormat == EGL_NO_TEXTURE)
808       return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
809 
810    if (buffer != EGL_BACK_BUFFER)
811       return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
812 
813    if (disp->Extensions.NOK_texture_from_pixmap)
814       texture_type |= EGL_PIXMAP_BIT;
815 
816    if (!(surf->Type & texture_type))
817       return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
818 
819    surf->BoundToTexture = EGL_FALSE;
820 
821    return EGL_TRUE;
822 }
823 
824 EGLBoolean
_eglSurfaceHasMutableRenderBuffer(_EGLSurface * surf)825 _eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
826 {
827    return surf->Type == EGL_WINDOW_BIT && surf->Config &&
828           (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
829 }
830 
831 EGLBoolean
_eglSurfaceInSharedBufferMode(_EGLSurface * surf)832 _eglSurfaceInSharedBufferMode(_EGLSurface *surf)
833 {
834    return _eglSurfaceHasMutableRenderBuffer(surf) &&
835           surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
836 }
837