641 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			641 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
/*-------------------------------------------------------------------------
 | 
						|
 * drawElements Quality Program EGL Module
 | 
						|
 * ---------------------------------------
 | 
						|
 *
 | 
						|
 * 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 EGL image tests.
 | 
						|
 *//*--------------------------------------------------------------------*/
 | 
						|
 | 
						|
#include "teglImageTests.hpp"
 | 
						|
 | 
						|
#include "teglImageUtil.hpp"
 | 
						|
#include "teglAndroidUtil.hpp"
 | 
						|
#include "teglImageFormatTests.hpp"
 | 
						|
 | 
						|
#include "egluNativeDisplay.hpp"
 | 
						|
#include "egluNativeWindow.hpp"
 | 
						|
#include "egluNativePixmap.hpp"
 | 
						|
#include "egluStrUtil.hpp"
 | 
						|
#include "egluUnique.hpp"
 | 
						|
#include "egluUtil.hpp"
 | 
						|
#include "egluGLUtil.hpp"
 | 
						|
 | 
						|
#include "eglwLibrary.hpp"
 | 
						|
#include "eglwEnums.hpp"
 | 
						|
 | 
						|
#include "gluDefs.hpp"
 | 
						|
#include "gluCallLogWrapper.hpp"
 | 
						|
#include "gluObjectWrapper.hpp"
 | 
						|
#include "gluStrUtil.hpp"
 | 
						|
 | 
						|
#include "glwDefs.hpp"
 | 
						|
#include "glwEnums.hpp"
 | 
						|
 | 
						|
#include "tcuTestLog.hpp"
 | 
						|
#include "tcuCommandLine.hpp"
 | 
						|
 | 
						|
#include "deUniquePtr.hpp"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <sstream>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
#include <set>
 | 
						|
 | 
						|
using tcu::TestLog;
 | 
						|
 | 
						|
using std::string;
 | 
						|
using std::vector;
 | 
						|
using std::set;
 | 
						|
using std::ostringstream;
 | 
						|
 | 
						|
using de::MovePtr;
 | 
						|
using de::UniquePtr;
 | 
						|
using glu::ApiType;
 | 
						|
using glu::ContextType;
 | 
						|
using glu::Texture;
 | 
						|
using eglu::AttribMap;
 | 
						|
using eglu::NativeWindow;
 | 
						|
using eglu::NativePixmap;
 | 
						|
using eglu::UniqueImage;
 | 
						|
using eglu::UniqueSurface;
 | 
						|
using eglu::ScopedCurrentContext;
 | 
						|
 | 
						|
using namespace glw;
 | 
						|
using namespace eglw;
 | 
						|
 | 
						|
