egl: Fixes transparency with EGL and X11.
[mesa.git] / src / mesa / drivers / dri / common / utils.c
index e0b3db8cf14267e9615d3569986fc83c025caa8f..2d57aef18f2734fd382f0d6aa168e0708595bcb2 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include <string.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include "utils.h"
 #include "dri_util.h"
 
-
-uint64_t
-driParseDebugString( const char * debug, 
-                    const struct dri_debug_control * control  )
-{
-   uint64_t flag = 0;
-
-   if ( debug != NULL ) {
-      while( control->string != NULL ) {
-        if ( !strcmp( debug, "all" ) ||
-             strstr( debug, control->string ) != NULL ) {
-           flag |= control->flag;
-        }
-
-        control++;
-      }
-   }
-
-   return flag;
-}
-
-
+/* WARNING: HACK: Local defines to avoid pulling glx.h.
+ *
+ * Any parts of this file that use the following defines are either partial or
+ * entirely broken wrt EGL.
+ *
+ * For example any getConfigAttrib() or indexConfigAttrib() query from EGL for
+ * SLOW or NON_CONFORMANT_CONFIG will not work as expected since the EGL tokens
+ * are different from the GLX ones.
+ */
+#define GLX_NONE                                                0x8000
+#define GLX_SLOW_CONFIG                                         0x8001
+#define GLX_NON_CONFORMANT_CONFIG                               0x800D
+#define GLX_DONT_CARE                                           0xFFFFFFFF
 
 /**
  * Create the \c GL_RENDERER string for DRI drivers.
@@ -156,18 +148,24 @@ driGetRendererString( char * buffer, const char * hardware_name,
  * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
  *                      \c stencil_bits.
  * \param db_modes      Array of buffer swap modes.  If an element has a
- *                      value of \c GLX_NONE, then it represents a
- *                      single-buffered mode.  Other valid values are
- *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
- *                      \c GLX_SWAP_UNDEFINED_OML.  See the
- *                      GLX_OML_swap_method extension spec for more details.
+ *                      value of \c __DRI_ATTRIB_SWAP_NONE, then it
+ *                      represents a single-buffered mode.  Other valid
+ *                      values are \c __DRI_ATTRIB_SWAP_EXCHANGE,
+ *                      \c __DRI_ATTRIB_SWAP_COPY, and \c __DRI_ATTRIB_SWAP_UNDEFINED.
+ *                      They represent the respective GLX values as in
+ *                      the GLX_OML_swap_method extension spec.
  * \param num_db_modes  Number of entries in \c db_modes.
  * \param msaa_samples  Array of msaa sample count. 0 represents a visual
  *                      without a multisample buffer.
  * \param num_msaa_modes Number of entries in \c msaa_samples.
- * \param visType       GLX visual type.  Usually either \c GLX_TRUE_COLOR or
- *                      \c GLX_DIRECT_COLOR.
- * 
+ * \param enable_accum  Add an accum buffer to the configs
+ * \param color_depth_match Whether the color depth must match the zs depth
+ *                          This forces 32-bit color to have 24-bit depth, and
+ *                          16-bit color to have 16-bit depth.
+ * \param mutable_render_buffer Enable __DRI_ATTRIB_MUTABLE_RENDER_BUFFER,
+ *                              which translates to
+ *                              EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.
+ *
  * \returns
  * Pointer to any array of pointers to the \c __DRIconfig structures created
  * for the specified formats.  If there is an error, \c NULL is returned.
@@ -180,22 +178,50 @@ driCreateConfigs(mesa_format format,
                 unsigned num_depth_stencil_bits,
                 const GLenum * db_modes, unsigned num_db_modes,
                 const uint8_t * msaa_samples, unsigned num_msaa_modes,
-                GLboolean enable_accum)
+                GLboolean enable_accum, GLboolean color_depth_match,
+                GLboolean mutable_render_buffer)
 {
-   static const uint32_t masks_table[][4] = {
+   static const struct {
+      uint32_t masks[4];
+      int shifts[4];
+   } format_table[] = {
       /* MESA_FORMAT_B5G6R5_UNORM */
