Add SwiftShader dump from Feb 6 2013
diff --git a/src/GLES2/libGLESv2/Device.cpp b/src/GLES2/libGLESv2/Device.cpp
new file mode 100644
index 0000000..64b888d
--- /dev/null
+++ b/src/GLES2/libGLESv2/Device.cpp
@@ -0,0 +1,805 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2013 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "Device.hpp"
+
+#include "Image.hpp"
+#include "Texture.h"
+
+#include "Renderer/Renderer.hpp"
+#include "Renderer/Clipper.hpp"
+#include "Shader/PixelShader.hpp"
+#include "Shader/VertexShader.hpp"
+#include "Main/Config.hpp"
+#include "Main/FrameBuffer.hpp"
+#include "Common/Math.hpp"
+#include "Common/Configurator.hpp"
+#include "Common/Timer.hpp"
+#include "../common/debug.h"
+
+bool localShaderConstants = false;
+
+namespace gl
+{
+ using namespace sw;
+
+ Device::Device(Context *context) : Renderer(context, true, true, true, true, true), context(context)
+ {
+ depthStencil = 0;
+ renderTarget = 0;
+
+ setDepthBufferEnable(true);
+ setFillMode(Context::FILL_SOLID);
+ setShadingMode(Context::SHADING_GOURAUD);
+ setDepthWriteEnable(true);
+ setAlphaTestEnable(false);
+ setSourceBlendFactor(Context::BLEND_ONE);
+ setDestBlendFactor(Context::BLEND_ZERO);
+ setCullMode(Context::CULL_COUNTERCLOCKWISE);
+ setDepthCompare(Context::DEPTH_LESSEQUAL);
+ setAlphaReference(0);
+ setAlphaCompare(Context::ALPHA_ALWAYS);
+ setAlphaBlendEnable(false);
+ setFogEnable(false);
+ setSpecularEnable(false);
+ setFogColor(0);
+ setPixelFogMode(Context::FOG_NONE);
+ setFogStart(0.0f);
+ setFogEnd(1.0f);
+ setFogDensity(1.0f);
+ setRangeFogEnable(false);
+ setStencilEnable(false);
+ setStencilFailOperation(Context::OPERATION_KEEP);
+ setStencilZFailOperation(Context::OPERATION_KEEP);
+ setStencilPassOperation(Context::OPERATION_KEEP);
+ setStencilCompare(Context::STENCIL_ALWAYS);
+ setStencilReference(0);
+ setStencilMask(0xFFFFFFFF);
+ setStencilWriteMask(0xFFFFFFFF);
+ setVertexFogMode(Context::FOG_NONE);
+ setClipFlags(0);
+ setPointSize(1.0f);
+ setPointSizeMin(0.125f);
+ setPointSpriteEnable(false);
+ setPointSizeMax(8192.0f);
+ setColorWriteMask(0, 0x0000000F);
+ setBlendOperation(Context::BLENDOP_ADD);
+ scissorEnable = false;
+ setSlopeDepthBias(0.0f);
+ setTwoSidedStencil(false);
+ setStencilFailOperationCCW(Context::OPERATION_KEEP);
+ setStencilZFailOperationCCW(Context::OPERATION_KEEP);
+ setStencilPassOperationCCW(Context::OPERATION_KEEP);
+ setStencilCompareCCW(Context::STENCIL_ALWAYS);
+ setColorWriteMask(1, 0x0000000F);
+ setColorWriteMask(2, 0x0000000F);
+ setColorWriteMask(3, 0x0000000F);
+ setBlendConstant(0xFFFFFFFF);
+ setWriteSRGB(false);
+ setDepthBias(0.0f);
+ setSeparateAlphaBlendEnable(false);
+ setSourceBlendFactorAlpha(Context::BLEND_ONE);
+ setDestBlendFactorAlpha(Context::BLEND_ZERO);
+ setBlendOperationAlpha(Context::BLENDOP_ADD);
+
+ for(int i = 0; i < 16; i++)
+ {
+ setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
+ setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
+ setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP);
+ setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000);
+ setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT);
+ setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE);
+ setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f);
+ }
+
+ for(int i = 0; i < 4; i++)
+ {
+ setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
+ setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
+ setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP);
+ setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000);
+ setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT);
+ setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE);
+ setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f);
+ }
+
+ for(int i = 0; i < 6; i++)
+ {
+ float plane[4] = {0, 0, 0, 0};
+
+ setClipPlane(i, plane);
+ }
+
+ pixelShader = 0;
+ vertexShader = 0;
+
+ pixelShaderDirty = true;
+ pixelShaderConstantsFDirty = 0;
+ vertexShaderDirty = true;
+ vertexShaderConstantsFDirty = 0;
+
+ for(int i = 0; i < 224; i++)
+ {
+ float zero[4] = {0, 0, 0, 0};
+
+ setPixelShaderConstantF(i, zero, 1);
+ }
+
+ for(int i = 0; i < 256; i++)
+ {
+ float zero[4] = {0, 0, 0, 0};
+
+ setVertexShaderConstantF(i, zero, 1);
+ }
+ }
+
+ Device::~Device()
+ {
+ if(depthStencil)
+ {
+ depthStencil->release();
+ depthStencil = 0;
+ }
+
+ if(renderTarget)
+ {
+ renderTarget->release();
+ renderTarget = 0;
+ }
+
+ delete context;
+ }
+
+ void Device::clearColor(unsigned int color, unsigned int rgbaMask)
+ {
+ TRACE("unsigned long color = 0x%0.8X", color);
+
+ if(!renderTarget)
+ {
+ return;
+ }
+
+ int x0 = 0;
+ int y0 = 0;
+ int width = renderTarget->getExternalWidth();
+ int height = renderTarget->getExternalHeight();
+
+ if(scissorEnable) // Clamp against scissor rectangle
+ {
+ if(x0 < scissorRect.x0) x0 = scissorRect.x0;
+ if(y0 < scissorRect.y0) y0 = scissorRect.y0;
+ if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
+ if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
+ }
+
+ renderTarget->clearColorBuffer(color, rgbaMask, x0, y0, width, height);
+ }
+
+ void Device::clearDepth(float z)
+ {
+ TRACE("float z = %f", z);
+
+ if(!depthStencil)
+ {
+ return;
+ }
+
+ if(z > 1) z = 1;
+ if(z < 0) z = 0;
+
+ int x0 = 0;
+ int y0 = 0;
+ int width = depthStencil->getExternalWidth();
+ int height = depthStencil->getExternalHeight();
+
+ if(scissorEnable) // Clamp against scissor rectangle
+ {
+ if(x0 < scissorRect.x0) x0 = scissorRect.x0;
+ if(y0 < scissorRect.y0) y0 = scissorRect.y0;
+ if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
+ if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
+ }
+
+ depthStencil->clearDepthBuffer(z, x0, y0, width, height);
+ }
+
+ void Device::clearStencil(unsigned int stencil, unsigned int mask)
+ {
+ TRACE("unsigned long stencil = %d", stencil);
+
+ if(!depthStencil)
+ {
+ return;
+ }
+
+ int x0 = 0;
+ int y0 = 0;
+ int width = depthStencil->getExternalWidth();
+ int height = depthStencil->getExternalHeight();
+
+ if(scissorEnable) // Clamp against scissor rectangle
+ {
+ if(x0 < scissorRect.x0) x0 = scissorRect.x0;
+ if(y0 < scissorRect.y0) y0 = scissorRect.y0;
+ if(width > scissorRect.x1 - scissorRect.x0) width = scissorRect.x1 - scissorRect.x0;
+ if(height > scissorRect.y1 - scissorRect.y0) height = scissorRect.y1 - scissorRect.y0;
+ }
+
+ depthStencil->clearStencilBuffer(stencil, mask, x0, y0, width, height);
+ }
+
+ Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
+ {
+ TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool discard = %d", width, height, format, multiSampleDepth, discard);
+
+ if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)
+ {
+ ERR("Invalid parameters");
+ return 0;
+ }
+
+ bool lockable = true;
+
+ switch(format)
+ {
+ // case FORMAT_D15S1:
+ case FORMAT_D24S8:
+ case FORMAT_D24X8:
+ // case FORMAT_D24X4S4:
+ case FORMAT_D24FS8:
+ case FORMAT_D32:
+ case FORMAT_D16:
+ lockable = false;
+ break;
+ // case FORMAT_S8_LOCKABLE:
+ // case FORMAT_D16_LOCKABLE:
+ case FORMAT_D32F_LOCKABLE:
+ // case FORMAT_D32_LOCKABLE:
+ case FORMAT_DF24S8:
+ case FORMAT_DF16S8:
+ lockable = true;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable, true);
+
+ if(!surface)
+ {
+ ERR("Out of memory");
+ return 0;
+ }
+
+ surface->addRef();
+
+ return surface;
+ }
+
+ Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable)
+ {
+ TRACE("unsigned int width = %d, unsigned int height = %d, sw::Format format = %d, int multiSampleDepth = %d, bool lockable = %d", width, height, format, multiSampleDepth, lockable);
+
+ if(height > OUTLINE_RESOLUTION)
+ {
+ ERR("Invalid parameters");
+ return 0;
+ }
+
+ Image *surface = new Image(0, width, height, format, GL_NONE, GL_NONE, multiSampleDepth, lockable, true);
+
+ if(!surface)
+ {
+ ERR("Out of memory");
+ return 0;
+ }
+
+ surface->addRef();
+
+ return surface;
+ }
+
+ void Device::drawIndexedPrimitive(PrimitiveType type, unsigned int indexOffset, unsigned int primitiveCount, int indexSize)
+ {
+ TRACE("");
+
+ if(!bindResources() || !primitiveCount)
+ {
+ return;
+ }
+
+ Context::DrawType drawType;
+
+ if(indexSize == 4)
+ {
+ switch(type)
+ {
+ case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST32; break;
+ case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST32; break;
+ case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP32; break;
+ case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP32; break;
+ case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST32; break;
+ case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP32; break;
+ case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN32; break;
+ default: UNREACHABLE();
+ }
+ }
+ else if(indexSize == 2)
+ {
+ switch(type)
+ {
+ case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST16; break;
+ case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST16; break;
+ case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP16; break;
+ case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP16; break;
+ case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST16; break;
+ case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP16; break;
+ case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN16; break;
+ default: UNREACHABLE();
+ }
+ }
+ else if(indexSize == 1)
+ {
+ switch(type)
+ {
+ case DRAW_POINTLIST: drawType = Context::DRAW_INDEXEDPOINTLIST8; break;
+ case DRAW_LINELIST: drawType = Context::DRAW_INDEXEDLINELIST8; break;
+ case DRAW_LINESTRIP: drawType = Context::DRAW_INDEXEDLINESTRIP8; break;
+ case DRAW_LINELOOP: drawType = Context::DRAW_INDEXEDLINELOOP8; break;
+ case DRAW_TRIANGLELIST: drawType = Context::DRAW_INDEXEDTRIANGLELIST8; break;
+ case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_INDEXEDTRIANGLESTRIP8; break;
+ case DRAW_TRIANGLEFAN: drawType = Context::DRAW_INDEXEDTRIANGLEFAN8; break;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+
+ draw(drawType, indexOffset, primitiveCount);
+ }
+
+ void Device::drawPrimitive(PrimitiveType primitiveType, unsigned int primitiveCount)
+ {
+ TRACE("");
+
+ if(!bindResources() || !primitiveCount)
+ {
+ return;
+ }
+
+ setIndexBuffer(0);
+
+ Context::DrawType drawType;
+
+ switch(primitiveType)
+ {
+ case DRAW_POINTLIST: drawType = Context::DRAW_POINTLIST; break;
+ case DRAW_LINELIST: drawType = Context::DRAW_LINELIST; break;
+ case DRAW_LINESTRIP: drawType = Context::DRAW_LINESTRIP; break;
+ case DRAW_LINELOOP: drawType = Context::DRAW_LINELOOP; break;
+ case DRAW_TRIANGLELIST: drawType = Context::DRAW_TRIANGLELIST; break;
+ case DRAW_TRIANGLESTRIP: drawType = Context::DRAW_TRIANGLESTRIP; break;
+ case DRAW_TRIANGLEFAN: drawType = Context::DRAW_TRIANGLEFAN; break;
+ default: UNREACHABLE();
+ }
+
+ draw(drawType, 0, primitiveCount);
+ }
+
+ void Device::setDepthStencilSurface(Image *depthStencil)
+ {
+ TRACE("Image *newDepthStencil = 0x%0.8p", depthStencil);
+
+ if(this->depthStencil == depthStencil)
+ {
+ return;
+ }
+
+ if(depthStencil)
+ {
+ depthStencil->addRef();
+ }
+
+ if(this->depthStencil)
+ {
+ this->depthStencil->release();
+ }
+
+ this->depthStencil = depthStencil;
+
+ setDepthStencil(depthStencil);
+ }
+
+ void Device::setPixelShader(PixelShader *pixelShader)
+ {
+ TRACE("PixelShader *shader = 0x%0.8p", pixelShader);
+
+ this->pixelShader = pixelShader;
+ pixelShaderDirty = true;
+ }
+
+ void Device::setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
+ {
+ TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
+
+ for(unsigned int i = 0; i < count && startRegister + i < 224; i++)
+ {
+ pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
+ pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
+ pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
+ pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
+ }
+
+ pixelShaderConstantsFDirty = max(startRegister + count, pixelShaderConstantsFDirty);
+ pixelShaderDirty = true; // Reload DEF constants
+ }
+
+ void Device::setScissorEnable(bool enable)
+ {
+ scissorEnable = enable;
+ }
+
+ void Device::setRenderTarget(Image *renderTarget)
+ {
+ TRACE("Image *newRenderTarget = 0x%0.8p", renderTarget);
+
+ if(renderTarget)
+ {
+ renderTarget->addRef();
+ }
+
+ if(this->renderTarget)
+ {
+ this->renderTarget->release();
+ }
+
+ this->renderTarget = renderTarget;
+
+ Renderer::setRenderTarget(0, renderTarget);
+ }
+
+ void Device::setScissorRect(const sw::Rect &rect)
+ {
+ TRACE("const sw::Rect *rect = 0x%0.8p", rect);
+
+ scissorRect = rect;
+ }
+
+ void Device::setVertexShader(VertexShader *vertexShader)
+ {
+ TRACE("VertexShader *shader = 0x%0.8p", vertexShader);
+
+ this->vertexShader = vertexShader;
+ vertexShaderDirty = true;
+ }
+
+ void Device::setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
+ {
+ TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
+
+ for(unsigned int i = 0; i < count && startRegister + i < 256; i++)
+ {
+ vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
+ vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
+ vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
+ vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
+ }
+
+ vertexShaderConstantsFDirty = max(startRegister + count, vertexShaderConstantsFDirty);
+ vertexShaderDirty = true; // Reload DEF constants
+ }
+
+ void Device::setViewport(const Viewport &viewport)
+ {
+ TRACE("const Viewport *viewport = 0x%0.8p", viewport);
+
+ this->viewport = viewport;
+ }
+
+ bool Device::stretchRect(Image *source, const sw::Rect *sourceRect, Image *dest, const sw::Rect *destRect, bool filter)
+ {
+ TRACE("Image *sourceSurface = 0x%0.8p, const sw::Rect *sourceRect = 0x%0.8p, Image *destSurface = 0x%0.8p, const sw::Rect *destRect = 0x%0.8p, bool filter = %d", source, sourceRect, dest, destRect, filter);
+
+ if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest))
+ {
+ ERR("Invalid parameters");
+ return false;
+ }
+
+ int sWidth = source->getExternalWidth();
+ int sHeight = source->getExternalHeight();
+ int dWidth = dest->getExternalWidth();
+ int dHeight = dest->getExternalHeight();
+
+ Rect sRect;
+ Rect dRect;
+
+ if(sourceRect)
+ {
+ sRect = *sourceRect;
+ }
+ else
+ {
+ sRect.y0 = 0;
+ sRect.x0 = 0;
+ sRect.y1 = sHeight;
+ sRect.x1 = sWidth;
+ }
+
+ if(destRect)
+ {
+ dRect = *destRect;
+ }
+ else
+ {
+ dRect.y0 = 0;
+ dRect.x0 = 0;
+ dRect.y1 = dHeight;
+ dRect.x1 = dWidth;
+ }
+
+ bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
+ bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
+ bool depthStencil = Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat());
+ bool alpha0xFF = false;
+
+ if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
+ (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
+ {
+ equalFormats = true;
+ alpha0xFF = true;
+ }
+
+ if(depthStencil) // Copy entirely, internally // FIXME: Check
+ {
+ if(source->hasDepth())
+ {
+ sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
+ sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
+
+ unsigned int width = source->getInternalWidth();
+ unsigned int height = source->getInternalHeight();
+ unsigned int pitch = source->getInternalPitchB();
+
+ for(unsigned int y = 0; y < height; y++)
+ {
+ memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
+
+ sourceBuffer += pitch;
+ destBuffer += pitch;
+ }
+
+ source->unlockInternal();
+ dest->unlockInternal();
+ }
+
+ if(source->hasStencil())
+ {
+ sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC);
+ sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC);
+
+ unsigned int width = source->getInternalWidth();
+ unsigned int height = source->getInternalHeight();
+ unsigned int pitch = source->getStencilPitchB();
+
+ for(unsigned int y = 0; y < height; y++)
+ {
+ memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes
+
+ sourceBuffer += pitch;
+ destBuffer += pitch;
+ }
+
+ source->unlockStencil();
+ dest->unlockStencil();
+ }
+ }
+ else if(!scaling && equalFormats)
+ {
+ unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, LOCK_READONLY, PUBLIC);
+ unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, LOCK_READWRITE, PUBLIC);
+ unsigned int sourcePitch = source->getInternalPitchB();
+ unsigned int destPitch = dest->getInternalPitchB();
+
+ unsigned int width = dRect.x1 - dRect.x0;
+ unsigned int height = dRect.y1 - dRect.y0;
+ unsigned int bytes = width * Image::bytes(source->getInternalFormat());
+
+ for(unsigned int y = 0; y < height; y++)
+ {
+ memcpy(destBytes, sourceBytes, bytes);
+
+ if(alpha0xFF)
+ {
+ for(unsigned int x = 0; x < width; x++)
+ {
+ destBytes[4 * x + 3] = 0xFF;
+ }
+ }
+
+ sourceBytes += sourcePitch;
+ destBytes += destPitch;
+ }
+
+ source->unlockInternal();
+ dest->unlockInternal();
+ }
+ else
+ {
+ blit(source, sRect, dest, dRect, scaling && filter);
+ }
+
+ return true;
+ }
+
+ bool Device::bindResources()
+ {
+ if(!bindViewport())
+ {
+ return false; // Zero-area target region
+ }
+
+ bindShaderConstants();
+
+ return true;
+ }
+
+ void Device::bindShaderConstants()
+ {
+ if(pixelShaderDirty)
+ {
+ if(pixelShader)
+ {
+ if(pixelShaderConstantsFDirty)
+ {
+ Renderer::setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
+ }
+
+ Renderer::setPixelShader(pixelShader); // Loads shader constants set with DEF
+ pixelShaderConstantsFDirty = pixelShader->dirtyConstantsF; // Shader DEF'ed constants are dirty
+ }
+ else
+ {
+ setPixelShader(0);
+ }
+
+ pixelShaderDirty = false;
+ }
+
+ if(vertexShaderDirty)
+ {
+ if(vertexShader)
+ {
+ if(vertexShaderConstantsFDirty)
+ {
+ Renderer::setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
+ }
+
+ Renderer::setVertexShader(vertexShader); // Loads shader constants set with DEF
+ vertexShaderConstantsFDirty = vertexShader->dirtyConstantsF; // Shader DEF'ed constants are dirty
+ }
+ else
+ {
+ setVertexShader(0);
+ }
+
+ vertexShaderDirty = false;
+ }
+ }
+
+ bool Device::bindViewport()
+ {
+ if(viewport.width <= 0 || viewport.height <= 0)
+ {
+ return false;
+ }
+
+ if(scissorEnable)
+ {
+ if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1)
+ {
+ return false;
+ }
+
+ sw::Rect scissor;
+ scissor.x0 = scissorRect.x0;
+ scissor.x1 = scissorRect.x1;
+ scissor.y0 = scissorRect.y0;
+ scissor.y1 = scissorRect.y1;
+
+ setScissor(scissor);
+ }
+ else
+ {
+ sw::Rect scissor;
+ scissor.x0 = viewport.x0;
+ scissor.x1 = viewport.x0 + viewport.width;
+ scissor.y0 = viewport.y0;
+ scissor.y1 = viewport.y0 + viewport.height;
+
+ if(renderTarget)
+ {
+ scissor.x0 = max(scissor.x0, 0);
+ scissor.x1 = min(scissor.x1, renderTarget->getExternalWidth());
+ scissor.y0 = max(scissor.y0, 0);
+ scissor.y1 = min(scissor.y1, renderTarget->getExternalHeight());
+ }
+
+ if(depthStencil)
+ {
+ scissor.x0 = max(scissor.x0, 0);
+ scissor.x1 = min(scissor.x1, depthStencil->getExternalWidth());
+ scissor.y0 = max(scissor.y0, 0);
+ scissor.y1 = min(scissor.y1, depthStencil->getExternalHeight());
+ }
+
+ setScissor(scissor);
+ }
+
+ sw::Viewport view;
+ view.x0 = (float)viewport.x0;
+ view.y0 = (float)viewport.y0;
+ view.width = (float)viewport.width;
+ view.height = (float)viewport.height;
+ view.minZ = viewport.minZ;
+ view.maxZ = viewport.maxZ;
+
+ Renderer::setViewport(view);
+
+ return true;
+ }
+
+ bool Device::validRectangle(const sw::Rect *rect, Image *surface)
+ {
+ if(!rect)
+ {
+ return true;
+ }
+
+ if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0)
+ {
+ return false;
+ }
+
+ if(rect->x0 < 0 || rect->y0 < 0)
+ {
+ return false;
+ }
+
+ if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight())
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ void Device::finish()
+ {
+ synchronize();
+ }
+}
+
+// Exported functions for use by EGL
+extern "C"
+{
+ gl::Device *createDevice()
+ {
+ sw::Context *context = new sw::Context();
+
+ if(context)
+ {
+ return new gl::Device(context);
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file