1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Fragment operation test utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "glsFragmentOpUtil.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "glwFunctions.hpp"
29 #include "glwEnums.hpp"
30
31 namespace deqp
32 {
33 namespace gls
34 {
35 namespace FragmentOpUtil
36 {
37
38 template <typename T>
triQuadInterpolate(const T values[4],float xFactor,float yFactor)39 inline T triQuadInterpolate(const T values[4], float xFactor, float yFactor)
40 {
41 if (xFactor + yFactor < 1.0f)
42 return values[0] + (values[2] - values[0]) * xFactor + (values[1] - values[0]) * yFactor;
43 else
44 return values[3] + (values[1] - values[3]) * (1.0f - xFactor) + (values[2] - values[3]) * (1.0f - yFactor);
45 }
46
47 // GLSL ES 1.0 shaders
48 static const char *s_glsl1VertSrc = "attribute highp vec4 a_position;\n"
49 "attribute mediump vec4 a_color;\n"
50 "varying mediump vec4 v_color;\n"
51 "void main()\n"
52 "{\n"
53 " gl_Position = a_position;\n"
54 " v_color = a_color;\n"
55 "}\n";
56 static const char *s_glsl1FragSrc = "varying mediump vec4 v_color;\n"
57 "void main()\n"
58 "{\n"
59 " gl_FragColor = v_color;\n"
60 "}\n";
61
62 // GLSL ES 3.0 shaders
63 static const char *s_glsl3VertSrc = "#version 300 es\n"
64 "in highp vec4 a_position;\n"
65 "in mediump vec4 a_color;\n"
66 "out mediump vec4 v_color;\n"
67 "void main()\n"
68 "{\n"
69 " gl_Position = a_position;\n"
70 " v_color = a_color;\n"
71 "}\n";
72 static const char *s_glsl3FragSrc = "#version 300 es\n"
73 "in mediump vec4 v_color;\n"
74 "layout(location = 0) out mediump vec4 o_color;\n"
75 "void main()\n"
76 "{\n"
77 " o_color = v_color;\n"
78 "}\n";
79
80 // GLSL 3.3 shaders
81 static const char *s_glsl33VertSrc = "#version 330 core\n"
82 "in vec4 a_position;\n"
83 "in vec4 a_color;\n"
84 "in vec4 a_color1;\n"
85 "out vec4 v_color;\n"
86 "out vec4 v_color1;\n"
87 "void main()\n"
88 "{\n"
89 " gl_Position = a_position;\n"
90 " v_color = a_color;\n"
91 " v_color1 = a_color1;\n"
92 "}\n";
93 static const char *s_glsl33FragSrc = "#version 330 core\n"
94 "in vec4 v_color;\n"
95 "in vec4 v_color1;\n"
96 "layout(location = 0, index = 0) out vec4 o_color;\n"
97 "layout(location = 0, index = 1) out vec4 o_color1;\n"
98 "void main()\n"
99 "{\n"
100 " o_color = v_color;\n"
101 " o_color1 = v_color1;\n"
102 "}\n";
103
getVertSrc(glu::GLSLVersion glslVersion)104 static const char *getVertSrc(glu::GLSLVersion glslVersion)
105 {
106 if (glslVersion == glu::GLSL_VERSION_100_ES)
107 return s_glsl1VertSrc;
108 else if (glslVersion == glu::GLSL_VERSION_300_ES)
109 return s_glsl3VertSrc;
110 else if (glslVersion == glu::GLSL_VERSION_330)
111 return s_glsl33VertSrc;
112
113 DE_ASSERT(false);
114 return 0;
115 }
116
getFragSrc(glu::GLSLVersion glslVersion)117 static const char *getFragSrc(glu::GLSLVersion glslVersion)
118 {
119 if (glslVersion == glu::GLSL_VERSION_100_ES)
120 return s_glsl1FragSrc;
121 else if (glslVersion == glu::GLSL_VERSION_300_ES)
122 return s_glsl3FragSrc;
123 else if (glslVersion == glu::GLSL_VERSION_330)
124 return s_glsl33FragSrc;
125
126 DE_ASSERT(false);
127 return 0;
128 }
129
QuadRenderer(const glu::RenderContext & context,glu::GLSLVersion glslVersion)130 QuadRenderer::QuadRenderer(const glu::RenderContext &context, glu::GLSLVersion glslVersion)
131 : m_context(context)
132 , m_program(DE_NULL)
133 , m_positionLoc(0)
134 , m_colorLoc(-1)
135 , m_color1Loc(-1)
136 , m_blendFuncExt(!glu::glslVersionIsES(glslVersion) && (glslVersion >= glu::GLSL_VERSION_330))
137 {
138 DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES || glslVersion == glu::GLSL_VERSION_300_ES ||
139 glslVersion == glu::GLSL_VERSION_330);
140
141 const glw::Functions &gl = context.getFunctions();
142 const char *vertSrc = getVertSrc(glslVersion);
143 const char *fragSrc = getFragSrc(glslVersion);
144
145 m_program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
146 if (!m_program->isOk())
147 {
148 delete m_program;
149 throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
150 }
151
152 m_positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_position");
153 m_colorLoc = gl.getAttribLocation(m_program->getProgram(), "a_color");
154
155 if (m_blendFuncExt)
156 m_color1Loc = gl.getAttribLocation(m_program->getProgram(), "a_color1");
157
158 if (m_positionLoc < 0 || m_colorLoc < 0 || (m_blendFuncExt && m_color1Loc < 0))
159 {
160 delete m_program;
161 throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
162 }
163 }
164
~QuadRenderer(void)165 QuadRenderer::~QuadRenderer(void)
166 {
167 delete m_program;
168 }
169
render(const Quad & quad) const170 void QuadRenderer::render(const Quad &quad) const
171 {
172 const float position[] = {quad.posA.x(), quad.posA.y(), quad.depth[0], 1.0f, quad.posA.x(), quad.posB.y(),
173 quad.depth[1], 1.0f, quad.posB.x(), quad.posA.y(), quad.depth[2], 1.0f,
174 quad.posB.x(), quad.posB.y(), quad.depth[3], 1.0f};
175 const uint8_t indices[] = {0, 2, 1, 1, 2, 3};
176
177 DE_STATIC_ASSERT(sizeof(tcu::Vec4) == sizeof(float) * 4);
178 DE_STATIC_ASSERT(sizeof(quad.color) == sizeof(float) * 4 * 4);
179 DE_STATIC_ASSERT(sizeof(quad.color1) == sizeof(float) * 4 * 4);
180
181 std::vector<glu::VertexArrayBinding> vertexArrays;
182
183 vertexArrays.push_back(glu::va::Float(m_positionLoc, 4, 4, 0, &position[0]));
184 vertexArrays.push_back(glu::va::Float(m_colorLoc, 4, 4, 0, (const float *)&quad.color[0]));
185
186 if (m_blendFuncExt)
187 vertexArrays.push_back(glu::va::Float(m_color1Loc, 4, 4, 0, (const float *)&quad.color1[0]));
188
189 m_context.getFunctions().useProgram(m_program->getProgram());
190 glu::draw(m_context, m_program->getProgram(), (int)vertexArrays.size(), &vertexArrays[0],
191 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
192 }
193
ReferenceQuadRenderer(void)194 ReferenceQuadRenderer::ReferenceQuadRenderer(void) : m_fragmentBufferSize(0)
195 {
196 for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_fragmentDepths); i++)
197 m_fragmentDepths[i] = 0.0f;
198 }
199
flushFragmentBuffer(const rr::MultisamplePixelBufferAccess & colorBuffer,const rr::MultisamplePixelBufferAccess & depthBuffer,const rr::MultisamplePixelBufferAccess & stencilBuffer,rr::FaceType faceType,const rr::FragmentOperationState & state)200 void ReferenceQuadRenderer::flushFragmentBuffer(const rr::MultisamplePixelBufferAccess &colorBuffer,
201 const rr::MultisamplePixelBufferAccess &depthBuffer,
202 const rr::MultisamplePixelBufferAccess &stencilBuffer,
203 rr::FaceType faceType, const rr::FragmentOperationState &state)
204 {
205 m_fragmentProcessor.render(colorBuffer, depthBuffer, stencilBuffer, &m_fragmentBuffer[0], m_fragmentBufferSize,
206 faceType, state);
207 m_fragmentBufferSize = 0;
208 }
209
render(const tcu::PixelBufferAccess & colorBuffer,const tcu::PixelBufferAccess & depthBuffer,const tcu::PixelBufferAccess & stencilBuffer,const IntegerQuad & quad,const rr::FragmentOperationState & state)210 void ReferenceQuadRenderer::render(const tcu::PixelBufferAccess &colorBuffer, const tcu::PixelBufferAccess &depthBuffer,
211 const tcu::PixelBufferAccess &stencilBuffer, const IntegerQuad &quad,
212 const rr::FragmentOperationState &state)
213 {
214 bool flipX = quad.posA.x() > quad.posB.x();
215 bool flipY = quad.posA.y() > quad.posB.y();
216 rr::FaceType faceType = flipX == flipY ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
217 int xFirst = flipX ? quad.posB.x() : quad.posA.x();
218 int xLast = flipX ? quad.posA.x() : quad.posB.x();
219 int yFirst = flipY ? quad.posB.y() : quad.posA.y();
220 int yLast = flipY ? quad.posA.y() : quad.posB.y();
221 float width = (float)(xLast - xFirst + 1);
222 float height = (float)(yLast - yFirst + 1);
223
224 for (int y = yFirst; y <= yLast; y++)
225 {
226 // Interpolation factor for y.
227 float yRatio = (0.5f + (float)(y - yFirst)) / height;
228 if (flipY)
229 yRatio = 1.0f - yRatio;
230
231 for (int x = xFirst; x <= xLast; x++)
232 {
233 // Interpolation factor for x.
234 float xRatio = (0.5f + (float)(x - xFirst)) / width;
235 if (flipX)
236 xRatio = 1.0f - xRatio;
237
238 tcu::Vec4 color = triQuadInterpolate(quad.color, xRatio, yRatio);
239 tcu::Vec4 color1 = triQuadInterpolate(quad.color1, xRatio, yRatio);
240 float depth = triQuadInterpolate(quad.depth, xRatio, yRatio);
241
242 // Interpolated color and depth.
243
244 DE_STATIC_ASSERT(MAX_FRAGMENT_BUFFER_SIZE == DE_LENGTH_OF_ARRAY(m_fragmentBuffer));
245
246 if (m_fragmentBufferSize >= MAX_FRAGMENT_BUFFER_SIZE)
247 flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
248 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
249 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType,
250 state);
251
252 m_fragmentDepths[m_fragmentBufferSize] = depth;
253 m_fragmentBuffer[m_fragmentBufferSize] =
254 rr::Fragment(tcu::IVec2(x, y), rr::GenericVec4(color), rr::GenericVec4(color1), 1u /* coverage mask */,
255 &m_fragmentDepths[m_fragmentBufferSize]);
256 m_fragmentBufferSize++;
257 }
258 }
259
260 flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
261 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
262 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
263 }
264
getMultisampleAccess(const tcu::PixelBufferAccess & original)265 tcu::PixelBufferAccess getMultisampleAccess(const tcu::PixelBufferAccess &original)
266 {
267 return tcu::PixelBufferAccess(original.getFormat(), 1, original.getWidth(), original.getHeight(),
268 original.getFormat().getPixelSize(), original.getRowPitch(), original.getDataPtr());
269 }
270
getMultisampleAccess(const tcu::ConstPixelBufferAccess & original)271 tcu::ConstPixelBufferAccess getMultisampleAccess(const tcu::ConstPixelBufferAccess &original)
272 {
273 return tcu::ConstPixelBufferAccess(original.getFormat(), 1, original.getWidth(), original.getHeight(),
274 original.getFormat().getPixelSize(), original.getRowPitch(),
275 original.getDataPtr());
276 }
277
278 } // namespace FragmentOpUtil
279 } // namespace gls
280 } // namespace deqp
281