blob: 1568509f669d1f7cab02a8cea84de274be736894 [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;
class FenceNVTest : public ANGLETest
{
protected:
FenceNVTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
};
class FenceSyncTest : public ANGLETest
{
protected:
FenceSyncTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
};
// FenceNV objects should respond false to glIsFenceNV until they've been set
TEST_P(FenceNVTest, IsFence)
{
if (!extensionEnabled("GL_NV_fence"))
{
std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
return;
}
GLuint fence = 0;
glGenFencesNV(1, &fence);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GL_FALSE, glIsFenceNV(fence));
EXPECT_GL_NO_ERROR();
glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GL_TRUE, glIsFenceNV(fence));
EXPECT_GL_NO_ERROR();
}
// Test error cases for all FenceNV functions
TEST_P(FenceNVTest, Errors)
{
if (!extensionEnabled("GL_NV_fence"))
{
std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
return;
}
// glTestFenceNV should still return TRUE for an invalid fence and generate an INVALID_OPERATION
EXPECT_EQ(GL_TRUE, glTestFenceNV(10));
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
GLuint fence = 20;
// glGenFencesNV should generate INVALID_VALUE for a negative n and not write anything to the fences pointer
glGenFencesNV(-1, &fence);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
EXPECT_EQ(20u, fence);
// Generate a real fence
glGenFencesNV(1, &fence);
EXPECT_GL_NO_ERROR();
// glTestFenceNV should still return TRUE for a fence that is not started and generate an INVALID_OPERATION
EXPECT_EQ(GL_TRUE, glTestFenceNV(fence));
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// glGetFenceivNV should generate an INVALID_OPERATION for an invalid or unstarted fence and not modify the params
GLint result = 30;
glGetFenceivNV(10, GL_FENCE_STATUS_NV, &result);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
EXPECT_EQ(30, result);
glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &result);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
EXPECT_EQ(30, result);
// glSetFenceNV should generate an error for any condition that is not ALL_COMPLETED_NV
glSetFenceNV(fence, 0);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
// glSetFenceNV should generate INVALID_OPERATION for an invalid fence
glSetFenceNV(10, GL_ALL_COMPLETED_NV);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
// Test that basic usage works and doesn't generate errors or crash
TEST_P(FenceNVTest, BasicOperations)
{
if (!extensionEnabled("GL_NV_fence"))
{
std::cout << "Test skipped due to missing GL_NV_fence extension." << std::endl;
return;
}
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
GLuint fences[20] = { 0 };
glGenFencesNV(static_cast<GLsizei>(ArraySize(fences)), fences);
EXPECT_GL_NO_ERROR();
for (GLuint fence : fences)
{
glSetFenceNV(fence, GL_ALL_COMPLETED_NV);
glClear(GL_COLOR_BUFFER_BIT);
}
glFinish();
for (GLuint fence : fences)
{
GLint status = 0;
glGetFenceivNV(fence, GL_FENCE_STATUS_NV, &status);
EXPECT_GL_NO_ERROR();
// Fence should be complete now that Finish has been called
EXPECT_EQ(GL_TRUE, status);
}
EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255);
}
// FenceSync objects should respond true to IsSync after they are created with glFenceSync
TEST_P(FenceSyncTest, IsSync)
{
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GL_TRUE, glIsSync(sync));
EXPECT_EQ(GL_FALSE, glIsSync(reinterpret_cast<GLsync>(40)));
}
// Test error cases for all FenceSync function
TEST_P(FenceSyncTest, Errors)
{
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
// DeleteSync generates INVALID_VALUE when the sync is not valid
glDeleteSync(reinterpret_cast<GLsync>(20));
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glFenceSync generates GL_INVALID_ENUM if the condition is not GL_SYNC_GPU_COMMANDS_COMPLETE
EXPECT_EQ(0, glFenceSync(0, 0));
EXPECT_GL_ERROR(GL_INVALID_ENUM);
// glFenceSync generates GL_INVALID_ENUM if the flags is not 0
EXPECT_EQ(0, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 10));
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if flags contains more than just GL_SYNC_FLUSH_COMMANDS_BIT
EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT | 0x2, 0));
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glClientWaitSync generates GL_INVALID_VALUE and returns GL_WAIT_FAILED if the sync object is not valid
EXPECT_GLENUM_EQ(GL_WAIT_FAILED, glClientWaitSync(reinterpret_cast<GLsync>(30), GL_SYNC_FLUSH_COMMANDS_BIT, 0));
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glWaitSync generates GL_INVALID_VALUE if flags is non-zero
glWaitSync(sync, 1, GL_TIMEOUT_IGNORED);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glWaitSync generates GL_INVALID_VALUE if GLuint64 is not GL_TIMEOUT_IGNORED
glWaitSync(sync, 0, 0);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glWaitSync generates GL_INVALID_VALUE if the sync object is not valid
glWaitSync(reinterpret_cast<GLsync>(30), 0, GL_TIMEOUT_IGNORED);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
// glGetSynciv generates GL_INVALID_VALUE if bufSize is less than zero, results should be untouched
GLsizei length = 20;
GLint value = 30;
glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &value);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
EXPECT_EQ(20, length);
EXPECT_EQ(30, value);
// glGetSynciv generates GL_INVALID_VALUE if the sync object tis not valid, results should be untouched
glGetSynciv(reinterpret_cast<GLsync>(30), GL_OBJECT_TYPE, 1, &length, &value);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
EXPECT_EQ(20, length);
EXPECT_EQ(30, value);
}
// Test usage of glGetSynciv
TEST_P(FenceSyncTest, BasicQueries)
{
GLsizei length = 0;
GLint value = 0;
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glGetSynciv(sync, GL_SYNC_CONDITION, 1, &length, &value);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GL_SYNC_GPU_COMMANDS_COMPLETE, value);
glGetSynciv(sync, GL_OBJECT_TYPE, 1, &length, &value);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(GL_SYNC_FENCE, value);
glGetSynciv(sync, GL_SYNC_FLAGS, 1, &length, &value);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0, value);
}
// Test that basic usage works and doesn't generate errors or crash
TEST_P(FenceSyncTest, BasicOperations)
{
// TODO(geofflang): Figure out why this is broken on Intel OpenGL
if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
{
std::cout << "Test skipped on Intel OpenGL." << std::endl;
return;
}
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glClear(GL_COLOR_BUFFER_BIT);
glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
EXPECT_GL_NO_ERROR();
GLsizei length = 0;
GLint value = 0;
unsigned int loopCount = 0;
glFlush();
// Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
while (value != GL_SIGNALED && loopCount <= 1000000)
{
loopCount++;
glGetSynciv(sync, GL_SYNC_STATUS, 1, &length, &value);
ASSERT_GL_NO_ERROR();
}
ASSERT_GLENUM_EQ(GL_SIGNALED, value);
for (size_t i = 0; i < 20; i++)
{
glClear(GL_COLOR_BUFFER_BIT);
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
EXPECT_GL_NO_ERROR();
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(FenceNVTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(FenceSyncTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());