From 9425c9224b80873d741543b24d55a066b5bac398 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 27 Feb 2020 20:08:50 -0400 Subject: [PATCH 1/4] Rename internal batched draw code to be more clear --- src/modules/graphics/Deprecations.cpp | 2 +- src/modules/graphics/Font.cpp | 6 +-- src/modules/graphics/Graphics.cpp | 42 ++++++++++---------- src/modules/graphics/Graphics.h | 18 ++++----- src/modules/graphics/Mesh.cpp | 2 +- src/modules/graphics/ParticleSystem.cpp | 2 +- src/modules/graphics/Polyline.cpp | 4 +- src/modules/graphics/SpriteBatch.cpp | 2 +- src/modules/graphics/Text.cpp | 2 +- src/modules/graphics/Texture.cpp | 14 +++---- src/modules/graphics/Video.cpp | 6 +-- src/modules/graphics/opengl/Graphics.cpp | 50 ++++++++++++------------ src/modules/graphics/opengl/Shader.cpp | 10 ++--- src/modules/graphics/opengl/Shader.h | 2 +- src/modules/graphics/wrap_Graphics.cpp | 2 +- 15 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/modules/graphics/Deprecations.cpp b/src/modules/graphics/Deprecations.cpp index ac093a455..9e312accb 100644 --- a/src/modules/graphics/Deprecations.cpp +++ b/src/modules/graphics/Deprecations.cpp @@ -82,7 +82,7 @@ void Deprecations::draw(Graphics *gfx) font.set(gfx->newDefaultFont(9, hinting), Acquire::NORETAIN); } - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); gfx->push(Graphics::STACK_ALL); gfx->reset(); diff --git a/src/modules/graphics/Font.cpp b/src/modules/graphics/Font.cpp index 928d96f7d..099e74a05 100644 --- a/src/modules/graphics/Font.cpp +++ b/src/modules/graphics/Font.cpp @@ -133,7 +133,7 @@ bool Font::loadVolatile() void Font::createTexture() { auto gfx = Module::getInstance(Module::M_GRAPHICS); - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); Texture *texture = nullptr; TextureSize size = {textureWidth, textureHeight}; @@ -645,13 +645,13 @@ void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vectorrequestStreamDraw(streamcmd); + Graphics::BatchedVertexData data = gfx->requestBatchedDraw(streamcmd); GlyphVertex *vertexdata = (GlyphVertex *) data.stream[0]; memcpy(vertexdata, &vertices[cmd.startvertex], sizeof(GlyphVertex) * cmd.vertexcount); diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 7fa8d587f..9c704ed50 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -114,7 +114,7 @@ Graphics::Graphics() , created(false) , active(true) , writingToStencil(false) - , streamBufferState() + , batchedDrawState() , projectionMatrix() , renderTargetSwitchCount(0) , drawCalls(0) @@ -157,9 +157,9 @@ Graphics::~Graphics() defaultFont.set(nullptr); - delete streamBufferState.vb[0]; - delete streamBufferState.vb[1]; - delete streamBufferState.indexBuffer; + delete batchedDrawState.vb[0]; + delete batchedDrawState.vb[1]; + delete batchedDrawState.indexBuffer; for (int i = 0; i < (int) ShaderStage::STAGE_MAX_ENUM; i++) cachedShaderStages[i].clear(); @@ -691,7 +691,7 @@ void Graphics::setRenderTargets(const RenderTargets &rts) int w = firsttex->getWidth(firsttarget.mipmap); int h = firsttex->getHeight(firsttarget.mipmap); - flushStreamDraws(); + flushBatchedDraws(); if (rts.depthStencil.texture == nullptr && rts.temporaryRTFlags != 0) { @@ -741,7 +741,7 @@ void Graphics::setRenderTarget() if (state.renderTargets.colors.empty() && state.renderTargets.depthStencil.texture == nullptr) return; - flushStreamDraws(); + flushBatchedDraws(); setRenderTargetsInternal(RenderTargets(), width, height, pixelWidth, pixelHeight, isGammaCorrect()); state.renderTargets = RenderTargetsStrongRef(); @@ -986,11 +986,11 @@ void Graphics::captureScreenshot(const ScreenshotInfo &info) pendingScreenshotCallbacks.push_back(info); } -Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand &cmd) +Graphics::BatchedVertexData Graphics::requestBatchedDraw(const BatchedDrawCommand &cmd) { using namespace vertex; - StreamBufferState &state = streamBufferState; + BatchedDrawState &state = batchedDrawState; bool shouldflush = false; bool shouldresize = false; @@ -1052,7 +1052,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & if (shouldflush || shouldresize) { - flushStreamDraws(); + flushBatchedDraws(); state.primitiveMode = cmd.primitiveMode; state.formats[0] = cmd.formats[0]; @@ -1096,7 +1096,7 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & state.indexBufferMap.data += reqIndexSize; } - StreamVertexData d; + BatchedVertexData d; for (int i = 0; i < 2; i++) { @@ -1120,11 +1120,11 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawCommand & return d; } -void Graphics::flushStreamDraws() +void Graphics::flushBatchedDraws() { using namespace vertex; - auto &sbstate = streamBufferState; + auto &sbstate = batchedDrawState; if (sbstate.vertexCount == 0 && sbstate.indexCount == 0) return; @@ -1195,15 +1195,15 @@ void Graphics::flushStreamDraws() if (attributes.isEnabled(ATTRIB_COLOR)) setColor(nc); - streamBufferState.vertexCount = 0; - streamBufferState.indexCount = 0; + batchedDrawState.vertexCount = 0; + batchedDrawState.indexCount = 0; } -void Graphics::flushStreamDrawsGlobal() +void Graphics::flushBatchedDrawsGlobal() { Graphics *instance = getInstance(M_GRAPHICS); if (instance != nullptr) - instance->flushStreamDraws(); + instance->flushBatchedDraws(); } /** @@ -1270,13 +1270,13 @@ void Graphics::points(const Vector2 *positions, const Colorf *colors, size_t num const Matrix4 &t = getTransform(); bool is2D = t.isAffine2DTransform(); - StreamDrawCommand cmd; + BatchedDrawCommand cmd; cmd.primitiveMode = PRIMITIVE_POINTS; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = vertex::CommonFormat::RGBAub; cmd.vertexCount = (int) numpoints; - StreamVertexData data = requestStreamDraw(cmd); + BatchedVertexData data = requestBatchedDraw(cmd); if (is2D) t.transformXY((Vector2 *) data.stream[0], positions, cmd.vertexCount); @@ -1566,13 +1566,13 @@ void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count, bool const Matrix4 &t = getTransform(); bool is2D = t.isAffine2DTransform(); - StreamDrawCommand cmd; + BatchedDrawCommand cmd; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = vertex::CommonFormat::RGBAub; cmd.indexMode = vertex::TriangleIndexMode::FAN; cmd.vertexCount = (int)count - (skipLastFilledVertex ? 1 : 0); - StreamVertexData data = requestStreamDraw(cmd); + BatchedVertexData data = requestBatchedDraw(cmd); if (is2D) t.transformXY((Vector2 *) data.stream[0], coords, cmd.vertexCount); @@ -1598,7 +1598,7 @@ Graphics::Stats Graphics::getStats() const getAPIStats(stats.shaderSwitches); stats.drawCalls = drawCalls; - if (streamBufferState.vertexCount > 0) + if (batchedDrawState.vertexCount > 0) stats.drawCalls++; stats.renderTargetSwitches = renderTargetSwitchCount; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 119ef5ff8..6068d8560 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -253,7 +253,7 @@ public: {} }; - struct StreamDrawCommand + struct BatchedDrawCommand { PrimitiveType primitiveMode = PRIMITIVE_TRIANGLES; vertex::CommonFormat formats[2]; @@ -262,14 +262,14 @@ public: Texture *texture = nullptr; Shader::StandardShader standardShaderType = Shader::STANDARD_DEFAULT; - StreamDrawCommand() + BatchedDrawCommand() { // VS2013 can't initialize arrays in the above manner... formats[1] = formats[0] = vertex::CommonFormat::NONE; } }; - struct StreamVertexData + struct BatchedVertexData { void *stream[2]; }; @@ -822,10 +822,10 @@ public: virtual void draw(const DrawIndexedCommand &cmd) = 0; virtual void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) = 0; - void flushStreamDraws(); - StreamVertexData requestStreamDraw(const StreamDrawCommand &command); + void flushBatchedDraws(); + BatchedVertexData requestBatchedDraw(const BatchedDrawCommand &command); - static void flushStreamDrawsGlobal(); + static void flushBatchedDrawsGlobal(); virtual Shader::Language getShaderLanguageTarget() const = 0; const DefaultShaderCode &getCurrentDefaultShaderCode() const; @@ -911,7 +911,7 @@ protected: SamplerState defaultSamplerState = SamplerState(); }; - struct StreamBufferState + struct BatchedDrawState { StreamBuffer *vb[2]; StreamBuffer *indexBuffer = nullptr; @@ -926,7 +926,7 @@ protected: StreamBuffer::MapInfo vbMap[2]; StreamBuffer::MapInfo indexBufferMap = StreamBuffer::MapInfo(); - StreamBufferState() + BatchedDrawState() { vb[0] = vb[1] = nullptr; formats[0] = formats[1] = vertex::CommonFormat::NONE; @@ -979,7 +979,7 @@ protected: std::vector pendingScreenshotCallbacks; - StreamBufferState streamBufferState; + BatchedDrawState batchedDrawState; std::vector transformStack; Matrix4 projectionMatrix; diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 7c3a42c95..29183d70a 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -584,7 +584,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (instancecount > 1 && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING]) throw love::Exception("Instancing is not supported on this system."); - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 35cb48979..fac406e96 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -1029,7 +1029,7 @@ void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m) if (pCount == 0 || texture.get() == nullptr || pMem == nullptr || buffer == nullptr) return; - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); diff --git a/src/modules/graphics/Polyline.cpp b/src/modules/graphics/Polyline.cpp index da1397b42..5698a9dd3 100644 --- a/src/modules/graphics/Polyline.cpp +++ b/src/modules/graphics/Polyline.cpp @@ -390,13 +390,13 @@ void Polyline::draw(love::graphics::Graphics *gfx) { const Vector2 *verts = vertices + vertex_start; - Graphics::StreamDrawCommand cmd; + Graphics::BatchedDrawCommand cmd; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = vertex::CommonFormat::RGBAub; cmd.indexMode = triangle_mode; cmd.vertexCount = std::min(maxvertices, total_vertex_count - vertex_start); - Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd); + Graphics::BatchedVertexData data = gfx->requestBatchedDraw(cmd); if (is2D) t.transformXY((Vector2 *) data.stream[0], verts, cmd.vertexCount); diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index ce264b019..d62729d32 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -301,7 +301,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) if (next == 0) return; - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); if (texture.get()) { diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 180862ed3..1ea624200 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -246,7 +246,7 @@ void Text::draw(Graphics *gfx, const Matrix4 &m) if (vertex_buffer == nullptr || draw_commands.empty()) return; - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index e85906e34..0200e58ef 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -324,14 +324,14 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) const Matrix4 &tm = gfx->getTransform(); bool is2D = tm.isAffine2DTransform(); - Graphics::StreamDrawCommand cmd; + Graphics::BatchedDrawCommand cmd; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STf_RGBAub; cmd.indexMode = TriangleIndexMode::QUADS; cmd.vertexCount = 4; cmd.texture = this; - Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd); + Graphics::BatchedVertexData data = gfx->requestBatchedDraw(cmd); Matrix4 t(tm, localTransform); @@ -381,7 +381,7 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) Matrix4 t(tm, m); - Graphics::StreamDrawCommand cmd; + Graphics::BatchedDrawCommand cmd; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::STPf_RGBAub; cmd.indexMode = TriangleIndexMode::QUADS; @@ -389,7 +389,7 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) cmd.texture = this; cmd.standardShaderType = Shader::STANDARD_ARRAY; - Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd); + Graphics::BatchedVertexData data = gfx->requestBatchedDraw(cmd); if (is2D) t.transformXY((Vector2 *) data.stream[0], q->getVertexPositions(), 4); @@ -464,7 +464,7 @@ void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap if (isPixelFormatCompressed(d->getFormat()) && (rect.x != 0 || rect.y != 0 || rect.w != mipw || rect.h != miph)) throw love::Exception("Compressed textures only support replacing the entire Texture."); - Graphics::flushStreamDrawsGlobal(); + Graphics::flushBatchedDrawsGlobal(); uploadImageData(d, mipmap, slice, x, y); @@ -481,7 +481,7 @@ void Texture::replacePixels(const void *data, size_t size, int slice, int mipmap if (gfx != nullptr && gfx->isRenderTargetActive(this)) return; - Graphics::flushStreamDrawsGlobal(); + Graphics::flushBatchedDrawsGlobal(); uploadByteData(format, data, size, mipmap, slice, rect, nullptr); @@ -631,7 +631,7 @@ void Texture::setSamplerState(const SamplerState &s) if (s.depthSampleMode.hasValue && !isPixelFormatDepth(format)) throw love::Exception("Only depth textures can have a depth sample compare mode."); - Graphics::flushStreamDrawsGlobal(); + Graphics::flushBatchedDrawsGlobal(); samplerState = s; diff --git a/src/modules/graphics/Video.cpp b/src/modules/graphics/Video.cpp index 9f2df9c5b..170ff08b2 100644 --- a/src/modules/graphics/Video.cpp +++ b/src/modules/graphics/Video.cpp @@ -120,14 +120,14 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) Matrix4 t(tm, m); - Graphics::StreamDrawCommand cmd; + Graphics::BatchedDrawCommand cmd; cmd.formats[0] = vertex::getSinglePositionFormat(is2D); cmd.formats[1] = vertex::CommonFormat::STf_RGBAub; cmd.indexMode = vertex::TriangleIndexMode::QUADS; cmd.vertexCount = 4; cmd.standardShaderType = Shader::STANDARD_VIDEO; - Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd); + Graphics::BatchedVertexData data = gfx->requestBatchedDraw(cmd); if (is2D) t.transformXY((Vector2 *) data.stream[0], vertices, 4); @@ -148,7 +148,7 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) if (Shader::current != nullptr) Shader::current->setVideoTextures(textures[0], textures[1], textures[2]); - gfx->flushStreamDraws(); + gfx->flushBatchedDraws(); } void Video::update() diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 7a700420a..ffde86c90 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -234,13 +234,13 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b setDebug(isDebugEnabled()); - if (streamBufferState.vb[0] == nullptr) + if (batchedDrawState.vb[0] == nullptr) { // Initial sizes that should be good enough for most cases. It will // resize to fit if needed, later. - streamBufferState.vb[0] = CreateStreamBuffer(BUFFER_VERTEX, 1024 * 1024 * 1); - streamBufferState.vb[1] = CreateStreamBuffer(BUFFER_VERTEX, 256 * 1024 * 1); - streamBufferState.indexBuffer = CreateStreamBuffer(BUFFER_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); + batchedDrawState.vb[0] = CreateStreamBuffer(BUFFER_VERTEX, 1024 * 1024 * 1); + batchedDrawState.vb[1] = CreateStreamBuffer(BUFFER_VERTEX, 256 * 1024 * 1); + batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFER_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); } // Reload all volatile objects. @@ -293,7 +293,7 @@ void Graphics::unSetMode() if (!isCreated()) return; - flushStreamDraws(); + flushBatchedDraws(); // Unload all volatile objects. These must be reloaded after the display // mode change. @@ -321,7 +321,7 @@ void Graphics::unSetMode() void Graphics::setActive(bool enable) { - flushStreamDraws(); + flushBatchedDraws(); // Make sure all pending OpenGL commands have fully executed before // returning, when going from active to inactive. This is required on iOS. @@ -505,7 +505,7 @@ void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int w, int h, OpenGL::TempDebugGroup debuggroup("setRenderTargets"); - flushStreamDraws(); + flushBatchedDraws(); endPass(); bool iswindow = rts.getFirstTarget().texture == nullptr; @@ -621,7 +621,7 @@ void Graphics::endPass() void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth) { if (c.hasValue || stencil.hasValue || depth.hasValue) - flushStreamDraws(); + flushBatchedDraws(); GLbitfield flags = 0; @@ -678,7 +678,7 @@ void Graphics::clear(const std::vector &colors, OptionalInt sten return; } - flushStreamDraws(); + flushBatchedDraws(); bool drawbuffersmodified = false; ncolors = std::min(ncolors, ncolorRTs); @@ -754,7 +754,7 @@ void Graphics::clear(const std::vector &colors, OptionalInt sten void Graphics::discard(const std::vector &colorbuffers, bool depthstencil) { - flushStreamDraws(); + flushBatchedDraws(); discard(OpenGL::FRAMEBUFFER_ALL, colorbuffers, depthstencil); } @@ -935,7 +935,7 @@ void Graphics::present(void *screenshotCallbackData) deprecations.draw(this); - flushStreamDraws(); + flushBatchedDraws(); endPass(); gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, gl.getDefaultFBO()); @@ -1038,9 +1038,9 @@ void Graphics::present(void *screenshotCallbackData) glBindRenderbuffer(GL_RENDERBUFFER, info.info.uikit.colorbuffer); #endif - for (StreamBuffer *buffer : streamBufferState.vb) + for (StreamBuffer *buffer : batchedDrawState.vb) buffer->nextFrame(); - streamBufferState.indexBuffer->nextFrame(); + batchedDrawState.indexBuffer->nextFrame(); auto window = getInstance(M_WINDOW); if (window != nullptr) @@ -1068,7 +1068,7 @@ void Graphics::present(void *screenshotCallbackData) void Graphics::setScissor(const Rect &rect) { - flushStreamDraws(); + flushBatchedDraws(); DisplayState &state = states.back(); @@ -1093,7 +1093,7 @@ void Graphics::setScissor(const Rect &rect) void Graphics::setScissor() { if (states.back().scissor) - flushStreamDraws(); + flushBatchedDraws(); states.back().scissor = false; @@ -1111,7 +1111,7 @@ void Graphics::drawToStencilBuffer(StencilAction action, int value) else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat()))) throw love::Exception("Drawing to the stencil buffer with a render target active requires either stencil=true or a custom stencil-type texture to be used, in setRenderTarget."); - flushStreamDraws(); + flushBatchedDraws(); writingToStencil = true; @@ -1156,7 +1156,7 @@ void Graphics::stopDrawToStencilBuffer() if (!writingToStencil) return; - flushStreamDraws(); + flushBatchedDraws(); writingToStencil = false; @@ -1174,7 +1174,7 @@ void Graphics::setStencilTest(CompareMode compare, int value) DisplayState &state = states.back(); if (state.stencilCompare != compare || state.stencilTestValue != value) - flushStreamDraws(); + flushBatchedDraws(); state.stencilCompare = compare; state.stencilTestValue = value; @@ -1211,7 +1211,7 @@ void Graphics::setDepthMode(CompareMode compare, bool write) DisplayState &state = states.back(); if (state.depthTest != compare || state.depthWrite != write) - flushStreamDraws(); + flushBatchedDraws(); state.depthTest = compare; state.depthWrite = write; @@ -1233,7 +1233,7 @@ void Graphics::setFrontFaceWinding(vertex::Winding winding) DisplayState &state = states.back(); if (state.winding != winding) - flushStreamDraws(); + flushBatchedDraws(); state.winding = winding; @@ -1255,7 +1255,7 @@ void Graphics::setColor(Colorf c) void Graphics::setColorMask(ColorChannelMask mask) { - flushStreamDraws(); + flushBatchedDraws(); glColorMask(mask.r, mask.g, mask.b, mask.a); states.back().colorMask = mask; @@ -1264,7 +1264,7 @@ void Graphics::setColorMask(ColorChannelMask mask) void Graphics::setBlendState(const BlendState &blend) { if (!(blend == states.back().blend)) - flushStreamDraws(); + flushBatchedDraws(); if (blend.operationRGB == BLENDOP_MAX || blend.operationA == BLENDOP_MAX || blend.operationRGB == BLENDOP_MIN || blend.operationA == BLENDOP_MIN) @@ -1294,8 +1294,8 @@ void Graphics::setBlendState(const BlendState &blend) void Graphics::setPointSize(float size) { - if (streamBufferState.primitiveMode == PRIMITIVE_POINTS) - flushStreamDraws(); + if (batchedDrawState.primitiveMode == PRIMITIVE_POINTS) + flushBatchedDraws(); gl.setPointSize(size * getCurrentDPIScale()); states.back().pointSize = size; @@ -1307,7 +1307,7 @@ void Graphics::setWireframe(bool enable) if (GLAD_ES_VERSION_2_0) return; - flushStreamDraws(); + flushBatchedDraws(); glPolygonMode(GL_FRONT_AND_BACK, enable ? GL_LINE : GL_FILL); states.back().wireframe = enable; diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index e57f918f3..84cef6f69 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -428,7 +428,7 @@ void Shader::attach() { if (current != this) { - Graphics::flushStreamDrawsGlobal(); + Graphics::flushBatchedDrawsGlobal(); gl.useProgram(program); current = this; @@ -479,7 +479,7 @@ void Shader::updateUniform(const UniformInfo *info, int count, bool internalupda } if (!internalupdate) - flushStreamDraws(); + flushBatchedDraws(); int location = info->location; UniformType type = info->baseType; @@ -577,7 +577,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex bool shaderactive = current == this; if (!internalUpdate && shaderactive) - flushStreamDraws(); + flushBatchedDraws(); count = std::min(count, info->count); @@ -643,10 +643,10 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex } } -void Shader::flushStreamDraws() const +void Shader::flushBatchedDraws() const { if (current == this) - Graphics::flushStreamDrawsGlobal(); + Graphics::flushBatchedDrawsGlobal(); } bool Shader::hasUniform(const std::string &name) const diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 8681ca5b1..868563970 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -90,7 +90,7 @@ private: TextureType getUniformTextureType(GLenum type) const; bool isDepthTextureType(GLenum type) const; - void flushStreamDraws() const; + void flushBatchedDraws() const; // Get any warnings or errors generated only by the shader program object. std::string getProgramWarnings() const; diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 981d7666c..a801f6594 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3029,7 +3029,7 @@ int w_polygon(lua_State *L) int w_flushBatch(lua_State *) { - instance()->flushStreamDraws(); + instance()->flushBatchedDraws(); return 0; } From b95788c1041fa098eafab1f20280df88ba1740c4 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 27 Feb 2020 20:19:55 -0400 Subject: [PATCH 2/4] Shader:send now returns false if the uniform doesn't exist It also returns false if the uniform exists but was optimized out by the shader compiler. Previously it would cause a Lua error in both situations. --- src/modules/graphics/wrap_Shader.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/modules/graphics/wrap_Shader.cpp b/src/modules/graphics/wrap_Shader.cpp index 2c34727b0..44badcb0d 100644 --- a/src/modules/graphics/wrap_Shader.cpp +++ b/src/modules/graphics/wrap_Shader.cpp @@ -411,14 +411,18 @@ int w_Shader_send(lua_State *L) const Shader::UniformInfo *info = shader->getUniformInfo(name); if (info == nullptr) - return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name); + { + luax_pushboolean(L, false); + return 1; + } - int startidx = 3; - - if (luax_istype(L, startidx, Data::type)) - return w_Shader_sendData(L, startidx, shader, info, false); + if (luax_istype(L, 3, Data::type)) + w_Shader_sendData(L, 3, shader, info, false); else - return w_Shader_sendLuaValues(L, startidx, shader, info, name); + w_Shader_sendLuaValues(L, 3, shader, info, name); + + luax_pushboolean(L, true); + return 1; } int w_Shader_sendColors(lua_State *L) @@ -428,15 +432,21 @@ int w_Shader_sendColors(lua_State *L) const Shader::UniformInfo *info = shader->getUniformInfo(name); if (info == nullptr) - return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name); + { + luax_pushboolean(L, false); + return 1; + } if (info->baseType != Shader::UNIFORM_FLOAT || info->components < 3) return luaL_error(L, "sendColor can only be used on vec3 or vec4 uniforms."); if (luax_istype(L, 3, Data::type)) - return w_Shader_sendData(L, 3, shader, info, true); + w_Shader_sendData(L, 3, shader, info, true); else - return w_Shader_sendFloats(L, 3, shader, info, true); + w_Shader_sendFloats(L, 3, shader, info, true); + + luax_pushboolean(L, true); + return 1; } int w_Shader_hasUniform(lua_State *L) From e71f27c65df42fbd0a1a67a76f2e37213a3a4812 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 28 Feb 2020 21:54:03 -0400 Subject: [PATCH 3/4] Move Lua wrapper code for Variants out of the Variant class file. --- src/common/Object.h | 14 +++ src/common/Variant.cpp | 157 +------------------------- src/common/Variant.h | 7 +- src/common/runtime.cpp | 154 +++++++++++++++++++++++++ src/common/runtime.h | 29 +++-- src/love.cpp | 4 +- src/modules/event/Event.cpp | 40 ------- src/modules/event/Event.h | 3 - src/modules/event/wrap_Event.cpp | 45 ++++++-- src/modules/event/wrap_Event.h | 1 + src/modules/thread/Channel.h | 7 +- src/modules/thread/LuaThread.cpp | 3 +- src/modules/thread/wrap_Channel.cpp | 10 +- src/modules/thread/wrap_Channel.h | 1 + src/modules/thread/wrap_LuaThread.cpp | 2 +- src/modules/thread/wrap_LuaThread.h | 1 + 16 files changed, 237 insertions(+), 241 deletions(-) diff --git a/src/common/Object.h b/src/common/Object.h index 6d91f316b..3e5c94104 100644 --- a/src/common/Object.h +++ b/src/common/Object.h @@ -78,6 +78,20 @@ private: }; // Object +/** + * Structure wrapping an object and its associated Type instance. This is used + * for storing everything necessary to identify an object's properties in + * environments where the Type is not easily obtained otherwise, for example in + * a Lua state. + **/ +struct Proxy +{ + // Holds type information (see types.h). + love::Type *type; + + // Pointer to the actual object. + Object *object; +}; enum class Acquire { diff --git a/src/common/Variant.cpp b/src/common/Variant.cpp index c1cb763d3..5c6c01dc6 100644 --- a/src/common/Variant.cpp +++ b/src/common/Variant.cpp @@ -26,25 +26,13 @@ namespace love { -static Proxy *tryextractproxy(lua_State *L, int idx) -{ - Proxy *u = (Proxy *)lua_touserdata(L, idx); - - if (u == nullptr || u->type == nullptr) - return nullptr; - - // We could get rid of the dynamic_cast for more performance, but it would - // be less safe... - if (dynamic_cast(u->object) != nullptr) - return u; - - return nullptr; -} +Variant::Variant(Type vtype) + : type(vtype) +{} Variant::Variant() : type(NIL) -{ -} +{} Variant::Variant(bool boolean) : type(BOOLEAN) @@ -152,141 +140,4 @@ Variant &Variant::operator = (const Variant &v) return *this; } -Variant Variant::fromLua(lua_State *L, int n, bool allowuserdata, std::set *tableSet) -{ - size_t len; - const char *str; - Proxy *p = nullptr; - - if (n < 0) // Fix the stack position, we might modify it later - n += lua_gettop(L) + 1; - - switch (lua_type(L, n)) - { - case LUA_TBOOLEAN: - return Variant(luax_toboolean(L, n)); - case LUA_TNUMBER: - return Variant(lua_tonumber(L, n)); - case LUA_TSTRING: - str = lua_tolstring(L, n, &len); - return Variant(str, len); - case LUA_TLIGHTUSERDATA: - return Variant(lua_touserdata(L, n)); - case LUA_TUSERDATA: - if (!allowuserdata) - { - luax_typerror(L, n, "copyable Lua value"); - return Variant(); - } - p = tryextractproxy(L, n); - if (p != nullptr) - return Variant(p->type, p->object); - else - { - luax_typerror(L, n, "love type"); - return Variant(); - } - case LUA_TNIL: - return Variant(); - case LUA_TTABLE: - { - bool success = true; - std::set topTableSet; - - // We can use a pointer to a stack-allocated variable because it's - // never used after the stack-allocated variable is destroyed. - if (tableSet == nullptr) - tableSet = &topTableSet; - - // Now make sure this table wasn't already serialised - const void *tablePointer = lua_topointer(L, n); - { - auto result = tableSet->insert(tablePointer); - if (!result.second) // insertion failed - throw love::Exception("Cycle detected in table"); - } - - SharedTable *table = new SharedTable(); - - size_t len = luax_objlen(L, -1); - if (len > 0) - table->pairs.reserve(len); - - lua_pushnil(L); - - while (lua_next(L, n)) - { - table->pairs.emplace_back(fromLua(L, -2, allowuserdata, tableSet), fromLua(L, -1, allowuserdata, tableSet)); - lua_pop(L, 1); - - const auto &p = table->pairs.back(); - if (p.first.getType() == UNKNOWN || p.second.getType() == UNKNOWN) - { - success = false; - break; - } - } - - // And remove the table from the set again - tableSet->erase(tablePointer); - - if (success) - return Variant(table); - else - table->release(); - } - break; - } - - Variant v; - v.type = UNKNOWN; - return v; -} - -void Variant::toLua(lua_State *L) const -{ - switch (type) - { - case BOOLEAN: - lua_pushboolean(L, data.boolean); - break; - case NUMBER: - lua_pushnumber(L, data.number); - break; - case STRING: - lua_pushlstring(L, data.string->str, data.string->len); - break; - case SMALLSTRING: - lua_pushlstring(L, data.smallstring.str, data.smallstring.len); - break; - case LUSERDATA: - lua_pushlightuserdata(L, data.userdata); - break; - case LOVEOBJECT: - luax_pushtype(L, *data.objectproxy.type, data.objectproxy.object); - break; - case TABLE: - { - std::vector> &table = data.table->pairs; - int tsize = (int) table.size(); - - lua_createtable(L, 0, tsize); - - for (int i = 0; i < tsize; ++i) - { - std::pair &kv = table[i]; - kv.first.toLua(L); - kv.second.toLua(L); - lua_settable(L, -3); - } - - break; - } - case NIL: - default: - lua_pushnil(L); - break; - } -} - } // love diff --git a/src/common/Variant.h b/src/common/Variant.h index 995df28b7..f7df8f686 100644 --- a/src/common/Variant.h +++ b/src/common/Variant.h @@ -22,14 +22,12 @@ #define LOVE_VARIANT_H #include "common/config.h" -#include "common/runtime.h" #include "common/Object.h" #include "common/int.h" #include #include #include -#include namespace love { @@ -112,11 +110,12 @@ public: Type getType() const { return type; } const Data &getData() const { return data; } - static Variant fromLua(lua_State *L, int n, bool allowuserdata = true, std::set *tableSet = nullptr); - void toLua(lua_State *L) const; + static Variant unknown() { return Variant(UNKNOWN); } private: + Variant(Type vtype); + Type type; Data data; diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index befeb4bb8..7b90b37f6 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -661,6 +661,160 @@ bool luax_istype(lua_State *L, int idx, love::Type &type) return false; } +static Proxy *tryextractproxy(lua_State *L, int idx) +{ + Proxy *u = (Proxy *)lua_touserdata(L, idx); + + if (u == nullptr || u->type == nullptr) + return nullptr; + + // We could get rid of the dynamic_cast for more performance, but it would + // be less safe... + if (dynamic_cast(u->object) != nullptr) + return u; + + return nullptr; +} + +Variant luax_checkvariant(lua_State *L, int n, bool allowuserdata, std::set *tableSet) +{ + size_t len; + const char *str; + Proxy *p = nullptr; + + if (n < 0) // Fix the stack position, we might modify it later + n += lua_gettop(L) + 1; + + switch (lua_type(L, n)) + { + case LUA_TBOOLEAN: + return Variant(luax_toboolean(L, n)); + case LUA_TNUMBER: + return Variant(lua_tonumber(L, n)); + case LUA_TSTRING: + str = lua_tolstring(L, n, &len); + return Variant(str, len); + case LUA_TLIGHTUSERDATA: + return Variant(lua_touserdata(L, n)); + case LUA_TUSERDATA: + if (!allowuserdata) + { + luax_typerror(L, n, "copyable Lua value"); + return Variant(); + } + p = tryextractproxy(L, n); + if (p != nullptr) + return Variant(p->type, p->object); + else + { + luax_typerror(L, n, "love type"); + return Variant(); + } + case LUA_TNIL: + return Variant(); + case LUA_TTABLE: + { + bool success = true; + std::set topTableSet; + + // We can use a pointer to a stack-allocated variable because it's + // never used after the stack-allocated variable is destroyed. + if (tableSet == nullptr) + tableSet = &topTableSet; + + // Now make sure this table wasn't already serialised + const void *tablePointer = lua_topointer(L, n); + { + auto result = tableSet->insert(tablePointer); + if (!result.second) // insertion failed + throw love::Exception("Cycle detected in table"); + } + + Variant::SharedTable *table = new Variant::SharedTable(); + + size_t len = luax_objlen(L, -1); + if (len > 0) + table->pairs.reserve(len); + + lua_pushnil(L); + + while (lua_next(L, n)) + { + table->pairs.emplace_back( + luax_checkvariant(L, -2, allowuserdata, tableSet), + luax_checkvariant(L, -1, allowuserdata, tableSet) + ); + lua_pop(L, 1); + + const auto &p = table->pairs.back(); + if (p.first.getType() == Variant::UNKNOWN || p.second.getType() == Variant::UNKNOWN) + { + success = false; + break; + } + } + + // And remove the table from the set again + tableSet->erase(tablePointer); + + if (success) + return Variant(table); + else + table->release(); + } + break; + } + + return Variant::unknown(); +} + +void luax_pushvariant(lua_State *L, const Variant &v) +{ + const Variant::Data &data = v.getData(); + switch (v.getType()) + { + case Variant::BOOLEAN: + lua_pushboolean(L, data.boolean); + break; + case Variant::NUMBER: + lua_pushnumber(L, data.number); + break; + case Variant::STRING: + lua_pushlstring(L, data.string->str, data.string->len); + break; + case Variant::SMALLSTRING: + lua_pushlstring(L, data.smallstring.str, data.smallstring.len); + break; + case Variant::LUSERDATA: + lua_pushlightuserdata(L, data.userdata); + break; + case Variant::LOVEOBJECT: + luax_pushtype(L, *data.objectproxy.type, data.objectproxy.object); + break; + case Variant::TABLE: + { + std::vector> &table = data.table->pairs; + int tsize = (int) table.size(); + + lua_createtable(L, 0, tsize); + + for (int i = 0; i < tsize; ++i) + { + std::pair &kv = table[i]; + luax_pushvariant(L, kv.first); + luax_pushvariant(L, kv.second); + lua_settable(L, -3); + } + + break; + } + case Variant::NIL: + default: + lua_pushnil(L); + break; + } +} + int luax_getfunction(lua_State *L, const char *mod, const char *fn) { lua_getglobal(L, "love"); diff --git a/src/common/runtime.h b/src/common/runtime.h index c3e4574e5..44f6e4cd7 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -24,6 +24,8 @@ // LOVE #include "config.h" #include "types.h" +#include "Object.h" +#include "Variant.h" #include "deprecation.h" // Lua @@ -37,12 +39,12 @@ extern "C" { // C++ #include #include +#include namespace love { // Forward declarations. -class Object; class Module; class Reference; @@ -59,21 +61,6 @@ enum Registry REGISTRY_OBJECTS }; -/** - * This structure wraps all Lua-exposed objects. It exists in the - * Lua state as a full userdata (so we can catch __gc "events"), - * though the Object it refers to is light userdata in the sense - * that it is not allocated by the Lua VM. - **/ -struct Proxy -{ - // Holds type information (see types.h). - love::Type *type; - - // Pointer to the actual object. - Object *object; -}; - /** * A Module with Lua wrapper functions and other data. **/ @@ -365,6 +352,16 @@ void luax_pushtype(lua_State *L, StrongRef &object) **/ void luax_rawnewtype(lua_State *L, love::Type &type, love::Object *object); +/** + * Stores the value at the given index on the stack into a Variant object. + */ +Variant luax_checkvariant(lua_State *L, int idx, bool allowuserdata = true, std::set *tableSet = nullptr); + +/** + * Pushes the contents of the given Variant index onto the stack. + */ +void luax_pushvariant(lua_State *L, const Variant &v); + /** * Checks whether the value at idx is a certain type. * @param L The Lua state. diff --git a/src/love.cpp b/src/love.cpp index 9057167b5..3c4e729df 100644 --- a/src/love.cpp +++ b/src/love.cpp @@ -205,7 +205,7 @@ static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &res } // Set love.restart = restartvalue, and clear restartvalue. - restartvalue.toLua(L); + love::luax_pushvariant(L, restartvalue); lua_setfield(L, -2, "restart"); restartvalue = love::Variant(); @@ -240,7 +240,7 @@ static DoneAction runlove(int argc, char **argv, int &retval, love::Variant &res // Disallow userdata (love objects) from being referenced by the restart // value. if (retidx < lua_gettop(L)) - restartvalue = love::Variant::fromLua(L, retidx + 1, false); + restartvalue = love::luax_checkvariant(L, retidx + 1, false); } lua_close(L); diff --git a/src/modules/event/Event.cpp b/src/modules/event/Event.cpp index a0ed327b5..8f8d82f9e 100644 --- a/src/modules/event/Event.cpp +++ b/src/modules/event/Event.cpp @@ -38,46 +38,6 @@ Message::~Message() { } -int Message::toLua(lua_State *L) -{ - luax_pushstring(L, name); - - for (const Variant &v : args) - v.toLua(L); - - return (int) args.size() + 1; -} - -Message *Message::fromLua(lua_State *L, int n) -{ - std::string name = luax_checkstring(L, n); - std::vector vargs; - - int count = lua_gettop(L) - n; - n++; - - Variant varg; - - for (int i = 0; i < count; i++) - { - if (lua_isnoneornil(L, n+i)) - break; - - luax_catchexcept(L, [&]() { - vargs.push_back(Variant::fromLua(L, n+i)); - }); - - if (vargs.back().getType() == Variant::UNKNOWN) - { - vargs.clear(); - luaL_error(L, "Argument %d can't be stored safely\nExpected boolean, number, string or userdata.", n+i); - return nullptr; - } - } - - return new Message(name, vargs); -} - Event::~Event() { } diff --git a/src/modules/event/Event.h b/src/modules/event/Event.h index 3de15f7a6..52583a877 100644 --- a/src/modules/event/Event.h +++ b/src/modules/event/Event.h @@ -46,9 +46,6 @@ public: Message(const std::string &name, const std::vector &vargs = {}); ~Message(); - int toLua(lua_State *L); - static Message *fromLua(lua_State *L, int n); - const std::string name; const std::vector args; diff --git a/src/modules/event/wrap_Event.cpp b/src/modules/event/wrap_Event.cpp index 4e8e2fea9..76388493e 100644 --- a/src/modules/event/wrap_Event.cpp +++ b/src/modules/event/wrap_Event.cpp @@ -38,13 +38,23 @@ namespace event #define instance() (Module::getInstance(Module::M_EVENT)) +static int luax_pushmessage(lua_State *L, const Message &m) +{ + luax_pushstring(L, m.name); + + for (const Variant &v : m.args) + luax_pushvariant(L, v); + + return (int) m.args.size() + 1; +} + static int w_poll_i(lua_State *L) { Message *m = nullptr; - if (instance()->poll(m)) + if (instance()->poll(m) && m != nullptr) { - int args = m->toLua(L); + int args = luax_pushmessage(L, *m); m->release(); return args; } @@ -63,9 +73,9 @@ int w_wait(lua_State *L) { Message *m = nullptr; luax_catchexcept(L, [&]() { m = instance()->wait(); }); - if (m) + if (m != nullptr) { - int args = m->toLua(L); + int args = luax_pushmessage(L, *m); m->release(); return args; } @@ -75,15 +85,28 @@ int w_wait(lua_State *L) int w_push(lua_State *L) { - StrongRef m; - luax_catchexcept(L, [&]() { m.set(Message::fromLua(L, 1), Acquire::NORETAIN); }); + std::string name = luax_checkstring(L, 1); + std::vector vargs; - luax_pushboolean(L, m.get() != nullptr); + int nargs = lua_gettop(L); + for (int i = 2; i <= nargs; i++) + { + if (lua_isnoneornil(L, i)) + break; - if (m.get() == nullptr) - return 1; + luax_catchexcept(L, [&]() { vargs.push_back(luax_checkvariant(L, i)); }); + + if (vargs.back().getType() == Variant::UNKNOWN) + { + vargs.clear(); + return luaL_error(L, "Argument %d can't be stored safely\nExpected boolean, number, string or userdata.", i); + } + } + + StrongRef m(new Message(name, vargs), Acquire::NORETAIN); instance()->push(m); + luax_pushboolean(L, true); return 1; } @@ -98,7 +121,7 @@ int w_quit(lua_State *L) luax_catchexcept(L, [&]() { std::vector args; for (int i = 1; i <= std::max(1, lua_gettop(L)); i++) - args.push_back(Variant::fromLua(L, i)); + args.push_back(luax_checkvariant(L, i)); StrongRef m(new Message("quit", args), Acquire::NORETAIN); instance()->push(m); @@ -115,7 +138,7 @@ int w_restart(lua_State *L) args.emplace_back("restart", strlen("restart")); for (int i = 1; i <= lua_gettop(L); i++) - args.push_back(Variant::fromLua(L, i)); + args.push_back(luax_checkvariant(L, i)); StrongRef m(new Message("quit", args), Acquire::NORETAIN); instance()->push(m); diff --git a/src/modules/event/wrap_Event.h b/src/modules/event/wrap_Event.h index 6c4bf85ed..d1352771d 100644 --- a/src/modules/event/wrap_Event.h +++ b/src/modules/event/wrap_Event.h @@ -24,6 +24,7 @@ // LOVE #include "common/config.h" #include "Event.h" +#include "common/runtime.h" namespace love { diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index ec6e55f5c..e3a866f9b 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -36,9 +36,6 @@ namespace thread class Channel : public love::Object { -// FOR WRAPPER USE ONLY -friend int w_Channel_performAtomic(lua_State *); - public: static love::Type type; @@ -57,11 +54,11 @@ public: bool hasRead(uint64 id) const; void clear(); -private: - void lockMutex(); void unlockMutex(); +private: + MutexRef mutex; ConditionalRef cond; std::queue queue; diff --git a/src/modules/thread/LuaThread.cpp b/src/modules/thread/LuaThread.cpp index 4b7afa6e1..9bb508c91 100644 --- a/src/modules/thread/LuaThread.cpp +++ b/src/modules/thread/LuaThread.cpp @@ -21,6 +21,7 @@ #include "LuaThread.h" #include "event/Event.h" #include "common/config.h" +#include "common/runtime.h" #ifdef LOVE_BUILD_STANDALONE extern "C" int luaopen_love(lua_State * L); @@ -76,7 +77,7 @@ void LuaThread::threadFunction() int pushedargs = (int) args.size(); for (int i = 0; i < pushedargs; i++) - args[i].toLua(L); + luax_pushvariant(L, args[i]); args.clear(); diff --git a/src/modules/thread/wrap_Channel.cpp b/src/modules/thread/wrap_Channel.cpp index c6d157f99..49a046e63 100644 --- a/src/modules/thread/wrap_Channel.cpp +++ b/src/modules/thread/wrap_Channel.cpp @@ -34,7 +34,7 @@ int w_Channel_push(lua_State *L) { Channel *c = luax_checkchannel(L, 1); luax_catchexcept(L, [&]() { - Variant var = Variant::fromLua(L, 2); + Variant var = luax_checkvariant(L, 2); if (var.getType() == Variant::UNKNOWN) luaL_argerror(L, 2, "boolean, number, string, love type, or table expected"); uint64 id = c->push(var); @@ -48,7 +48,7 @@ int w_Channel_supply(lua_State *L) Channel *c = luax_checkchannel(L, 1); bool result = false; luax_catchexcept(L, [&]() { - Variant var = Variant::fromLua(L, 2); + Variant var = luax_checkvariant(L, 2); if (var.getType() == Variant::UNKNOWN) luaL_argerror(L, 2, "boolean, number, string, love type, or table expected"); if (lua_isnumber(L, 3)) @@ -66,7 +66,7 @@ int w_Channel_pop(lua_State *L) Channel *c = luax_checkchannel(L, 1); Variant var; if (c->pop(&var)) - var.toLua(L); + luax_pushvariant(L, var); else lua_pushnil(L); return 1; @@ -84,7 +84,7 @@ int w_Channel_demand(lua_State *L) result = c->demand(&var); if (result) - var.toLua(L); + luax_pushvariant(L, var); else lua_pushnil(L); return 1; @@ -95,7 +95,7 @@ int w_Channel_peek(lua_State *L) Channel *c = luax_checkchannel(L, 1); Variant var; if (c->peek(&var)) - var.toLua(L); + luax_pushvariant(L, var); else lua_pushnil(L); return 1; diff --git a/src/modules/thread/wrap_Channel.h b/src/modules/thread/wrap_Channel.h index 013b2138f..56fb6e59c 100644 --- a/src/modules/thread/wrap_Channel.h +++ b/src/modules/thread/wrap_Channel.h @@ -23,6 +23,7 @@ // LOVE #include "Channel.h" +#include "common/runtime.h" namespace love { diff --git a/src/modules/thread/wrap_LuaThread.cpp b/src/modules/thread/wrap_LuaThread.cpp index db71f9ca1..db29c1a65 100644 --- a/src/modules/thread/wrap_LuaThread.cpp +++ b/src/modules/thread/wrap_LuaThread.cpp @@ -39,7 +39,7 @@ int w_Thread_start(lua_State *L) for (int i = 0; i < nargs; ++i) { luax_catchexcept(L, [&]() { - args.push_back(Variant::fromLua(L, i+2)); + args.push_back(luax_checkvariant(L, i+2)); }); if (args.back().getType() == Variant::UNKNOWN) diff --git a/src/modules/thread/wrap_LuaThread.h b/src/modules/thread/wrap_LuaThread.h index 50fcffa9a..26696bf85 100644 --- a/src/modules/thread/wrap_LuaThread.h +++ b/src/modules/thread/wrap_LuaThread.h @@ -23,6 +23,7 @@ // LOVE #include "ThreadModule.h" +#include "common/runtime.h" namespace love { From e188740c1819ff8bafb31667eba1ddc24b91092b Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 28 Feb 2020 22:17:20 -0400 Subject: [PATCH 4/4] Fix a link error on Windows --- src/common/runtime.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/runtime.h b/src/common/runtime.h index 44f6e4cd7..93441e6d0 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -355,12 +355,12 @@ void luax_rawnewtype(lua_State *L, love::Type &type, love::Object *object); /** * Stores the value at the given index on the stack into a Variant object. */ -Variant luax_checkvariant(lua_State *L, int idx, bool allowuserdata = true, std::set *tableSet = nullptr); +LOVE_EXPORT Variant luax_checkvariant(lua_State *L, int idx, bool allowuserdata = true, std::set *tableSet = nullptr); /** * Pushes the contents of the given Variant index onto the stack. */ -void luax_pushvariant(lua_State *L, const Variant &v); +LOVE_EXPORT void luax_pushvariant(lua_State *L, const Variant &v); /** * Checks whether the value at idx is a certain type.