Home | History | Annotate | Download | only in libGLES_CM
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "Device.hpp"
     16 
     17 #include "common/Image.hpp"
     18 #include "Texture.h"
     19 
     20 #include "Renderer/Renderer.hpp"
     21 #include "Renderer/Clipper.hpp"
     22 #include "Shader/PixelShader.hpp"
     23 #include "Shader/VertexShader.hpp"
     24 #include "Main/Config.hpp"
     25 #include "Main/FrameBuffer.hpp"
     26 #include "Common/Math.hpp"
     27 #include "Common/Configurator.hpp"
     28 #include "Common/Memory.hpp"
     29 #include "Common/Timer.hpp"
     30 #include "../common/debug.h"
     31 
     32 namespace es1
     33 {
     34 	using namespace sw;
     35 
     36 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
     37 	{
     38 		renderTarget = nullptr;
     39 		depthBuffer = nullptr;
     40 		stencilBuffer = nullptr;
     41 
     42 		setDepthBufferEnable(true);
     43 		setFillMode(FILL_SOLID);
     44 		setShadingMode(SHADING_GOURAUD);
     45 		setDepthWriteEnable(true);
     46 		setAlphaTestEnable(false);
     47 		setSourceBlendFactor(BLEND_ONE);
     48 		setDestBlendFactor(BLEND_ZERO);
     49 		setCullMode(CULL_COUNTERCLOCKWISE);
     50 		setDepthCompare(DEPTH_LESSEQUAL);
     51 		setAlphaReference(0.0f);
     52 		setAlphaCompare(ALPHA_ALWAYS);
     53 		setAlphaBlendEnable(false);
     54 		setFogEnable(false);
     55 		setSpecularEnable(true);
     56 		setLocalViewer(false);
     57 		setFogColor(0);
     58 		setPixelFogMode(FOG_NONE);
     59 		setFogStart(0.0f);
     60 		setFogEnd(1.0f);
     61 		setFogDensity(1.0f);
     62 		setRangeFogEnable(false);
     63 		setStencilEnable(false);
     64 		setStencilFailOperation(OPERATION_KEEP);
     65 		setStencilZFailOperation(OPERATION_KEEP);
     66 		setStencilPassOperation(OPERATION_KEEP);
     67 		setStencilCompare(STENCIL_ALWAYS);
     68 		setStencilReference(0);
     69 		setStencilMask(0xFFFFFFFF);
     70 		setStencilWriteMask(0xFFFFFFFF);
     71 		setVertexFogMode(FOG_NONE);
     72 		setClipFlags(0);
     73 		setPointSize(1.0f);
     74 		setPointSizeMin(0.125f);
     75         setPointSizeMax(8192.0f);
     76 		setColorWriteMask(0, 0x0000000F);
     77 		setBlendOperation(BLENDOP_ADD);
     78 		scissorEnable = false;
     79 		setSlopeDepthBias(0.0f);
     80 		setTwoSidedStencil(false);
     81 		setStencilFailOperationCCW(OPERATION_KEEP);
     82 		setStencilZFailOperationCCW(OPERATION_KEEP);
     83 		setStencilPassOperationCCW(OPERATION_KEEP);
     84 		setStencilCompareCCW(STENCIL_ALWAYS);
     85 		setColorWriteMask(1, 0x0000000F);
     86 		setColorWriteMask(2, 0x0000000F);
     87 		setColorWriteMask(3, 0x0000000F);
     88 		setBlendConstant(0xFFFFFFFF);
     89 		setWriteSRGB(false);
     90 		setDepthBias(0.0f);
     91 		setSeparateAlphaBlendEnable(false);
     92 		setSourceBlendFactorAlpha(BLEND_ONE);
     93 		setDestBlendFactorAlpha(BLEND_ZERO);
     94 		setBlendOperationAlpha(BLENDOP_ADD);
     95 		setPointSpriteEnable(true);
     96 
     97 		for(int i = 0; i < 16; i++)
     98 		{
     99 			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    100 			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    101 			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    102 			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
    103 			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
    104 			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
    105 			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
    106 		}
    107 
    108 		for(int i = 0; i < 4; i++)
    109 		{
    110 			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    111 			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    112 			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    113 			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
    114 			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
    115 			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
    116 			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
    117 		}
    118 
    119 		for(int i = 0; i < 6; i++)
    120 		{
    121 			float plane[4] = {0, 0, 0, 0};
    122 
    123 			setClipPlane(i, plane);
    124 		}
    125 	}
    126 
    127 	Device::~Device()
    128 	{
    129 		if(renderTarget)
    130 		{
    131 			renderTarget->release();
    132 			renderTarget = nullptr;
    133 		}
    134 
    135 		if(depthBuffer)
    136 		{
    137 			depthBuffer->release();
    138 			depthBuffer = nullptr;
    139 		}
    140 
    141 		if(stencilBuffer)
    142 		{
    143 			stencilBuffer->release();
    144 			stencilBuffer = nullptr;
    145 		}
    146 
    147 		delete context;
    148 	}
    149 
    150 	// This object has to be mem aligned
    151 	void* Device::operator new(size_t size)
    152 	{
    153 		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
    154 		return sw::allocate(sizeof(Device), 16);
    155 	}
    156 
    157 	void Device::operator delete(void * mem)
    158 	{
    159 		sw::deallocate(mem);
    160 	}
    161 
    162 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
    163 	{
    164 		if(!renderTarget || !rgbaMask)
    165 		{
    166 			return;
    167 		}
    168 
    169 		float rgba[4];
    170 		rgba[0] = red;
    171 		rgba[1] = green;
    172 		rgba[2] = blue;
    173 		rgba[3] = alpha;
    174 
    175 		sw::Rect clearRect = renderTarget->getRect();
    176 
    177 		if(scissorEnable)
    178 		{
    179 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    180 		}
    181 
    182 		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
    183 	}
    184 
    185 	void Device::clearDepth(float z)
    186 	{
    187 		if(!depthBuffer)
    188 		{
    189 			return;
    190 		}
    191 
    192 		z = clamp01(z);
    193 		sw::Rect clearRect = depthBuffer->getRect();
    194 
    195 		if(scissorEnable)
    196 		{
    197 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    198 		}
    199 
    200 		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    201 	}
    202 
    203 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
    204 	{
    205 		if(!stencilBuffer)
    206 		{
    207 			return;
    208 		}
    209 
    210 		sw::Rect clearRect = stencilBuffer->getRect();
    211 
    212 		if(scissorEnable)
    213 		{
    214 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    215 		}
    216 
    217 		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    218 	}
    219 
    220 	egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
    221 	{
    222 		if(height > OUTLINE_RESOLUTION)
    223 		{
    224 			ERR("Invalid parameters: %dx%d", width, height);
    225 			return nullptr;
    226 		}
    227 
    228 		bool lockable = true;
    229 
    230 		switch(format)
    231 		{
    232 	//	case FORMAT_D15S1:
    233 		case FORMAT_D24S8:
    234 		case FORMAT_D24X8:
    235 	//	case FORMAT_D24X4S4:
    236 		case FORMAT_D24FS8:
    237 		case FORMAT_D32:
    238 		case FORMAT_D16:
    239 			lockable = false;
    240 			break;
    241 	//	case FORMAT_S8_LOCKABLE:
    242 	//	case FORMAT_D16_LOCKABLE:
    243 		case FORMAT_D32F_LOCKABLE:
    244 	//	case FORMAT_D32_LOCKABLE:
    245 		case FORMAT_DF24S8:
    246 		case FORMAT_DF16S8:
    247 			lockable = true;
    248 			break;
    249 		default:
    250 			UNREACHABLE(format);
    251 		}
    252 
    253 		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
    254 
    255 		if(!surface)
    256 		{
    257 			ERR("Out of memory");
    258 			return nullptr;
    259 		}
    260 
    261 		return surface;
    262 	}
    263 
    264 	egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
    265 	{
    266 		if(height > OUTLINE_RESOLUTION)
    267 		{
    268 			ERR("Invalid parameters: %dx%d", width, height);
    269 			return nullptr;
    270 		}
    271 
    272 		egl::Image *surface = egl::Image::create(width, height, format, multiSampleDepth, lockable);
    273 
    274 		if(!surface)
    275 		{
    276 			ERR("Out of memory");
    277 			return nullptr;
    278 		}
    279 
    280 		return surface;
    281 	}
    282 
    283 	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
    284 	{
    285 		if(!bindResources() || !primitiveCount)
    286 		{
    287 			return;
    288 		}
    289 
    290 		draw(type, indexOffset, primitiveCount);
    291 	}
    292 
    293 	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
    294 	{
    295 		if(!bindResources() || !primitiveCount)
    296 		{
    297 			return;
    298 		}
    299 
    300 		setIndexBuffer(nullptr);
    301 
    302 		draw(type, 0, primitiveCount);
    303 	}
    304 
    305 	void Device::setScissorEnable(bool enable)
    306 	{
    307 		scissorEnable = enable;
    308 	}
    309 
    310 	void Device::setRenderTarget(int index, egl::Image *renderTarget)
    311 	{
    312 		if(renderTarget)
    313 		{
    314 			renderTarget->addRef();
    315 		}
    316 
    317 		if(this->renderTarget)
    318 		{
    319 			this->renderTarget->release();
    320 		}
    321 
    322 		this->renderTarget = renderTarget;
    323 
    324 		Renderer::setRenderTarget(index, renderTarget);
    325 	}
    326 
    327 	void Device::setDepthBuffer(egl::Image *depthBuffer)
    328 	{
    329 		if(this->depthBuffer == depthBuffer)
    330 		{
    331 			return;
    332 		}
    333 
    334 		if(depthBuffer)
    335 		{
    336 			depthBuffer->addRef();
    337 		}
    338 
    339 		if(this->depthBuffer)
    340 		{
    341 			this->depthBuffer->release();
    342 		}
    343 
    344 		this->depthBuffer = depthBuffer;
    345 
    346 		Renderer::setDepthBuffer(depthBuffer);
    347 	}
    348 
    349 	void Device::setStencilBuffer(egl::Image *stencilBuffer)
    350 	{
    351 		if(this->stencilBuffer == stencilBuffer)
    352 		{
    353 			return;
    354 		}
    355 
    356 		if(stencilBuffer)
    357 		{
    358 			stencilBuffer->addRef();
    359 		}
    360 
    361 		if(this->stencilBuffer)
    362 		{
    363 			this->stencilBuffer->release();
    364 		}
    365 
    366 		this->stencilBuffer = stencilBuffer;
    367 
    368 		Renderer::setStencilBuffer(stencilBuffer);
    369 	}
    370 
    371 	void Device::setScissorRect(const sw::Rect &rect)
    372 	{
    373 		scissorRect = rect;
    374 	}
    375 
    376 	void Device::setViewport(const Viewport &viewport)
    377 	{
    378 		this->viewport = viewport;
    379 	}
    380 
    381 	bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
    382 	{
    383 		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
    384 		{
    385 			ERR("Invalid parameters");
    386 			return false;
    387 		}
    388 
    389 		int sWidth = source->getWidth();
    390 		int sHeight = source->getHeight();
    391 		int dWidth = dest->getWidth();
    392 		int dHeight = dest->getHeight();
    393 
    394 		SliceRect sRect;
    395 		SliceRect dRect;
    396 
    397 		if(sourceRect)
    398 		{
    399 			sRect = *sourceRect;
    400 		}
    401 		else
    402 		{
    403 			sRect.y0 = 0;
    404 			sRect.x0 = 0;
    405 			sRect.y1 = sHeight;
    406 			sRect.x1 = sWidth;
    407 		}
    408 
    409 		if(destRect)
    410 		{
    411 			dRect = *destRect;
    412 		}
    413 		else
    414 		{
    415 			dRect.y0 = 0;
    416 			dRect.x0 = 0;
    417 			dRect.y1 = dHeight;
    418 			dRect.x1 = dWidth;
    419 		}
    420 
    421 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
    422 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
    423 		bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
    424 		bool alpha0xFF = false;
    425 
    426 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
    427 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
    428 		{
    429 			equalFormats = true;
    430 			alpha0xFF = true;
    431 		}
    432 
    433 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
    434 		{
    435 			if(source->hasDepth())
    436 			{
    437 				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
    438 				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
    439 
    440 				unsigned int width = source->getWidth();
    441 				unsigned int height = source->getHeight();
    442 				unsigned int pitch = source->getInternalPitchB();
    443 
    444 				for(unsigned int y = 0; y < height; y++)
    445 				{
    446 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
    447 
    448 					sourceBuffer += pitch;
    449 					destBuffer += pitch;
    450 				}
    451 
    452 				source->unlockInternal();
    453 				dest->unlockInternal();
    454 			}
    455 
    456 			if(source->hasStencil())
    457 			{
    458 				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
    459 				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
    460 
    461 				unsigned int width = source->getWidth();
    462 				unsigned int height = source->getHeight();
    463 				unsigned int pitch = source->getStencilPitchB();
    464 
    465 				for(unsigned int y = 0; y < height; y++)
    466 				{
    467 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
    468 
    469 					sourceBuffer += pitch;
    470 					destBuffer += pitch;
    471 				}
    472 
    473 				source->unlockStencil();
    474 				dest->unlockStencil();
    475 			}
    476 		}
    477 		else if(!scaling && equalFormats)
    478 		{
    479 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
    480 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
    481 			unsigned int sourcePitch = source->getInternalPitchB();
    482 			unsigned int destPitch = dest->getInternalPitchB();
    483 
    484 			unsigned int width = dRect.x1 - dRect.x0;
    485 			unsigned int height = dRect.y1 - dRect.y0;
    486 			unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat());
    487 
    488 			for(unsigned int y = 0; y < height; y++)
    489 			{
    490 				memcpy(destBytes, sourceBytes, bytes);
    491 
    492 				if(alpha0xFF)
    493 				{
    494 					for(unsigned int x = 0; x < width; x++)
    495 					{
    496 						destBytes[4 * x + 3] = 0xFF;
    497 					}
    498 				}
    499 
    500 				sourceBytes += sourcePitch;
    501 				destBytes += destPitch;
    502 			}
    503 
    504 			source->unlockInternal();
    505 			dest->unlockInternal();
    506 		}
    507 		else
    508 		{
    509 			blit(source, sRect, dest, dRect, scaling && filter);
    510 		}
    511 
    512 		return true;
    513 	}
    514 
    515 	bool Device::bindResources()
    516 	{
    517 		if(!bindViewport())
    518 		{
    519 			return false;   // Zero-area target region
    520 		}
    521 
    522 		return true;
    523 	}
    524 
    525 	bool Device::bindViewport()
    526 	{
    527 		if(viewport.width <= 0 || viewport.height <= 0)
    528 		{
    529 			return false;
    530 		}
    531 
    532 		if(scissorEnable)
    533 		{
    534 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
    535 			{
    536 				return false;
    537 			}
    538 
    539 			sw::Rect scissor;
    540 			scissor.x0 = scissorRect.x0;
    541 			scissor.x1 = scissorRect.x1;
    542 			scissor.y0 = scissorRect.y0;
    543 			scissor.y1 = scissorRect.y1;
    544 
    545 			setScissor(scissor);
    546 		}
    547 		else
    548 		{
    549 			sw::Rect scissor;
    550 			scissor.x0 = viewport.x0;
    551 			scissor.x1 = viewport.x0 + viewport.width;
    552 			scissor.y0 = viewport.y0;
    553 			scissor.y1 = viewport.y0 + viewport.height;
    554 
    555 			if(renderTarget)
    556 			{
    557 				scissor.x0 = max(scissor.x0, 0);
    558 				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
    559 				scissor.y0 = max(scissor.y0, 0);
    560 				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
    561 			}
    562 
    563 			if(depthBuffer)
    564 			{
    565 				scissor.x0 = max(scissor.x0, 0);
    566 				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
    567 				scissor.y0 = max(scissor.y0, 0);
    568 				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
    569 			}
    570 
    571 			if(stencilBuffer)
    572 			{
    573 				scissor.x0 = max(scissor.x0, 0);
    574 				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
    575 				scissor.y0 = max(scissor.y0, 0);
    576 				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
    577 			}
    578 
    579 			setScissor(scissor);
    580 		}
    581 
    582 		sw::Viewport view;
    583 		view.x0 = (float)viewport.x0;
    584 		view.y0 = (float)viewport.y0;
    585 		view.width = (float)viewport.width;
    586 		view.height = (float)viewport.height;
    587 		view.minZ = viewport.minZ;
    588 		view.maxZ = viewport.maxZ;
    589 
    590 		Renderer::setViewport(view);
    591 
    592 		return true;
    593 	}
    594 
    595 	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
    596 	{
    597 		if(!rect)
    598 		{
    599 			return true;
    600 		}
    601 
    602 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
    603 		{
    604 			return false;
    605 		}
    606 
    607 		if(rect->x0 < 0 || rect->y0 < 0)
    608 		{
    609 			return false;
    610 		}
    611 
    612 		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
    613 		{
    614 			return false;
    615 		}
    616 
    617 		return true;
    618 	}
    619 
    620 	void Device::finish()
    621 	{
    622 		synchronize();
    623 	}
    624 }
    625