OSDN Git Service

Make Blitter part of Renderer.
[android-x86/external-swiftshader.git] / src / Renderer / Renderer.cpp
index 3fd13bb..a84423d 100644 (file)
@@ -1,13 +1,16 @@
-// SwiftShader Software Renderer
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
 //
-// Copyright(c) 2005-2012 TransGaming Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
 //
-// 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.
+//    http://www.apache.org/licenses/LICENSE-2.0
 //
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 #include "Renderer.hpp"
 
@@ -28,9 +31,6 @@
 #include "Debug.hpp"
 #include "Reactor/Reactor.hpp"
 
-#include <malloc.h>
-#include <assert.h>
-
 #undef max
 
 bool disableServer = true;
@@ -46,6 +46,8 @@ namespace sw
        extern bool symmetricNormalizedDepth;   // [-1, 1] instead of [0, 1]
        extern bool booleanFaceRegister;
        extern bool fullPixelPositionRegister;
+       extern bool leadingVertexFirst;         // Flat shading uses first vertex, else last
+       extern bool secondaryColor;             // Specular lighting is applied after texturing
 
        extern bool forceWindowed;
        extern bool complementaryDepthBuffer;
@@ -69,8 +71,6 @@ namespace sw
        TranscendentalPrecision rsqPrecision = ACCURATE;
        bool perspectiveCorrection = true;
 
