blob: be6e3572cf1f090014bd22170a0de3a06da97d96 [file] [log] [blame] [edit]
/*-------------------------------------------------------------------------
* drawElements Quality Program EGL Module
* ---------------------------------------
*
* Copyright 2016 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 EGL thread clean up tests
*//*--------------------------------------------------------------------*/
#include "teglThreadCleanUpTests.hpp"
#include "egluUtil.hpp"
#include "egluUnique.hpp"
#include "egluConfigFilter.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "tcuMaybe.hpp"
#include "tcuTestLog.hpp"
#include "deThread.hpp"
namespace deqp
{
namespace egl
{
namespace
{
using namespace eglw;
using tcu::TestLog;
bool isES2Renderable(const eglu::CandidateConfig &c)
{
return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
}
bool isPBuffer(const eglu::CandidateConfig &c)
{
return (c.surfaceType() & EGL_PBUFFER_BIT) == EGL_PBUFFER_BIT;
}
class Thread : public de::Thread
{
public:
Thread(const Library &egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLConfig config,
tcu::Maybe<eglu::Error> &error)
: m_egl(egl)
, m_display(display)
, m_surface(surface)
, m_context(context)
, m_config(config)
, m_error(error)
{
}
void testContext(EGLContext context)
{
if (m_surface != EGL_NO_SURFACE)
{
EGLU_CHECK_MSG(m_egl, "eglCreateContext");
m_egl.makeCurrent(m_display, m_surface, m_surface, context);
EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
}
else
{
const EGLint attribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
const eglu::UniqueSurface surface(m_egl, m_display,
m_egl.createPbufferSurface(m_display, m_config, attribs));
EGLU_CHECK_MSG(m_egl, "eglCreateContext");
m_egl.makeCurrent(m_display, *surface, *surface, context);
EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
}
}
void run(void)
{
try
{
const EGLint attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
m_egl.bindAPI(EGL_OPENGL_ES_API);
if (m_context == EGL_NO_CONTEXT)
{
const eglu::UniqueContext context(m_egl, m_display,
m_egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList));
testContext(*context);
}
else
{
testContext(m_context);
}
}
catch (const eglu::Error &error)
{
m_error = error;
}
m_egl.releaseThread();
}
private:
const Library &m_egl;
const EGLDisplay m_display;
const EGLSurface m_surface;
const EGLContext m_context;
const EGLConfig m_config;
tcu::Maybe<eglu::Error> &m_error;
};
class ThreadCleanUpTest : public TestCase
{
public:
enum ContextType
{
CONTEXTTYPE_SINGLE = 0,
CONTEXTTYPE_MULTI
};
enum SurfaceType
{
SURFACETYPE_SINGLE = 0,
SURFACETYPE_MULTI
};
static std::string testCaseName(ContextType contextType, SurfaceType surfaceType)
{
std::string name;
if (contextType == CONTEXTTYPE_SINGLE)
name += "single_context_";
else
name += "multi_context_";
if (surfaceType == SURFACETYPE_SINGLE)
name += "single_surface";
else
name += "multi_surface";
return name;
}
ThreadCleanUpTest(EglTestContext &eglTestCtx, ContextType contextType, SurfaceType surfaceType)
: TestCase(eglTestCtx, testCaseName(contextType, surfaceType).c_str(), "Simple thread context clean up test")
, m_contextType(contextType)
, m_surfaceType(surfaceType)
, m_iterCount(250)
, m_iterNdx(0)
, m_display(EGL_NO_DISPLAY)
, m_config(0)
, m_surface(EGL_NO_SURFACE)
, m_context(EGL_NO_CONTEXT)
{
}
~ThreadCleanUpTest(void)
{
deinit();
}
void init(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
{
eglu::FilterList filters;
filters << isES2Renderable << isPBuffer;
m_config = eglu::chooseSingleConfig(egl, m_display, filters);
}
if (m_contextType == CONTEXTTYPE_SINGLE)
{
const EGLint attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
egl.bindAPI(EGL_OPENGL_ES_API);
m_context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
EGLU_CHECK_MSG(egl, "Failed to create context");
}
if (m_surfaceType == SURFACETYPE_SINGLE)
{
const EGLint attribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE};
m_surface = egl.createPbufferSurface(m_display, m_config, attribs);
EGLU_CHECK_MSG(egl, "Failed to create surface");
}
}
void deinit(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
if (m_surface != EGL_NO_SURFACE)
{
egl.destroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE;
}
if (m_context != EGL_NO_CONTEXT)
{
egl.destroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT;
}
if (m_display != EGL_NO_DISPLAY)
{
egl.terminate(m_display);
m_display = EGL_NO_DISPLAY;
}
}
IterateResult iterate(void)
{
if (m_iterNdx < m_iterCount)
{
tcu::Maybe<eglu::Error> error;
Thread thread(m_eglTestCtx.getLibrary(), m_display, m_surface, m_context, m_config, error);
thread.start();
thread.join();
if (error)
{
m_testCtx.getLog() << TestLog::Message << "Failed. Got error: " << error->getMessage()
<< TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error->getMessage());
return STOP;
}
m_iterNdx++;
return CONTINUE;
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
}
private:
const ContextType m_contextType;
const SurfaceType m_surfaceType;
const size_t m_iterCount;
size_t m_iterNdx;
EGLDisplay m_display;
EGLConfig m_config;
EGLSurface m_surface;
EGLContext m_context;
};
} // namespace
TestCaseGroup *createThreadCleanUpTest(EglTestContext &eglTestCtx)
{
de::MovePtr<TestCaseGroup> group(new TestCaseGroup(eglTestCtx, "thread_cleanup", "Thread cleanup tests"));
group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE,
ThreadCleanUpTest::SURFACETYPE_SINGLE));
group->addChild(
new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI, ThreadCleanUpTest::SURFACETYPE_SINGLE));
group->addChild(
new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE, ThreadCleanUpTest::SURFACETYPE_MULTI));
group->addChild(
new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI, ThreadCleanUpTest::SURFACETYPE_MULTI));
return group.release();
}
} // namespace egl
} // namespace deqp