Home | History | Annotate | Download | only in libGLESv2
      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 es2
     33 {
     34 	using namespace sw;
     35 
     36 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
     37 	{
     38 		for(int i = 0; i < RENDERTARGETS; i++)
     39 		{
     40 			renderTarget[i] = nullptr;
     41 		}
     42 
     43 		depthBuffer = nullptr;
     44 		stencilBuffer = nullptr;
     45 
     46 		setDepthBufferEnable(true);
     47 		setFillMode(FILL_SOLID);
     48 		setShadingMode(SHADING_GOURAUD);
     49 		setDepthWriteEnable(true);
     50 		setAlphaTestEnable(false);
     51 		setSourceBlendFactor(BLEND_ONE);
     52 		setDestBlendFactor(BLEND_ZERO);
     53 		setCullMode(CULL_COUNTERCLOCKWISE, true);
     54 		setDepthCompare(DEPTH_LESSEQUAL);
     55 		setAlphaReference(127.5f);
     56 		setAlphaCompare(ALPHA_ALWAYS);
     57 		setAlphaBlendEnable(false);
     58 		setFogEnable(false);
     59 		setSpecularEnable(false);
     60 		setFogColor(0);
     61 		setPixelFogMode(FOG_NONE);
     62 		setFogStart(0.0f);
     63 		setFogEnd(1.0f);
     64 		setFogDensity(1.0f);
     65 		setRangeFogEnable(false);
     66 		setStencilEnable(false);
     67 		setStencilFailOperation(OPERATION_KEEP);
     68 		setStencilZFailOperation(OPERATION_KEEP);
     69 		setStencilPassOperation(OPERATION_KEEP);
     70 		setStencilCompare(STENCIL_ALWAYS);
     71 		setStencilReference(0);
     72 		setStencilMask(0xFFFFFFFF);
     73 		setStencilWriteMask(0xFFFFFFFF);
     74 		setVertexFogMode(FOG_NONE);
     75 		setClipFlags(0);
     76 		setPointSize(1.0f);
     77 		setPointSizeMin(0.125f);
     78         setPointSizeMax(8192.0f);
     79 		setBlendOperation(BLENDOP_ADD);
     80 		scissorEnable = false;
     81 		setSlopeDepthBias(0.0f);
     82 		setTwoSidedStencil(false);
     83 		setStencilFailOperationCCW(OPERATION_KEEP);
     84 		setStencilZFailOperationCCW(OPERATION_KEEP);
     85 		setStencilPassOperationCCW(OPERATION_KEEP);
     86 		setStencilCompareCCW(STENCIL_ALWAYS);
     87 		setBlendConstant(0xFFFFFFFF);
     88 		setWriteSRGB(false);
     89 		setDepthBias(0.0f);
     90 		setSeparateAlphaBlendEnable(false);
     91 		setSourceBlendFactorAlpha(BLEND_ONE);
     92 		setDestBlendFactorAlpha(BLEND_ZERO);
     93 		setBlendOperationAlpha(BLENDOP_ADD);
     94 		setPointSpriteEnable(true);
     95 		setColorLogicOpEnabled(false);
     96 		setLogicalOperation(LOGICALOP_COPY);
     97 
     98 		for(int i = 0; i < 16; i++)
     99 		{
    100 			setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    101 			setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    102 			setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
    103 			setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
    104 			setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
    105 			setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
    106 			setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
    107 		}
    108 
    109 		for(int i = 0; i < 4; i++)
    110 		{
    111 			setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    112 			setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    113 			setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
    114 			setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
    115 			setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
    116 			setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
    117 			setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
    118 		}
    119 
    120 		for(int i = 0; i < 6; i++)
    121 		{
    122 			float plane[4] = {0, 0, 0, 0};
    123 
    124 			setClipPlane(i, plane);
    125 		}
    126 
    127 		pixelShader = nullptr;
    128 		vertexShader = nullptr;
    129 
    130 		pixelShaderDirty = true;
    131 		pixelShaderConstantsFDirty = 0;
    132 		vertexShaderDirty = true;
    133 		vertexShaderConstantsFDirty = 0;
    134 
    135 		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
    136 		{
    137 			float zero[4] = {0, 0, 0, 0};
    138 
    139 			setPixelShaderConstantF(i, zero, 1);
    140 		}
    141 
    142 		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
    143 		{
    144 			float zero[4] = {0, 0, 0, 0};
    145 
    146 			setVertexShaderConstantF(i, zero, 1);
    147 		}
    148 	}
    149 
    150 	Device::~Device()
    151 	{
    152 		for(int i = 0; i < RENDERTARGETS; i++)
    153 		{
    154 			if(renderTarget[i])
    155 			{
    156 				renderTarget[i]->release();
    157 				renderTarget[i] = nullptr;
    158 			}
    159 		}
    160 
    161 		if(depthBuffer)
    162 		{
    163 			depthBuffer->release();
    164 			depthBuffer = nullptr;
    165 		}
    166 
    167 		if(stencilBuffer)
    168 		{
    169 			stencilBuffer->release();
    170 			stencilBuffer = nullptr;
    171 		}
    172 
    173 		delete context;
    174 	}
    175 
    176 	// This object has to be mem aligned
    177 	void* Device::operator new(size_t size)
    178 	{
    179 		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
    180 		return sw::allocate(sizeof(Device), 16);
    181 	}
    182 
    183 	void Device::operator delete(void * mem)
    184 	{
    185 		sw::deallocate(mem);
    186 	}
    187 
    188 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
    189 	{
    190 		if(!rgbaMask)
    191 		{
    192 			return;
    193 		}
    194 
    195 		float rgba[4];
    196 		rgba[0] = red;
    197 		rgba[1] = green;
    198 		rgba[2] = blue;
    199 		rgba[3] = alpha;
    200 
    201 		for(int i = 0; i < RENDERTARGETS; ++i)
    202 		{
    203 			if(renderTarget[i])
    204 			{
    205 				sw::Rect clearRect = renderTarget[i]->getRect();
    206 
    207 				if(scissorEnable)
    208 				{
    209 					clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    210 				}
    211 
    212 				clear(rgba, FORMAT_A32B32G32R32F, renderTarget[i], clearRect, rgbaMask);
    213 			}
    214 		}
    215 	}
    216 
    217 	void Device::clearDepth(float z)
    218 	{
    219 		if(!depthBuffer)
    220 		{
    221 			return;
    222 		}
    223 
    224 		z = clamp01(z);
    225 		sw::Rect clearRect = depthBuffer->getRect();
    226 
    227 		if(scissorEnable)
    228 		{
    229 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    230 		}
    231 
    232 		depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    233 	}
    234 
    235 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
    236 	{
    237 		if(!stencilBuffer)
    238 		{
    239 			return;
    240 		}
    241 
    242 		sw::Rect clearRect = stencilBuffer->getRect();
    243 
    244 		if(scissorEnable)
    245 		{
    246 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    247 		}
    248 
    249 		stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    250 	}
    251 
    252 	void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount)
    253 	{
    254 		if(!bindResources() || !primitiveCount)
    255 		{
    256 			return;
    257 		}
    258 
    259 		draw(type, indexOffset, primitiveCount);
    260 	}
    261 
    262 	void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount)
    263 	{
    264 		if(!bindResources() || !primitiveCount)
    265 		{
    266 			return;
    267 		}
    268 
    269 		setIndexBuffer(nullptr);
    270 
    271 		draw(type, 0, primitiveCount);
    272 	}
    273 
    274 	void Device::setPixelShader(const PixelShader *pixelShader)
    275 	{
    276 		this->pixelShader = pixelShader;
    277 		pixelShaderDirty = true;
    278 	}
    279 
    280 	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
    281 	{
    282 		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
    283 		{
    284 			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
    285 			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
    286 			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
    287 			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
    288 		}
    289 
    290 		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
    291 		pixelShaderDirty = true;   // Reload DEF constants
    292 	}
    293 
    294 	void Device::setScissorEnable(bool enable)
    295 	{
    296 		scissorEnable = enable;
    297 	}
    298 
    299 	void Device::setRenderTarget(int index, egl::Image *renderTarget, unsigned int layer)
    300 	{
    301 		if(renderTarget)
    302 		{
    303 			renderTarget->addRef();
    304 		}
    305 
    306 		if(this->renderTarget[index])
    307 		{
    308 			this->renderTarget[index]->release();
    309 		}
    310 
    311 		this->renderTarget[index] = renderTarget;
    312 
    313 		Renderer::setRenderTarget(index, renderTarget, layer);
    314 	}
    315 
    316 	void Device::setDepthBuffer(egl::Image *depthBuffer, unsigned int layer)
    317 	{
    318 		if(this->depthBuffer == depthBuffer)
    319 		{
    320 			return;
    321 		}
    322 
    323 		if(depthBuffer)
    324 		{
    325 			depthBuffer->addRef();
    326 		}
    327 
    328 		if(this->depthBuffer)
    329 		{
    330 			this->depthBuffer->release();
    331 		}
    332 
    333 		this->depthBuffer = depthBuffer;
    334 
    335 		Renderer::setDepthBuffer(depthBuffer, layer);
    336 	}
    337 
    338 	void Device::setStencilBuffer(egl::Image *stencilBuffer, unsigned int layer)
    339 	{
    340 		if(this->stencilBuffer == stencilBuffer)
    341 		{
    342 			return;
    343 		}
    344 
    345 		if(stencilBuffer)
    346 		{
    347 			stencilBuffer->addRef();
    348 		}
    349 
    350 		if(this->stencilBuffer)
    351 		{
    352 			this->stencilBuffer->release();
    353 		}
    354 
    355 		this->stencilBuffer = stencilBuffer;
    356 
    357 		Renderer::setStencilBuffer(stencilBuffer, layer);
    358 	}
    359 
    360 	void Device::setScissorRect(const sw::Rect &rect)
    361 	{
    362 		scissorRect = rect;
    363 	}
    364 
    365 	void Device::setVertexShader(const VertexShader *vertexShader)
    366 	{
    367 		this->vertexShader = vertexShader;
    368 		vertexShaderDirty = true;
    369 	}
    370 
    371 	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
    372 	{
    373 		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
    374 		{
    375 			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
    376 			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
    377 			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
    378 			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
    379 		}
    380 
    381 		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
    382 		vertexShaderDirty = true;   // Reload DEF constants
    383 	}
    384 
    385 	void Device::setViewport(const Viewport &viewport)
    386 	{
    387 		this->viewport = viewport;
    388 	}
    389 
    390 	void Device::copyBuffer(byte *sourceBuffer, byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY)
    391 	{
    392 		if(flipX)
    393 		{
    394 			if(flipY)
    395 			{
    396 				sourceBuffer += (height - 1) * sourcePitch;
    397 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
    398 				{
    399 					byte *srcX = sourceBuffer + (width - 1) * bytes;
    400 					byte *dstX = destBuffer;
    401 					for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
    402 					{
    403 						memcpy(dstX, srcX, bytes);
    404 					}
    405 				}
    406 			}
    407 			else
    408 			{
    409 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
    410 				{
    411 					byte *srcX = sourceBuffer + (width - 1) * bytes;
    412 					byte *dstX = destBuffer;
    413 					for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
    414 					{
    415 						memcpy(dstX, srcX, bytes);
    416 					}
    417 				}
    418 			}
    419 		}
    420 		else
    421 		{
    422 			unsigned int widthB = width * bytes;
    423 
    424 			if(flipY)
    425 			{
    426 				sourceBuffer += (height - 1) * sourcePitch;
    427 				for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
    428 				{
    429 					memcpy(destBuffer, sourceBuffer, widthB);
    430 				}
    431 			}
    432 			else
    433 			{
    434 				for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
    435 				{
    436 					memcpy(destBuffer, sourceBuffer, widthB);
    437 				}
    438 			}
    439 		}
    440 	}
    441 
    442 	bool Device::stretchRect(sw::Surface *source, const sw::SliceRectF *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, unsigned char flags)
    443 	{
    444 		if(!source || !dest)
    445 		{
    446 			ERR("Invalid parameters");
    447 			return false;
    448 		}
    449 
    450 		int sWidth = source->getWidth();
    451 		int sHeight = source->getHeight();
    452 		int dWidth = dest->getWidth();
    453 		int dHeight = dest->getHeight();
    454 
    455 		bool flipX = false;
    456 		bool flipY = false;
    457 		if(sourceRect && destRect)
    458 		{
    459 			flipX = (sourceRect->x0 < sourceRect->x1) ^ (destRect->x0 < destRect->x1);
    460 			flipY = (sourceRect->y0 < sourceRect->y1) ^ (destRect->y0 < destRect->y1);
    461 		}
    462 		else if(sourceRect)
    463 		{
    464 			flipX = (sourceRect->x0 > sourceRect->x1);
    465 			flipY = (sourceRect->y0 > sourceRect->y1);
    466 		}
    467 		else if(destRect)
    468 		{
    469 			flipX = (destRect->x0 > destRect->x1);
    470 			flipY = (destRect->y0 > destRect->y1);
    471 		}
    472 
    473 		SliceRectF sRect;
    474 		SliceRect dRect;
    475 
    476 		if(sourceRect)
    477 		{
    478 			sRect.x0 = sourceRect->x0;
    479 			sRect.x1 = sourceRect->x1;
    480 			sRect.y0 = sourceRect->y0;
    481 			sRect.y1 = sourceRect->y1;
    482 			sRect.slice = sourceRect->slice;
    483 
    484 			if(sRect.x0 > sRect.x1)
    485 			{
    486 				swap(sRect.x0, sRect.x1);
    487 			}
    488 
    489 			if(sRect.y0 > sRect.y1)
    490 			{
    491 				swap(sRect.y0, sRect.y1);
    492 			}
    493 		}
    494 		else
    495 		{
    496 			sRect.y0 = 0.0f;
    497 			sRect.x0 = 0.0f;
    498 			sRect.y1 = (float)sHeight;
    499 			sRect.x1 = (float)sWidth;
    500 		}
    501 
    502 		if(destRect)
    503 		{
    504 			dRect = *destRect;
    505 
    506 			if(dRect.x0 > dRect.x1)
    507 			{
    508 				swap(dRect.x0, dRect.x1);
    509 			}
    510 
    511 			if(dRect.y0 > dRect.y1)
    512 			{
    513 				swap(dRect.y0, dRect.y1);
    514 			}
    515 		}
    516 		else
    517 		{
    518 			dRect.y0 = 0;
    519 			dRect.x0 = 0;
    520 			dRect.y1 = dHeight;
    521 			dRect.x1 = dWidth;
    522 		}
    523 
    524 		sw::Rect srcClipRect(0, 0, sWidth, sHeight);
    525 		ClipSrcRect(sRect, dRect, srcClipRect, flipX, flipY);
    526 
    527 		sw::Rect dstClipRect(0, 0, dWidth, dHeight);
    528 		ClipDstRect(sRect, dRect, dstClipRect, flipX, flipY);
    529 
    530 		if((sRect.width() == 0) || (sRect.height() == 0) ||
    531 		   (dRect.width() == 0) || (dRect.height() == 0))
    532 		{
    533 			return true; // no work to do
    534 		}
    535 
    536 		if(!validRectangle(&sRect, source) || !validRectangle(&dRect, dest))
    537 		{
    538 			ERR("Invalid parameters");
    539 			return false;
    540 		}
    541 
    542 		bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat());
    543 		bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat());
    544 		bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
    545 
    546 		if(!isColor && !isDepth && !isStencil)
    547 		{
    548 			return true;
    549 		}
    550 
    551 		int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB();
    552 		int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB();
    553 		int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB();
    554 		int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB();
    555 
    556 		bool isOutOfBounds = (sRect.x0 < 0.0f) || (sRect.y0 < 0.0f) || (sRect.x1 > (float)sWidth) || (sRect.y1 > (float)sHeight);
    557 		bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height());
    558 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
    559 		bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
    560 		bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
    561 		                (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight);
    562 		bool alpha0xFF = false;
    563 		bool equalSlice = sourceSliceB == destSliceB;
    564 		bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16;
    565 
    566 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
    567 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
    568 		{
    569 			equalFormats = true;
    570 			alpha0xFF = true;
    571 		}
    572 
    573 		if(fullCopy && !scaling && !isOutOfBounds && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY)
    574 		{
    575 			byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
    576 			byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
    577 
    578 			memcpy(destBuffer, sourceBuffer, sourceSliceB);
    579 
    580 			isStencil ? source->unlockStencil() : source->unlockInternal();
    581 			isStencil ? dest->unlockStencil() : dest->unlockInternal();
    582 		}
    583 		else if(isDepth && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
    584 		{
    585 			byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
    586 			byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
    587 
    588 			copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
    589 
    590 			source->unlockInternal();
    591 			dest->unlockInternal();
    592 		}
    593 		else if((flags & Device::COLOR_BUFFER) && !scaling && !isOutOfBounds && equalFormats && !hasQuadLayout)
    594 		{
    595 			byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
    596 			byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
    597 
    598 			unsigned int width = dRect.x1 - dRect.x0;
    599 			unsigned int height = dRect.y1 - dRect.y0;
    600 
    601 			copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
    602 
    603 			if(alpha0xFF)
    604 			{
    605 				for(unsigned int y = 0; y < height; y++)
    606 				{
    607 					for(unsigned int x = 0; x < width; x++)
    608 					{
    609 						destBytes[4 * x + 3] = 0xFF;
    610 					}
    611 
    612 					destBytes += destPitchB;
    613 				}
    614 			}
    615 
    616 			source->unlockInternal();
    617 			dest->unlockInternal();
    618 		}
    619 		else if(isColor || isDepth || isStencil)
    620 		{
    621 			if(flipX)
    622 			{
    623 				swap(dRect.x0, dRect.x1);
    624 			}
    625 			if(flipY)
    626 			{
    627 				swap(dRect.y0, dRect.y1);
    628 			}
    629 
    630 			blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
    631 		}
    632 		else UNREACHABLE(false);
    633 
    634 		return true;
    635 	}
    636 
    637 	bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
    638 	{
    639 		if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat()))
    640 		{
    641 			ERR("Invalid parameters");
    642 			return false;
    643 		}
    644 
    645 		int sWidth  = source->getWidth();
    646 		int sHeight = source->getHeight();
    647 		int sDepth  = source->getDepth();
    648 		int dWidth  = dest->getWidth();
    649 		int dHeight = dest->getHeight();
    650 		int dDepth  = dest->getDepth();
    651 
    652 		if((sWidth == 0) || (sHeight == 0) || (sDepth == 0) ||
    653 		   (dWidth == 0) || (dHeight == 0) || (dDepth == 0))
    654 		{
    655 			return true; // no work to do
    656 		}
    657 
    658 		bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);
    659 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
    660 		bool alpha0xFF = false;
    661 
    662 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
    663 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
    664 		{
    665 			equalFormats = true;
    666 			alpha0xFF = true;
    667 		}
    668 
    669 		if(!scaling && equalFormats)
    670 		{
    671 			unsigned int sourcePitch = source->getInternalPitchB();
    672 			unsigned int destPitch = dest->getInternalPitchB();
    673 			unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat());
    674 
    675 			for(int z = 0; z < dDepth; z++)
    676 			{
    677 				unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);
    678 				unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);
    679 
    680 				for(int y = 0; y < dHeight; y++)
    681 				{
    682 					memcpy(destBytes, sourceBytes, bytes);
    683 
    684 					if(alpha0xFF)
    685 					{
    686 						for(int x = 0; x < dWidth; x++)
    687 						{
    688 							destBytes[4 * x + 3] = 0xFF;
    689 						}
    690 					}
    691 
    692 					sourceBytes += sourcePitch;
    693 					destBytes += destPitch;
    694 				}
    695 
    696 				source->unlockInternal();
    697 				dest->unlockInternal();
    698 			}
    699 		}
    700 		else
    701 		{
    702 			blit3D(source, dest);
    703 		}
    704 
    705 		return true;
    706 	}
    707 
    708 	bool Device::bindResources()
    709 	{
    710 		if(!bindViewport())
    711 		{
    712 			return false;   // Zero-area target region
    713 		}
    714 
    715 		bindShaderConstants();
    716 
    717 		return true;
    718 	}
    719 
    720 	void Device::bindShaderConstants()
    721 	{
    722 		if(pixelShaderDirty)
    723 		{
    724 			if(pixelShader)
    725 			{
    726 				if(pixelShaderConstantsFDirty)
    727 				{
    728 					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
    729 				}
    730 
    731 				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
    732 				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
    733 			}
    734 			else
    735 			{
    736 				setPixelShader(0);
    737 			}
    738 
    739 			pixelShaderDirty = false;
    740 		}
    741 
    742 		if(vertexShaderDirty)
    743 		{
    744 			if(vertexShader)
    745 			{
    746 				if(vertexShaderConstantsFDirty)
    747 				{
    748 					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
    749 				}
    750 
    751 				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
    752 				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
    753 			}
    754 			else
    755 			{
    756 				setVertexShader(0);
    757 			}
    758 
    759 			vertexShaderDirty = false;
    760 		}
    761 	}
    762 
    763 	bool Device::bindViewport()
    764 	{
    765 		if(viewport.width <= 0 || viewport.height <= 0)
    766 		{
    767 			return false;
    768 		}
    769 
    770 		if(scissorEnable)
    771 		{
    772 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
    773 			{
    774 				return false;
    775 			}
    776 
    777 			sw::Rect scissor;
    778 			scissor.x0 = scissorRect.x0;
    779 			scissor.x1 = scissorRect.x1;
    780 			scissor.y0 = scissorRect.y0;
    781 			scissor.y1 = scissorRect.y1;
    782 
    783 			setScissor(scissor);
    784 		}
    785 		else
    786 		{
    787 			sw::Rect scissor;
    788 			scissor.x0 = viewport.x0;
    789 			scissor.x1 = viewport.x0 + viewport.width;
    790 			scissor.y0 = viewport.y0;
    791 			scissor.y1 = viewport.y0 + viewport.height;
    792 
    793 			for(int i = 0; i < RENDERTARGETS; ++i)
    794 			{
    795 				if(renderTarget[i])
    796 				{
    797 					scissor.x0 = max(scissor.x0, 0);
    798 					scissor.x1 = min(scissor.x1, renderTarget[i]->getWidth());
    799 					scissor.y0 = max(scissor.y0, 0);
    800 					scissor.y1 = min(scissor.y1, renderTarget[i]->getHeight());
    801 				}
    802 			}
    803 
    804 			if(depthBuffer)
    805 			{
    806 				scissor.x0 = max(scissor.x0, 0);
    807 				scissor.x1 = min(scissor.x1, depthBuffer->getWidth());
    808 				scissor.y0 = max(scissor.y0, 0);
    809 				scissor.y1 = min(scissor.y1, depthBuffer->getHeight());
    810 			}
    811 
    812 			if(stencilBuffer)
    813 			{
    814 				scissor.x0 = max(scissor.x0, 0);
    815 				scissor.x1 = min(scissor.x1, stencilBuffer->getWidth());
    816 				scissor.y0 = max(scissor.y0, 0);
    817 				scissor.y1 = min(scissor.y1, stencilBuffer->getHeight());
    818 			}
    819 
    820 			setScissor(scissor);
    821 		}
    822 
    823 		sw::Viewport view;
    824 		view.x0 = (float)viewport.x0;
    825 		view.y0 = (float)viewport.y0;
    826 		view.width = (float)viewport.width;
    827 		view.height = (float)viewport.height;
    828 		view.minZ = viewport.minZ;
    829 		view.maxZ = viewport.maxZ;
    830 
    831 		Renderer::setViewport(view);
    832 
    833 		return true;
    834 	}
    835 
    836 	bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface)
    837 	{
    838 		if(!rect)
    839 		{
    840 			return true;
    841 		}
    842 
    843 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
    844 		{
    845 			return false;
    846 		}
    847 
    848 		if(rect->x0 < 0 || rect->y0 < 0)
    849 		{
    850 			return false;
    851 		}
    852 
    853 		if(rect->x1 >(int)surface->getWidth() || rect->y1 >(int)surface->getHeight())
    854 		{
    855 			return false;
    856 		}
    857 
    858 		return true;
    859 	}
    860 
    861 	bool Device::validRectangle(const sw::RectF *rect, sw::Surface *surface)
    862 	{
    863 		if(!rect)
    864 		{
    865 			return true;
    866 		}
    867 
    868 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
    869 		{
    870 			return false;
    871 		}
    872 
    873 		return true;
    874 	}
    875 
    876 	void Device::ClipDstRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
    877 	{
    878 		if(dstRect.x0 < clipRect.x0)
    879 		{
    880 			float offset = (static_cast<float>(clipRect.x0 - dstRect.x0) / static_cast<float>(dstRect.width())) * srcRect.width();
    881 			if(flipX)
    882 			{
    883 				srcRect.x1 -= offset;
    884 			}
    885 			else
    886 			{
    887 				srcRect.x0 += offset;
    888 			}
    889 			dstRect.x0 = clipRect.x0;
    890 		}
    891 		if(dstRect.x1 > clipRect.x1)
    892 		{
    893 			float offset = (static_cast<float>(dstRect.x1 - clipRect.x1) / static_cast<float>(dstRect.width())) * srcRect.width();
    894 			if(flipX)
    895 			{
    896 				srcRect.x0 += offset;
    897 			}
    898 			else
    899 			{
    900 				srcRect.x1 -= offset;
    901 			}
    902 			dstRect.x1 = clipRect.x1;
    903 		}
    904 		if(dstRect.y0 < clipRect.y0)
    905 		{
    906 			float offset = (static_cast<float>(clipRect.y0 - dstRect.y0) / static_cast<float>(dstRect.height())) * srcRect.height();
    907 			if(flipY)
    908 			{
    909 				srcRect.y1 -= offset;
    910 			}
    911 			else
    912 			{
    913 				srcRect.y0 += offset;
    914 			}
    915 			dstRect.y0 = clipRect.y0;
    916 		}
    917 		if(dstRect.y1 > clipRect.y1)
    918 		{
    919 			float offset = (static_cast<float>(dstRect.y1 - clipRect.y1) / static_cast<float>(dstRect.height())) * srcRect.height();
    920 			if(flipY)
    921 			{
    922 				srcRect.y0 += offset;
    923 			}
    924 			else
    925 			{
    926 				srcRect.y1 -= offset;
    927 			}
    928 			dstRect.y1 = clipRect.y1;
    929 		}
    930 	}
    931 
    932 	void Device::ClipSrcRect(sw::RectF &srcRect, sw::Rect &dstRect, sw::Rect &clipRect, bool flipX, bool flipY)
    933 	{
    934 		if(srcRect.x0 < static_cast<float>(clipRect.x0))
    935 		{
    936 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
    937 			float offsetf = roundf((static_cast<float>(clipRect.x0) - srcRect.x0) * ratio);
    938 			int offset = static_cast<int>(offsetf);
    939 			if(flipX)
    940 			{
    941 				dstRect.x1 -= offset;
    942 			}
    943 			else
    944 			{
    945 				dstRect.x0 += offset;
    946 			}
    947 			srcRect.x0 += offsetf / ratio;
    948 		}
    949 		if(srcRect.x1 > static_cast<float>(clipRect.x1))
    950 		{
    951 			float ratio = static_cast<float>(dstRect.width()) / srcRect.width();
    952 			float offsetf = roundf((srcRect.x1 - static_cast<float>(clipRect.x1)) * ratio);
    953 			int offset = static_cast<int>(offsetf);
    954 			if(flipX)
    955 			{
    956 				dstRect.x0 += offset;
    957 			}
    958 			else
    959 			{
    960 				dstRect.x1 -= offset;
    961 			}
    962 			srcRect.x1 -= offsetf / ratio;
    963 		}
    964 		if(srcRect.y0 < static_cast<float>(clipRect.y0))
    965 		{
    966 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
    967 			float offsetf = roundf((static_cast<float>(clipRect.y0) - srcRect.y0) * ratio);
    968 			int offset = static_cast<int>(offsetf);
    969 			if(flipY)
    970 			{
    971 				dstRect.y1 -= offset;
    972 			}
    973 			else
    974 			{
    975 				dstRect.y0 += offset;
    976 			}
    977 			srcRect.y0 += offsetf / ratio;
    978 		}
    979 		if(srcRect.y1 > static_cast<float>(clipRect.y1))
    980 		{
    981 			float ratio = static_cast<float>(dstRect.height()) / srcRect.height();
    982 			float offsetf = roundf((srcRect.y1 - static_cast<float>(clipRect.y1)) * ratio);
    983 			int offset = static_cast<int>(offsetf);
    984 			if(flipY)
    985 			{
    986 				dstRect.y0 += offset;
    987 			}
    988 			else
    989 			{
    990 				dstRect.y1 -= offset;
    991 			}
    992 			srcRect.y1 -= offsetf / ratio;
    993 		}
    994 	}
    995 
    996 	void Device::finish()
    997 	{
    998 		synchronize();
    999 	}
   1000 }
   1001