sw::exactColorRounding = exactColorRounding;
setRenderTarget(0, 0);
- clipper = new Clipper();
+ clipper = new Clipper(symmetricNormalizedDepth);
+ blitter = new Blitter;
updateViewMatrix = true;
updateBaseMatrix = true;
sync->destruct();
delete clipper;
- clipper = 0;
+ clipper = nullptr;
+
+ delete blitter;
+ blitter = nullptr;
terminateThreads();
delete resumeApp;
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)
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();
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;
draw->vsDirtyConstB = 0;
}
- if(context->vertexShader->instanceIdDeclared)
+ if(context->vertexShader->isInstanceIdDeclared())
{
data->instanceID = context->instanceID;
}
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();
}
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)
{
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;
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);
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;
return;
}
- task->vertexStart = start * 3;
+ task->primitiveStart = start;
task->vertexCount = triangleCount * 3;
- // Note: Quads aren't handled for verticesPerPrimitive, but verticesPerPrimitive is used for transform feedback,
- // which is an OpenGL ES 3.0 feature, and OpenGL ES 3.0 doesn't support quads as a primitive type.
- DrawType type = static_cast<DrawType>(static_cast<unsigned int>(draw->drawType) & 0xF);
- task->verticesPerPrimitive = 1 + (type >= DRAW_LINELIST) + (type >= DRAW_TRIANGLELIST);
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;
if(clipFlagsOr != Clipper::CLIP_FINITE)
{
- if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+ if(!clipper->clip(polygon, clipFlagsOr, draw))
{
continue;
}
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;
for(int i = 0; i < 3; i++)
{
- if(setupLine(renderer, *primitive, *triangle, draw))
+ if(setupLine(*primitive, *triangle, draw))
{
primitive->area = 0.5f * d;
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;
for(int i = 0; i < 3; i++)
{
- if(setupPoint(renderer, *primitive, *triangle, draw))
+ if(setupPoint(*primitive, *triangle, draw))
{
primitive->area = 0.5f * d;
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++;
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++;
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;
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)
{
if(clipFlagsOr != Clipper::CLIP_FINITE)
{
- if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+ if(!clipper->clip(polygon, clipFlagsOr, draw))
{
return false;
}
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)
{
if(clipFlagsOr != Clipper::CLIP_FINITE)
{
- if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+ if(!clipper->clip(polygon, clipFlagsOr, draw))
{
return false;
}
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;
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;
if(clipFlagsOr != Clipper::CLIP_FINITE)
{
- if(!renderer->clipper->clip(polygon, clipFlagsOr, draw))
+ if(!clipper->clip(polygon, clipFlagsOr, draw))
{
return false;
}
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);
}
}
+ 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);