diff --git a/src/api.h b/src/api.h index 8ffb5267..cd5045fa 100644 --- a/src/api.h +++ b/src/api.h @@ -1,6 +1,7 @@ #include "luax.h" #include "data/blob.h" #include "event/event.h" +#include "graphics/canvas.h" #include "graphics/mesh.h" #include "math/math.h" #include "math/randomGenerator.h" @@ -122,3 +123,4 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des void luax_checkuniformtype(lua_State* L, int index, UniformType* baseType, int* components); int luax_optmipmap(lua_State* L, int index, Texture* texture); Texture* luax_checktexture(lua_State* L, int index); +void luax_readattachments(lua_State* L, int index, Attachment* attachments, int* count); diff --git a/src/api/graphics.c b/src/api/graphics.c index 2604d012..74fee2be 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -929,12 +929,32 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) { } int l_lovrGraphicsNewCanvas(lua_State* L) { - int width = luaL_checkinteger(L, 1); - int height = luaL_checkinteger(L, 2); + Attachment attachments[MAX_CANVAS_ATTACHMENTS]; + bool anonymous = false; + int attachmentCount = 0; + int width = 0; + int height = 0; + int index; + + if (luax_totype(L, 1, Texture)) { + for (index = 1; index <= MAX_CANVAS_ATTACHMENTS; index++) { + Texture* texture = luax_totype(L, index, Texture); + if (!texture) break; + attachments[attachmentCount++] = (Attachment) { texture, 0, 0 }; + } + } else if (lua_istable(L, 1)) { + luax_readattachments(L, 1, attachments, &attachmentCount); + index = 2; + } else { + width = luaL_checkinteger(L, 1); + height = luaL_checkinteger(L, 2); + index = 3; + } + CanvasFlags flags = { .depth = DEPTH_D16, .stereo = true, .msaa = 0, .mipmaps = true }; - if (lua_istable(L, 3)) { - lua_getfield(L, 3, "depth"); + if (lua_istable(L, index)) { + lua_getfield(L, index, "depth"); switch (lua_type(L, -1)) { case LUA_TNIL: break; case LUA_TBOOLEAN: flags.depth = lua_toboolean(L, -1) ? DEPTH_D16 : DEPTH_NONE; break; @@ -942,20 +962,46 @@ int l_lovrGraphicsNewCanvas(lua_State* L) { } lua_pop(L, 1); - lua_getfield(L, 3, "stereo"); + lua_getfield(L, index, "stereo"); flags.stereo = lua_isnil(L, -1) ? flags.stereo : lua_toboolean(L, -1); lua_pop(L, 1); - lua_getfield(L, 3, "msaa"); + lua_getfield(L, index, "msaa"); flags.msaa = lua_isnil(L, -1) ? flags.msaa : luaL_checkinteger(L, -1); lua_pop(L, 1); - lua_getfield(L, 3, "mipmaps"); + lua_getfield(L, index, "mipmaps"); flags.mipmaps = lua_isnil(L, -1) ? flags.mipmaps : lua_toboolean(L, -1); lua_pop(L, 1); + + if (attachmentCount == 0) { + lua_getfield(L, index, "format"); + if (lua_type(L, -1) == LUA_TSTRING) { + TextureFormat format = luaL_checkoption(L, -1, "rgba", TextureFormats); + Texture* texture = lovrTextureCreate(TEXTURE_2D, NULL, 0, true, flags.mipmaps, flags.msaa); + lovrTextureAllocate(texture, width, height, 1, format); + attachments[0] = (Attachment) { texture, 0, 0 }; + attachmentCount++; + anonymous = true; + } + lua_pop(L, 1); + } + } + + if (width == 0 && height == 0 && attachmentCount > 0) { + width = lovrTextureGetWidth(attachments[0].texture, attachments[0].level); + height = lovrTextureGetHeight(attachments[0].texture, attachments[0].level); } Canvas* canvas = lovrCanvasCreate(width, height, flags); + + if (attachmentCount > 0) { + lovrCanvasSetAttachments(canvas, attachments, attachmentCount); + if (anonymous) { + lovrRelease(attachments[0].texture); + } + } + luax_pushobject(L, canvas); lovrRelease(canvas); return 1; diff --git a/src/api/types/canvas.c b/src/api/types/canvas.c index 7391e491..acaad0d5 100644 --- a/src/api/types/canvas.c +++ b/src/api/types/canvas.c @@ -13,14 +13,53 @@ Texture* luax_checktexture(lua_State* L, int index) { } static int luax_checkattachment(lua_State* L, int index, Attachment* attachment) { - attachment->texture = luax_checktype(L, index++, Texture); - attachment->slice = lua_type(L, index) == LUA_TNUMBER ? lua_tointeger(L, index++) - 1 : 0; - attachment->level = lua_type(L, index) == LUA_TNUMBER ? luax_optmipmap(L, index++, attachment->texture) : 0; + if (lua_istable(L, index)) { + lua_rawgeti(L, index, 1); + attachment->texture = luax_checktype(L, -1, Texture); + lua_pop(L, 1); + + lua_rawgeti(L, index, 2); + attachment->slice = luaL_optinteger(L, -1, 1) - 1; + lua_pop(L, 1); + + lua_rawgeti(L, index, 3); + attachment->level = luax_optmipmap(L, -1, attachment->texture); + lua_pop(L, 1); + + index++; + } else { + attachment->texture = luax_checktype(L, index++, Texture); + attachment->slice = lua_type(L, index) == LUA_TNUMBER ? lua_tointeger(L, index++) - 1 : 0; + attachment->level = lua_type(L, index) == LUA_TNUMBER ? luax_optmipmap(L, index++, attachment->texture) : 0; + } bool isValidSlice = attachment->slice >= 0 && attachment->slice < lovrTextureGetDepth(attachment->texture, 0); lovrAssert(isValidSlice, "Invalid slice %d\n", attachment->slice + 1); return index; } +void luax_readattachments(lua_State* L, int index, Attachment* attachments, int* count) { + bool table = lua_istable(L, index); + int top = table ? -1 : lua_gettop(L); + int n; + + if (lua_istable(L, index)) { + n = lua_objlen(L, index); + n = MIN(n, 3 * MAX_CANVAS_ATTACHMENTS); + for (int i = 0; i < n; i++) { + lua_rawgeti(L, index, i + 1); + } + index = -n; + } + + for (*count = 0; *count < MAX_CANVAS_ATTACHMENTS && index <= top; (*count)++) { + index = luax_checkattachment(L, index, attachments + *count); + } + + if (table) { + lua_pop(L, n); + } +} + int l_lovrCanvasNewTextureData(lua_State* L) { Canvas* canvas = luax_checktype(L, 1, Canvas); int index = luaL_optinteger(L, 2, 1) - 1; @@ -58,14 +97,8 @@ int l_lovrCanvasSetTexture(lua_State* L) { Canvas* canvas = luax_checktype(L, 1, Canvas); Attachment attachments[MAX_CANVAS_ATTACHMENTS]; int count; - int index = 2; - int top = lua_gettop(L); - for (count = 0; count < MAX_CANVAS_ATTACHMENTS && index <= top; count++) { - index = luax_checkattachment(L, index, attachments + count); - } - + luax_readattachments(L, 2, attachments, &count); lovrCanvasSetAttachments(canvas, attachments, count); - return 0; } diff --git a/src/graphics/mesh.h b/src/graphics/mesh.h index c6dd2691..bd771e00 100644 --- a/src/graphics/mesh.h +++ b/src/graphics/mesh.h @@ -23,7 +23,7 @@ Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, void lovrMeshDestroy(void* ref); void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor); void lovrMeshDetachAttribute(Mesh* mesh, const char* name); -void lovrMeshBind(Mesh* mesh, Shader* shader); +void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier); void lovrMeshDraw(Mesh* mesh, int instances); VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh); MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);