-       BackoffLock Renderer::codegenMutex;
-
        struct Parameters
        {
                Renderer *renderer;
@@ -81,11 +81,11 @@ namespace sw
        {
                queries = 0;
 
-               vsDirtyConstF = 256 + 1;
+               vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
                vsDirtyConstI = 16;
                vsDirtyConstB = 16;
 
-               psDirtyConstF = 224;
+               psDirtyConstF = FRAGMENT_UNIFORM_VECTORS;
                psDirtyConstI = 16;
                psDirtyConstB = 16;
 
@@ -102,16 +102,19 @@ namespace sw
                deallocate(data);
        }
 
-       Renderer::Renderer(Context *context, bool halfIntegerCoordinates, bool symmetricNormalizedDepth, bool booleanFaceRegister, bool fullPixelPositionRegister, bool exactColorRounding) : context(context), VertexProcessor(context), PixelProcessor(context), SetupProcessor(context), viewport()
+       Renderer::Renderer(Context *context, Conventions conventions, bool exactColorRounding) : VertexProcessor(context), PixelProcessor(context), SetupProcessor(context), context(context), viewport()
        {
-               sw::halfIntegerCoordinates = halfIntegerCoordinates;
-               sw::symmetricNormalizedDepth = symmetricNormalizedDepth;
-               sw::booleanFaceRegister = booleanFaceRegister;
-               sw::fullPixelPositionRegister = fullPixelPositionRegister;
+               sw::halfIntegerCoordinates = conventions.halfIntegerCoordinates;
+               sw::symmetricNormalizedDepth = conventions.symmetricNormalizedDepth;
+               sw::booleanFaceRegister = conventions.booleanFaceRegister;
+               sw::fullPixelPositionRegister = conventions.fullPixelPositionRegister;
+               sw::leadingVertexFirst = conventions.leadingVertexFirst;
+               sw::secondaryColor = conventions.secondaryColor;
                sw::exactColorRounding = exactColorRounding;
 
                setRenderTarget(0, 0);
-               clipper = new Clipper();
+               clipper = new Clipper(symmetricNormalizedDepth);
+               blitter = new Blitter;
 
                updateViewMatrix = true;
                updateBaseMatrix = true;
@@ -175,7 +178,10 @@ namespace sw
                sync->destruct();
 
                delete clipper;
-               clipper = 0;
+               clipper = nullptr;
+
+               delete blitter;
+               blitter = nullptr;
 
                terminateThreads();
                delete resumeApp;
@@ -188,9 +194,16 @@ namespace sw
                delete swiftConfig;
        }
 
-       void Renderer::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
+       // This object has to be mem aligned
+       void* Renderer::operator new(size_t size)
+       {
+               ASSERT(size == sizeof(Renderer)); // This operator can't be called from a derived class
+               return sw::allocate(sizeof(Renderer), 16);
+       }
+
+       void Renderer::operator delete(void * mem)
        {
-               blitter.blit(source, sRect, dest, dRect, filter);
+               sw::deallocate(mem);
        }
 
        void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
@@ -212,7 +225,7 @@ namespace sw
 
                for(int q = 0; q < ss; q++)
                {
-                       int oldMultiSampleMask = context->multiSampleMask;
+                       unsigned int oldMultiSampleMask = context->multiSampleMask;
                        context->multiSampleMask = (context->sampleMask >> (ms * q)) & ((unsigned)0xFFFFFFFF >> (32 - ms));
 
                        if(!context->multiSampleMask)
@@ -222,54 +235,48 @@ namespace sw
 
                        sync->lock(sw::PRIVATE);
 
-                       Routine *vertexRoutine;
-                       Routine *setupRoutine;
-                       Routine *pixelRoutine;
-
                        if(update || oldMultiSampleMask != context->multiSampleMask)
                        {
-                               vertexState = VertexProcessor::update();
+                               vertexState = VertexProcessor::update(drawType);
                                setupState = SetupProcessor::update();
                                pixelState = PixelProcessor::update();
 
-                               codegenMutex.lock();
-
                                vertexRoutine = VertexProcessor::routine(vertexState);
                                setupRoutine = SetupProcessor::routine(setupState);
                                pixelRoutine = PixelProcessor::routine(pixelState);
-
-                               codegenMutex.unlock();
                        }
 
                        int batch = batchSize / ms;
 
-                       int (*setupPrimitives)(Renderer *renderer, int batch, int count);
+                       int (Renderer::*setupPrimitives)(int batch, int count);
 
                        if(context->isDrawTriangle())
                        {
                                switch(context->fillMode)
                                {
                                case FILL_SOLID:
-                                       setupPrimitives = setupSolidTriangles;
+                                       setupPrimitives = &Renderer::setupSolidTriangles;
                                        break;
                                case FILL_WIREFRAME:
-                                       setupPrimitives = setupWireframeTriangle;
+                                       setupPrimitives = &Renderer::setupWireframeTriangle;
                                        batch = 1;
                                        break;
                                case FILL_VERTEX:
-                                       setupPrimitives = setupVertexTriangle;
+                                       setupPrimitives = &Renderer::setupVertexTriangle;
                                        batch = 1;
                                        break;
-                               default: ASSERT(false);
+                               default:
+                                       ASSERT(false);
+                                       return;
                                }
                        }
                        else if(context->isDrawLine())
                        {
-                               setupPrimitives = setupLines;
+                               setupPrimitives = &Renderer::setupLines;
                        }
                        else   // Point draw
                        {
-                               setupPrimitives = setupPoints;
+                               setupPrimitives = &Renderer::setupPoints;
                        }
 
                        DrawCall *draw = 0;
@@ -298,12 +305,17 @@ namespace sw
 
                        if(queries.size() != 0)
                        {
+                               draw->queries = new std::list<Query*>();
+                               bool includePrimitivesWrittenQueries = vertexState.transformFeedbackQueryEnabled && vertexState.transformFeedbackEnabled;
                                for(std::list<Query*>::iterator query = queries.begin(); query != queries.end(); query++)
                                {
-                                       atomicIncrement(&(*query)->reference);
+                                       Query* q = *query;
+                                       if(includePrimitivesWrittenQueries || (q->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
+                                       {
+                                               atomicIncrement(&(q->reference));
+                                               draw->queries->push_back(q);
+                                       }
                                }
-
-                               draw->queries = new std::list<Query*>(queries);
                        }
 
                        draw->drawType = drawType;
@@ -316,13 +328,13 @@ namespace sw
                        draw->vertexRoutine = vertexRoutine;
                        draw->setupRoutine = setupRoutine;
                        draw->pixelRoutine = pixelRoutine;
-                       draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();;
+                       draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
                        draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
                        draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
                        draw->setupPrimitives = setupPrimitives;
                        draw->setupState = setupState;
 
-                       for(int i = 0; i < 16; i++)
+                       for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
                        {
                                draw->vertexStream[i] = context->input[i].resource;
                                data->input[i] = context->input[i].buffer;
@@ -377,8 +389,17 @@ namespace sw
                                        memcpy(&data->ps.b, PixelProcessor::b, sizeof(bool) * draw->psDirtyConstB);
                                        draw->psDirtyConstB = 0;
                                }
+
+                               PixelProcessor::lockUniformBuffers(data->ps.u, draw->pUniformBuffers);
                        }
-                       
+                       else
+                       {
+                               for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
+                               {
+                                       draw->pUniformBuffers[i] = nullptr;
+                               }
+                       }
+
                        if(context->pixelShaderVersion() <= 0x0104)
                        {
                                for(int stage = 0; stage < 8; stage++)
@@ -424,14 +445,32 @@ namespace sw
                                        memcpy(&data->vs.b, VertexProcessor::b, sizeof(bool) * draw->vsDirtyConstB);
                                        draw->vsDirtyConstB = 0;
                                }
+
+                               if(context->vertexShader->isInstanceIdDeclared())
+                               {
+                                       data->instanceID = context->instanceID;
+                               }
+
+                               VertexProcessor::lockUniformBuffers(data->vs.u, draw->vUniformBuffers);
+                               VertexProcessor::lockTransformFeedbackBuffers(data->vs.t, data->vs.reg, data->vs.row, data->vs.col, data->vs.str, draw->transformFeedbackBuffers);
                        }
                        else
                        {
                                data->ff = ff;
 
-                               draw->vsDirtyConstF = 256 + 1;
+                               draw->vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
                                draw->vsDirtyConstI = 16;
                                draw->vsDirtyConstB = 16;
+
+                               for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
+                               {
+                                       draw->vUniformBuffers[i] = nullptr;
+                               }
+
+                               for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
+                               {
+                                       draw->transformFeedbackBuffers[i] = nullptr;
+                               }
                        }
 
                        if(pixelState.stencilActive)
@@ -456,7 +495,7 @@ namespace sw
 
                        if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
                        {
-                               float ref = (float)context->alphaReference * (1.0f / 255.0f);
+                               float ref = context->alphaReference * (1.0f / 255.0f);
                                float margin = sw::min(ref, 1.0f - ref);
 
                                if(ms == 4)
@@ -535,8 +574,8 @@ namespace sw
 
                                data->Wx16 = replicate(W * 16);
                                data->Hx16 = replicate(H * 16);
-                               data->X0x16 = replicate(X0 * 16);
-                               data->Y0x16 = replicate(Y0 * 16);
+                               data->X0x16 = replicate(X0 * 16 - 8);
+                               data->Y0x16 = replicate(Y0 * 16 - 8);
                                data->XXXX = replicate(X[s][q] / W);
                                data->YYYY = replicate(Y[s][q] / H);
                                data->halfPixelX = replicate(0.5f / W);
@@ -560,7 +599,7 @@ namespace sw
 
                        // Target
                        {
-                               for(int index = 0; index < 4; index++)
+                               for(int index = 0; index < RENDERTARGETS; index++)
                                {
                                        draw->renderTarget[index] = context->renderTarget[index];
 
@@ -572,17 +611,21 @@ namespace sw
                                        }
                                }
 
-                               draw->depthStencil = context->depthStencil;
+                               draw->depthBuffer = context->depthBuffer;
+                               draw->stencilBuffer = context->stencilBuffer;
 
-                               if(draw->depthStencil)
+                               if(draw->depthBuffer)
                                {
-                                       data->depthBuffer = (float*)context->depthStencil->lockInternal(0, 0, q * ms, LOCK_READWRITE, MANAGED);
-                                       data->depthPitchB = context->depthStencil->getInternalPitchB();
-                                       data->depthSliceB = context->depthStencil->getInternalSliceB();
+                                       data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, q * ms, LOCK_READWRITE, MANAGED);
+                                       data->depthPitchB = context->depthBuffer->getInternalPitchB();
+                                       data->depthSliceB = context->depthBuffer->getInternalSliceB();
+                               }
 
-                                       data->stencilBuffer = (unsigned char*)context->depthStencil->lockStencil(q * ms, MANAGED);
-                                       data->stencilPitchB = context->depthStencil->getStencilPitchB();
-                                       data->stencilSliceB = context->depthStencil->getStencilSliceB();
+                               if(draw->stencilBuffer)
+                               {
+                                       data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, q * ms, MANAGED);
+                                       data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
+                                       data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
                                }
                        }
 