namespace deqp
 | 
						|
{
 | 
						|
namespace egl
 | 
						|
{
 | 
						|
 | 
						|
namespace Image
 | 
						|
{
 | 
						|
 | 
						|
#define CHECK_EXTENSION(DPY, EXTNAME) \
 | 
						|
	TCU_CHECK_AND_THROW(NotSupportedError, eglu::hasExtension(m_eglTestCtx.getLibrary(), DPY, EXTNAME), (string("Unsupported extension: ") + (EXTNAME)).c_str())
 | 
						|
 | 
						|
template <typename RetVal>
 | 
						|
RetVal checkCallError (EglTestContext& eglTestCtx, const char* call, RetVal returnValue, EGLint expectError)
 | 
						|
{
 | 
						|
	tcu::TestContext&	testCtx		= eglTestCtx.getTestContext();
 | 
						|
	TestLog&			log			= testCtx.getLog();
 | 
						|
	EGLint				error;
 | 
						|
 | 
						|
	log << TestLog::Message << call << TestLog::EndMessage;
 | 
						|
 | 
						|
	error = eglTestCtx.getLibrary().getError();
 | 
						|
 | 
						|
	if (error != expectError)
 | 
						|
	{
 | 
						|
		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
 | 
						|
		log << TestLog::Message << "  " << returnValue << " was returned" << TestLog::EndMessage;
 | 
						|
 | 
						|
		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
 | 
						|
			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
 | 
						|
	}
 | 
						|
 | 
						|
	return returnValue;
 | 
						|
}
 | 
						|
 | 
						|
template <typename RetVal>
 | 
						|
void checkCallReturn (EglTestContext& eglTestCtx, const char* call, RetVal returnValue, RetVal expectReturnValue, EGLint expectError)
 | 
						|
{
 | 
						|
	tcu::TestContext&	testCtx		= eglTestCtx.getTestContext();
 | 
						|
	TestLog&			log			= testCtx.getLog();
 | 
						|
	EGLint				error;
 | 
						|
 | 
						|
	log << TestLog::Message << call << TestLog::EndMessage;
 | 
						|
 | 
						|
	error = eglTestCtx.getLibrary().getError();
 | 
						|
 | 
						|
	if (returnValue != expectReturnValue)
 | 
						|
	{
 | 
						|
		log << TestLog::Message << "  Fail: Return value mismatch! Expected " << expectReturnValue << ", got " << returnValue << TestLog::EndMessage;
 | 
						|
 | 
						|
		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
 | 
						|
			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value");
 | 
						|
	}
 | 
						|
 | 
						|
	if (error != expectError)
 | 
						|
	{
 | 
						|
		log << TestLog::Message << "  Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage;
 | 
						|
 | 
						|
		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
 | 
						|
			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// \note These macros expect "EglTestContext m_eglTestCtx" to be defined.
 | 
						|
#define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR)	checkCallReturn(m_eglTestCtx, #CALL, CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR))
 | 
						|
#define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR)						checkCallError(m_eglTestCtx, #CALL, CALL, (EXPECT_ERROR))
 | 
						|
 | 
						|
class ImageTestCase : public TestCase, public glu::CallLogWrapper
 | 
						|
{
 | 
						|
public:
 | 
						|
				ImageTestCase		(EglTestContext& eglTestCtx, ApiType api, const string& name, const string& desc)
 | 
						|
					: TestCase				(eglTestCtx, name.c_str(), desc.c_str())
 | 
						|
					, glu::CallLogWrapper	(m_gl, m_testCtx.getLog())
 | 
						|
					, m_api					(api)
 | 
						|
					, m_display				(EGL_NO_DISPLAY)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	void		init				(void)
 | 
						|
	{
 | 
						|
		DE_ASSERT(m_display == EGL_NO_DISPLAY);
 | 
						|
		m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
 | 
						|
 | 
						|
		const char* extensions[] = { "GL_OES_EGL_image" };
 | 
						|
		m_eglTestCtx.initGLFunctions(&m_gl, m_api, DE_LENGTH_OF_ARRAY(extensions), &extensions[0]);
 | 
						|
	}
 | 
						|
 | 
						|
	void		deinit				(void)
 | 
						|
	{
 | 
						|
		m_eglTestCtx.getLibrary().terminate(m_display);
 | 
						|
		m_display = EGL_NO_DISPLAY;
 | 
						|
	}
 | 
						|
 | 
						|
	bool		isGLRedSupported	(void)
 | 
						|
	{
 | 
						|
		return m_api.getMajorVersion() >= 3 || glu::hasExtension(m_gl, m_api, "GL_EXT_texture_rg");
 | 
						|
	}
 | 
						|
 | 
						|
protected:
 | 
						|
	glw::Functions	m_gl;
 | 
						|
	ApiType			m_api;
 | 
						|
	EGLDisplay		m_display;
 | 
						|
};
 | 
						|
 | 
						|
class InvalidCreateImage : public ImageTestCase
 | 
						|
{
 | 
						|
public:
 | 
						|
	typedef EGLImage    (Library::*createImage)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLAttrib *) const ;
 | 
						|
	typedef EGLImageKHR (Library::*createImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) const ;
 | 
						|
 | 
						|
	InvalidCreateImage (EglTestContext& eglTestCtx)
 | 
						|
		: ImageTestCase(eglTestCtx, ApiType::es(2, 0), "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	template <typename createImageFuncType, typename imageType>
 | 
						|
	void checkCreate	(createImageFuncType createImageFunc,
 | 
						|
						 string createImageName,
 | 
						|
						 const char* msg,
 | 
						|
						 EGLDisplay dpy,
 | 
						|
						 const char* dpyStr,
 | 
						|
						 EGLContext context,
 | 
						|
						 const char* ctxStr,
 | 
						|
						 EGLenum source,
 | 
						|
						 const char* srcStr,
 | 
						|
						 EGLint expectError,
 | 
						|
						 imageType noImageVal);
 | 
						|
 | 
						|
	IterateResult iterate (void)
 | 
						|
	{
 | 
						|
		const Library& egl = m_eglTestCtx.getLibrary();
 | 
						|
 | 
						|
		if (eglu::getVersion(egl, m_display) < eglu::Version(1, 5) &&
 | 
						|
			!eglu::hasExtension(egl, m_display, "EGL_KHR_image") &&
 | 
						|
			!eglu::hasExtension(egl, m_display, "EGL_KHR_image_base"))
 | 
						|
		{
 | 
						|
			TCU_THROW(NotSupportedError, "EGLimages not supported");
 | 
						|
		}
 | 
						|
 | 
						|
		if (eglu::getVersion(egl, m_display) >= eglu::Version(1, 5))
 | 
						|
		{
 | 
						|
#define CHECK_CREATE(MSG, DPY, CONTEXT, SOURCE, ERR) \
 | 
						|
			checkCreate<createImage, EGLImage>(&Library::createImage, "eglCreateImage", MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR, EGL_NO_IMAGE)
 | 
						|
		CHECK_CREATE("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
 | 
						|
		CHECK_CREATE("Testing bad context (-1)...", m_display, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
 | 
						|
		CHECK_CREATE("Testing bad source (-1)...", m_display, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
 | 
						|
#undef CHECK_CREATE
 | 
						|
		}
 | 
						|
 | 
						|
		if (eglu::hasExtension(egl, m_display, "EGL_KHR_image") &&
 | 
						|
			eglu::hasExtension(egl, m_display, "EGL_KHR_image_base"))
 | 
						|
		{
 | 
						|
#define CHECK_CREATE_KHR(MSG, DPY, CONTEXT, SOURCE, ERR) \
 | 
						|
			checkCreate<createImageKHR, EGLImageKHR>(&Library::createImageKHR, "eglCreateImageKHR", MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR, EGL_NO_IMAGE_KHR)
 | 
						|
		CHECK_CREATE_KHR("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
 | 
						|
		CHECK_CREATE_KHR("Testing bad context (-1)...", m_display, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
 | 
						|
		CHECK_CREATE_KHR("Testing bad source (-1)...", m_display, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
 | 
						|
#undef CHECK_CREATE_KHR
 | 
						|
		}
 | 
						|
 | 
						|
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
 | 
						|
		return STOP;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename createImageFuncType, typename imageType>
 | 
						|
void InvalidCreateImage::checkCreate (createImageFuncType createImageFunc,
 | 
						|
									  string createImageName,
 | 
						|
									  const char* msg,
 | 
						|
									  EGLDisplay dpy,
 | 
						|
									  const char* dpyStr,
 | 
						|
									  EGLContext context,
 | 
						|
									  const char* ctxStr,
 | 
						|
									  EGLenum source,
 | 
						|
									  const char* srcStr,
 | 
						|
									  EGLint expectError,
 | 
						|
									  imageType noImageVal)
 | 
						|
{
 | 
						|
	m_testCtx.getLog() << TestLog::Message << msg << TestLog::EndMessage;
 | 
						|
	{
 | 
						|
		const Library&		egl		= m_eglTestCtx.getLibrary();
 | 
						|
		const imageType	    image	= (egl.*createImageFunc)(dpy, context, source, 0, DE_NULL);
 | 
						|
		ostringstream		call;
 | 
						|
 | 
						|
		call << createImageName << "(" << dpyStr << ", " << ctxStr << ", " << srcStr << ", 0, DE_NULL)";
 | 
						|
		checkCallReturn(m_eglTestCtx, call.str().c_str(), image, noImageVal, expectError);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
EGLConfig chooseConfig (const Library& egl, EGLDisplay display, ApiType apiType)
 | 
						|
{
 | 
						|
	AttribMap				attribs;
 | 
						|
	vector<EGLConfig>		configs;
 | 
						|
	// Prefer configs in order: pbuffer, window, pixmap
 | 
						|
	static const EGLenum	s_surfaceTypes[] = { EGL_PBUFFER_BIT, EGL_WINDOW_BIT, EGL_PIXMAP_BIT };
 | 
						|
 | 
						|
	attribs[EGL_RENDERABLE_TYPE] = eglu::apiRenderableType(apiType);
 | 
						|
 | 
						|
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_surfaceTypes); ++ndx)
 | 
						|
	{
 | 
						|
		attribs[EGL_SURFACE_TYPE] = s_surfaceTypes[ndx];
 | 
						|
		configs = eglu::chooseConfigs(egl, display, attribs);
 | 
						|
 | 
						|
		if (!configs.empty())
 | 
						|
			return configs.front();
 | 
						|
	}
 | 
						|
 | 
						|
	TCU_THROW(NotSupportedError, "No compatible EGL configs found");
 | 
						|
	return (EGLConfig)0;
 | 
						|
}
 | 
						|
 | 
						|
class Context
 | 
						|
{
 | 
						|
public:
 | 
						|
								Context			(EglTestContext& eglTestCtx, EGLDisplay display, ContextType ctxType, int width, int height)
 | 
						|
									: m_eglTestCtx	(eglTestCtx)
 | 
						|
									, m_display		(display)
 | 
						|
									, m_config		(chooseConfig(eglTestCtx.getLibrary(), display, ctxType.getAPI()))
 | 
						|
									, m_context		(m_eglTestCtx.getLibrary(), m_display, eglu::createGLContext(eglTestCtx.getLibrary(), m_display, m_config, ctxType))
 | 
						|
									, m_surface		(createSurface(eglTestCtx, m_display, m_config, width, height))
 | 
						|
									, m_current		(eglTestCtx.getLibrary(), m_display, m_surface->get(), m_surface->get(), *m_context)
 | 
						|
	{
 | 
						|
		m_eglTestCtx.initGLFunctions(&m_gl, ctxType.getAPI());
 | 
						|
	}
 | 
						|
 | 
						|
	EGLConfig					getConfig		(void) const { return m_config; }
 | 
						|
	EGLDisplay					getEglDisplay	(void) const { return m_display; }
 | 
						|
	EGLContext					getEglContext	(void) const { return *m_context; }
 | 
						|
	const glw::Functions&		gl				(void) const { return m_gl; }
 | 
						|
 | 
						|
private:
 | 
						|
	EglTestContext&				m_eglTestCtx;
 | 
						|
	EGLDisplay					m_display;
 | 
						|
	EGLConfig					m_config;
 | 
						|
	eglu::UniqueContext			m_context;
 | 
						|
	UniquePtr<ManagedSurface>	m_surface;
 | 
						|
	ScopedCurrentContext		m_current;
 | 
						|
	glw::Functions				m_gl;
 | 
						|
 | 
						|
								Context			(const Context&);
 | 
						|
	Context&					operator=		(const Context&);
 | 
						|
};
 | 
						|
 | 
						|
class CreateImageGLES2 : public ImageTestCase
 | 
						|
{
 | 
						|
public:
 | 
						|
	static const char* getTargetName (EGLint target)
 | 
						|
	{
 | 
						|
		switch (target)
 | 
						|
		{
 | 
						|
			case EGL_GL_TEXTURE_2D_KHR:						return "tex2d";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:	return "cubemap_pos_x";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:	return "cubemap_neg_x";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:	return "cubemap_pos_y";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:	return "cubemap_neg_y";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:	return "cubemap_pos_z";
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:	return "cubemap_neg_z";
 | 
						|
			case EGL_GL_RENDERBUFFER_KHR:					return "renderbuffer";
 | 
						|
			case EGL_NATIVE_BUFFER_ANDROID:					return "android_native";
 | 
						|
			default:		DE_ASSERT(DE_FALSE);			return "";
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	static const char* getStorageName (GLenum storage)
 | 
						|
	{
 | 
						|
		switch (storage)
 | 
						|
		{
 | 
						|
			case GL_RED:				return "red";
 | 
						|
			case GL_RG:					return "rg";
 | 
						|
			case GL_LUMINANCE:			return "luminance";
 | 
						|
			case GL_LUMINANCE_ALPHA:	return "luminance_alpha";
 | 
						|
			case GL_RGB:				return "rgb";
 | 
						|
			case GL_RGBA:				return "rgba";
 | 
						|
			case GL_RGBA16F:			return "rgba16f";
 | 
						|
			case GL_DEPTH_COMPONENT16:	return "depth_component_16";
 | 
						|
			case GL_DEPTH_COMPONENT24:	return "depth_component_24";
 | 
						|
			case GL_DEPTH_COMPONENT32F:	return "depth_component_32f";
 | 
						|
			case GL_DEPTH24_STENCIL8:	return "depth24_stencil8";
 | 
						|
			case GL_DEPTH32F_STENCIL8:	return "depth32f_stencil8";
 | 
						|
			case GL_RGB10_A2:			return "rgb10_a2";
 | 
						|
			case GL_RGBA4:				return "rgba4";
 | 
						|
			case GL_RGB5_A1:			return "rgb5_a1";
 | 
						|
			case GL_RGB565:				return "rgb565";
 | 
						|
			case GL_RGB8:				return "rgb8";
 | 
						|
			case GL_RGBA8:				return "rgba8";
 | 
						|
			case GL_STENCIL_INDEX8:		return "stencil_index8";
 | 
						|
			default:
 | 
						|
				DE_ASSERT(DE_FALSE);
 | 
						|
				return "";
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	MovePtr<ImageSource> getImageSource (EGLint target, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
 | 
						|
	{
 | 
						|
		switch (target)
 | 
						|
		{
 | 
						|
			case EGL_GL_TEXTURE_2D_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
 | 
						|
			case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
 | 
						|
				DE_ASSERT(format != 0u && type != 0u);
 | 
						|
				return createTextureImageSource(target, internalFormat, format, type, useTexLevel0);
 | 
						|
 | 
						|
			case EGL_GL_RENDERBUFFER_KHR:
 | 
						|
				DE_ASSERT(format == 0u && type == 0u);
 | 
						|
				return createRenderbufferImageSource(internalFormat);
 | 
						|
 | 
						|
			case EGL_NATIVE_BUFFER_ANDROID:
 | 
						|
				DE_ASSERT(format == 0u && type == 0u);
 | 
						|
				return createAndroidNativeImageSource(internalFormat, 1u, false);
 | 
						|
 | 
						|
			default:
 | 
						|
				DE_FATAL("Impossible");
 | 
						|
				return MovePtr<ImageSource>();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0 = false)
 | 
						|
		: ImageTestCase		(eglTestCtx, ApiType::es(2, 0), string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(internalFormat) + (useTexLevel0 ? "_level0_only" : ""), "Create EGLImage from GLES2 object")
 | 
						|
		, m_source			(getImageSource(target, internalFormat, format, type, useTexLevel0))
 | 
						|
		, m_internalFormat	(internalFormat)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	IterateResult iterate (void)
 | 
						|
	{
 | 
						|
		const Library&			egl				= m_eglTestCtx.getLibrary();
 | 
						|
		const EGLDisplay		dpy				= m_display;
 | 
						|
 | 
						|
		if (eglu::getVersion(egl, dpy) < eglu::Version(1, 5))
 | 
						|
			CHECK_EXTENSION(dpy, m_source->getRequiredExtension());
 | 
						|
 | 
						|
		// Initialize result.
 | 
						|
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
 | 
						|
 | 
						|
		// Create GLES2 context
 | 
						|
		TestLog&				log				= m_testCtx.getLog();
 | 
						|
		const ContextType		contextType		(ApiType::es(2, 0));
 | 
						|
		Context					context			(m_eglTestCtx, dpy, contextType, 64, 64);
 | 
						|
		const EGLContext		eglContext		= context.getEglContext();
 | 
						|
 | 
						|
		if ((m_internalFormat == GL_RED || m_internalFormat == GL_RG) && !isGLRedSupported())
 | 
						|
			TCU_THROW(NotSupportedError, "Unsupported extension: GL_EXT_texture_rg");
 | 
						|
 | 
						|
		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(egl, dpy, context.getConfig()) << TestLog::EndMessage;
 | 
						|
 | 
						|
		UniquePtr<ClientBuffer>	clientBuffer	(m_source->createBuffer(egl, context.gl()));
 | 
						|
		const EGLImageKHR		image			= m_source->createImage(egl, dpy, eglContext, clientBuffer->get());
 | 
						|
 | 
						|
		if (image == EGL_NO_IMAGE_KHR)
 | 
						|
		{
 | 
						|
			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
 | 
						|
 | 
						|
			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
 | 
						|
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
 | 
						|
		}
 | 
						|
 | 
						|
		// Destroy image
 | 
						|
		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
 | 
						|
 | 
						|
		return STOP;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	const UniquePtr<ImageSource>	m_source;
 | 
						|
	const GLenum					m_internalFormat;
 | 
						|
};
 | 
						|
 | 
						|
class ImageTargetGLES2 : public ImageTestCase
 | 
						|
{
 | 
						|
public:
 | 
						|
	static const char* getTargetName (GLenum target)
 | 
						|
	{
 | 
						|
		switch (target)
 | 
						|
		{
 | 
						|
			case GL_TEXTURE_2D:		return "tex2d";
 | 
						|
			case GL_RENDERBUFFER:	return "renderbuffer";
 | 
						|
			default:
 | 
						|
				DE_ASSERT(DE_FALSE);
 | 
						|
				return "";
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target)
 | 
						|
		: ImageTestCase	(eglTestCtx, ApiType::es(2, 0), string("image_target_gles2_") + getTargetName(target), "Use EGLImage as GLES2 object")
 | 
						|
		, m_target		(target)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	IterateResult iterate (void)
 | 
						|
	{
 | 
						|
		const Library&	egl	= m_eglTestCtx.getLibrary();
 | 
						|
		TestLog&		log	= m_testCtx.getLog();
 | 
						|
 | 
						|
		// \todo [2011-07-21 pyry] Try all possible EGLImage sources
 | 
						|
		CHECK_EXTENSION(m_display, "EGL_KHR_gl_texture_2D_image");
 | 
						|
 | 
						|
		// Initialize result.
 | 
						|
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
 | 
						|
 | 
						|
		// Create GLES2 context
 | 
						|
 | 
						|
		Context context(m_eglTestCtx, m_display, ContextType(ApiType::es(2, 0)), 64, 64);
 | 
						|
		log << TestLog::Message << "Using EGL config " << eglu::getConfigID(m_eglTestCtx.getLibrary(), context.getEglDisplay(), context.getConfig()) << TestLog::EndMessage;
 | 
						|
 | 
						|
		// Check for OES_EGL_image
 | 
						|
		{
 | 
						|
			const char* glExt = (const char*)glGetString(GL_EXTENSIONS);
 | 
						|
 | 
						|
			if (string(glExt).find("GL_OES_EGL_image") == string::npos)
 | 
						|
				throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__);
 | 
						|
 | 
						|
			TCU_CHECK(m_gl.eglImageTargetTexture2DOES);
 | 
						|
			TCU_CHECK(m_gl.eglImageTargetRenderbufferStorageOES);
 | 
						|
		}
 | 
						|
 | 
						|
		// Create GL_TEXTURE_2D and EGLImage from it.
 | 
						|
		log << TestLog::Message << "Creating EGLImage using GL_TEXTURE_2D with GL_RGBA storage" << TestLog::EndMessage;
 | 
						|
 | 
						|
		deUint32 srcTex = 1;
 | 
						|
		GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
 | 
						|
		GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL));
 | 
						|
		GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
 | 
						|
 | 
						|
		// Create EGL image
 | 
						|
		EGLint		attribs[]	= { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
 | 
						|
		EGLImageKHR	image		= CHECK_EXT_CALL_ERR(egl.createImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attribs), EGL_SUCCESS);
 | 
						|
		if (image == EGL_NO_IMAGE_KHR)
 | 
						|
		{
 | 
						|
			log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
 | 
						|
 | 
						|
			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
 | 
						|
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
 | 
						|
		}
 | 
						|
 | 
						|
		// Create texture or renderbuffer
 | 
						|
		if (m_target == GL_TEXTURE_2D)
 | 
						|
		{
 | 
						|
			log << TestLog::Message << "Creating GL_TEXTURE_2D from EGLimage" << TestLog::EndMessage;
 | 
						|
 | 
						|
			deUint32 dstTex = 2;
 | 
						|
			GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex));
 | 
						|
			GLU_CHECK_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image));
 | 
						|
			GLU_CHECK_CALL(glDeleteTextures(1, &dstTex));
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			DE_ASSERT(m_target == GL_RENDERBUFFER);
 | 
						|
 | 
						|
			log << TestLog::Message << "Creating GL_RENDERBUFFER from EGLimage" << TestLog::EndMessage;
 | 
						|
 | 
						|
			deUint32 dstRbo = 2;
 | 
						|
			GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo));
 | 
						|
			GLU_CHECK_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image));
 | 
						|
			GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo));
 | 
						|
		}
 | 
						|
 | 
						|
		// Destroy image
 | 
						|
		CHECK_EXT_CALL_RET(egl.destroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
 | 
						|
 | 
						|
		// Destroy source texture object
 | 
						|
		GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
 | 
						|
 | 
						|
		return STOP;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	GLenum	m_target;
 | 
						|
};
 | 
						|
 | 
						|
class ApiTests : public TestCaseGroup
 | 
						|
{
 | 
						|
public:
 | 
						|
	ApiTests (EglTestContext& eglTestCtx, const string& name, const string& desc) : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
 | 
						|
 | 
						|
	void init (void)
 | 
						|
	{
 | 
						|
		addChild(new Image::InvalidCreateImage(m_eglTestCtx));
 | 
						|
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RED, GL_RED, GL_UNSIGNED_BYTE, false));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RG, GL_RG, GL_UNSIGNED_BYTE, false));
 | 
						|
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE));
 | 
						|
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true));
 | 
						|
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true));
 | 
						|
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
		addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE));
 | 
						|
 | 
						|
		static const GLenum rboStorages[] =
 | 
						|
		{
 | 
						|
			GL_DEPTH_COMPONENT16,
 | 
						|
			GL_RGBA4,
 | 
						|
			GL_RGB5_A1,
 | 
						|
			GL_RGB565,
 | 
						|
			GL_STENCIL_INDEX8
 | 
						|
		};
 | 
						|
		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(rboStorages); storageNdx++)
 | 
						|
			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_RENDERBUFFER_KHR, rboStorages[storageNdx], (GLenum)0, (GLenum)0));
 | 
						|
 | 
						|
		static const GLenum androidFormats[] =
 | 
						|
		{
 | 
						|
			GL_RGB565,
 | 
						|
			GL_RGB8,
 | 
						|
			GL_RGBA8,
 | 
						|
			GL_RGBA4,
 | 
						|
			GL_RGB5_A1,
 | 
						|
			GL_DEPTH_COMPONENT16,
 | 
						|
			GL_DEPTH_COMPONENT24,
 | 
						|
			GL_DEPTH24_STENCIL8,
 | 
						|
			GL_DEPTH_COMPONENT32F,
 | 
						|
			GL_DEPTH32F_STENCIL8,
 | 
						|
			GL_RGB10_A2,
 | 
						|
			GL_RGBA16F,
 | 
						|
			GL_STENCIL_INDEX8
 | 
						|
		};
 | 
						|
 | 
						|
		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(androidFormats); ++formatNdx)
 | 
						|
			addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_NATIVE_BUFFER_ANDROID, androidFormats[formatNdx], (GLenum)0, (GLenum)0));
 | 
						|
 | 
						|
		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_TEXTURE_2D));
 | 
						|
		addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_RENDERBUFFER));
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
} // Image
 | 
						|
 | 
						|
ImageTests::ImageTests (EglTestContext& eglTestCtx)
 | 
						|
	: TestCaseGroup(eglTestCtx, "image", "EGLImage Tests")
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
ImageTests::~ImageTests (void)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void ImageTests::init (void)
 | 
						|
{
 | 
						|
	addChild(new Image::ApiTests(m_eglTestCtx, "api", "EGLImage API tests"));
 | 
						|
	addChild(Image::createSimpleCreationTests(m_eglTestCtx, "create", "EGLImage creation tests"));
 | 
						|
	addChild(Image::createModifyTests(m_eglTestCtx, "modify", "EGLImage modifying tests"));
 | 
						|
	addChild(Image::createMultiContextRenderTests(m_eglTestCtx, "render_multiple_contexts", "EGLImage render tests on multiple contexts"));
 | 
						|
}
 | 
						|
 | 
						|
} // egl
 | 
						|
} // deqp
 |