/*-------------------------------------------------------------------------
* drawElements Quality Program Tester Core
* ----------------------------------------
*
* Copyright 2014 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 Legacy EGL utilities
*//*--------------------------------------------------------------------*/
#include "tcuEgl.hpp"
#include "egluStrUtil.hpp"
#include "egluConfigInfo.hpp"
#include "deString.h"
#include <sstream>
using std::vector;
using std::string;
namespace tcu
{
namespace egl
{
Display::Display (EGLDisplay display, EGLint majorVersion, EGLint minorVersion)
: m_display(display)
{
m_version[0] = majorVersion;
m_version[1] = minorVersion;
}
Display::Display (EGLNativeDisplayType nativeDisplay)
: m_display (EGL_NO_DISPLAY)
{
m_display = eglGetDisplay(nativeDisplay);
TCU_CHECK_EGL();
TCU_CHECK(m_display != EGL_NO_DISPLAY);
TCU_CHECK_EGL_CALL(eglInitialize(m_display, &m_version[0], &m_version[1]));
}
Display::~Display ()
{
if (m_display)
eglTerminate(m_display);
}
void Display::getConfigs (std::vector<EGLConfig>& configs) const
{
EGLint numConfigs = 0;
TCU_CHECK_EGL_CALL(eglGetConfigs(m_display, DE_NULL, 0, &numConfigs));
configs.resize(numConfigs);
if (numConfigs > 0)
TCU_CHECK_EGL_CALL(eglGetConfigs(m_display, &configs[0], (EGLint)configs.size(), &numConfigs));
}
void Display::chooseConfig (const EGLint* attribList, std::vector<EGLConfig>& configs) const
{
EGLint numConfigs = 0;
TCU_CHECK_EGL_CALL(eglChooseConfig(m_display, attribList, DE_NULL, 0, &numConfigs));
configs.resize(numConfigs);
if (numConfigs > 0)
TCU_CHECK_EGL_CALL(eglChooseConfig(m_display, attribList, &configs[0], (EGLint)configs.size(), &numConfigs));
}
EGLint Display::getConfigAttrib (EGLConfig config, EGLint attribute) const
{
EGLint value = 0;
TCU_CHECK_EGL_CALL(eglGetConfigAttrib(m_display, config, attribute, &value));
return value;
}
void Display::describeConfig (EGLConfig config, tcu::PixelFormat& pf) const
{
eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &pf.redBits);
eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &pf.greenBits);
eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &pf.blueBits);
eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &pf.alphaBits);
TCU_CHECK_EGL();
}
void Display::describeConfig (EGLConfig config, eglu::ConfigInfo& info) const
{
eglu::queryConfigInfo(m_display, config, &info);
}
static void split (vector<string>& dst, const string& src)
{
size_t start = 0;
size_t end = string::npos;
while ((end = src.find(' ', start)) != string::npos)
{
dst.push_back(src.substr(start, end-start));
start = end+1;
}
if (start < end)
dst.push_back(src.substr(start, end-start));
}
void Display::getExtensions (vector<string>& dst) const
{
const char* extStr = eglQueryString(m_display, EGL_EXTENSIONS);
TCU_CHECK_EGL_MSG("eglQueryString(EGL_EXTENSIONS");
TCU_CHECK(extStr);
split(dst, extStr);
}
void Display::getString (EGLint name, std::string& dst) const
{
const char* retStr = eglQueryString(m_display, name);
TCU_CHECK_EGL_MSG("eglQueryString()");
TCU_CHECK(retStr);
dst = retStr;
}
EGLint Surface::getAttribute (EGLint attribute) const
{
EGLint value;
TCU_CHECK_EGL_CALL(eglQuerySurface(m_display.getEGLDisplay(), m_surface, attribute, &value));
return value;
}
void Surface::setAttribute (EGLint attribute, EGLint value)
{
TCU_CHECK_EGL_CALL(eglSurfaceAttrib(m_display.getEGLDisplay(), m_surface, attribute, value));
}
int Surface::getWidth (void) const
{
return getAttribute(EGL_WIDTH);
}
int Surface::getHeight (void) const
{
return getAttribute(EGL_HEIGHT);
}
void Surface::getSize (int& x, int& y) const
{
x = getWidth();
y = getHeight();
}
WindowSurface::WindowSurface (Display& display, EGLSurface windowSurface)
: Surface (display)
{
m_surface = windowSurface;
}
WindowSurface::WindowSurface (Display& display, EGLConfig config, EGLNativeWindowType nativeWindow, const EGLint* attribList)
: Surface (display)
{
m_surface = eglCreateWindowSurface(display.getEGLDisplay(), config, nativeWindow, attribList);
TCU_CHECK_EGL();
TCU_CHECK(m_surface != EGL_NO_SURFACE);
}
WindowSurface::~WindowSurface (void)
{
eglDestroySurface(m_display.getEGLDisplay(), m_surface);
m_surface = EGL_NO_SURFACE;
}
void WindowSurface::swapBuffers (void)
{
TCU_CHECK_EGL_CALL(eglSwapBuffers(m_display.getEGLDisplay(), m_surface));
}
PixmapSurface::PixmapSurface (Display& display, EGLSurface surface)
: Surface (display)
{
m_surface = surface;
}
PixmapSurface::PixmapSurface (Display& display, EGLConfig config, EGLNativePixmapType nativePixmap, const EGLint* attribList)
: Surface (display)
{
m_surface = eglCreatePixmapSurface(m_display.getEGLDisplay(), config, nativePixmap, attribList);
TCU_CHECK_EGL();
TCU_CHECK(m_surface != EGL_NO_SURFACE);
}
PixmapSurface::~PixmapSurface (void)
{
eglDestroySurface(m_display.getEGLDisplay(), m_surface);
m_surface = EGL_NO_SURFACE;
}
#if 0 // \todo [mika] Fix borken
void PixmapSurface::copyBuffers (void)
{
TCU_CHECK_EGL_CALL(eglCopyBuffers(m_display.getEGLDisplay(), m_surface, m_nativePixmap));
}
#endif
PbufferSurface::PbufferSurface (Display& display, EGLConfig config, const EGLint* attribList)
: Surface(display)
{
m_surface = eglCreatePbufferSurface(m_display.getEGLDisplay(), config, attribList);
TCU_CHECK_EGL();
TCU_CHECK(m_surface != EGL_NO_SURFACE);
}
PbufferSurface::~PbufferSurface (void)
{
eglDestroySurface(m_display.getEGLDisplay(), m_surface);
m_surface = EGL_NO_SURFACE;
}
Context::Context (const Display& display, EGLConfig config, const EGLint* attribList, EGLenum api)
: m_display(display)
, m_config(config)
, m_api(api)
, m_context(EGL_NO_CONTEXT)
{
TCU_CHECK_EGL_CALL(eglBindAPI(m_api));
m_context = eglCreateContext(m_display.getEGLDisplay(), config, EGL_NO_CONTEXT, attribList);
TCU_CHECK_EGL();
TCU_CHECK(m_context);
}
Context::~Context (void)
{
if (m_context)
{
/* If this is current surface, remove binding. */
EGLContext curContext = EGL_NO_CONTEXT;
eglBindAPI(m_api);
curContext = eglGetCurrentContext();
if (curContext == m_context)
eglMakeCurrent(m_display.getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(m_display.getEGLDisplay(), m_context);
}
}
void Context::makeCurrent (const Surface& draw, const Surface& read)
{
TCU_CHECK_EGL_CALL(eglMakeCurrent(m_display.getEGLDisplay(), draw.getEGLSurface(), read.getEGLSurface(), m_context));
}
} // egl
} // tcu