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