blob: 78938e7efd96710c895b937d2fe6864b413f0591 [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 <unistd.h> // for close()
#include <va/va_drm.h>
namespace VAAPI {
VAAPIFixture::VAAPIFixture()
: ::testing::Test::Test()
, m_vaDisplay(NULL)
, m_drmHandle(-1)
, drmDevicePaths({ "/dev/dri/renderD128", "/dev/dri/card0" })
, m_maxEntrypoints(0)
, m_maxProfiles(0)
, m_numProfiles(0)
, m_maxConfigAttributes(0)
, m_configID(VA_INVALID_ID)
, m_contextID(VA_INVALID_ID)
, m_bufferID(VA_INVALID_ID)
{
m_profileList.clear();
m_entrypointList.clear();
m_configAttribList.clear();
m_configAttribToCreateConfig.clear();
m_querySurfaceAttribList.clear();
m_surfaceID.clear();
}
VAAPIFixture::~VAAPIFixture()
{
m_vaDisplay = NULL;
if (m_drmHandle >= 0)
close(m_drmHandle);
m_drmHandle = -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 m_vaDisplay;
}
VADisplay VAAPIFixture::doInitialize()
{
VADisplay vaDisplay;
int majorVersion, minorVersion;
vaDisplay = getDisplay();
EXPECT_TRUE(vaDisplay);
if (vaDisplay) {
EXPECT_STATUS(vaInitialize(vaDisplay, &majorVersion, &minorVersion));
}
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::doGetMaxNumConfigAttribs()
{
m_maxConfigAttributes = vaMaxNumConfigAttributes(m_vaDisplay);
EXPECT_EQ(m_maxConfigAttributes, 32);
}
void VAAPIFixture::doGetMaxValues()
{
doGetMaxProfiles();
doGetMaxEntrypoints();
doGetMaxNumConfigAttribs();
}
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);
}
std::vector<VAProfile> VAAPIFixture::getSupportedProfileList()
{
return m_profileList;
}
std::vector<VAEntrypoint> VAAPIFixture::getSupportedEntrypointList()
{
return m_entrypointList;
}
bool VAAPIFixture::doFindProfileInList(VAProfile profile)
{
return std::find(m_profileList.begin(), m_profileList.end(), profile)
!= m_profileList.end();
}
void VAAPIFixture::doQueryConfigEntrypoints(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(VAEntrypoint entrypoint)
{
return std::find(m_entrypointList.begin(), m_entrypointList.end(),
entrypoint)
!= m_entrypointList.end();
}
void VAAPIFixture::doFillConfigAttribList()
{
m_configAttribList.clear();
// fill it with all the VAConfigAttribs known
for (auto& it : m_vaConfigAttribs) {
VAConfigAttrib configAttrib;
configAttrib.type = it;
m_configAttribList.push_back(configAttrib);
}
EXPECT_EQ(m_configAttribList.size(), m_vaConfigAttribs.size());
}
void VAAPIFixture::doGetConfigAttributes(VAProfile profile,
VAEntrypoint entrypoint)
{
int numAttributes = m_configAttribList.size();
ASSERT_STATUS(vaGetConfigAttributes(m_vaDisplay, profile, entrypoint,
&m_configAttribList[0], numAttributes));
}
void VAAPIFixture::doGetConfigAttributes(
VAProfile profile, VAEntrypoint entrypoint,
std::vector<VAConfigAttrib>& configAttrib)
{
int numAttributes = configAttrib.size();
ASSERT_STATUS(vaGetConfigAttributes(m_vaDisplay, profile, entrypoint,
&configAttrib[0], numAttributes));
}
const std::vector<VAConfigAttrib>& VAAPIFixture::getConfigAttribList() const
{
return m_configAttribList;
}
const std::vector<VAConfigAttrib>&
VAAPIFixture::getQueryConfigAttribList() const
{
return m_queryConfigAttribList;
}
void VAAPIFixture::doCheckAttribsMatch(std::vector<VAConfigAttrib> configAttrib)
{
auto itOne = m_queryConfigAttribList.begin();
auto itTwo = configAttrib.begin();
auto diff = 0;
EXPECT_EQ(configAttrib.size(), m_queryConfigAttribList.size());
while (itOne != m_queryConfigAttribList.end()
&& itTwo != configAttrib.end()) {
if (itOne->value != itTwo->value || itOne->type != itTwo->type) {
diff++;
}
itOne++;
itTwo++;
}
EXPECT_TRUE(diff == 0);
}
void VAAPIFixture::doCreateConfigWithAttrib(VAProfile profile,
VAEntrypoint entrypoint)
{
m_configAttribToCreateConfig.clear();
for (auto& it : m_configAttribList) {
if (it.value != VA_ATTRIB_NOT_SUPPORTED)
m_configAttribToCreateConfig.push_back(it);
}
ASSERT_STATUS(vaCreateConfig(
m_vaDisplay, profile, entrypoint, &m_configAttribToCreateConfig[0],
m_configAttribToCreateConfig.size(), &m_configID));
EXPECT_TRUE(m_configID > 0);
doQueryConfigAttributes(profile, entrypoint);
}
void VAAPIFixture::doDestroyConfig()
{
ASSERT_STATUS(vaDestroyConfig(m_vaDisplay, m_configID));
}
void VAAPIFixture::doQuerySurfacesWithConfigAttribs(VAProfile profile,
VAEntrypoint entrypoint)
{
std::vector<VASurfaceAttrib> m_querySurfaceAttribList;
uint32_t queryNumSurfaceAttribs;
doCreateConfigWithAttrib(profile, entrypoint);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
NULL,
&queryNumSurfaceAttribs));
EXPECT_TRUE(queryNumSurfaceAttribs > 0);
m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
&m_querySurfaceAttribList[0],
&queryNumSurfaceAttribs));
EXPECT_TRUE(queryNumSurfaceAttribs > 0);
EXPECT_TRUE(queryNumSurfaceAttribs <= m_querySurfaceAttribList.size());
m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);
for (auto& it : m_querySurfaceAttribList) {
unsigned int flags
= 0 | VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
EXPECT_NE(it.flags & flags,
(unsigned int)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
EXPECT_TRUE((it.value.type >= VAGenericValueTypeInteger)
&& it.value.type <= VAGenericValueTypeFunc);
}
}
inline bool isSurfaceAttribInList(VASurfaceAttrib surfaceAttrib,
VASurfaceAttribType surfaceAttribType)
{
return surfaceAttrib.type == surfaceAttribType;
}
void VAAPIFixture::doGetMaxSurfaceResolution(
VAProfile profile, VAEntrypoint entrypoint,
std::pair<uint32_t, uint32_t>& maxResolution)
{
std::vector<VASurfaceAttrib>::iterator it;
doQuerySurfacesNoConfigAttribs(profile, entrypoint);
it = std::find_if(m_querySurfaceAttribList.begin(),
m_querySurfaceAttribList.end(),
std::bind(isSurfaceAttribInList, std::placeholders::_1,
VASurfaceAttribMaxWidth));
EXPECT_TRUE(it != m_querySurfaceAttribList.end());
EXPECT_EQ(it->value.type, VAGenericValueTypeInteger);
maxResolution.first = it->value.value.i;
it = std::find_if(m_querySurfaceAttribList.begin(),
m_querySurfaceAttribList.end(),
std::bind(isSurfaceAttribInList, std::placeholders::_1,
VASurfaceAttribMaxHeight));
EXPECT_TRUE(it != m_querySurfaceAttribList.end());
EXPECT_EQ(it->value.type, VAGenericValueTypeInteger);
maxResolution.second = it->value.value.i;
}
void VAAPIFixture::doCreateConfigNoAttrib(VAProfile profile,
VAEntrypoint entrypoint)
{
ASSERT_STATUS(
vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0, &m_configID));
EXPECT_TRUE(m_configID > 0);
doQueryConfigAttributes(profile, entrypoint);
}
void VAAPIFixture::doQueryConfigAttributes(VAProfile profile,
VAEntrypoint entrypoint,
VAStatus expectation)
{
VAProfile queryProfile;
VAEntrypoint queryEntrypoint;
int queryNumConfigAttribs;
m_queryConfigAttribList.resize(m_maxConfigAttributes); // va-api requirement
ASSERT_EQ(vaQueryConfigAttributes(
m_vaDisplay, m_configID, &queryProfile, &queryEntrypoint,
&m_queryConfigAttribList[0], &queryNumConfigAttribs),
expectation);
if (expectation == VA_STATUS_SUCCESS) {
m_queryConfigAttribList.resize(queryNumConfigAttribs);
EXPECT_EQ(queryProfile, profile);
EXPECT_EQ(queryEntrypoint, entrypoint);
EXPECT_TRUE(queryNumConfigAttribs > 0);
m_queryConfigAttribList.resize(queryNumConfigAttribs);
// reported Config Attributes should be supported
for (auto& it : m_queryConfigAttribList) {
EXPECT_NE(it.value, VA_ATTRIB_NOT_SUPPORTED);
}
}
}
void VAAPIFixture::doQuerySurfacesNoConfigAttribs(VAProfile profile,
VAEntrypoint entrypoint)
{
uint32_t queryNumSurfaceAttribs;
doCreateConfigNoAttrib(profile, entrypoint);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
NULL,
&queryNumSurfaceAttribs));
EXPECT_TRUE(queryNumSurfaceAttribs > 0);
m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);
ASSERT_STATUS(vaQuerySurfaceAttributes(m_vaDisplay, m_configID,
&m_querySurfaceAttribList[0],
&queryNumSurfaceAttribs));
EXPECT_TRUE(queryNumSurfaceAttribs > 0);
EXPECT_TRUE(queryNumSurfaceAttribs <= m_querySurfaceAttribList.size());
m_querySurfaceAttribList.resize(queryNumSurfaceAttribs);
for (auto& it : m_querySurfaceAttribList) {
unsigned int flags
= 0 | VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
EXPECT_NE(it.flags & flags,
(unsigned int)VA_SURFACE_ATTRIB_NOT_SUPPORTED);
EXPECT_TRUE((it.value.type >= VAGenericValueTypeInteger)
&& it.value.type <= VAGenericValueTypeFunc);
}
}
inline bool isConfigAttribInList(VAConfigAttrib configAttrib,
VAConfigAttribType type)
{
return configAttrib.type == type;
}
void VAAPIFixture::doCreateSurfaces(VAProfile profile, VAEntrypoint entrypoint,
std::pair<uint32_t, uint32_t> resolution)
{
VASurfaceAttrib* attribList = NULL;
uint32_t numAttribs = 0;
// when ConfigAttribs were not queried just do YUV420 as it is considered
// the universal supported format by the driver. RT formats depend on
// profile and entrypoint.
unsigned int formats = VA_RT_FORMAT_YUV420;
m_surfaceID.resize(10);
if (!m_querySurfaceAttribList.empty()) {
numAttribs = m_querySurfaceAttribList.size();
attribList = &m_querySurfaceAttribList[0];
}
if (!m_queryConfigAttribList.empty()) {
std::vector<VAConfigAttrib>::iterator it = std::find_if(
m_queryConfigAttribList.begin(), m_queryConfigAttribList.end(),
std::bind(isConfigAttribInList, std::placeholders::_1,
VAConfigAttribRTFormat));
formats = it->value;
}
for (auto& itFormat : m_vaRTFormats) {
unsigned int currentFormat = formats & itFormat;
if (currentFormat) {
ASSERT_STATUS(vaCreateSurfaces(
m_vaDisplay, currentFormat, resolution.first, resolution.second,
&m_surfaceID[0], 10, attribList, numAttribs));
formats &= ~itFormat;
}
}
}
void VAAPIFixture::doCreateContext(std::pair<uint32_t, uint32_t> resolution,
VAStatus expectation)
{
m_contextID = 0;
ASSERT_EQ(vaCreateContext(m_vaDisplay, m_configID, resolution.first,
resolution.second, VA_PROGRESSIVE,
&m_surfaceID[0], m_surfaceID.size(),
&m_contextID),
expectation);
}
void VAAPIFixture::doDestroyContext(VAStatus expectation)
{
ASSERT_EQ(vaDestroyContext(m_vaDisplay, m_contextID), expectation);
}
void VAAPIFixture::doCreateBuffer(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::doCreateConfig(VAProfile profile, VAEntrypoint entrypoint)
{
m_configID = 0;
ASSERT_STATUS(
vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0, &m_configID));
EXPECT_NE(m_configID, 0u);
}
void VAAPIFixture::doCreateConfigToFail(VAProfile profile,
VAEntrypoint entrypoint, int error)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
m_configID = 0;
vaStatus = vaCreateConfig(m_vaDisplay, profile, entrypoint, NULL, 0,
&m_configID);
ASSERT_EQ(vaStatus, error);
EXPECT_EQ(m_configID, 0u);
m_queryConfigAttribList.resize(m_maxConfigAttributes); // va-api requirement
doQueryConfigAttributes(profile, entrypoint,
VA_STATUS_ERROR_INVALID_CONFIG);
ASSERT_EQ(vaDestroyConfig(m_vaDisplay, m_configID),
VA_STATUS_ERROR_INVALID_CONFIG);
}
void VAAPIFixture::doTerminate() { EXPECT_STATUS(vaTerminate(m_vaDisplay)); }
TEST_F(VAAPIFixture, getDisplay)
{
VADisplay vaDisplay;
vaDisplay = getDisplay();
ASSERT_TRUE(vaDisplay);
}
void VAAPIFixture::doLogSkipTest(VAProfile profile, VAEntrypoint entrypoint)
{
RecordProperty("skipped", true);
std::cout << "[ SKIPPED ]"
<< " " << profile << " / " << entrypoint
<< " not supported on this hardware" << std::endl;
}
} // namespace VAAPI