OSDN Git Service

Make Blitter part of Renderer.
[android-x86/external-swiftshader.git] / src / Renderer / Renderer.cpp
index a5e8760..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"
 
@@ -110,7 +113,8 @@ namespace sw
                sw::exactColorRounding = exactColorRounding;
 
                setRenderTarget(0, 0);
-               clipper = new Clipper();
+               clipper = new Clipper(symmetricNormalizedDepth);
+               blitter = new Blitter;
 
                updateViewMatrix = true;
                updateBaseMatrix = true;
@@ -174,7 +178,10 @@ namespace sw
                sync->destruct();
 
                delete clipper;
-               clipper = 0;
+               clipper = nullptr;
+
+               delete blitter;
+               blitter = nullptr;
 
                terminateThreads();
                delete resumeApp;
@@ -187,19 +194,16 @@ namespace sw
                delete swiftConfig;
        }
 
-       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)
+       // This object has to be mem aligned
+       void* Renderer::operator new(size_t size)
        {
-               blitter.blit(source, sRect, dest, dRect, filter);
+               ASSERT(size == sizeof(Renderer)); // This operator can't be called from a derived class
+               return sw::allocate(sizeof(Renderer), 16);
        }
 
-       void Renderer::blit3D(Surface *source, Surface *dest)
+       void Renderer::operator delete(void * mem)
        {
-               blitter.blit3D(source, dest);
+               sw::deallocate(mem);
        }
 
        void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
@@ -231,13 +235,9 @@ 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();
 
@@ -248,33 +248,35 @@ namespace sw
 
                        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;
@@ -332,7 +334,7 @@ namespace sw
                        draw->setupPrimitives = setupPrimitives;
                        draw->setupState = setupState;
 
-                       for(int i = 0; i < VERTEX_ATTRIBUTES; i++)
+                       for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
                        {
                                draw->vertexStream[i] = context->input[i].resource;
                                data->input[i] = context->input[i].buffer;
@@ -388,9 +390,16 @@ namespace sw
                                        draw->psDirtyConstB = 0;
                                }
 
-                               PixelProcessor::lockUniformBuffers(data->ps.u);
+                               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++)
@@ -437,12 +446,13 @@ namespace sw
                                        draw->vsDirtyConstB = 0;
                                }
 
-                               if(context->vertexShader->instanceIdDeclared)
+                               if(context->vertexShader->isInstanceIdDeclared())
                                {
                                        data->instanceID = context->instanceID;
                                }
 
-                               VertexProcessor::lockUniformBuffers(data->vs.u);
+                               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
                        {
@@ -451,6 +461,16 @@ namespace sw
                                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)
@@ -603,7 +623,7 @@ namespace sw
 
                                if(draw->stencilBuffer)
                                {
-                                       data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(q * ms, MANAGED);
+                                       data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, q * ms, MANAGED);
                                        data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
                                        data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
                                }
@@ -626,7 +646,16 @@ namespace sw
                        nextDraw++;
                        schedulerMutex.unlock();
 
-                       if(threadCount > 1)
+                       #ifndef NDEBUG
+                       if(threadCount == 1)   // Use main thread for draw execution
+                       {
+                               threadsAwake = 1;
+                               task[0].type = Task::RESUME;
+
+                               taskLoop(0);
+                       }
+                       else
+                       #endif
                        {
                                if(!threadsAwake)
                                {
@@ -638,16 +667,24 @@ namespace sw
                                        resume[0]->signal();
                                }
                        }
-                       else   // Use main thread for draw execution
-                       {
-                               threadsAwake = 1;
-                               task[0].type = Task::RESUME;
-
-                               taskLoop(0);
-                       }
                }
        }
 
+       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;
@@ -715,7 +752,7 @@ namespace sw
                                }
                        }
                }
-       
+
                // Find primitive tasks
                if(currentDraw == nextDraw)
                {
@@ -816,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);
 
@@ -830,7 +867,12 @@ namespace sw
                                        startTick = time;
                                #endif
 
-                               int visible = draw->setupState.rasterizerDiscard ? 0 : setupPrimitives(this, unit, count);
+                               int visible = 0;
+
+                               if(!draw->setupState.rasterizerDiscard)
+                               {
+                                       visible = (this->*setupPrimitives)(unit, count);
+                               }
 
                                primitiveProgress[unit].visible = visible;
                                primitiveProgress[unit].references = clusterCount;