@@ -603,18 +646,45 @@ namespace sw
                        nextDraw++;
                        schedulerMutex.unlock();
 
-                       if(!threadsAwake)
+                       #ifndef NDEBUG
+                       if(threadCount == 1)   // Use main thread for draw execution
                        {
-                               suspend[0]->wait();
-
                                threadsAwake = 1;
                                task[0].type = Task::RESUME;
 
-                               resume[0]->signal();
+                               taskLoop(0);
+                       }
+                       else
+                       #endif
+                       {
+                               if(!threadsAwake)
+                               {
+                                       suspend[0]->wait();
+
+                                       threadsAwake = 1;
+                                       task[0].type = Task::RESUME;
+
+                                       resume[0]->signal();
+                               }
                        }
                }
        }
 
+       void Renderer::clear(void *pixel, Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask)
+       {
+               blitter->clear(pixel, format, dest, dRect, rgbaMask);
+       }
+
+       void Renderer::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil)
+       {
+               blitter->blit(source, sRect, dest, dRect, filter, isStencil);
+       }
+
+       void Renderer::blit3D(Surface *source, Surface *dest)
+       {
+               blitter->blit3D(source, dest);
+       }
+
        void Renderer::threadFunction(void *parameters)
        {
                Renderer *renderer = static_cast<Parameters*>(parameters)->renderer;
@@ -682,7 +752,7 @@ namespace sw
                                }
                        }
                }
