mesa: Fix core GL genned-name handling for glBeginQuery().
[mesa.git] / src / mesa / main / format_pack.c
index 390b494c009a9b9876d696781659ffecd653001d..be6c026e8c2f4cb90ddb7c3e6251eef2b3a4540a 100644 (file)
 #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
 
 
+/** Helper struct for MESA_FORMAT_Z32_FLOAT_X24S8 */
+struct z32f_x24s8
+{
+   float z;
+   uint32_t x24s8;
+};
+
+
 typedef void (*pack_ubyte_rgba_row_func)(GLuint n,
                                          const GLubyte src[][4], void *dst);
 
@@ -636,7 +644,7 @@ pack_float_ARGB1555_REV(const GLfloat src[4], void *dst)
 static void
 pack_ubyte_AL44(const GLubyte src[4], void *dst)
 {
-   GLushort *d = ((GLushort *) dst);
+   GLubyte *d = ((GLubyte *) dst);
    *d = PACK_COLOR_44(src[ACOMP], src[RCOMP]);
 }
 
@@ -997,6 +1005,32 @@ pack_float_ARGB2101010(const GLfloat src[4], void *dst)
 }
 
 
+/* MESA_FORMAT_ABGR2101010_UINT */
+
+static void
+pack_ubyte_ABGR2101010_UINT(const GLubyte src[4], void *dst)
+{
+   GLuint *d = ((GLuint *) dst);
+   GLushort r = UBYTE_TO_USHORT(src[RCOMP]);
+   GLushort g = UBYTE_TO_USHORT(src[GCOMP]);
+   GLushort b = UBYTE_TO_USHORT(src[BCOMP]);
+   GLushort a = UBYTE_TO_USHORT(src[ACOMP]);
+   *d = PACK_COLOR_2101010_US(a, b, g, r);
+}
+
+static void
+pack_float_ABGR2101010_UINT(const GLfloat src[4], void *dst)
+{
+   GLuint *d = ((GLuint *) dst);
+   GLushort r, g, b, a;
+   UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]);
+   UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]);
+   UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]);
+   UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]);
+   *d = PACK_COLOR_2101010_US(a, b, g, r);
+}
+
+
 /* MESA_FORMAT_SRGB8 */
 
 static void
@@ -1688,6 +1722,7 @@ _mesa_get_pack_ubyte_rgba_function(gl_format format)
       table[MESA_FORMAT_RG1616] = pack_ubyte_RG1616;
       table[MESA_FORMAT_RG1616_REV] = pack_ubyte_RG1616_REV;
       table[MESA_FORMAT_ARGB2101010] = pack_ubyte_ARGB2101010;
+      table[MESA_FORMAT_ABGR2101010_UINT] = pack_ubyte_ABGR2101010_UINT;
 
       /* should never convert RGBA to these formats */
       table[MESA_FORMAT_Z24_S8] = NULL;
@@ -1833,6 +1868,7 @@ _mesa_get_pack_float_rgba_function(gl_format format)
       table[MESA_FORMAT_RG1616] = pack_float_RG1616;
       table[MESA_FORMAT_RG1616_REV] = pack_float_RG1616_REV;
       table[MESA_FORMAT_ARGB2101010] = pack_float_ARGB2101010;
+      table[MESA_FORMAT_ABGR2101010_UINT] = pack_float_ABGR2101010_UINT;
 
       /* should never convert RGBA to these formats */
       table[MESA_FORMAT_Z24_S8] = NULL;
@@ -2049,6 +2085,48 @@ _mesa_pack_ubyte_rgba_row(gl_format format, GLuint n,
 }
 
 
+/**
+ * Pack a 2D image of ubyte RGBA pixels in the given format.
+ * \param srcRowStride  source image row stride in bytes
+ * \param dstRowStride  destination image row stride in bytes
+ */
+void
+_mesa_pack_ubyte_rgba_rect(gl_format format, GLuint width, GLuint height,
+                           const GLubyte *src, GLint srcRowStride,
+                           void *dst, GLint dstRowStride)
+{
+   pack_ubyte_rgba_row_func packrow = get_pack_ubyte_rgba_row_function(format);
+   GLubyte *dstUB = (GLubyte *) dst;
+   GLuint i;
+
+   if (packrow) {
+      if (srcRowStride == width * 4 * sizeof(GLubyte) &&
+          dstRowStride == _mesa_format_row_stride(format, width)) {
+         /* do whole image at once */
+         packrow(width * height, (const GLubyte (*)[4]) src, dst);
+      }
+      else {
+         /* row by row */
+         for (i = 0; i < height; i++) {
+            packrow(width, (const GLubyte (*)[4]) src, dstUB);
+            src += srcRowStride;
+            dstUB += dstRowStride;
+         }
+      }
+   }
+   else {
+      /* slower fallback */
+      for (i = 0; i < height; i++) {
+         _mesa_pack_ubyte_rgba_row(format, width,
+                                   (const GLubyte (*)[4]) src, dstUB);
+         src += srcRowStride;
+         dstUB += dstRowStride;
+      }
+   }
+}
+
+
+
 /**
  ** Pack float Z pixels
  **/