@@ -887,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)
                {
@@ -929,7 +972,7 @@ namespace sw
                                                        }
                                                        break;
                                                case Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
-                                                       atomicAdd((volatile int*)&query->data, pixelProgress[cluster].processedPrimitives);
+                                                       atomicAdd((volatile int*)&query->data, processedPrimitives);
                                                        break;
                                                default:
                                                        break;
@@ -968,7 +1011,7 @@ namespace sw
                                        }
                                }
 
-                               for(int i = 0; i < VERTEX_ATTRIBUTES; i++)
+                               for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
                                {
                                        if(draw.vertexStream[i])
                                        {
@@ -981,8 +1024,25 @@ namespace sw
                                        draw.indexBuffer->unlock();
                                }
 
-                               PixelProcessor::unlockUniformBuffers();
-                               VertexProcessor::unlockUniformBuffers();
+                               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();
@@ -1398,7 +1458,7 @@ namespace sw
                                }
                        }
                        break;
-        case DRAW_QUADLIST:
+               case DRAW_QUADLIST:
                        {
                                unsigned int index = 4 * start / 2;
 
@@ -1408,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;
 
@@ -1421,16 +1481,17 @@ namespace sw
                        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;
 
@@ -1453,7 +1514,7 @@ namespace sw
 
                                if(clipFlagsOr != Clipper::CLIP_FINITE)
                                {
-                                       if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+                                       if(!clipper->clip(polygon, clipFlagsOr, draw))
                                        {
                                                continue;
                                        }
@@ -1470,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;
@@ -1514,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;
 
@@ -1527,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;
@@ -1558,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;
 
@@ -1572,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++;
@@ -1597,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++;
@@ -1622,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;
@@ -1681,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)
                        {
@@ -1703,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;
                                        }
@@ -1733,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)
                        {
@@ -1809,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;
                                        }
@@ -1822,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;
@@ -1834,7 +1894,7 @@ namespace sw
 
                int pts = state.pointSizeRegister;
 
-               if(state.pointSizeRegister != 0xF)
+               if(state.pointSizeRegister != Unused)
                {
                        pSize = v.v[pts].y;
                }
@@ -1860,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;
@@ -1888,29 +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)
-       {
-               return ((v.x > v.w)  << 0) |
-                          ((v.y > v.w)  << 1) |
-                          ((v.z > v.w)  << 2) |
-                          ((v.x < -v.w) << 3) |
-                      ((v.y < -v.w) << 4) |
-                          ((v.z < 0)    << 5) |
-                          Clipper::CLIP_FINITE;   // FIXME: xyz finite
-       }
-
        void Renderer::initializeThreads()
        {
                unitCount = ceilPow2(threadCount);
@@ -1958,7 +2007,7 @@ namespace sw
                                exitThreads = true;
                                resume[thread]->signal();
                                worker[thread]->join();
-                               
+
                                delete worker[thread];
                                worker[thread] = 0;
                                delete resume[thread];
@@ -1966,7 +2015,7 @@ namespace sw
                                delete suspend[thread];
                                suspend[thread] = 0;
                        }
-               
+
                        deallocate(vertexTask[thread]);
                        vertexTask[thread] = 0;
                }
@@ -2093,7 +2142,7 @@ namespace sw
                                return true;
                        }
                }
-       
+
                if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
                {
                        return true;
@@ -2101,7 +2150,7 @@ namespace sw
 
                return false;
        }
-       
+
        void Renderer::updateClipper()
        {
                if(updateClipPlanes)
@@ -2141,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);
        }
 
@@ -2313,6 +2362,54 @@ namespace sw
                }
        }
 
+       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);
@@ -2486,7 +2583,7 @@ namespace sw
        {
                queries.push_back(query);
        }
-       
+
        void Renderer::removeQuery(Query *query)
        {
                queries.remove(query);
@@ -2497,7 +2594,7 @@ namespace sw
                {
                        return threadCount;
                }
-               
+
                int64_t Renderer::getVertexTime(int thread)
                {
                        return vertexTime[thread];
@@ -2507,7 +2604,7 @@ namespace sw
                {
                        return setupTime[thread];
                }
-                       
+
                int64_t Renderer::getPixelTime(int thread)
                {
                        return pixelTime[thread];