-      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
+      {{ 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
+       { 11, 5, 0, -1 }},
       /* MESA_FORMAT_B8G8R8X8_UNORM */
-      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+      {{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+       { 16, 8, 0, -1 }},
       /* MESA_FORMAT_B8G8R8A8_UNORM */
-      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 },
+      {{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 },
+       { 16, 8, 0, 24 }},
       /* MESA_FORMAT_B10G10R10X2_UNORM */
-      { 0x3FF00000, 0x000FFC00, 0x000003FF, 0x00000000 },
+      {{ 0x3FF00000, 0x000FFC00, 0x000003FF, 0x00000000 },
+       { 20, 10, 0, -1 }},
       /* MESA_FORMAT_B10G10R10A2_UNORM */
-      { 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000 },
+      {{ 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000 },
+       { 20, 10, 0, 30 }},
+      /* MESA_FORMAT_R8G8B8A8_UNORM */
+      {{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 },
+       { 0, 8, 16, 24 }},
+      /* MESA_FORMAT_R8G8B8X8_UNORM */
+      {{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
+       { 0, 8, 16, -1 }},
+      /* MESA_FORMAT_R10G10B10X2_UNORM */
+      {{ 0x000003FF, 0x000FFC00, 0x3FF00000, 0x00000000 },
+       { 0, 10, 20, -1 }},
+      /* MESA_FORMAT_R10G10B10A2_UNORM */
+      {{ 0x000003FF, 0x000FFC00, 0x3FF00000, 0xC0000000 },
+       { 0, 10, 20, 30 }},
+      /* MESA_FORMAT_RGBX_FLOAT16 */
+      {{ 0, 0, 0, 0},
+       { 0, 16, 32, -1 }},
+      /* MESA_FORMAT_RGBA_FLOAT16 */
+      {{ 0, 0, 0, 0},
+       { 0, 16, 32, 48 }},
    };
 
    const uint32_t * masks;
+   const int * shifts;
    __DRIconfig **configs, **c;
    struct gl_config *modes;
    unsigned i, j, k, h;
@@ -206,27 +232,59 @@ driCreateConfigs(mesa_format format,
    int blue_bits;
    int alpha_bits;
    bool is_srgb;
+   bool is_float;
 
    switch (format) {
    case MESA_FORMAT_B5G6R5_UNORM:
-      masks = masks_table[0];
+      masks = format_table[0].masks;
+      shifts = format_table[0].shifts;
       break;
    case MESA_FORMAT_B8G8R8X8_UNORM:
-      masks = masks_table[1];
+   case MESA_FORMAT_B8G8R8X8_SRGB:
+      masks = format_table[1].masks;
+      shifts = format_table[1].shifts;
       break;
    case MESA_FORMAT_B8G8R8A8_UNORM:
    case MESA_FORMAT_B8G8R8A8_SRGB:
-      masks = masks_table[2];
+      masks = format_table[2].masks;
+      shifts = format_table[2].shifts;
+      break;
+   case MESA_FORMAT_R8G8B8A8_UNORM:
+   case MESA_FORMAT_R8G8B8A8_SRGB:
+      masks = format_table[5].masks;
+      shifts = format_table[5].shifts;
+      break;
+   case MESA_FORMAT_R8G8B8X8_UNORM:
+      masks = format_table[6].masks;
+      shifts = format_table[6].shifts;
       break;
    case MESA_FORMAT_B10G10R10X2_UNORM:
-      masks = masks_table[3];
+      masks = format_table[3].masks;
+      shifts = format_table[3].shifts;
       break;
    case MESA_FORMAT_B10G10R10A2_UNORM:
-      masks = masks_table[4];
+      masks = format_table[4].masks;
+      shifts = format_table[4].shifts;
+      break;
+   case MESA_FORMAT_RGBX_FLOAT16:
+      masks = format_table[9].masks;
+      shifts = format_table[9].shifts;
+      break;
+   case MESA_FORMAT_RGBA_FLOAT16:
+      masks = format_table[10].masks;
+      shifts = format_table[10].shifts;
+      break;
+   case MESA_FORMAT_R10G10B10X2_UNORM:
+      masks = format_table[7].masks;
+      shifts = format_table[7].shifts;
+      break;
+   case MESA_FORMAT_R10G10B10A2_UNORM:
+      masks = format_table[8].masks;
+      shifts = format_table[8].shifts;
       break;
    default:
       fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n",
-              __FUNCTION__, __LINE__,
+              __func__, __LINE__,
               _mesa_get_format_name(format), format);
       return NULL;
    }
@@ -235,10 +293,11 @@ driCreateConfigs(mesa_format format,
    green_bits = _mesa_get_format_bits(format, GL_GREEN_BITS);
    blue_bits = _mesa_get_format_bits(format, GL_BLUE_BITS);
    alpha_bits = _mesa_get_format_bits(format, GL_ALPHA_BITS);
-   is_srgb = _mesa_get_format_color_encoding(format) == GL_SRGB;
+   is_srgb = _mesa_is_format_srgb(format);
+   is_float = _mesa_get_format_datatype(format) == GL_FLOAT;
 
    num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
-   configs = calloc(1, (num_modes + 1) * sizeof *configs);
+   configs = calloc(num_modes + 1, sizeof *configs);
    if (configs == NULL)
        return NULL;
 
@@ -247,11 +306,25 @@ driCreateConfigs(mesa_format format,
        for ( i = 0 ; i < num_db_modes ; i++ ) {
            for ( h = 0 ; h < num_msaa_modes; h++ ) {
                for ( j = 0 ; j < num_accum_bits ; j++ ) {
+                   if (color_depth_match &&
+                       (depth_bits[k] || stencil_bits[k])) {
+                       /* Depth can really only be 0, 16, 24, or 32. A 32-bit
+                        * color format still matches 24-bit depth, as there
+                        * is an implicit 8-bit stencil. So really we just
+                        * need to make sure that color/depth are both 16 or
+                        * both non-16.
+                        */
+                       if ((depth_bits[k] + stencil_bits[k] == 16) !=
+                           (red_bits + green_bits + blue_bits + alpha_bits == 16))
+                           continue;
+                   }
+
                    *c = malloc (sizeof **c);
                    modes = &(*c)->modes;
                    c++;
 
                    memset(modes, 0, sizeof *modes);
+                   modes->floatMode = is_float;
                    modes->redBits   = red_bits;
                    modes->greenBits = green_bits;
                    modes->blueBits  = blue_bits;
@@ -260,6 +333,10 @@ driCreateConfigs(mesa_format format,
                    modes->greenMask = masks[1];
                    modes->blueMask  = masks[2];
                    modes->alphaMask = masks[3];
+                   modes->redShift   = shifts[0];
+                   modes->greenShift = shifts[1];
+                   modes->blueShift  = shifts[2];
+                   modes->alphaShift = shifts[3];
                    modes->rgbBits   = modes->redBits + modes->greenBits
                        + modes->blueBits + modes->alphaBits;
 
@@ -278,10 +355,10 @@ driCreateConfigs(mesa_format format,
                    modes->transparentBlue = GLX_DONT_CARE;
                    modes->transparentAlpha = GLX_DONT_CARE;
                    modes->transparentIndex = GLX_DONT_CARE;
-                   modes->rgbMode = GL_TRUE;
 
-                   if ( db_modes[i] == GLX_NONE ) {
+                   if (db_modes[i] == __DRI_ATTRIB_SWAP_NONE) {
                        modes->doubleBufferMode = GL_FALSE;
+                       modes->swapMethod = __DRI_ATTRIB_SWAP_UNDEFINED;
                    }
                    else {
                        modes->doubleBufferMode = GL_TRUE;
@@ -291,14 +368,6 @@ driCreateConfigs(mesa_format format,
                    modes->samples = msaa_samples[h];
                    modes->sampleBuffers = modes->samples ? 1 : 0;
 
-
-                   modes->haveAccumBuffer = ((modes->accumRedBits +
-                                          modes->accumGreenBits +
-                                          modes->accumBlueBits +
-                                          modes->accumAlphaBits) > 0);
-                   modes->haveDepthBuffer = (modes->depthBits > 0);
-                   modes->haveStencilBuffer = (modes->stencilBits > 0);
-
                    modes->bindToTextureRgb = GL_TRUE;
                    modes->bindToTextureRgba = GL_TRUE;
                    modes->bindToMipmapTexture = GL_FALSE;
@@ -309,6 +378,8 @@ driCreateConfigs(mesa_format format,
 
                    modes->yInverted = GL_TRUE;
                    modes->sRGBCapable = is_srgb;
+                   modes->mutableRenderBuffer = mutable_render_buffer;
+                   modes->configSelectGroup = 0;
                }
            }
        }
@@ -378,9 +449,13 @@ static const struct { unsigned int attrib, offset; } attribMap[] = {
     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,      transparentBlue),
     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,     transparentAlpha),
     __ATTRIB(__DRI_ATTRIB_RED_MASK,                    redMask),
+    __ATTRIB(__DRI_ATTRIB_RED_SHIFT,                   redShift),
     __ATTRIB(__DRI_ATTRIB_GREEN_MASK,                  greenMask),
+    __ATTRIB(__DRI_ATTRIB_GREEN_SHIFT,                 greenShift),
     __ATTRIB(__DRI_ATTRIB_BLUE_MASK,                   blueMask),
+    __ATTRIB(__DRI_ATTRIB_BLUE_SHIFT,                  blueShift),
     __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,                  alphaMask),
+    __ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT,                 alphaShift),
     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,           maxPbufferWidth),
     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,          maxPbufferHeight),
     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,          maxPbufferPixels),
@@ -393,13 +468,14 @@ static const struct { unsigned int attrib, offset; } attribMap[] = {
     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS,     bindToTextureTargets),
     __ATTRIB(__DRI_ATTRIB_YINVERTED,                   yInverted),
     __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE,    sRGBCapable),
+    __ATTRIB(__DRI_ATTRIB_MUTABLE_RENDER_BUFFER,       mutableRenderBuffer),
+    __ATTRIB(__DRI_ATTRIB_CONFIG_SELECT_GROUP, configSelectGroup),
 
     /* The struct field doesn't matter here, these are handled by the
      * switch in driGetConfigAttribIndex.  We need them in the array
      * so the iterator includes them though.*/
     __ATTRIB(__DRI_ATTRIB_RENDER_TYPE,                 level),
     __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT,               level),
-    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,                 level)
 };
 
 
