Merge branch 'love2d:12.0-development' into 12.0-development

This commit is contained in:
nikeinikei
2022-12-21 17:20:43 +01:00
committed by GitHub
51 changed files with 1335 additions and 523 deletions
+3 -3
View File
@@ -30,7 +30,7 @@
#include "ParticleSystem.h"
#include "Font.h"
#include "Video.h"
#include "Text.h"
#include "TextBatch.h"
#include "common/deprecation.h"
#include "common/config.h"
@@ -439,9 +439,9 @@ Mesh *Graphics::newMesh(const std::vector<Mesh::BufferAttribute> &attributes, Pr
return new Mesh(attributes, drawmode);
}
love::graphics::Text *Graphics::newText(graphics::Font *font, const std::vector<Font::ColoredString> &text)
love::graphics::TextBatch *Graphics::newTextBatch(graphics::Font *font, const std::vector<Font::ColoredString> &text)
{
return new Text(font, text);
return new TextBatch(font, text);
}
love::data::ByteData *Graphics::readbackBuffer(Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset)
+2 -2
View File
@@ -58,7 +58,7 @@ namespace graphics
class SpriteBatch;
class ParticleSystem;
class Text;
class TextBatch;
class Video;
class Buffer;
@@ -460,7 +460,7 @@ public:
Mesh *newMesh(const std::vector<Buffer::DataDeclaration> &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferDataUsage usage);
Mesh *newMesh(const std::vector<Mesh::BufferAttribute> &attributes, PrimitiveType drawmode);
Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {});
TextBatch *newTextBatch(Font *font, const std::vector<Font::ColoredString> &text = {});
data::ByteData *readbackBuffer(Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset);
GraphicsReadback *readbackBufferAsync(Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset);
+8 -3
View File
@@ -140,7 +140,7 @@ void Mesh::setupAttachedAttributes()
if (getAttachedAttributeIndex(name) != -1)
throw love::Exception("Duplicate vertex attribute name: %s", name.c_str());
attachedAttributes.push_back({name, vertexBuffer, nullptr, (int) i, STEP_PER_VERTEX, true});
attachedAttributes.push_back({name, vertexBuffer, nullptr, (int) i, 0, STEP_PER_VERTEX, true});
}
}
@@ -208,7 +208,7 @@ bool Mesh::isAttributeEnabled(const std::string &name) const
return attachedAttributes[index].enabled;
}
void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, AttributeStep step)
void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, int startindex, AttributeStep step)
{
if ((buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0)
throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute.");
@@ -217,6 +217,9 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh,
if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING])
throw love::Exception("Vertex attribute instancing is not supported on this system.");
if (startindex < 0 || startindex >= (int) buffer->getArrayLength())
throw love::Exception("Invalid start array index %d.", startindex + 1);
BufferAttribute oldattrib = {};
BufferAttribute newattrib = {};
@@ -231,6 +234,7 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh,
newattrib.mesh = mesh;
newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true;
newattrib.indexInBuffer = buffer->getDataMemberIndex(attachname);
newattrib.startArrayIndex = startindex;
newattrib.step = step;
if (newattrib.indexInBuffer < 0)
@@ -578,12 +582,13 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
uint16 offset = (uint16) member.offset;
uint16 stride = (uint16) buffer->getArrayStride();
size_t bufferoffset = (size_t) stride * attrib.startArrayIndex;
attributes.set(attributeindex, member.decl.format, offset, activebuffers);
attributes.setBufferLayout(activebuffers, stride, attrib.step);
// TODO: Ideally we want to reuse buffers with the same stride+step.
buffers.set(activebuffers, buffer, 0);
buffers.set(activebuffers, buffer, bufferoffset);
activebuffers++;
}
}
+2 -1
View File
@@ -57,6 +57,7 @@ public:
StrongRef<Buffer> buffer;
StrongRef<Mesh> mesh;
int indexInBuffer;
int startArrayIndex;
AttributeStep step;
bool enabled;
};
@@ -109,7 +110,7 @@ public:
* to make sure this Mesh knows to flush the passed in Mesh's data to its
* buffer when drawing.
**/
void attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX);
void attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, int startindex = 0, AttributeStep step = STEP_PER_VERTEX);
bool detachAttribute(const std::string &name);
const std::vector<BufferAttribute> &getAttachedAttributes() const;
@@ -18,7 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Text.h"
#include "TextBatch.h"
#include "Graphics.h"
#include <algorithm>
@@ -28,9 +28,9 @@ namespace love
namespace graphics
{
love::Type Text::type("Text", &Drawable::type);
love::Type TextBatch::type("TextBatch", &Drawable::type);
Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
TextBatch::TextBatch(Font *font, const std::vector<Font::ColoredString> &text)
: font(font)
, vertexAttributes(Font::vertexFormat, 0)
, vertexData(nullptr)
@@ -41,13 +41,13 @@ Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
set(text);
}
Text::~Text()
TextBatch::~TextBatch()
{
if (vertexData != nullptr)
free(vertexData);
}
void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
void TextBatch::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
{
size_t offset = vertoffset * sizeof(Font::GlyphVertex);
size_t datasize = vertices.size() * sizeof(Font::GlyphVertex);
@@ -90,7 +90,7 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
}
}
void Text::regenerateVertices()
void TextBatch::regenerateVertices()
{
// If the font's texture cache was invalidated then we need to recreate the
// text's vertices, since glyph texcoords might have changed.
@@ -107,7 +107,7 @@ void Text::regenerateVertices()
}
}
void Text::addTextData(const TextData &t)
void TextBatch::addTextData(const TextData &t)
{
std::vector<Font::GlyphVertex> vertices;
std::vector<Font::DrawCommand> newcommands;
@@ -172,12 +172,12 @@ void Text::addTextData(const TextData &t)
regenerateVertices();
}
void Text::set(const std::vector<Font::ColoredString> &text)
void TextBatch::set(const std::vector<Font::ColoredString> &text)
{
return set(text, -1.0f, Font::ALIGN_MAX_ENUM);
}
void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
void TextBatch::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
{
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
return clear();
@@ -188,12 +188,12 @@ void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::A
addTextData({codepoints, wrap, align, {}, false, false, Matrix4()});
}
int Text::add(const std::vector<Font::ColoredString> &text, const Matrix4 &m)
int TextBatch::add(const std::vector<Font::ColoredString> &text, const Matrix4 &m)
{
return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, m);
}
int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m)
int TextBatch::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m)
{
Font::ColoredCodepoints codepoints;
Font::getCodepointsFromString(text, codepoints);
@@ -203,7 +203,7 @@ int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::A
return (int) textData.size() - 1;
}
void Text::clear()
void TextBatch::clear()
{
textData.clear();
drawCommands.clear();
@@ -211,7 +211,7 @@ void Text::clear()
vertOffset = 0;
}
void Text::setFont(Font *f)
void TextBatch::setFont(Font *f)
{
font.set(f);
@@ -221,12 +221,12 @@ void Text::setFont(Font *f)
regenerateVertices();
}
Font *Text::getFont() const
Font *TextBatch::getFont() const
{
return font.get();
}
int Text::getWidth(int index) const
int TextBatch::getWidth(int index) const
{
if (index < 0)
index = std::max((int) textData.size() - 1, 0);
@@ -237,7 +237,7 @@ int Text::getWidth(int index) const
return textData[index].textInfo.width;
}
int Text::getHeight(int index) const
int TextBatch::getHeight(int index) const
{
if (index < 0)
index = std::max((int) textData.size() - 1, 0);
@@ -248,7 +248,7 @@ int Text::getHeight(int index) const
return textData[index].textInfo.height;
}
void Text::draw(Graphics *gfx, const Matrix4 &m)
void TextBatch::draw(Graphics *gfx, const Matrix4 &m)
{
if (vertexBuffer == nullptr || vertexData == nullptr || drawCommands.empty())
return;
@@ -34,14 +34,14 @@ namespace graphics
class Graphics;
class Text : public Drawable
class TextBatch : public Drawable
{
public:
static love::Type type;
Text(Font *font, const std::vector<Font::ColoredString> &text = {});
virtual ~Text();
TextBatch(Font *font, const std::vector<Font::ColoredString> &text = {});
virtual ~TextBatch();
void set(const std::vector<Font::ColoredString> &text);
void set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align);
+19 -19
View File
@@ -28,7 +28,7 @@
#include "Shader.h"
#include "Vulkan.h"
#include "SDL_vulkan.h"
#include <SDL_vulkan.h>
#include <algorithm>
#include <vector>
@@ -468,7 +468,8 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
this->pixelWidth = pixelwidth;
this->pixelHeight = pixelheight;
resetProjection();
if (!isRenderTargetActive())
resetProjection();
}
bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa)
@@ -476,6 +477,9 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
requestedMsaa = msaa;
windowHasStencil = windowhasstencil;
// Must be called before the swapchain is created.
setViewportSize(width, height, pixelwidth, pixelheight);
cleanUpFunctions.clear();
cleanUpFunctions.resize(MAX_FRAMES_IN_FLIGHT);
@@ -529,8 +533,6 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
restoreState(states.back());
setViewportSize(width, height, pixelwidth, pixelheight);
Vulkan::resetShaderSwitches();
frameCounter = 0;
@@ -1783,16 +1785,20 @@ VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentMode
else
return VK_PRESENT_MODE_FIFO_KHR;
case 0:
if (std::find(begin, end, VK_PRESENT_MODE_MAILBOX_KHR) != end)
// Mailbox mode might be better than immediate mode for a lot of people.
// But on at least some systems it acts as if vsync is enabled
// https://github.com/love2d/love/issues/1852
// TODO: is that a bug in love's code or the graphics driver / compositor?
// Should love expose mailbox mode in an API to users in some manner,
// instead of trying to guess what to do?
if (std::find(begin, end, VK_PRESENT_MODE_IMMEDIATE_KHR) != end)
return VK_PRESENT_MODE_IMMEDIATE_KHR;
else if (std::find(begin, end, VK_PRESENT_MODE_MAILBOX_KHR) != end)
return VK_PRESENT_MODE_MAILBOX_KHR;
else
{
if (std::find(begin, end, VK_PRESENT_MODE_IMMEDIATE_KHR) != end)
return VK_PRESENT_MODE_IMMEDIATE_KHR;
else
return VK_PRESENT_MODE_FIFO_KHR;
}
return VK_PRESENT_MODE_FIFO_KHR;
default:
// TODO: support for swap interval = 2, etc?
return VK_PRESENT_MODE_FIFO_KHR;
}
}
@@ -1814,15 +1820,9 @@ VkExtent2D Graphics::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabiliti
return capabilities.currentExtent;
else
{
auto window = Module::getInstance<love::window::Window>(M_WINDOW);
const void *handle = window->getHandle();
int width, height;
SDL_Vulkan_GetDrawableSize((SDL_Window*)handle, &width, &height);
VkExtent2D actualExtent = {
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
static_cast<uint32_t>(pixelWidth),
static_cast<uint32_t>(pixelHeight)
};
actualExtent.width = clampuint32_t(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
+13 -6
View File
@@ -2101,21 +2101,21 @@ int w_newMesh(lua_State *L)
return 1;
}
int w_newText(lua_State *L)
int w_newTextBatch(lua_State *L)
{
luax_checkgraphicscreated(L);
graphics::Font *font = luax_checkfont(L, 1);
Text *t = nullptr;
TextBatch *t = nullptr;
if (lua_isnoneornil(L, 2))
luax_catchexcept(L, [&](){ t = instance()->newText(font); });
luax_catchexcept(L, [&](){ t = instance()->newTextBatch(font); });
else
{
std::vector<Font::ColoredString> text;
luax_checkcoloredstring(L, 2, text);
luax_catchexcept(L, [&](){ t = instance()->newText(font, text); });
luax_catchexcept(L, [&](){ t = instance()->newTextBatch(font, text); });
}
luax_pushtype(L, t);
@@ -2123,6 +2123,12 @@ int w_newText(lua_State *L)
return 1;
}
int w_newText(lua_State *L)
{
luax_markdeprecated(L, 1, "love.graphics.newText", API_FUNCTION, DEPRECATED_RENAMED, "love.graphics.newTextBatch");
return w_newTextBatch(L);
}
int w_newVideo(lua_State *L)
{
luax_checkgraphicscreated(L);
@@ -3769,7 +3775,7 @@ static const luaL_Reg functions[] =
{ "newVertexBuffer", w_newVertexBuffer },
{ "newIndexBuffer", w_newIndexBuffer },
{ "newMesh", w_newMesh },
{ "newText", w_newText },
{ "newTextBatch", w_newTextBatch },
{ "_newVideo", w_newVideo },
{ "readbackBuffer", w_readbackBuffer },
@@ -3895,6 +3901,7 @@ static const luaL_Reg functions[] =
{ "newArrayImage", w_newArrayImage },
{ "newVolumeImage", w_newVolumeImage },
{ "newCubeImage", w_newCubeImage },
{ "newText", w_newText },
{ "getCanvasFormats", w_getCanvasFormats },
{ "getImageFormats", w_getImageFormats },
@@ -3919,7 +3926,7 @@ static const lua_CFunction types[] =
luaopen_particlesystem,
luaopen_shader,
luaopen_mesh,
luaopen_text,
luaopen_textbatch,
luaopen_video,
0
};
+1 -1
View File
@@ -29,7 +29,7 @@
#include "wrap_ParticleSystem.h"
#include "wrap_Shader.h"
#include "wrap_Mesh.h"
#include "wrap_Text.h"
#include "wrap_TextBatch.h"
#include "wrap_Video.h"
#include "wrap_Buffer.h"
#include "wrap_GraphicsReadback.h"
+6 -2
View File
@@ -314,8 +314,9 @@ int w_Mesh_attachAttribute(lua_State *L)
return luax_enumerror(L, "vertex attribute step", getConstants(step), stepstr);
const char *attachname = luaL_optstring(L, 5, name);
int startindex = (int) luaL_optinteger(L, 6, 1) - 1;
luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer, mesh, attachname, step); });
luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer, mesh, attachname, startindex, step); });
return 0;
}
@@ -340,7 +341,7 @@ int w_Mesh_getAttachedAttributes(lua_State *L)
{
const auto &attrib = attributes[i];
lua_createtable(L, 4, 0);
lua_createtable(L, 5, 0);
luax_pushstring(L, attrib.name);
lua_rawseti(L, -1, 1);
@@ -358,6 +359,9 @@ int w_Mesh_getAttachedAttributes(lua_State *L)
luax_pushstring(L, member.decl.name);
lua_rawseti(L, -1, 4);
lua_pushinteger(L, attrib.startArrayIndex + 1);
lua_rawseti(L, -1, 5);
lua_rawseti(L, -1, i + 1);
}
@@ -18,7 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_Text.h"
#include "wrap_TextBatch.h"
#include "wrap_Font.h"
#include "math/wrap_Transform.h"
@@ -27,14 +27,14 @@ namespace love
namespace graphics
{
Text *luax_checktext(lua_State *L, int idx)
TextBatch *luax_checktextbatch(lua_State *L, int idx)
{
return luax_checktype<Text>(L, idx);
return luax_checktype<TextBatch>(L, idx);
}
int w_Text_set(lua_State *L)
int w_TextBatch_set(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
std::vector<Font::ColoredString> newtext;
luax_checkcoloredstring(L, 2, newtext);
@@ -43,9 +43,9 @@ int w_Text_set(lua_State *L)
return 0;
}
int w_Text_setf(lua_State *L)
int w_TextBatch_setf(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
float wraplimit = (float) luaL_checknumber(L, 3);
@@ -62,9 +62,9 @@ int w_Text_setf(lua_State *L)
return 0;
}
int w_Text_add(lua_State *L)
int w_TextBatch_add(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
int index = 0;
@@ -96,9 +96,9 @@ int w_Text_add(lua_State *L)
return 1;
}
int w_Text_addf(lua_State *L)
int w_TextBatch_addf(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
int index = 0;
@@ -138,72 +138,72 @@ int w_Text_addf(lua_State *L)
return 1;
}
int w_Text_clear(lua_State *L)
int w_TextBatch_clear(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
luax_catchexcept(L, [&](){ t->clear(); });
return 0;
}
int w_Text_setFont(lua_State *L)
int w_TextBatch_setFont(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
Font *f = luax_checktype<Font>(L, 2);
luax_catchexcept(L, [&](){ t->setFont(f); });
return 0;
}
int w_Text_getFont(lua_State *L)
int w_TextBatch_getFont(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
Font *f = t->getFont();
luax_pushtype(L, f);
return 1;
}
int w_Text_getWidth(lua_State *L)
int w_TextBatch_getWidth(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getWidth(index));
return 1;
}
int w_Text_getHeight(lua_State *L)
int w_TextBatch_getHeight(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getHeight(index));
return 1;
}
int w_Text_getDimensions(lua_State *L)
int w_TextBatch_getDimensions(lua_State *L)
{
Text *t = luax_checktext(L, 1);
TextBatch *t = luax_checktextbatch(L, 1);
int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getWidth(index));
lua_pushnumber(L, t->getHeight(index));
return 2;
}
static const luaL_Reg w_Text_functions[] =
static const luaL_Reg w_TextBatch_functions[] =
{
{ "set", w_Text_set },
{ "setf", w_Text_setf },
{ "add", w_Text_add },
{ "addf", w_Text_addf },
{ "clear", w_Text_clear },
{ "setFont", w_Text_setFont },
{ "getFont", w_Text_getFont },
{ "getWidth", w_Text_getWidth },
{ "getHeight", w_Text_getHeight },
{ "getDimensions", w_Text_getDimensions },
{ "set", w_TextBatch_set },
{ "setf", w_TextBatch_setf },
{ "add", w_TextBatch_add },
{ "addf", w_TextBatch_addf },
{ "clear", w_TextBatch_clear },
{ "setFont", w_TextBatch_setFont },
{ "getFont", w_TextBatch_getFont },
{ "getWidth", w_TextBatch_getWidth },
{ "getHeight", w_TextBatch_getHeight },
{ "getDimensions", w_TextBatch_getDimensions },
{ 0, 0 }
};
extern "C" int luaopen_text(lua_State *L)
extern "C" int luaopen_textbatch(lua_State *L)
{
return luax_register_type(L, &Text::type, w_Text_functions, nullptr);
return luax_register_type(L, &TextBatch::type, w_TextBatch_functions, nullptr);
}
} // graphics
@@ -20,7 +20,7 @@
#pragma once
#include "Text.h"
#include "TextBatch.h"
#include "common/runtime.h"
namespace love
@@ -28,8 +28,8 @@ namespace love
namespace graphics
{
Text *luax_checktext(lua_State *L, int idx);
extern "C" int luaopen_text(lua_State *L);
TextBatch *luax_checktextbatch(lua_State *L, int idx);
extern "C" int luaopen_textbatch(lua_State *L);
} // graphics
} // love
+1 -1
View File
@@ -242,7 +242,7 @@ int w_Texture_setWrap(lua_State *L)
return luax_enumerror(L, "wrap mode", SamplerState::getConstants(s.wrapW), rstr);
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
return 1;
return 0;
}
int w_Texture_getWrap(lua_State *L)