• 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 /**
32  * Surface-related functions.
33  */
34 
35 
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "egldisplay.h"
40 #include "egldriver.h"
41 #include "eglcontext.h"
42 #include "eglconfig.h"
43 #include "eglcurrent.h"
44 #include "egllog.h"
45 #include "eglsurface.h"
46 
47 
48 static void
_eglClampSwapInterval(_EGLSurface * surf,EGLint interval)49 _eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
50 {
51    EGLint bound = surf->Config->MaxSwapInterval;
52    if (interval >= bound) {
53       interval = bound;
54    }
55    else {
56       bound = surf->Config->MinSwapInterval;
57       if (interval < bound)
58          interval = bound;
59    }
60    surf->SwapInterval = interval;
61 }
62 
63 
64 /**
65  * Parse the list of surface attributes and return the proper error code.
66  */
67 static EGLint
_eglParseSurfaceAttribList(_EGLSurface * surf,const EGLint * attrib_list)68 _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
69 {
70    _EGLDisplay *dpy = surf->Resource.Display;
71    EGLint type = surf->Type;
72    EGLint texture_type = EGL_PBUFFER_BIT;
73    EGLint i, err = EGL_SUCCESS;
74    EGLint attr = EGL_NONE;
75    EGLint val = EGL_NONE;
76 
77    if (!attrib_list)
78       return EGL_SUCCESS;
79 
80    if (dpy->Extensions.NOK_texture_from_pixmap)
81       texture_type |= EGL_PIXMAP_BIT;
82 
83    for (i = 0; attrib_list[i] != EGL_NONE; i++) {
84       attr = attrib_list[i++];
85       val = attrib_list[i];
86 
87       switch (attr) {
88       /* common attributes */
89       case EGL_GL_COLORSPACE_KHR:
90          if (!dpy->Extensions.KHR_gl_colorspace) {
91             err = EGL_BAD_ATTRIBUTE;
92             break;
93          }
94          switch (val) {
95          case EGL_GL_COLORSPACE_SRGB_KHR:
96          case EGL_GL_COLORSPACE_LINEAR_KHR:
97             break;
98          default:
99             err = EGL_BAD_ATTRIBUTE;
100          }
101          if (err != EGL_SUCCESS)
102             break;
103          surf->GLColorspace = val;
104          break;
105       case EGL_VG_COLORSPACE:
106          switch (val) {
107          case EGL_VG_COLORSPACE_sRGB:
108          case EGL_VG_COLORSPACE_LINEAR:
109             break;
110          default:
111             err = EGL_BAD_ATTRIBUTE;
112             break;
113          }
114          if (err != EGL_SUCCESS)
115             break;
116          surf->VGColorspace = val;
117          break;
118       case EGL_VG_ALPHA_FORMAT:
119          switch (val) {
120          case EGL_VG_ALPHA_FORMAT_NONPRE:
121          case EGL_VG_ALPHA_FORMAT_PRE:
122             break;
123          default:
124             err = EGL_BAD_ATTRIBUTE;
125             break;
126          }
127          if (err != EGL_SUCCESS)
128             break;
129          surf->VGAlphaFormat = val;
130          break;
131       /* window surface attributes */
132       case EGL_RENDER_BUFFER:
133          if (type != EGL_WINDOW_BIT) {
134             err = EGL_BAD_ATTRIBUTE;
135             break;
136          }
137          if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
138             err = EGL_BAD_ATTRIBUTE;
139             break;
140          }
141          surf->RenderBuffer = val;
142          break;
143       case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
144          if (!dpy->Extensions.NV_post_sub_buffer ||
145              type != EGL_WINDOW_BIT) {
146             err = EGL_BAD_ATTRIBUTE;
147             break;
148          }
149          if (val != EGL_TRUE && val != EGL_FALSE) {
150             err = EGL_BAD_PARAMETER;
151             break;
152          }
153          surf->PostSubBufferSupportedNV = val;
154          break;
155       /* pbuffer surface attributes */
156       case EGL_WIDTH:
157          if (type != EGL_PBUFFER_BIT) {
158             err = EGL_BAD_ATTRIBUTE;
159             break;
160          }
161          if (val < 0) {
162             err = EGL_BAD_PARAMETER;
163             break;
164          }
165          surf->Width = val;
166          break;
167       case EGL_HEIGHT:
168          if (type != EGL_PBUFFER_BIT) {
169             err = EGL_BAD_ATTRIBUTE;
170             break;
171          }
172          if (val < 0) {
173             err = EGL_BAD_PARAMETER;
174             break;
175          }
176          surf->Height = val;
177          break;
178       case EGL_LARGEST_PBUFFER:
179          if (type != EGL_PBUFFER_BIT) {
180             err = EGL_BAD_ATTRIBUTE;
181             break;
182          }
183          surf->LargestPbuffer = !!val;
184          break;
185       /* for eglBindTexImage */
186       case EGL_TEXTURE_FORMAT:
187          if (!(type & texture_type)) {
188             err = EGL_BAD_ATTRIBUTE;
189             break;
190          }
191 
192          switch (val) {
193          case EGL_TEXTURE_RGB:
194          case EGL_TEXTURE_RGBA:
195          case EGL_NO_TEXTURE:
196             break;
197          default:
198             err = EGL_BAD_ATTRIBUTE;
199             break;
200          }
201          if (err != EGL_SUCCESS)
202             break;
203          surf->TextureFormat = val;
204          break;
205       case EGL_TEXTURE_TARGET:
206          if (!(type & texture_type)) {
207             err = EGL_BAD_ATTRIBUTE;
208             break;
209          }
210 
211          switch (val) {
212          case EGL_TEXTURE_2D:
213          case EGL_NO_TEXTURE:
214             break;
215          default:
216             err = EGL_BAD_ATTRIBUTE;
217             break;
218          }
219          if (err != EGL_SUCCESS)
220             break;
221          surf->TextureTarget = val;
222          break;
223       case EGL_MIPMAP_TEXTURE:
224          if (!(type & texture_type)) {
225             err = EGL_BAD_ATTRIBUTE;
226             break;
227          }
228          surf->MipmapTexture = !!val;
229          break;
230       /* no pixmap surface specific attributes */
231       default:
232          err = EGL_BAD_ATTRIBUTE;
233          break;
234       }
235 
236       if (err != EGL_SUCCESS)
237          break;
238    }
239 
240    if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
241       if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) ||
242           (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) {
243          attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT;
244          err = EGL_BAD_MATCH;
245       }
246    }
247 
248    if (err != EGL_SUCCESS)
249       _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
250 
251    return err;
252 }
253 
254 
255 /**
256  * Do error check on parameters and initialize the given _EGLSurface object.
257  * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
258  */
259 EGLBoolean
_eglInitSurface(_EGLSurface * surf,_EGLDisplay * dpy,EGLint type,_EGLConfig * conf,const EGLint * attrib_list)260 _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
261                 _EGLConfig *conf, const EGLint *attrib_list)
262 {
263    const char *func;
264    EGLint renderBuffer = EGL_BACK_BUFFER;
265    EGLint swapBehavior = EGL_BUFFER_DESTROYED;
266    EGLint err;
267 
268    /* Swap behavior can be preserved only if config supports this. */
269    if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
270       swapBehavior = EGL_BUFFER_PRESERVED;
271 
272    switch (type) {
273    case EGL_WINDOW_BIT:
274       func = "eglCreateWindowSurface";
275       swapBehavior = EGL_BUFFER_DESTROYED;
276       break;
277    case EGL_PIXMAP_BIT:
278       func = "eglCreatePixmapSurface";
279       renderBuffer = EGL_SINGLE_BUFFER;
280       break;
281    case EGL_PBUFFER_BIT:
282       func = "eglCreatePBufferSurface";
283       break;
284    default:
285       _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
286       return EGL_FALSE;
287    }
288 
289    if ((conf->SurfaceType & type) == 0) {
290       /* The config can't be used to create a surface of this type */
291       _eglError(EGL_BAD_MATCH, func);
292       return EGL_FALSE;
293    }
294 
295    _eglInitResource(&surf->Resource, sizeof(*surf), dpy);
296    surf->Type = type;
297    surf->Config = conf;
298 
299    surf->Width = 0;
300    surf->Height = 0;
301    surf->TextureFormat = EGL_NO_TEXTURE;
302    surf->TextureTarget = EGL_NO_TEXTURE;
303    surf->MipmapTexture = EGL_FALSE;
304    surf->LargestPbuffer = EGL_FALSE;
305    surf->RenderBuffer = renderBuffer;
306    surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
307    surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
308    surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
309 
310    surf->MipmapLevel = 0;
311    surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
312    surf->SwapBehavior = swapBehavior;
313 
314    surf->HorizontalResolution = EGL_UNKNOWN;
315    surf->VerticalResolution = EGL_UNKNOWN;
316    surf->AspectRatio = EGL_UNKNOWN;
317 
318    surf->PostSubBufferSupportedNV = EGL_FALSE;
319 
320    /* the default swap interval is 1 */
321    _eglClampSwapInterval(surf, 1);
322 
323    err = _eglParseSurfaceAttribList(surf, attrib_list);
324    if (err != EGL_SUCCESS)
325       return _eglError(err, func);
326 
327    /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
328    if (surf->LargestPbuffer) {
329       surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
330       surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
331    }
332 
333    return EGL_TRUE;
334 }
335 
336 
337 EGLBoolean
_eglQuerySurface(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surface,EGLint attribute,EGLint * value)338 _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
339                  EGLint attribute, EGLint *value)
340 {
341    switch (attribute) {
342    case EGL_WIDTH:
343       *value = surface->Width;
344       break;
345    case EGL_HEIGHT:
346       *value = surface->Height;
347       break;
348    case EGL_CONFIG_ID:
349       *value = surface->Config->ConfigID;
350       break;
351    case EGL_LARGEST_PBUFFER:
352       if (surface->Type == EGL_PBUFFER_BIT)
353          *value = surface->LargestPbuffer;
354       break;
355    case EGL_TEXTURE_FORMAT:
356       /* texture attributes: only for pbuffers, no error otherwise */
357       if (surface->Type == EGL_PBUFFER_BIT)
358          *value = surface->TextureFormat;
359       break;
360    case EGL_TEXTURE_TARGET:
361       if (surface->Type == EGL_PBUFFER_BIT)
362          *value = surface->TextureTarget;
363       break;
364    case EGL_MIPMAP_TEXTURE:
365       if (surface->Type == EGL_PBUFFER_BIT)
366          *value = surface->MipmapTexture;
367       break;
368    case EGL_MIPMAP_LEVEL:
369       if (surface->Type == EGL_PBUFFER_BIT)
370          *value = surface->MipmapLevel;
371       break;
372    case EGL_SWAP_BEHAVIOR:
373       *value = surface->SwapBehavior;
374       break;
375    case EGL_RENDER_BUFFER:
376       *value = surface->RenderBuffer;
377       break;
378    case EGL_PIXEL_ASPECT_RATIO:
379       *value = surface->AspectRatio;
380       break;
381    case EGL_HORIZONTAL_RESOLUTION:
382       *value = surface->HorizontalResolution;
383       break;
384    case EGL_VERTICAL_RESOLUTION:
385       *value = surface->VerticalResolution;
386       break;
387    case EGL_MULTISAMPLE_RESOLVE:
388       *value = surface->MultisampleResolve;
389       break;
390    case EGL_VG_ALPHA_FORMAT:
391       *value = surface->VGAlphaFormat;
392       break;
393    case EGL_VG_COLORSPACE:
394       *value = surface->VGColorspace;
395       break;
396    case EGL_GL_COLORSPACE_KHR:
397       if (!dpy->Extensions.KHR_gl_colorspace) {
398          _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
399          return EGL_FALSE;
400       }
401       *value = surface->GLColorspace;
402       break;
403    case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
404       *value = surface->PostSubBufferSupportedNV;
405       break;
406    case EGL_BUFFER_AGE_EXT:
407       if (!dpy->Extensions.EXT_buffer_age) {
408          _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
409          return EGL_FALSE;
410       }
411       *value = drv->API.QueryBufferAge(drv, dpy, surface);
412       break;
413    default:
414       _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
415       return EGL_FALSE;
416    }
417 
418    return EGL_TRUE;
419 }
420 
421 
422 /**
423  * Default fallback routine - drivers might override this.
424  */
425 EGLBoolean
_eglSurfaceAttrib(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surface,EGLint attribute,EGLint value)426 _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
427                   EGLint attribute, EGLint value)
428 {
429    EGLint confval;
430    EGLint err = EGL_SUCCESS;
431    EGLint all_es_bits = EGL_OPENGL_ES_BIT |
432                         EGL_OPENGL_ES2_BIT |
433                         EGL_OPENGL_ES3_BIT_KHR;
434 
435    switch (attribute) {
436    case EGL_MIPMAP_LEVEL:
437       confval = surface->Config->RenderableType;
438       if (!(confval & all_es_bits)) {
439          err = EGL_BAD_PARAMETER;
440          break;
441       }
442       surface->MipmapLevel = value;
443       break;
444    case EGL_MULTISAMPLE_RESOLVE:
445       switch (value) {
446       case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
447          break;
448       case EGL_MULTISAMPLE_RESOLVE_BOX:
449          confval = surface->Config->SurfaceType;
450          if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
451             err = EGL_BAD_MATCH;
452          break;
453       default:
454          err = EGL_BAD_ATTRIBUTE;
455          break;
456       }
457       if (err != EGL_SUCCESS)
458          break;
459       surface->MultisampleResolve = value;
460       break;
461    case EGL_SWAP_BEHAVIOR:
462       switch (value) {
463       case EGL_BUFFER_DESTROYED:
464          break;
465       case EGL_BUFFER_PRESERVED:
466          confval = surface->Config->SurfaceType;
467          if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
468             err = EGL_BAD_MATCH;
469          break;
470       default:
471          err = EGL_BAD_ATTRIBUTE;
472          break;
473       }
474       if (err != EGL_SUCCESS)
475          break;
476       surface->SwapBehavior = value;
477       break;
478    default:
479       err = EGL_BAD_ATTRIBUTE;
480       break;
481    }
482 
483    if (err != EGL_SUCCESS)
484       return _eglError(err, "eglSurfaceAttrib");
485    return EGL_TRUE;
486 }
487 
488 
489 EGLBoolean
_eglBindTexImage(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surface,EGLint buffer)490 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
491                  EGLint buffer)
492 {
493    EGLint texture_type = EGL_PBUFFER_BIT;
494 
495    /* Just do basic error checking and return success/fail.
496     * Drivers must implement the real stuff.
497     */
498 
499    if (dpy->Extensions.NOK_texture_from_pixmap)
500       texture_type |= EGL_PIXMAP_BIT;
501 
502    if (!(surface->Type & texture_type)) {
503       _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
504       return EGL_FALSE;
505    }
506 
507    if (surface->TextureFormat == EGL_NO_TEXTURE) {
508       _eglError(EGL_BAD_MATCH, "eglBindTexImage");
509       return EGL_FALSE;
510    }
511 
512    if (surface->TextureTarget == EGL_NO_TEXTURE) {
513       _eglError(EGL_BAD_MATCH, "eglBindTexImage");
514       return EGL_FALSE;
515    }
516 
517    if (buffer != EGL_BACK_BUFFER) {
518       _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
519       return EGL_FALSE;
520    }
521 
522    surface->BoundToTexture = EGL_TRUE;
523 
524    return EGL_TRUE;
525 }
526 
527 EGLBoolean
_eglReleaseTexImage(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surf,EGLint buffer)528 _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
529                     EGLint buffer)
530 {
531    /* Just do basic error checking and return success/fail.
532     * Drivers must implement the real stuff.
533     */
534 
535    EGLint texture_type = EGL_PBUFFER_BIT;
536 
537    if (surf == EGL_NO_SURFACE)
538    {
539       _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
540       return EGL_FALSE;
541    }
542 
543    if (!surf->BoundToTexture)
544    {
545       /* Not an error, simply nothing to do */
546       return EGL_TRUE;
547    }
548 
549    if (surf->TextureFormat == EGL_NO_TEXTURE)
550    {
551       _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
552       return EGL_FALSE;
553    }
554 
555    if (buffer != EGL_BACK_BUFFER)
556    {
557       _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
558       return EGL_FALSE;
559    }
560 
561    if (dpy->Extensions.NOK_texture_from_pixmap)
562       texture_type |= EGL_PIXMAP_BIT;
563 
564    if (!(surf->Type & texture_type))
565    {
566       _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
567       return EGL_FALSE;
568    }
569 
570    surf->BoundToTexture = EGL_FALSE;
571 
572    return EGL_TRUE;
573 }
574 
575 
576 EGLBoolean
_eglSwapInterval(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surf,EGLint interval)577 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
578                  EGLint interval)
579 {
580    _eglClampSwapInterval(surf, interval);
581    return EGL_TRUE;
582 }
583