Home | History | Annotate | Download | only in main
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      4  * Copyright 2009-2010 Chia-I Wu <olvaffe (at) 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
     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
     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
    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
    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
    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
    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
    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
    577 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
    578                  EGLint interval)
    579 {
    580    _eglClampSwapInterval(surf, interval);
    581    return EGL_TRUE;
    582 }
    583