summaryrefslogtreecommitdiff
path: root/tests/fbo
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2011-02-17 14:59:27 -0700
committerBrian Paul <brianp@vmware.com>2011-02-17 15:01:04 -0700
commitdf2ce5530179c44d960c96e8c1194a528219b056 (patch)
treeb0c87d1dbb29951cfbbbdb5bcfa1ada14b03f064 /tests/fbo
parent209f3d642a2825f103e2147d7ef356806d1255a5 (diff)
fbo-depth-sample-compare: compare depth texture sampling vs. fragment.z
Multi-pass algorithms that compare fragment Z to a depth texture sample can exercise this sort of thing.
Diffstat (limited to 'tests/fbo')
-rw-r--r--tests/fbo/CMakeLists.txt1
-rw-r--r--tests/fbo/fbo-depth-sample-compare.c365
2 files changed, 366 insertions, 0 deletions
diff --git a/tests/fbo/CMakeLists.txt b/tests/fbo/CMakeLists.txt
index 74ea97c39..38c95c8f2 100644
--- a/tests/fbo/CMakeLists.txt
+++ b/tests/fbo/CMakeLists.txt
@@ -21,6 +21,7 @@ link_libraries (
add_executable (fbo-1d fbo-1d.c)
add_executable (fbo-depth fbo-depth.c)
+add_executable (fbo-depth-sample-compare fbo-depth-sample-compare.c)
add_executable (fbo-depthtex fbo-depthtex.c)
add_executable (fbo-3d fbo-3d.c)
add_executable (fbo-alpha fbo-alpha.c)
diff --git a/tests/fbo/fbo-depth-sample-compare.c b/tests/fbo/fbo-depth-sample-compare.c
new file mode 100644
index 000000000..23a5d29b4
--- /dev/null
+++ b/tests/fbo/fbo-depth-sample-compare.c
@@ -0,0 +1,365 @@
+/*
+ * 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
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+/**
+ * Test rendering to a depth texture, sampling from it, and comparing the
+ * texture depth values against the fragment Z values when drawing the
+ * same object a second time.
+ *
+ * The left side of the window should be mostly black. Red pixels indicate
+ * errors.
+ * The center and right parts of the window should show gray-scale spheres
+ * on a white background (they're just Z buffer images as gray-scale).
+ *
+ * Brian Paul
+ * 17 Feb 2011
+ */
+
+
+#include <assert.h>
+#include "piglit-util.h"
+
+
+#define SIZE 256
+
+
+int piglit_width = 3 * SIZE;
+int piglit_height = SIZE;
+int piglit_window_mode = GLUT_DOUBLE | GLUT_DEPTH;
+
+static GLfloat ErrorScale = 0.0;
+static GLuint ColorTex, DepthTex, FBO;
+static GLuint ShaderProg;
+static GLint Zbits;
+
+
+static void
+create_fbo(void)
+{
+ GLenum depthIntFormat = GL_DEPTH_COMPONENT24;
+ GLenum status;
+
+ /* depth texture */
+ glGenTextures(1, &DepthTex);
+ glBindTexture(GL_TEXTURE_2D, DepthTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, depthIntFormat,
+ SIZE, SIZE, 0,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ assert(glGetError() == 0);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH_SIZE, &Zbits);
+
+ /* color texture */
+ glGenTextures(1, &ColorTex);
+ glBindTexture(GL_TEXTURE_2D, ColorTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ SIZE, SIZE, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ assert(glGetError() == 0);
+
+ /* Create FBO */
+ glGenFramebuffersEXT(1, &FBO);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D,
+ ColorTex,
+ 0);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_TEXTURE_2D,
+ DepthTex,
+ 0);
+
+ assert(glGetError() == 0);
+
+ status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ piglit_report_result(PIGLIT_SKIP);
+ }
+}
+
+
+static void
+create_frag_shader(void)
+{
+ /* This shader samples the currently bound depth texture, then compares
+ * that value to the current fragment Z value to produce a shade of red
+ * indicating error/difference.
+ *
+ * E.g: gl_FragColor = scale * abs(texture.Z - fragment.Z);
+ *
+ * Note that we have to be pretty careful with converting gl_FragCoord
+ * into a texture coordinate. There's a -0.5 bias and scale factor.
+ */
+ static const char *text =
+ "uniform sampler2D zTex; \n"
+ "uniform float sizeScale; \n"
+ "uniform float errorScale; \n"
+ "void main() \n"
+ "{ \n"
+ " vec2 coord = (gl_FragCoord.xy - vec2(0.5)) / sizeScale; \n"
+ " vec4 z = texture2D(zTex, coord); \n"
+ " float diff = errorScale * abs(z.r - gl_FragCoord.z); \n"
+ " //gl_FragColor = vec4(gl_FragCoord.z, 0, 0, 0); \n"
+ " //gl_FragColor = z; \n"
+ " gl_FragColor = vec4(diff, 0, 0, 0); \n"
+ "} \n";
+ GLuint fs;
+ GLint zTex, errorScale, sizeScale;
+
+ fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, text);
+ assert(fs);
+
+ ShaderProg = piglit_link_simple_program(0, fs);
+ assert(ShaderProg);
+
+ glUseProgram(ShaderProg);
+
+ zTex = glGetUniformLocation(ShaderProg, "zTex");
+ glUniform1i(zTex, 0); /* unit 0 */
+
+ errorScale = glGetUniformLocation(ShaderProg, "errorScale");
+ glUniform1f(errorScale, ErrorScale);
+
+ sizeScale = glGetUniformLocation(ShaderProg, "sizeScale");
+ glUniform1f(sizeScale, (float) (SIZE - 1));
+
+ glUseProgram(0);
+}
+
+
+
+static void
+render_to_fbo(void)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
+
+ glViewport(0, 0, SIZE, SIZE);
+
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1.0);
+
+ glColor4f(1.0, 0.0, 0.0, 0.0);
+ glutSolidSphere(0.95, 40, 20);
+
+ glDisable(GL_DEPTH_TEST);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+}
+
+
+/** Show contents of depth buffer in middle of window */
+static void
+show_depth_fbo(void)
+{
+ GLfloat *z = (GLfloat *) malloc(SIZE * SIZE * sizeof(GLfloat));
+
+ glViewport(1 * SIZE, 0, SIZE, SIZE); /* not really needed */
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
+ glReadPixels(0, 0, SIZE, SIZE, GL_DEPTH_COMPONENT, GL_FLOAT, z);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ glWindowPos2i(SIZE, 0);
+ glDrawPixels(SIZE, SIZE, GL_LUMINANCE, GL_FLOAT, z);
+ assert(glGetError() == 0);
+ free(z);
+}
+
+
+/** Draw quad textured with depth image on right side of window */
+static void
+draw_quad_with_depth_texture(void)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ glViewport(2 * SIZE, 0, SIZE, SIZE);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1.0);
+
+ glBindTexture(GL_TEXTURE_2D, DepthTex);
+ glEnable(GL_TEXTURE_2D);
+
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0, 0);
+ glVertex2f(-1, -1);
+ glTexCoord2f(1, 0);
+ glVertex2f( 1, -1);
+ glTexCoord2f(1, 1);
+ glVertex2f( 1, 1);
+ glTexCoord2f(0, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+
+ glDisable(GL_TEXTURE_2D);
+}
+
+
+/**
+ * Draw quad with fragment shader that compares fragment.z against the
+ * depth texture value (draw on left side of window).
+ * We draw on the left side of the window to easily convert gl_FragCoord
+ * into a texture coordinate.
+ */
+static void
+draw_sphere_with_fragment_shader_compare(void)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ glViewport(0 * SIZE, 0, SIZE, SIZE);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBindTexture(GL_TEXTURE_2D, DepthTex);
+
+ glUseProgram(ShaderProg);
+
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -1, 1.0);
+
+ glEnable(GL_DEPTH_TEST);
+
+ if (1) {
+ glutSolidSphere(0.95, 40, 20);
+ }
+ else {
+ /* To test using gl_TexCoord[0].xy instead of gl_FragCoord.xy in the shader
+ */
+ static const GLfloat sPlane[4] = {0.5, 0, 0, 0.5};
+ static const GLfloat tPlane[4] = {0, 0.5, 0, 0.5};
+
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
+ glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+
+ glutSolidSphere(0.95, 40, 20);
+
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ }
+
+ glDisable(GL_DEPTH_TEST);
+
+ glUseProgram(0);
+}
+
+
+static enum piglit_result
+count_and_report_bad_pixels(void)
+{
+ GLubyte *z;
+ GLuint error = 0;
+ int i;
+
+ z = (GLubyte *) malloc(SIZE * SIZE * 4 * sizeof(GLubyte));
+ glReadPixels(0, 0, SIZE, SIZE, GL_RGBA, GL_UNSIGNED_BYTE, z);
+
+ for (i = 0; i < SIZE * SIZE * 4; i += 4) {
+ error += z[i];
+ }
+ free(z);
+
+ if (!piglit_automatic)
+ printf("total error = %u\n", error);
+
+ /* XXX this error test is a total hack for now */
+ if (error > ErrorScale)
+ return PIGLIT_FAILURE;
+ else
+ return PIGLIT_SUCCESS;
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+ enum piglit_result result;
+
+ render_to_fbo();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ show_depth_fbo();
+
+ draw_quad_with_depth_texture();
+
+ draw_sphere_with_fragment_shader_compare();
+
+ result = count_and_report_bad_pixels();
+
+ glutSwapBuffers();
+
+ return result;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+ if (argc > 1) {
+ ErrorScale = atof(argv[1]);
+ }
+
+ piglit_require_extension("GL_EXT_framebuffer_object");
+ piglit_require_extension("GL_ARB_shader_objects");
+ piglit_require_extension("GL_ARB_fragment_shader");
+
+ create_fbo();
+
+ if (ErrorScale == 0.0) {
+ /* A 1-bit error/difference in Z values results in a delta of 64 in
+ * pixel intensity (where pixels are in [0,255]).
+ */
+ ErrorScale = ((float) (1 << Zbits)) * 64.0 / 255.0;
+ }
+
+ create_frag_shader();
+
+ if (!piglit_automatic) {
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+ printf("Left: Shader showing difference pixels (black=good, red=error)\n");
+ printf("Middle: Depth buffer of FBO\n");
+ printf("Right: Quad textured with depth values\n");
+ printf("Z bits = %d\n", Zbits);
+ printf("ErrorScale = %f\n", ErrorScale);
+ }
+}