blob: 8cd9cd3df2bd8fbba9758c16eb2044e1a260b88d [file] [log] [blame]
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "test_utils/ANGLETest.h"
using namespace angle;
namespace
{
class ViewportTest : public ANGLETest
{
protected:
ViewportTest()
{
setWindowWidth(512);
setWindowHeight(512);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
mProgram = 0;
}
void runNonScissoredTest()
{
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
runTest();
}
void runScissoredTest()
{
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
glScissor(0, getWindowHeight() / 2, getWindowWidth(), getWindowHeight() / 2);
runTest();
}
void runTest()
{
// Firstly ensure that no errors have been hit.
EXPECT_GL_NO_ERROR();
GLint viewportSize[4];
glGetIntegerv(GL_VIEWPORT, viewportSize);
// Clear to green. Might be a scissored clear, if scissorSize != window size
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a red quad centered in the middle of the viewport, with dimensions 25% of the size of the viewport.
drawQuad(mProgram, "position", 0.5f, 0.25f);
GLint centerViewportX = viewportSize[0] + (viewportSize[2] / 2);
GLint centerViewportY = viewportSize[1] + (viewportSize[3] / 2);
GLint redQuadLeftSideX = viewportSize[0] + viewportSize[2] * 3 / 8;
GLint redQuadRightSideX = viewportSize[0] + viewportSize[2] * 5 / 8;
GLint redQuadTopSideY = viewportSize[1] + viewportSize[3] * 3 / 8;
GLint redQuadBottomSideY = viewportSize[1] + viewportSize[3] * 5 / 8;
// The midpoint of the viewport should be red.
checkPixel(centerViewportX, centerViewportY, true);
// Pixels just inside the red quad should be red.
checkPixel(redQuadLeftSideX, redQuadTopSideY, true);
checkPixel(redQuadLeftSideX, redQuadBottomSideY - 1, true);
checkPixel(redQuadRightSideX - 1, redQuadTopSideY, true);
checkPixel(redQuadRightSideX - 1, redQuadBottomSideY - 1, true);
// Pixels just outside the red quad shouldn't be red.
checkPixel(redQuadLeftSideX - 1, redQuadTopSideY - 1, false);
checkPixel(redQuadLeftSideX - 1, redQuadBottomSideY, false);
checkPixel(redQuadRightSideX, redQuadTopSideY - 1, false);
checkPixel(redQuadRightSideX, redQuadBottomSideY, false);
// Pixels just within the viewport shouldn't be red.
checkPixel(viewportSize[0], viewportSize[1], false);
checkPixel(viewportSize[0], viewportSize[1] + viewportSize[3] - 1, false);
checkPixel(viewportSize[0] + viewportSize[2] - 1, viewportSize[1], false);
checkPixel(viewportSize[0] + viewportSize[2] - 1, viewportSize[1] + viewportSize[3] - 1, false);
}
void checkPixel(GLint x, GLint y, GLboolean renderedRed)
{
// By default, expect the pixel to be black.
GLint expectedRedChannel = 0;
GLint expectedGreenChannel = 0;
GLint scissorSize[4];
glGetIntegerv(GL_SCISSOR_BOX, scissorSize);
EXPECT_GL_NO_ERROR();
if (scissorSize[0] <= x && x < scissorSize[0] + scissorSize[2]
&& scissorSize[1] <= y && y < scissorSize[1] + scissorSize[3])
{
// If the pixel lies within the scissor rect, then it should have been cleared to green.
// If we rendered a red square on top of it, then the pixel should be red (the green channel will have been reset to 0).
expectedRedChannel = renderedRed ? 255 : 0;
expectedGreenChannel = renderedRed ? 0 : 255;
}
// If the pixel is within the bounds of the window, then we check it. Otherwise we skip it.
if (0 <= x && x < getWindowWidth() && 0 <= y && y < getWindowHeight())
{
EXPECT_PIXEL_EQ(x, y, expectedRedChannel, expectedGreenChannel, 0, 255);
}
}
void SetUp() override
{
ANGLETest::SetUp();
const std::string testVertexShaderSource = SHADER_SOURCE
(
attribute highp vec4 position;
void main(void)
{
gl_Position = position;
}
);
const std::string testFragmentShaderSource = SHADER_SOURCE
(
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
if (mProgram == 0)
{
FAIL() << "shader compilation failed.";
}
glUseProgram(mProgram);
glClearColor(0, 0, 0, 1);
glClearDepthf(0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Call glViewport and glScissor with default parameters.
glScissor(0, 0, getWindowWidth(), getWindowHeight());
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glDisable(GL_DEPTH_TEST);
}
void TearDown() override
{
glDeleteProgram(mProgram);
ANGLETest::TearDown();
}
GLuint mProgram;
};
TEST_P(ViewportTest, QuarterWindow)
{
glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, QuarterWindowCentered)
{
glViewport(getWindowWidth() * 3 / 8, getWindowHeight() * 3 / 8, getWindowWidth() / 4, getWindowHeight() / 4);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, FullWindow)
{
glViewport(0, 0, getWindowWidth(), getWindowHeight());
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, FullWindowOffCenter)
{
glViewport(-getWindowWidth() / 2, getWindowHeight() / 2, getWindowWidth(), getWindowHeight());
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, DoubleWindow)
{
glViewport(0, 0, getWindowWidth() * 2, getWindowHeight() * 2);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, DoubleWindowCentered)
{
glViewport(-getWindowWidth() / 2, -getWindowHeight() / 2, getWindowWidth() * 2, getWindowHeight() * 2);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, DoubleWindowOffCenter)
{
glViewport(-getWindowWidth() * 3 / 4, getWindowHeight() * 3 / 4, getWindowWidth(), getWindowHeight());
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, TripleWindow)
{
glViewport(0, 0, getWindowWidth() * 3, getWindowHeight() * 3);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, TripleWindowCentered)
{
glViewport(-getWindowWidth(), -getWindowHeight(), getWindowWidth() * 3, getWindowHeight() * 3);
runNonScissoredTest();
runScissoredTest();
}
TEST_P(ViewportTest, TripleWindowOffCenter)
{
glViewport(-getWindowWidth() * 3 / 2, -getWindowHeight() * 3 / 2, getWindowWidth() * 3, getWindowHeight() * 3);
runNonScissoredTest();
runScissoredTest();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
// D3D11 Feature Level 9 and D3D9 emulate large and negative viewports in the vertex shader. We should test both of these as well as D3D11 Feature Level 10_0+.
ANGLE_INSTANTIATE_TEST(ViewportTest,
ES2_D3D9(),
ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
ES2_D3D11_FL9_3(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace