Add SwiftShader source to repo
Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Renderer/SetupProcessor.cpp b/src/Renderer/SetupProcessor.cpp
new file mode 100644
index 0000000..1e737a4
--- /dev/null
+++ b/src/Renderer/SetupProcessor.cpp
@@ -0,0 +1,236 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 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 "SetupProcessor.hpp"
+
+#include "SetupRoutine.hpp"
+#include "Primitive.hpp"
+#include "Polygon.hpp"
+#include "Viewport.hpp"
+#include "Context.hpp"
+#include "Renderer.hpp"
+#include "Constants.hpp"
+#include "Debug.hpp"
+
+namespace sw
+{
+ extern bool complementaryDepthBuffer;
+
+ unsigned int SetupProcessor::States::computeHash()
+ {
+ unsigned int *state = (unsigned int*)this;
+ unsigned int hash = 0;
+
+ for(int i = 0; i < sizeof(States) / 4; i++)
+ {
+ hash ^= state[i];
+ }
+
+ return hash;
+ }
+
+ SetupProcessor::State::State(int i)
+ {
+ memset(this, 0, sizeof(State));
+ }
+
+ bool SetupProcessor::State::operator==(const State &state) const
+ {
+ if(hash != state.hash)
+ {
+ return false;
+ }
+
+ return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
+ }
+
+ SetupProcessor::SetupProcessor(Context *context) : context(context)
+ {
+ routineCache = 0;
+ setRoutineCacheSize(1024);
+ }
+
+ SetupProcessor::~SetupProcessor()
+ {
+ delete routineCache;
+ routineCache = 0;
+ }
+
+ SetupProcessor::State SetupProcessor::update() const
+ {
+ State state;
+
+ state.isDrawPoint = context->isDrawPoint(true);
+ state.isDrawLine = context->isDrawLine(true);
+ state.isDrawTriangle = context->isDrawTriangle(false);
+ state.isDrawSolidTriangle = context->isDrawTriangle(true);
+ state.interpolateDepth = context->depthBufferActive() || context->pixelFogActive() != Context::FOG_NONE;
+ state.perspective = context->perspectiveActive();
+ state.pointSprite = context->pointSpriteActive();
+ state.cullMode = context->cullMode;
+ state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
+ state.slopeDepthBias = slopeDepthBias != 0.0f;
+ state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
+
+ state.positionRegister = Pos;
+ state.pointSizeRegister = 0xF; // No vertex point size
+
+ state.multiSample = context->renderTarget[0]->getMultiSampleCount();
+
+ if(context->vertexShader)
+ {
+ state.positionRegister = context->vertexShader->positionRegister;
+ state.pointSizeRegister = context->vertexShader->pointSizeRegister;
+ }
+ else if(context->pointSizeActive())
+ {
+ state.pointSizeRegister = Pts;
+ }
+
+ for(int interpolant = 0; interpolant < 11; interpolant++)
+ {
+ int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
+
+ for(int component = 0; component < componentCount; component++)
+ {
+ state.gradient[interpolant][component].attribute = 0x3F;
+ state.gradient[interpolant][component].flat = false;
+ state.gradient[interpolant][component].wrap = false;
+ }
+ }
+
+ const bool point = context->isDrawPoint(true);
+ const bool sprite = context->pointSpriteActive();
+ const bool flatShading = (context->shadingMode == Context::SHADING_FLAT) || point;
+
+ if(context->vertexShader && context->pixelShader)
+ {
+ for(int interpolant = 0; interpolant < 10; interpolant++)
+ {
+ for(int component = 0; component < 4; component++)
+ {
+ int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
+
+ if(context->pixelShader->semantic[interpolant][component - project].active())
+ {
+ int input = interpolant;
+ for(int i = 0; i < 12; i++)
+ {
+ if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
+ {
+ input = i;
+ break;
+ }
+ }
+
+ bool flat = point;
+
+ switch(context->pixelShader->semantic[interpolant][component - project].usage)
+ {
+ case ShaderOperation::USAGE_TEXCOORD: flat = point && !sprite; break;
+ case ShaderOperation::USAGE_COLOR: flat = flatShading; break;
+ }
+
+ state.gradient[interpolant][component].attribute = input;
+ state.gradient[interpolant][component].flat = flat;
+ }
+ }
+ }
+ }
+ else if(context->preTransformed && context->pixelShader)
+ {
+ for(int interpolant = 0; interpolant < 10; interpolant++)
+ {
+ for(int component = 0; component < 4; component++)
+ {
+ int index = context->pixelShader->semantic[interpolant][component].index;
+
+ switch(context->pixelShader->semantic[interpolant][component].usage)
+ {
+ case 0xFF:
+ break;
+ case ShaderOperation::USAGE_TEXCOORD:
+ state.gradient[interpolant][component].attribute = T0 + index;
+ state.gradient[interpolant][component].flat = point && !sprite;
+ break;
+ case ShaderOperation::USAGE_COLOR:
+ state.gradient[interpolant][component].attribute = D0 + index;
+ state.gradient[interpolant][component].flat = flatShading;
+ break;
+ default:
+ ASSERT(false);
+ }
+ }
+ }
+ }
+ else if(context->pixelShaderVersion() < 0x0300)
+ {
+ for(int coordinate = 0; coordinate < 8; coordinate++)
+ {
+ for(int component = 0; component < 4; component++)
+ {
+ if(context->textureActive(coordinate, component))
+ {
+ state.texture[coordinate][component].attribute = T0 + coordinate;
+ state.texture[coordinate][component].flat = point && !sprite;
+ state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
+ }
+ }
+ }
+
+ for(int color = 0; color < 2; color++)
+ {
+ for(int component = 0; component < 4; component++)
+ {
+ if(context->colorActive(color, component))
+ {
+ state.color[color][component].attribute = D0 + color;
+ state.color[color][component].flat = flatShading;
+ }
+ }
+ }
+ }
+ else ASSERT(false);
+
+ if(context->fogActive())
+ {
+ state.fog.attribute = Fog;
+ state.fog.flat = point;
+ }
+
+ state.hash = state.computeHash();
+
+ return state;
+ }
+
+ Routine *SetupProcessor::routine(const State &state)
+ {
+ Routine *routine = routineCache->query(state);
+
+ if(!routine)
+ {
+ SetupRoutine *generator = new SetupRoutine(state);
+ generator->generate();
+ routine = generator->getRoutine();
+ delete generator;
+
+ routineCache->add(state, routine);
+ }
+
+ return routine;
+ }
+
+ void SetupProcessor::setRoutineCacheSize(int cacheSize)
+ {
+ delete routineCache;
+ routineCache = new LRUCache<State, Routine>(clamp(cacheSize, 1, 65536));
+ }
+}