diff options
author | Jason Ekstrand <jason.ekstrand@intel.com> | 2014-07-28 18:33:34 -0700 |
---|---|---|
committer | Jason Ekstrand <jason.ekstrand@intel.com> | 2014-08-22 12:54:53 -0700 |
commit | a4a466e8ffcc0ea9990bff677345411c34e56a3f (patch) | |
tree | 4c98310cdc85bdd0192c0c53b0ab87d21a543b06 | |
parent | 029228655fe64c9ff2abde437e84f9ea669d0633 (diff) |
util: Add a function for uploading multisample textures
One of the greatest difficulties in properly testing multisample textures
is actually generating and working with reference images. This adds a nice
little util function that allows you to upload a multisampled image as if
you were using glTexImage3D.
Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>
-rw-r--r-- | tests/util/piglit-util-gl.c | 202 | ||||
-rw-r--r-- | tests/util/piglit-util-gl.h | 5 |
2 files changed, 207 insertions, 0 deletions
diff --git a/tests/util/piglit-util-gl.c b/tests/util/piglit-util-gl.c index 6c9fa7cb7..b71100017 100644 --- a/tests/util/piglit-util-gl.c +++ b/tests/util/piglit-util-gl.c @@ -2470,6 +2470,208 @@ piglit_array_texture(GLenum target, GLenum internalformat, return tex; } +static const char multisample_texture_vs_source[] = +"#version 130\n" +"in vec2 vertex;\n" +"out vec2 tex_coords;\n" +"void main()\n" +"{\n" +" tex_coords = vertex;\n" +" vec2 pos = (vertex.xy * 2) - vec2(1, 1);\n" +" gl_Position = vec4(pos, 0, 1);\n" +"}\n"; + +static const char multisample_texture_fs_source[] = +"#version 130\n" +"#extension GL_ARB_sample_shading : enable\n" +"in vec2 tex_coords;\n" +"uniform sampler2DArray tex;\n" +"uniform int tex_depth;\n" +"uniform int z;\n" +"void main()\n" +"{\n" +" int layer = (gl_SampleID * tex_depth) + z;\n" +" gl_FragColor = texture(tex, vec3(tex_coords, layer));\n" +"}\n"; + +/** + * Uploads an arbitrary multisample texture. + * + * This function acts like glTexImage for multisample textures. If the + * input texture is zero, it will create one. Otherwise, it will use the + * texture given and assumes that glTexImage[23]DMultisample has already + * been called to establish the storage. + * + * When this function returns, multisample texture will be bound to the + * currently active texture. + * + * \param target either GL_TEXTURE_2D_MULTISAMPLE or + * GL_TEXTURE2D_MULTISAMPLE_ARRAY + * \param internalformat a renderable color format accepted by + * glTexImage2DMultisample + * \param width texture width + * \param height texture height + * \param depth texture depth. If target is + * GL_TEXTURE_2D_MULTISAMPLE, this must be 1. + * \param samples the number of samples + * \param format format of the pixel data + * \param type type of the pixel data + * \param data pixel data with whitch to fill the texture + * + * \return the new texture object id + */ +GLuint +piglit_multisample_texture(GLenum target, GLenum tex, GLenum internalFormat, + unsigned width, unsigned height, + unsigned depth, unsigned samples, + GLenum format, GLenum type, void *data) +{ + static GLuint prog = 0; + static GLint tex_loc, tex_depth_loc, z_loc; + static GLuint fbo, array_tex, ms_tex; + static const float verts[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + 1.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + }; + unsigned z; + + struct { + GLint active_tex; + GLint draw_fbo; + GLint prog; + GLint viewport[4]; + GLboolean arb_sample_shading; + GLfloat min_sample_shading; + GLint clamp_fragment_color; + } backup; + + piglit_require_extension("GL_ARB_texture_multisample"); + piglit_require_extension("GL_ARB_sample_shading"); + + if (target == GL_TEXTURE_2D_MULTISAMPLE) { + assert(depth == 1); + } else if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { + } else { + assert(!"Invalid texture target"); + return 0; + } + + if (prog == 0) { + /* First-run setup */ + prog = piglit_build_simple_program_unlinked( + multisample_texture_vs_source, + multisample_texture_fs_source); + glBindAttribLocation(prog, 0, "vertex"); + glLinkProgram(prog); + if (!piglit_link_check_status(prog)) { + prog = 0; + return 0; + } + + tex_loc = glGetUniformLocation(prog, "tex"); + tex_depth_loc = glGetUniformLocation(prog, "tex_depth"); + z_loc = glGetUniformLocation(prog, "z"); + + glGenFramebuffers(1, &fbo); + glGenTextures(1, &array_tex); + } + + /* Backup client values so we can restore them later */ + glGetIntegerv(GL_ACTIVE_TEXTURE, &backup.active_tex); + glGetIntegerv(GL_CURRENT_PROGRAM, &backup.prog); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &backup.draw_fbo); + glGetIntegerv(GL_CLAMP_FRAGMENT_COLOR, &backup.clamp_fragment_color); + glGetIntegerv(GL_VIEWPORT, backup.viewport); + glGetBooleanv(GL_SAMPLE_SHADING_ARB, &backup.arb_sample_shading); + glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_ARB, &backup.min_sample_shading); + + glEnable(GL_SAMPLE_SHADING_ARB); + glMinSampleShadingARB(1.0f); + + if (tex) { + ms_tex = tex; + } else { + glGenTextures(1, &ms_tex); + glBindTexture(target, ms_tex); + if (target == GL_TEXTURE_2D_MULTISAMPLE) { + assert(depth == 1); + glTexImage2DMultisample(target, samples, internalFormat, + width, height, GL_TRUE); + } else { + glTexImage3DMultisample(target, samples, internalFormat, + width, height, depth, GL_TRUE); + } + } + + glBindTexture(GL_TEXTURE_2D_ARRAY, array_tex); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, width, height, + depth * samples, 0, format, type, data); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glViewport(0, 0, width, height); + + glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + + glUseProgram(prog); + glUniform1i(tex_loc, backup.active_tex - GL_TEXTURE0); + glUniform1i(tex_depth_loc, depth); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts); + + if (target == GL_TEXTURE_2D_MULTISAMPLE) { + glUniform1i(z_loc, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + target, ms_tex, 0); + if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != + GL_FRAMEBUFFER_COMPLETE) + goto error; + + glDrawArrays(GL_TRIANGLES, 0, 6); + } else { + for (z = 0; z < depth; ++z) { + glUniform1i(z_loc, z); + glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + ms_tex, 0, z); + if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != + GL_FRAMEBUFFER_COMPLETE) + goto error; + + glDrawArrays(GL_TRIANGLES, 0, 6); + } + } + + glDisableVertexAttribArray(0); + + /* Restore values for the client */ + if (!backup.arb_sample_shading) + glDisable(GL_SAMPLE_SHADING_ARB); + glMinSampleShadingARB(backup.min_sample_shading); + + glUseProgram(backup.prog); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backup.draw_fbo); + glViewport(backup.viewport[0], backup.viewport[1], + backup.viewport[2], backup.viewport[3]); + glBindTexture(target, ms_tex); + glClampColor(GL_CLAMP_FRAGMENT_COLOR, backup.clamp_fragment_color); + + return ms_tex; + +error: + if (tex == 0) /* We created it, clean it up */ + glDeleteTextures(1, &ms_tex); + + return 0; +} + /** * Require transform feedback. * diff --git a/tests/util/piglit-util-gl.h b/tests/util/piglit-util-gl.h index fcd8988c7..5c7406975 100644 --- a/tests/util/piglit-util-gl.h +++ b/tests/util/piglit-util-gl.h @@ -204,6 +204,11 @@ GLuint piglit_rgbw_texture(GLenum internalFormat, int w, int h, GLboolean mip, GLboolean alpha, GLenum basetype); GLuint piglit_depth_texture(GLenum target, GLenum format, int w, int h, int d, GLboolean mip); GLuint piglit_array_texture(GLenum target, GLenum format, int w, int h, int d, GLboolean mip); +GLuint piglit_multisample_texture(GLenum target, GLenum tex, + GLenum internalFormat, + unsigned width, unsigned height, + unsigned depth, unsigned samples, + GLenum format, GLenum type, void *data); extern float piglit_tolerance[4]; void piglit_set_tolerance_for_bits(int rbits, int gbits, int bbits, int abits); extern void piglit_require_transform_feedback(void); |