1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Fragment operation test utilities.
22 *//*--------------------------------------------------------------------*/
24 #include "glsFragmentOpUtil.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "glwFunctions.hpp"
29 #include "glwEnums.hpp"
35 namespace FragmentOpUtil
39 inline T triQuadInterpolate (const T values[4], float xFactor, float yFactor)
41 if (xFactor + yFactor < 1.0f)
42 return values[0] + (values[2]-values[0])*xFactor + (values[1]-values[0])*yFactor;
44 return values[3] + (values[1]-values[3])*(1.0f-xFactor) + (values[2]-values[3])*(1.0f-yFactor);
47 // GLSL ES 1.0 shaders
48 static const char* s_glsl1VertSrc =
49 "attribute highp vec4 a_position;\n"
50 "attribute mediump vec4 a_color;\n"
51 "varying mediump vec4 v_color;\n"
54 " gl_Position = a_position;\n"
55 " v_color = a_color;\n"
57 static const char* s_glsl1FragSrc =
58 "varying mediump vec4 v_color;\n"
61 " gl_FragColor = v_color;\n"
64 // GLSL ES 3.0 shaders
65 static const char* s_glsl3VertSrc =
67 "in highp vec4 a_position;\n"
68 "in mediump vec4 a_color;\n"
69 "out mediump vec4 v_color;\n"
72 " gl_Position = a_position;\n"
73 " v_color = a_color;\n"
75 static const char* s_glsl3FragSrc =
77 "in mediump vec4 v_color;\n"
78 "layout(location = 0) out mediump vec4 o_color;\n"
81 " o_color = v_color;\n"
85 static const char* s_glsl33VertSrc =
87 "in vec4 a_position;\n"
91 "out vec4 v_color1;\n"
94 " gl_Position = a_position;\n"
95 " v_color = a_color;\n"
96 " v_color1 = a_color1;\n"
98 static const char* s_glsl33FragSrc =
101 "in vec4 v_color1;\n"
102 "layout(location = 0, index = 0) out vec4 o_color;\n"
103 "layout(location = 0, index = 1) out vec4 o_color1;\n"
106 " o_color = v_color;\n"
107 " o_color1 = v_color1;\n"
110 static const char* getVertSrc (glu::GLSLVersion glslVersion)
112 if (glslVersion == glu::GLSL_VERSION_100_ES)
113 return s_glsl1VertSrc;
114 else if (glslVersion == glu::GLSL_VERSION_300_ES)
115 return s_glsl3VertSrc;
116 else if (glslVersion == glu::GLSL_VERSION_330)
117 return s_glsl33VertSrc;
123 static const char* getFragSrc (glu::GLSLVersion glslVersion)
125 if (glslVersion == glu::GLSL_VERSION_100_ES)
126 return s_glsl1FragSrc;
127 else if (glslVersion == glu::GLSL_VERSION_300_ES)
128 return s_glsl3FragSrc;
129 else if (glslVersion == glu::GLSL_VERSION_330)
130 return s_glsl33FragSrc;
136 QuadRenderer::QuadRenderer (const glu::RenderContext& context, glu::GLSLVersion glslVersion)
137 : m_context (context)
138 , m_program (DE_NULL)
142 , m_blendFuncExt (!glu::glslVersionIsES(glslVersion) && (glslVersion >= glu::GLSL_VERSION_330))
144 DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES ||
145 glslVersion == glu::GLSL_VERSION_300_ES ||
146 glslVersion == glu::GLSL_VERSION_330);
148 const glw::Functions& gl = context.getFunctions();
149 const char* vertSrc = getVertSrc(glslVersion);
150 const char* fragSrc = getFragSrc(glslVersion);
152 m_program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
153 if (!m_program->isOk())
156 throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
159 m_positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_position");
160 m_colorLoc = gl.getAttribLocation(m_program->getProgram(), "a_color");
163 m_color1Loc = gl.getAttribLocation(m_program->getProgram(), "a_color1");
165 if (m_positionLoc < 0 || m_colorLoc < 0 || (m_blendFuncExt && m_color1Loc < 0))
168 throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
172 QuadRenderer::~QuadRenderer (void)
177 void QuadRenderer::render (const Quad& quad) const
179 const float position[] =
181 quad.posA.x(), quad.posA.y(), quad.depth[0], 1.0f,
182 quad.posA.x(), quad.posB.y(), quad.depth[1], 1.0f,
183 quad.posB.x(), quad.posA.y(), quad.depth[2], 1.0f,
184 quad.posB.x(), quad.posB.y(), quad.depth[3], 1.0f
186 const deUint8 indices[] = { 0, 2, 1, 1, 2, 3 };
188 DE_STATIC_ASSERT(sizeof(tcu::Vec4) == sizeof(float)*4);
189 DE_STATIC_ASSERT(sizeof(quad.color) == sizeof(float)*4*4);
190 DE_STATIC_ASSERT(sizeof(quad.color1) == sizeof(float)*4*4);
192 std::vector<glu::VertexArrayBinding> vertexArrays;
194 vertexArrays.push_back(glu::va::Float(m_positionLoc, 4, 4, 0, &position[0]));
195 vertexArrays.push_back(glu::va::Float(m_colorLoc, 4, 4, 0, (const float*)&quad.color[0]));
198 vertexArrays.push_back(glu::va::Float(m_color1Loc, 4, 4, 0, (const float*)&quad.color1[0]));
200 m_context.getFunctions().useProgram(m_program->getProgram());
201 glu::draw(m_context, m_program->getProgram(),
202 (int)vertexArrays.size(), &vertexArrays[0],
203 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
206 ReferenceQuadRenderer::ReferenceQuadRenderer (void)
207 : m_fragmentBufferSize(0)
209 for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_fragmentDepths); i++)
210 m_fragmentDepths[i] = 0.0f;
213 void ReferenceQuadRenderer::flushFragmentBuffer (const rr::MultisamplePixelBufferAccess& colorBuffer,
214 const rr::MultisamplePixelBufferAccess& depthBuffer,
215 const rr::MultisamplePixelBufferAccess& stencilBuffer,
216 rr::FaceType faceType,
217 const rr::FragmentOperationState& state)
219 m_fragmentProcessor.render(colorBuffer, depthBuffer, stencilBuffer, &m_fragmentBuffer[0], m_fragmentBufferSize, faceType, state);
220 m_fragmentBufferSize = 0;
223 void ReferenceQuadRenderer::render (const tcu::PixelBufferAccess& colorBuffer,
224 const tcu::PixelBufferAccess& depthBuffer,
225 const tcu::PixelBufferAccess& stencilBuffer,
226 const IntegerQuad& quad,
227 const rr::FragmentOperationState& state)
229 bool flipX = quad.posA.x() > quad.posB.x();
230 bool flipY = quad.posA.y() > quad.posB.y();
231 rr::FaceType faceType = flipX == flipY ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
232 int xFirst = flipX ? quad.posB.x() : quad.posA.x();
233 int xLast = flipX ? quad.posA.x() : quad.posB.x();
234 int yFirst = flipY ? quad.posB.y() : quad.posA.y();
235 int yLast = flipY ? quad.posA.y() : quad.posB.y();
236 float width = (float)(xLast - xFirst + 1);
237 float height = (float)(yLast - yFirst + 1);
239 for (int y = yFirst; y <= yLast; y++)
241 // Interpolation factor for y.
242 float yRatio = (0.5f + (float)(y - yFirst)) / height;
244 yRatio = 1.0f - yRatio;
246 for (int x = xFirst; x <= xLast; x++)
248 // Interpolation factor for x.
249 float xRatio = (0.5f + (float)(x - xFirst)) / width;
251 xRatio = 1.0f - xRatio;
253 tcu::Vec4 color = triQuadInterpolate(quad.color, xRatio, yRatio);
254 tcu::Vec4 color1 = triQuadInterpolate(quad.color1, xRatio, yRatio);
255 float depth = triQuadInterpolate(quad.depth, xRatio, yRatio);
257 // Interpolated color and depth.
259 DE_STATIC_ASSERT(MAX_FRAGMENT_BUFFER_SIZE == DE_LENGTH_OF_ARRAY(m_fragmentBuffer));
261 if (m_fragmentBufferSize >= MAX_FRAGMENT_BUFFER_SIZE)
262 flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
263 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
264 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
266 m_fragmentDepths[m_fragmentBufferSize] = depth;
267 m_fragmentBuffer[m_fragmentBufferSize] = rr::Fragment(tcu::IVec2(x, y), rr::GenericVec4(color), rr::GenericVec4(color1), 1u /* coverage mask */, &m_fragmentDepths[m_fragmentBufferSize]);
268 m_fragmentBufferSize++;
272 flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
273 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
274 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
277 tcu::PixelBufferAccess getMultisampleAccess(const tcu::PixelBufferAccess& original)
279 return tcu::PixelBufferAccess(original.getFormat(),
282 original.getHeight(),
283 original.getFormat().getPixelSize(),
284 original.getRowPitch(),
285 original.getDataPtr());
288 tcu::ConstPixelBufferAccess getMultisampleAccess(const tcu::ConstPixelBufferAccess& original)
290 return tcu::ConstPixelBufferAccess(original.getFormat(),
293 original.getHeight(),
294 original.getFormat().getPixelSize(),
295 original.getRowPitch(),
296 original.getDataPtr());