Home | History | Annotate | Download | only in null
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES Utilities
      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 Render context implementation that does no rendering.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "tcuNullRenderContext.hpp"
     25 #include "tcuTexture.hpp"
     26 #include "tcuTextureUtil.hpp"
     27 #include "deThreadLocal.hpp"
     28 #include "gluRenderConfig.hpp"
     29 #include "gluTextureUtil.hpp"
     30 #include "glwEnums.hpp"
     31 
     32 #include <string>
     33 #include <vector>
     34 
     35 namespace tcu
     36 {
     37 namespace null
     38 {
     39 
     40 using std::string;
     41 using std::vector;
     42 using namespace glw;
     43 using namespace glu;
     44 
     45 class ObjectManager
     46 {
     47 public:
     48 	ObjectManager (void)
     49 		: m_lastObject(0)
     50 	{
     51 	}
     52 
     53 	deUint32 allocate (void)
     54 	{
     55 		deUint32 object = ++m_lastObject;
     56 		if (object == 0)
     57 			object = ++m_lastObject; // Just ignore overflow.
     58 		return object;
     59 	}
     60 
     61 	void free (deUint32 object)
     62 	{
     63 		DE_UNREF(object);
     64 	}
     65 
     66 private:
     67 	deUint32 m_lastObject;
     68 };
     69 
     70 class Context
     71 {
     72 public:
     73 							Context				(ContextType ctxType_);
     74 							~Context			(void);
     75 
     76 private:
     77 							Context				(const Context&);
     78 	Context&				operator=			(const Context&);
     79 
     80 	void					addExtension		(const char* name);
     81 
     82 public:
     83 	// GL state exposed to implementation functions.
     84 	const ContextType		ctxType;
     85 
     86 	string					vendor;
     87 	string					version;
     88 	string					renderer;
     89 	string					shadingLanguageVersion;
     90 	string					extensions;
     91 	vector<string>			extensionList;
     92 
     93 	GLenum					lastError;
     94 
     95 	int						pixelPackRowLength;
     96 	int						pixelPackSkipRows;
     97 	int						pixelPackSkipPixels;
     98 	int						pixelPackAlignment;
     99 
    100 	GLuint					pixelPackBufferBufferBinding;
    101 
    102 	ObjectManager			shaders;
    103 	ObjectManager			programs;
    104 	ObjectManager			textures;
    105 	ObjectManager			buffers;
    106 	ObjectManager			renderbuffers;
    107 	ObjectManager			framebuffers;
    108 	ObjectManager			samplers;
    109 	ObjectManager			vertexArrays;
    110 	ObjectManager			queries;
    111 	ObjectManager			transformFeedbacks;
    112 	ObjectManager			programPipelines;
    113 };
    114 
    115 Context::Context (ContextType ctxType_)
    116 	: ctxType						(ctxType_)
    117 	, vendor						("drawElements")
    118 	, renderer						("dummy")
    119 	, lastError						(GL_NO_ERROR)
    120 	, pixelPackRowLength			(0)
    121 	, pixelPackSkipRows				(0)
    122 	, pixelPackSkipPixels			(0)
    123 	, pixelPackAlignment			(0)
    124 	, pixelPackBufferBufferBinding	(0)
    125 {
    126 	using glu::ApiType;
    127 
    128 	if (ctxType.getAPI() == ApiType::es(2, 0))
    129 	{
    130 		version					= "OpenGL ES 2.0";
    131 		shadingLanguageVersion	= "OpenGL ES GLSL ES 1.0";
    132 	}
    133 	else if (ctxType.getAPI() == ApiType::es(3, 0))
    134 	{
    135 		version					= "OpenGL ES 3.0";
    136 		shadingLanguageVersion	= "OpenGL ES GLSL ES 3.0";
    137 	}
    138 	else if (ctxType.getAPI() == ApiType::es(3, 1))
    139 	{
    140 		version					= "OpenGL ES 3.1";
    141 		shadingLanguageVersion	= "OpenGL ES GLSL ES 3.1";
    142 		addExtension("GL_OES_texture_stencil8");
    143 		addExtension("GL_OES_sample_shading");
    144 		addExtension("GL_OES_sample_variables");
    145 		addExtension("GL_OES_shader_multisample_interpolation");
    146 		addExtension("GL_OES_shader_image_atomics");
    147 		addExtension("GL_OES_texture_storage_multisample_2d_array");
    148 		addExtension("GL_KHR_blend_equation_advanced");
    149 		addExtension("GL_KHR_blend_equation_advanced_coherent");
    150 		addExtension("GL_EXT_shader_io_blocks");
    151 		addExtension("GL_EXT_geometry_shader");
    152 		addExtension("GL_EXT_geometry_point_size");
    153 		addExtension("GL_EXT_tessellation_shader");
    154 		addExtension("GL_EXT_tessellation_point_size");
    155 		addExtension("GL_EXT_gpu_shader5");
    156 	}
    157 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 3)
    158 	{
    159 		version					= "3.3.0";
    160 		shadingLanguageVersion	= "3.30";
    161 	}
    162 	else if (glu::isContextTypeGLCore(ctxType) && ctxType.getMajorVersion() == 4 && ctxType.getMinorVersion() <= 4)
    163 	{
    164 		version					= "4.4.0";
    165 		shadingLanguageVersion	= "4.40";
    166 	}
    167 	else
    168 		throw tcu::NotSupportedError("Unsupported GL version", "", __FILE__, __LINE__);
    169 
    170 	if (isContextTypeES(ctxType))
    171 		addExtension("GL_EXT_color_buffer_float");
    172 }
    173 
    174 Context::~Context (void)
    175 {
    176 }
    177 
    178 void Context::addExtension (const char* name)
    179 {
    180 	if (!extensions.empty())
    181 		extensions += " ";
    182 	extensions += name;
    183 
    184 	extensionList.push_back(name);
    185 }
    186 
    187 static de::ThreadLocal s_currentCtx;
    188 
    189 void setCurrentContext (Context* context)
    190 {
    191 	s_currentCtx.set((void*)context);
    192 }
    193 
    194 Context* getCurrentContext (void)
    195 {
    196 	return (Context*)s_currentCtx.get();
    197 }
    198 
    199 GLW_APICALL GLenum GLW_APIENTRY glGetError (void)
    200 {
    201 	Context* const	ctx		= getCurrentContext();
    202 	const GLenum	lastErr	= ctx->lastError;
    203 
    204 	ctx->lastError = GL_NO_ERROR;
    205 
    206 	return lastErr;
    207 }
    208 
    209 GLW_APICALL void GLW_APIENTRY glGetIntegerv (GLenum pname, GLint* params)
    210 {
    211 	Context* const ctx = getCurrentContext();
    212 
    213 	switch (pname)
    214 	{
    215 		case GL_NUM_EXTENSIONS:
    216 			*params = (int)ctx->extensionList.size();
    217 			break;
    218 
    219 		case GL_MAX_VERTEX_ATTRIBS:
    220 			*params = 32;
    221 			break;
    222 
    223 		case GL_MAX_DRAW_BUFFERS:
    224 		case GL_MAX_COLOR_ATTACHMENTS:
    225 			*params = 8;
    226 			break;
    227 
    228 		case GL_MAX_TEXTURE_IMAGE_UNITS:
    229 		case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    230 		case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    231 		case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
    232 		case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS:
    233 		case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS:
    234 			*params = 16;
    235 			break;
    236 
    237 		case GL_MAX_TEXTURE_SIZE:
    238 		case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    239 		case GL_MAX_3D_TEXTURE_SIZE:
    240 		case GL_MAX_RENDERBUFFER_SIZE:
    241 			*params = 2048;
    242 			break;
    243 
    244 		case GL_MAX_ARRAY_TEXTURE_LAYERS:
    245 			*params = 128;
    246 			break;
    247 
    248 		case GL_NUM_SHADER_BINARY_FORMATS:
    249 			*params = 0;
    250 			break;
    251 
    252 		case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    253 			*params = 0;
    254 			break;
    255 
    256 		case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
    257 			*params = 16;
    258 			break;
    259 
    260 		case GL_MAX_UNIFORM_BUFFER_BINDINGS:
    261 			*params = 32;
    262 			break;
    263 
    264 		case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
    265 			*params = 16;
    266 			break;
    267 
    268 		case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
    269 			*params = GL_RGBA;
    270 			break;
    271 
    272 		case GL_IMPLEMENTATION_COLOR_READ_TYPE:
    273 			*params = GL_UNSIGNED_BYTE;
    274 			break;
    275 
    276 		case GL_SAMPLE_BUFFERS:
    277 			*params = 0;
    278 			break;
    279 
    280 		default:
    281 			break;
    282 	}
    283 }
    284 
    285 GLW_APICALL void GLW_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params)
    286 {
    287 	switch (pname)
    288 	{
    289 		case GL_SHADER_COMPILER:
    290 			*params = GL_TRUE;
    291 			break;
    292 
    293 		default:
    294 			break;
    295 	}
    296 }
    297 
    298 GLW_APICALL void GLW_APIENTRY glGetFloatv (GLenum pname, GLfloat* params)
    299 {
    300 	switch (pname)
    301 	{
    302 		case GL_ALIASED_LINE_WIDTH_RANGE:
    303 		case GL_ALIASED_POINT_SIZE_RANGE:
    304 			params[0] = 0.0f;
    305 			params[1] = 64.0f;
    306 			break;
    307 
    308 		default:
    309 			break;
    310 	}
    311 }
    312 
    313 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetString (GLenum name)
    314 {
    315 	Context* const ctx = getCurrentContext();
    316 
    317 	switch (name)
    318 	{
    319 		case GL_VENDOR:						return (const glw::GLubyte*)ctx->vendor.c_str();
    320 		case GL_VERSION:					return (const glw::GLubyte*)ctx->version.c_str();
    321 		case GL_RENDERER:					return (const glw::GLubyte*)ctx->renderer.c_str();
    322 		case GL_SHADING_LANGUAGE_VERSION:	return (const glw::GLubyte*)ctx->shadingLanguageVersion.c_str();
    323 		case GL_EXTENSIONS:					return (const glw::GLubyte*)ctx->extensions.c_str();
    324 		default:
    325 			ctx->lastError = GL_INVALID_ENUM;
    326 			return DE_NULL;
    327 	}
    328 }
    329 
    330 GLW_APICALL const glw::GLubyte* GLW_APIENTRY glGetStringi (GLenum name, GLuint index)
    331 {
    332 	Context* const ctx = getCurrentContext();
    333 
    334 	if (name == GL_EXTENSIONS)
    335 	{
    336 		if ((size_t)index < ctx->extensionList.size())
    337 			return (const glw::GLubyte*)ctx->extensionList[index].c_str();
    338 		else
    339 		{
    340 			ctx->lastError = GL_INVALID_VALUE;
    341 			return DE_NULL;
    342 		}
    343 	}
    344 	else
    345 	{
    346 		ctx->lastError = GL_INVALID_ENUM;
    347 		return DE_NULL;
    348 	}
    349 }
    350 
    351 GLW_APICALL GLuint GLW_APIENTRY glCreateProgram ()
    352 {
    353 	Context* const ctx = getCurrentContext();
    354 	return (GLuint)ctx->programs.allocate();
    355 }
    356 
    357 GLW_APICALL GLuint GLW_APIENTRY glCreateShader (GLenum type)
    358 {
    359 	Context* const ctx = getCurrentContext();
    360 	DE_UNREF(type);
    361 	return (GLuint)ctx->shaders.allocate();
    362 }
    363 
    364 GLW_APICALL void GLW_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params)
    365 {
    366 	DE_UNREF(shader);
    367 
    368 	if (pname == GL_COMPILE_STATUS)
    369 		*params = GL_TRUE;
    370 }
    371 
    372 GLW_APICALL void GLW_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params)
    373 {
    374 	DE_UNREF(program);
    375 
    376 	if (pname == GL_LINK_STATUS)
    377 		*params = GL_TRUE;
    378 }
    379 
    380 GLW_APICALL void GLW_APIENTRY glGenTextures (GLsizei n, GLuint* textures)
    381 {
    382 	Context* const ctx = getCurrentContext();
    383 
    384 	if (textures)
    385 	{
    386 		for (int ndx = 0; ndx < n; ndx++)
    387 			textures[ndx] = ctx->textures.allocate();
    388 	}
    389 }
    390 
    391 GLW_APICALL void GLW_APIENTRY glGenQueries (GLsizei n, GLuint* ids)
    392 {
    393 	Context* const ctx = getCurrentContext();
    394 
    395 	if (ids)
    396 	{
    397 		for (int ndx = 0; ndx < n; ndx++)
    398 			ids[ndx] = ctx->queries.allocate();
    399 	}
    400 }
    401 
    402 GLW_APICALL void GLW_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers)
    403 {
    404 	Context* const ctx = getCurrentContext();
    405 
    406 	if (buffers)
    407 	{
    408 		for (int ndx = 0; ndx < n; ndx++)
    409 			buffers[ndx] = ctx->buffers.allocate();
    410 	}
    411 }
    412 
    413 GLW_APICALL void GLW_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers)
    414 {
    415 	Context* const ctx = getCurrentContext();
    416 
    417 	if (renderbuffers)
    418 	{
    419 		for (int ndx = 0; ndx < n; ndx++)
    420 			renderbuffers[ndx] = ctx->renderbuffers.allocate();
    421 	}
    422 }
    423 
    424 GLW_APICALL void GLW_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers)
    425 {
    426 	Context* const ctx = getCurrentContext();
    427 
    428 	if (framebuffers)
    429 	{
    430 		for (int ndx = 0; ndx < n; ndx++)
    431 			framebuffers[ndx] = ctx->framebuffers.allocate();
    432 	}
    433 }
    434 
    435 GLW_APICALL void GLW_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays)
    436 {
    437 	Context* const ctx = getCurrentContext();
    438 
    439 	if (arrays)
    440 	{
    441 		for (int ndx = 0; ndx < n; ndx++)
    442 			arrays[ndx] = ctx->vertexArrays.allocate();
    443 	}
    444 }
    445 
    446 GLW_APICALL void GLW_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers)
    447 {
    448 	Context* const ctx = getCurrentContext();
    449 
    450 	if (samplers)
    451 	{
    452 		for (int ndx = 0; ndx < count; ndx++)
    453 			samplers[ndx] = ctx->samplers.allocate();
    454 	}
    455 }
    456 
    457 GLW_APICALL void GLW_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids)
    458 {
    459 	Context* const ctx = getCurrentContext();
    460 
    461 	if (ids)
    462 	{
    463 		for (int ndx = 0; ndx < n; ndx++)
    464 			ids[ndx] = ctx->transformFeedbacks.allocate();
    465 	}
    466 }
    467 
    468 GLW_APICALL void GLW_APIENTRY glGenProgramPipelines (GLsizei n, GLuint* pipelines)
    469 {
    470 	Context* const ctx = getCurrentContext();
    471 
    472 	if (pipelines)
    473 	{
    474 		for (int ndx = 0; ndx < n; ndx++)
    475 			pipelines[ndx] = ctx->programPipelines.allocate();
    476 	}
    477 }
    478 
    479 GLW_APICALL GLvoid* GLW_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
    480 {
    481 	Context* const ctx = getCurrentContext();
    482 
    483 	DE_UNREF(target);
    484 	DE_UNREF(offset);
    485 	DE_UNREF(length);
    486 	DE_UNREF(access);
    487 
    488 	if (ctx->lastError == GL_NO_ERROR)
    489 		ctx->lastError = GL_INVALID_OPERATION;
    490 
    491 	return (GLvoid*)0;
    492 }
    493 
    494 GLW_APICALL GLenum GLW_APIENTRY glCheckFramebufferStatus (GLenum target)
    495 {
    496 	DE_UNREF(target);
    497 	return GL_FRAMEBUFFER_COMPLETE;
    498 }
    499 
    500 GLW_APICALL void GLW_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
    501 {
    502 	DE_UNREF(x);
    503 	DE_UNREF(y);
    504 
    505 	Context* const					ctx					= getCurrentContext();
    506 	const tcu::Vec4					clearColor			(0.0f, 0.0f, 0.0f, 1.0f); // black
    507 	const tcu::TextureFormat		transferFormat		= glu::mapGLTransferFormat(format, type);
    508 
    509 	// invalid formats
    510 	if (transferFormat.order == TextureFormat::CHANNELORDER_LAST || transferFormat.type == TextureFormat::CHANNELTYPE_LAST)
    511 	{
    512 		if (ctx->lastError == GL_NO_ERROR)
    513 			ctx->lastError = GL_INVALID_ENUM;
    514 		return;
    515 	}
    516 
    517 	// unsupported formats
    518 	if (!(format == GL_RGBA			&& type == GL_UNSIGNED_BYTE)	&&
    519 		!(format == GL_RGBA_INTEGER	&& type == GL_INT)				&&
    520 		!(format == GL_RGBA_INTEGER	&& type == GL_UNSIGNED_INT)		&&
    521 		!(format == GL_RGBA			&& type == GL_FLOAT))
    522 	{
    523 		if (ctx->lastError == GL_NO_ERROR)
    524 			ctx->lastError = GL_INVALID_ENUM;
    525 		return;
    526 	}
    527 
    528 	// invalid arguments
    529 	if (width < 0 || height < 0)
    530 	{
    531 		if (ctx->lastError == GL_NO_ERROR)
    532 			ctx->lastError = GL_INVALID_OPERATION;
    533 		return;
    534 	}
    535 
    536 	// read to buffer
    537 	if (ctx->pixelPackBufferBufferBinding)
    538 		return;
    539 
    540 	// read to use pointer
    541 	{
    542 		const int						targetRowLength		= (ctx->pixelPackRowLength != 0) ? (ctx->pixelPackRowLength) : (width);
    543 		const int						targetSkipRows		= ctx->pixelPackSkipRows;
    544 		const int						targetSkipPixels	= ctx->pixelPackSkipPixels;
    545 		const int						infiniteHeight		= targetSkipRows + height; // as much as needed
    546 		const int						targetRowPitch		= (ctx->pixelPackAlignment == 0) ? (targetRowLength * transferFormat.getPixelSize()) : (deAlign32(targetRowLength * transferFormat.getPixelSize(), ctx->pixelPackAlignment));
    547 
    548 		// Create access to the whole copy target
    549 		const tcu::PixelBufferAccess	targetAccess		(transferFormat, targetRowLength, infiniteHeight, 1, targetRowPitch, 0, pixels);
    550 
    551 		// Select (skip_pixels, skip_rows, width, height) subregion from it. Clip to horizontal boundaries
    552 		const tcu::PixelBufferAccess	targetRectAccess	= tcu::getSubregion(targetAccess,
    553 																				de::clamp(targetSkipPixels, 0, targetAccess.getWidth()-1),
    554 																				targetSkipRows,
    555 																				de::clamp(width, 0, de::max(0, targetAccess.getWidth() - targetSkipPixels)),
    556 																				height);
    557 
    558 		tcu::clear(targetRectAccess, clearColor);
    559 	}
    560 }
    561 
    562 GLW_APICALL void GLW_APIENTRY glBindBuffer (GLenum target, GLuint buffer)
    563 {
    564 	Context* const ctx = getCurrentContext();
    565 
    566 	if (target == GL_PIXEL_PACK_BUFFER)
    567 		ctx->pixelPackBufferBufferBinding = buffer;
    568 }
    569 
    570 GLW_APICALL void GLW_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers)
    571 {
    572 	Context* const ctx = getCurrentContext();
    573 
    574 	for (GLsizei ndx = 0; ndx < n; ++ndx)
    575 		if (buffers[ndx] && buffers[ndx] == ctx->pixelPackBufferBufferBinding)
    576 			ctx->pixelPackBufferBufferBinding = 0;
    577 }
    578 
    579 #include "tcuNullRenderContextFuncs.inl"
    580 
    581 void initFunctions (glw::Functions* gl)
    582 {
    583 #	include "tcuNullRenderContextInitFuncs.inl"
    584 }
    585 
    586 static tcu::RenderTarget toRenderTarget (const RenderConfig& renderCfg)
    587 {
    588 	const int		width			= getValueOrDefault(renderCfg, &RenderConfig::width,		256);
    589 	const int		height			= getValueOrDefault(renderCfg, &RenderConfig::height,		256);
    590 	const int		redBits			= getValueOrDefault(renderCfg, &RenderConfig::redBits,		8);
    591 	const int		greenBits		= getValueOrDefault(renderCfg, &RenderConfig::greenBits,	8);
    592 	const int		blueBits		= getValueOrDefault(renderCfg, &RenderConfig::blueBits,		8);
    593 	const int		alphaBits		= getValueOrDefault(renderCfg, &RenderConfig::alphaBits,	8);
    594 	const int		depthBits		= getValueOrDefault(renderCfg, &RenderConfig::depthBits,	24);
    595 	const int		stencilBits		= getValueOrDefault(renderCfg, &RenderConfig::stencilBits,	8);
    596 	const int		numSamples		= getValueOrDefault(renderCfg, &RenderConfig::numSamples,	0);
    597 
    598 	return tcu::RenderTarget(width, height, tcu::PixelFormat(redBits, greenBits, blueBits, alphaBits), depthBits, stencilBits, numSamples);
    599 }
    600 
    601 RenderContext::RenderContext (const RenderConfig& renderCfg)
    602 	: m_ctxType			(renderCfg.type)
    603 	, m_renderTarget	(toRenderTarget(renderCfg))
    604 	, m_context			(DE_NULL)
    605 {
    606 	m_context = new Context(m_ctxType);
    607 
    608 	initFunctions(&m_functions);
    609 	setCurrentContext(m_context);
    610 }
    611 
    612 RenderContext::~RenderContext (void)
    613 {
    614 	setCurrentContext(DE_NULL);
    615 	delete m_context;
    616 }
    617 
    618 void RenderContext::postIterate (void)
    619 {
    620 }
    621 
    622 } // null
    623 } // tcu
    624