[Piglit] [PATCH] oes_texture_float tests: GL_OES_texture_float, GL_OES_texture_half_float, GL_OES_texture_float_linear and GL_OES_texture_half_float_linear

kevin.rogovin at intel.com kevin.rogovin at intel.com
Thu Jul 31 11:42:38 PDT 2014


From: Kevin Rogovin <kevin.rogovin at intel.com>

 Adds unit tests (based off of ARB_texture_float unit test) 
for GLES2 texture float extensions. 

---
 tests/all.py                                      |   8 +
 tests/spec/CMakeLists.txt                         |   1 +
 tests/spec/oes_texture_float/CMakeLists.gles2.txt |   6 +
 tests/spec/oes_texture_float/CMakeLists.txt       |   1 +
 tests/spec/oes_texture_float/oes_texture_float.c  | 514 ++++++++++++++++++++++
 5 files changed, 530 insertions(+)
 create mode 100644 tests/spec/oes_texture_float/CMakeLists.gles2.txt
 create mode 100644 tests/spec/oes_texture_float/CMakeLists.txt
 create mode 100644 tests/spec/oes_texture_float/oes_texture_float.c

diff --git a/tests/all.py b/tests/all.py
index 9d7a861..c6948cb 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -2865,6 +2865,14 @@ add_texwrap_format_tests(arb_texture_float, 'GL_ARB_texture_float')
 add_plain_test(arb_texture_float, 'arb_texture_float-texture-float-formats')
 add_msaa_formats_tests(arb_texture_float, 'GL_ARB_texture_float')
 
+oes_texture_float = {}
+spec['OES_texture_float'] = oes_texture_float
+add_concurrent_test(oes_texture_float, 'oes_texture_float')
+add_concurrent_test(oes_texture_float, 'oes_texture_float half')
+add_concurrent_test(oes_texture_float, 'oes_texture_float linear')
+add_concurrent_test(oes_texture_float, 'oes_texture_float half linear')
+
+
 ext_texture_integer = {}
 spec['EXT_texture_integer'] = ext_texture_integer
 # unsupported for int yet
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index c7001f1..c679e15 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -109,3 +109,4 @@ add_subdirectory (ext_image_dma_buf_import)
 add_subdirectory (arb_blend_func_extended)
 add_subdirectory (ext_unpack_subimage)
 add_subdirectory (arb_vertex_array_object)
