Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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