void piglit_init(int argc, char **argv) { GLuint tex, view; GLuint buffer; int i, j; bool use_pbo = false; bool pass = true; #ifdef PIGLIT_USE_OPENGL piglit_require_extension("GL_ARB_texture_view"); #else piglit_require_extension("GL_OES_texture_view"); #endif for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "pbo") == 0) { piglit_require_extension("GL_ARB_pixel_buffer_object"); use_pbo = true; } } /* build a texture with full miptree */ glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexStorage2D(GL_TEXTURE_2D, NUM_LEVELS, GL_RGBA8, TEX_SIZE, TEX_SIZE); if (use_pbo) { glGenBuffers(1, &buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); } for (i=0; i < NUM_LEVELS; i++) { int dim = TEX_SIZE >> i; GLubyte *pixels = create_solid_image(dim, dim, 1, 4, i); if (!pixels) { printf("Failed to allocate image for level %d\n", i); piglit_report_result(PIGLIT_FAIL); } if (use_pbo) { glBufferData(GL_PIXEL_UNPACK_BUFFER, dim * dim * 4, pixels, GL_STREAM_DRAW); } glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, dim, dim, GL_RGBA, GL_UNSIGNED_BYTE, use_pbo ? NULL : pixels); free(pixels); } /* create a view to a subset of the layers */ glGenTextures(1, &view); glTextureView(view, GL_TEXTURE_2D, tex, GL_RGBA8, VIEW_MIN_LEVEL, VIEW_NUM_LEVELS, 0, 1); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* upload through the view */ glBindTexture(GL_TEXTURE_2D, view); for (i = 0; i < VIEW_NUM_LEVELS; i++) { int dim = TEX_SIZE >> (VIEW_MIN_LEVEL + i); GLubyte *pixels = create_solid_image(dim, dim, 1, 4, i + NUM_LEVELS); if (!pixels) { printf("Failed to allocate image for view level %d\n", i); piglit_report_result(PIGLIT_FAIL); } if (use_pbo) { glBufferData(GL_PIXEL_UNPACK_BUFFER, dim * dim * 4, pixels, GL_STREAM_DRAW); } glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, dim, dim, GL_RGBA, GL_UNSIGNED_BYTE, use_pbo ? NULL : pixels); free(pixels); } if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* bind the underlying texture and readback */ glBindTexture(GL_TEXTURE_2D, tex); for (i = 0; i < NUM_LEVELS; i++) { /* the levels inside the view should have been replaced. * everything else should be untouched. */ float expected_color[4]; int dim = TEX_SIZE >> i; int color_index = i; if (i >= VIEW_MIN_LEVEL && i < VIEW_MIN_LEVEL + VIEW_NUM_LEVELS) { color_index = i + NUM_LEVELS - VIEW_MIN_LEVEL; } printf("Testing level %d\n", i); for (j = 0; j < 4; j++) expected_color[j] = Colors[color_index][j] / 255.0f; pass = piglit_probe_texel_rect_rgba(GL_TEXTURE_2D, i, 0, 0, dim, dim, expected_color) && pass; } if (use_pbo) glDeleteBuffers(1, &buffer); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
/** * Simple views of textures; test rendering with various texture view targets */ static bool test_render_with_targets(GLenum target) { GLuint tex, newTex; GLint width = 128, height = 64, depth = 4, levels = 8; GLint l; bool pass = true; glUseProgram(0); glGenTextures(1, &tex); glBindTexture(target, tex); switch (target) { case GL_TEXTURE_1D: glTexStorage1D(target, levels, GL_RGBA8, width); height = 1; depth = 1; break; case GL_TEXTURE_2D: glTexStorage2D(target, levels, GL_RGBA8, width, height); depth = 1; break; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: glTexStorage3D(target, levels, GL_RGBA8, width, height, depth); break; default: /* only handle subset of legal targets */ piglit_report_result(PIGLIT_FAIL); assert(!"Illegal target for test_render_with_targets()\n"); break; } /* load each mipmap with a different color texture */ for (l = 0; l < levels; l++) { GLubyte *buf = create_solid_image(width, height, depth, 4, l); if (buf != NULL) { switch(target) { case GL_TEXTURE_1D: glTexSubImage1D(GL_TEXTURE_1D, l, 0, width, GL_RGBA, GL_UNSIGNED_BYTE, buf); break; case GL_TEXTURE_2D: glTexSubImage2D(GL_TEXTURE_2D, l, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); break; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY: glTexSubImage3D(target, l, 0, 0, 0, width, height, depth, GL_RGBA, GL_UNSIGNED_BYTE, buf); break; } free(buf); } else { piglit_report_result(PIGLIT_FAIL); assert(!"create_solid_image() failed\n"); } if (width > 1) width /= 2; if (height > 1) height /= 2; if (depth > 1 && target == GL_TEXTURE_3D) depth /= 2; } if (piglit_check_gl_error(GL_NO_ERROR) == GL_FALSE) { printf("%s: Found gl errors prior to testing glTextureView\n", TestName); glDeleteTextures(1, &tex); return false; } /* create view of texture and bind it to target */ glGenTextures(1, &newTex); glTextureView(newTex, target, tex, GL_RGBA8, 0, levels, 0, 1); glDeleteTextures(1, &tex); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glActiveTexture(GL_TEXTURE0); glBindTexture(target, newTex); /* draw a quad/line using each texture mipmap level */ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); for (l = 0; l < levels; l++) { GLfloat expected[3]; int p; glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, l); glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, l); glClear(GL_COLOR_BUFFER_BIT); switch (target) { case GL_TEXTURE_1D: glUseProgram(prog1D); glUniform1i(tex_loc_1D, 0); piglit_draw_rect_tex(-1.0, -1.0, 2.0, 2.0, 0.0, 0.0, 1.0, 1.0); break; case GL_TEXTURE_2D: glEnable(target); piglit_draw_rect_tex(-1.0, -1.0, 2.0, 2.0, 0.0, 0.0, 1.0, 1.0); glDisable(target); break; case GL_TEXTURE_2D_ARRAY: glUseProgram(prog2Darray); glUniform1i(tex_loc_2Darray, 0); draw_3d_depth(-1.0, -1.0, 2.0, 2.0, l); break; case GL_TEXTURE_3D: glEnable(target); draw_3d_depth(-1.0, -1.0, 2.0, 2.0, l); glDisable(target); break; } expected[0] = Colors[l][0] / 255.0; expected[1] = Colors[l][1] / 255.0; expected[2] = Colors[l][2] / 255.0; p = piglit_probe_pixel_rgb(piglit_width/2, piglit_height/2, expected); piglit_present_results(); #if 0 /* debug */ printf("for level=%d, target=%s, expected color=%f %f %f\n", l, piglit_get_gl_enum_name(target), expected[0], expected[1], expected[2]); sleep(1); #endif if (!p) { printf("%s: wrong color for mipmap level %d\n", TestName, l); pass = false; } } glDeleteTextures(1, &newTex); return pass; }
/** * Texture views with varying minimum and number of levels, 2D only */ static bool test_render_levels(void) { GLuint tex, new_tex; GLint width = 4096, height = 4096, levels =13; GLuint numLevels[] = {3,2,2,1}; GLint l; int expectedLevel; GLfloat expected[3]; int p; bool pass = true; glUseProgram(0); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGBA8, width, height); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* load each mipmap with a different color texture */ for (l = 0; l < levels; l++) { GLubyte *buf = create_solid_image(width, height, 1, 4, l); if (buf != NULL) { glTexSubImage2D(GL_TEXTURE_2D, l, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); free(buf); } if (width > 1) width /= 2; if (height > 1) height /= 2; } pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* create view of texture with restricted levels and draw quad */ /* using smallest mip level in the view range which varies every loop */ for (l = 0; l < ARRAY_SIZE(numLevels); l++) { glGenTextures(1, &new_tex); glTextureView(new_tex, GL_TEXTURE_2D, tex, GL_RGBA8, l, numLevels[l], 0, 1); glBindTexture(GL_TEXTURE_2D, new_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels-1); glClear(GL_COLOR_BUFFER_BIT); piglit_draw_rect_tex(-1.0, -1.0, 2.0/(float) (l+2), 2.0/ (float) (l+2), 0.0, 0.0, 1.0, 1.0); expectedLevel = l + numLevels[l] - 1; expected[0] = Colors[expectedLevel][0] / 255.0; expected[1] = Colors[expectedLevel][1] / 255.0; expected[2] = Colors[expectedLevel][2] / 255.0; p = piglit_probe_pixel_rgb(piglit_width/(2*(l+3)), piglit_height/(2*(l+3)), expected); piglit_present_results(); #if 0 { /* debug */ GLint param; glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, ¶m); printf("for view min level=%d base_level=%d exp color=%f %f %f\n", l, param, expected[0], expected[1], expected[2]); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, ¶m); printf("max_level=%d\n", param); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_VIEW_MIN_LEVEL, ¶m); printf("view min_level=%d\n", param); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_VIEW_NUM_LEVELS, ¶m); printf("view num_level=%d\n", param); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_LEVELS, ¶m); printf("immutable levels=%d\n", param); sleep(1); } #endif if (!p) { printf("%s: wrong color for view min level %d, expectedLevel %d\n", TestName, l, expectedLevel); pass = false; } glDeleteTextures(1, &new_tex); } glDisable(GL_TEXTURE_2D); glDeleteTextures(1, &tex); return pass; }
/** * Views with varying minimum and number of layers 2D_ARRAY only */ static bool test_render_layers(void) { GLuint tex, new_tex; GLint width = 16, height = 16, layers = 8; GLint l; GLint numLayers[] = {7, 1, 2, 2}; int expectedLayer; GLfloat expected[3]; int p; bool pass = true; glUseProgram(prog2Darray); glUniform1i(tex_loc_2Darray, 0); glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, tex); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, layers); /* load each array layer with a different color texture */ for (l = 0; l < layers; l++) { GLubyte *buf = create_solid_image(width, height, 1, 4, l); if (buf != NULL) { glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, l, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf); free(buf); } } pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* create view of texture with restricted layers and draw quad */ /* using a single layer in the view range which varies every loop */ for (l = 0; l < ARRAY_SIZE(numLayers); l++) { glGenTextures(1, &new_tex); glTextureView(new_tex, GL_TEXTURE_2D_ARRAY, tex, GL_RGBA8, 0, 1, l, numLayers[l]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, new_tex); glClear(GL_COLOR_BUFFER_BIT); expectedLayer = l + numLayers[l] - 1; draw_3d_depth(-1.0, -1.0, 2.0, 2.0, expectedLayer); expected[0] = Colors[expectedLayer][0] / 255.0; expected[1] = Colors[expectedLayer][1] / 255.0; expected[2] = Colors[expectedLayer][2] / 255.0; p = piglit_probe_pixel_rgb(piglit_width/2, piglit_height/2, expected); piglit_present_results(); #if 0 printf("for view min layer=%d expectedLayer=%d expected color=%f %f %f\n", l, expectedLayer, expected[0], expected[1], expected[2]); sleep(1); #endif if (!p) { printf("%s: wrong color for view min layer %d, expectedLayer %d\n", TestName, l, expectedLayer); pass = false; } glDeleteTextures(1, &new_tex); } glDeleteTextures(1, &tex); return pass; }
void piglit_init(int argc, char **argv) { GLuint tex, view, scratch; GLuint fbo; int i, j; bool pass = true; piglit_require_extension("GL_ARB_texture_storage"); piglit_require_extension("GL_ARB_texture_view"); /* build a 2d array texture; no mip levels */ glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_ARRAY, tex); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, TEX_SIZE, TEX_SIZE, NUM_LAYERS); for (i=0; i < NUM_LAYERS; i++) { GLubyte *pixels = create_solid_image(TEX_SIZE, TEX_SIZE, 1, 4, i); if (!pixels) { printf("Allocation failure for layer %d\n", i); piglit_report_result(PIGLIT_FAIL); } glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, TEX_SIZE, TEX_SIZE, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); free(pixels); } /* create a view of just one layer, as a non-array 2d texture */ glGenTextures(1, &view); glTextureView(view, GL_TEXTURE_2D, tex, GL_RGBA8, 0, 1, VIEW_MIN_LAYER, VIEW_NUM_LAYERS); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* create scratch fbo, clear into it */ glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glGenTextures(1, &scratch); glBindTexture(GL_TEXTURE_2D, scratch); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scratch, 0); if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) piglit_report_result(PIGLIT_FAIL); glViewport(0, 0, TEX_SIZE, TEX_SIZE); glClearColor(Colors[NUM_LAYERS][0] / 255.0f, Colors[NUM_LAYERS][1] / 255.0f, Colors[NUM_LAYERS][2] / 255.0f, Colors[NUM_LAYERS][3] / 255.0f); glClear(GL_COLOR_BUFFER_BIT); /* glCopyTexSubImage2D out of the scratch fbo */ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); glBindTexture(GL_TEXTURE_2D, view); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEX_SIZE, TEX_SIZE); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* bind the underlying texture and readback */ glBindTexture(GL_TEXTURE_2D_ARRAY, tex); for (i = 0; i < NUM_LAYERS; i++) { /* only the layer in the view should have been touched. */ int color_index; float expected_color[4]; color_index = i; if (i >= VIEW_MIN_LAYER && i < VIEW_MIN_LAYER + VIEW_NUM_LAYERS) color_index = i + NUM_LAYERS - VIEW_MIN_LAYER; printf("Testing layer %d\n", i); for (j = 0; j < 4; j++) expected_color[j] = Colors[color_index][j] / 255.0f; pass = piglit_probe_texel_volume_rgba(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, TEX_SIZE, TEX_SIZE, 1, expected_color) && pass; } piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
static bool test_format_lifetime(const struct format_desc desc0, const struct format_desc desc1) { GLuint tex, viewTex[3]; GLint width = 32, w, levels = 6; GLint l; int bytes; unsigned char *buffer0, *buffer1; bool pass = true; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_1D, tex); glTexStorage1D(GL_TEXTURE_1D, levels, desc0.storagefmt, width); glGenTextures(3, viewTex); glTextureView(viewTex[0], GL_TEXTURE_1D, tex, desc0.internalfmt, 0, levels, 0, 1); glTextureView(viewTex[1], GL_TEXTURE_1D, viewTex[0], desc1.internalfmt, 0, levels, 0, 1); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* load each mipmap with a different color texture */ w = width; bytes = (desc0.red + desc0.green + desc0.blue + desc0.alpha) / 8; for (l = 0; l < levels; l++) { GLubyte *buf = create_solid_image(width, 1, 1, bytes, l); if (buf != NULL) { glTexSubImage1D(GL_TEXTURE_1D, l, 0, w, desc0.imagefmt, desc0.imagetype, buf); free(buf); } else { piglit_report_result(PIGLIT_FAIL); assert(!"create_solid_image() failed\n"); } if (w > 1) w /= 2; } #if 0 /* debug */ printf("fmt0=%s, fmt1=%s, strgfmt0=%s, gettype0=%s\n", piglit_get_gl_enum_name(desc0.internalfmt), piglit_get_gl_enum_name(desc1.internalfmt), piglit_get_gl_enum_name(desc0.storagefmt), piglit_get_gl_enum_name(desc0.gettype)); printf("bytes=%d, width=%d, viewTex[0]=%d, [1]=%d, [2]=%d\n",bytes, width, viewTex[0], viewTex[1], viewTex[2]); #endif glDeleteTextures(1, &tex); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* compare view0 all level texels bytes to view1 texels bytes */ buffer0 = malloc(width * bytes); buffer1 = malloc(width * bytes); w = width; for (l = 0; l < levels; l++) { glBindTexture(GL_TEXTURE_1D, viewTex[0]); glGetTexImage(GL_TEXTURE_1D, l, desc0.getfmt, desc0.gettype, buffer0); glBindTexture(GL_TEXTURE_1D, viewTex[1]); glGetTexImage(GL_TEXTURE_1D, l, desc1.getfmt, desc1.gettype, buffer1); if (buffers_equal(buffer0, buffer1, w)) { pass = piglit_check_gl_error(GL_NO_ERROR) && pass; printf("level %d texel mismatch view0 and view1, width=%d\n", l, w); printf("internal format0 %s, internal format1 %s\n", piglit_get_gl_enum_name(desc0.internalfmt), piglit_get_gl_enum_name(desc1.internalfmt)); pass = false; } if (w > 1) w /= 2; } /* compare view1 base level texels to view2 after view0 and view1 deleted */ glBindTexture(GL_TEXTURE_1D, viewTex[1]); glGetTexImage(GL_TEXTURE_1D, 0, desc1.getfmt, desc1.gettype, buffer1); glTextureView(viewTex[2], GL_TEXTURE_1D, viewTex[0], desc0.internalfmt, 0, 1, 0, 1); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glDeleteTextures(2, viewTex); glBindTexture(GL_TEXTURE_1D, viewTex[2]); glGetTexImage(GL_TEXTURE_1D, 0, desc0.getfmt, desc0.gettype, buffer0); if (buffers_equal(buffer0, buffer1, width)) { pass = piglit_check_gl_error(GL_NO_ERROR) && pass; printf("Mismatched texels view1 and view2\n"); printf("internal format0 %s, internal format1 %s\n", piglit_get_gl_enum_name(desc0.internalfmt), piglit_get_gl_enum_name(desc1.internalfmt)); pass = false; } free(buffer0); free(buffer1); glDeleteTextures(1, &viewTex[2]); return pass; }