+add_subdirectory (oes_texture_float)
diff --git a/tests/spec/oes_texture_float/CMakeLists.gles2.txt b/tests/spec/oes_texture_float/CMakeLists.gles2.txt
new file mode 100644
index 0000000..4e787e2
--- /dev/null
+++ b/tests/spec/oes_texture_float/CMakeLists.gles2.txt
@@ -0,0 +1,6 @@
+include_directories(
+	${GLEXT_INCLUDE_DIR}
+	${OPENGL_INCLUDE_PATH}
+)
+link_libraries(piglitutil_${piglit_target_api})
+piglit_add_executable(oes_texture_float oes_texture_float.c)
diff --git a/tests/spec/oes_texture_float/CMakeLists.txt b/tests/spec/oes_texture_float/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/oes_texture_float/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/oes_texture_float/oes_texture_float.c b/tests/spec/oes_texture_float/oes_texture_float.c
new file mode 100644
index 0000000..9ceb600
--- /dev/null
+++ b/tests/spec/oes_texture_float/oes_texture_float.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2011 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * Tests GL_OES_texture_float and GL_OES_texture_half_float 
+ * floating point formats
+ */
+
+/**
+ * This code is used to produces 2 distinct tests, one for
+ * GL_OES_texture_float and one for GL_OES_texture_half_float.
+ */
+#include <stdio.h>
+ 
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 20;
+
+	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static GLint TexWidth = 16, TexHeight = 16;
+static GLint BiasUniform = -1, ScaleUniform = -1, TexUniform = -1;
+static const float Scale = 1.0 / 2000.0, Bias = 0.5;
+
+
+
+struct format_info
+{
+   const char *Name;
+   GLenum Format;
+   int NumComponents;
+};
+
+static const struct format_info Formats[] = {
+  { "GL_RGBA",            GL_RGBA,            4 },
+  { "GL_RGB",             GL_RGB,             3 },
+  { "GL_ALPHA",           GL_ALPHA,           1 },
+  { "GL_LUMINANCE",       GL_LUMINANCE,       1 },
+  { "GL_LUMINANCE_ALPHA", GL_LUMINANCE_ALPHA, 2 },
+};
+
+static const char *VertShaderText = 
+  "attribute highp vec2 coord01; \n"
+  "varying mediump vec2 tex_coord; \n"
+  "void main() \n"
+  "{ \n"
+  "  tex_coord = coord01; \n"
+  "  gl_Position =vec4(coord01*2.0 - vec2(1.0, 1.0), 0.0, 1.0); \n"
+  "} \n";
+
+static const char *FragShaderText =
+   "uniform mediump float bias, scale; \n"
+   "uniform mediump sampler2D tex; \n"
+   "varying mediump vec2 tex_coord; \n"
+   "void main() \n"
+   "{ \n"
+   "   mediump vec4 t = vec4(texture2D(tex, tex_coord.xy)); \n"
+   "   gl_FragColor = t * scale + bias; \n"
+   "} \n";
+
+
+static GLuint Program, AttributeLoc;
+
+
+
+static void
+fill_array_fp32(int comps, int texels, void *buf, const float val[4])
+{
+   GLfloat *f = (GLfloat*) buf;
+   int i, j;
+
+   for (i = 0; i < texels; i++) {
+      for (j = 0; j < comps; j++) {
+         f[i * comps + j] = val[j];
+      }
+   }
+}
+
+
+/* Taken from Mesa: src/mesa/main/imports.h */
+typedef union { GLfloat f; GLint i; GLuint u; } fi_type;
+static inline int IROUND(float f)
+{
+   return (int) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F));
+}
+
+
+/* Taken from Mesa: src/mesa/main/imports.c */
+static int
+_mesa_round_to_even(float val)
+{
+   int rounded = IROUND(val);
+
+   if (val - floor(val) == 0.5) {
+      if (rounded % 2 != 0)
+         rounded += val > 0 ? -1 : 1;
+   }
+
+   return rounded;
+}
+
+static uint16_t
+_mesa_float_to_half(float val)
+{
+   const fi_type fi = {val};
+   const int flt_m = fi.i & 0x7fffff;
+   const int flt_e = (fi.i >> 23) & 0xff;
+   const int flt_s = (fi.i >> 31) & 0x1;
+   int s, e, m = 0;
+   uint16_t result;
+   
+   /* sign bit */
+   s = flt_s;
+
+   /* handle special cases */
+   if ((flt_e == 0) && (flt_m == 0)) {
+      /* zero */
+      /* m = 0; - already set */
+      e = 0;
+   }
+   else if ((flt_e == 0) && (flt_m != 0)) {
+      /* denorm -- denorm float maps to 0 half */
+      /* m = 0; - already set */
+      e = 0;
+   }
+   else if ((flt_e == 0xff) && (flt_m == 0)) {
+      /* infinity */
+      /* m = 0; - already set */
+      e = 31;
+   }
+   else if ((flt_e == 0xff) && (flt_m != 0)) {
+      /* NaN */
+      m = 1;
+      e = 31;
+   }
+   else {
+      /* regular number */
+      const int new_exp = flt_e - 127;
+      if (new_exp < -14) {
+         /* The float32 lies in the range (0.0, min_normal16) and is rounded
+          * to a nearby float16 value. The result will be either zero, subnormal,
+          * or normal.
+          */
+         e = 0;
+         m = _mesa_round_to_even((1 << 24) * fabsf(fi.f));
+      }
+      else if (new_exp > 15) {
+         /* map this value to infinity */
+         /* m = 0; - already set */
+         e = 31;
+      }
+      else {
+         /* The float32 lies in the range
+          *   [min_normal16, max_normal16 + max_step16)
+          * and is rounded to a nearby float16 value. The result will be
+          * either normal or infinite.
+          */
+         e = new_exp + 15;
+         m = _mesa_round_to_even(flt_m / (float) (1 << 13));
+      }
+   }
+
+   assert(0 <= m && m <= 1024);
+   if (m == 1024) {
+      /* The float32 was rounded upwards into the range of the next exponent,
+       * so bump the exponent. This correctly handles the case where f32
+       * should be rounded up to float16 infinity.
+       */
+      ++e;
+      m = 0;
+   }
+
+   result = (s << 15) | (e << 10) | m;
+   return result;
+
+}
+
+static void
+fill_array_fp16(int comps, int texels, void *buf, const float val[4])
+{
+   uint16_t *f = (uint16_t*) buf;
+   int i, j;
+
+   for (i = 0; i < texels; i++) {
+      for (j = 0; j < comps; j++) {
+        f[i * comps + j] = _mesa_float_to_half(val[j]);
+      }
+   }
+}
+
+
+struct texture_float_info
+{
+  void (*fill_array)(int comps, int texels, void *buf, const float val[4]);
+  GLenum TextureType;
+  size_t SizeOfType;
+  const char *TestName;
+  const char *ExtensionName;
+  const char *ExtensionNameLinearFilter;
+};
+
+const struct texture_float_info Tests[]=
+  {
+    {
+      fill_array_fp32, 
+      GL_FLOAT, 4, 
+      "oes-texture-float", 
+      "GL_OES_texture_float", 
+      "GL_OES_texture_float_linear"
+    },
+
+    {
+      fill_array_fp16, 
+      GL_HALF_FLOAT_OES, 2, 
+      "oes-texture-half-float", 
+      "GL_OES_texture_half_float", 
+      "GL_OES_texture_half_float_linear"
+    },
+  };
+
+
+static GLboolean
+check_error(const char *file, int line, const struct texture_float_info *test)
+{
+   GLenum err = glGetError();
+   if (err) {
+      printf("%s: error 0x%x at %s:%d\n", test->TestName, err, file, line);
+      return GL_TRUE;
+   }
+   return GL_FALSE;
+}
+
+
+/** Scale a float in [-1000, 1000] to [0, 1] */
+static float
+scale_and_bias(float val)
+{
+   return val * Scale + Bias;
+}
+
+
+/**
+ * Get a color to use for filling the texture image.
+ * Range of values is [-1000, 1000]
+ */
+static void
+get_texture_color(GLfloat value[4])
+{
+   static const GLfloat colors[12][4] = {
+      { 690.0, 633.0, -649.0, -975.0 },
+      { 409.0, -678.0, 624.0, -976.0 },
+      { -460.0, -102.0, -983.0, 120.0 },
+      { 202.0, 75.0, 826.0, -339.0 },
+      { -709.0, 620.0, 204.0, -666.0 },
+      { 718.0, -299.0, 290.0, 383.0 },
+      { 634.0, 235.0, 571.0, -651.0 },
+      { -984.0, -99.0, 448.0, 263.0 },
+      { -466.0, 356.0, -155.0, 500.0 },
+      { 678.0, -531.0, 81.0, -783.0 },
+      { -76.0, 98.0, -106.0, -875.0 },
+      { 730.0, -723.0, -656.0, -980.0 }
+   };
+   static int i = 0;
+   value[0] = colors[i][0];
+   value[1] = colors[i][1];
+   value[2] = colors[i][2];
+   value[3] = colors[i][3];
+   i = (i + 1) % 12;
+}
+
+
+/** \return GL_TRUE for pass, GL_FALSE for fail */
+static GLboolean
+test_format(const struct format_info *info, const struct texture_float_info *test)
+{
+   const int comps = info->NumComponents;
+   const int texels = TexWidth * TexHeight;
+   const int w = piglit_width / 10;
+   const int h = piglit_height / 10;
+   GLfloat expected[4];
+   void *image;
+   float value[4];
+   int p;
+   GLushort drawIndices[] = 
+     {
+       0, 1, 2,
+       0, 2, 3
+     };
+   
+   /** printf("Testing %s of %s\n", info->Name, test->TestName); **/
+
+   get_texture_color(value);
+
+   /* alloc, fill texture image */
+   image = malloc(comps * texels * test->SizeOfType);
+   test->fill_array(comps, texels, image, value);
+
+   
+   glTexImage2D(GL_TEXTURE_2D, 0, info->Format, TexWidth, TexHeight, 0,
+                info->Format, test->TextureType, image);
+   free(image);
+
+   if (check_error(__FILE__, __LINE__, test))
+      return GL_FALSE;
+
+   /* compute expected color */
+   switch (info->Format) {
+   case GL_RGBA:
+      expected[0] = scale_and_bias(value[0]);
+      expected[1] = scale_and_bias(value[1]);
+      expected[2] = scale_and_bias(value[2]);
+      expected[3] = scale_and_bias(value[3]);
+      break;
+   case GL_RGB:
+      expected[0] = scale_and_bias(value[0]);
+      expected[1] = scale_and_bias(value[1]);
+      expected[2] = scale_and_bias(value[2]);
+      expected[3] = scale_and_bias(1.0);
+      break;
+   case GL_ALPHA:
+      expected[0] =
+      expected[1] =
+      expected[2] = scale_and_bias(0.0);
+      expected[3] = scale_and_bias(value[0]);
+      break;
+   case GL_LUMINANCE:
+      expected[0] =
+      expected[1] =
+      expected[2] = scale_and_bias(value[0]);
+      expected[3] = scale_and_bias(1.0);
+      break;
+   case GL_LUMINANCE_ALPHA:
+      expected[0] =
+      expected[1] =
+      expected[2] = scale_and_bias(value[0]);
+      expected[3] = scale_and_bias(value[1]);
+      break;
+   default:
+      abort();
+   }
+
+   /* draw */
+
+   
+   
+   glClearColor(0.5, 0.5, 0.5, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT);
+   glDisable(GL_DEPTH_TEST);
+   glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, drawIndices);
+
+   /* test */
+   p = piglit_probe_pixel_rgba(w/2, h/2, expected);
+   if (!p) {
+      int i;
+
+      printf("  Failed with format %s:\n", info->Name);
+      printf("  Texture color = ");
+      for (i = 0; i < comps; i++) {
+         printf("%f", value[i]);
+         if (i + 1 < comps)
+            printf(", ");
+      }
+      printf("\n");
+   } 
+
+   piglit_swap_buffers();
+
+   
+   return p;
+}
+
+static GLboolean
+test_each_format(const struct texture_float_info *test)
+{
+  int f;
+  GLboolean pass = GL_TRUE;
+  for (f = 0; f < ARRAY_SIZE(Formats); f++) {
+     if (!test_format(&Formats[f], test)) {
+        pass = GL_FALSE;
+     }
+  }
+  return pass;
+}
+
+static const struct texture_float_info *ActiveTest = NULL;
+static GLboolean linearFilter = GL_FALSE;
+
+
+enum piglit_result
+piglit_display(void)
+{
+   GLboolean pass = GL_TRUE;
+   GLenum minFilters[6] = 
+     { 
+       GL_NEAREST, 
+       GL_LINEAR, 
+       GL_NEAREST_MIPMAP_NEAREST,
+       GL_NEAREST_MIPMAP_LINEAR,
+       GL_LINEAR_MIPMAP_NEAREST,
+       GL_LINEAR_MIPMAP_LINEAR,
+     };
+   GLenum magFilters[2] = 
+     {
+       GL_NEAREST,
+       GL_LINEAR,
+     };
+
+   if (linearFilter) {
+      int magFilterIdx, minFilterIdx;
+      GLenum magFilter, minFilter;
+      for (magFilterIdx = 0; magFilterIdx < 2; ++magFilterIdx) {
+         magFilter = magFilters[magFilterIdx];
+         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+         for (minFilterIdx = 0; minFilterIdx < 2; ++minFilterIdx) {
+            minFilter = minFilters[minFilterIdx];
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+            if (!test_each_format(ActiveTest)) {
+              pass = GL_FALSE;
+            }
+         } 
+      }
+   } else {
+     pass = test_each_format(ActiveTest);
+   }
+
+   return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static GLfloat AttributeValues[] = 
+  {
+    0.0f, 0.0f,
+    1.0f, 0.0f,
+    1.0f, 1.0f,
+    0.0f, 1.0f,
+  };
+
+void
+piglit_init(int argc, char **argv)
+{
+   GLuint Texture;
+   GLboolean half = GL_FALSE;
+   int i;
+
+   for (i = 1; i<argc; ++i) {
+      if (!strcmp(argv[i], "half")) {
+        half = GL_TRUE;
+      } else if (!strcmp(argv[i], "linear")) {
+        linearFilter = GL_TRUE;
+      }
+   }
+   
+   if (half) {
+     ActiveTest = &Tests[1];
+   } else {
+     ActiveTest = &Tests[0];
+   }
+
+   if (linearFilter) {
+     piglit_require_extension(ActiveTest->ExtensionNameLinearFilter);
+   }
+   piglit_require_extension(ActiveTest->ExtensionName);
+
+   Program = piglit_build_simple_program(VertShaderText, FragShaderText);
+
+   glUseProgram(Program);
+
+   BiasUniform = glGetUniformLocation(Program, "bias");
+   ScaleUniform = glGetUniformLocation(Program, "scale");
+   TexUniform = glGetUniformLocation(Program, "tex");
+   
+   glUniform1f(BiasUniform, Bias);
+   glUniform1f(ScaleUniform, Scale);
+   glUniform1i(TexUniform, 0);  /* tex unit zero */
+
+   AttributeLoc = glGetAttribLocation(Program, "coord01");
+   glEnableVertexAttribArray(AttributeLoc);
+   glVertexAttribPointer(AttributeLoc, 2, //slot, count 
+                         GL_FLOAT, GL_FALSE, //type, normalized
+                         2*sizeof(float), //stride
+                         AttributeValues); //pointer/offset
+
+   (void) check_error(__FILE__, __LINE__, ActiveTest);
+
+
+   glGenTextures(1, &Texture);
+   glBindTexture(GL_TEXTURE_2D, Texture);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+}
-- 
1.8.1.2



More information about the Piglit mailing list