From 4f491c2e6162ff880818b4725a0c59912ca2c6c7 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Thu, 7 Jan 2021 11:49:11 +0800 Subject: [PATCH 01/17] Allow full 64-bit lightuserdata usage if the LuaJIT supports it. Issue love2d/love-android#200 Original patch was sent by slime in Discord. Modified a bit to add code that checks for 64-bit lightuserdata support. --- src/common/runtime.cpp | 64 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index 72c1bbe94..3570890e2 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -93,11 +93,42 @@ static int w__eq(lua_State *L) return 1; } +typedef uint64 ObjectKey; + +static bool luax_isfulllightuserdatasupported(lua_State *L) +{ + // LuaJIT prior to commit e9af1abec542e6f9851ff2368e7f196b6382a44c doesn't + // support lightuserdata > 48 bits. This is not a problem with Android, + // Windows, macOS, and iOS as they'll use updated LuaJIT or won't use + // pointers > 48 bits, but this is not the case for Linux. So check for + // this capability first! + static bool checked = false; + static bool supported = false; + + if (!checked) + { + lua_pushcclosure(L, [](lua_State *L) -> int + { + // Try to push pointer with all bits set. + lua_pushlightuserdata(L, (void *) (~((size_t) 0))); + return 1; + }, 0); + + supported = lua_pcall(L, 0, 1, 0) == 0; + checked = true; + + lua_pop(L, 1); + } + + return supported; +} + // For use with the love object pointer -> Proxy pointer registry. // Using the pointer directly via lightuserdata would be ideal, but LuaJIT -// cannot use lightuserdata with more than 47 bits whereas some newer arm64 -// architectures allow pointers which use more than that. -static lua_Number luax_computeloveobjectkey(lua_State *L, love::Object *object) +// (before a commit to 2.1 in 2020) cannot use lightuserdata with more than 47 +// bits whereas some newer arm64 architectures allow pointers which use more +// than that. +static ObjectKey luax_computeloveobjectkey(lua_State *L, love::Object *object) { // love objects should be allocated on the heap, and thus are subject // to the alignment rules of operator new / malloc. Lua numbers (doubles) @@ -118,11 +149,20 @@ static lua_Number luax_computeloveobjectkey(lua_State *L, love::Object *object) key >>= shift; - // Make sure our key isn't larger than 2^53. - if (key > 0x20000000000000ULL) - luaL_error(L, "Cannot push love object to Lua: pointer value %p is too large", object); + return (ObjectKey) key; +} - return (lua_Number) key; +static void luax_pushloveobjectkey(lua_State *L, ObjectKey key) +{ + // If full 64-bit lightuserdata is supported, always use that. Otherwise, + // if the key is smaller than 2^53 (which is integer precision for double + // datatype), then push number. Otherwise, throw error. + if (luax_isfulllightuserdatasupported(L)) + lua_pushlightuserdata(L, (void *) key); + else if (key > 0x20000000000000ULL) // 2^53 + luaL_error(L, "Cannot push love object to Lua: pointer value %p is too large", key); + else + lua_pushnumber(L, (lua_Number) key); } static int w__release(lua_State *L) @@ -141,8 +181,8 @@ static int w__release(lua_State *L) if (lua_istable(L, -1)) { // loveobjects[object] = nil - lua_Number objectkey = luax_computeloveobjectkey(L, object); - lua_pushnumber(L, objectkey); + ObjectKey objectkey = luax_computeloveobjectkey(L, object); + luax_pushloveobjectkey(L, objectkey); lua_pushnil(L); lua_settable(L, -3); } @@ -605,10 +645,10 @@ void luax_pushtype(lua_State *L, love::Type &type, love::Object *object) return luax_rawnewtype(L, type, object); } - lua_Number objectkey = luax_computeloveobjectkey(L, object); + ObjectKey objectkey = luax_computeloveobjectkey(L, object); // Get the value of loveobjects[object] on the stack. - lua_pushnumber(L, objectkey); + luax_pushloveobjectkey(L, objectkey); lua_gettable(L, -2); // If the Proxy userdata isn't in the instantiated types table yet, add it. @@ -618,7 +658,7 @@ void luax_pushtype(lua_State *L, love::Type &type, love::Object *object) luax_rawnewtype(L, type, object); - lua_pushnumber(L, objectkey); + luax_pushloveobjectkey(L, objectkey); lua_pushvalue(L, -2); // loveobjects[object] = Proxy. From 5e77944dc04b88b54d165325471379863d78deb7 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 16 Jan 2021 13:09:01 -0400 Subject: [PATCH 02/17] refactor texture format support internals --- src/modules/graphics/Graphics.h | 2 +- src/modules/graphics/Texture.cpp | 2 +- src/modules/graphics/Texture.h | 20 +++ src/modules/graphics/opengl/Graphics.cpp | 26 ++- src/modules/graphics/opengl/Graphics.h | 2 +- src/modules/graphics/opengl/OpenGL.cpp | 213 +++++++++++++---------- src/modules/graphics/opengl/OpenGL.h | 2 +- 7 files changed, 164 insertions(+), 103 deletions(-) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 88258532d..999d8a1fa 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -775,7 +775,7 @@ public: /** * Converts PIXELFORMAT_NORMAL and PIXELFORMAT_HDR into a real format. **/ - virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const = 0; + virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const = 0; /** * Gets whether the specified pixel format is supported. diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 7b9345f9b..b320865b5 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -225,7 +225,7 @@ Texture::Texture(const Settings &settings, const Slices *slices) else readable = !renderTarget || !isPixelFormatDepthStencil(format); - format = gfx->getSizedFormat(format, renderTarget, readable, sRGB); + format = gfx->getSizedFormat(format, renderTarget, readable); if (mipmapsMode == MIPMAPS_AUTO && isCompressed()) mipmapsMode = MIPMAPS_MANUAL; diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index c6ee1b01b..8c73e1d6c 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -56,6 +56,26 @@ enum TextureType TEXTURE_MAX_ENUM }; +enum PixelFormatUsage +{ + PIXELFORMATUSAGE_SAMPLE, + PIXELFORMATUSAGE_LINEAR, + PIXELFORMATUSAGE_RENDERTARGET, + PIXELFORMATUSAGE_BLEND, + PIXELFORMATUSAGE_MSAA, + PIXELFORMATUSAGE_MAX_ENUM +}; + +enum PixelFormatUsageFlags +{ + PIXELFORMATUSAGEFLAGS_NONE = 0, + PIXELFORMATUSAGEFLAGS_SAMPLE = (1 << PIXELFORMATUSAGE_SAMPLE), + PIXELFORMATUSAGEFLAGS_LINEAR = (1 << PIXELFORMATUSAGE_LINEAR), + PIXELFORMATUSAGEFLAGS_RENDERTARGET = (1 << PIXELFORMATUSAGE_RENDERTARGET), + PIXELFORMATUSAGEFLAGS_BLEND = (1 << PIXELFORMATUSAGE_BLEND), + PIXELFORMATUSAGEFLAGS_MSAA = (1 << PIXELFORMATUSAGE_MSAA), +}; + struct SamplerState { enum WrapMode diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 94b3deab7..9375e2161 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1549,14 +1549,20 @@ void Graphics::initCapabilities() capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i); } -PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const +PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const { + uint32 requiredflags = 0; + if (rendertarget) + requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; + if (readable) + requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE; + switch (format) { case PIXELFORMAT_NORMAL: if (isGammaCorrect()) return PIXELFORMAT_sRGBA8_UNORM; - else if (!OpenGL::isPixelFormatSupported(PIXELFORMAT_RGBA8_UNORM, rendertarget, readable, sRGB)) + else if ((OpenGL::getPixelFormatUsageFlags(PIXELFORMAT_RGBA8_UNORM) & requiredflags) != requiredflags) // 32-bit render targets don't have guaranteed support on GLES2. return PIXELFORMAT_RGBA4_UNORM; else @@ -1572,18 +1578,26 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo { if (sRGB && format == PIXELFORMAT_RGBA8_UNORM) { - format = PIXELFORMAT_sRGBA8_UNORM; + format = getSRGBPixelFormat(format); sRGB = false; } - format = getSizedFormat(format, rendertarget, readable, sRGB); + uint32 requiredflags = 0; + if (rendertarget) + requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; + if (readable) + requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE; + + format = getSizedFormat(format, rendertarget, readable); OptionalBool &supported = supportedFormats[format][rendertarget ? 1 : 0][readable ? 1 : 0][sRGB ? 1 : 0]; if (supported.hasValue) return supported.value; - if (!OpenGL::isPixelFormatSupported(format, rendertarget, readable, sRGB)) + auto supportedflags = OpenGL::getPixelFormatUsageFlags(format); + + if ((requiredflags & supportedflags) != requiredflags) { supported.set(false); return supported.value; @@ -1613,7 +1627,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo return true; } - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, readable, sRGB); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB); GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL); diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 7f9ef56fd..f478c90e2 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -104,7 +104,7 @@ public: void setWireframe(bool enable) override; - PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const override; + PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override; bool isPixelFormatSupported(PixelFormat format, bool rendertarget, bool readable, bool sRGB = false) override; Renderer getRenderer() const override; RendererInfo getRendererInfo() const override; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 0974da473..d6522d6d5 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -1932,152 +1932,170 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r return f; } -bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool readable, bool isSRGB) +uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) { - if (rendertarget && isPixelFormatCompressed(pixelformat)) - return false; + const uint32 commonsample = PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_LINEAR; + const uint32 commonrender = PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_BLEND | PIXELFORMATUSAGEFLAGS_MSAA; - if (pixelformat == PIXELFORMAT_RGBA8_UNORM && isSRGB) - pixelformat = PIXELFORMAT_sRGBA8_UNORM; + uint32 flags = PIXELFORMATUSAGEFLAGS_NONE; switch (pixelformat) { case PIXELFORMAT_R8_UNORM: case PIXELFORMAT_RG8_UNORM: if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_texture_rg || GLAD_EXT_texture_rg) - return true; - else if (pixelformat == PIXELFORMAT_R8_UNORM && !rendertarget && (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_1)) - return true; // We'll use OpenGL's luminance format internally. - else - return false; + flags |= commonsample | commonrender; + else if (pixelformat == PIXELFORMAT_R8_UNORM && (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_1)) + flags |= commonsample; // We'll use OpenGL's luminance format internally. + break; case PIXELFORMAT_RGBA8_UNORM: - if (rendertarget) - return GLAD_VERSION_1_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8; - else - return true; + flags |= commonsample; + if (GLAD_VERSION_1_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8) + flags |= commonrender; + break; case PIXELFORMAT_sRGBA8_UNORM: if (gl.bugs.brokenSRGB) - return false; - if (rendertarget) - { - if (GLAD_VERSION_1_0) - { - return GLAD_VERSION_3_0 || ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB) - && (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB)); - } - else - return GLAD_ES_VERSION_3_0; - } - else - return GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB; + break; + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB) + flags |= commonsample; + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 + || ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB) && (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB))) + flags |= commonrender; + break; case PIXELFORMAT_R16_UNORM: case PIXELFORMAT_RG16_UNORM: - return GLAD_VERSION_3_0 + if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_1 && GLAD_ARB_texture_rg) - || (GLAD_EXT_texture_norm16 && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)); + || (GLAD_EXT_texture_norm16 && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg))) + flags |= commonsample | commonrender; + break; case PIXELFORMAT_RGBA16_UNORM: - return GLAD_VERSION_1_1 || GLAD_EXT_texture_norm16; + if (GLAD_VERSION_1_1 || GLAD_EXT_texture_norm16) + flags |= commonsample | commonrender; + break; case PIXELFORMAT_R16_FLOAT: case PIXELFORMAT_RG16_FLOAT: - if (GLAD_VERSION_1_0) - return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel && GLAD_ARB_texture_rg); - else if (rendertarget && !GLAD_EXT_color_buffer_half_float) - return false; - else - return GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_half_float && GLAD_EXT_texture_rg); + if (GLAD_VERSION_1_0 && (GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel && GLAD_ARB_texture_rg))) + flags |= commonsample | commonrender; + if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_half_float && GLAD_EXT_texture_rg)) + flags |= commonsample; + if (GLAD_EXT_color_buffer_half_float && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)) + flags |= commonrender; + break; case PIXELFORMAT_RGBA16_FLOAT: - if (GLAD_VERSION_1_0) - return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel); - else if (rendertarget && !GLAD_EXT_color_buffer_half_float) - return false; - else - return GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float; + if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel)) + flags |= commonsample | commonrender; + if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float) + flags |= commonsample; + if (GLAD_EXT_color_buffer_half_float) + flags |= commonrender; + break; case PIXELFORMAT_R32_FLOAT: case PIXELFORMAT_RG32_FLOAT: - if (GLAD_VERSION_1_0) - return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_texture_rg); - else if (!rendertarget) - return GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg); - else - return false; + if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float && GLAD_ARB_texture_rg)) + flags |= commonsample | commonrender; + if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg)) + flags |= commonsample; + break; case PIXELFORMAT_RGBA32_FLOAT: - if (GLAD_VERSION_1_0) - return GLAD_VERSION_3_0 || GLAD_ARB_texture_float; - else if (!rendertarget) - return GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float; - else - return false; + if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float)) + flags |= commonsample | commonrender; + if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float) + flags |= commonsample; + break; case PIXELFORMAT_LA8_UNORM: - return !rendertarget; + flags |= commonsample; + break; case PIXELFORMAT_RGBA4_UNORM: case PIXELFORMAT_RGB5A1_UNORM: - return true; + flags |= commonsample | commonrender; + break; case PIXELFORMAT_RGB565_UNORM: - return GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility; + if (GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility) + flags |= commonsample | commonrender; + break; case PIXELFORMAT_RGB10A2_UNORM: - return GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0; + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0) + flags |= commonsample | commonrender; + break; case PIXELFORMAT_RG11B10_FLOAT: - if (rendertarget) - return GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_color_buffer_packed_float; - else - return GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float; + if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float) + flags |= commonsample; + if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_color_buffer_packed_float) + flags |= commonrender; + break; case PIXELFORMAT_STENCIL8: - return rendertarget && !readable; + flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA; + break; case PIXELFORMAT_DEPTH16_UNORM: - if (!rendertarget) - return false; - else if (readable) - return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth_texture; - else - return true; + flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA; + if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth_texture) + flags |= commonsample; + break; case PIXELFORMAT_DEPTH24_UNORM: - if (!rendertarget) - return false; - else if (readable) - return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || (GLAD_OES_depth_texture && (GLAD_OES_depth24 || GLAD_OES_depth_texture)); - else - return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth24 || GLAD_OES_depth_texture; + if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth24 || GLAD_OES_depth_texture) + flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA; + + if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || (GLAD_OES_depth_texture && (GLAD_OES_depth24 || GLAD_OES_depth_texture))) + flags |= commonsample; + break; case PIXELFORMAT_DEPTH24_UNORM_STENCIL8: - if (!rendertarget) - return false; - else if (readable) - return GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || (GLAD_OES_depth_texture && GLAD_OES_packed_depth_stencil); - else - return GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || GLAD_OES_packed_depth_stencil; + if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || GLAD_OES_packed_depth_stencil) + flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA; + + if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || (GLAD_OES_depth_texture && GLAD_OES_packed_depth_stencil)) + flags |= commonsample; + break; case PIXELFORMAT_DEPTH32_FLOAT: case PIXELFORMAT_DEPTH32_FLOAT_STENCIL8: - return rendertarget && (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_depth_buffer_float); + if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_depth_buffer_float) + flags |= commonsample | PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA; + break; case PIXELFORMAT_DXT1_UNORM: - return GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1; + if (GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1) + flags |= commonsample; + break; case PIXELFORMAT_DXT3_UNORM: - return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3; + if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3) + flags |= commonsample; + break; case PIXELFORMAT_DXT5_UNORM: - return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5; + if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5) + flags |= commonsample; + break; case PIXELFORMAT_BC4_UNORM: case PIXELFORMAT_BC4_SNORM: case PIXELFORMAT_BC5_UNORM: case PIXELFORMAT_BC5_SNORM: - return (GLAD_VERSION_3_0 || GLAD_ARB_texture_compression_rgtc || GLAD_EXT_texture_compression_rgtc); + if (GLAD_VERSION_3_0 || GLAD_ARB_texture_compression_rgtc || GLAD_EXT_texture_compression_rgtc) + flags |= commonsample; + break; case PIXELFORMAT_BC6H_UFLOAT: case PIXELFORMAT_BC6H_FLOAT: case PIXELFORMAT_BC7_UNORM: - return GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc; + if (GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc) + flags |= commonsample; + break; case PIXELFORMAT_PVR1_RGB2_UNORM: case PIXELFORMAT_PVR1_RGB4_UNORM: case PIXELFORMAT_PVR1_RGBA2_UNORM: case PIXELFORMAT_PVR1_RGBA4_UNORM: - return isSRGB ? GLAD_EXT_pvrtc_sRGB : GLAD_IMG_texture_compression_pvrtc; + if (GLAD_IMG_texture_compression_pvrtc) + flags |= commonsample; + break; case PIXELFORMAT_ETC1_UNORM: // ETC2 support guarantees ETC1 support as well. - return GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture; + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture) + flags |= commonsample; + break; case PIXELFORMAT_ETC2_RGB_UNORM: case PIXELFORMAT_ETC2_RGBA_UNORM: case PIXELFORMAT_ETC2_RGBA1_UNORM: @@ -2085,7 +2103,9 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, case PIXELFORMAT_EAC_R_SNORM: case PIXELFORMAT_EAC_RG_UNORM: case PIXELFORMAT_EAC_RG_SNORM: - return GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility; + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility) + flags |= commonsample; + break; case PIXELFORMAT_ASTC_4x4: case PIXELFORMAT_ASTC_5x4: case PIXELFORMAT_ASTC_5x5: @@ -2100,11 +2120,18 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, case PIXELFORMAT_ASTC_10x10: case PIXELFORMAT_ASTC_12x10: case PIXELFORMAT_ASTC_12x12: - return GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr; + if (GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr) + flags |= commonsample; + break; - default: - return false; + case PIXELFORMAT_UNKNOWN: + case PIXELFORMAT_NORMAL: + case PIXELFORMAT_HDR: + case PIXELFORMAT_MAX_ENUM: + break; } + + return flags; } bool OpenGL::hasTextureFilteringSupport(PixelFormat pixelformat) diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index d1ac0ae86..48f43f516 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -443,7 +443,7 @@ public: static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB); static bool isTexStorageSupported(); - static bool isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool readable, bool isSRGB); + static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat); static bool hasTextureFilteringSupport(PixelFormat pixelformat); static const char *errorString(GLenum errorcode); From 52238bb7d9f9b7f1ab9d625cb599176bc69fd86e Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 16 Jan 2021 20:34:27 -0400 Subject: [PATCH 03/17] Add optional source data start index arg to Buffer:setArrayData The argument list is now Buffer:setArrayData(data or table, sourceindex=1, destindex=1, count=automatically computed) #1598 --- src/modules/graphics/wrap_Buffer.cpp | 55 +++++++++++++++++++--------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index e15ccb01b..9609ee8a6 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -190,34 +190,49 @@ static int w_Buffer_setArrayData(lua_State *L) { Buffer *t = luax_checkbuffer(L, 1); - int startindex = (int) luaL_optnumber(L, 3, 1) - 1; + int sourceindex = (int) luaL_optnumber(L, 3, 1) - 1; + int destindex = (int) luaL_optnumber(L, 4, 1) - 1; + + if (sourceindex < 0) + return luaL_error(L, "Source start index must be at least 1."); int count = -1; - if (!lua_isnoneornil(L, 4)) + if (!lua_isnoneornil(L, 5)) { - count = (int) luaL_checknumber(L, 4); + count = (int) luaL_checknumber(L, 5); if (count <= 0) return luaL_error(L, "Element count must be greater than 0."); } size_t stride = t->getArrayStride(); - size_t offset = startindex * stride; + size_t bufferoffset = destindex * stride; int arraylength = (int) t->getArrayLength(); - if (startindex >= arraylength || startindex < 0) - return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", arraylength); + if (destindex >= arraylength || destindex < 0) + return luaL_error(L, "Invalid buffer start index (must be between 1 and %d)", arraylength); if (luax_istype(L, 2, Data::type)) { Data *d = luax_checktype(L, 2); - count = count >= 0 ? count : (arraylength - startindex); - if (startindex + count > arraylength) - return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count); + int dataarraylength = d->getSize() / stride; - size_t datasize = std::min(d->getSize(), count * stride); + if (sourceindex >= dataarraylength) + return luaL_error(L, "Invalid data start index (must be between 1 and %d)", dataarraylength); - t->fill(offset, datasize, d->getData()); + int maxcount = std::min(dataarraylength - sourceindex, arraylength - destindex); + + if (count < 0) + count = maxcount; + + if (count > maxcount) + return luaL_error(L, "Too many array elements (expected at most %d, got %d)", maxcount, count); + + size_t dataoffset = sourceindex * stride; + size_t datasize = std::min(d->getSize() - dataoffset, count * stride); + const void *sourcedata = (const uint8 *) d->getData() + dataoffset; + + t->fill(bufferoffset, datasize, sourcedata); return 0; } @@ -241,15 +256,19 @@ static int w_Buffer_setArrayData(lua_State *L) tablelen /= ncomponents; } - count = count >= 0 ? std::min(count, tablelen) : tablelen; - if (startindex + count > arraylength) - return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count); + if (sourceindex >= tablelen) + return luaL_error(L, "Invalid data start index (must be between 1 and %d)", tablelen); - char *data = (char *) t->map(Buffer::MAP_WRITE_INVALIDATE, offset, count * stride); + count = count >= 0 ? std::min(count, tablelen - sourceindex) : tablelen - sourceindex; + + if (destindex + count > arraylength) + return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - destindex, count); + + char *data = (char *) t->map(Buffer::MAP_WRITE_INVALIDATE, bufferoffset, count * stride); if (tableoftables) { - for (int i = 0; i < count; i++) + for (int i = sourceindex; i < count; i++) { // get arraydata[index] lua_rawgeti(L, 2, i + 1); @@ -273,7 +292,7 @@ static int w_Buffer_setArrayData(lua_State *L) } else // Flat array { - for (int i = 0; i < count; i++) + for (int i = sourceindex; i < count; i++) { // get arraydata[arrayindex * ncomponents + componentindex] for (int componentindex = 1; componentindex <= ncomponents; componentindex++) @@ -292,7 +311,7 @@ static int w_Buffer_setArrayData(lua_State *L) } } - t->unmap(offset, count * stride); + t->unmap(bufferoffset, count * stride); return 0; } From e1f40b433d29954cf7ffa238c36a9c63630c018e Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 16 Jan 2021 20:51:06 -0400 Subject: [PATCH 04/17] Clean up some graphics enum declaration code --- src/modules/graphics/Graphics.cpp | 200 +++++++----------------------- src/modules/graphics/Graphics.h | 53 ++------ 2 files changed, 54 insertions(+), 199 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 25b1ad775..59632ff47 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -1792,179 +1792,73 @@ Vector2 Graphics::inverseTransformPoint(Vector2 point) return p; } -/** - * Constants. - **/ - -bool Graphics::getConstant(const char *in, DrawMode &out) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::DrawMode, Graphics::DRAW_MAX_ENUM, drawMode) { - return drawModes.find(in, out); + { "line", Graphics::DRAW_LINE }, + { "fill", Graphics::DRAW_FILL }, } +STRINGMAP_CLASS_END(Graphics, Graphics::DrawMode, Graphics::DRAW_MAX_ENUM, drawMode) -bool Graphics::getConstant(DrawMode in, const char *&out) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::ArcMode, Graphics::ARC_MAX_ENUM, arcMode) { - return drawModes.find(in, out); + { "open", Graphics::ARC_OPEN }, + { "closed", Graphics::ARC_CLOSED }, + { "pie", Graphics::ARC_PIE }, } +STRINGMAP_CLASS_END(Graphics, Graphics::ArcMode, Graphics::ARC_MAX_ENUM, arcMode) -std::vector Graphics::getConstants(DrawMode) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::LineStyle, Graphics::LINE_MAX_ENUM, lineStyle) { - return drawModes.getNames(); + { "smooth", Graphics::LINE_SMOOTH }, + { "rough", Graphics::LINE_ROUGH } } +STRINGMAP_CLASS_END(Graphics, Graphics::LineStyle, Graphics::LINE_MAX_ENUM, lineStyle) -bool Graphics::getConstant(const char *in, ArcMode &out) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM, lineJoin) { - return arcModes.find(in, out); + { "none", Graphics::LINE_JOIN_NONE }, + { "miter", Graphics::LINE_JOIN_MITER }, + { "bevel", Graphics::LINE_JOIN_BEVEL } } +STRINGMAP_CLASS_END(Graphics, Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM, lineJoin) -bool Graphics::getConstant(ArcMode in, const char *&out) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, feature) { - return arcModes.find(in, out); + { "multirendertargetformats", Graphics::FEATURE_MULTI_RENDER_TARGET_FORMATS }, + { "clampzero", Graphics::FEATURE_CLAMP_ZERO }, + { "blendminmax", Graphics::FEATURE_BLEND_MINMAX }, + { "lighten", Graphics::FEATURE_LIGHTEN }, + { "fullnpot", Graphics::FEATURE_FULL_NPOT }, + { "pixelshaderhighp", Graphics::FEATURE_PIXEL_SHADER_HIGHP }, + { "shaderderivatives", Graphics::FEATURE_SHADER_DERIVATIVES }, + { "glsl3", Graphics::FEATURE_GLSL3 }, + { "glsl4", Graphics::FEATURE_GLSL4 }, + { "instancing", Graphics::FEATURE_INSTANCING }, + { "texelbuffer", Graphics::FEATURE_TEXEL_BUFFER }, } +STRINGMAP_CLASS_END(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, feature) -std::vector Graphics::getConstants(ArcMode) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM, systemLimit) { - return arcModes.getNames(); + { "pointsize", Graphics::LIMIT_POINT_SIZE }, + { "texturesize", Graphics::LIMIT_TEXTURE_SIZE }, + { "texturelayers", Graphics::LIMIT_TEXTURE_LAYERS }, + { "volumetexturesize", Graphics::LIMIT_VOLUME_TEXTURE_SIZE }, + { "cubetexturesize", Graphics::LIMIT_CUBE_TEXTURE_SIZE }, + { "texelbuffersize", Graphics::LIMIT_TEXEL_BUFFER_SIZE }, + { "shaderstoragebuffersize", Graphics::LIMIT_SHADER_STORAGE_BUFFER_SIZE }, + { "rendertargets", Graphics::LIMIT_RENDER_TARGETS }, + { "texturemsaa", Graphics::LIMIT_TEXTURE_MSAA }, + { "anisotropy", Graphics::LIMIT_ANISOTROPY }, } +STRINGMAP_CLASS_END(Graphics, Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM, systemLimit) -bool Graphics::getConstant(const char *in, LineStyle &out) +STRINGMAP_CLASS_BEGIN(Graphics, Graphics::StackType, Graphics::STACK_MAX_ENUM, stackType) { - return lineStyles.find(in, out); + { "all", Graphics::STACK_ALL }, + { "transform", Graphics::STACK_TRANSFORM }, } - -bool Graphics::getConstant(LineStyle in, const char *&out) -{ - return lineStyles.find(in, out); -} - -std::vector Graphics::getConstants(LineStyle) -{ - return lineStyles.getNames(); -} - -bool Graphics::getConstant(const char *in, LineJoin &out) -{ - return lineJoins.find(in, out); -} - -bool Graphics::getConstant(LineJoin in, const char *&out) -{ - return lineJoins.find(in, out); -} - -std::vector Graphics::getConstants(LineJoin) -{ - return lineJoins.getNames(); -} - -bool Graphics::getConstant(const char *in, Feature &out) -{ - return features.find(in, out); -} - -bool Graphics::getConstant(Feature in, const char *&out) -{ - return features.find(in, out); -} - -bool Graphics::getConstant(const char *in, SystemLimit &out) -{ - return systemLimits.find(in, out); -} - -bool Graphics::getConstant(SystemLimit in, const char *&out) -{ - return systemLimits.find(in, out); -} - -bool Graphics::getConstant(const char *in, StackType &out) -{ - return stackTypes.find(in, out); -} - -bool Graphics::getConstant(StackType in, const char *&out) -{ - return stackTypes.find(in, out); -} - -std::vector Graphics::getConstants(StackType) -{ - return stackTypes.getNames(); -} - -StringMap::Entry Graphics::drawModeEntries[] = -{ - { "line", DRAW_LINE }, - { "fill", DRAW_FILL }, -}; - -StringMap Graphics::drawModes(Graphics::drawModeEntries, sizeof(Graphics::drawModeEntries)); - -StringMap::Entry Graphics::arcModeEntries[] = -{ - { "open", ARC_OPEN }, - { "closed", ARC_CLOSED }, - { "pie", ARC_PIE }, -}; - -StringMap Graphics::arcModes(Graphics::arcModeEntries, sizeof(Graphics::arcModeEntries)); - -StringMap::Entry Graphics::lineStyleEntries[] = -{ - { "smooth", LINE_SMOOTH }, - { "rough", LINE_ROUGH } -}; - -StringMap Graphics::lineStyles(Graphics::lineStyleEntries, sizeof(Graphics::lineStyleEntries)); - -StringMap::Entry Graphics::lineJoinEntries[] = -{ - { "none", LINE_JOIN_NONE }, - { "miter", LINE_JOIN_MITER }, - { "bevel", LINE_JOIN_BEVEL } -}; - -StringMap Graphics::lineJoins(Graphics::lineJoinEntries, sizeof(Graphics::lineJoinEntries)); - -StringMap::Entry Graphics::featureEntries[] = -{ - { "multirendertargetformats", FEATURE_MULTI_RENDER_TARGET_FORMATS }, - { "clampzero", FEATURE_CLAMP_ZERO }, - { "blendminmax", FEATURE_BLEND_MINMAX }, - { "lighten", FEATURE_LIGHTEN }, - { "fullnpot", FEATURE_FULL_NPOT }, - { "pixelshaderhighp", FEATURE_PIXEL_SHADER_HIGHP }, - { "shaderderivatives", FEATURE_SHADER_DERIVATIVES }, - { "glsl3", FEATURE_GLSL3 }, - { "glsl4", FEATURE_GLSL4 }, - { "instancing", FEATURE_INSTANCING }, - { "texelbuffer", FEATURE_TEXEL_BUFFER }, -}; - -StringMap Graphics::features(Graphics::featureEntries, sizeof(Graphics::featureEntries)); - -StringMap::Entry Graphics::systemLimitEntries[] = -{ - { "pointsize", LIMIT_POINT_SIZE }, - { "texturesize", LIMIT_TEXTURE_SIZE }, - { "texturelayers", LIMIT_TEXTURE_LAYERS }, - { "volumetexturesize", LIMIT_VOLUME_TEXTURE_SIZE }, - { "cubetexturesize", LIMIT_CUBE_TEXTURE_SIZE }, - { "texelbuffersize", LIMIT_TEXEL_BUFFER_SIZE }, - { "shaderstoragebuffersize", LIMIT_SHADER_STORAGE_BUFFER_SIZE }, - { "rendertargets", LIMIT_RENDER_TARGETS }, - { "texturemsaa", LIMIT_TEXTURE_MSAA }, - { "anisotropy", LIMIT_ANISOTROPY }, -}; - -StringMap Graphics::systemLimits(Graphics::systemLimitEntries, sizeof(Graphics::systemLimitEntries)); - -StringMap::Entry Graphics::stackTypeEntries[] = -{ - { "all", STACK_ALL }, - { "transform", STACK_TRANSFORM }, -}; - -StringMap Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries)); +STRINGMAP_CLASS_END(Graphics, Graphics::StackType, Graphics::STACK_MAX_ENUM, stackType) } // graphics } // love diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 999d8a1fa..e7cc43a88 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -840,31 +840,13 @@ public: return (T *) scratchBuffer.data(); } - static bool getConstant(const char *in, DrawMode &out); - static bool getConstant(DrawMode in, const char *&out); - static std::vector getConstants(DrawMode); - - static bool getConstant(const char *in, ArcMode &out); - static bool getConstant(ArcMode in, const char *&out); - static std::vector getConstants(ArcMode); - - static bool getConstant(const char *in, LineStyle &out); - static bool getConstant(LineStyle in, const char *&out); - static std::vector getConstants(LineStyle); - - static bool getConstant(const char *in, LineJoin &out); - static bool getConstant(LineJoin in, const char *&out); - static std::vector getConstants(LineJoin); - - static bool getConstant(const char *in, Feature &out); - static bool getConstant(Feature in, const char *&out); - - static bool getConstant(const char *in, SystemLimit &out); - static bool getConstant(SystemLimit in, const char *&out); - - static bool getConstant(const char *in, StackType &out); - static bool getConstant(StackType in, const char *&out); - static std::vector getConstants(StackType); + STRINGMAP_CLASS_DECLARE(DrawMode); + STRINGMAP_CLASS_DECLARE(ArcMode); + STRINGMAP_CLASS_DECLARE(LineStyle); + STRINGMAP_CLASS_DECLARE(LineJoin); + STRINGMAP_CLASS_DECLARE(Feature); + STRINGMAP_CLASS_DECLARE(SystemLimit); + STRINGMAP_CLASS_DECLARE(StackType); protected: @@ -1011,27 +993,6 @@ private: std::unordered_map cachedShaderStages[ShaderStage::STAGE_MAX_ENUM]; - static StringMap::Entry drawModeEntries[]; - static StringMap drawModes; - - static StringMap::Entry arcModeEntries[]; - static StringMap arcModes; - - static StringMap::Entry lineStyleEntries[]; - static StringMap lineStyles; - - static StringMap::Entry lineJoinEntries[]; - static StringMap lineJoins; - - static StringMap::Entry featureEntries[]; - static StringMap features; - - static StringMap::Entry systemLimitEntries[]; - static StringMap systemLimits; - - static StringMap::Entry stackTypeEntries[]; - static StringMap stackTypes; - }; // Graphics } // graphics From e2838131f236a5e7954e3a82410edfb9ba1d8254 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 17 Jan 2021 14:02:00 -0400 Subject: [PATCH 05/17] Add love.graphics.copyBuffer. --- src/common/Range.h | 5 +++++ src/modules/graphics/Buffer.cpp | 4 ++++ src/modules/graphics/Buffer.h | 7 ++++++ src/modules/graphics/Graphics.cpp | 27 ++++++++++++++++++++++++ src/modules/graphics/Graphics.h | 3 +++ src/modules/graphics/opengl/Buffer.cpp | 8 +++++++ src/modules/graphics/opengl/Buffer.h | 1 + src/modules/graphics/opengl/Graphics.cpp | 3 ++- src/modules/graphics/opengl/OpenGL.cpp | 5 +++++ src/modules/graphics/vertex.cpp | 2 ++ src/modules/graphics/vertex.h | 2 ++ src/modules/graphics/wrap_Graphics.cpp | 23 ++++++++++++++++++++ 12 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/common/Range.h b/src/common/Range.h index d150919f8..6dc892d5f 100644 --- a/src/common/Range.h +++ b/src/common/Range.h @@ -61,6 +61,11 @@ struct Range return first <= other.first && last >= other.last; } + bool intersects(const Range &other) + { + return !(first > other.last || last < other.first); + } + void encapsulate(size_t index) { first = std::min(first, index); diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index aaf9b2228..6c34100f2 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -50,6 +50,7 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorgetTypeFlags() & Buffer::TYPEFLAG_COPY_SOURCE)) + throw love::Exception("Copy source buffer must be created with the copysource flag."); + + if (!(dest->getTypeFlags() & Buffer::TYPEFLAG_COPY_DEST)) + throw love::Exception("Copy destination buffer must be created with the copydest flag."); + + Range sourcerange(sourceoffset, size); + Range destrange(destoffset, size); + + if (sourcerange.getMax() >= source->getSize()) + throw love::Exception("Buffer copy source offset and size doesn't fit within the source Buffer's size."); + + if (destrange.getMax() >= dest->getSize()) + throw love::Exception("Buffer copy destination offset and size doesn't fit within the destination buffer's size."); + + if (source == dest && sourcerange.intersects(destrange)) + throw love::Exception("Copying a portion of a buffer to the same buffer requires non-overlapping source and destination offsets."); + + source->copyTo(dest, sourceoffset, destoffset, size); +} + Graphics::BatchedVertexData Graphics::requestBatchedDraw(const BatchedDrawCommand &cmd) { BatchedDrawState &state = batchedDrawState; @@ -1835,6 +1861,7 @@ STRINGMAP_CLASS_BEGIN(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, f { "glsl4", Graphics::FEATURE_GLSL4 }, { "instancing", Graphics::FEATURE_INSTANCING }, { "texelbuffer", Graphics::FEATURE_TEXEL_BUFFER }, + { "copybuffer", Graphics::FEATURE_COPY_BUFFER }, } STRINGMAP_CLASS_END(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, feature) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index e7cc43a88..1bbdfff70 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -144,6 +144,7 @@ public: FEATURE_GLSL4, FEATURE_INSTANCING, FEATURE_TEXEL_BUFFER, + FEATURE_COPY_BUFFER, FEATURE_MAX_ENUM }; @@ -668,6 +669,8 @@ public: void captureScreenshot(const ScreenshotInfo &info); + void copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size); + void draw(Drawable *drawable, const Matrix4 &m); void draw(Texture *texture, Quad *quad, const Matrix4 &m); void drawLayer(Texture *texture, int layer, const Matrix4 &m); diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index a9e33c0f9..e6ace77ad 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -253,6 +253,14 @@ void Buffer::fill(size_t offset, size_t size, const void *data) } } +void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) +{ + gl.bindBuffer(BUFFERTYPE_COPY_SOURCE, buffer); + gl.bindBuffer(BUFFERTYPE_COPY_DEST, ((Buffer *) dest)->buffer); + + glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sourceoffset, destoffset, size); +} + } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index db0ae85fe..b875d862f 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -53,6 +53,7 @@ public: void *map(MapType map, size_t offset, size_t size) override; void unmap(size_t usedoffset, size_t usedsize) override; void fill(size_t offset, size_t size, const void *data) override; + void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override; ptrdiff_t getHandle() const override { return buffer; }; ptrdiff_t getTexelBufferHandle() const override { return texture; }; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 9375e2161..1384fbd72 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1531,7 +1531,8 @@ void Graphics::initCapabilities() capabilities.features[FEATURE_GLSL4] = GLAD_ES_VERSION_3_1 || (gl.isCoreProfile() && GLAD_VERSION_4_3); capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported(); capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_TEXEL); - static_assert(FEATURE_MAX_ENUM == 11, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); + capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_COPY_SOURCE); + static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize(); capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize(); diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index d6522d6d5..e7d0ddb69 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -621,6 +621,8 @@ GLenum OpenGL::getGLBufferType(BufferType type) case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; case BUFFERTYPE_TEXEL: return GL_TEXTURE_BUFFER; case BUFFERTYPE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER; + case BUFFERTYPE_COPY_SOURCE: return GL_COPY_READ_BUFFER; + case BUFFERTYPE_COPY_DEST: return GL_COPY_WRITE_BUFFER; case BUFFERTYPE_MAX_ENUM: return GL_ZERO; } @@ -1444,6 +1446,9 @@ bool OpenGL::isBufferTypeSupported(BufferType type) const return GLAD_VERSION_3_1; case BUFFERTYPE_SHADER_STORAGE: return (GLAD_VERSION_4_3 && isCoreProfile()) || GLAD_ES_VERSION_3_1; + case BUFFERTYPE_COPY_SOURCE: + case BUFFERTYPE_COPY_DEST: + return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0; case BUFFERTYPE_MAX_ENUM: return false; } diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index d448b9895..91c168edd 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -343,6 +343,8 @@ STRINGMAP_BEGIN(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) { "index", BUFFERTYPE_INDEX }, { "texel", BUFFERTYPE_TEXEL }, { "shaderstorage", BUFFERTYPE_SHADER_STORAGE }, + { "copysource", BUFFERTYPE_COPY_SOURCE }, + { "copydest", BUFFERTYPE_COPY_DEST }, } STRINGMAP_END(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 21ff230ce..45e320ea9 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -60,6 +60,8 @@ enum BufferType BUFFERTYPE_INDEX, BUFFERTYPE_TEXEL, BUFFERTYPE_SHADER_STORAGE, + BUFFERTYPE_COPY_SOURCE, + BUFFERTYPE_COPY_DEST, BUFFERTYPE_MAX_ENUM }; diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 713e5b5dd..3b2a45415 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3255,6 +3255,27 @@ int w_polygon(lua_State *L) return 0; } +int w_copyBuffer(lua_State *L) +{ + Buffer *source = luax_checkbuffer(L, 1); + Buffer *dest = luax_checkbuffer(L, 2); + + ssize_t sourceoffset = luaL_optinteger(L, 3, 0); + ssize_t destoffset = luaL_optinteger(L, 4, 0); + + ssize_t size = std::min(source->getSize() - sourceoffset, dest->getSize() - destoffset); + if (!lua_isnoneornil(L, 5)) + size = luaL_checkinteger(L, 5); + + if (sourceoffset < 0 || destoffset < 0) + return luaL_error(L, "copyBuffer offsets cannot be negative."); + if (size <= 0) + return luaL_error(L, "copyBuffer size must be greater than 0."); + + luax_catchexcept(L, [&](){ instance()->copyBuffer(source, dest, sourceoffset, destoffset, size); }); + return 0; +} + int w_flushBatch(lua_State *) { instance()->flushBatchedDraws(); @@ -3451,6 +3472,8 @@ static const luaL_Reg functions[] = { "print", w_print }, { "printf", w_printf }, + { "copyBuffer", w_copyBuffer }, + { "isCreated", w_isCreated }, { "isActive", w_isActive }, { "isGammaCorrect", w_isGammaCorrect }, From ef5a0250e9bc96697c0dba9127f338b9c5353e16 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 17 Jan 2021 14:13:16 -0400 Subject: [PATCH 06/17] Fix compilation on windows --- src/modules/graphics/wrap_Graphics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 3b2a45415..5c8f90a3f 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3260,10 +3260,10 @@ int w_copyBuffer(lua_State *L) Buffer *source = luax_checkbuffer(L, 1); Buffer *dest = luax_checkbuffer(L, 2); - ssize_t sourceoffset = luaL_optinteger(L, 3, 0); - ssize_t destoffset = luaL_optinteger(L, 4, 0); + ptrdiff_t sourceoffset = luaL_optinteger(L, 3, 0); + ptrdiff_t destoffset = luaL_optinteger(L, 4, 0); - ssize_t size = std::min(source->getSize() - sourceoffset, dest->getSize() - destoffset); + ptrdiff_t size = std::min(source->getSize() - sourceoffset, dest->getSize() - destoffset); if (!lua_isnoneornil(L, 5)) size = luaL_checkinteger(L, 5); From 4244e01a35db04d6ea625c4c52ca910d98c414e8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 17 Jan 2021 14:48:35 -0400 Subject: [PATCH 07/17] More texture format support cleanup --- src/modules/graphics/opengl/OpenGL.cpp | 25 ++++++++----------------- src/modules/graphics/opengl/OpenGL.h | 1 - src/modules/graphics/opengl/Texture.cpp | 4 +++- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index e7d0ddb69..4583c3a9f 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -1986,6 +1986,8 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample; if (GLAD_EXT_color_buffer_half_float && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)) flags |= commonrender; + if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) + flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; break; case PIXELFORMAT_RGBA16_FLOAT: if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel)) @@ -1994,6 +1996,8 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample; if (GLAD_EXT_color_buffer_half_float) flags |= commonrender; + if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) + flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; break; case PIXELFORMAT_R32_FLOAT: case PIXELFORMAT_RG32_FLOAT: @@ -2001,12 +2005,16 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg)) flags |= commonsample; + if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) + flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; break; case PIXELFORMAT_RGBA32_FLOAT: if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float)) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float) flags |= commonsample; + if (!(GLAD_VERSION_1_1 || GLAD_OES_texture_float_linear)) + flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; break; case PIXELFORMAT_LA8_UNORM: @@ -2139,23 +2147,6 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) return flags; } -bool OpenGL::hasTextureFilteringSupport(PixelFormat pixelformat) -{ - switch (pixelformat) - { - case PIXELFORMAT_R16_FLOAT: - case PIXELFORMAT_RG16_FLOAT: - case PIXELFORMAT_RGBA16_FLOAT: - return GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear; - case PIXELFORMAT_R32_FLOAT: - case PIXELFORMAT_RG32_FLOAT: - case PIXELFORMAT_RGBA32_FLOAT: - return GLAD_VERSION_1_1 || GLAD_OES_texture_float_linear; - default: - return true; - } -} - const char *OpenGL::errorString(GLenum errorcode) { switch (errorcode) diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 48f43f516..b964896a4 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -444,7 +444,6 @@ public: static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB); static bool isTexStorageSupported(); static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat); - static bool hasTextureFilteringSupport(PixelFormat pixelformat); static const char *errorString(GLenum errorcode); static const char *framebufferStatusString(GLenum status); diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 2d7c8a62f..bef283dde 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -539,7 +539,9 @@ void Texture::setSamplerState(const SamplerState &s) // Base class does common validation and assigns samplerState. love::graphics::Texture::setSamplerState(s); - if (!OpenGL::hasTextureFilteringSupport(getPixelFormat())) + auto supportedflags = OpenGL::getPixelFormatUsageFlags(getPixelFormat()); + + if ((supportedflags & PIXELFORMATUSAGEFLAGS_LINEAR) == 0) { samplerState.magFilter = samplerState.minFilter = SamplerState::FILTER_NEAREST; From 2e2ebe95cdc9e89898d6f301d9ff65eb72299d2b Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 17 Jan 2021 16:50:44 -0400 Subject: [PATCH 08/17] Clean up some obsolete internal graphics code --- src/modules/graphics/Texture.cpp | 4 ++-- src/modules/graphics/Texture.h | 2 +- src/modules/graphics/opengl/Buffer.cpp | 4 ++++ src/modules/graphics/opengl/Texture.cpp | 14 ++------------ src/modules/graphics/opengl/Texture.h | 2 +- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index b320865b5..9b3a73698 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -421,7 +421,7 @@ void Texture::uploadImageData(love::image::ImageDataBase *d, int level, int slic lock.setLock(id->getMutex()); Rect rect = {x, y, d->getWidth(), d->getHeight()}; - uploadByteData(d->getFormat(), d->getData(), d->getSize(), level, slice, rect, d); + uploadByteData(d->getFormat(), d->getData(), d->getSize(), level, slice, rect); } void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, int x, int y, bool reloadmipmaps) @@ -487,7 +487,7 @@ void Texture::replacePixels(const void *data, size_t size, int slice, int mipmap Graphics::flushBatchedDrawsGlobal(); - uploadByteData(format, data, size, mipmap, slice, rect, nullptr); + uploadByteData(format, data, size, mipmap, slice, rect); if (reloadmipmaps && mipmap == 0 && getMipmapCount() > 1) generateMipmaps(); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index 8c73e1d6c..c56ae6e12 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -296,7 +296,7 @@ protected: void setGraphicsMemorySize(int64 size); void uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y); - virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) = 0; + virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) = 0; virtual void generateMipmapsInternal() = 0; virtual void readbackImageData(love::image::ImageData *imagedata, int slice, int mipmap, const Rect &rect) = 0; diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index e6ace77ad..30196a396 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -80,6 +80,10 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st mapType = BUFFERTYPE_INDEX; else if (typeFlags & TYPEFLAG_SHADER_STORAGE) mapType = BUFFERTYPE_SHADER_STORAGE; + else if (typeFlags & TYPEFLAG_COPY_SOURCE) + mapType = BUFFERTYPE_COPY_SOURCE; + else if (typeFlags & TYPEFLAG_COPY_DEST) + mapType = BUFFERTYPE_COPY_DEST; target = OpenGL::getGLBufferType(mapType); diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index bef283dde..00f30d640 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -251,7 +251,7 @@ void Texture::createTexture() int slices = texType == TEXTURE_CUBE ? 6 : 1; Rect rect = {0, 0, 2, 2}; for (int slice = 0; slice < slices; slice++) - uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect, nullptr); + uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect); return; } @@ -452,18 +452,8 @@ void Texture::unloadVolatile() setGraphicsMemorySize(0); } -void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd) +void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) { - love::image::ImageDataBase *oldd = slices.get(slice, level); - - // We can only replace the internal Data (used when reloading due to setMode) - // if the dimensions match. - if (imgd != nullptr && oldd != nullptr && oldd->getWidth() == imgd->getWidth() - && oldd->getHeight() == imgd->getHeight()) - { - slices.set(slice, level, imgd); - } - OpenGL::TempDebugGroup debuggroup("Texture data upload"); gl.bindTextureToUnit(this, 0, false); diff --git a/src/modules/graphics/opengl/Texture.h b/src/modules/graphics/opengl/Texture.h index 9619a8a1c..40f9f26e9 100644 --- a/src/modules/graphics/opengl/Texture.h +++ b/src/modules/graphics/opengl/Texture.h @@ -58,7 +58,7 @@ private: void createTexture(); - void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) override; + void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override; void generateMipmapsInternal() override; From deff79590899ba43ef2ccd17cf990f2fd56d04f0 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 17 Jan 2021 20:59:16 -0400 Subject: [PATCH 09/17] Rename some internal buffer enums to better match what they do --- src/modules/graphics/Buffer.cpp | 18 +++--- src/modules/graphics/Buffer.h | 31 +++------ src/modules/graphics/Graphics.cpp | 16 ++--- src/modules/graphics/Graphics.h | 8 +-- src/modules/graphics/Mesh.cpp | 24 +++---- src/modules/graphics/Mesh.h | 4 +- src/modules/graphics/ParticleSystem.cpp | 2 +- src/modules/graphics/SpriteBatch.cpp | 10 +-- src/modules/graphics/SpriteBatch.h | 2 +- src/modules/graphics/StreamBuffer.cpp | 2 +- src/modules/graphics/StreamBuffer.h | 6 +- src/modules/graphics/Text.cpp | 4 +- src/modules/graphics/opengl/Buffer.cpp | 54 ++++++++-------- src/modules/graphics/opengl/Buffer.h | 2 +- src/modules/graphics/opengl/Graphics.cpp | 38 +++++------ src/modules/graphics/opengl/Graphics.h | 4 +- src/modules/graphics/opengl/OpenGL.cpp | 66 ++++++++++---------- src/modules/graphics/opengl/OpenGL.h | 14 ++--- src/modules/graphics/opengl/Shader.cpp | 12 ++-- src/modules/graphics/opengl/StreamBuffer.cpp | 14 ++--- src/modules/graphics/opengl/StreamBuffer.h | 2 +- src/modules/graphics/vertex.cpp | 26 ++++---- src/modules/graphics/vertex.h | 41 +++++++----- src/modules/graphics/wrap_Buffer.cpp | 8 +-- src/modules/graphics/wrap_Graphics.cpp | 24 +++---- 25 files changed, 217 insertions(+), 215 deletions(-) diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 6c34100f2..380e5173c 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -33,8 +33,8 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorgetCapabilities(); bool supportsGLSL3 = caps.features[Graphics::FEATURE_GLSL3]; - bool indexbuffer = settings.typeFlags & TYPEFLAG_INDEX; - bool vertexbuffer = settings.typeFlags & TYPEFLAG_VERTEX; - bool texelbuffer = settings.typeFlags & TYPEFLAG_TEXEL; - bool storagebuffer = settings.typeFlags & TYPEFLAG_SHADER_STORAGE; - bool copydest = settings.typeFlags & TYPEFLAG_COPY_DEST; + bool indexbuffer = settings.usageFlags & BUFFERUSAGEFLAG_INDEX; + bool vertexbuffer = settings.usageFlags & BUFFERUSAGEFLAG_VERTEX; + bool texelbuffer = settings.usageFlags & BUFFERUSAGEFLAG_TEXEL; + bool storagebuffer = settings.usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE; + bool copydest = settings.usageFlags & BUFFERUSAGEFLAG_COPY_DEST; if (!indexbuffer && !vertexbuffer && !texelbuffer && !storagebuffer) throw love::Exception("Buffer must be created with at least one buffer type (index, vertex, texel, or shaderstorage)."); @@ -61,8 +61,8 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) +Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferDataUsage usage) { return new Mesh(this, vertexformat, vertexcount, drawmode, usage); } -Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) +Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferDataUsage usage) { return new Mesh(this, vertexformat, data, datasize, drawmode, usage); } @@ -1044,10 +1044,10 @@ void Graphics::copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, siz if (!capabilities.features[FEATURE_COPY_BUFFER]) throw love::Exception("Buffer copying is not supported on this system."); - if (!(source->getTypeFlags() & Buffer::TYPEFLAG_COPY_SOURCE)) + if (!(source->getUsageFlags() & BUFFERUSAGEFLAG_COPY_SOURCE)) throw love::Exception("Copy source buffer must be created with the copysource flag."); - if (!(dest->getTypeFlags() & Buffer::TYPEFLAG_COPY_DEST)) + if (!(dest->getUsageFlags() & BUFFERUSAGEFLAG_COPY_DEST)) throw love::Exception("Copy destination buffer must be created with the copydest flag."); Range sourcerange(sourceoffset, size); @@ -1151,14 +1151,14 @@ Graphics::BatchedVertexData Graphics::requestBatchedDraw(const BatchedDrawComman if (state.vb[i]->getSize() < buffersizes[i]) { delete state.vb[i]; - state.vb[i] = newStreamBuffer(BUFFERTYPE_VERTEX, buffersizes[i]); + state.vb[i] = newStreamBuffer(BUFFERUSAGE_VERTEX, buffersizes[i]); } } if (state.indexBuffer->getSize() < buffersizes[2]) { delete state.indexBuffer; - state.indexBuffer = newStreamBuffer(BUFFERTYPE_INDEX, buffersizes[2]); + state.indexBuffer = newStreamBuffer(BUFFERUSAGE_INDEX, buffersizes[2]); } } diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 1bbdfff70..67a0198a0 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -432,7 +432,7 @@ public: Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting); Video *newVideo(love::video::VideoStream *stream, float dpiscale); - SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferUsage usage); + SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferDataUsage usage); ParticleSystem *newParticleSystem(Texture *texture, int size); Shader *newShader(const std::vector &stagessource); @@ -440,8 +440,8 @@ public: virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) = 0; virtual Buffer *newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength); - Mesh *newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); - Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); + Mesh *newMesh(const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferDataUsage usage); + Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferDataUsage usage); Mesh *newMesh(const std::vector &attributes, PrimitiveType drawmode); Text *newText(Font *font, const std::vector &text = {}); @@ -930,7 +930,7 @@ protected: ShaderStage *newShaderStage(ShaderStage::StageType stage, const std::string &source, const Shader::SourceInfo &info); virtual ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0; virtual Shader *newShaderInternal(ShaderStage *vertex, ShaderStage *pixel) = 0; - virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0; + virtual StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) = 0; virtual void setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBtexture) = 0; diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 46b425394..4c1bfbb71 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -45,7 +45,7 @@ std::vector Mesh::getDefaultVertexFormat() love::Type Mesh::type("Mesh", &Drawable::type); -Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferDataUsage usage) : primitiveType(drawmode) { try @@ -59,7 +59,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & memcpy(vertexData, data, datasize); - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, usage); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, usage); vertexBuffer.set(gfx->newBuffer(settings, vertexformat, vertexData, datasize, 0), Acquire::NORETAIN); vertexCount = vertexBuffer->getArrayLength(); @@ -71,7 +71,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & indexDataType = getIndexDataTypeFromMax(vertexCount); } -Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage) +Mesh::Mesh(graphics::Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferDataUsage usage) : vertexCount((size_t) vertexcount) , indexDataType(getIndexDataTypeFromMax(vertexcount)) , primitiveType(drawmode) @@ -79,7 +79,7 @@ Mesh::Mesh(graphics::Graphics *gfx, const std::vector & if (vertexcount <= 0) throw love::Exception("Invalid number of vertices (%d).", vertexcount); - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, usage); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, usage); vertexBuffer.set(gfx->newBuffer(settings, vertexformat, nullptr, 0, vertexcount), Acquire::NORETAIN); vertexStride = vertexBuffer->getArrayStride(); @@ -112,7 +112,7 @@ Mesh::Mesh(const std::vector &attributes, PrimitiveType d for (const auto &attrib : attachedAttributes) { - if ((attrib.buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) + if ((attrib.buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0) throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); if (getAttachedAttributeIndex(attrib.name) != -1) @@ -210,7 +210,7 @@ bool Mesh::isAttributeEnabled(const std::string &name) const void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, AttributeStep step) { - if ((buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) + 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."); auto gfx = Module::getInstance(Module::M_GRAPHICS); @@ -276,7 +276,7 @@ void Mesh::flush() { if (vertexBuffer.get() && vertexData != nullptr && modifiedVertexData.isValid()) { - if (vertexBuffer->getUsage() == BUFFERUSAGE_STREAM) + if (vertexBuffer->getDataUsage() == BUFFERDATAUSAGE_STREAM) { vertexBuffer->fill(0, vertexBuffer->getSize(), vertexData); } @@ -327,8 +327,8 @@ void Mesh::setVertexMap(const std::vector &map) if (indexBuffer.get() == nullptr || size > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - auto usage = vertexBuffer.get() ? vertexBuffer->getUsage() : BUFFERUSAGE_DYNAMIC; - Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, usage); + auto usage = vertexBuffer.get() ? vertexBuffer->getDataUsage() : BUFFERDATAUSAGE_DYNAMIC; + Buffer::Settings settings(BUFFERUSAGEFLAG_INDEX, usage); indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, size, 0), Acquire::NORETAIN); } @@ -360,8 +360,8 @@ void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasiz if (indexBuffer.get() == nullptr || datasize > indexBuffer->getSize() || indexBuffer->getDataMember(0).decl.format != dataformat) { auto gfx = Module::getInstance(Module::M_GRAPHICS); - auto usage = vertexBuffer.get() ? vertexBuffer->getUsage() : BUFFERUSAGE_DYNAMIC; - Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, usage); + auto usage = vertexBuffer.get() ? vertexBuffer->getDataUsage() : BUFFERDATAUSAGE_DYNAMIC; + Buffer::Settings settings(BUFFERUSAGEFLAG_INDEX, usage); indexBuffer.set(gfx->newBuffer(settings, dataformat, nullptr, datasize, 0), Acquire::NORETAIN); } @@ -423,7 +423,7 @@ void Mesh::setIndexBuffer(Buffer *buffer) { // Buffer constructor does the rest of the validation for index buffers // (data member formats, etc.) - if (buffer != nullptr && (buffer->getTypeFlags() & Buffer::TYPEFLAG_INDEX) == 0) + if (buffer != nullptr && (buffer->getUsageFlags() & BUFFERUSAGEFLAG_INDEX) == 0) throw love::Exception("setIndexBuffer requires a Buffer created as an index buffer."); indexBuffer.set(buffer); diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index b739238a4..bfe2ccec8 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -63,8 +63,8 @@ public: static love::Type type; - Mesh(Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferUsage usage); - Mesh(Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferUsage usage); + Mesh(Graphics *gfx, const std::vector &vertexformat, const void *data, size_t datasize, PrimitiveType drawmode, BufferDataUsage usage); + Mesh(Graphics *gfx, const std::vector &vertexformat, int vertexcount, PrimitiveType drawmode, BufferDataUsage usage); Mesh(const std::vector &attributes, PrimitiveType drawmode); virtual ~Mesh(); diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 5039d4fdf..ab8d4f940 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -191,7 +191,7 @@ void ParticleSystem::createBuffers(size_t size) auto gfx = Module::getInstance(Module::M_GRAPHICS); size_t bytes = sizeof(Vertex) * size * 4; - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, BUFFERUSAGE_STREAM); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STREAM); auto decl = Buffer::getCommonFormatDeclaration(CommonFormat::XYf_STf_RGBAub); buffer = gfx->newBuffer(settings, decl, nullptr, bytes, 0); } diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index 6fd5eaefb..201e10d70 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -40,7 +40,7 @@ namespace graphics love::Type SpriteBatch::type("SpriteBatch", &Drawable::type); -SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage usage) +SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferDataUsage usage) : texture(texture) , size(size) , next(0) @@ -73,7 +73,7 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage memset(vertex_data, 0, vertex_size); - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, usage); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, usage); auto decl = Buffer::getCommonFormatDeclaration(vertex_format); array_buf.set(gfx->newBuffer(settings, decl, nullptr, vertex_size, 0), Acquire::NORETAIN); @@ -185,7 +185,7 @@ void SpriteBatch::flush() size_t offset = modified_sprites.getOffset() * vertex_stride * 4; size_t size = modified_sprites.getSize() * vertex_stride * 4; - if (array_buf->getUsage() == BUFFERUSAGE_STREAM) + if (array_buf->getDataUsage() == BUFFERDATAUSAGE_STREAM) array_buf->fill(0, array_buf->getSize(), vertex_data); else array_buf->fill(offset, size, vertex_data + offset); @@ -244,7 +244,7 @@ void SpriteBatch::setBufferSize(int newsize) throw love::Exception("Out of memory."); auto gfx = Module::getInstance(Module::M_GRAPHICS); - Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getUsage()); + Buffer::Settings settings(array_buf->getUsageFlags(), array_buf->getDataUsage()); auto decl = Buffer::getCommonFormatDeclaration(vertex_format); array_buf.set(gfx->newBuffer(settings, decl, nullptr, vertex_size, 0), Acquire::NORETAIN); @@ -264,7 +264,7 @@ int SpriteBatch::getBufferSize() const void SpriteBatch::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh) { - if ((buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0) + if ((buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0) throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a SpriteBatch vertex attribute."); AttachedAttribute oldattrib = {}; diff --git a/src/modules/graphics/SpriteBatch.h b/src/modules/graphics/SpriteBatch.h index 813bf5d2f..4a0d80cbd 100644 --- a/src/modules/graphics/SpriteBatch.h +++ b/src/modules/graphics/SpriteBatch.h @@ -52,7 +52,7 @@ public: static love::Type type; - SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage usage); + SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferDataUsage usage); virtual ~SpriteBatch(); int add(const Matrix4 &m, int index = -1); diff --git a/src/modules/graphics/StreamBuffer.cpp b/src/modules/graphics/StreamBuffer.cpp index dc532f20a..2440a3902 100644 --- a/src/modules/graphics/StreamBuffer.cpp +++ b/src/modules/graphics/StreamBuffer.cpp @@ -26,7 +26,7 @@ namespace love namespace graphics { -StreamBuffer::StreamBuffer(BufferType mode, size_t size) +StreamBuffer::StreamBuffer(BufferUsage mode, size_t size) : bufferSize(size) , frameGPUReadOffset(0) , mode(mode) diff --git a/src/modules/graphics/StreamBuffer.h b/src/modules/graphics/StreamBuffer.h index 17a6ab573..a669ec78a 100644 --- a/src/modules/graphics/StreamBuffer.h +++ b/src/modules/graphics/StreamBuffer.h @@ -53,7 +53,7 @@ public: virtual ~StreamBuffer() {} size_t getSize() const { return bufferSize; } - BufferType getMode() const { return mode; } + BufferUsage getMode() const { return mode; } size_t getUsableSize() const { return bufferSize - frameGPUReadOffset; } virtual MapInfo map(size_t minsize) = 0; @@ -64,11 +64,11 @@ public: protected: - StreamBuffer(BufferType mode, size_t size); + StreamBuffer(BufferUsage mode, size_t size); size_t bufferSize; size_t frameGPUReadOffset; - BufferType mode; + BufferUsage mode; }; // StreamBuffer diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 3fa4d5ff3..35fa7ef5d 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -63,7 +63,7 @@ void Text::uploadVertices(const std::vector &vertices, size_t auto gfx = Module::getInstance(Module::M_GRAPHICS); - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, BUFFERUSAGE_DYNAMIC); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_DYNAMIC); auto decl = Buffer::getCommonFormatDeclaration(Font::vertexFormat); Buffer *newbuffer = gfx->newBuffer(settings, decl, nullptr, newsize, 0); @@ -279,7 +279,7 @@ void Text::draw(Graphics *gfx, const Matrix4 &m) size_t offset = modifiedVertices.getOffset(); size_t size = modifiedVertices.getSize(); - if (vertexBuffer->getUsage() == BUFFERUSAGE_STREAM) + if (vertexBuffer->getDataUsage() == BUFFERDATAUSAGE_STREAM) vertexBuffer->fill(0, vertexBuffer->getSize(), vertexData); else vertexBuffer->fill(offset, size, vertexData + offset); diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 30196a396..80beb20b3 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -72,22 +72,22 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st size = getSize(); arraylength = getArrayLength(); - if (typeFlags & TYPEFLAG_TEXEL) - mapType = BUFFERTYPE_TEXEL; - else if (typeFlags & TYPEFLAG_VERTEX) - mapType = BUFFERTYPE_VERTEX; - else if (typeFlags & TYPEFLAG_INDEX) - mapType = BUFFERTYPE_INDEX; - else if (typeFlags & TYPEFLAG_SHADER_STORAGE) - mapType = BUFFERTYPE_SHADER_STORAGE; - else if (typeFlags & TYPEFLAG_COPY_SOURCE) - mapType = BUFFERTYPE_COPY_SOURCE; - else if (typeFlags & TYPEFLAG_COPY_DEST) - mapType = BUFFERTYPE_COPY_DEST; + if (usageFlags & BUFFERUSAGEFLAG_TEXEL) + mapUsage = BUFFERUSAGE_TEXEL; + else if (usageFlags & BUFFERUSAGEFLAG_VERTEX) + mapUsage = BUFFERUSAGE_VERTEX; + else if (usageFlags & BUFFERUSAGEFLAG_INDEX) + mapUsage = BUFFERUSAGE_INDEX; + else if (usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE) + mapUsage = BUFFERUSAGE_SHADER_STORAGE; + else if (usageFlags & BUFFERUSAGEFLAG_COPY_SOURCE) + mapUsage = BUFFERUSAGE_COPY_SOURCE; + else if (usageFlags & BUFFERUSAGEFLAG_COPY_DEST) + mapUsage = BUFFERUSAGE_COPY_DEST; - target = OpenGL::getGLBufferType(mapType); + target = OpenGL::getGLBufferType(mapUsage); - if (usage == BUFFERUSAGE_STREAM) + if (dataUsage == BUFFERDATAUSAGE_STREAM) ownsMemoryMap = true; std::vector emptydata; @@ -143,12 +143,14 @@ bool Buffer::load(const void *initialdata) /* Clear the error buffer. */; glGenBuffers(1, &buffer); - gl.bindBuffer(mapType, buffer); + gl.bindBuffer(mapUsage, buffer); + + GLenum gldatausage = OpenGL::getGLBufferDataUsage(getDataUsage()); // initialdata can be null. - glBufferData(target, (GLsizeiptr) getSize(), initialdata, OpenGL::getGLBufferUsage(getUsage())); + glBufferData(target, (GLsizeiptr) getSize(), initialdata, gldatausage); - if (getTypeFlags() & TYPEFLAG_TEXEL) + if (getUsageFlags() & BUFFERUSAGEFLAG_TEXEL) { glGenTextures(1, &texture); gl.bindBufferTextureToUnit(texture, 0, false, true); @@ -204,7 +206,7 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize) mapped = false; // Orphan optimization - see fill(). - if (usage != BUFFERUSAGE_STATIC && mappedRange.first == 0 && mappedRange.getSize() == getSize()) + if (dataUsage != BUFFERDATAUSAGE_STATIC && mappedRange.first == 0 && mappedRange.getSize() == getSize()) { usedoffset = 0; usedsize = getSize(); @@ -232,21 +234,21 @@ void Buffer::fill(size_t offset, size_t size, const void *data) if (!Range(0, buffersize).contains(Range(offset, size))) return; - GLenum glusage = OpenGL::getGLBufferUsage(usage); + GLenum gldatausage = OpenGL::getGLBufferDataUsage(dataUsage); - gl.bindBuffer(mapType, buffer); + gl.bindBuffer(mapUsage, buffer); - if (usage != BUFFERUSAGE_STATIC && size == buffersize) + if (dataUsage != BUFFERDATAUSAGE_STATIC && size == buffersize) { // "orphan" current buffer to avoid implicit synchronisation on the GPU: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf - gl.bindBuffer(mapType, buffer); - glBufferData(target, (GLsizeiptr) buffersize, nullptr, glusage); + gl.bindBuffer(mapUsage, buffer); + glBufferData(target, (GLsizeiptr) buffersize, nullptr, gldatausage); #if LOVE_WINDOWS // TODO: Verify that this codepath is a useful optimization. if (gl.getVendor() == OpenGL::VENDOR_INTEL) - glBufferData(target, (GLsizeiptr) buffersize, data, glusage); + glBufferData(target, (GLsizeiptr) buffersize, data, gldatausage); else #endif glBufferSubData(target, 0, (GLsizeiptr) buffersize, data); @@ -259,8 +261,8 @@ void Buffer::fill(size_t offset, size_t size, const void *data) void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) { - gl.bindBuffer(BUFFERTYPE_COPY_SOURCE, buffer); - gl.bindBuffer(BUFFERTYPE_COPY_DEST, ((Buffer *) dest)->buffer); + gl.bindBuffer(BUFFERUSAGE_COPY_SOURCE, buffer); + gl.bindBuffer(BUFFERUSAGE_COPY_DEST, ((Buffer *) dest)->buffer); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sourceoffset, destoffset, size); } diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index b875d862f..cf0b62a0a 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -65,7 +65,7 @@ private: void unmapStatic(size_t offset, size_t size); void unmapStream(); - BufferType mapType = BUFFERTYPE_VERTEX; + BufferUsage mapUsage = BUFFERUSAGE_VERTEX; GLenum target = 0; // The buffer object identifier. Assigned by OpenGL. diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 1384fbd72..5b4055d83 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -140,7 +140,7 @@ const char *Graphics::getName() const return "love.graphics.opengl"; } -love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferType type, size_t size) +love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferUsage type, size_t size) { return CreateStreamBuffer(type, size); } @@ -333,46 +333,46 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b { // Initial sizes that should be good enough for most cases. It will // resize to fit if needed, later. - batchedDrawState.vb[0] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 1024 * 1024 * 1); - batchedDrawState.vb[1] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 256 * 1024 * 1); - batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFERTYPE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); + batchedDrawState.vb[0] = CreateStreamBuffer(BUFFERUSAGE_VERTEX, 1024 * 1024 * 1); + batchedDrawState.vb[1] = CreateStreamBuffer(BUFFERUSAGE_VERTEX, 256 * 1024 * 1); + batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); } - if (capabilities.features[FEATURE_TEXEL_BUFFER] && defaultBuffers[BUFFERTYPE_TEXEL].get() == nullptr) + if (capabilities.features[FEATURE_TEXEL_BUFFER] && defaultBuffers[BUFFERUSAGE_TEXEL].get() == nullptr) { - Buffer::Settings settings(Buffer::TYPEFLAG_TEXEL, BUFFERUSAGE_STATIC); + Buffer::Settings settings(BUFFERUSAGEFLAG_TEXEL, BUFFERDATAUSAGE_STATIC); std::vector format = {{"", DATAFORMAT_FLOAT_VEC4, 0}}; const float texel[] = {0.0f, 0.0f, 0.0f, 1.0f}; auto buffer = newBuffer(settings, format, texel, sizeof(texel), 1); - defaultBuffers[BUFFERTYPE_TEXEL].set(buffer, Acquire::NORETAIN); + defaultBuffers[BUFFERUSAGE_TEXEL].set(buffer, Acquire::NORETAIN); } - if (capabilities.features[FEATURE_GLSL4] && defaultBuffers[BUFFERTYPE_SHADER_STORAGE].get() == nullptr) + if (capabilities.features[FEATURE_GLSL4] && defaultBuffers[BUFFERUSAGE_SHADER_STORAGE].get() == nullptr) { - Buffer::Settings settings(Buffer::TYPEFLAG_SHADER_STORAGE, BUFFERUSAGE_STATIC); + Buffer::Settings settings(BUFFERUSAGEFLAG_SHADER_STORAGE, BUFFERDATAUSAGE_STATIC); std::vector format = {{"", DATAFORMAT_FLOAT, 0}}; std::vector data; data.resize(Buffer::SHADER_STORAGE_BUFFER_MAX_STRIDE / 4); auto buffer = newBuffer(settings, format, data.data(), data.size() * sizeof(float), data.size()); - defaultBuffers[BUFFERTYPE_TEXEL].set(buffer, Acquire::NORETAIN); + defaultBuffers[BUFFERUSAGE_TEXEL].set(buffer, Acquire::NORETAIN); } // Load default resources before other Volatile. - for (int i = 0; i < BUFFERTYPE_MAX_ENUM; i++) + for (int i = 0; i < BUFFERUSAGE_MAX_ENUM; i++) { if (defaultBuffers[i].get()) ((Buffer *) defaultBuffers[i].get())->loadVolatile(); } - if (defaultBuffers[BUFFERTYPE_TEXEL].get()) - gl.setDefaultTexelBuffer((GLuint) defaultBuffers[BUFFERTYPE_TEXEL]->getTexelBufferHandle()); + if (defaultBuffers[BUFFERUSAGE_TEXEL].get()) + gl.setDefaultTexelBuffer((GLuint) defaultBuffers[BUFFERUSAGE_TEXEL]->getTexelBufferHandle()); - if (defaultBuffers[BUFFERTYPE_SHADER_STORAGE].get()) - gl.setDefaultStorageBuffer((GLuint) defaultBuffers[BUFFERTYPE_SHADER_STORAGE]->getHandle()); + if (defaultBuffers[BUFFERUSAGE_SHADER_STORAGE].get()) + gl.setDefaultStorageBuffer((GLuint) defaultBuffers[BUFFERUSAGE_SHADER_STORAGE]->getHandle()); // Reload all volatile objects. if (!Volatile::loadAll()) @@ -494,7 +494,7 @@ void Graphics::draw(const DrawIndexedCommand &cmd) GLenum glprimitivetype = OpenGL::getGLPrimitiveType(cmd.primitiveType); GLenum gldatatype = OpenGL::getGLIndexDataType(cmd.indexType); - gl.bindBuffer(BUFFERTYPE_INDEX, cmd.indexBuffer->getHandle()); + gl.bindBuffer(BUFFERUSAGE_INDEX, cmd.indexBuffer->getHandle()); if (cmd.instanceCount > 1) glDrawElementsInstanced(glprimitivetype, cmd.indexCount, gldatatype, gloffset, cmd.instanceCount); @@ -536,7 +536,7 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute gl.bindTextureToUnit(texture, 0, false); gl.setCullMode(CULL_NONE); - gl.bindBuffer(BUFFERTYPE_INDEX, quadIndexBuffer->getHandle()); + gl.bindBuffer(BUFFERUSAGE_INDEX, quadIndexBuffer->getHandle()); if (gl.isBaseVertexSupported()) { @@ -1530,8 +1530,8 @@ void Graphics::initCapabilities() capabilities.features[FEATURE_GLSL3] = GLAD_ES_VERSION_3_0 || gl.isCoreProfile(); capabilities.features[FEATURE_GLSL4] = GLAD_ES_VERSION_3_1 || (gl.isCoreProfile() && GLAD_VERSION_4_3); capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported(); - capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_TEXEL); - capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_COPY_SOURCE); + capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_TEXEL); + capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_COPY_SOURCE); static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize(); diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index f478c90e2..1244328d5 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -138,7 +138,7 @@ private: love::graphics::ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) override; love::graphics::Shader *newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel) override; - love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override; + love::graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override; void setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBtexture) override; void initCapabilities() override; void getAPIStats(int &shaderswitches) const override; @@ -166,7 +166,7 @@ private: size_t bufferMapMemorySize; // Only needed for buffer types that can be bound to shaders. - StrongRef defaultBuffers[BUFFERTYPE_MAX_ENUM]; + StrongRef defaultBuffers[BUFFERUSAGE_MAX_ENUM]; // [rendertarget][readable][srgb] OptionalBool supportedFormats[PIXELFORMAT_MAX_ENUM][2][2][2]; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 4583c3a9f..13facd10a 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -235,15 +235,15 @@ void OpenGL::setupContext() glGetIntegerv(GL_CULL_FACE_MODE, &faceCull); state.faceCullMode = faceCull; - for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++) + for (int i = 0; i < (int) BUFFERUSAGE_MAX_ENUM; i++) { state.boundBuffers[i] = 0; - if (isBufferTypeSupported((BufferType) i)) - glBindBuffer(getGLBufferType((BufferType) i), 0); + if (isBufferUsageSupported((BufferUsage) i)) + glBindBuffer(getGLBufferType((BufferUsage) i), 0); } - if (isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE)) - state.boundIndexedBuffers[BUFFERTYPE_SHADER_STORAGE].resize(maxShaderStorageBufferBindings, 0); + if (isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE)) + state.boundIndexedBuffers[BUFFERUSAGE_SHADER_STORAGE].resize(maxShaderStorageBufferBindings, 0); // Initialize multiple texture unit support for shaders. for (int i = 0; i < TEXTURE_MAX_ENUM + 1; i++) @@ -484,12 +484,12 @@ void OpenGL::initMaxValues() else maxTextureArrayLayers = 0; - if (isBufferTypeSupported(BUFFERTYPE_TEXEL)) + if (isBufferUsageSupported(BUFFERUSAGE_TEXEL)) glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTexelBufferSize); else maxTexelBufferSize = 0; - if (isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE)) + if (isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE)) { glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBufferSize); glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings); @@ -613,17 +613,17 @@ GLenum OpenGL::getGLPrimitiveType(PrimitiveType type) return GL_ZERO; } -GLenum OpenGL::getGLBufferType(BufferType type) +GLenum OpenGL::getGLBufferType(BufferUsage usage) { - switch (type) + switch (usage) { - case BUFFERTYPE_VERTEX: return GL_ARRAY_BUFFER; - case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; - case BUFFERTYPE_TEXEL: return GL_TEXTURE_BUFFER; - case BUFFERTYPE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER; - case BUFFERTYPE_COPY_SOURCE: return GL_COPY_READ_BUFFER; - case BUFFERTYPE_COPY_DEST: return GL_COPY_WRITE_BUFFER; - case BUFFERTYPE_MAX_ENUM: return GL_ZERO; + case BUFFERUSAGE_VERTEX: return GL_ARRAY_BUFFER; + case BUFFERUSAGE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; + case BUFFERUSAGE_TEXEL: return GL_TEXTURE_BUFFER; + case BUFFERUSAGE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER; + case BUFFERUSAGE_COPY_SOURCE: return GL_COPY_READ_BUFFER; + case BUFFERUSAGE_COPY_DEST: return GL_COPY_WRITE_BUFFER; + case BUFFERUSAGE_MAX_ENUM: return GL_ZERO; } return GL_ZERO; @@ -792,18 +792,18 @@ GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean return GL_ZERO; } -GLenum OpenGL::getGLBufferUsage(BufferUsage usage) +GLenum OpenGL::getGLBufferDataUsage(BufferDataUsage usage) { switch (usage) { - case BUFFERUSAGE_STREAM: return GL_STREAM_DRAW; - case BUFFERUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW; - case BUFFERUSAGE_STATIC: return GL_STATIC_DRAW; + case BUFFERDATAUSAGE_STREAM: return GL_STREAM_DRAW; + case BUFFERDATAUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW; + case BUFFERDATAUSAGE_STATIC: return GL_STATIC_DRAW; default: return 0; } } -void OpenGL::bindBuffer(BufferType type, GLuint buffer) +void OpenGL::bindBuffer(BufferUsage type, GLuint buffer) { if (state.boundBuffers[type] != buffer) { @@ -816,7 +816,7 @@ void OpenGL::deleteBuffer(GLuint buffer) { glDeleteBuffers(1, &buffer); - for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++) + for (int i = 0; i < (int) BUFFERUSAGE_MAX_ENUM; i++) { if (state.boundBuffers[i] == buffer) state.boundBuffers[i] = 0; @@ -869,7 +869,7 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe const void *offsetpointer = reinterpret_cast(bufferinfo.offset + attrib.offsetFromVertex); - bindBuffer(BUFFERTYPE_VERTEX, (GLuint) bufferinfo.buffer->getHandle()); + bindBuffer(BUFFERUSAGE_VERTEX, (GLuint) bufferinfo.buffer->getHandle()); if (intformat) glVertexAttribIPointer(i, components, gltype, layout.stride, offsetpointer); @@ -1165,7 +1165,7 @@ void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restorepr bindTextureToUnit(textype, handle, textureunit, restoreprev, bindforedit); } -void OpenGL::bindIndexedBuffer(GLuint buffer, BufferType type, int index) +void OpenGL::bindIndexedBuffer(GLuint buffer, BufferUsage type, int index) { auto &bindings = state.boundIndexedBuffers[type]; if (bindings.size() > (size_t) index && buffer != bindings[index]) @@ -1434,22 +1434,22 @@ bool OpenGL::isTextureTypeSupported(TextureType type) const return false; } -bool OpenGL::isBufferTypeSupported(BufferType type) const +bool OpenGL::isBufferUsageSupported(BufferUsage usage) const { - switch (type) + switch (usage) { - case BUFFERTYPE_VERTEX: - case BUFFERTYPE_INDEX: + case BUFFERUSAGE_VERTEX: + case BUFFERUSAGE_INDEX: return true; - case BUFFERTYPE_TEXEL: + case BUFFERUSAGE_TEXEL: // Not supported in ES until 3.2, which we don't support shaders for... return GLAD_VERSION_3_1; - case BUFFERTYPE_SHADER_STORAGE: + case BUFFERUSAGE_SHADER_STORAGE: return (GLAD_VERSION_4_3 && isCoreProfile()) || GLAD_ES_VERSION_3_1; - case BUFFERTYPE_COPY_SOURCE: - case BUFFERTYPE_COPY_DEST: + case BUFFERUSAGE_COPY_SOURCE: + case BUFFERUSAGE_COPY_DEST: return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0; - case BUFFERTYPE_MAX_ENUM: + case BUFFERUSAGE_MAX_ENUM: return false; } return false; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index b964896a4..dbead66fa 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -235,7 +235,7 @@ public: * NOTE: This does not account for multiple VAOs being used! Index buffer * bindings are per-VAO in OpenGL, but this doesn't know about that. **/ - void bindBuffer(BufferType type, GLuint buffer); + void bindBuffer(BufferUsage type, GLuint buffer); /** * glDeleteBuffers which updates our shadowed state. @@ -341,7 +341,7 @@ public: void bindBufferTextureToUnit(GLuint texture, int textureunit, bool restoreprev, bool bindforedit); - void bindIndexedBuffer(GLuint buffer, BufferType type, int index); + void bindIndexedBuffer(GLuint buffer, BufferUsage type, int index); /** * Helper for deleting an OpenGL texture. @@ -362,7 +362,7 @@ public: bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1); bool isTextureTypeSupported(TextureType type) const; - bool isBufferTypeSupported(BufferType type) const; + bool isBufferUsageSupported(BufferUsage usage) const; bool isClampZeroOneTextureWrapSupported() const; bool isPixelShaderHighpSupported() const; bool isInstancingSupported() const; @@ -433,10 +433,10 @@ public: Vendor getVendor() const; static GLenum getGLPrimitiveType(PrimitiveType type); - static GLenum getGLBufferType(BufferType type); + static GLenum getGLBufferType(BufferUsage usage); static GLenum getGLIndexDataType(IndexDataType type); static GLenum getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat); - static GLenum getGLBufferUsage(BufferUsage usage); + static GLenum getGLBufferDataUsage(BufferDataUsage usage); static GLenum getGLTextureType(TextureType type); static GLint getGLWrapMode(SamplerState::WrapMode wmode); static GLint getGLCompareMode(CompareMode mode); @@ -486,12 +486,12 @@ private: // Tracked OpenGL state. struct { - GLuint boundBuffers[BUFFERTYPE_MAX_ENUM]; + GLuint boundBuffers[BUFFERUSAGE_MAX_ENUM]; // Texture unit state (currently bound texture for each texture unit.) std::vector boundTextures[TEXTURE_MAX_ENUM + 1]; - std::vector boundIndexedBuffers[BUFFERTYPE_MAX_ENUM]; + std::vector boundIndexedBuffers[BUFFERUSAGE_MAX_ENUM]; bool enableState[ENABLE_MAX_ENUM]; diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 458091db2..fd6bd331e 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -315,7 +315,7 @@ void Shader::mapActiveUniforms() } } - if (gl.isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE)) + if (gl.isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE)) { GLint numstoragebuffers = 0; glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numstoragebuffers); @@ -586,7 +586,7 @@ void Shader::attach() } for (auto bufferbinding : activeStorageBufferBindings) - gl.bindIndexedBuffer(bufferbinding.buffer, BUFFERTYPE_SHADER_STORAGE, bufferbinding.bindingindex); + gl.bindIndexedBuffer(bufferbinding.buffer, BUFFERUSAGE_SHADER_STORAGE, bufferbinding.bindingindex); // send any pending uniforms to the shader program. for (const auto &p : pendingUniformUpdates) @@ -816,9 +816,9 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe bool storagebinding = info->baseType == UNIFORM_STORAGEBUFFER; if (texelbinding) - requiredtypeflags = Buffer::TYPEFLAG_TEXEL; + requiredtypeflags = BUFFERUSAGEFLAG_TEXEL; else if (storagebinding) - requiredtypeflags = Buffer::TYPEFLAG_SHADER_STORAGE; + requiredtypeflags = BUFFERUSAGEFLAG_SHADER_STORAGE; if (requiredtypeflags == 0) return; @@ -837,7 +837,7 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe if (buffer != nullptr) { - if ((buffer->getTypeFlags() & requiredtypeflags) == 0) + if ((buffer->getUsageFlags() & requiredtypeflags) == 0) { if (internalUpdate) continue; @@ -915,7 +915,7 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe glbuffer = gl.getDefaultStorageBuffer(); if (shaderactive) - gl.bindIndexedBuffer(glbuffer, BUFFERTYPE_SHADER_STORAGE, bindingindex); + gl.bindIndexedBuffer(glbuffer, BUFFERUSAGE_SHADER_STORAGE, bindingindex); int activeindex = storageBufferBindingIndexToActiveBinding[bindingindex]; if (activeindex >= 0) diff --git a/src/modules/graphics/opengl/StreamBuffer.cpp b/src/modules/graphics/opengl/StreamBuffer.cpp index 672b3f3df..ec96ee192 100644 --- a/src/modules/graphics/opengl/StreamBuffer.cpp +++ b/src/modules/graphics/opengl/StreamBuffer.cpp @@ -44,7 +44,7 @@ class StreamBufferClientMemory final : public love::graphics::StreamBuffer { public: - StreamBufferClientMemory(BufferType mode, size_t size) + StreamBufferClientMemory(BufferUsage mode, size_t size) : love::graphics::StreamBuffer(mode, size) , data(nullptr) { @@ -86,7 +86,7 @@ class StreamBufferSubDataOrphan final : public love::graphics::StreamBuffer, pub { public: - StreamBufferSubDataOrphan(BufferType mode, size_t size) + StreamBufferSubDataOrphan(BufferUsage mode, size_t size) : love::graphics::StreamBuffer(mode, size) , vbo(0) , glMode(OpenGL::getGLBufferType(mode)) @@ -184,7 +184,7 @@ class StreamBufferSync : public love::graphics::StreamBuffer { public: - StreamBufferSync(BufferType type, size_t size) + StreamBufferSync(BufferUsage type, size_t size) : love::graphics::StreamBuffer(type, size) , frameIndex(0) , syncs() @@ -220,7 +220,7 @@ class StreamBufferMapSync final : public StreamBufferSync, public Volatile { public: - StreamBufferMapSync(BufferType type, size_t size) + StreamBufferMapSync(BufferUsage type, size_t size) : StreamBufferSync(type, size) , vbo(0) , glMode(OpenGL::getGLBufferType(mode)) @@ -302,7 +302,7 @@ public: // Coherent mapping is supposedly faster on intel/nvidia aside from a couple // old nvidia GPUs. - StreamBufferPersistentMapSync(BufferType type, size_t size, bool coherent = true) + StreamBufferPersistentMapSync(BufferUsage type, size_t size, bool coherent = true) : StreamBufferSync(type, size) , vbo(0) , glMode(OpenGL::getGLBufferType(mode)) @@ -393,7 +393,7 @@ class StreamBufferPinnedMemory final : public StreamBufferSync, public Volatile { public: - StreamBufferPinnedMemory(BufferType type, size_t size) + StreamBufferPinnedMemory(BufferUsage type, size_t size) : StreamBufferSync(type, size) , vbo(0) , glMode(OpenGL::getGLBufferType(mode)) @@ -491,7 +491,7 @@ private: }; // StreamBufferPinnedMemory -love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size) +love::graphics::StreamBuffer *CreateStreamBuffer(BufferUsage mode, size_t size) { if (gl.isCoreProfile()) { diff --git a/src/modules/graphics/opengl/StreamBuffer.h b/src/modules/graphics/opengl/StreamBuffer.h index 01b273b40..64ee15496 100644 --- a/src/modules/graphics/opengl/StreamBuffer.h +++ b/src/modules/graphics/opengl/StreamBuffer.h @@ -29,7 +29,7 @@ namespace graphics namespace opengl { -love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size); +love::graphics::StreamBuffer *CreateStreamBuffer(BufferUsage mode, size_t size); } // opengl } // graphics diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 91c168edd..99178ff9e 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -337,16 +337,16 @@ const char *getConstant(BuiltinVertexAttribute attrib) return name; } -STRINGMAP_BEGIN(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) +STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsageName) { - { "vertex", BUFFERTYPE_VERTEX }, - { "index", BUFFERTYPE_INDEX }, - { "texel", BUFFERTYPE_TEXEL }, - { "shaderstorage", BUFFERTYPE_SHADER_STORAGE }, - { "copysource", BUFFERTYPE_COPY_SOURCE }, - { "copydest", BUFFERTYPE_COPY_DEST }, + { "vertex", BUFFERUSAGE_VERTEX }, + { "index", BUFFERUSAGE_INDEX }, + { "texel", BUFFERUSAGE_TEXEL }, + { "shaderstorage", BUFFERUSAGE_SHADER_STORAGE }, + { "copysource", BUFFERUSAGE_COPY_SOURCE }, + { "copydest", BUFFERUSAGE_COPY_DEST }, } -STRINGMAP_END(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName) +STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsageName) STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) { @@ -355,13 +355,13 @@ STRINGMAP_BEGIN(IndexDataType, INDEX_MAX_ENUM, indexType) } STRINGMAP_END(IndexDataType, INDEX_MAX_ENUM, indexType) -STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) +STRINGMAP_BEGIN(BufferDataUsage, BUFFERDATAUSAGE_MAX_ENUM, bufferDataUsage) { - { "stream", BUFFERUSAGE_STREAM }, - { "dynamic", BUFFERUSAGE_DYNAMIC }, - { "static", BUFFERUSAGE_STATIC }, + { "stream", BUFFERDATAUSAGE_STREAM }, + { "dynamic", BUFFERDATAUSAGE_DYNAMIC }, + { "static", BUFFERDATAUSAGE_STATIC }, } -STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsage) +STRINGMAP_END(BufferDataUsage, BUFFERDATAUSAGE_MAX_ENUM, bufferDataUsage) STRINGMAP_BEGIN(PrimitiveType, PRIMITIVE_MAX_ENUM, primitiveType) { diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 45e320ea9..006df24a7 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -54,15 +54,26 @@ enum BuiltinVertexAttributeFlags ATTRIBFLAG_COLOR = 1 << ATTRIB_COLOR, }; -enum BufferType +enum BufferUsage { - BUFFERTYPE_VERTEX = 0, - BUFFERTYPE_INDEX, - BUFFERTYPE_TEXEL, - BUFFERTYPE_SHADER_STORAGE, - BUFFERTYPE_COPY_SOURCE, - BUFFERTYPE_COPY_DEST, - BUFFERTYPE_MAX_ENUM + BUFFERUSAGE_VERTEX = 0, + BUFFERUSAGE_INDEX, + BUFFERUSAGE_TEXEL, + BUFFERUSAGE_SHADER_STORAGE, + BUFFERUSAGE_COPY_SOURCE, + BUFFERUSAGE_COPY_DEST, + BUFFERUSAGE_MAX_ENUM +}; + +enum BufferUsageFlags +{ + BUFFERUSAGEFLAG_NONE = 0, + BUFFERUSAGEFLAG_VERTEX = 1 << BUFFERUSAGE_VERTEX, + BUFFERUSAGEFLAG_INDEX = 1 << BUFFERUSAGE_INDEX, + BUFFERUSAGEFLAG_TEXEL = 1 << BUFFERUSAGE_TEXEL, + BUFFERUSAGEFLAG_SHADER_STORAGE = 1 << BUFFERUSAGE_SHADER_STORAGE, + BUFFERUSAGEFLAG_COPY_SOURCE = 1 << BUFFERUSAGE_COPY_SOURCE, + BUFFERUSAGEFLAG_COPY_DEST = 1 << BUFFERUSAGE_COPY_DEST, }; enum IndexDataType @@ -98,12 +109,12 @@ enum CullMode }; // The expected usage pattern of buffer data. -enum BufferUsage +enum BufferDataUsage { - BUFFERUSAGE_STREAM, - BUFFERUSAGE_DYNAMIC, - BUFFERUSAGE_STATIC, - BUFFERUSAGE_MAX_ENUM + BUFFERDATAUSAGE_STREAM, + BUFFERDATAUSAGE_DYNAMIC, + BUFFERDATAUSAGE_STATIC, + BUFFERDATAUSAGE_MAX_ENUM }; // Value types used when interfacing with the GPU (vertex and shader data). @@ -381,9 +392,9 @@ void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices); STRINGMAP_DECLARE(BuiltinVertexAttribute); -STRINGMAP_DECLARE(BufferType); -STRINGMAP_DECLARE(IndexDataType); STRINGMAP_DECLARE(BufferUsage); +STRINGMAP_DECLARE(IndexDataType); +STRINGMAP_DECLARE(BufferDataUsage); STRINGMAP_DECLARE(PrimitiveType); STRINGMAP_DECLARE(AttributeStep); STRINGMAP_DECLARE(DataFormat); diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index 9609ee8a6..8bd77e1a4 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -373,11 +373,11 @@ static int w_Buffer_getFormat(lua_State *L) static int w_Buffer_isBufferType(lua_State *L) { Buffer *t = luax_checkbuffer(L, 1); - BufferType buffertype = BUFFERTYPE_MAX_ENUM; + BufferUsage bufferusage = BUFFERUSAGE_MAX_ENUM; const char *typestr = luaL_checkstring(L, 2); - if (!getConstant(typestr, buffertype)) - return luax_enumerror(L, "buffer type", getConstants(buffertype), typestr); - luax_pushboolean(L, (t->getTypeFlags() & (1 << buffertype)) != 0); + if (!getConstant(typestr, bufferusage)) + return luax_enumerror(L, "buffer type", getConstants(bufferusage), typestr); + luax_pushboolean(L, (t->getUsageFlags() & (1 << bufferusage)) != 0); return 1; } diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 5c8f90a3f..3e57a3646 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1325,7 +1325,7 @@ int w_newSpriteBatch(lua_State *L) Texture *texture = luax_checktexture(L, 1); int size = (int) luaL_optinteger(L, 2, 1000); - BufferUsage usage = BUFFERUSAGE_DYNAMIC; + BufferDataUsage usage = BUFFERDATAUSAGE_DYNAMIC; if (lua_gettop(L) > 2) { const char *usagestr = luaL_checkstring(L, 3); @@ -1488,7 +1488,7 @@ int w_validateShader(lua_State *L) return 1; } -static BufferUsage luax_optbufferusage(lua_State *L, int idx, BufferUsage def) +static BufferDataUsage luax_optdatausage(lua_State *L, int idx, BufferDataUsage def) { const char *usagestr = lua_isnoneornil(L, idx) ? nullptr : luaL_checkstring(L, idx); @@ -1506,7 +1506,7 @@ static void luax_optbuffersettings(lua_State *L, int idx, Buffer::Settings &sett luaL_checktype(L, idx, LUA_TTABLE); lua_getfield(L, idx, "usage"); - settings.usage = luax_optbufferusage(L, -1, settings.usage); + settings.dataUsage = luax_optdatausage(L, -1, settings.dataUsage); lua_pop(L, 1); } @@ -1664,18 +1664,18 @@ static Buffer *luax_newbuffer(lua_State *L, int idx, Buffer::Settings settings, int w_newBuffer(lua_State *L) { - Buffer::Settings settings(0, BUFFERUSAGE_DYNAMIC); + Buffer::Settings settings(0, BUFFERDATAUSAGE_DYNAMIC); luaL_checktype(L, 3, LUA_TTABLE); - for (int i = 0; i < BUFFERTYPE_MAX_ENUM; i++) + for (int i = 0; i < BUFFERUSAGE_MAX_ENUM; i++) { - BufferType buffertype = (BufferType) i; + BufferUsage bufferusage = (BufferUsage) i; const char *tname = nullptr; - if (!getConstant(buffertype, tname)) + if (!getConstant(bufferusage, tname)) continue; if (luax_boolflag(L, 3, tname, false)) - settings.typeFlags = (Buffer::TypeFlags)(settings.typeFlags | (1u << i)); + settings.usageFlags = (BufferUsageFlags)(settings.usageFlags | (1u << i)); } luax_optbuffersettings(L, 3, settings); @@ -1692,7 +1692,7 @@ int w_newBuffer(lua_State *L) int w_newVertexBuffer(lua_State *L) { - Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, BUFFERUSAGE_DYNAMIC); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_DYNAMIC); luax_optbuffersettings(L, 3, settings); std::vector format; @@ -1707,7 +1707,7 @@ int w_newVertexBuffer(lua_State *L) int w_newIndexBuffer(lua_State *L) { - Buffer::Settings settings(Buffer::TYPEFLAG_INDEX, BUFFERUSAGE_DYNAMIC); + Buffer::Settings settings(BUFFERUSAGEFLAG_INDEX, BUFFERDATAUSAGE_DYNAMIC); luax_optbuffersettings(L, 3, settings); size_t arraylength = 0; @@ -1799,7 +1799,7 @@ static Mesh *newStandardMesh(lua_State *L) Mesh *t = nullptr; PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN); - BufferUsage usage = luax_optbufferusage(L, 3, BUFFERUSAGE_DYNAMIC); + BufferDataUsage usage = luax_optdatausage(L, 3, BUFFERDATAUSAGE_DYNAMIC); std::vector format = Mesh::getDefaultVertexFormat(); @@ -1861,7 +1861,7 @@ static Mesh *newCustomMesh(lua_State *L) std::vector vertexformat; PrimitiveType drawmode = luax_optmeshdrawmode(L, 3, PRIMITIVE_TRIANGLE_FAN); - BufferUsage usage = luax_optbufferusage(L, 4, BUFFERUSAGE_DYNAMIC); + BufferDataUsage usage = luax_optdatausage(L, 4, BUFFERDATAUSAGE_DYNAMIC); lua_rawgeti(L, 1, 1); if (!lua_istable(L, -1)) From 694d448e836bbff46e8cf0996abfdf3f2bf2613b Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 23 Jan 2021 13:47:12 -0400 Subject: [PATCH 10/17] Vertex shaders can write to gl_PointSize (fixes #1603). If a shader uses gl_PointSize then it can only be used when drawing points. If a shader doesn't use gl_PointSize then it can't be used when drawing points. Added 'ConstantPointSize' and 'CurrentDPIScale' built-in shader uniforms. ConstantPointSize is in DPI-scaled points, whereas gl_PointSize is in pixels, so to get the correct default behaviour a shader needs to do gl_PointSize = ConstantPointSize * CurrentDPIScale --- src/modules/graphics/Graphics.cpp | 12 ++-- src/modules/graphics/Mesh.cpp | 4 +- src/modules/graphics/ParticleSystem.cpp | 4 +- src/modules/graphics/Shader.cpp | 74 ++++++++++++++++-------- src/modules/graphics/Shader.h | 6 +- src/modules/graphics/SpriteBatch.cpp | 6 +- src/modules/graphics/Text.cpp | 6 +- src/modules/graphics/opengl/Graphics.cpp | 6 +- src/modules/graphics/opengl/OpenGL.cpp | 13 ----- src/modules/graphics/opengl/OpenGL.h | 6 -- src/modules/graphics/opengl/Shader.cpp | 24 ++------ src/modules/graphics/opengl/Shader.h | 7 --- src/modules/graphics/wrap_Graphics.cpp | 2 +- 13 files changed, 83 insertions(+), 87 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 420a73594..1ae95803b 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -1138,11 +1138,14 @@ Graphics::BatchedVertexData Graphics::requestBatchedDraw(const BatchedDrawComman state.standardShaderType = cmd.standardShaderType; } - if (state.vertexCount == 0 && Shader::isDefaultActive()) - Shader::attachDefault(state.standardShaderType); + if (state.vertexCount == 0) + { + if (Shader::isDefaultActive()) + Shader::attachDefault(state.standardShaderType); - if (state.vertexCount == 0 && Shader::current != nullptr && cmd.texture != nullptr) - Shader::current->checkMainTexture(cmd.texture); + if (Shader::current != nullptr) + Shader::current->validateDrawState(cmd.primitiveMode, cmd.texture); + } if (shouldresize) { @@ -1350,6 +1353,7 @@ void Graphics::points(const Vector2 *positions, const Colorf *colors, size_t num cmd.formats[0] = getSinglePositionFormat(is2D); cmd.formats[1] = CommonFormat::RGBAub; cmd.vertexCount = (int) numpoints; + cmd.standardShaderType = Shader::STANDARD_POINTS; BatchedVertexData data = requestBatchedDraw(cmd); diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 4c1bfbb71..410c38ab2 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -519,8 +519,8 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); - if (Shader::current && texture.get()) - Shader::current->checkMainTexture(texture); + if (Shader::current) + Shader::current->validateDrawState(primitiveType, texture); VertexAttributes attributes; BufferBindings buffers; diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index ab8d4f940..a775c1887 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -1037,8 +1037,8 @@ void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m) if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); - if (Shader::current && texture.get()) - Shader::current->checkMainTexture(texture); + if (Shader::current) + Shader::current->validateDrawState(PRIMITIVE_TRIANGLES, texture); const Vector2 *positions = texture->getQuad()->getVertexPositions(); const Vector2 *texcoords = texture->getQuad()->getVertexTexCoords(); diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index 605d74bd6..a8e7457fe 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -28,6 +28,7 @@ // Needed for reflection information. #include "libraries/glslang/glslang/Include/Types.h" +#include "libraries/glslang/glslang/MachineIndependent/localintermediate.h" // C++ #include @@ -94,6 +95,10 @@ LOVE_HIGHP_OR_MEDIUMP mat3 NormalMatrix; LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize; LOVE_HIGHP_OR_MEDIUMP vec4 ConstantColor; +LOVE_HIGHP_OR_MEDIUMP float CurrentDPIScale; + +LOVE_HIGHP_OR_MEDIUMP float ConstantPointSize; + #define TransformProjectionMatrix (ProjectionMatrix * TransformMatrix) // Alternate names @@ -123,6 +128,8 @@ void love_initializeBuiltinUniforms() { love_UniformsPerDraw[10].xyz ); + CurrentDPIScale = love_UniformsPerDraw[8].w; + ConstantPointSize = love_UniformsPerDraw[9].w; love_ScreenSize = love_UniformsPerDraw[11]; ConstantColor = love_UniformsPerDraw[12]; } @@ -237,6 +244,7 @@ mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c static const char vertex_header[] = R"( #define love_Position gl_Position +#define love_PointSize gl_PointSize #if __VERSION__ >= 130 #define attribute in @@ -246,19 +254,9 @@ static const char vertex_header[] = R"( #define love_InstanceID gl_InstanceID #endif #endif - -#ifdef GL_ES - uniform mediump float love_PointSize; -#endif )"; -static const char vertex_functions[] = R"( -void setPointSize() { -#ifdef GL_ES - gl_PointSize = love_PointSize; -#endif -} -)"; +static const char vertex_functions[] = R"()"; static const char vertex_main[] = R"( attribute vec4 VertexPosition; @@ -274,7 +272,6 @@ void main() { love_initializeBuiltinUniforms(); VaryingTexCoord = VertexTexCoord; VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; - setPointSize(); love_Position = position(ClipSpaceFromLocal, VertexPosition); } )"; @@ -284,7 +281,6 @@ void vertexmain(); void main() { love_initializeBuiltinUniforms(); - setPointSize(); vertexmain(); } )"; @@ -599,13 +595,29 @@ TextureType Shader::getMainTextureType() const return info != nullptr ? info->textureType : TEXTURE_MAX_ENUM; } -void Shader::checkMainTextureType(TextureType textype, bool isDepthSampler) const +void Shader::validateDrawState(PrimitiveType primtype, Texture *maintex) const { + if ((primtype == PRIMITIVE_POINTS) != validationReflection.usesPointSize) + { + if (validationReflection.usesPointSize) + throw love::Exception("The active shader can only be used to draw points."); + else + throw love::Exception("The gl_PointSize variable must be set in a vertex shader when drawing points."); + } + + if (maintex == nullptr) + return; + const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN); if (info == nullptr) return; + if (!maintex->isReadable()) + throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader."); + + auto textype = maintex->getTextureType(); + if (info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype) { const char *textypestr = "unknown"; @@ -615,7 +627,7 @@ void Shader::checkMainTextureType(TextureType textype, bool isDepthSampler) cons throw love::Exception("Texture's type (%s) must match the type of the shader's main texture type (%s).", textypestr, shadertextypestr); } - if (info->isDepthSampler != isDepthSampler) + if (info->isDepthSampler != maintex->getSamplerState().depthSampleMode.hasValue) { if (info->isDepthSampler) throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set."); @@ -624,14 +636,6 @@ void Shader::checkMainTextureType(TextureType textype, bool isDepthSampler) cons } } -void Shader::checkMainTexture(Texture *tex) const -{ - if (!tex->isReadable()) - throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader."); - - checkMainTextureType(tex->getTextureType(), tex->getSamplerState().depthSampleMode.hasValue); -} - bool Shader::validate(ShaderStage* vertex, ShaderStage* pixel, std::string& err) { ValidationReflection reflection; @@ -660,6 +664,13 @@ bool Shader::validateInternal(ShaderStage *vertex, ShaderStage *pixel, std::stri return false; } + const auto *vertintermediate = program.getIntermediate(EShLangVertex); + if (vertintermediate != nullptr) + { + // NOTE: this doesn't check whether the use affects final output... + reflection.usesPointSize = vertintermediate->inIoAccessed("gl_PointSize"); + } + for (int i = 0; i < program.getNumBufferBlocks(); i++) { const glslang::TObjectReflection &info = program.getBufferBlock(i); @@ -727,6 +738,14 @@ vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) } )"; +static const std::string defaultPointsVertex = R"( +vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) +{ + love_PointSize = ConstantPointSize * CurrentDPIScale; + return clipSpaceFromLocal * localPosition; +} +)"; + static const std::string defaultStandardPixel = R"( vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) { @@ -752,7 +771,12 @@ void effect() const std::string &Shader::getDefaultCode(StandardShader shader, ShaderStage::StageType stage) { if (stage == ShaderStage::STAGE_VERTEX) - return defaultVertex; + { + if (shader == STANDARD_POINTS) + return defaultPointsVertex; + else + return defaultVertex; + } static std::string nocode = ""; @@ -761,6 +785,7 @@ const std::string &Shader::getDefaultCode(StandardShader shader, ShaderStage::St case STANDARD_DEFAULT: return defaultStandardPixel; case STANDARD_VIDEO: return defaultVideoPixel; case STANDARD_ARRAY: return defaultArrayPixel; + case STANDARD_POINTS: return defaultStandardPixel; case STANDARD_MAX_ENUM: return nocode; } @@ -783,7 +808,6 @@ static StringMap::Entry builti { "love_VideoCbChannel", Shader::BUILTIN_TEXTURE_VIDEO_CB }, { "love_VideoCrChannel", Shader::BUILTIN_TEXTURE_VIDEO_CR }, { "love_UniformsPerDraw", Shader::BUILTIN_UNIFORMS_PER_DRAW }, - { "love_PointSize", Shader::BUILTIN_POINT_SIZE }, }; static StringMap builtinNames(builtinNameEntries, sizeof(builtinNameEntries)); diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h index c04c51bb8..3660bd16f 100644 --- a/src/modules/graphics/Shader.h +++ b/src/modules/graphics/Shader.h @@ -64,7 +64,6 @@ public: BUILTIN_TEXTURE_VIDEO_CB, BUILTIN_TEXTURE_VIDEO_CR, BUILTIN_UNIFORMS_PER_DRAW, - BUILTIN_POINT_SIZE, BUILTIN_MAX_ENUM }; @@ -88,6 +87,7 @@ public: STANDARD_DEFAULT, STANDARD_VIDEO, STANDARD_ARRAY, + STANDARD_POINTS, STANDARD_MAX_ENUM }; @@ -209,8 +209,7 @@ public: virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0; TextureType getMainTextureType() const; - void checkMainTextureType(TextureType textype, bool isDepthSampler) const; - void checkMainTexture(Texture *texture) const; + void validateDrawState(PrimitiveType primtype, Texture *maintexture) const; static SourceInfo getSourceInfo(const std::string &src); static std::string createShaderStageCode(Graphics *gfx, ShaderStage::StageType stage, const std::string &code, const SourceInfo &info); @@ -239,6 +238,7 @@ protected: struct ValidationReflection { std::map storageBuffers; + bool usesPointSize; }; static bool validateInternal(ShaderStage* vertex, ShaderStage* pixel, std::string& err, ValidationReflection &reflection); diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index 201e10d70..2af56d252 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -329,11 +329,11 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) Shader::attachDefault(defaultshader); } - - if (Shader::current) - Shader::current->checkMainTexture(texture); } + if (Shader::current) + Shader::current->validateDrawState(PRIMITIVE_TRIANGLES, texture); + flush(); // Upload any modified sprite data to the GPU. VertexAttributes attributes; diff --git a/src/modules/graphics/Text.cpp b/src/modules/graphics/Text.cpp index 35fa7ef5d..413125293 100644 --- a/src/modules/graphics/Text.cpp +++ b/src/modules/graphics/Text.cpp @@ -262,8 +262,12 @@ void Text::draw(Graphics *gfx, const Matrix4 &m) if (Shader::isDefaultActive()) Shader::attachDefault(Shader::STANDARD_DEFAULT); + Texture *firsttex = nullptr; + if (!drawCommands.empty()) + firsttex = drawCommands[0].texture; + if (Shader::current) - Shader::current->checkMainTextureType(TEXTURE_2D, false); + Shader::current->validateDrawState(PRIMITIVE_TRIANGLES, firsttex); // Re-generate the text if the Font's texture cache was invalidated. if (font->getTextureCacheID() != textureCacheID) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 5b4055d83..a1c32e3d9 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -304,6 +304,9 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b glEnable(GL_TEXTURE_2D); } + if (!GLAD_ES_VERSION_2_0) + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + gl.setTextureUnit(0); // Set pixel row alignment - code that calls glTexSubImage and glReadPixels @@ -1444,10 +1447,9 @@ void Graphics::setBlendState(const BlendState &blend) void Graphics::setPointSize(float size) { - if (batchedDrawState.primitiveMode == PRIMITIVE_POINTS) + if (size != states.back().pointSize) flushBatchedDraws(); - gl.setPointSize(size * getCurrentDPIScale()); states.back().pointSize = size; } diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 13facd10a..93de3e422 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -943,19 +943,6 @@ void OpenGL::setScissor(const Rect &v, bool rtActive) state.scissor = v; } -void OpenGL::setPointSize(float size) -{ - if (GLAD_VERSION_1_0) - glPointSize(size); - - state.pointSize = size; -} - -float OpenGL::getPointSize() const -{ - return state.pointSize; -} - void OpenGL::setEnableState(EnableState enablestate, bool enable) { GLenum glstate = GL_NONE; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index dbead66fa..dbdbe7d2d 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -270,12 +270,6 @@ public: **/ void setScissor(const Rect &v, bool rtActive); - /** - * Sets the global point size. - **/ - void setPointSize(float size); - float getPointSize() const; - /** * State-tracked version of glEnable. **/ diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index fd6bd331e..a854c7e17 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -48,7 +48,6 @@ Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage , builtinUniforms() , builtinUniformInfo() , builtinAttributes() - , lastPointSize(0.0f) { // load shader source and create program object loadVolatile(); @@ -430,8 +429,6 @@ bool Shader::loadVolatile() { OpenGL::TempDebugGroup debuggroup("Shader load"); - lastPointSize = -1.0f; - // zero out active texture list textureUnits.clear(); textureUnits.push_back(TextureUnit()); @@ -971,26 +968,11 @@ void Shader::setVideoTextures(love::graphics::Texture *ytexture, love::graphics: } } -void Shader::updatePointSize(float size) -{ - if (size == lastPointSize || current != this) - return; - - GLint location = builtinUniforms[BUILTIN_POINT_SIZE]; - if (location >= 0) - glUniform1f(location, size); - - lastPointSize = size; -} - void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int viewportH) { if (current != this) return; - if (GLAD_ES_VERSION_2_0) - updatePointSize(gl.getPointSize()); - BuiltinUniformData data; data.transformMatrix = gfx->getTransform(); @@ -1010,6 +992,12 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, } } + // Store DPI scale in an unused component of another vector. + data.normalMatrix[0].w = (float) gfx->getCurrentDPIScale(); + + // Same with point size. + data.normalMatrix[1].w = gfx->getPointSize(); + data.screenSizeParams.x = viewportW; data.screenSizeParams.y = viewportH; diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 2f215c687..30934a932 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -43,10 +43,6 @@ class Shader final : public love::graphics::Shader, public Volatile { public: - /** - * Creates a new Shader using a list of source codes. - * Source must contain either vertex or pixel shader code, or both. - **/ Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel); virtual ~Shader(); @@ -67,7 +63,6 @@ public: ptrdiff_t getHandle() const override; void setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture) override; - void updatePointSize(float size); void updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int viewportH); private: @@ -128,8 +123,6 @@ private: std::vector> pendingUniformUpdates; - float lastPointSize; - }; // Shader } // opengl diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 3e57a3646..2fd3dfcb7 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3103,7 +3103,7 @@ int w_rectangle(lua_State *L) if (lua_isnoneornil(L, 6)) { - instance()->rectangle(mode, x, y, w, h); + luax_catchexcept(L, [&](){ instance()->rectangle(mode, x, y, w, h); }); return 0; } From e9673484093d8465975c0072f7767980500824b2 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 6 Feb 2021 19:42:53 +0800 Subject: [PATCH 11/17] Implement AAsset virtual archive for Android --- src/common/android.cpp | 403 ++++++++++++++++++++++++++++++++++++++++- src/common/android.h | 21 +++ 2 files changed, 421 insertions(+), 3 deletions(-) diff --git a/src/common/android.cpp b/src/common/android.cpp index 22a6ccefa..3ba418c64 100644 --- a/src/common/android.cpp +++ b/src/common/android.cpp @@ -22,13 +22,20 @@ #ifdef LOVE_ANDROID -#include "SDL.h" -#include "jni.h" +#include +#include + +#include + +#include +#include +#include #include #include #include -#include + +#include "physfs.h" namespace love { @@ -326,6 +333,396 @@ void showRecordingPermissionMissingDialog() env->DeleteLocalRef(activity); } +/* + * Helper functions to aid new fusing method + */ +static AAssetManager *getAssetManager() +{ + JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv(); + jobject self = (jobject) SDL_AndroidGetActivity(); + jclass activity = env->GetObjectClass(self); + jmethodID method = env->GetMethodID(activity, "getAssetManager", "()Landroid/content/res/AssetManager;"); + + jobject assetManager = env->CallObjectMethod(self, method); + AAssetManager *assetManagerObject = AAssetManager_fromJava(env, assetManager); + + env->DeleteLocalRef(assetManager); + env->DeleteLocalRef(activity); + + return assetManagerObject; +} + +namespace aasset +{ +namespace io +{ + +struct AssetInfo +{ + AAssetManager *assetManager; + AAsset *asset; + char *filename; + size_t size; +}; + +static std::unordered_map fileTree; + +// Workaround AAsset can't detect whetever something is a directory or doesn't exist +static void buildFileLookup( + AAssetManager *assetManager, + std::unordered_map &out, + const std::string &path = "" +) +{ + if (!path.empty()) + { + AAsset *test = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_STREAMING); + if (test) + { + AAsset_close(test); + out[path] = PHYSFS_FILETYPE_REGULAR; + return; + } + + out[path] = PHYSFS_FILETYPE_DIRECTORY; + } + + AAssetDir *dir = AAssetManager_openDir(assetManager, path.c_str()); + const char *file; + + while ((file = AAssetDir_getNextFileName(dir)) != nullptr) + buildFileLookup(assetManager, out, file); + + AAssetDir_close(dir); +} + +PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len) +{ + AAsset *asset = ((AssetInfo *) io->opaque)->asset; + int readed = AAsset_read(asset, buf, (size_t) len); + + PHYSFS_setErrorCode(readed < 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK); + return (PHYSFS_sint64) readed; +} + +PHYSFS_sint64 write(PHYSFS_Io *io, const void *buf, PHYSFS_uint64 len) +{ + LOVE_UNUSED(io); + LOVE_UNUSED(buf); + LOVE_UNUSED(len); + + PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY); + return -1; +} + +int seek(PHYSFS_Io *io, PHYSFS_uint64 offset) +{ + AAsset *asset = ((AssetInfo *) io->opaque)->asset; + int success = AAsset_seek64(asset, (off64_t) offset, SEEK_SET) != -1; + + PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR); + return success; +} + +PHYSFS_sint64 tell(PHYSFS_Io *io) +{ + AAsset *asset = ((AssetInfo *) io->opaque)->asset; + off64_t len = AAsset_getLength64(asset); + off64_t remain = AAsset_getRemainingLength64(asset); + + return len - remain; +} + +PHYSFS_sint64 length(PHYSFS_Io *io) +{ + AAsset *asset = ((AssetInfo *) io->opaque)->asset; + return AAsset_getLength64(asset); +} + +// Forward declaration +PHYSFS_Io *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset); + +PHYSFS_Io *duplicate(PHYSFS_Io *io) +{ + AssetInfo *assetInfo = (AssetInfo *) io->opaque; + AAsset *asset = AAssetManager_open(assetInfo->assetManager, assetInfo->filename, AASSET_MODE_RANDOM); + + if (asset == nullptr) + { + PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); + return nullptr; + } + + AAsset_seek64(asset, tell(io), SEEK_SET); + return fromAAsset(assetInfo->assetManager, assetInfo->filename, asset); +} + +void destroy(PHYSFS_Io *io) +{ + AssetInfo *assetInfo = (AssetInfo *) io->opaque; + AAsset_close(assetInfo->asset); + delete[] assetInfo->filename; + delete assetInfo; + delete io; +} + +PHYSFS_Io *fromAAsset(AAssetManager *assetManager, const char *filename, AAsset *asset) +{ + // Create AssetInfo + AssetInfo *assetInfo = new (std::nothrow) AssetInfo(); + assetInfo->assetManager = assetManager; + assetInfo->asset = asset; + assetInfo->size = strlen(filename) + 1; + assetInfo->filename = new (std::nothrow) char[assetInfo->size]; + memcpy(assetInfo->filename, filename, assetInfo->size); + + // Create PHYSFS_Io + PHYSFS_Io *io = new (std::nothrow) PHYSFS_Io(); + io->version = 0; + io->opaque = assetInfo; + io->read = read; + io->write = write; + io->seek = seek; + io->tell = tell; + io->length = length; + io->duplicate = duplicate; + io->flush = nullptr; + io->destroy = destroy; + + return io; +} + +} + +void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed) +{ + if (io->opaque == nullptr || memcmp(io->opaque, "ASET", 4) != 0) + return nullptr; + + // It's our archive + *claimed = 1; + AAssetManager *assetManager = getAssetManager(); + + if (io::fileTree.empty()) + io::buildFileLookup(assetManager, io::fileTree); + + return assetManager; +} + +PHYSFS_EnumerateCallbackResult enumerate( + void *opaque, + const char *dirname, + PHYSFS_EnumerateCallback cb, + const char *origdir, + void *callbackdata +) +{ + const char *path = dirname; + if (path == nullptr || (path[0] == '/' && path[1] == 0)) + path = ""; + + AAssetManager *assetManager = (AAssetManager *) opaque; + AAssetDir *dir = AAssetManager_openDir(assetManager, path); + + if (dir == nullptr) + { + PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND); + return PHYSFS_ENUM_ERROR; + } + + PHYSFS_EnumerateCallbackResult ret = PHYSFS_ENUM_OK; + + while (ret == PHYSFS_ENUM_OK) + { + const char *name = AAssetDir_getNextFileName(dir); + + // No more files? + if (name == nullptr) + break; + + ret = cb(callbackdata, origdir, name); + } + + AAssetDir_close(dir); + return ret; +} + +PHYSFS_Io *openRead(void *opaque, const char *name) +{ + AAssetManager *assetManager = (AAssetManager *) opaque; + AAsset *file = AAssetManager_open(assetManager, name, AASSET_MODE_UNKNOWN); + + if (file == nullptr) + { + PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND); + return nullptr; + } + + PHYSFS_setErrorCode(PHYSFS_ERR_OK); + return io::fromAAsset(assetManager, name, file); +} + +PHYSFS_Io *openWriteAppend(void *opaque, const char *name) +{ + LOVE_UNUSED(opaque); + LOVE_UNUSED(name); + + // AAsset doesn't support modification + PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY); + return nullptr; +} + +int removeMkdir(void *opaque, const char *name) +{ + LOVE_UNUSED(opaque); + LOVE_UNUSED(name); + + // AAsset doesn't support modification + PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY); + return 0; +} + +int stat(void *opaque, const char *name, PHYSFS_Stat *out) +{ + LOVE_UNUSED(opaque); + + auto result = io::fileTree.find(name); + + if (result != io::fileTree.end()) + { + out->filetype = result->second; + out->modtime = -1; + out->createtime = -1; + out->accesstime = -1; + out->readonly = 1; + + PHYSFS_setErrorCode(PHYSFS_ERR_OK); + return 1; + } + else + { + PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND); + return 0; + } +} + +void closeArchive(void *opaque) +{ + // Do nothing + LOVE_UNUSED(opaque); + PHYSFS_setErrorCode(PHYSFS_ERR_OK); +} + +static PHYSFS_Archiver g_AAssetArchiver = { + 0, + { + "AASSET", + "Android AAsset Wrapper", + "LOVE Development Team", + "https://developer.android.com/ndk/reference/group/asset", + 0 + }, + openArchive, + enumerate, + openRead, + openWriteAppend, + openWriteAppend, + removeMkdir, + removeMkdir, + stat, + closeArchive +}; + +static PHYSFS_sint64 dummyReturn0(PHYSFS_Io *io) +{ + LOVE_UNUSED(io); + PHYSFS_setErrorCode(PHYSFS_ERR_OK); + return 0; +} + +static PHYSFS_Io *getDummyIO(PHYSFS_Io *io); + +static char dummyOpaque[] = "ASET"; +static PHYSFS_Io dummyIo = { + 0, + dummyOpaque, + nullptr, + nullptr, + [](PHYSFS_Io *io, PHYSFS_uint64 offset) -> int + { + PHYSFS_setErrorCode(offset == 0 ? PHYSFS_ERR_OK : PHYSFS_ERR_PAST_EOF); + return offset == 0; + }, + dummyReturn0, + dummyReturn0, + getDummyIO, + nullptr, + [](PHYSFS_Io *io) { LOVE_UNUSED(io); } +}; + +static PHYSFS_Io *getDummyIO(PHYSFS_Io *io) +{ + return &dummyIo; +} + +} + +static bool isVirtualArchiveInitialized = false; + +bool initializeVirtualArchive() +{ + if (isVirtualArchiveInitialized) + return true; + + if (!PHYSFS_registerArchiver(&aasset::g_AAssetArchiver)) + return false; + if (!PHYSFS_mountIo(&aasset::dummyIo, "ASET.AASSET", nullptr, 0)) + { + PHYSFS_deregisterArchiver(aasset::g_AAssetArchiver.info.extension); + return false; + } + + isVirtualArchiveInitialized = true; + return true; +} + +void deinitializeVirtualArchive() +{ + if (isVirtualArchiveInitialized) + { + PHYSFS_deregisterArchiver(aasset::g_AAssetArchiver.info.extension); + isVirtualArchiveInitialized = false; + } +} + +bool checkFusedGame(void **physfsIO_Out) +{ + // TODO: Reorder the loading in 12.0 + PHYSFS_Io *&io = *(PHYSFS_Io **) physfsIO_Out; + AAssetManager *assetManager = getAssetManager(); + + // Prefer game.love inside assets/ folder + AAsset *asset = AAssetManager_open(assetManager, "game.love", AASSET_MODE_RANDOM); + if (asset) + { + io = aasset::io::fromAAsset(assetManager, "game.love", asset); + return true; + } + + // If there's no game.love inside assets/ try main.lua + asset = AAssetManager_open(assetManager, "main.lua", AASSET_MODE_STREAMING); + + if (asset) + { + AAsset_close(asset); + io = nullptr; + return true; + } + + // Not found + return false; +} + } // android } // love diff --git a/src/common/android.h b/src/common/android.h index 45b5acdea..9f066c2e8 100644 --- a/src/common/android.h +++ b/src/common/android.h @@ -80,6 +80,27 @@ void requestRecordingPermission(); void showRecordingPermissionMissingDialog(); +/** + * Initialize Android AAsset virtual archive. + * @return true if successful. + */ +bool initializeVirtualArchive(); + +/** + * Deinitialize Android AAsset virtual archive. + * @return true if successful. + */ +void deinitializeVirtualArchive(); + +/** + * Retrieve the fused game inside the APK + * @param physfsIO_Out Pointer to PHYSFS_Io* struct + * @return true if there's game inside the APK. If physfsIO_Out is not null, then it contains + * the game.love which needs to be mounted to root. false if it's not fused, in which case + * physfsIO_Out is undefined. + */ +bool checkFusedGame(void **physfsIO_Out); + } // android } // love From 22455276f60bb248b56cf66a51541b61ee9db46e Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 6 Feb 2021 22:10:49 +0800 Subject: [PATCH 12/17] Implement experimental fusing method. https://github.com/love2d/love-android/issues/201#issuecomment-772628115 --- src/modules/filesystem/physfs/Filesystem.cpp | 68 ++++++++++++++------ 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/src/modules/filesystem/physfs/Filesystem.cpp b/src/modules/filesystem/physfs/Filesystem.cpp index 653eaec1a..807bb6ee0 100644 --- a/src/modules/filesystem/physfs/Filesystem.cpp +++ b/src/modules/filesystem/physfs/Filesystem.cpp @@ -108,6 +108,10 @@ Filesystem::Filesystem() Filesystem::~Filesystem() { +#ifdef LOVE_ANDROID + love::android::deinitializeVirtualArchive(); +#endif + if (PHYSFS_isInit()) PHYSFS_deinit(); } @@ -224,30 +228,56 @@ bool Filesystem::setSource(const char *source) if (!love::android::createStorageDirectories()) SDL_Log("Error creating storage directories!"); - new_search_path = love::android::getSelectedGameFile(); + new_search_path = ""; - // try mounting first, if that fails, load to memory and mount - if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1)) + PHYSFS_Io *gameLoveIO; + bool hasFusedGame = love::android::checkFusedGame((void **) &gameLoveIO); + + if (hasFusedGame) { - // PHYSFS cannot yet mount a zip file inside an .apk - SDL_Log("Mounting %s did not work. Loading to memory.", - new_search_path.c_str()); - char* game_archive_ptr = NULL; - size_t game_archive_size = 0; - if (!love::android::loadGameArchiveToMemory( - new_search_path.c_str(), &game_archive_ptr, - &game_archive_size)) + if (gameLoveIO) { - SDL_Log("Failure memory loading archive %s", new_search_path.c_str()); - return false; + // Actually we should just be able to mount gameLoveIO, but that's experimental. + gameLoveIO->destroy(gameLoveIO); + goto oldschool; } - if (!PHYSFS_mountMemory( - game_archive_ptr, game_archive_size, - love::android::freeGameArchiveMemory, "archive.zip", "/", 0)) + else { - SDL_Log("Failure mounting in-memory archive."); - love::android::freeGameArchiveMemory(game_archive_ptr); - return false; + if (!love::android::initializeVirtualArchive()) + { + SDL_Log("Unable to mount AAsset: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); + return false; + } + } + } + else + { + oldschool: + new_search_path = love::android::getSelectedGameFile(); + + // try mounting first, if that fails, load to memory and mount + if (!PHYSFS_mount(new_search_path.c_str(), nullptr, 1)) + { + // PHYSFS cannot yet mount a zip file inside an .apk + SDL_Log("Mounting %s did not work. Loading to memory.", + new_search_path.c_str()); + char* game_archive_ptr = NULL; + size_t game_archive_size = 0; + if (!love::android::loadGameArchiveToMemory( + new_search_path.c_str(), &game_archive_ptr, + &game_archive_size)) + { + SDL_Log("Failure memory loading archive %s", new_search_path.c_str()); + return false; + } + if (!PHYSFS_mountMemory( + game_archive_ptr, game_archive_size, + love::android::freeGameArchiveMemory, "archive.zip", "/", 0)) + { + SDL_Log("Failure mounting in-memory archive."); + love::android::freeGameArchiveMemory(game_archive_ptr); + return false; + } } } #else From 994cec9ee8330951c897fc2de034174eb1457e69 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Fri, 12 Feb 2021 19:48:41 +0800 Subject: [PATCH 13/17] Add Android-specific conditionals. --- CMakeLists.txt | 67 ++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c955156d5..e49d09a0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,10 +145,10 @@ if(MEGA) # automatically. endif() else() - if(MSVC) + if(MSVC or ANDROID) message(FATAL_ERROR " -It is currently only possible to build with megasource on Windows. -Please see http://bitbucket.org/rude/megasource +It is currently only possible to build with megasource on Windows and Android. +Please see https://github.com/love2d/megasource ") endif() @@ -1696,6 +1696,13 @@ if(MSVC) ) endif() +if(ANDROID) + # In Android, the LOVE main entrypoint needs to be compiled + # as shared library, so change the library name and add love.cpp + set(LOVE_LIB_NAME ${LOVE_EXE_NAME}) + set(LOVE_LIB_SRC ${LOVE_LIB_SRC} src/love.cpp) +endif() + add_library(${LOVE_LIB_NAME} SHARED ${LOVE_LIB_SRC} ${LOVE_RC}) target_link_libraries(${LOVE_LIB_NAME} ${LOVE_LINK_LIBRARIES} ${LOVE_3P}) @@ -1711,35 +1718,37 @@ endif() # # love (executable) # -add_executable(${LOVE_EXE_NAME} WIN32 src/love.cpp ${LOVE_RC}) -target_link_libraries(${LOVE_EXE_NAME} ${LOVE_LIB_NAME}) +if(NOT ANDROID) + add_executable(${LOVE_EXE_NAME} WIN32 src/love.cpp ${LOVE_RC}) + target_link_libraries(${LOVE_EXE_NAME} ${LOVE_LIB_NAME}) -if(MSVC) - add_executable(${LOVE_CONSOLE_EXE_NAME} src/love.cpp ${LOVE_RC}) - target_link_libraries(${LOVE_CONSOLE_EXE_NAME} ${LOVE_LIB_NAME}) -endif() - -function(post_step_move_dll ARG_POST_TARGET ARG_TARGET_OR_FILE) - if(TARGET ${ARG_TARGET_OR_FILE}) - add_custom_command(TARGET ${ARG_POST_TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - ${CMAKE_CURRENT_BINARY_DIR}/$/$) - else() - get_filename_component(TEMP_FILENAME ${ARG_TARGET_OR_FILE} NAME) - add_custom_command(TARGET ${ARG_POST_TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - ${ARG_TARGET_OR_FILE} - ${CMAKE_CURRENT_BINARY_DIR}/$/${TEMP_FILENAME}) + if(MSVC) + add_executable(${LOVE_CONSOLE_EXE_NAME} src/love.cpp ${LOVE_RC}) + target_link_libraries(${LOVE_CONSOLE_EXE_NAME} ${LOVE_LIB_NAME}) endif() -endfunction() -# Add post build steps to move the DLLs next to the binary. Otherwise -# running/debugging the binary will not work from inside VS. -if(LOVE_MOVE_DLLS) - foreach(DLL ${LOVE_MOVE_DLLS}) - post_step_move_dll(love ${DLL}) - endforeach() + function(post_step_move_dll ARG_POST_TARGET ARG_TARGET_OR_FILE) + if(TARGET ${ARG_TARGET_OR_FILE}) + add_custom_command(TARGET ${ARG_POST_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + $ + ${CMAKE_CURRENT_BINARY_DIR}/$/$) + else() + get_filename_component(TEMP_FILENAME ${ARG_TARGET_OR_FILE} NAME) + add_custom_command(TARGET ${ARG_POST_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${ARG_TARGET_OR_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/$/${TEMP_FILENAME}) + endif() + endfunction() + + # Add post build steps to move the DLLs next to the binary. Otherwise + # running/debugging the binary will not work from inside VS. + if(LOVE_MOVE_DLLS) + foreach(DLL ${LOVE_MOVE_DLLS}) + post_step_move_dll(love ${DLL}) + endforeach() + endif() endif() if (NOT MSVC) From cbc0602620c3d3a4bb16f038555f9a190152364f Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 13 Feb 2021 19:03:23 +0800 Subject: [PATCH 14/17] Make sure to delete activity returned by SDL when calling getAssetManager() --- src/common/android.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/android.cpp b/src/common/android.cpp index 3ba418c64..e6394847d 100644 --- a/src/common/android.cpp +++ b/src/common/android.cpp @@ -348,6 +348,7 @@ static AAssetManager *getAssetManager() env->DeleteLocalRef(assetManager); env->DeleteLocalRef(activity); + env->DeleteLocalRef(self); return assetManagerObject; } From 1e27b1d6edf0f9a740e605ce26f07b05898ecc92 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 14 Feb 2021 14:40:45 -0400 Subject: [PATCH 15/17] Add Joystick:getGamepadType. Return value is "unknown", "xbox360", "xboxone", "ps3", "ps4", "ps5", "switchpro", or "virtual". --- src/modules/joystick/Joystick.cpp | 133 ++++++++++--------------- src/modules/joystick/Joystick.h | 45 ++++----- src/modules/joystick/sdl/Joystick.cpp | 24 +++++ src/modules/joystick/sdl/Joystick.h | 2 + src/modules/joystick/wrap_Joystick.cpp | 10 ++ 5 files changed, 107 insertions(+), 107 deletions(-) diff --git a/src/modules/joystick/Joystick.cpp b/src/modules/joystick/Joystick.cpp index 7ee43ec0c..a67a16c3c 100644 --- a/src/modules/joystick/Joystick.cpp +++ b/src/modules/joystick/Joystick.cpp @@ -42,102 +42,71 @@ float Joystick::clampval(float x) return x; } -bool Joystick::getConstant(const char *in, Joystick::Hat &out) +STRINGMAP_CLASS_BEGIN(Joystick, Joystick::Hat, Joystick::HAT_MAX_ENUM, hat) { - return hats.find(in, out); + { "c", Joystick::HAT_CENTERED }, + { "u", Joystick::HAT_UP }, + { "r", Joystick::HAT_RIGHT }, + { "d", Joystick::HAT_DOWN }, + { "l", Joystick::HAT_LEFT }, + { "ru", Joystick::HAT_RIGHTUP }, + { "rd", Joystick::HAT_RIGHTDOWN }, + { "lu", Joystick::HAT_LEFTUP }, + { "ld", Joystick::HAT_LEFTDOWN }, } +STRINGMAP_CLASS_END(Joystick, Joystick::Hat, Joystick::HAT_MAX_ENUM, hat) -bool Joystick::getConstant(Joystick::Hat in, const char *&out) +STRINGMAP_CLASS_BEGIN(Joystick, Joystick::GamepadType, Joystick::GAMEPAD_TYPE_MAX_ENUM, gamepadType) { - return hats.find(in, out); + { "unknown", Joystick::GAMEPAD_TYPE_UNKNOWN }, + { "xbox360", Joystick::GAMEPAD_TYPE_XBOX360 }, + { "xboxone", Joystick::GAMEPAD_TYPE_XBOXONE }, + { "ps3", Joystick::GAMEPAD_TYPE_PS3 }, + { "ps4", Joystick::GAMEPAD_TYPE_PS4 }, + { "ps5", Joystick::GAMEPAD_TYPE_PS5 }, + { "switchpro", Joystick::GAMEPAD_TYPE_NINTENDO_SWITCH_PRO }, + { "virtual", Joystick::GAMEPAD_TYPE_VIRTUAL }, } +STRINGMAP_CLASS_END(Joystick, Joystick::GamepadType, Joystick::GAMEPAD_TYPE_MAX_ENUM, gamepadType) -bool Joystick::getConstant(const char *in, Joystick::GamepadAxis &out) +STRINGMAP_CLASS_BEGIN(Joystick, Joystick::GamepadAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM, gpAxis) { - return gpAxes.find(in, out); + { "leftx", Joystick::GAMEPAD_AXIS_LEFTX }, + { "lefty", Joystick::GAMEPAD_AXIS_LEFTY }, + { "rightx", Joystick::GAMEPAD_AXIS_RIGHTX }, + { "righty", Joystick::GAMEPAD_AXIS_RIGHTY }, + { "triggerleft", Joystick::GAMEPAD_AXIS_TRIGGERLEFT }, + { "triggerright", Joystick::GAMEPAD_AXIS_TRIGGERRIGHT }, } +STRINGMAP_CLASS_END(Joystick, Joystick::GamepadAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM, gpAxis) -bool Joystick::getConstant(Joystick::GamepadAxis in, const char *&out) +STRINGMAP_CLASS_BEGIN(Joystick, Joystick::GamepadButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM, gpButton) { - return gpAxes.find(in, out); + { "a", Joystick::GAMEPAD_BUTTON_A }, + { "b", Joystick::GAMEPAD_BUTTON_B }, + { "x", Joystick::GAMEPAD_BUTTON_X }, + { "y", Joystick::GAMEPAD_BUTTON_Y }, + { "back", Joystick::GAMEPAD_BUTTON_BACK }, + { "guide", Joystick::GAMEPAD_BUTTON_GUIDE }, + { "start", Joystick::GAMEPAD_BUTTON_START }, + { "leftstick", Joystick::GAMEPAD_BUTTON_LEFTSTICK }, + { "rightstick", Joystick::GAMEPAD_BUTTON_RIGHTSTICK }, + { "leftshoulder", Joystick::GAMEPAD_BUTTON_LEFTSHOULDER }, + { "rightshoulder", Joystick::GAMEPAD_BUTTON_RIGHTSHOULDER }, + { "dpup", Joystick::GAMEPAD_BUTTON_DPAD_UP }, + { "dpdown", Joystick::GAMEPAD_BUTTON_DPAD_DOWN }, + { "dpleft", Joystick::GAMEPAD_BUTTON_DPAD_LEFT }, + { "dpright", Joystick::GAMEPAD_BUTTON_DPAD_RIGHT }, } +STRINGMAP_CLASS_END(Joystick, Joystick::GamepadButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM, gpButton) -bool Joystick::getConstant(const char *in, Joystick::GamepadButton &out) +STRINGMAP_CLASS_BEGIN(Joystick, Joystick::InputType, Joystick::INPUT_TYPE_MAX_ENUM, inputType) { - return gpButtons.find(in, out); + { "axis", Joystick::INPUT_TYPE_AXIS }, + { "button", Joystick::INPUT_TYPE_BUTTON }, + { "hat", Joystick::INPUT_TYPE_HAT }, } - -bool Joystick::getConstant(Joystick::GamepadButton in, const char *&out) -{ - return gpButtons.find(in, out); -} - -bool Joystick::getConstant(const char *in, Joystick::InputType &out) -{ - return inputTypes.find(in, out); -} - -bool Joystick::getConstant(Joystick::InputType in, const char *&out) -{ - return inputTypes.find(in, out); -} - -StringMap::Entry Joystick::hatEntries[] = -{ - {"c", Joystick::HAT_CENTERED}, - {"u", Joystick::HAT_UP}, - {"r", Joystick::HAT_RIGHT}, - {"d", Joystick::HAT_DOWN}, - {"l", Joystick::HAT_LEFT}, - {"ru", Joystick::HAT_RIGHTUP}, - {"rd", Joystick::HAT_RIGHTDOWN}, - {"lu", Joystick::HAT_LEFTUP}, - {"ld", Joystick::HAT_LEFTDOWN}, -}; - -StringMap Joystick::hats(Joystick::hatEntries, sizeof(Joystick::hatEntries)); - -StringMap::Entry Joystick::gpAxisEntries[] = -{ - {"leftx", GAMEPAD_AXIS_LEFTX}, - {"lefty", GAMEPAD_AXIS_LEFTY}, - {"rightx", GAMEPAD_AXIS_RIGHTX}, - {"righty", GAMEPAD_AXIS_RIGHTY}, - {"triggerleft", GAMEPAD_AXIS_TRIGGERLEFT}, - {"triggerright", GAMEPAD_AXIS_TRIGGERRIGHT}, -}; - -StringMap Joystick::gpAxes(Joystick::gpAxisEntries, sizeof(Joystick::gpAxisEntries)); - -StringMap::Entry Joystick::gpButtonEntries[] = -{ - {"a", GAMEPAD_BUTTON_A}, - {"b", GAMEPAD_BUTTON_B}, - {"x", GAMEPAD_BUTTON_X}, - {"y", GAMEPAD_BUTTON_Y}, - {"back", GAMEPAD_BUTTON_BACK}, - {"guide", GAMEPAD_BUTTON_GUIDE}, - {"start", GAMEPAD_BUTTON_START}, - {"leftstick", GAMEPAD_BUTTON_LEFTSTICK}, - {"rightstick", GAMEPAD_BUTTON_RIGHTSTICK}, - {"leftshoulder", GAMEPAD_BUTTON_LEFTSHOULDER}, - {"rightshoulder", GAMEPAD_BUTTON_RIGHTSHOULDER}, - {"dpup", GAMEPAD_BUTTON_DPAD_UP}, - {"dpdown", GAMEPAD_BUTTON_DPAD_DOWN}, - {"dpleft", GAMEPAD_BUTTON_DPAD_LEFT}, - {"dpright", GAMEPAD_BUTTON_DPAD_RIGHT}, -}; - -StringMap Joystick::gpButtons(Joystick::gpButtonEntries, sizeof(Joystick::gpButtonEntries)); - -StringMap::Entry Joystick::inputTypeEntries[] = -{ - {"axis", Joystick::INPUT_TYPE_AXIS}, - {"button", Joystick::INPUT_TYPE_BUTTON}, - {"hat", Joystick::INPUT_TYPE_HAT}, -}; - -StringMap Joystick::inputTypes(Joystick::inputTypeEntries, sizeof(Joystick::inputTypeEntries)); +STRINGMAP_CLASS_END(Joystick, Joystick::InputType, Joystick::INPUT_TYPE_MAX_ENUM, inputType) } // joystick } // love diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index c16109246..456445bf5 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -56,6 +56,19 @@ public: HAT_MAX_ENUM = 16 }; + enum GamepadType + { + GAMEPAD_TYPE_UNKNOWN, + GAMEPAD_TYPE_XBOX360, + GAMEPAD_TYPE_XBOXONE, + GAMEPAD_TYPE_PS3, + GAMEPAD_TYPE_PS4, + GAMEPAD_TYPE_PS5, + GAMEPAD_TYPE_NINTENDO_SWITCH_PRO, + GAMEPAD_TYPE_VIRTUAL, + GAMEPAD_TYPE_MAX_ENUM + }; + // Valid Gamepad axes. enum GamepadAxis { @@ -149,6 +162,8 @@ public: virtual bool openGamepad(int deviceindex) = 0; virtual bool isGamepad() const = 0; + virtual GamepadType getGamepadType() const = 0; + virtual float getGamepadAxis(GamepadAxis axis) const = 0; virtual bool isGamepadDown(const std::vector &blist) const = 0; @@ -168,34 +183,14 @@ public: virtual bool setVibration() = 0; virtual void getVibration(float &left, float &right) = 0; - static bool getConstant(const char *in, Hat &out); - static bool getConstant(Hat in, const char *&out); - - static bool getConstant(const char *in, GamepadAxis &out); - static bool getConstant(GamepadAxis in, const char *&out); - - static bool getConstant(const char *in, GamepadButton &out); - static bool getConstant(GamepadButton in, const char *&out); - - static bool getConstant(const char *in, InputType &out); - static bool getConstant(InputType in, const char *&out); + STRINGMAP_CLASS_DECLARE(Hat); + STRINGMAP_CLASS_DECLARE(GamepadType); + STRINGMAP_CLASS_DECLARE(GamepadAxis); + STRINGMAP_CLASS_DECLARE(GamepadButton); + STRINGMAP_CLASS_DECLARE(InputType); static float clampval(float x); -private: - - static StringMap::Entry hatEntries[]; - static StringMap hats; - - static StringMap::Entry gpAxisEntries[]; - static StringMap gpAxes; - - static StringMap::Entry gpButtonEntries[]; - static StringMap gpButtons; - - static StringMap::Entry inputTypeEntries[]; - static StringMap inputTypes; - }; // Joystick } // joystick diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index 612cce5cf..d4476cd9b 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -215,6 +215,30 @@ bool Joystick::isGamepad() const return controller != nullptr; } +Joystick::GamepadType Joystick::getGamepadType() const +{ + if (controller == nullptr) + return GAMEPAD_TYPE_UNKNOWN; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + switch (SDL_GameControllerGetType(controller)) + { + case SDL_CONTROLLER_TYPE_UNKNOWN: return GAMEPAD_TYPE_UNKNOWN; + case SDL_CONTROLLER_TYPE_XBOX360: return GAMEPAD_TYPE_XBOX360; + case SDL_CONTROLLER_TYPE_XBOXONE: return GAMEPAD_TYPE_XBOXONE; + case SDL_CONTROLLER_TYPE_PS3: return GAMEPAD_TYPE_PS3; + case SDL_CONTROLLER_TYPE_PS4: return GAMEPAD_TYPE_PS4; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: return GAMEPAD_TYPE_NINTENDO_SWITCH_PRO; +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_VIRTUAL: return GAMEPAD_TYPE_VIRTUAL; + case SDL_CONTROLLER_TYPE_PS5: return GAMEPAD_TYPE_PS5; +#endif + } +#endif + + return GAMEPAD_TYPE_UNKNOWN; +} + float Joystick::getGamepadAxis(love::joystick::Joystick::GamepadAxis axis) const { if (!isConnected() || !isGamepad()) diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index 8b9fedca7..c559ea228 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -64,6 +64,8 @@ public: bool openGamepad(int deviceindex) override; bool isGamepad() const override; + GamepadType getGamepadType() const override; + float getGamepadAxis(GamepadAxis axis) const override; bool isGamepadDown(const std::vector &blist) const override; diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index 9608aee37..76b9f6db9 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -178,6 +178,15 @@ int w_Joystick_isGamepad(lua_State *L) return 1; } +int w_Joystick_getGamepadType(lua_State *L) +{ + Joystick *j = luax_checkjoystick(L, 1); + const char *str = "unknown"; + Joystick::getConstant(j->getGamepadType(), str); + lua_pushstring(L, str); + return 1; +} + int w_Joystick_getGamepadAxis(lua_State *L) { Joystick *j = luax_checkjoystick(L, 1); @@ -359,6 +368,7 @@ static const luaL_Reg w_Joystick_functions[] = { "isDown", w_Joystick_isDown }, { "isGamepad", w_Joystick_isGamepad }, + { "getGamepadType", w_Joystick_getGamepadType }, { "getGamepadAxis", w_Joystick_getGamepadAxis }, { "isGamepadDown", w_Joystick_isGamepadDown }, { "getGamepadMapping", w_Joystick_getGamepadMapping }, From 5e411f607fe1613642024ad4b1ab39eaaa0482a6 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 14 Feb 2021 16:03:36 -0400 Subject: [PATCH 16/17] Expose new gamepad buttons from SDL --- src/modules/joystick/Joystick.cpp | 6 ++++++ src/modules/joystick/Joystick.h | 6 ++++++ src/modules/joystick/sdl/Joystick.cpp | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/src/modules/joystick/Joystick.cpp b/src/modules/joystick/Joystick.cpp index a67a16c3c..b976d8b26 100644 --- a/src/modules/joystick/Joystick.cpp +++ b/src/modules/joystick/Joystick.cpp @@ -97,6 +97,12 @@ STRINGMAP_CLASS_BEGIN(Joystick, Joystick::GamepadButton, Joystick::GAMEPAD_BUTTO { "dpdown", Joystick::GAMEPAD_BUTTON_DPAD_DOWN }, { "dpleft", Joystick::GAMEPAD_BUTTON_DPAD_LEFT }, { "dpright", Joystick::GAMEPAD_BUTTON_DPAD_RIGHT }, + { "misc1", Joystick::GAMEPAD_BUTTON_MISC1 }, + { "paddle1", Joystick::GAMEPAD_BUTTON_PADDLE1 }, + { "paddle2", Joystick::GAMEPAD_BUTTON_PADDLE2 }, + { "paddle3", Joystick::GAMEPAD_BUTTON_PADDLE3 }, + { "paddle4", Joystick::GAMEPAD_BUTTON_PADDLE4 }, + { "touchpad", Joystick::GAMEPAD_BUTTON_TOUCHPAD }, } STRINGMAP_CLASS_END(Joystick, Joystick::GamepadButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM, gpButton) diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index 456445bf5..5242f967c 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -101,6 +101,12 @@ public: GAMEPAD_BUTTON_DPAD_DOWN, GAMEPAD_BUTTON_DPAD_LEFT, GAMEPAD_BUTTON_DPAD_RIGHT, + GAMEPAD_BUTTON_MISC1, // Xbox Series X share button, PS5 mic button, Switch Pro capture button + GAMEPAD_BUTTON_PADDLE1, + GAMEPAD_BUTTON_PADDLE2, + GAMEPAD_BUTTON_PADDLE3, + GAMEPAD_BUTTON_PADDLE4, + GAMEPAD_BUTTON_TOUCHPAD, GAMEPAD_BUTTON_MAX_ENUM }; diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index d4476cd9b..f3cfcde0c 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -660,6 +660,14 @@ EnumMap Joystick::gpButtons(Joystick::gpButtonEntries, sizeof(Joystick::gpButtonEntries)); From b1b70a83db3c379c19f2eabc5d1ccbf0fce70abf Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 15 Feb 2021 16:08:23 -0400 Subject: [PATCH 17/17] Add Joystick:set/getPlayerIndex --- src/modules/joystick/Joystick.h | 3 +++ src/modules/joystick/sdl/Joystick.cpp | 24 ++++++++++++++++++++++++ src/modules/joystick/sdl/Joystick.h | 3 +++ src/modules/joystick/wrap_Joystick.cpp | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index 5242f967c..c635f5bff 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -165,6 +165,9 @@ public: virtual bool isDown(const std::vector &buttonlist) const = 0; + virtual void setPlayerIndex(int index) = 0; + virtual int getPlayerIndex() const = 0; + virtual bool openGamepad(int deviceindex) = 0; virtual bool isGamepad() const = 0; diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index f3cfcde0c..f05de9372 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -195,6 +195,30 @@ bool Joystick::isDown(const std::vector &buttonlist) const return false; } +void Joystick::setPlayerIndex(int index) +{ + if (!isConnected()) + return; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + SDL_JoystickSetPlayerIndex(joyhandle, index); +#else + LOVE_UNUSED(index); +#endif +} + +int Joystick::getPlayerIndex() const +{ + if (!isConnected()) + return -1; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + return SDL_JoystickGetPlayerIndex(joyhandle); +#else + return -1; +#endif +} + bool Joystick::openGamepad(int deviceindex) { if (!SDL_IsGameController(deviceindex)) diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index c559ea228..1f378d9ed 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -61,6 +61,9 @@ public: bool isDown(const std::vector &buttonlist) const override; + void setPlayerIndex(int index) override; + int getPlayerIndex() const override; + bool openGamepad(int deviceindex) override; bool isGamepad() const override; diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index 76b9f6db9..9c23def9e 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -171,6 +171,22 @@ int w_Joystick_isDown(lua_State *L) return 1; } +int w_Joystick_setPlayerIndex(lua_State *L) +{ + Joystick *j = luax_checkjoystick(L, 1); + int index = (int) luaL_checkinteger(L, 2) - 1; + j->setPlayerIndex(index); + return 0; +} + +int w_Joystick_getPlayerIndex(lua_State *L) +{ + Joystick *j = luax_checkjoystick(L, 1); + int index = j->getPlayerIndex(); + lua_pushinteger(L, index >= 0 ? index + 1 : index); + return 1; +} + int w_Joystick_isGamepad(lua_State *L) { Joystick *j = luax_checkjoystick(L, 1); @@ -366,6 +382,8 @@ static const luaL_Reg w_Joystick_functions[] = { "getAxes", w_Joystick_getAxes }, { "getHat", w_Joystick_getHat }, { "isDown", w_Joystick_isDown }, + { "setPlayerIndex", w_Joystick_setPlayerIndex }, + { "getPlayerIndex", w_Joystick_getPlayerIndex }, { "isGamepad", w_Joystick_isGamepad }, { "getGamepadType", w_Joystick_getGamepadType },