-       
+
                // Find primitive tasks
                if(currentDraw == nextDraw)
                {
@@ -783,11 +853,11 @@ namespace sw
                case Task::PRIMITIVES:
                        {
                                int unit = task[threadIndex].primitiveUnit;
-                               
+
                                int input = primitiveProgress[unit].firstPrimitive;
                                int count = primitiveProgress[unit].primitiveCount;
                                DrawCall *draw = drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
-                               int (*setupPrimitives)(Renderer *renderer, int batch, int count) = draw->setupPrimitives;
+                               int (Renderer::*setupPrimitives)(int batch, int count) = draw->setupPrimitives;
 
                                processPrimitiveVertices(unit, input, count, draw->count, threadIndex);
 
@@ -797,7 +867,12 @@ namespace sw
                                        startTick = time;
                                #endif
 
-                               int visible = setupPrimitives(this, unit, count);
+                               int visible = 0;
+
+                               if(!draw->setupState.rasterizerDiscard)
+                               {
+                                       visible = (this->*setupPrimitives)(unit, count);
+                               }
 
                                primitiveProgress[unit].visible = visible;
                                primitiveProgress[unit].references = clusterCount;
@@ -854,8 +929,9 @@ namespace sw
                DrawData &data = *draw.data;
                int primitive = primitiveProgress[unit].firstPrimitive;
                int count = primitiveProgress[unit].primitiveCount;
+               int processedPrimitives = primitive + count;
 
-               pixelProgress[cluster].processedPrimitives = primitive + count;
+               pixelProgress[cluster].processedPrimitives = processedPrimitives;
 
                if(pixelProgress[cluster].processedPrimitives >= draw.count)
                {
@@ -887,9 +963,19 @@ namespace sw
                                        {
                                                Query *query = *q;
 
-                                               for(int cluster = 0; cluster < clusterCount; cluster++)
+                                               switch(query->type)
                                                {
-                                                       atomicAdd((volatile int*)&query->data, data.occlusion[cluster]);
+                                               case Query::FRAGMENTS_PASSED:
+                                                       for(int cluster = 0; cluster < clusterCount; cluster++)
+                                                       {
+                                                               atomicAdd((volatile int*)&query->data, data.occlusion[cluster]);
+                                                       }
+                                                       break;
+                                               case Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+                                                       atomicAdd((volatile int*)&query->data, processedPrimitives);
+                                                       break;
+                                               default:
+                                                       break;
                                                }
 
                                                atomicDecrement(&query->reference);
@@ -899,7 +985,7 @@ namespace sw
                                        draw.queries = 0;
                                }
 
-                               for(int i = 0; i < 4; i++)
+                               for(int i = 0; i < RENDERTARGETS; i++)
                                {
                                        if(draw.renderTarget[i])
                                        {
@@ -907,10 +993,14 @@ namespace sw
                                        }
                                }
 
-                               if(draw.depthStencil)
+                               if(draw.depthBuffer)
+                               {
+                                       draw.depthBuffer->unlockInternal();
+                               }
+
+                               if(draw.stencilBuffer)
                                {
-                                       draw.depthStencil->unlockInternal();
-                                       draw.depthStencil->unlockStencil();
+                                       draw.stencilBuffer->unlockStencil();
                                }
 
                                for(int i = 0; i < TOTAL_IMAGE_UNITS; i++)
@@ -921,7 +1011,7 @@ namespace sw
                                        }
                                }
 
-                               for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
+                               for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
                                {
                                        if(draw.vertexStream[i])
                                        {
@@ -934,6 +1024,26 @@ namespace sw
                                        draw.indexBuffer->unlock();
                                }
 
+                               for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
+                               {
+                                       if(draw.pUniformBuffers[i])
+                                       {
+                                               draw.pUniformBuffers[i]->unlock();
+                                       }
+                                       if(draw.vUniformBuffers[i])
+                                       {
+                                               draw.vUniformBuffers[i]->unlock();
+                                       }
+                               }
+
+                               for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
+                               {
+                                       if(draw.transformFeedbackBuffers[i])
+                                       {
+                                               draw.transformFeedbackBuffers[i]->unlock();
+                                       }
+                               }
+
                                draw.vertexRoutine->unbind();
                                draw.setupRoutine->unbind();
                                draw.pixelRoutine->unbind();
@@ -1348,7 +1458,7 @@ namespace sw
                                }
                        }
                        break;
