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 302