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