-        case DRAW_QUADLIST:
+               case DRAW_QUADLIST:
                        {
                                unsigned int index = 4 * start / 2;
 
@@ -1358,7 +1468,7 @@ namespace sw
                                        batch[i+0][1] = index + 1;
                                        batch[i+0][2] = index + 2;
 
-                    batch[i+1][0] = index + 0;
+                                       batch[i+1][0] = index + 0;
                                        batch[i+1][1] = index + 2;
                                        batch[i+1][2] = index + 3;
 
@@ -1368,18 +1478,20 @@ namespace sw
                        break;
                default:
                        ASSERT(false);
+                       return;
                }
 
+               task->primitiveStart = start;
                task->vertexCount = triangleCount * 3;
                vertexRoutine(&triangle->v0, (unsigned int*)&batch, task, data);
        }
 
-       int Renderer::setupSolidTriangles(Renderer *renderer, int unit, int count)
+       int Renderer::setupSolidTriangles(int unit, int count)
        {
-               Triangle *triangle = renderer->triangleBatch[unit];
-               Primitive *primitive = renderer->primitiveBatch[unit];
+               Triangle *triangle = triangleBatch[unit];
+               Primitive *primitive = primitiveBatch[unit];
 
-               DrawCall &draw = *renderer->drawList[renderer->primitiveProgress[unit].drawCall % DRAW_COUNT];
+               DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
                SetupProcessor::State &state = draw.setupState;
                const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
 
@@ -1402,7 +1514,7 @@ namespace sw
 
                                if(clipFlagsOr != Clipper::CLIP_FINITE)
                                {
-                                       if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+                                       if(!clipper->clip(polygon, clipFlagsOr, draw))
                                        {
                                                continue;
                                        }
@@ -1419,15 +1531,14 @@ namespace sw
                return visible;
        }
 
-       int Renderer::setupWireframeTriangle(Renderer *renderer, int unit, int count)
+       int Renderer::setupWireframeTriangle(int unit, int count)
        {
-               Triangle *triangle = renderer->triangleBatch[unit];
-               Primitive *primitive = renderer->primitiveBatch[unit];
+               Triangle *triangle = triangleBatch[unit];
+               Primitive *primitive = primitiveBatch[unit];
                int visible = 0;
 
-               DrawCall &draw = *renderer->drawList[renderer->primitiveProgress[unit].drawCall % DRAW_COUNT];
+               DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
                SetupProcessor::State &state = draw.setupState;
-               SetupProcessor::RoutinePointer setupRoutine = draw.setupPointer;
 
                const Vertex &v0 = triangle[0].v0;
                const Vertex &v1 = triangle[0].v1;
@@ -1463,7 +1574,7 @@ namespace sw
 
                for(int i = 0; i < 3; i++)
                {
-                       if(setupLine(renderer, *primitive, *triangle, draw))
+                       if(setupLine(*primitive, *triangle, draw))
                        {
                                primitive->area = 0.5f * d;
 
@@ -1476,14 +1587,14 @@ namespace sw
 
                return visible;
        }
-       
-       int Renderer::setupVertexTriangle(Renderer *renderer, int unit, int count)
+
+       int Renderer::setupVertexTriangle(int unit, int count)
        {
-               Triangle *triangle = renderer->triangleBatch[unit];
-               Primitive *primitive = renderer->primitiveBatch[unit];
+               Triangle *triangle = triangleBatch[unit];
+               Primitive *primitive = primitiveBatch[unit];
                int visible = 0;
 
-               DrawCall &draw = *renderer->drawList[renderer->primitiveProgress[unit].drawCall % DRAW_COUNT];
+               DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
                SetupProcessor::State &state = draw.setupState;
 
                const Vertex &v0 = triangle[0].v0;
@@ -1507,7 +1618,7 @@ namespace sw
 
                for(int i = 0; i < 3; i++)
                {
-                       if(setupPoint(renderer, *primitive, *triangle, draw))
+                       if(setupPoint(*primitive, *triangle, draw))
                        {
                                primitive->area = 0.5f * d;
 
@@ -1521,20 +1632,20 @@ namespace sw
                return visible;
        }
 
-       int Renderer::setupLines(Renderer *renderer, int unit, int count)
+       int Renderer::setupLines(int unit, int count)
        {
-               Triangle *triangle = renderer->triangleBatch[unit];
-               Primitive *primitive = renderer->primitiveBatch[unit];
+               Triangle *triangle = triangleBatch[unit];
+               Primitive *primitive = primitiveBatch[unit];
                int visible = 0;
 
-               DrawCall &draw = *renderer->drawList[renderer->primitiveProgress[unit].drawCall % DRAW_COUNT];
+               DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
                SetupProcessor::State &state = draw.setupState;
 
                int ms = state.multiSample;
 
                for(int i = 0; i < count; i++)
                {
-                       if(setupLine(renderer, *primitive, *triangle, draw))
+                       if(setupLine(*primitive, *triangle, draw))
                        {
                                primitive += ms;
                                visible++;
@@ -1546,20 +1657,20 @@ namespace sw
                return visible;
        }
 
-       int Renderer::setupPoints(Renderer *renderer, int unit, int count)
+       int Renderer::setupPoints(int unit, int count)
        {
-               Triangle *triangle = renderer->triangleBatch[unit];
-               Primitive *primitive = renderer->primitiveBatch[unit];
+               Triangle *triangle = triangleBatch[unit];
+               Primitive *primitive = primitiveBatch[unit];
                int visible = 0;
 
-               DrawCall &draw = *renderer->drawList[renderer->primitiveProgress[unit].drawCall % DRAW_COUNT];
+               DrawCall &draw = *drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
                SetupProcessor::State &state = draw.setupState;
 
                int ms = state.multiSample;
 
                for(int i = 0; i < count; i++)
                {
-                       if(setupPoint(renderer, *primitive, *triangle, draw))
+                       if(setupPoint(*primitive, *triangle, draw))
                        {
                                primitive += ms;
                                visible++;
@@ -1571,7 +1682,7 @@ namespace sw
                return visible;
        }
 
-       bool Renderer::setupLine(Renderer *renderer, Primitive &primitive, Triangle &triangle, const DrawCall &draw)
+       bool Renderer::setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
        {
                const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
                const SetupProcessor::State &state = draw.setupState;
@@ -1630,19 +1741,19 @@ namespace sw
 
                        P[0].x += -dy0w + -dx0w;
                        P[0].y += -dx0h + +dy0h;
-                       C[0] = computeClipFlags(P[0], data);
+                       C[0] = clipper->computeClipFlags(P[0]);
 
                        P[1].x += -dy1w + +dx1w;
                        P[1].y += -dx1h + +dy1h;
-                       C[1] = computeClipFlags(P[1], data);
+                       C[1] = clipper->computeClipFlags(P[1]);
 
                        P[2].x += +dy1w + +dx1w;
                        P[2].y += +dx1h + -dy1h;
-                       C[2] = computeClipFlags(P[2], data);
+                       C[2] = clipper->computeClipFlags(P[2]);
 
                        P[3].x += +dy0w + -dx0w;
                        P[3].y += +dx0h + +dy0h;
-                       C[3] = computeClipFlags(P[3], data);
+                       C[3] = clipper->computeClipFlags(P[3]);
 
                        if((C[0] & C[1] & C[2] & C[3]) == Clipper::CLIP_FINITE)
                        {
@@ -1652,7 +1763,7 @@ namespace sw
 
                                if(clipFlagsOr != Clipper::CLIP_FINITE)
                                {
-                                       if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+                                       if(!clipper->clip(polygon, clipFlagsOr, draw))
                                        {
                                                return false;
                                        }
@@ -1682,28 +1793,28 @@ namespace sw
                        float dy1 = lineWidth * 0.5f * P1.w / H;
 
                        P[0].x += -dx0;
-                       C[0] = computeClipFlags(P[0], data);
+                       C[0] = clipper->computeClipFlags(P[0]);
 
                        P[1].y += +dy0;
-                       C[1] = computeClipFlags(P[1], data);
+                       C[1] = clipper->computeClipFlags(P[1]);
 
                        P[2].x += +dx0;
-                       C[2] = computeClipFlags(P[2], data);
+                       C[2] = clipper->computeClipFlags(P[2]);
 
                        P[3].y += -dy0;
-                       C[3] = computeClipFlags(P[3], data);
+                       C[3] = clipper->computeClipFlags(P[3]);
 
                        P[4].x += -dx1;
-                       C[4] = computeClipFlags(P[4], data);
+                       C[4] = clipper->computeClipFlags(P[4]);
 
                        P[5].y += +dy1;
-                       C[5] = computeClipFlags(P[5], data);
+                       C[5] = clipper->computeClipFlags(P[5]);
 
                        P[6].x += +dx1;
-                       C[6] = computeClipFlags(P[6], data);
+                       C[6] = clipper->computeClipFlags(P[6]);
 
                        P[7].y += -dy1;
-                       C[7] = computeClipFlags(P[7], data);
+                       C[7] = clipper->computeClipFlags(P[7]);
 
                        if((C[0] & C[1] & C[2] & C[3] & C[4] & C[5] & C[6] & C[7]) == Clipper::CLIP_FINITE)
                        {
@@ -1758,7 +1869,7 @@ namespace sw
 
                                if(clipFlagsOr != Clipper::CLIP_FINITE)
                                {
-                                       if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+                                       if(!clipper->clip(polygon, clipFlagsOr, draw))
                                        {
                                                return false;
                                        }
@@ -1771,7 +1882,7 @@ namespace sw
                return false;
        }
 
-       bool Renderer::setupPoint(Renderer *renderer, Primitive &primitive, Triangle &triangle, const DrawCall &draw)
+       bool Renderer::setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw)
        {
                const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
                const SetupProcessor::State &state = draw.setupState;
@@ -1783,7 +1894,7 @@ namespace sw
 
                int pts = state.pointSizeRegister;
 
-               if(state.pointSizeRegister != 0xF)
+               if(state.pointSizeRegister != Unused)
                {
                        pSize = v.v[pts].y;
                }
@@ -1809,19 +1920,19 @@ namespace sw
 
                P[0].x -= X;
                P[0].y += Y;
-               C[0] = computeClipFlags(P[0], data);
+               C[0] = clipper->computeClipFlags(P[0]);
 
                P[1].x += X;
                P[1].y += Y;
-               C[1] = computeClipFlags(P[1], data);
+               C[1] = clipper->computeClipFlags(P[1]);
 
                P[2].x += X;
                P[2].y -= Y;
-               C[2] = computeClipFlags(P[2], data);
+               C[2] = clipper->computeClipFlags(P[2]);
 
                P[3].x -= X;
                P[3].y -= Y;
-               C[3] = computeClipFlags(P[3], data);
+               C[3] = clipper->computeClipFlags(P[3]);
 
                triangle.v1 = triangle.v0;
                triangle.v2 = triangle.v0;
@@ -1837,32 +1948,18 @@ namespace sw
 
                        if(clipFlagsOr != Clipper::CLIP_FINITE)
                        {
-                               if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+                               if(!clipper->clip(polygon, clipFlagsOr, draw))
                                {
                                        return false;
                                }
                        }
-                       
+
                        return setupRoutine(&primitive, &triangle, &polygon, &data);
                }
 
                return false;
        }
 
-       unsigned int Renderer::computeClipFlags(const float4 &v, const DrawData &data)
-       {
-               float clX = v.x + data.halfPixelX[0] * v.w;
-               float clY = v.y + data.halfPixelY[0] * v.w;
-
-               return ((clX > v.w)  << 0) |
-                          ((clY > v.w)  << 1) |
-                          ((v.z > v.w)  << 2) |
-                          ((clX < -v.w) << 3) |
-                      ((clY < -v.w) << 4) |
-                          ((v.z < 0)    << 5) |
-                          Clipper::CLIP_FINITE;   // FIXME: xyz finite
-       }
-
        void Renderer::initializeThreads()
        {
                unitCount = ceilPow2(threadCount);
@@ -1910,7 +2007,7 @@ namespace sw
                                exitThreads = true;
                                resume[thread]->signal();
                                worker[thread]->join();
-                               
+
                                delete worker[thread];
                                worker[thread] = 0;
                                delete resume[thread];
@@ -1918,7 +2015,7 @@ namespace sw
                                delete suspend[thread];
                                suspend[thread] = 0;
                        }
-               
+
                        deallocate(vertexTask[thread]);
                        vertexTask[thread] = 0;
                }
@@ -2038,22 +2135,22 @@ namespace sw
 
        bool Renderer::isReadWriteTexture(int sampler)
        {
-               for(int index = 0; index < 4; index++)
+               for(int index = 0; index < RENDERTARGETS; index++)
                {
                        if(context->renderTarget[index] && context->texture[sampler] == context->renderTarget[index]->getResource())
                        {
                                return true;
                        }
                }
-       
-               if(context->depthStencil && context->texture[sampler] == context->depthStencil->getResource())
+
+               if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
                {
                        return true;
                }
 
                return false;
        }
-       
+
        void Renderer::updateClipper()
        {
                if(updateClipPlanes)
@@ -2093,7 +2190,7 @@ namespace sw
        void Renderer::setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type)
        {
                ASSERT(sampler < TOTAL_IMAGE_UNITS && face < 6 && level < MIPMAP_LEVELS);
-               
+
                context->sampler[sampler].setTextureLevel(face, level, surface, type);
        }
 
@@ -2217,6 +2314,102 @@ namespace sw
                }
        }
 
+       void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setSwizzleR(sampler, swizzleR);
+               }
+               else
+               {
+                       VertexProcessor::setSwizzleR(sampler, swizzleR);
+               }
+       }
+
+       void Renderer::setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setSwizzleG(sampler, swizzleG);
+               }
+               else
+               {
+                       VertexProcessor::setSwizzleG(sampler, swizzleG);
+               }
+       }
+
+       void Renderer::setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setSwizzleB(sampler, swizzleB);
+               }
+               else
+               {
+                       VertexProcessor::setSwizzleB(sampler, swizzleB);
+               }
+       }
+
+       void Renderer::setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setSwizzleA(sampler, swizzleA);
+               }
+               else
+               {
+                       VertexProcessor::setSwizzleA(sampler, swizzleA);
+               }
+       }
+
+       void Renderer::setBaseLevel(SamplerType type, int sampler, int baseLevel)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setBaseLevel(sampler, baseLevel);
+               }
+               else
+               {
+                       VertexProcessor::setBaseLevel(sampler, baseLevel);
+               }
+       }
+
+       void Renderer::setMaxLevel(SamplerType type, int sampler, int maxLevel)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setMaxLevel(sampler, maxLevel);
+               }
+               else
+               {
+                       VertexProcessor::setMaxLevel(sampler, maxLevel);
+               }
+       }
+
+       void Renderer::setMinLod(SamplerType type, int sampler, float minLod)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setMinLod(sampler, minLod);
+               }
+               else
+               {
+                       VertexProcessor::setMinLod(sampler, minLod);
+               }
+       }
+
+       void Renderer::setMaxLod(SamplerType type, int sampler, float maxLod)
+       {
+               if(type == SAMPLER_PIXEL)
+               {
+                       PixelProcessor::setMaxLod(sampler, maxLod);
+               }
+               else
+               {
+                       VertexProcessor::setMaxLod(sampler, maxLod);
+               }
+       }
+
        void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
        {
                context->setPointSpriteEnable(pointSpriteEnable);
@@ -2242,6 +2435,11 @@ namespace sw
                slopeDepthBias = slopeBias;
        }
 
