void compileTo(VertexArrays& vas) { if (!glBlocks.empty()) throw std::logic_error("Custom code cannot be recorded into a macro"); std::stable_sort(ops.begin(), ops.end()); for (DrawOps::const_iterator op = ops.begin(), end = ops.end(); op != end; ++op) op->compileTo(vas); }
// I really wish I would trust ADL. :| void swap(DrawOpQueue& other) { clipRectStack.swap(other.clipRectStack); std::swap(effectiveRect, other.effectiveRect); std::swap(haveEffectiveRect, other.haveEffectiveRect); ops.swap(other.ops); code.swap(other.code); }
void clear() { // Not sure if Graphics::begin() should implicitly do that. //clipRectStack.clear(); //effectiveRect.reset(); code.clear(); ops.clear(); }
void performDrawOpsAndCode() { // Allows us to make some assumptions. if (ops.empty()) { for (CodeMap::iterator it = code.begin(), end = code.end(); it != end; ++it) it->second(); return; } // Apply Z-Ordering. std::stable_sort(ops.begin(), ops.end()); // We will loop: Drawing DrawOps, execute custom code. // This means if there is no code, we just draw one batch // of DrawOps, so no performance is sacrified. DrawOps::const_iterator current = ops.begin(), last = ops.begin(); CodeMap::const_iterator it = code.begin(); while (true) { if (it == code.end()) // Last or only batch of DrawOps: // Just draw everything. last = ops.end() - 1; else { // There is code waiting: // Only draw up to this Z level. while (last != ops.end() - 1 && (last + 1)->z < it->first) ++last; } if (current <= last) { // Draw DrawOps until next code is due RenderState renderState; while (current < last) { DrawOps::const_iterator next = current + 1; current->perform(renderState, &*next); current = next; } last->perform(renderState, 0); ++current; } // Draw next code, or break if there is none if (it == code.end()) break; else { it->second(); ++it; } } }
void clear() { absoluteTransforms.resize(1); // Important!! Due to all the swapping, the first entry in the list is not necessarily // the base matrix. We need to restore it. absoluteTransforms.front() = scale(1); individualTransforms.resize(1); clipRectStack.clear(); glBlocks.clear(); ops.clear(); }
void scheduleDrawOp(DrawOp op) { if (clipRectStack.clippedWorldAway()) return; #ifdef GOSU_IS_IPHONE // No triangles, no lines supported assert (op.verticesOrBlockIndex == 4); #endif op.renderState.transform = ¤tTransform(); if (const ClipRect* cr = clipRectStack.maybeEffectiveRect()) op.renderState.clipRect = *cr; ops.push_back(op); }
void scheduleGL(std::tr1::function<void()> glBlock, ZPos z) { // TODO: Document this case: Clipped-away GL blocks are *not* being run. if (clipRectStack.clippedWorldAway()) return; int complementOfBlockIndex = ~(int)glBlocks.size(); glBlocks.push_back(glBlock); DrawOp op; op.verticesOrBlockIndex = complementOfBlockIndex; op.renderState.transform = ¤tTransform(); if (const ClipRect* cr = clipRectStack.maybeEffectiveRect()) op.renderState.clipRect = *cr; op.z = z; ops.push_back(op); }
void scheduleDrawOp(DrawOp op, ZPos z) { #ifdef GOSU_IS_IPHONE // No triangles, no lines supported assert (op.usedVertices == 4); #endif if (haveEffectiveRect) { op.clipX = effectiveRect.x; op.clipY = effectiveRect.y; op.clipWidth = effectiveRect.width; op.clipHeight = effectiveRect.height; } else if (!clipRectStack.empty()) // When we have no effect rect but the stack is not empty, we have clipped // the whole world away and don't need to render things. return; op.z = z; ops.push_back(op); }
void performDrawOpsAndCode() { // Apply Z-Ordering. std::stable_sort(ops.begin(), ops.end()); RenderStateManager manager; #ifdef GOSU_IS_IPHONE if (ops.empty()) return; DrawOps::const_iterator current = ops.begin(), last = ops.end() - 1; for (; current != last; ++current) { manager.setRenderState(current->renderState); current->perform(&*(current + 1)); } manager.setRenderState(last->renderState); last->perform(0); #else for (DrawOps::const_iterator current = ops.begin(), last = ops.end(); current != last; ++current) { manager.setRenderState(current->renderState); if (current->verticesOrBlockIndex >= 0) current->perform(0); else { // GL code int blockIndex = ~current->verticesOrBlockIndex; assert (blockIndex >= 0); assert (blockIndex < glBlocks.size()); glBlocks[blockIndex](); manager.enforceAfterUntrustedGL(); } } #endif }
// This retains the current stack of transforms and clippings. void clearQueue() { glBlocks.clear(); ops.clear(); }