Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1584)

Unified Diff: src/gpu/gl/GrGLColorConversionTest.cpp

Issue 5669045: Add test to detect bias in conversion of frag shader floats to bytes (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: remove unneeded deletes of fbo/rb Created 12 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/gl/GrGLColorConversionTest.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/gl/GrGLColorConversionTest.cpp
===================================================================
--- src/gpu/gl/GrGLColorConversionTest.cpp (revision 0)
+++ src/gpu/gl/GrGLColorConversionTest.cpp (revision 0)
@@ -0,0 +1,238 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLColorConversionTest.h"
+#include "GrGLContextInfo.h"
+#include "GrGLShaderVar.h"
+#include "GrGLSL.h"
+
+/**
+ * Draws a 256 pixel wide strip. At pixel i floating point values that are close
+ * to the high and low threshold of rounding to i when converted to bytes using
+ * round-to-nearest are output from the FS. After read pixels we check how the
+ * values were actually rounded. As a sanity check, a value smack dab in the
+ * middle of the range we expect to convert to i is also output.
+ */
+GrGLByteColorConversion
+ GrGLFloatToByteColorConversion(const GrGLContextInfo& ctxInfo) {
+
+ bool fail = true;
+
+ GrGLuint dstRb = 0;
+ GrGLuint dstFbo = 0;
+ GrGLuint vertBuf = 0;
+ GrGLuint vsId = 0;
+ GrGLuint fsId = 0;
+ GrGLuint progId = 0;
+ GrGLShaderVar posIn, tOut, tIn, colorOut;
+ GrStringBuilder vs, fs;
+
+ const GrGLInterface* gl = ctxInfo.interface();
+ GrGLSLGeneration gen = ctxInfo.glslGeneration();
+ GrGLBinding binding = ctxInfo.binding();
+
+ // setup the dst
+ GR_GL_CALL(gl, GenFramebuffers(1, &dstFbo));
+ GrAssert(0 != dstFbo);
+ GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, dstFbo));
+ GR_GL_CALL(gl, GenRenderbuffers(1, &dstRb));
+ GrAssert(0 != dstRb);
+ GR_GL_CALL(gl, BindRenderbuffer(GR_GL_RENDERBUFFER, dstRb));
+ GR_GL_CALL(gl, RenderbufferStorage(GR_GL_RENDERBUFFER,
+ GR_GL_RGBA8,
+ 256, 1));
+ GR_GL_CALL(gl, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_COLOR_ATTACHMENT0,
+ GR_GL_RENDERBUFFER,
+ dstRb));
+ GR_GL_CALL(gl, Viewport(0, 0, 256, 1));
+ GrGLenum status;
+ GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
+ goto FINISHED;
+ }
+
+ GR_GL_CALL_RET(gl, vsId, CreateShader(GR_GL_VERTEX_SHADER));
+ GR_GL_CALL_RET(gl, fsId, CreateShader(GR_GL_FRAGMENT_SHADER));
+ GR_GL_CALL_RET(gl, progId, CreateProgram());
+
+ GR_GL_CALL(gl, Disable(GR_GL_CULL_FACE));
+ GR_GL_CALL(gl, Disable(GR_GL_BLEND));
+ GR_GL_CALL(gl, Disable(GR_GL_DEPTH_TEST));
+ GR_GL_CALL(gl, Disable(GR_GL_DITHER));
+ GR_GL_CALL(gl, Disable(GR_GL_SCISSOR_TEST));
+ GR_GL_CALL(gl, Disable(GR_GL_STENCIL_TEST));
+ GR_GL_CALL(gl, ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
+
+ // setup the geometry: a single tri that fills the screen
+ static const GrGLfloat verts[] = {-2.f, -1.f,
+ 1.f, -1.f,
+ 1.f, 2.f};
+ GR_GL_CALL(gl, GenBuffers(1, &vertBuf));
+ GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, vertBuf));
+ GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER,
+ sizeof(verts),
+ verts,
+ GR_GL_STATIC_DRAW));
+ GR_GL_CALL(gl, EnableVertexAttribArray(0));
+ GR_GL_CALL(gl, VertexAttribPointer(0, // index
+ 2, // vector size
+ GR_GL_FLOAT,
+ false,
+ 2 * sizeof(GrGLfloat),
+ 0)); // offset
+
+
+ const char* verStr = GrGetGLSLVersionDecl(binding, gen);
+
+ posIn.set(GrGLShaderVar::kVec2f_Type,
+ GrGLShaderVar::kAttribute_TypeModifier,
+ "pos");
+ tOut.set(GrGLShaderVar::kVec2f_Type,
+ GrGLShaderVar::kOut_TypeModifier,
+ "t");
+ tIn.set(GrGLShaderVar::kVec2f_Type,
+ GrGLShaderVar::kIn_TypeModifier,
+ "t");
+ bool declColor = GrGLSLSetupFSColorOuput(gen, "color", &colorOut);
+
+ vs.append(verStr);
+ posIn.appendDecl(ctxInfo, &vs);
+ tOut.appendDecl(ctxInfo, &vs);
+ vs.appendf("void main() {\n"
+ " gl_Position = vec4(%s.xy, 0.0, 1.0);\n"
+ " %s = (%s + vec2(1.0, 1.0)) / 2.0;\n"
+ "}\n",
+ posIn.getName().c_str(),
+ tOut.getName().c_str(),
+ posIn.getName().c_str());
+
+ fs.append(verStr);
+ fs.append(GrGetGLSLShaderPrecisionDecl(binding));
+ tIn.appendDecl(ctxInfo, &fs);
+
+ if (declColor) {
+ colorOut.appendDecl(ctxInfo, &fs);
+ }
+ fs.append( "void main() {\n");
+ fs.appendf(" float intVal = floor(%s.x * 256.0) ;\n", tIn.getName().c_str());
+ fs.append( " float justAboveExpectedLowCutoff = (intVal - 0.49) / 255.0;\n");
+ fs.append( " float justBelowExpectedHighCutoff = (intVal + 0.49) / 255.0;\n");
+ fs.append( " float middleOfExpectedRange = intVal / 255.0;\n");
+ fs.appendf(" %s = vec4(justAboveExpectedLowCutoff,justBelowExpectedHighCutoff,middleOfExpectedRange,0.0);\n", colorOut.getName().c_str());
+ fs.append( "}\n");
+
+ GrGLint vsCompiled = GR_GL_INIT_ZERO;
+ const GrGLchar* vsStr = vs.c_str();
+ const GrGLint vsLen = vs.size();
+ GrAssert(0 != vsId);
+ GR_GL_CALL(gl, ShaderSource(vsId, 1, &vsStr, &vsLen));
+ GR_GL_CALL(gl, CompileShader(vsId));
+ GR_GL_CALL(gl, GetShaderiv(vsId, GR_GL_COMPILE_STATUS, &vsCompiled));
+ if (!vsCompiled) {
+ goto FINISHED;
+ }
+
+ GrGLint fsCompiled = GR_GL_INIT_ZERO;
+ const GrGLchar* fsStr = fs.c_str();
+ const GrGLint fsLen = fs.size();
+ GrAssert(0 != fsId);
+ GR_GL_CALL(gl, ShaderSource(fsId, 1, &fsStr, &fsLen));
+ GR_GL_CALL(gl, CompileShader(fsId));
+ GR_GL_CALL(gl, GetShaderiv(fsId, GR_GL_COMPILE_STATUS, &fsCompiled));
+ if (!fsCompiled) {
+ goto FINISHED;
+ }
+
+ GrGLint progLinked = GR_GL_INIT_ZERO;
+ GrAssert(0 != progId);
+ GR_GL_CALL(gl, AttachShader(progId, vsId));
+ GR_GL_CALL(gl, AttachShader(progId, fsId));
+ if (declColor) {
+ GR_GL_CALL(gl, BindFragDataLocation(progId, 0,
+ colorOut.getName().c_str()));
+ }
+ GR_GL_CALL(gl, BindAttribLocation(progId, 0, posIn.getName().c_str()));
+ GR_GL_CALL(gl, LinkProgram(progId));
+ GR_GL_CALL(gl, GetProgramiv(progId, GR_GL_LINK_STATUS, &progLinked));
+ if (!progLinked) {
+ goto FINISHED;
+ }
+ GR_GL_CALL(gl, UseProgram(progId));
+
+ GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, 3));
+ uint32_t readData[256];
+ // set to junk values just in case readPixels silently fails (as it is
+ // known to do on some Intel GMA drivers).
+ memset(readData, 0xab, sizeof(readData));
+ GR_GL_CALL(gl, PixelStorei(GR_GL_PACK_ALIGNMENT, 4));
+ GR_GL_CALL(gl, ReadPixels(0, 0, 256, 1, GR_GL_RGBA,
+ GR_GL_UNSIGNED_BYTE, readData));
+
+ bool foundHighBias = false;
+ bool foundLowBias = false;
+ for (int i = 0; i < 256 && (!foundHighBias || !foundLowBias); ++i) {
+ int nearLowCutoffVal = readData[i] & 0x000000ff;
+ int nearHighCutoffVal = (readData[i] & 0x0000ff00) >> 8;
+ int middle = (readData[i] & 0x00ff0000) >> 16;
+
+ if (middle != i) {
+ goto FINISHED;
+ }
+
+ int diff0 = i - nearLowCutoffVal;
+ int diff1 = nearHighCutoffVal - i;
+ if (diff0 < 0 || diff0 > 1) {
+ goto FINISHED;
+ }
+ if (diff1 < 0 || diff1 > 1) {
+ goto FINISHED;
+ }
+
+ if (1 == diff0) {
+ foundHighBias = true;
+ }
+
+ if (1 == diff1) {
+ foundLowBias = true;
+ }
+ }
+ fail = (foundHighBias && foundLowBias);
+
+FINISHED:
+ if (dstFbo) {
+ GR_GL_CALL(gl, DeleteFramebuffers(1, &dstFbo));
+ }
+ if (dstRb) {
+ GR_GL_CALL(gl, DeleteRenderbuffers(1, &dstRb));
+ }
+ if (vertBuf) {
+ GR_GL_CALL(gl, DeleteBuffers(1, &vertBuf));
+ }
+ if (vsId) {
+ GR_GL_CALL(gl, DeleteShader(vsId));
+ }
+ if (fsId) {
+ GR_GL_CALL(gl, DeleteShader(fsId));
+ }
+ if (progId) {
+ GR_GL_CALL(gl, DeleteProgram(progId));
+ }
+
+ if (fail) {
+ return kUnknown_GrGLByteColorConversion;
+ }
+
+ if (foundHighBias) {
+ return kHigh_GrGLByteColorConversion;
+ } else if (foundLowBias) {
+ return kLow_GrGLByteColorConversion;
+ } else {
+ return kRound_GrGLByteColorConversion;
+ }
+}
Property changes on: src\gpu\gl\GrGLColorConversionTest.cpp
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « src/gpu/gl/GrGLColorConversionTest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b