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