Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsFragmentOpUtil.cpp
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>
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 =
49         "attribute highp vec4 a_position;\n"
50         "attribute mediump vec4 a_color;\n"
51         "varying mediump vec4 v_color;\n"
52         "void main()\n"
53         "{\n"
54         "       gl_Position = a_position;\n"
55         "       v_color = a_color;\n"
56         "}\n";
57 static const char* s_glsl1FragSrc =
58         "varying mediump vec4 v_color;\n"
59         "void main()\n"
60         "{\n"
61         "       gl_FragColor = v_color;\n"
62         "}\n";
63
64 // GLSL ES 3.0 shaders
65 static const char* s_glsl3VertSrc =
66         "#version 300 es\n"
67         "in highp vec4 a_position;\n"
68         "in mediump vec4 a_color;\n"
69         "out mediump vec4 v_color;\n"
70         "void main()\n"
71         "{\n"
72         "       gl_Position = a_position;\n"
73         "       v_color = a_color;\n"
74         "}\n";
75 static const char* s_glsl3FragSrc =
76         "#version 300 es\n"
77         "in mediump vec4 v_color;\n"
78         "layout(location = 0) out mediump vec4 o_color;\n"
79         "void main()\n"
80         "{\n"
81         "       o_color = v_color;\n"
82         "}\n";
83
84 // GLSL 3.3 shaders
85 static const char* s_glsl33VertSrc =
86         "#version 330 core\n"
87         "in vec4 a_position;\n"
88         "in vec4 a_color;\n"
89         "in vec4 a_color1;\n"
90         "out vec4 v_color;\n"
91         "out vec4 v_color1;\n"
92         "void main()\n"
93         "{\n"
94         "       gl_Position     = a_position;\n"
95         "       v_color         = a_color;\n"
96         "       v_color1        = a_color1;\n"
97         "}\n";
98 static const char* s_glsl33FragSrc =
99         "#version 330 core\n"
100         "in vec4 v_color;\n"
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"
104         "void main()\n"
105         "{\n"
106         "       o_color  = v_color;\n"
107         "       o_color1 = v_color1;\n"
108         "}\n";
109
110 static const char* getVertSrc (glu::GLSLVersion glslVersion)
111 {
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;
118
119         DE_ASSERT(DE_FALSE);
120         return 0;
121 }
122
123 static const char* getFragSrc (glu::GLSLVersion glslVersion)
124 {
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;
131
132         DE_ASSERT(DE_FALSE);
133         return 0;
134 }
135
136 QuadRenderer::QuadRenderer (const glu::RenderContext& context, glu::GLSLVersion glslVersion)
137         : m_context                     (context)
138         , m_program                     (DE_NULL)
139         , m_positionLoc         (0)
140         , m_colorLoc            (-1)
141         , m_color1Loc           (-1)
142         , m_blendFuncExt        (!glu::glslVersionIsES(glslVersion) && (glslVersion >= glu::GLSL_VERSION_330))
143 {
144         DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES ||
145                           glslVersion == glu::GLSL_VERSION_300_ES ||
146                           glslVersion == glu::GLSL_VERSION_330);
147
148         const glw::Functions&   gl              = context.getFunctions();
149         const char*                             vertSrc = getVertSrc(glslVersion);
150         const char*                             fragSrc = getFragSrc(glslVersion);
151
152         m_program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
153         if (!m_program->isOk())
154         {
155                 delete m_program;
156                 throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
157         }
158
159         m_positionLoc   = gl.getAttribLocation(m_program->getProgram(), "a_position");
160         m_colorLoc              = gl.getAttribLocation(m_program->getProgram(), "a_color");
161
162         if (m_blendFuncExt)
163                 m_color1Loc = gl.getAttribLocation(m_program->getProgram(), "a_color1");
164
165         if (m_positionLoc < 0 || m_colorLoc < 0 || (m_blendFuncExt && m_color1Loc < 0))
166         {
167                 delete m_program;
168                 throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
169         }
170 }
171
172 QuadRenderer::~QuadRenderer (void)
173 {
174         delete m_program;
175 }
176
177 void QuadRenderer::render (const Quad& quad) const
178 {
179         const float position[] =
180         {
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
185         };
186         const deUint8 indices[] = { 0, 2, 1, 1, 2, 3 };
187
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);
191
192         std::vector<glu::VertexArrayBinding> vertexArrays;
193
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]));
196
197         if (m_blendFuncExt)
198                 vertexArrays.push_back(glu::va::Float(m_color1Loc,      4, 4, 0, (const float*)&quad.color1[0]));
199
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]));
204 }
205
206 ReferenceQuadRenderer::ReferenceQuadRenderer (void)
207         : m_fragmentBufferSize(0)
208 {
209         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_fragmentDepths); i++)
210                 m_fragmentDepths[i] = 0.0f;
211 }
212
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)
218 {
219         m_fragmentProcessor.render(colorBuffer, depthBuffer, stencilBuffer, &m_fragmentBuffer[0], m_fragmentBufferSize, faceType, state);
220         m_fragmentBufferSize = 0;
221 }
222
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)
228 {
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);
238
239         for (int y = yFirst; y <= yLast; y++)
240         {
241                 // Interpolation factor for y.
242                 float yRatio = (0.5f + (float)(y - yFirst)) / height;
243                 if (flipY)
244                         yRatio = 1.0f - yRatio;
245
246                 for (int x = xFirst; x <= xLast; x++)
247                 {
248                         // Interpolation factor for x.
249                         float xRatio = (0.5f + (float)(x - xFirst)) / width;
250                         if (flipX)
251                                 xRatio = 1.0f - xRatio;
252
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);
256
257                         // Interpolated color and depth.
258
259                         DE_STATIC_ASSERT(MAX_FRAGMENT_BUFFER_SIZE == DE_LENGTH_OF_ARRAY(m_fragmentBuffer));
260
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);
265
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++;
269                 }
270         }
271
272         flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
273                                                 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
274                                                 rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
275 }
276
277 tcu::PixelBufferAccess getMultisampleAccess(const tcu::PixelBufferAccess& original)
278 {
279         return tcu::PixelBufferAccess(original.getFormat(),
280                                                                   1,
281                                                                   original.getWidth(),
282                                                                   original.getHeight(),
283                                                                   original.getFormat().getPixelSize(),
284                                                                   original.getRowPitch(),
285                                                                   original.getDataPtr());
286 }
287
288 tcu::ConstPixelBufferAccess getMultisampleAccess(const tcu::ConstPixelBufferAccess& original)
289 {
290         return tcu::ConstPixelBufferAccess(original.getFormat(),
291                                                                            1,
292                                                                            original.getWidth(),
293                                                                            original.getHeight(),
294                                                                            original.getFormat().getPixelSize(),
295                                                                            original.getRowPitch(),
296                                                                            original.getDataPtr());
297 }
298
299 } // FragmentOpUtil
300 } // gls
301 } // deqp