Home | History | Annotate | Download | only in egl
      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 Common utilities for EGL images.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 
     25 #include "teglImageUtil.hpp"
     26 
     27 #include "tcuTexture.hpp"
     28 #include "tcuTextureUtil.hpp"
     29 
     30 #include "egluGLUtil.hpp"
     31 #include "egluNativeWindow.hpp"
     32 #include "egluNativePixmap.hpp"
     33 
     34 #include "eglwLibrary.hpp"
     35 #include "eglwEnums.hpp"
     36 
     37 #include "glwEnums.hpp"
     38 
     39 #include "gluObjectWrapper.hpp"
     40 #include "gluTextureUtil.hpp"
     41 
     42 namespace deqp
     43 {
     44 namespace egl
     45 {
     46 namespace Image
     47 {
     48 
     49 using std::string;
     50 using std::vector;
     51 
     52 using de::UniquePtr;
     53 using de::MovePtr;
     54 
     55 using tcu::TextureFormat;
     56 using tcu::Texture2D;
     57 using tcu::Vec4;
     58 
     59 using glu::Framebuffer;
     60 using glu::Texture;
     61 
     62 using eglu::AttribMap;
     63 using eglu::UniqueSurface;
     64 using eglu::NativeDisplay;
     65 using eglu::NativeWindow;
     66 using eglu::NativePixmap;
     67 using eglu::NativeDisplayFactory;
     68 using eglu::NativeWindowFactory;
     69 using eglu::NativePixmapFactory;
     70 using eglu::WindowParams;
     71 
     72 using namespace glw;
     73 using namespace eglw;
     74 
     75 enum {
     76 	IMAGE_WIDTH		= 64,
     77 	IMAGE_HEIGHT	= 64,
     78 };
     79 
     80 
     81 template <typename T>
     82 struct NativeSurface : public ManagedSurface
     83 {
     84 public:
     85 	explicit		NativeSurface	(MovePtr<UniqueSurface>	surface,
     86 									 MovePtr<T>				native)
     87 						: ManagedSurface	(surface)
     88 						, m_native			(native) {}
     89 
     90 private:
     91 	UniquePtr<T>	m_native;
     92 };
     93 
     94 typedef NativeSurface<NativeWindow> NativeWindowSurface;
     95 typedef NativeSurface<NativePixmap> NativePixmapSurface;
     96 
     97 MovePtr<ManagedSurface> createSurface (EglTestContext& eglTestCtx, EGLDisplay dpy, EGLConfig config, int width, int height)
     98 {
     99 	const Library&				egl				= eglTestCtx.getLibrary();
    100 	EGLint						surfaceTypeBits	= eglu::getConfigAttribInt(egl, dpy, config, EGL_SURFACE_TYPE);
    101 	const NativeDisplayFactory&	displayFactory	= eglTestCtx.getNativeDisplayFactory();
    102 	NativeDisplay&				nativeDisplay	= eglTestCtx.getNativeDisplay();
    103 
    104 	if (surfaceTypeBits & EGL_PBUFFER_BIT)
    105 	{
    106 		static const EGLint attribs[]	= { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE };
    107 		const EGLSurface	surface		= egl.createPbufferSurface(dpy, config, attribs);
    108 
    109 		EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
    110 
    111 		return de::newMovePtr<ManagedSurface>(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)));
    112 	}
    113 	else if (surfaceTypeBits & EGL_WINDOW_BIT)
    114 	{
    115 		const NativeWindowFactory&	windowFactory	= selectNativeWindowFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());
    116 
    117 		MovePtr<NativeWindow>		window	(windowFactory.createWindow(&nativeDisplay, dpy, config, DE_NULL, WindowParams(width, height, WindowParams::VISIBILITY_DONT_CARE)));
    118 		const EGLSurface			surface	= eglu::createWindowSurface(nativeDisplay, *window, dpy, config, DE_NULL);
    119 
    120 		return MovePtr<ManagedSurface>(new NativeWindowSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), window));
    121 	}
    122 	else if (surfaceTypeBits & EGL_PIXMAP_BIT)
    123 	{
    124 		const NativePixmapFactory&	pixmapFactory	= selectNativePixmapFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());
    125 
    126 		MovePtr<NativePixmap>	pixmap	(pixmapFactory.createPixmap(&nativeDisplay, dpy, config, DE_NULL, width, height));
    127 		const EGLSurface		surface	= eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *pixmap, dpy, config, DE_NULL);
    128 
    129 		return MovePtr<ManagedSurface>(new NativePixmapSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), pixmap));
    130 	}
    131 	else
    132 		TCU_FAIL("No valid surface types supported in config");
    133 }
    134 
    135 class GLClientBuffer : public ClientBuffer
    136 {
    137 	EGLClientBuffer	get		(void) const { return reinterpret_cast<EGLClientBuffer>(static_cast<deUintptr>(getName())); }
    138 
    139 protected:
    140 	virtual GLuint	getName	(void) const = 0;
    141 };
    142 
    143 class TextureClientBuffer : public GLClientBuffer
    144 {
    145 public:
    146 						TextureClientBuffer	(const glw::Functions& gl) : m_texture (gl) {}
    147 	GLuint				getName				(void) const { return *m_texture; }
    148 
    149 private:
    150 	glu::Texture		m_texture;
    151 };
    152 
    153 class GLImageSource : public ImageSource
    154 {
    155 public:
    156 	EGLImageKHR			createImage			(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
    157 
    158 protected:
    159 	virtual AttribMap	getCreateAttribs	(void) const = 0;
    160 	virtual EGLenum		getSource			(void) const = 0;
    161 };
    162 
    163 EGLImageKHR GLImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const
    164 {
    165 	AttribMap				attribMap	= getCreateAttribs();
    166 
    167 	attribMap[EGL_IMAGE_PRESERVED_KHR] = EGL_TRUE;
    168 
    169 	{
    170 		const vector<EGLint>	attribs	= eglu::attribMapToList(attribMap);
    171 		const EGLImageKHR		image	= egl.createImageKHR(dpy, ctx, getSource(),
    172 															 clientBuffer, &attribs.front());
    173 		EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
    174 		return image;
    175 	}
    176 }
    177 
    178 class TextureImageSource : public GLImageSource
    179 {
    180 public:
    181 							TextureImageSource	(GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0) : m_internalFormat(internalFormat), m_format(format), m_type(type), m_useTexLevel0(useTexLevel0) {}
    182 	MovePtr<ClientBuffer>	createBuffer		(const glw::Functions& gl, Texture2D* reference) const;
    183 	GLenum					getEffectiveFormat	(void) const;
    184 	GLenum					getInternalFormat	(void) const { return m_internalFormat; }
    185 
    186 protected:
    187 	AttribMap				getCreateAttribs	(void) const;
    188 	virtual void			initTexture			(const glw::Functions& gl) const = 0;
    189 	virtual GLenum			getGLTarget			(void) const = 0;
    190 
    191 	const GLenum			m_internalFormat;
    192 	const GLenum			m_format;
    193 	const GLenum			m_type;
    194 	const bool				m_useTexLevel0;
    195 };
    196 
    197 bool isSizedFormat (GLenum format)
    198 {
    199 	try
    200 	{
    201 		glu::mapGLInternalFormat(format);
    202 		return true;
    203 	}
    204 	catch (const tcu::InternalError&)
    205 	{
    206 		return false;
    207 	}
    208 }
    209 
    210 GLenum getEffectiveFormat (GLenum format, GLenum type)
    211 {
    212 	return glu::getInternalFormat(glu::mapGLTransferFormat(format, type));
    213 }
    214 
    215 GLenum TextureImageSource::getEffectiveFormat (void) const
    216 {
    217 	if (isSizedFormat(m_internalFormat))
    218 		return m_internalFormat;
    219 	else
    220 		return deqp::egl::Image::getEffectiveFormat(m_format, m_type);
    221 }
    222 
    223 AttribMap TextureImageSource::getCreateAttribs (void) const
    224 {
    225 	AttribMap ret;
    226 
    227 	ret[EGL_GL_TEXTURE_LEVEL_KHR] = 0;
    228 
    229 	return ret;
    230 }
    231 
    232 MovePtr<ClientBuffer> TextureImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
    233 {
    234 	MovePtr<TextureClientBuffer>	clientBuffer	(new TextureClientBuffer(gl));
    235 	const GLuint					texture			= clientBuffer->getName();
    236 	const GLenum					target			= getGLTarget();
    237 
    238 	GLU_CHECK_GLW_CALL(gl, bindTexture(target, texture));
    239 	initTexture(gl);
    240 
    241 	if (!m_useTexLevel0)
    242 	{
    243 		// Set minification filter to linear. This makes the texture complete.
    244 		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    245 	}
    246 
    247 	if (ref != DE_NULL)
    248 	{
    249 		GLenum		imgTarget	= eglu::getImageGLTarget(getSource());
    250 
    251 		*ref = Texture2D(glu::mapGLTransferFormat(m_format, m_type), IMAGE_WIDTH, IMAGE_HEIGHT);
    252 		ref->allocLevel(0);
    253 		tcu::fillWithComponentGradients(ref->getLevel(0),
    254 										tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
    255 										tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    256 
    257 		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    258 		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    259 		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
    260 		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    261 
    262 		GLU_CHECK_GLW_CALL(gl, texImage2D(imgTarget, 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT,
    263 										  0, m_format, m_type, ref->getLevel(0).getDataPtr()));
    264 	}
    265 	GLU_CHECK_GLW_CALL(gl, bindTexture(target, 0));
    266 	return MovePtr<ClientBuffer>(clientBuffer);
    267 }
    268 
    269 class Texture2DImageSource : public TextureImageSource
    270 {
    271 public:
    272 					Texture2DImageSource	(GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(internalFormat, format, type, useTexLevel0) {}
    273 	EGLenum			getSource				(void) const { return EGL_GL_TEXTURE_2D_KHR; }
    274 	string			getRequiredExtension	(void) const { return "EGL_KHR_gl_texture_2D_image"; }
    275 	GLenum			getGLTarget				(void) const { return GL_TEXTURE_2D; }
    276 
    277 protected:
    278 	void			initTexture				(const glw::Functions& gl) const;
    279 };
    280 
    281 void Texture2DImageSource::initTexture (const glw::Functions& gl) const
    282 {
    283 	// Specify mipmap level 0
    284 	GLU_CHECK_CALL_ERROR(gl.texImage2D(GL_TEXTURE_2D, 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL),
    285 						 gl.getError());
    286 }
    287 
    288 class TextureCubeMapImageSource : public TextureImageSource
    289 {
    290 public:
    291 					TextureCubeMapImageSource	(EGLenum source, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(internalFormat, format, type, useTexLevel0), m_source(source) {}
    292 	EGLenum			getSource					(void) const { return m_source; }
    293 	string			getRequiredExtension		(void) const { return "EGL_KHR_gl_texture_cubemap_image"; }
    294 	GLenum			getGLTarget					(void) const { return GL_TEXTURE_CUBE_MAP; }
    295 
    296 protected:
    297 	void			initTexture					(const glw::Functions& gl) const;
    298 
    299 	EGLenum			m_source;
    300 };
    301 
    302 void TextureCubeMapImageSource::initTexture (const glw::Functions& gl) const
    303 {
    304 	// Specify mipmap level 0 for all faces
    305 	static const GLenum faces[] =
    306 	{
    307 		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    308 		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    309 		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    310 		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    311 		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    312 		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    313 	};
    314 
    315 	for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
    316 		GLU_CHECK_GLW_CALL(gl, texImage2D(faces[faceNdx], 0, m_internalFormat, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL));
    317 }
    318 
    319 class RenderbufferClientBuffer : public GLClientBuffer
    320 {
    321 public:
    322 						RenderbufferClientBuffer	(const glw::Functions& gl) : m_rbo (gl) {}
    323 	GLuint				getName						(void) const { return *m_rbo; }
    324 
    325 private:
    326 	glu::Renderbuffer	m_rbo;
    327 };
    328 
    329 class RenderbufferImageSource : public GLImageSource
    330 {
    331 public:
    332 							RenderbufferImageSource	(GLenum format) : m_format(format) {}
    333 
    334 	string					getRequiredExtension	(void) const	{ return "EGL_KHR_gl_renderbuffer_image"; }
    335 	MovePtr<ClientBuffer>	createBuffer			(const glw::Functions& gl, Texture2D* reference) const;
    336 	GLenum					getEffectiveFormat		(void) const { return m_format; }
    337 
    338 protected:
    339 	EGLenum					getSource				(void) const	{ return EGL_GL_RENDERBUFFER_KHR; }
    340 	AttribMap				getCreateAttribs		(void) const	{ return AttribMap(); }
    341 
    342 	GLenum					m_format;
    343 };
    344 
    345 void initializeStencilRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
    346 {
    347 	static const deUint32 stencilValues[] =
    348 	{
    349 		0xBF688C11u,
    350 		0xB43D2922u,
    351 		0x055D5FFBu,
    352 		0x9300655Eu,
    353 		0x63BE0DF2u,
    354 		0x0345C13Bu,
    355 		0x1C184832u,
    356 		0xD107040Fu,
    357 		0x9B91569Fu,
    358 		0x0F0CFDC7u,
    359 	};
    360 
    361 	const deUint32 numStencilBits	= tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(ref.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
    362 	const deUint32 stencilMask		= deBitMask32(0, numStencilBits);
    363 
    364 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
    365 												   GL_RENDERBUFFER, rbo));
    366 	GLU_CHECK_GLW_CALL(gl, clearStencil(0));
    367 	GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
    368 	tcu::clearStencil(ref.getLevel(0), 0);
    369 
    370 	// create a pattern
    371 	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
    372 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilValues); ++ndx)
    373 	{
    374 		const deUint32		stencil	= stencilValues[ndx] & stencilMask;
    375 		const tcu::IVec2	size	= tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(stencilValues) - ndx) * ((float)ref.getWidth() / float(DE_LENGTH_OF_ARRAY(stencilValues)))),
    376 												 (int)((float)(DE_LENGTH_OF_ARRAY(stencilValues) - ndx) * ((float)ref.getHeight() / float(DE_LENGTH_OF_ARRAY(stencilValues) + 4)))); // not symmetric
    377 
    378 		if (size.x() == 0 || size.y() == 0)
    379 			break;
    380 
    381 		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
    382 		GLU_CHECK_GLW_CALL(gl, clearStencil(stencil));
    383 		GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
    384 
    385 		tcu::clearStencil(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), stencil);
    386 	}
    387 
    388 	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
    389 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
    390 												   GL_RENDERBUFFER, 0));
    391 }
    392 
    393 void initializeDepthRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
    394 {
    395 	const int NUM_STEPS = 13;
    396 
    397 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
    398 												   GL_RENDERBUFFER, rbo));
    399 
    400 	GLU_CHECK_GLW_CALL(gl, clearDepthf(0.0f));
    401 	GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
    402 	tcu::clearDepth(ref.getLevel(0), 0.0f);
    403 
    404 	// create a pattern
    405 	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
    406 	for (int ndx = 0; ndx < NUM_STEPS; ++ndx)
    407 	{
    408 		const float			depth	= (float)ndx / float(NUM_STEPS);
    409 		const tcu::IVec2	size	= tcu::IVec2((int)((float)(NUM_STEPS - ndx) * ((float)ref.getWidth() / float(NUM_STEPS))),
    410 												 (int)((float)(NUM_STEPS - ndx) * ((float)ref.getHeight() / float(NUM_STEPS + 4)))); // not symmetric
    411 
    412 		if (size.x() == 0 || size.y() == 0)
    413 			break;
    414 
    415 		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
    416 		GLU_CHECK_GLW_CALL(gl, clearDepthf(depth));
    417 		GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
    418 
    419 		tcu::clearDepth(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), depth);
    420 	}
    421 
    422 	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
    423 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
    424 												   GL_RENDERBUFFER, 0));
    425 
    426 }
    427 
    428 void initializeColorRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
    429 {
    430 	static const tcu::Vec4 colorValues[] =
    431 	{
    432 		tcu::Vec4(0.9f, 0.5f, 0.65f, 1.0f),
    433 		tcu::Vec4(0.5f, 0.7f, 0.65f, 1.0f),
    434 		tcu::Vec4(0.2f, 0.5f, 0.65f, 1.0f),
    435 		tcu::Vec4(0.3f, 0.1f, 0.5f, 1.0f),
    436 		tcu::Vec4(0.8f, 0.2f, 0.3f, 1.0f),
    437 		tcu::Vec4(0.9f, 0.4f, 0.8f, 1.0f),
    438 	};
    439 
    440 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
    441 												   GL_RENDERBUFFER, rbo));
    442 	GLU_CHECK_GLW_CALL(gl, clearColor(1.0f, 1.0f, 0.0f, 1.0f));
    443 	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
    444 	tcu::clear(ref.getLevel(0), Vec4(1.0f, 1.0f, 0.0f, 1.0f));
    445 
    446 	// create a pattern
    447 	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
    448 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorValues); ++ndx)
    449 	{
    450 		const tcu::IVec2	size	= tcu::IVec2((int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)ref.getWidth() / float(DE_LENGTH_OF_ARRAY(colorValues)))),
    451 												 (int)((float)(DE_LENGTH_OF_ARRAY(colorValues) - ndx) * ((float)ref.getHeight() / float(DE_LENGTH_OF_ARRAY(colorValues) + 4)))); // not symmetric
    452 
    453 		if (size.x() == 0 || size.y() == 0)
    454 			break;
    455 
    456 		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
    457 		GLU_CHECK_GLW_CALL(gl, clearColor(colorValues[ndx].x(), colorValues[ndx].y(), colorValues[ndx].z(), colorValues[ndx].w()));
    458 		GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
    459 
    460 		tcu::clear(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), colorValues[ndx]);
    461 	}
    462 
    463 	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
    464 	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
    465 												   GL_RENDERBUFFER, 0));
    466 }
    467 
    468 MovePtr<ClientBuffer> RenderbufferImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
    469 {
    470 	MovePtr<RenderbufferClientBuffer>	buffer	(new RenderbufferClientBuffer(gl));
    471 	const GLuint						rbo		= buffer->getName();
    472 
    473 	GLU_CHECK_CALL_ERROR(gl.bindRenderbuffer(GL_RENDERBUFFER, rbo), gl.getError());
    474 
    475 	// Specify storage.
    476 	GLU_CHECK_CALL_ERROR(gl.renderbufferStorage(GL_RENDERBUFFER, m_format, 64, 64), gl.getError());
    477 
    478 	if (ref != DE_NULL)
    479 	{
    480 		Framebuffer			fbo			(gl);
    481 		const TextureFormat	texFormat	= glu::mapGLInternalFormat(m_format);
    482 
    483 		*ref = tcu::Texture2D(texFormat, 64, 64);
    484 		ref->allocLevel(0);
    485 
    486 		gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
    487 		switch (m_format)
    488 		{
    489 			case GL_STENCIL_INDEX8:
    490 				initializeStencilRbo(gl, rbo, *ref);
    491 				break;
    492 			case GL_DEPTH_COMPONENT16:
    493 				initializeDepthRbo(gl, rbo, *ref);
    494 				break;
    495 			case GL_RGBA4:
    496 				initializeColorRbo(gl, rbo, *ref);
    497 				break;
    498 			case GL_RGB5_A1:
    499 				initializeColorRbo(gl, rbo, *ref);
    500 				break;
    501 			case GL_RGB565:
    502 				initializeColorRbo(gl, rbo, *ref);
    503 				break;
    504 			default:
    505 				DE_FATAL("Impossible");
    506 		}
    507 
    508 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    509 	}
    510 
    511 	return MovePtr<ClientBuffer>(buffer);
    512 }
    513 
    514 class UnsupportedImageSource : public ImageSource
    515 {
    516 public:
    517 							UnsupportedImageSource	(const string& message, GLenum format) : m_message(message), m_format(format) {}
    518 	string					getRequiredExtension	(void) const { fail(); return ""; }
    519 	MovePtr<ClientBuffer>	createBuffer			(const glw::Functions&, tcu::Texture2D*) const { fail(); return de::MovePtr<ClientBuffer>(); }
    520 	EGLImageKHR				createImage				(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
    521 	GLenum					getEffectiveFormat		(void) const { return m_format; }
    522 
    523 private:
    524 	const string			m_message;
    525 	GLenum					m_format;
    526 
    527 	void					fail					(void) const { TCU_THROW(NotSupportedError, m_message.c_str()); }
    528 };
    529 
    530 EGLImageKHR	UnsupportedImageSource::createImage (const Library&, EGLDisplay, EGLContext, EGLClientBuffer) const
    531 {
    532 	fail();
    533 	return EGL_NO_IMAGE_KHR;
    534 }
    535 
    536 MovePtr<ImageSource> createTextureImageSource (EGLenum source, GLenum internalFormat, GLenum format, GLenum type, bool useTexLevel0)
    537 {
    538 	if (source == EGL_GL_TEXTURE_2D_KHR)
    539 		return MovePtr<ImageSource>(new Texture2DImageSource(internalFormat, format, type, useTexLevel0));
    540 	else
    541 		return MovePtr<ImageSource>(new TextureCubeMapImageSource(source, internalFormat, format, type, useTexLevel0));
    542 }
    543 
    544 MovePtr<ImageSource> createRenderbufferImageSource (GLenum format)
    545 {
    546 	return MovePtr<ImageSource>(new RenderbufferImageSource(format));
    547 }
    548 
    549 MovePtr<ImageSource> createUnsupportedImageSource (const string& message, GLenum format)
    550 {
    551 	return MovePtr<ImageSource>(new UnsupportedImageSource(message, format));
    552 }
    553 
    554 } // Image
    555 } // egl
    556 } // deqp
    557