Home | History | Annotate | Download | only in libGL
      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 "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 gl
     33 {
     34 	using namespace sw;
     35 
     36 	Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context)
     37 	{
     38 		depthStencil = 0;
     39 		renderTarget = 0;
     40 
     41 		setDepthBufferEnable(true);
     42 		setFillMode(FILL_SOLID);
     43 		setShadingMode(SHADING_GOURAUD);
     44 		setDepthWriteEnable(true);
     45 		setAlphaTestEnable(false);
     46 		setSourceBlendFactor(BLEND_ONE);
     47 		setDestBlendFactor(BLEND_ZERO);
     48 		setCullMode(CULL_COUNTERCLOCKWISE);
     49 		setDepthCompare(DEPTH_LESSEQUAL);
     50 		setAlphaReference(0.0f);
     51 		setAlphaCompare(ALPHA_ALWAYS);
     52 		setAlphaBlendEnable(false);
     53 		setFogEnable(false);
     54 		setSpecularEnable(false);
     55 		setFogColor(0);
     56 		setPixelFogMode(FOG_NONE);
     57 		setFogStart(0.0f);
     58 		setFogEnd(1.0f);
     59 		setFogDensity(1.0f);
     60 		setRangeFogEnable(false);
     61 		setStencilEnable(false);
     62 		setStencilFailOperation(OPERATION_KEEP);
     63 		setStencilZFailOperation(OPERATION_KEEP);
     64 		setStencilPassOperation(OPERATION_KEEP);
     65 		setStencilCompare(STENCIL_ALWAYS);
     66 		setStencilReference(0);
     67 		setStencilMask(0xFFFFFFFF);
     68 		setStencilWriteMask(0xFFFFFFFF);
     69 		setVertexFogMode(FOG_NONE);
     70 		setClipFlags(0);
     71 		setPointSize(1.0f);
     72 		setPointSizeMin(0.125f);
     73 		setPointSizeMax(8192.0f);
     74 		setColorWriteMask(0, 0x0000000F);
     75 		setBlendOperation(BLENDOP_ADD);
     76 		scissorEnable = false;
     77 		setSlopeDepthBias(0.0f);
     78 		setTwoSidedStencil(false);
     79 		setStencilFailOperationCCW(OPERATION_KEEP);
     80 		setStencilZFailOperationCCW(OPERATION_KEEP);
     81 		setStencilPassOperationCCW(OPERATION_KEEP);
     82 		setStencilCompareCCW(STENCIL_ALWAYS);
     83 		setColorWriteMask(1, 0x0000000F);
     84 		setColorWriteMask(2, 0x0000000F);
     85 		setColorWriteMask(3, 0x0000000F);
     86 		setBlendConstant(0xFFFFFFFF);
     87 		setWriteSRGB(false);
     88 		setDepthBias(0.0f);
     89 		setSeparateAlphaBlendEnable(false);
     90 		setSourceBlendFactorAlpha(BLEND_ONE);
     91 		setDestBlendFactorAlpha(BLEND_ZERO);
     92 		setBlendOperationAlpha(BLENDOP_ADD);
     93 		setPointSpriteEnable(true);
     94 		setColorLogicOpEnabled(false);
     95 		setLogicalOperation(LOGICALOP_COPY);
     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 		pixelShader = 0;
    127 		vertexShader = 0;
    128 
    129 		pixelShaderDirty = true;
    130 		pixelShaderConstantsFDirty = 0;
    131 		vertexShaderDirty = true;
    132 		vertexShaderConstantsFDirty = 0;
    133 
    134 		for(int i = 0; i < FRAGMENT_UNIFORM_VECTORS; i++)
    135 		{
    136 			float zero[4] = {0, 0, 0, 0};
    137 
    138 			setPixelShaderConstantF(i, zero, 1);
    139 		}
    140 
    141 		for(int i = 0; i < VERTEX_UNIFORM_VECTORS; i++)
    142 		{
    143 			float zero[4] = {0, 0, 0, 0};
    144 
    145 			setVertexShaderConstantF(i, zero, 1);
    146 		}
    147 
    148 		setLightingEnable(false);
    149 
    150 		setGlobalAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
    151 		setMaterialAmbient(sw::Color<float>(0.2f, 0.2f, 0.2f, 1.0f));
    152 		setMaterialDiffuse(sw::Color<float>(0.8f, 0.8f, 0.8f, 1.0f));
    153 		setMaterialSpecular(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
    154 		setMaterialEmission(sw::Color<float>(0.0f, 0.0f, 0.0f, 1.0f));
    155 
    156 		for(int i = 0; i < 8; i++)
    157 		{
    158 			setLightEnable(i, false);
    159 			setLightAttenuation(i, 1.0f, 0.0f, 0.0f);
    160 		}
    161 
    162 		setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
    163 		setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
    164 		setAmbientMaterialSource(sw::MATERIAL_COLOR1);
    165 		setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
    166 	}
    167 
    168 	Device::~Device()
    169 	{
    170 		if(depthStencil)
    171 		{
    172 			depthStencil->release();
    173 			depthStencil = 0;
    174 		}
    175 
    176 		if(renderTarget)
    177 		{
    178 			renderTarget->release();
    179 			renderTarget = 0;
    180 		}
    181 
    182 		delete context;
    183 	}
    184 
    185 	// This object has to be mem aligned
    186 	void* Device::operator new(size_t size)
    187 	{
    188 		ASSERT(size == sizeof(Device)); // This operator can't be called from a derived class
    189 		return sw::allocate(sizeof(gl::Device), 16);
    190 	}
    191 
    192 	void Device::operator delete(void * mem)
    193 	{
    194 		sw::deallocate(mem);
    195 	}
    196 
    197 	void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask)
    198 	{
    199 		if(!renderTarget || !rgbaMask)
    200 		{
    201 			return;
    202 		}
    203 
    204 		sw::Rect clearRect = renderTarget->getRect();
    205 
    206 		if(scissorEnable)
    207 		{
    208 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    209 		}
    210 
    211 		float rgba[4];
    212 		rgba[0] = red;
    213 		rgba[1] = green;
    214 		rgba[2] = blue;
    215 		rgba[3] = alpha;
    216 
    217 		clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask);
    218 	}
    219 
    220 	void Device::clearDepth(float z)
    221 	{
    222 		if(!depthStencil)
    223 		{
    224 			return;
    225 		}
    226 
    227 		z = clamp01(z);
    228 		sw::Rect clearRect = depthStencil->getRect();
    229 
    230 		if(scissorEnable)
    231 		{
    232 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    233 		}
    234 
    235 		depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    236 	}
    237 
    238 	void Device::clearStencil(unsigned int stencil, unsigned int mask)
    239 	{
    240 		if(!depthStencil)
    241 		{
    242 			return;
    243 		}
    244 
    245 		sw::Rect clearRect = depthStencil->getRect();
    246 
    247 		if(scissorEnable)
    248 		{
    249 			clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1);
    250 		}
    251 
    252 		depthStencil->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    253 	}
    254 
    255 	Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
    256 	{
    257 		if(height > OUTLINE_RESOLUTION)
    258 		{
    259 			ERR("Invalid parameters: %dx%d", width, height);
    260 			return 0;
    261 		}
    262 
    263 		bool lockable = true;
    264 
    265 		switch(format)
    266 		{
    267 	//	case FORMAT_D15S1:
    268 		case FORMAT_D24S8:
    269 		case FORMAT_D24X8:
    270 	//	case FORMAT_D24X4S4:
    271 		case FORMAT_D24FS8:
    272 		case FORMAT_D32:
    273 		case FORMAT_D16:
    274 			lockable = false;
    275 			break;
    276 	//	case FORMAT_S8_LOCKABLE:
    277 	//	case FORMAT_D16_LOCKABLE:
    278 		case FORMAT_D32F_LOCKABLE:
    279 	//	case FORMAT_D32_LOCKABLE:
    280 		case FORMAT_DF24S8:
    281 		case FORMAT_DF16S8:
    282 			lockable = true;
    283 			break;
    284 		default:
    285 			UNREACHABLE(format);
    286 		}
    287 
    288 		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
    289 
    290 		if(!surface)
    291 		{
    292 			ERR("Out of memory");
    293 			return 0;
    294 		}
    295 
    296 		return surface;
    297 	}
    298 
    299 	Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
    300 	{
    301 		if(height > OUTLINE_RESOLUTION)
    302 		{
    303 			ERR("Invalid parameters: %dx%d", width, height);
    304 			return 0;
    305 		}
    306 
    307 		Image *surface = new Image(0, width, height, format, multiSampleDepth, lockable, true);
    308 
    309 		if(!surface)
    310 		{
    311 			ERR("Out of memory");
    312 			return 0;
    313 		}
    314 
    315 		return surface;
    316 	}
    317 
    318 	void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
    319 	{
    320 		if(!bindResources() || !primitiveCount)
    321 		{
    322 			return;
    323 		}
    324 
    325 		DrawType drawType;
    326 
    327 		if(indexSize == 4)
    328 		{
    329 			switch(type)
    330 			{
    331 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
    332 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
    333 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
    334 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP32;      break;
    335 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
    336 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
    337 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;	  break;
    338 			default: UNREACHABLE(type);
    339 			}
    340 		}
    341 		else if(indexSize == 2)
    342 		{
    343 			switch(type)
    344 			{
    345 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
    346 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
    347 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
    348 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP16;      break;
    349 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
    350 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
    351 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
    352 			default: UNREACHABLE(type);
    353 			}
    354 		}
    355 		else if(indexSize == 1)
    356 		{
    357 			switch(type)
    358 			{
    359 			case DRAW_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST8;     break;
    360 			case DRAW_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST8;      break;
    361 			case DRAW_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP8;     break;
    362 			case DRAW_LINELOOP:      drawType = sw::DRAW_INDEXEDLINELOOP8;      break;
    363 			case DRAW_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST8;  break;
    364 			case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP8; break;
    365 			case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN8;   break;
    366 			default: UNREACHABLE(type);
    367 			}
    368 		}
    369 		else UNREACHABLE(indexSize);
    370 
    371 		draw(drawType, indexOffset, primitiveCount);
    372 	}
    373 
    374 	void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
    375 	{
    376 		if(!bindResources() || !primitiveCount)
    377 		{
    378 			return;
    379 		}
    380 
    381 		setIndexBuffer(0);
    382 
    383 		DrawType drawType;
    384 
    385 		switch(primitiveType)
    386 		{
    387 		case DRAW_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
    388 		case DRAW_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
    389 		case DRAW_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
    390 		case DRAW_LINELOOP:      drawType = sw::DRAW_LINELOOP;      break;
    391 		case DRAW_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
    392 		case DRAW_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
    393 		case DRAW_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
    394 		case DRAW_QUADLIST:      drawType = sw::DRAW_QUADLIST;      break;
    395 		default: UNREACHABLE(primitiveType);
    396 		}
    397 
    398 		draw(drawType, 0, primitiveCount);
    399 	}
    400 
    401 	void Device::setDepthStencilSurface(Image *depthStencil)
    402 	{
    403 		if(this->depthStencil == depthStencil)
    404 		{
    405 			return;
    406 		}
    407 
    408 		if(depthStencil)
    409 		{
    410 			depthStencil->addRef();
    411 		}
    412 
    413 		if(this->depthStencil)
    414 		{
    415 			this->depthStencil->release();
    416 		}
    417 
    418 		this->depthStencil = depthStencil;
    419 
    420 		setDepthBuffer(depthStencil);
    421 		setStencilBuffer(depthStencil);
    422 	}
    423 
    424 	void Device::setPixelShader(PixelShader *pixelShader)
    425 	{
    426 		this->pixelShader = pixelShader;
    427 		pixelShaderDirty = true;
    428 	}
    429 
    430 	void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
    431 	{
    432 		for(unsigned int i = 0; i < count && startRegister + i < FRAGMENT_UNIFORM_VECTORS; i++)
    433 		{
    434 			pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
    435 			pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
    436 			pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
    437 			pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
    438 		}
    439 
    440 		pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
    441 		pixelShaderDirty = true;   // Reload DEF constants
    442 	}
    443 
    444 	void Device::setScissorEnable(bool enable)
    445 	{
    446 		scissorEnable = enable;
    447 	}
    448 
    449 	void Device::setRenderTarget(int index, Image *renderTarget)
    450 	{
    451 		if(renderTarget)
    452 		{
    453 			renderTarget->addRef();
    454 		}
    455 
    456 		if(this->renderTarget)
    457 		{
    458 			this->renderTarget->release();
    459 		}
    460 
    461 		this->renderTarget = renderTarget;
    462 
    463 		Renderer::setRenderTarget(index, renderTarget);
    464 	}
    465 
    466 	void Device::setScissorRect(const sw::Rect &rect)
    467 	{
    468 		scissorRect = rect;
    469 	}
    470 
    471 	void Device::setVertexShader(VertexShader *vertexShader)
    472 	{
    473 		this->vertexShader = vertexShader;
    474 		vertexShaderDirty = true;
    475 	}
    476 
    477 	void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
    478 	{
    479 		for(unsigned int i = 0; i < count && startRegister + i < VERTEX_UNIFORM_VECTORS; i++)
    480 		{
    481 			vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
    482 			vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
    483 			vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
    484 			vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
    485 		}
    486 
    487 		vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
    488 		vertexShaderDirty = true;   // Reload DEF constants
    489 	}
    490 
    491 	void Device::setViewport(const Viewport &viewport)
    492 	{
    493 		this->viewport = viewport;
    494 	}
    495 
    496 	bool Device::stretchRect(Image *source, const sw::SliceRect *sourceRect, Image *dest, const sw::SliceRect *destRect, bool filter)
    497 	{
    498 		if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
    499 		{
    500 			ERR("Invalid parameters");
    501 			return false;
    502 		}
    503 
    504 		int sWidth = source->getWidth();
    505 		int sHeight = source->getHeight();
    506 		int dWidth = dest->getWidth();
    507 		int dHeight = dest->getHeight();
    508 
    509 		SliceRect sRect;
    510 		SliceRect dRect;
    511 
    512 		if(sourceRect)
    513 		{
    514 			sRect = *sourceRect;
    515 		}
    516 		else
    517 		{
    518 			sRect.y0 = 0;
    519 			sRect.x0 = 0;
    520 			sRect.y1 = sHeight;
    521 			sRect.x1 = sWidth;
    522 		}
    523 
    524 		if(destRect)
    525 		{
    526 			dRect = *destRect;
    527 		}
    528 		else
    529 		{
    530 			dRect.y0 = 0;
    531 			dRect.x0 = 0;
    532 			dRect.y1 = dHeight;
    533 			dRect.x1 = dWidth;
    534 		}
    535 
    536 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
    537 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
    538 		bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
    539 		bool alpha0xFF = false;
    540 
    541 		if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
    542 		   (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
    543 		{
    544 			equalFormats = true;
    545 			alpha0xFF = true;
    546 		}
    547 
    548 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
    549 		{
    550 			if(source->hasDepth())
    551 			{
    552 				sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC);
    553 				sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC);
    554 
    555 				unsigned int width = source->getWidth();
    556 				unsigned int height = source->getHeight();
    557 				unsigned int pitch = source->getInternalPitchB();
    558 
    559 				for(unsigned int y = 0; y < height; y++)
    560 				{
    561 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
    562 
    563 					sourceBuffer += pitch;
    564 					destBuffer += pitch;
    565 				}
    566 
    567 				source->unlockInternal();
    568 				dest->unlockInternal();
    569 			}
    570 
    571 			if(source->hasStencil())
    572 			{
    573 				sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
    574 				sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
    575 
    576 				unsigned int width = source->getWidth();
    577 				unsigned int height = source->getHeight();
    578 				unsigned int pitch = source->getStencilPitchB();
    579 
    580 				for(unsigned int y = 0; y < height; y++)
    581 				{
    582 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
    583 
    584 					sourceBuffer += pitch;
    585 					destBuffer += pitch;
    586 				}
    587 
    588 				source->unlockStencil();
    589 				dest->unlockStencil();
    590 			}
    591 		}
    592 		else if(!scaling && equalFormats)
    593 		{
    594 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC);
    595 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC);
    596 			unsigned int sourcePitch = source->getInternalPitchB();
    597 			unsigned int destPitch = dest->getInternalPitchB();
    598 
    599 			unsigned int width = dRect.x1 - dRect.x0;
    600 			unsigned int height = dRect.y1 - dRect.y0;
    601 			unsigned int bytes = width * Image::bytes(source->getInternalFormat());
    602 
    603 			for(unsigned int y = 0; y < height; y++)
    604 			{
    605 				memcpy(destBytes, sourceBytes, bytes);
    606 
    607 				if(alpha0xFF)
    608 				{
    609 					for(unsigned int x = 0; x < width; x++)
    610 					{
    611 						destBytes[4 * x + 3] = 0xFF;
    612 					}
    613 				}
    614 
    615 				sourceBytes += sourcePitch;
    616 				destBytes += destPitch;
    617 			}
    618 
    619 			source->unlockInternal();
    620 			dest->unlockInternal();
    621 		}
    622 		else
    623 		{
    624 			blit(source, sRect, dest, dRect, scaling && filter);
    625 		}
    626 
    627 		return true;
    628 	}
    629 
    630 	bool Device::bindResources()
    631 	{
    632 		if(!bindViewport())
    633 		{
    634 			return false;   // Zero-area target region
    635 		}
    636 
    637 		bindShaderConstants();
    638 
    639 		return true;
    640 	}
    641 
    642 	void Device::bindShaderConstants()
    643 	{
    644 		if(pixelShaderDirty)
    645 		{
    646 			if(pixelShader)
    647 			{
    648 				if(pixelShaderConstantsFDirty)
    649 				{
    650 					Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
    651 				}
    652 
    653 				Renderer::setPixelShader(pixelShader);   // Loads shader constants set with DEF
    654 				pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
    655 			}
    656 			else
    657 			{
    658 				setPixelShader(0);
    659 			}
    660 
    661 			pixelShaderDirty = false;
    662 		}
    663 
    664 		if(vertexShaderDirty)
    665 		{
    666 			if(vertexShader)
    667 			{
    668 				if(vertexShaderConstantsFDirty)
    669 				{
    670 					Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
    671 				}
    672 
    673 				Renderer::setVertexShader(vertexShader);   // Loads shader constants set with DEF
    674 				vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF;   // Shader DEF'ed constants are dirty
    675 			}
    676 			else
    677 			{
    678 				setVertexShader(0);
    679 			}
    680 
    681 			vertexShaderDirty = false;
    682 		}
    683 	}
    684 
    685 	bool Device::bindViewport()
    686 	{
    687 		if(viewport.width <= 0 || viewport.height <= 0)
    688 		{
    689 			return false;
    690 		}
    691 
    692 		if(scissorEnable)
    693 		{
    694 			if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
    695 			{
    696 				return false;
    697 			}
    698 
    699 			sw::Rect scissor;
    700 			scissor.x0 = scissorRect.x0;
    701 			scissor.x1 = scissorRect.x1;
    702 			scissor.y0 = scissorRect.y0;
    703 			scissor.y1 = scissorRect.y1;
    704 
    705 			setScissor(scissor);
    706 		}
    707 		else
    708 		{
    709 			sw::Rect scissor;
    710 			scissor.x0 = viewport.x0;
    711 			scissor.x1 = viewport.x0 + viewport.width;
    712 			scissor.y0 = viewport.y0;
    713 			scissor.y1 = viewport.y0 + viewport.height;
    714 
    715 			if(renderTarget)
    716 			{
    717 				scissor.x0 = max(scissor.x0, 0);
    718 				scissor.x1 = min(scissor.x1, renderTarget->getWidth());
    719 				scissor.y0 = max(scissor.y0, 0);
    720 				scissor.y1 = min(scissor.y1, renderTarget->getHeight());
    721 			}
    722 
    723 			if(depthStencil)
    724 			{
    725 				scissor.x0 = max(scissor.x0, 0);
    726 				scissor.x1 = min(scissor.x1, depthStencil->getWidth());
    727 				scissor.y0 = max(scissor.y0, 0);
    728 				scissor.y1 = min(scissor.y1, depthStencil->getHeight());
    729 			}
    730 
    731 			setScissor(scissor);
    732 		}
    733 
    734 		sw::Viewport view;
    735 		view.x0 = (float)viewport.x0;
    736 		view.y0 = (float)viewport.y0;
    737 		view.width = (float)viewport.width;
    738 		view.height = (float)viewport.height;
    739 		view.minZ = viewport.minZ;
    740 		view.maxZ = viewport.maxZ;
    741 
    742 		Renderer::setViewport(view);
    743 
    744 		return true;
    745 	}
    746 
    747 	bool Device::validRectangle(const sw::Rect *rect, Image *surface)
    748 	{
    749 		if(!rect)
    750 		{
    751 			return true;
    752 		}
    753 
    754 		if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
    755 		{
    756 			return false;
    757 		}
    758 
    759 		if(rect->x0 < 0 || rect->y0 < 0)
    760 		{
    761 			return false;
    762 		}
    763 
    764 		if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
    765 		{
    766 			return false;
    767 		}
    768 
    769 		return true;
    770 	}
    771 
    772 	void Device::finish()
    773 	{
    774 		synchronize();
    775 	}
    776 }
    777