1/*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Android-specific operations.
22 *//*--------------------------------------------------------------------*/
23
24#include "teglAndroidUtil.hpp"
25
26#include "deStringUtil.hpp"
27#include "tcuTextureUtil.hpp"
28#include "gluTextureUtil.hpp"
29#include "glwEnums.hpp"
30#include "eglwLibrary.hpp"
31#include "eglwEnums.hpp"
32
33#if (DE_OS == DE_OS_ANDROID)
34#	include "tcuAndroidInternals.hpp"
35#endif
36
37namespace deqp
38{
39namespace egl
40{
41namespace Image
42{
43using std::string;
44using de::MovePtr;
45using tcu::PixelBufferAccess;
46using tcu::TextureFormat;
47using tcu::Texture2D;
48using eglu::AttribMap;
49using namespace glw;
50using namespace eglw;
51
52#if (DE_OS != DE_OS_ANDROID)
53
54MovePtr<ImageSource> createAndroidNativeImageSource	(GLenum format)
55{
56	return createUnsupportedImageSource("Not Android platform", format);
57}
58
59#else // DE_OS == DE_OS_ANDROID
60
61using tcu::Android::internal::LibUI;
62using tcu::Android::internal::GraphicBuffer;
63using tcu::Android::internal::PixelFormat;
64using tcu::Android::internal::status_t;
65
66PixelFormat getPixelFormat (GLenum format)
67{
68	switch (format)
69	{
70		case GL_RGB565:		return tcu::Android::internal::PIXEL_FORMAT_RGB_565;
71		case GL_RGB8:		return tcu::Android::internal::PIXEL_FORMAT_RGB_888;
72		case GL_RGBA4:		return tcu::Android::internal::PIXEL_FORMAT_RGBA_4444;
73		case GL_RGB5_A1:	return tcu::Android::internal::PIXEL_FORMAT_RGBA_5551;
74		case GL_RGBA8:		return tcu::Android::internal::PIXEL_FORMAT_RGBA_8888;
75		default:			TCU_THROW(NotSupportedError, "Texture format unsupported by Android");
76	}
77}
78
79class AndroidNativeClientBuffer : public ClientBuffer
80{
81public:
82							AndroidNativeClientBuffer	(const LibUI& lib, GLenum format);
83	EGLClientBuffer			get							(void) const { return reinterpret_cast<EGLClientBuffer>(m_windowBuffer); }
84	GraphicBuffer&			getGraphicBuffer			(void) { return m_graphicBuffer; }
85
86private:
87	GraphicBuffer			m_graphicBuffer;
88	ANativeWindowBuffer*	m_windowBuffer;
89};
90
91AndroidNativeClientBuffer::AndroidNativeClientBuffer (const LibUI& lib, GLenum format)
92	: m_graphicBuffer	(lib, 64, 64, getPixelFormat(format),
93						 GraphicBuffer::USAGE_SW_READ_OFTEN		|
94						 GraphicBuffer::USAGE_SW_WRITE_RARELY	|
95						 GraphicBuffer::USAGE_HW_TEXTURE		|
96						 GraphicBuffer::USAGE_HW_RENDER)
97	, m_windowBuffer	(m_graphicBuffer.getNativeBuffer())
98{
99}
100
101class AndroidNativeImageSource : public ImageSource
102{
103public:
104							AndroidNativeImageSource	(GLenum format) : m_format(format) {}
105	MovePtr<ClientBuffer>	createBuffer 				(const glw::Functions&, Texture2D*) const;
106	string					getRequiredExtension		(void) const { return "EGL_ANDROID_image_native_buffer"; }
107	EGLImageKHR				createImage					(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
108	GLenum					getFormat					(void) const { return m_format; }
109
110protected:
111	GLenum					m_format;
112	LibUI					m_libui;
113};
114
115void checkStatus (status_t status)
116{
117	if (status != tcu::Android::internal::OK)
118		TCU_FAIL(("Android error: status code " + de::toString(status)).c_str());
119}
120
121MovePtr<ClientBuffer> AndroidNativeImageSource::createBuffer (const glw::Functions&, Texture2D* ref) const
122{
123	MovePtr<AndroidNativeClientBuffer>	buffer			(new AndroidNativeClientBuffer(m_libui, m_format));
124	GraphicBuffer&						graphicBuffer	= buffer->getGraphicBuffer();
125	if (ref != DE_NULL)
126	{
127		const TextureFormat	texFormat	= glu::mapGLInternalFormat(m_format);
128		void*				bufferData	= DE_NULL;
129
130		*ref = Texture2D(texFormat, 64, 64);
131		ref->allocLevel(0);
132		tcu::fillWithComponentGradients(ref->getLevel(0),
133										tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
134										tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
135		checkStatus(graphicBuffer.lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, &bufferData));
136		{
137			PixelBufferAccess nativeBuffer(texFormat, 64, 64, 1, bufferData);
138			tcu::copy(nativeBuffer, ref->getLevel(0));
139		}
140		checkStatus(graphicBuffer.unlock());
141	}
142	return MovePtr<ClientBuffer>(buffer);
143}
144
145EGLImageKHR AndroidNativeImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext, EGLClientBuffer clientBuffer) const
146{
147	static const EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
148	const EGLImageKHR	image 		= egl.createImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);
149
150	EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
151	return image;
152}
153
154MovePtr<ImageSource> createAndroidNativeImageSource	(GLenum format)
155{
156	try
157	{
158		return MovePtr<ImageSource>(new AndroidNativeImageSource(format));
159	}
160	catch (std::runtime_error& exc)
161	{
162		return createUnsupportedImageSource(string("Android native buffers unsupported: ") + exc.what(), format);
163	}
164}
165
166#endif // DE_OS == DE_OS_ANDROID
167
168} // Image
169} // egl
170} // deqp
171