PIGLIT_GL_TEST_CONFIG_END static enum piglit_result test_format(void) { GLboolean pass = GL_TRUE; GLuint texsrgb, texfb, fb; GLenum status; int i; float tex_vals[256][4]; float readf[256][4]; float tolerance; GLubyte readb[256][4]; float maxErr = 0.0f; for (i = 0; i < 256; i++) { tex_vals[i][0] = (float)i / 255.0f; tex_vals[i][1] = tex_vals[i][2] = 0.0f; tex_vals[i][3] = 1.0f; } /* initialize texture */ glGenTextures(1, &texsrgb); glBindTexture(GL_TEXTURE_2D, texsrgb); glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8_EXT, 16, 16, 0, GL_RGBA, GL_FLOAT, &tex_vals[0][0]); glGenFramebuffersEXT(1, &fb); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); glViewport(0, 0, piglit_width, piglit_height); /* draw into float framebuffer and verify results */ glGenTextures(1, &texfb); glBindTexture(GL_TEXTURE_2D, texfb); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, piglit_width, piglit_height, 0, GL_RGBA, GL_FLOAT, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texfb, 0); assert(glGetError() == 0); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); printf("Testing using fb float format"); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf(" - fbo incomplete (status = %s)\n", piglit_get_gl_enum_name(status)); piglit_report_subtest_result(PIGLIT_SKIP, "float fb"); return PIGLIT_SKIP; } printf("\n"); glColor4f(1, 1, 1, 1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texsrgb); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1); glDisable(GL_TEXTURE_2D); /* have to make up our own error measuring, since we measure error on srgb side (so with values mapped back to srgb using accurate formula) */ tolerance = 0.5f; /* as required by d3d10 */ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_FLOAT, &readf[0][0]); for (i = 0; i < 256; i++) { float err = fabs(piglit_linear_to_srgb(readf[i][0]) - (float)i); if (0) printf("readback: %f observed: %f expected: %f\n", readf[i][0], piglit_linear_to_srgb(readf[i][0]), (float)i); if (err > maxErr) { maxErr = err; } if (err > tolerance) { printf(" failed when testing srgb->float result\n"); pass = GL_FALSE; break; } } printf("max error srgb->linear was %f\n", maxErr); piglit_present_results(); piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL, "srgb->linear"); /* draw into srgb framebuffer and verify results */ glBindTexture(GL_TEXTURE_2D, texfb); glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8_EXT, piglit_width, piglit_height, 0, GL_RGBA, GL_FLOAT, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texfb, 0); assert(glGetError() == 0); glEnable(GL_FRAMEBUFFER_SRGB_EXT); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); printf("Testing using fb srgb format"); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf(" - fbo incomplete (status = %s)\n", piglit_get_gl_enum_name(status)); piglit_report_subtest_result(PIGLIT_SKIP, "srgb fb"); return PIGLIT_SKIP; } printf("\n"); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texsrgb); piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1); glDisable(GL_TEXTURE_2D); tolerance = 0.6f; /* as required by d3d10 */ /* TODO: should test this tolerance too really right now only test the previously converted from srgb values, so we only enforce any value stays the same when doing srgb->linear->srgb, which corresponds to 0.5 tolerance but only for these exact values. */ glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, &readb[0][0]); for (i = 0; i < 256; i++) { if (0) printf("observed: %d expected: %d\n", readb[i][0], i); if (readb[i][0] != i) { printf(" failed when testing srgb->float->srgb result\n"); pass = GL_FALSE; break; } } piglit_present_results(); piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL, "srgb->linear->srgb"); glDeleteTextures(1, &texfb); glDeleteTextures(1, &texsrgb); glDeleteFramebuffersEXT(1, &fb); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
/** * Common code for framebuffer and FBO tests. */ static GLboolean test_srgb(void) { GLboolean pass = GL_TRUE; GLboolean srgb_capable; float green[] = {0, 0.3, 0, 0}; float expected_green[4]; float expected_blend[4]; /* * Note: the window-system framebuffer may or may not be sRGB capable. * But the user-created FBO should be sRGB capable. */ glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable); glDisable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_FRAMEBUFFER_SRGB_EXT); glColor4fv(green); /* * First square: draw green square without sRGB and no blending */ piglit_draw_rect(0, 0, 20, 20); /* * Second square: draw a green square with sRGB enabled and no blending */ glEnable(GL_FRAMEBUFFER_SRGB_EXT); piglit_draw_rect(20, 0, 20, 20); /* * Third square: draw green square, then blend/add another on top of it */ glEnable(GL_FRAMEBUFFER_SRGB_EXT); piglit_draw_rect(40, 0, 20, 20); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); piglit_draw_rect(40, 0, 20, 20); glDisable(GL_BLEND); glDisable(GL_FRAMEBUFFER_SRGB_EXT); /* * Check first square. */ if (!piglit_probe_rect_rgb(0, 0, 20, 20, green)) pass = GL_FALSE; /* check pixel path */ glEnable(GL_FRAMEBUFFER_SRGB_EXT); if (!piglit_probe_rect_rgb(0, 0, 20, 20, green)) pass = GL_FALSE; glDisable(GL_FRAMEBUFFER_SRGB_EXT); /* * Check second square */ memcpy(expected_green, green, sizeof(float) * 4); if (srgb_capable) expected_green[1] = piglit_linear_to_srgb(green[1]); if (!piglit_probe_rect_rgb(20, 0, 20, 20, expected_green)) pass = GL_FALSE; /* check it doesn't affect the pixel path */ glEnable(GL_FRAMEBUFFER_SRGB_EXT); if (!piglit_probe_rect_rgb(20, 0, 20, 20, expected_green)) pass = GL_FALSE; glDisable(GL_FRAMEBUFFER_SRGB_EXT); /* * Check third square */ memcpy(expected_blend, green, sizeof(float) * 4); if (srgb_capable) expected_blend[1] = piglit_linear_to_srgb(green[1] * 2.0); else expected_blend[1] = green[1] * 2.0; if (!piglit_probe_rect_rgb(40, 0, 20, 20, expected_blend)) pass = GL_FALSE; return pass; }