302 lines
9.6 KiB
C++
302 lines
9.6 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL (ES) Module
|
|
* -----------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Fragment operation test utilities.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "glsFragmentOpUtil.hpp"
|
|
#include "gluRenderContext.hpp"
|
|
#include "gluShaderProgram.hpp"
|
|
#include "gluDrawUtil.hpp"
|
|
#include "glwFunctions.hpp"
|
|
#include "glwEnums.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gls
|
|
{
|
|
namespace FragmentOpUtil
|
|
{
|
|
|
|
template<typename T>
|
|
inline T triQuadInterpolate (const T values[4], float xFactor, float yFactor)
|
|
{
|
|
if (xFactor + yFactor < 1.0f)
|
|
return values[0] + (values[2]-values[0])*xFactor + (values[1]-values[0])*yFactor;
|
|
else
|
|
return values[3] + (values[1]-values[3])*(1.0f-xFactor) + (values[2]-values[3])*(1.0f-yFactor);
|
|
}
|
|
|
|
// GLSL ES 1.0 shaders
|
|
static const char* s_glsl1VertSrc =
|
|
"attribute highp vec4 a_position;\n"
|
|
"attribute mediump vec4 a_color;\n"
|
|
"varying mediump vec4 v_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_color = a_color;\n"
|
|
"}\n";
|
|
static const char* s_glsl1FragSrc =
|
|
"varying mediump vec4 v_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_FragColor = v_color;\n"
|
|
"}\n";
|
|
|
|
// GLSL ES 3.0 shaders
|
|
static const char* s_glsl3VertSrc =
|
|
"#version 300 es\n"
|
|
"in highp vec4 a_position;\n"
|
|
"in mediump vec4 a_color;\n"
|
|
"out mediump vec4 v_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_color = a_color;\n"
|
|
"}\n";
|
|
static const char* s_glsl3FragSrc =
|
|
"#version 300 es\n"
|
|
"in mediump vec4 v_color;\n"
|
|
"layout(location = 0) out mediump vec4 o_color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" o_color = v_color;\n"
|
|
"}\n";
|
|
|
|
// GLSL 3.3 shaders
|
|
static const char* s_glsl33VertSrc =
|
|
"#version 330 core\n"
|
|
"in vec4 a_position;\n"
|
|
"in vec4 a_color;\n"
|
|
"in vec4 a_color1;\n"
|
|
"out vec4 v_color;\n"
|
|
"out vec4 v_color1;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
" v_color = a_color;\n"
|
|
" v_color1 = a_color1;\n"
|
|
"}\n";
|
|
static const char* s_glsl33FragSrc =
|
|
"#version 330 core\n"
|
|
"in vec4 v_color;\n"
|
|
"in vec4 v_color1;\n"
|
|
"layout(location = 0, index = 0) out vec4 o_color;\n"
|
|
"layout(location = 0, index = 1) out vec4 o_color1;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" o_color = v_color;\n"
|
|
" o_color1 = v_color1;\n"
|
|
"}\n";
|
|
|
|
static const char* getVertSrc (glu::GLSLVersion glslVersion)
|
|
{
|
|
if (glslVersion == glu::GLSL_VERSION_100_ES)
|
|
return s_glsl1VertSrc;
|
|
else if (glslVersion == glu::GLSL_VERSION_300_ES)
|
|
return s_glsl3VertSrc;
|
|
else if (glslVersion == glu::GLSL_VERSION_330)
|
|
return s_glsl33VertSrc;
|
|
|
|
DE_ASSERT(DE_FALSE);
|
|
return 0;
|
|
}
|
|
|
|
static const char* getFragSrc (glu::GLSLVersion glslVersion)
|
|
{
|
|
if (glslVersion == glu::GLSL_VERSION_100_ES)
|
|
return s_glsl1FragSrc;
|
|
else if (glslVersion == glu::GLSL_VERSION_300_ES)
|
|
return s_glsl3FragSrc;
|
|
else if (glslVersion == glu::GLSL_VERSION_330)
|
|
return s_glsl33FragSrc;
|
|
|
|
DE_ASSERT(DE_FALSE);
|
|
return 0;
|
|
}
|
|
|
|
QuadRenderer::QuadRenderer (const glu::RenderContext& context, glu::GLSLVersion glslVersion)
|
|
: m_context (context)
|
|
, m_program (DE_NULL)
|
|
, m_positionLoc (0)
|
|
, m_colorLoc (-1)
|
|
, m_color1Loc (-1)
|
|
, m_blendFuncExt (!glu::glslVersionIsES(glslVersion) && (glslVersion >= glu::GLSL_VERSION_330))
|
|
{
|
|
DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES ||
|
|
glslVersion == glu::GLSL_VERSION_300_ES ||
|
|
glslVersion == glu::GLSL_VERSION_330);
|
|
|
|
const glw::Functions& gl = context.getFunctions();
|
|
const char* vertSrc = getVertSrc(glslVersion);
|
|
const char* fragSrc = getFragSrc(glslVersion);
|
|
|
|
m_program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
|
|
if (!m_program->isOk())
|
|
{
|
|
delete m_program;
|
|
throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
|
|
}
|
|
|
|
m_positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_position");
|
|
m_colorLoc = gl.getAttribLocation(m_program->getProgram(), "a_color");
|
|
|
|
if (m_blendFuncExt)
|
|
m_color1Loc = gl.getAttribLocation(m_program->getProgram(), "a_color1");
|
|
|
|
if (m_positionLoc < 0 || m_colorLoc < 0 || (m_blendFuncExt && m_color1Loc < 0))
|
|
{
|
|
delete m_program;
|
|
throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
QuadRenderer::~QuadRenderer (void)
|
|
{
|
|
delete m_program;
|
|
}
|
|
|
|
void QuadRenderer::render (const Quad& quad) const
|
|
{
|
|
const float position[] =
|
|
{
|
|
quad.posA.x(), quad.posA.y(), quad.depth[0], 1.0f,
|
|
quad.posA.x(), quad.posB.y(), quad.depth[1], 1.0f,
|
|
quad.posB.x(), quad.posA.y(), quad.depth[2], 1.0f,
|
|
quad.posB.x(), quad.posB.y(), quad.depth[3], 1.0f
|
|
};
|
|
const deUint8 indices[] = { 0, 2, 1, 1, 2, 3 };
|
|
|
|
DE_STATIC_ASSERT(sizeof(tcu::Vec4) == sizeof(float)*4);
|
|
DE_STATIC_ASSERT(sizeof(quad.color) == sizeof(float)*4*4);
|
|
DE_STATIC_ASSERT(sizeof(quad.color1) == sizeof(float)*4*4);
|
|
|
|
std::vector<glu::VertexArrayBinding> vertexArrays;
|
|
|
|
vertexArrays.push_back(glu::va::Float(m_positionLoc, 4, 4, 0, &position[0]));
|
|
vertexArrays.push_back(glu::va::Float(m_colorLoc, 4, 4, 0, (const float*)&quad.color[0]));
|
|
|
|
if (m_blendFuncExt)
|
|
vertexArrays.push_back(glu::va::Float(m_color1Loc, 4, 4, 0, (const float*)&quad.color1[0]));
|
|
|
|
m_context.getFunctions().useProgram(m_program->getProgram());
|
|
glu::draw(m_context, m_program->getProgram(),
|
|
(int)vertexArrays.size(), &vertexArrays[0],
|
|
glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
|
|
}
|
|
|
|
ReferenceQuadRenderer::ReferenceQuadRenderer (void)
|
|
: m_fragmentBufferSize(0)
|
|
{
|
|
for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_fragmentDepths); i++)
|
|
m_fragmentDepths[i] = 0.0f;
|
|
}
|
|
|
|
void ReferenceQuadRenderer::flushFragmentBuffer (const rr::MultisamplePixelBufferAccess& colorBuffer,
|
|
const rr::MultisamplePixelBufferAccess& depthBuffer,
|
|
const rr::MultisamplePixelBufferAccess& stencilBuffer,
|
|
rr::FaceType faceType,
|
|
const rr::FragmentOperationState& state)
|
|
{
|
|
m_fragmentProcessor.render(colorBuffer, depthBuffer, stencilBuffer, &m_fragmentBuffer[0], m_fragmentBufferSize, faceType, state);
|
|
m_fragmentBufferSize = 0;
|
|
}
|
|
|
|
void ReferenceQuadRenderer::render (const tcu::PixelBufferAccess& colorBuffer,
|
|
const tcu::PixelBufferAccess& depthBuffer,
|
|
const tcu::PixelBufferAccess& stencilBuffer,
|
|
const IntegerQuad& quad,
|
|
const rr::FragmentOperationState& state)
|
|
{
|
|
bool flipX = quad.posA.x() > quad.posB.x();
|
|
bool flipY = quad.posA.y() > quad.posB.y();
|
|
rr::FaceType faceType = flipX == flipY ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
|
|
int xFirst = flipX ? quad.posB.x() : quad.posA.x();
|
|
int xLast = flipX ? quad.posA.x() : quad.posB.x();
|
|
int yFirst = flipY ? quad.posB.y() : quad.posA.y();
|
|
int yLast = flipY ? quad.posA.y() : quad.posB.y();
|
|
float width = (float)(xLast - xFirst + 1);
|
|
float height = (float)(yLast - yFirst + 1);
|
|
|
|
for (int y = yFirst; y <= yLast; y++)
|
|
{
|
|
// Interpolation factor for y.
|
|
float yRatio = (0.5f + (float)(y - yFirst)) / height;
|
|
if (flipY)
|
|
yRatio = 1.0f - yRatio;
|
|
|
|
for (int x = xFirst; x <= xLast; x++)
|
|
{
|
|
// Interpolation factor for x.
|
|
float xRatio = (0.5f + (float)(x - xFirst)) / width;
|
|
if (flipX)
|
|
xRatio = 1.0f - xRatio;
|
|
|
|
tcu::Vec4 color = triQuadInterpolate(quad.color, xRatio, yRatio);
|
|
tcu::Vec4 color1 = triQuadInterpolate(quad.color1, xRatio, yRatio);
|
|
float depth = triQuadInterpolate(quad.depth, xRatio, yRatio);
|
|
|
|
// Interpolated color and depth.
|
|
|
|
DE_STATIC_ASSERT(MAX_FRAGMENT_BUFFER_SIZE == DE_LENGTH_OF_ARRAY(m_fragmentBuffer));
|
|
|
|
if (m_fragmentBufferSize >= MAX_FRAGMENT_BUFFER_SIZE)
|
|
flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
|
|
rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
|
|
rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
|
|
|
|
m_fragmentDepths[m_fragmentBufferSize] = depth;
|
|
m_fragmentBuffer[m_fragmentBufferSize] = rr::Fragment(tcu::IVec2(x, y), rr::GenericVec4(color), rr::GenericVec4(color1), 1u /* coverage mask */, &m_fragmentDepths[m_fragmentBufferSize]);
|
|
m_fragmentBufferSize++;
|
|
}
|
|
}
|
|
|
|
flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
|
|
rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
|
|
rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
|
|
}
|
|
|
|
tcu::PixelBufferAccess getMultisampleAccess(const tcu::PixelBufferAccess& original)
|
|
{
|
|
return tcu::PixelBufferAccess(original.getFormat(),
|
|
1,
|
|
original.getWidth(),
|
|
original.getHeight(),
|
|
original.getFormat().getPixelSize(),
|
|
original.getRowPitch(),
|
|
original.getDataPtr());
|
|
}
|
|
|
|
tcu::ConstPixelBufferAccess getMultisampleAccess(const tcu::ConstPixelBufferAccess& original)
|
|
{
|
|
return tcu::ConstPixelBufferAccess(original.getFormat(),
|
|
1,
|
|
original.getWidth(),
|
|
original.getHeight(),
|
|
original.getFormat().getPixelSize(),
|
|
original.getRowPitch(),
|
|
original.getDataPtr());
|
|
}
|
|
|
|
} // FragmentOpUtil
|
|
} // gls
|
|
} // deqp
|