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