@@ -2330,10 +2408,10 @@ _mesa_pack_float_z_row(gl_format format, GLuint n,
       break;
    case MESA_FORMAT_Z32_FLOAT_X24S8:
       {
-         GLfloat *d = ((GLfloat *) dst);
+         struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
          GLuint i;
          for (i = 0; i < n; i++) {
-            d[i * 2] = src[i];
+            d[i].z = src[i];
          }
       }
       break;
@@ -2403,13 +2481,13 @@ _mesa_pack_uint_z_row(gl_format format, GLuint n,
       break;
    case MESA_FORMAT_Z32_FLOAT_X24S8:
       {
-         GLfloat *d = ((GLfloat *) dst);
+         struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
          const GLdouble scale = 1.0 / (GLdouble) 0xffffffff;
          GLuint i;
          for (i = 0; i < n; i++) {
-            d[i * 2] = src[i] * scale;
-            assert(d[i * 2] >= 0.0f);
-            assert(d[i * 2] <= 1.0f);
+            d[i].z = src[i] * scale;
+            assert(d[i].z >= 0.0f);
+            assert(d[i].z <= 1.0f);
          }
       }
       break;
@@ -2453,10 +2531,10 @@ _mesa_pack_ubyte_stencil_row(gl_format format, GLuint n,
       break;
    case MESA_FORMAT_Z32_FLOAT_X24S8:
       {
-         GLfloat *d = ((GLfloat *) dst);
+         struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
          GLuint i;
          for (i = 0; i < n; i++) {
-            d[i * 2 + 1] = src[i];
+            d[i].x24s8 = src[i];
          }
       }
       break;
@@ -2488,9 +2566,96 @@ _mesa_pack_uint_24_8_depth_stencil_row(gl_format format, GLuint n,
          }
       }
       break;
+   case MESA_FORMAT_Z32_FLOAT_X24S8:
+      {
+         const GLdouble scale = 1.0 / (GLdouble) 0xffffff;
+         struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
+         GLint i;
+         for (i = 0; i < n; i++) {
+            GLfloat z = (src[i] >> 8) * scale;
+            d[i].z = z;
+            d[i].x24s8 = src[i];
+         }
+      }
+      break;
    default:
       _mesa_problem(NULL, "bad format %s in _mesa_pack_ubyte_s_row",
                     _mesa_get_format_name(format));
       return;
    }
 }
+
+
+
+/**
+ * Convert a boolean color mask to a packed color where each channel of
+ * the packed value at dst will be 0 or ~0 depending on the colorMask.
+ */
+void
+_mesa_pack_colormask(gl_format format, const GLubyte colorMask[4], void *dst)
+{
+   GLfloat maskColor[4];
+
+   switch (_mesa_get_format_datatype(format)) {
+   case GL_UNSIGNED_NORMALIZED:
+      /* simple: 1.0 will convert to ~0 in the right bit positions */
+      maskColor[0] = colorMask[0] ? 1.0 : 0.0;
+      maskColor[1] = colorMask[1] ? 1.0 : 0.0;
+      maskColor[2] = colorMask[2] ? 1.0 : 0.0;
+      maskColor[3] = colorMask[3] ? 1.0 : 0.0;
+      _mesa_pack_float_rgba_row(format, 1,
+                                (const GLfloat (*)[4]) maskColor, dst);
+      break;
+   case GL_SIGNED_NORMALIZED:
+   case GL_FLOAT:
+      /* These formats are harder because it's hard to know the floating
+       * point values that will convert to ~0 for each color channel's bits.
+       * This solution just generates a non-zero value for each color channel
+       * then fixes up the non-zero values to be ~0.
+       * Note: we'll need to add special case code if we ever have to deal
+       * with formats with unequal color channel sizes, like R11_G11_B10.
+       * We issue a warning below for channel sizes other than 8,16,32.
+       */
+      {
+         GLuint bits = _mesa_get_format_max_bits(format); /* bits per chan */
+         GLuint bytes = _mesa_get_format_bytes(format);
+         GLuint i;
+
+         /* this should put non-zero values into the channels of dst */
+         maskColor[0] = colorMask[0] ? -1.0f : 0.0f;
+         maskColor[1] = colorMask[1] ? -1.0f : 0.0f;
+         maskColor[2] = colorMask[2] ? -1.0f : 0.0f;
+         maskColor[3] = colorMask[3] ? -1.0f : 0.0f;
+         _mesa_pack_float_rgba_row(format, 1,
+                                   (const GLfloat (*)[4]) maskColor, dst);
+
+         /* fix-up the dst channels by converting non-zero values to ~0 */
+         if (bits == 8) {
+            GLubyte *d = (GLubyte *) dst;
+            for (i = 0; i < bytes; i++) {
+               d[i] = d[i] ? 0xff : 0x0;
+            }
+         }
+         else if (bits == 16) {
+            GLushort *d = (GLushort *) dst;
+            for (i = 0; i < bytes / 2; i++) {
+               d[i] = d[i] ? 0xffff : 0x0;
+            }
+         }
+         else if (bits == 32) {
+            GLuint *d = (GLuint *) dst;
+            for (i = 0; i < bytes / 4; i++) {
+               d[i] = d[i] ? 0xffffffffU : 0x0;
+            }
+         }
+         else {
+            _mesa_problem(NULL, "unexpected size in _mesa_pack_colormask()");
+            return;
+         }
+      }
+      break;
+   default:
+      _mesa_problem(NULL, "unexpected format data type in gen_color_mask()");
+      return;
+   }
+}