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