@@ -415,6 +491,8 @@ driGetConfigAttribIndex(const __DRIconfig *config,
     case __DRI_ATTRIB_RENDER_TYPE:
         /* no support for color index mode */
        *value = __DRI_ATTRIB_RGBA_BIT;
+        if (config->modes.floatMode)
+            *value |= __DRI_ATTRIB_FLOAT_BIT;
        break;
     case __DRI_ATTRIB_CONFIG_CAVEAT:
        if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
@@ -424,10 +502,6 @@ driGetConfigAttribIndex(const __DRIconfig *config,
        else
            *value = 0;
        break;
-    case __DRI_ATTRIB_SWAP_METHOD:
-        /* XXX no return value??? */
-       break;
-
     default:
         /* any other int-sized field */
        *value = *(unsigned int *)
@@ -450,7 +524,7 @@ int
 driGetConfigAttrib(const __DRIconfig *config,
                   unsigned int attrib, unsigned int *value)
 {
-    int i;
+    unsigned i;
 
     for (i = 0; i < ARRAY_SIZE(attribMap); i++)
        if (attribMap[i].attrib == attrib)
@@ -485,6 +559,7 @@ driIndexConfigAttrib(const __DRIconfig *config, int index,
  * Currently only the following queries are supported by this function:
  *
  *     - \c __DRI2_RENDERER_VERSION
+ *     - \c __DRI2_RENDERER_PREFERRED_PROFILE
  *     - \c __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION
  *     - \c __DRI2_RENDERER_OPENGL_COMPATIBLITY_PROFILE_VERSION
  *     - \c __DRI2_RENDERER_ES_PROFILE_VERSION