blob: 0ba567ee757902d333e10ed4cb7e6f454ce0a4ff [file] [log] [blame]
/*
* Copyright (C) 2016 Intel Corporation. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "test_va_api_fixture.h"
#include <algorithm>
#include <functional>
#include <fcntl.h> // for O_RDWR
#include <limits>
#include <unistd.h> // for close()
#include <va/va_drm.h>
namespace VAAPI {
VAAPIFixture::VAAPIFixture()
: ::testing::Test::Test()
, m_vaDisplay(NULL)
, m_restoreDriverName(getenv("LIBVA_DRIVER_NAME"))
, m_drmHandle(-1)
, drmDevicePaths({ "/dev/dri/renderD128", "/dev/dri/card0" })
, m_maxEntrypoints(0)
, m_maxProfiles(0)
, m_numProfiles(0)
, m_configID(VA_INVALID_ID)
, m_contextID(VA_INVALID_ID)
, m_bufferID(VA_INVALID_ID)
{
return;
}
VAAPIFixture::~VAAPIFixture()
{
m_vaDisplay = NULL;
if (m_drmHandle >= 0)
close(m_drmHandle);
m_drmHandle = -1;
// Ensure LIBVA_DRIVER_NAME environment is restored to its original
// setting so successive tests use the expected driver.
unsetenv("LIBVA_DRIVER_NAME");
if (m_restoreDriverName)
setenv("LIBVA_DRIVER_NAME", m_restoreDriverName, 1);
}
VADisplay VAAPIFixture::getDisplay()
{
uint32_t i;
for (i = 0; i < sizeof(drmDevicePaths) / sizeof(*drmDevicePaths); i++) {
m_drmHandle = open(drmDevicePaths[i].c_str(), O_RDWR);
if (m_drmHandle < 0)
continue;
m_vaDisplay = vaGetDisplayDRM(m_drmHandle);
if (m_vaDisplay)
return m_vaDisplay;
}
return NULL;
}
VADisplay VAAPIFixture::doInitialize()
{
VADisplay vaDisplay;
VAStatus status;
int majorVersion, minorVersion;
vaDisplay = getDisplay();
EXPECT_TRUE(vaDisplay);
if (!vaDisplay) {
return NULL;
}
status = vaInitialize(vaDisplay, &majorVersion, &minorVersion);
EXPECT_STATUS(status);
if (status != VA_STATUS_SUCCESS) {
return NULL;
}
return vaDisplay;
}
void VAAPIFixture::doGetMaxProfiles()
{
m_maxProfiles = vaMaxNumProfiles(m_vaDisplay);
EXPECT_TRUE(m_maxProfiles > 0) << m_maxProfiles
<< " profiles are reported, check setup";
}
void VAAPIFixture::doGetMaxEntrypoints()
{
m_maxEntrypoints = vaMaxNumEntrypoints(m_vaDisplay);
EXPECT_TRUE(m_maxEntrypoints > 0)
<< m_maxEntrypoints << " entrypoints are reported, check setup";
}
void VAAPIFixture::doGetMaxValues()
{
doGetMaxProfiles();
doGetMaxEntrypoints();
}
void VAAPIFixture::doQueryConfigProfiles()
{
m_profileList.resize(m_maxProfiles);
ASSERT_STATUS(
vaQueryConfigProfiles(m_vaDisplay, &m_profileList[0], &m_numProfiles));
// at least one profile should be supported for tests to be executed
ASSERT_TRUE(m_numProfiles > 0);
m_profileList.resize(m_numProfiles);
}
const Profiles& VAAPIFixture::getSupportedProfileList() const
{
return m_profileList;
}
const Entrypoints& VAAPIFixture::getSupportedEntrypointList() const
{
return m_entrypointList;
}
bool VAAPIFixture::doFindProfileInList(const VAProfile& profile) const
{
return std::find(m_profileList.begin(), m_profileList.end(), profile)
!= m_profileList.end();
}
void VAAPIFixture::doQueryConfigEntrypoints(const VAProfile& profile)
{
int numEntrypoints = 0;
m_entrypointList.resize(m_maxEntrypoints);
ASSERT_STATUS(vaQueryConfigEntrypoints(
m_vaDisplay, profile, &m_entrypointList[0], &numEntrypoints));
EXPECT_TRUE(numEntrypoints > 0);
m_entrypointList.resize(numEntrypoints);
}
bool VAAPIFixture::doFindEntrypointInList(const VAEntrypoint& entrypoint) const
{
return std::find(m_entrypointList.begin(), m_entrypointList.end(),
entrypoint)
!= m_entrypointList.end();
}
void VAAPIFixture::queryConfigProfiles(Profiles& profiles) const
{
const int maxProfiles = vaMaxNumProfiles(m_vaDisplay);
ASSERT_GT(maxProfiles, 0);
profiles.resize(maxProfiles);
int numProfiles(0);
EXPECT_STATUS(
vaQueryConfigProfiles(m_vaDisplay, profiles.data(), &numProfiles));
if (not HasFailure()) {
ASSERT_LE(numProfiles, maxProfiles);
ASSERT_GT(numProfiles, 0);
profiles.resize(numProfiles);
} else {
profiles.clear();
}
}
void VAAPIFixture::queryConfigEntrypoints(const VAProfile& profile,
Entrypoints& entrypoints, const VAStatus& expectation) const
{
const int maxEntrypoints = vaMaxNumEntrypoints(m_vaDisplay);
ASSERT_GT(maxEntrypoints, 0);
entrypoints.resize(maxEntrypoints);
int numEntrypoints(0);
EXPECT_STATUS_EQ(
expectation,
vaQueryConfigEntrypoints(m_vaDisplay, profile, entrypoints.data(),
&numEntrypoints));
if ((VA_STATUS_SUCCESS == expectation) and not HasFailure()) {
ASSERT_LE(numEntrypoints, maxEntrypoints);
ASSERT_GT(numEntrypoints, 0);
entrypoints.resize(numEntrypoints);
} else {
entrypoints.clear();
}
}
VAStatus VAAPIFixture::getSupportStatus(const VAProfile& profile,
const VAEntrypoint& entrypoint) const
{
Profiles profiles;
queryConfigProfiles(profiles);
const auto pBegin(profiles.begin());
const auto pEnd(profiles.end());
if (std::find(pBegin, pEnd, profile) != pEnd) {
Entrypoints entrypoints;
queryConfigEntrypoints(profile, entrypoints);
const auto eBegin(entrypoints.begin());
const auto eEnd(entrypoints.end());
return (std::find(eBegin, eEnd, entrypoint) != eEnd) ?
VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
}
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
bool VAAPIFixture::isSupported(const VAProfile& profile,
const VAEntrypoint& entrypoint) const
{
return VA_STATUS_SUCCESS == getSupportStatus(profile, entrypoint);
}
void VAAPIFixture::getConfigAttributes(const VAProfile& profile,
const VAEntrypoint& entrypoint, ConfigAttributes& attribs,
const VAStatus& expectation) const
{
const bool defaults(attribs.empty());
if (defaults) {
// fill config attributes with default config attributes
const auto op = [](const VAConfigAttribType& t) {
return VAConfigAttrib{type: t, value: VA_ATTRIB_NOT_SUPPORTED};
};
std::transform(g_vaConfigAttribTypes.begin(),
g_vaConfigAttribTypes.end(), std::back_inserter(attribs), op);
}
ASSERT_FALSE(attribs.empty());
EXPECT_STATUS_EQ(
expectation,
vaGetConfigAttributes(
m_vaDisplay, profile, entrypoint, attribs.data(), attribs.size()));
if (defaults) {
// remove unsupported config attributes
const auto begin(attribs.begin());
const auto end(attribs.end());
const auto predicate = [](const VAConfigAttrib& a) {
return a.value == VA_ATTRIB_NOT_SUPPORTED;
};
attribs.erase(std::remove_if(begin, end, predicate), end);
}
}
void VAAPIFixture::createConfig(const VAProfile& profile,
const VAEntrypoint& entrypoint, const ConfigAttributes& attribs,
const VAStatus& expectation)
{
ASSERT_INVALID_ID(m_configID)
<< "test logic error: did you forget to call destroyConfig?";
EXPECT_STATUS_EQ(
expectation,
vaCreateConfig(m_vaDisplay, profile, entrypoint,
(attribs.size() != 0 ?
const_cast<VAConfigAttrib*>(attribs.data()) : NULL),
attribs.size(), &m_configID))
<< "profile = " << profile << std::endl
<< "entrypoint = " << entrypoint << std::endl
<< "numAttribs = " << attribs.size();
if (expectation == VA_STATUS_SUCCESS) {
EXPECT_ID(m_configID);
} else {
EXPECT_INVALID_ID(m_configID);
}
}
void VAAPIFixture::queryConfigAttributes(
const VAProfile& expectedProfile, const VAEntrypoint& expectedEntrypoint,
ConfigAttributes& attributes, const VAStatus& expectedStatus) const
{
VAProfile actualProfile;
VAEntrypoint actualEntrypoint;
int numAttributes(0);
ASSERT_TRUE(attributes.empty())
<< "test logic error: attributes must be empty";
const int maxAttributes = vaMaxNumConfigAttributes(m_vaDisplay);
ASSERT_GT(maxAttributes, 0);
attributes.resize(maxAttributes);
EXPECT_STATUS_EQ(
expectedStatus,
vaQueryConfigAttributes(m_vaDisplay, m_configID, &actualProfile,
&actualEntrypoint, attributes.data(), &numAttributes));
if (expectedStatus == VA_STATUS_SUCCESS) {
EXPECT_EQ(expectedProfile, actualProfile);
EXPECT_EQ(expectedEntrypoint, actualEntrypoint);
ASSERT_LE(numAttributes, maxAttributes);
ASSERT_GT(numAttributes, 0);
attributes.resize(numAttributes);
// reported config attributes should be supported
for (const auto& attribute : attributes) {
EXPECT_NE(VA_ATTRIB_NOT_SUPPORTED, attribute.value);
}
} else {
attributes.clear();
}
}
void VAAPIFixture::destroyConfig(const VAStatus& expectation)
{
EXPECT_STATUS_EQ(expectation, vaDestroyConfig(m_vaDisplay, m_configID));
m_configID = VA_INVALID_ID;
}
void VAAPIFixture::querySurfaceAttributes(SurfaceAttributes& attribs) const
{
ASSERT_TRUE(attribs.empty())
<< "test logic error: surface attributes must be empty";
unsigned numAttribs(0);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID, NULL,
&numAttribs));
ASSERT_GT(numAttribs, 0u);
attribs.resize(numAttribs);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
attribs.data(), &numAttribs));
ASSERT_GT(numAttribs, 0u);
EXPECT_GE(attribs.size(), numAttribs);
attribs.resize(numAttribs);
const uint32_t flags = 0x0 | VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE;
for (const auto& attrib : attribs) {
EXPECT_NE(attrib.flags & flags,
(uint32_t)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
EXPECT_GE(attrib.value.type, VAGenericValueTypeInteger);
EXPECT_LE(attrib.value.type, VAGenericValueTypeFunc);
}
}
void VAAPIFixture::getMinMaxSurfaceResolution(
Resolution& minRes, Resolution& maxRes) const
{
const Resolution::DataType maxVal =
std::numeric_limits<Resolution::DataType>::max();
// set default resolutions
minRes.width = 1;
minRes.height = 1;
maxRes.width = maxVal;
maxRes.height = maxVal;
SurfaceAttributes attribs;
querySurfaceAttributes(attribs);
SurfaceAttributes::const_iterator match;
const SurfaceAttributes::const_iterator begin(attribs.begin());
const SurfaceAttributes::const_iterator end(attribs.end());
// minimum surface width
match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
{return a.type == VASurfaceAttribMinWidth;});
if (match != end) {
EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
ASSERT_GE(match->value.value.i, 1);
ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
minRes.width = match->value.value.i;
}
// minimum surface height
match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
{return a.type == VASurfaceAttribMinHeight;});
if (match != end) {
EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
ASSERT_GE(match->value.value.i, 1);
ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
minRes.height = match->value.value.i;
}
// maximum surface width
match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
{return a.type == VASurfaceAttribMaxWidth;});
if (match != end) {
EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
ASSERT_GE(match->value.value.i, 1);
ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
maxRes.width = match->value.value.i;
}
// maximum surface height
match = std::find_if(begin, end, [](const VASurfaceAttrib& a)
{return a.type == VASurfaceAttribMaxHeight;});
if (match != end) {
EXPECT_EQ(VAGenericValueTypeInteger, match->value.type);
ASSERT_GE(match->value.value.i, 1);
ASSERT_LE((Resolution::DataType)match->value.value.i, maxVal);
maxRes.height = match->value.value.i;
}
EXPECT_LE(minRes, maxRes);
}
void VAAPIFixture::createSurfaces(Surfaces& surfaces, const unsigned format,
const Resolution& resolution, const SurfaceAttributes& attribs,
const VAStatus& expectation) const
{
ASSERT_GT(surfaces.size(), 0u)
<< "test logic error: surfaces must not be emtpy";
for (const auto& surface : surfaces) {
ASSERT_INVALID_ID(surface)
<< "test logic error: surfaces must all be VA_INVALID_SURFACE";
}
ASSERT_STATUS_EQ(
expectation,
vaCreateSurfaces(m_vaDisplay, format, resolution.width,
resolution.height, surfaces.data(), surfaces.size(),
(attribs.size() != 0 ?
const_cast<VASurfaceAttrib*>(attribs.data()) : NULL),
attribs.size()));
if (expectation == VA_STATUS_SUCCESS) {
for (const auto& surface : surfaces) {
ASSERT_ID(surface);
}
}
}
void VAAPIFixture::destroySurfaces(Surfaces& surfaces) const
{
if (surfaces.size() != 0) {
EXPECT_STATUS(vaDestroySurfaces(m_vaDisplay, surfaces.data(),
surfaces.size()));
}
}
void VAAPIFixture::doCreateContext(const Resolution& resolution,
const VAStatus& expectation)
{
m_contextID = 0;
ASSERT_STATUS_EQ(expectation,
vaCreateContext(m_vaDisplay, m_configID, resolution.width,
resolution.height, VA_PROGRESSIVE,
NULL, 0, &m_contextID));
}
void VAAPIFixture::doDestroyContext(const VAStatus& expectation)
{
ASSERT_STATUS_EQ(expectation, vaDestroyContext(m_vaDisplay, m_contextID));
}
void VAAPIFixture::doCreateBuffer(const VABufferType& bufferType)
{
ASSERT_STATUS(vaCreateBuffer(m_vaDisplay, m_contextID, bufferType,
sizeof(bufferType), 1, NULL, &m_bufferID));
}
void VAAPIFixture::doDestroyBuffer()
{
ASSERT_STATUS(vaDestroyBuffer(m_vaDisplay, m_bufferID));
}
void VAAPIFixture::doTerminate()
{
EXPECT_STATUS(vaTerminate(m_vaDisplay));
}
void VAAPIFixture::doLogSkipTest(const VAProfile& profile,
const VAEntrypoint& entrypoint) const
{
RecordProperty("skipped", true);
std::cout << "[ SKIPPED ]"
<< " " << profile << " / " << entrypoint
<< " not supported on this hardware" << std::endl;
}
TEST_F(VAAPIFixture, getDisplay)
{
VADisplay vaDisplay;
vaDisplay = getDisplay();
ASSERT_TRUE(vaDisplay);
EXPECT_STATUS(vaTerminate(vaDisplay));
}
} // namespace VAAPI