+       void Renderer::setRasterizerDiscard(bool rasterizerDiscard)
+       {
+               context->rasterizerDiscard = rasterizerDiscard;
+       }
+
        void Renderer::setPixelShader(const PixelShader *shader)
        {
                context->pixelShader = shader;
@@ -2385,7 +2583,7 @@ namespace sw
        {
                queries.push_back(query);
        }
-       
+
        void Renderer::removeQuery(Query *query)
        {
                queries.remove(query);
@@ -2396,7 +2594,7 @@ namespace sw
                {
                        return threadCount;
                }
-               
+
                int64_t Renderer::getVertexTime(int thread)
                {
                        return vertexTime[thread];
@@ -2406,7 +2604,7 @@ namespace sw
                {
                        return setupTime[thread];
                }
-                       
+
                int64_t Renderer::getPixelTime(int thread)
                {
                        return pixelTime[thread];
@@ -2440,7 +2638,7 @@ namespace sw
 
        void Renderer::setClipPlane(unsigned int index, const float plane[4])
        {
-               if(index < 6)
+               if(index < MAX_CLIP_PLANES)
                {
                        userPlane[index] = plane;
                }
@@ -2457,7 +2655,7 @@ namespace sw
                {
                        terminateThreads();
 
-                       SwiftConfig::Configuration configuration = {0};
+                       SwiftConfig::Configuration configuration = {};
                        swiftConfig->getConfiguration(configuration);
 
                        precacheVertex = !newConfiguration && configuration.precache;