From b46b3ed5524c7de6427077a1fe21abdafbf069f8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 3 Feb 2020 19:02:58 -0400 Subject: [PATCH] Move some Canvas code to Texture, devirtualize Texture::draw. --- src/common/pixelformat.cpp | 14 +++++ src/common/pixelformat.h | 10 ++++ src/modules/graphics/Canvas.cpp | 31 +++-------- src/modules/graphics/Canvas.h | 6 --- src/modules/graphics/Graphics.cpp | 15 +++--- src/modules/graphics/Graphics.h | 9 ++-- src/modules/graphics/Image.cpp | 20 ++----- src/modules/graphics/Image.h | 6 --- src/modules/graphics/Texture.cpp | 26 +++++++++ src/modules/graphics/Texture.h | 14 ++++- src/modules/graphics/opengl/Canvas.cpp | 67 ++++++++++-------------- src/modules/graphics/opengl/Canvas.h | 2 - src/modules/graphics/opengl/Graphics.cpp | 10 ++-- src/modules/graphics/opengl/Graphics.h | 2 +- src/modules/graphics/opengl/Image.cpp | 17 +++--- src/modules/graphics/opengl/Image.h | 2 +- src/modules/graphics/opengl/OpenGL.cpp | 5 ++ src/modules/graphics/opengl/OpenGL.h | 1 + src/modules/graphics/wrap_Graphics.cpp | 7 +-- 19 files changed, 136 insertions(+), 128 deletions(-) diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index 0177cc824..0048236b4 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -137,6 +137,20 @@ bool isPixelFormatStencil(PixelFormat format) return format == PIXELFORMAT_STENCIL8 || format == PIXELFORMAT_DEPTH24_UNORM_STENCIL8 || format == PIXELFORMAT_DEPTH32_FLOAT_STENCIL8; } +PixelFormat getSRGBPixelFormat(PixelFormat format) +{ + if (format == PIXELFORMAT_RGBA8_UNORM) + return PIXELFORMAT_sRGBA8_UNORM; + return format; +} + +PixelFormat getLinearPixelFormat(PixelFormat format) +{ + if (format == PIXELFORMAT_sRGBA8_UNORM) + return PIXELFORMAT_RGBA8_UNORM; + return format; +} + size_t getPixelFormatSize(PixelFormat format) { switch (format) diff --git a/src/common/pixelformat.h b/src/common/pixelformat.h index b1657d92e..40f1be664 100644 --- a/src/common/pixelformat.h +++ b/src/common/pixelformat.h @@ -132,6 +132,16 @@ bool isPixelFormatDepth(PixelFormat format); **/ bool isPixelFormatStencil(PixelFormat format); +/** + * Gets the sRGB version of a linear pixel format, if applicable. + **/ +PixelFormat getSRGBPixelFormat(PixelFormat format); + +/** + * Gets the linear version of a sRGB pixel format, if applicable. + **/ +PixelFormat getLinearPixelFormat(PixelFormat format); + /** * Gets the size in bytes of the specified pixel format. * NOTE: Currently returns 0 for compressed formats. diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index 008851615..88cd98b5a 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -27,13 +27,15 @@ namespace graphics { love::Type Canvas::type("Canvas", &Texture::type); -int Canvas::canvasCount = 0; Canvas::Canvas(const Settings &settings) : Texture(settings.type) { this->settings = settings; + renderTarget = true; + sRGB = false; + width = settings.width; height = settings.height; pixelWidth = (int) ((width * settings.dpiScale) + 0.5); @@ -69,7 +71,7 @@ Canvas::Canvas(const Settings &settings) auto gfx = Module::getInstance(Module::M_GRAPHICS); const Graphics::Capabilities &caps = gfx->getCapabilities(); - if (!gfx->isPixelFormatSupported(format, true, readable, false)) + if (!gfx->isPixelFormatSupported(format, renderTarget, readable, sRGB)) { const char *fstr = "rgba8"; const char *readablestr = ""; @@ -93,13 +95,10 @@ Canvas::Canvas(const Settings &settings) } validateDimensions(true); - - canvasCount++; } Canvas::~Canvas() { - canvasCount--; } Canvas::MipmapMode Canvas::getMipmapMode() const @@ -131,12 +130,10 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int sli } Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); - if (gfx != nullptr && gfx->isCanvasActive(this)) + if (gfx != nullptr && gfx->isRenderTargetActive(this)) throw love::Exception("Canvas:newImageData cannot be called while that Canvas is currently active."); - PixelFormat dataformat = getPixelFormat(); - if (dataformat == PIXELFORMAT_sRGBA8_UNORM) - dataformat = PIXELFORMAT_RGBA8_UNORM; + PixelFormat dataformat = getLinearPixelFormat(getPixelFormat()); if (!image::ImageData::validPixelFormat(dataformat)) { @@ -148,22 +145,6 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int sli return module->newImageData(r.w, r.h, dataformat); } -void Canvas::draw(Graphics *gfx, Quad *q, const Matrix4 &t) -{ - if (gfx->isCanvasActive(this)) - throw love::Exception("Cannot render a Canvas to itself!"); - - Texture::draw(gfx, q, t); -} - -void Canvas::drawLayer(Graphics *gfx, int layer, Quad *quad, const Matrix4 &m) -{ - if (gfx->isCanvasActive(this, layer)) - throw love::Exception("Cannot render a Canvas to itself!"); - - Texture::drawLayer(gfx, layer, quad, m); -} - bool Canvas::getConstant(const char *in, MipmapMode &out) { return mipmapModes.find(in, out); diff --git a/src/modules/graphics/Canvas.h b/src/modules/graphics/Canvas.h index 8171f5f54..05e5a844d 100644 --- a/src/modules/graphics/Canvas.h +++ b/src/modules/graphics/Canvas.h @@ -81,16 +81,10 @@ public: int getRequestedMSAA() const; virtual love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect); - virtual void generateMipmaps() = 0; virtual int getMSAA() const = 0; virtual ptrdiff_t getRenderTargetHandle() const = 0; - void draw(Graphics *gfx, Quad *q, const Matrix4 &t) override; - void drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &t) override; - - static int canvasCount; - static bool getConstant(const char *in, MipmapMode &out); static bool getConstant(MipmapMode in, const char *&out); static std::vector getConstants(MipmapMode); diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index fcdb70cee..5ae9493dd 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -761,33 +761,33 @@ bool Graphics::isCanvasActive() const return !rts.colors.empty() || rts.depthStencil.canvas != nullptr; } -bool Graphics::isCanvasActive(love::graphics::Canvas *canvas) const +bool Graphics::isRenderTargetActive(Texture *texture) const { const auto &rts = states.back().renderTargets; for (const auto &rt : rts.colors) { - if (rt.canvas.get() == canvas) + if (rt.canvas.get() == texture) return true; } - if (rts.depthStencil.canvas.get() == canvas) + if (rts.depthStencil.canvas.get() == texture) return true; return false; } -bool Graphics::isCanvasActive(Canvas *canvas, int slice) const +bool Graphics::isRenderTargetActive(Texture *texture, int slice) const { const auto &rts = states.back().renderTargets; for (const auto &rt : rts.colors) { - if (rt.canvas.get() == canvas && rt.slice == slice) + if (rt.canvas.get() == texture && rt.slice == slice) return true; } - if (rts.depthStencil.canvas.get() == canvas && rts.depthStencil.slice == slice) + if (rts.depthStencil.canvas.get() == texture && rts.depthStencil.slice == slice) return true; return false; @@ -1593,8 +1593,7 @@ Graphics::Stats Graphics::getStats() const stats.canvasSwitches = canvasSwitchCount; stats.drawCallsBatched = drawCallsBatched; - stats.canvases = Canvas::canvasCount; - stats.images = Image::imageCount; + stats.textures = Texture::textureCount; stats.fonts = Font::fontCount; stats.textureMemory = Texture::totalGraphicsMemory; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 151be6f08..cac7a6edc 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -202,8 +202,7 @@ public: int drawCallsBatched; int canvasSwitches; int shaderSwitches; - int canvases; - int images; + int textures; int fonts; int64 textureMemory; }; @@ -551,8 +550,8 @@ public: RenderTargets getCanvas() const; bool isCanvasActive() const; - bool isCanvasActive(Canvas *canvas) const; - bool isCanvasActive(Canvas *canvas, int slice) const; + bool isRenderTargetActive(Texture *texture) const; + bool isRenderTargetActive(Texture *texture, int slice) const; /** * Scissor defines a box such that everything outside that box is discarded @@ -781,7 +780,7 @@ public: /** * Converts PIXELFORMAT_NORMAL and PIXELFORMAT_HDR into a real format. **/ - virtual PixelFormat getSizedFormat(PixelFormat format) const = 0; + virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const = 0; /** * Gets whether the specified pixel format is supported. diff --git a/src/modules/graphics/Image.cpp b/src/modules/graphics/Image.cpp index 83d423dae..99d89d98e 100644 --- a/src/modules/graphics/Image.cpp +++ b/src/modules/graphics/Image.cpp @@ -31,15 +31,14 @@ namespace graphics love::Type Image::type("Image", &Texture::type); -int Image::imageCount = 0; - Image::Image(const Slices &data, const Settings &settings, bool validatedata) : Texture(data.getTextureType()) , settings(settings) , mipmapsType(settings.mipmaps ? MIPMAPS_GENERATED : MIPMAPS_NONE) - , sRGB(isGammaCorrect() && !settings.linear) , usingDefaultTexture(false) { + renderTarget = false; + sRGB = isGammaCorrect() && !settings.linear; if (validatedata && data.validate() && data.getMipmapCount() > 1) mipmapsType = MIPMAPS_DATA; } @@ -72,13 +71,12 @@ Image::Image(const Slices &slices, const Settings &settings) Image::~Image() { - --imageCount; } void Image::init(PixelFormat fmt, int w, int h, const Settings &settings) { Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); - if (gfx != nullptr && !gfx->isPixelFormatSupported(fmt, false, true, sRGB)) + if (gfx != nullptr && !gfx->isPixelFormatSupported(fmt, renderTarget, readable, sRGB)) { const char *str; if (love::getConstant(fmt, str)) @@ -104,8 +102,6 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings) mipmapCount = mipmapsType == MIPMAPS_NONE ? 1 : getTotalMipmapCount(w, h, depth); initQuad(); - - ++imageCount; } void Image::uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y) @@ -172,16 +168,6 @@ void Image::replacePixels(const void *data, size_t size, int slice, int mipmap, generateMipmaps(); } -bool Image::isCompressed() const -{ - return isPixelFormatCompressed(format); -} - -bool Image::isFormatLinear() const -{ - return isGammaCorrect() && !sRGB && format != PIXELFORMAT_sRGBA8_UNORM; -} - Image::MipmapsType Image::getMipmapsType() const { return mipmapsType; diff --git a/src/modules/graphics/Image.h b/src/modules/graphics/Image.h index a8aeabb7c..0d4f1139c 100644 --- a/src/modules/graphics/Image.h +++ b/src/modules/graphics/Image.h @@ -58,11 +58,8 @@ public: void replacePixels(const void *data, size_t size, int slice, int mipmap, const Rect &rect, bool reloadmipmaps); bool isFormatLinear() const; - bool isCompressed() const; MipmapsType getMipmapsType() const; - static int imageCount; - static bool getConstant(const char *in, SettingType &out); static bool getConstant(SettingType in, const char *&out); static const char *getConstant(SettingType in); @@ -76,13 +73,10 @@ protected: 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 generateMipmaps() = 0; - // The settings used to initialize this Image. Settings settings; MipmapsType mipmapsType; - bool sRGB; // True if the image wasn't able to be properly created and it had to fall // back to a default texture. diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 1866aae50..3ac2ba8e9 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -156,12 +156,15 @@ std::vector SamplerState::getConstants(WrapMode) } love::Type Texture::type("Texture", &Drawable::type); +int Texture::textureCount = 0; int64 Texture::totalGraphicsMemory = 0; Texture::Texture(TextureType texType) : texType(texType) , format(PIXELFORMAT_UNKNOWN) + , renderTarget(false) , readable(true) + , sRGB(false) , width(0) , height(0) , depth(1) @@ -175,10 +178,12 @@ Texture::Texture(TextureType texType) auto gfx = Module::getInstance(Module::M_GRAPHICS); if (gfx != nullptr) samplerState = gfx->getDefaultSamplerState(); + ++textureCount; } Texture::~Texture() { + --textureCount; setGraphicsMemorySize(0); } @@ -207,11 +212,26 @@ PixelFormat Texture::getPixelFormat() const return format; } +bool Texture::isRenderTarget() const +{ + return renderTarget; +} + bool Texture::isReadable() const { return readable; } +bool Texture::isCompressed() const +{ + return isPixelFormatCompressed(format); +} + +bool Texture::isFormatLinear() const +{ + return isGammaCorrect() && !sRGB && format != PIXELFORMAT_sRGBA8_UNORM; +} + bool Texture::isValidSlice(int slice) const { if (slice < 0) @@ -241,6 +261,9 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) if (!readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); + if (renderTarget && gfx->isRenderTargetActive(this)) + throw love::Exception("Cannot render a Texture to itself."); + if (texType == TEXTURE_2D_ARRAY) { drawLayer(gfx, q->getLayer(), q, localTransform); @@ -291,6 +314,9 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) if (!readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); + if (renderTarget && gfx->isRenderTargetActive(this, layer)) + throw love::Exception("Cannot render a Texture to itself."); + if (texType != TEXTURE_2D_ARRAY) throw love::Exception("drawLayer can only be used with Array Textures!"); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index ee0c7c654..c93a28d04 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -126,6 +126,7 @@ class Texture : public Drawable, public Resource public: static love::Type type; + static int textureCount; enum MipmapsType { @@ -175,16 +176,20 @@ public: /** * Draws the texture using the specified transformation with a Quad applied. **/ - virtual void draw(Graphics *gfx, Quad *quad, const Matrix4 &m); + void draw(Graphics *gfx, Quad *quad, const Matrix4 &m); void drawLayer(Graphics *gfx, int layer, const Matrix4 &m); - virtual void drawLayer(Graphics *gfx, int layer, Quad *quad, const Matrix4 &m); + void drawLayer(Graphics *gfx, int layer, Quad *quad, const Matrix4 &m); TextureType getTextureType() const; PixelFormat getPixelFormat() const; + bool isRenderTarget() const; bool isReadable() const; + bool isCompressed() const; + bool isFormatLinear() const; + bool isValidSlice(int slice) const; int getWidth(int mip = 0) const; @@ -201,6 +206,8 @@ public: virtual void setSamplerState(const SamplerState &s); const SamplerState &getSamplerState() const; + virtual void generateMipmaps() = 0; + Quad *getQuad() const; static int getTotalMipmapCount(int w, int h); @@ -220,8 +227,11 @@ protected: TextureType texType; PixelFormat format; + bool renderTarget; bool readable; + bool sRGB; + int width; int height; diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index f3555d1d9..7ee5faf3e 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -31,7 +31,7 @@ namespace graphics namespace opengl { -static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat format, GLuint texture, int layers, int nb_mips) +static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat format, GLuint texture, int layers) { // get currently bound fbo to reset to it later GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL); @@ -60,42 +60,35 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo // Make sure all faces and layers of the texture are initialized to // transparent black. This is unfortunately probably pretty slow for // 2D-array and 3D textures with a lot of layers... - for (int mip = nb_mips - 1; mip >= 0; mip--) + for (int layer = layers - 1; layer >= 0; layer--) { - int nlayers = layers; - if (texType == TEXTURE_VOLUME) - nlayers = std::max(layers >> mip, 1); - - for (int layer = nlayers - 1; layer >= 0; layer--) + for (int face = faces - 1; face >= 0; face--) { - for (int face = faces - 1; face >= 0; face--) + for (GLenum attachment : fmt.framebufferAttachments) { - for (GLenum attachment : fmt.framebufferAttachments) - { - if (attachment == GL_NONE) - continue; + if (attachment == GL_NONE) + continue; - gl.framebufferTexture(attachment, texType, texture, mip, layer, face); - } + gl.framebufferTexture(attachment, texType, texture, 0, layer, face); + } - if (isPixelFormatDepthStencil(format)) - { - bool hadDepthWrites = gl.hasDepthWrites(); - if (!hadDepthWrites) // glDepthMask also affects glClear. - gl.setDepthWrites(true); + if (isPixelFormatDepthStencil(format)) + { + bool hadDepthWrites = gl.hasDepthWrites(); + if (!hadDepthWrites) // glDepthMask also affects glClear. + gl.setDepthWrites(true); - gl.clearDepth(1.0); - glClearStencil(0); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + gl.clearDepth(1.0); + glClearStencil(0); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - if (!hadDepthWrites) - gl.setDepthWrites(hadDepthWrites); - } - else - { - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - } + if (!hadDepthWrites) + gl.setDepthWrites(hadDepthWrites); + } + else + { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); } } } @@ -198,7 +191,7 @@ Canvas::Canvas(const Settings &settings) { auto gfx = Module::getInstance(Module::M_GRAPHICS); if (gfx != nullptr) - format = gfx->getSizedFormat(format); + format = gfx->getSizedFormat(format, renderTarget, readable, sRGB); initQuad(); loadVolatile(); @@ -259,8 +252,8 @@ bool Canvas::loadVolatile() return false; } - // Create a canvas-local FBO used for glReadPixels as well as MSAA blitting. - status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers, mipmapCount); + // Create a local FBO used for glReadPixels as well as MSAA blitting. + status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -287,6 +280,9 @@ bool Canvas::loadVolatile() setGraphicsMemorySize(memsize); + if (getMipmapCount() > 1) + generateMipmaps(); + return true; } @@ -390,11 +386,6 @@ void Canvas::generateMipmaps() glGenerateMipmap(gltextype); } -bool Canvas::isMultiFormatMultiCanvasSupported() -{ - return gl.getMaxRenderTargets() > 1 && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); -} - } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index bb45edf7b..deb6b8e48 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -68,8 +68,6 @@ public: return fbo; } - static bool isMultiFormatMultiCanvasSupported(); - private: GLuint fbo; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 18b227e0a..0b961c0ba 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1362,7 +1362,7 @@ void Graphics::getAPIStats(int &shaderswitches) const void Graphics::initCapabilities() { - capabilities.features[FEATURE_MULTI_CANVAS_FORMATS] = Canvas::isMultiFormatMultiCanvasSupported(); + capabilities.features[FEATURE_MULTI_CANVAS_FORMATS] = gl.isMultiFormatMRTSupported(); capabilities.features[FEATURE_CLAMP_ZERO] = gl.isClampZeroOneTextureWrapSupported(); capabilities.features[FEATURE_BLENDMINMAX] = GLAD_VERSION_1_4 || GLAD_ES_VERSION_3_0 || GLAD_EXT_blend_minmax; capabilities.features[FEATURE_LIGHTEN] = capabilities.features[FEATURE_BLENDMINMAX]; @@ -1388,14 +1388,14 @@ void Graphics::initCapabilities() capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i); } -PixelFormat Graphics::getSizedFormat(PixelFormat format) const +PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const { switch (format) { case PIXELFORMAT_NORMAL: if (isGammaCorrect()) return PIXELFORMAT_sRGBA8_UNORM; - else if (!OpenGL::isPixelFormatSupported(PIXELFORMAT_RGBA8_UNORM, true, true, false)) + else if (!OpenGL::isPixelFormatSupported(PIXELFORMAT_RGBA8_UNORM, rendertarget, readable, sRGB)) // 32-bit render targets don't have guaranteed support on GLES2. return PIXELFORMAT_RGBA4_UNORM; else @@ -1409,14 +1409,14 @@ PixelFormat Graphics::getSizedFormat(PixelFormat format) const bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, bool readable, bool sRGB) { - format = getSizedFormat(format); - if (sRGB && format == PIXELFORMAT_RGBA8_UNORM) { format = PIXELFORMAT_sRGBA8_UNORM; sRGB = false; } + format = getSizedFormat(format, rendertarget, readable, sRGB); + OptionalBool &supported = supportedFormats[format][rendertarget ? 1 : 0][readable ? 1 : 0][sRGB ? 1 : 0]; if (supported.hasValue) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 9dbdb3033..837390585 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) const override; + PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) 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/Image.cpp b/src/modules/graphics/opengl/Image.cpp index ac5bdd50e..a724b003b 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -105,9 +105,6 @@ void Image::loadData() if (!isCompressed()) gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers); - if (mipmapsType == MIPMAPS_GENERATED) - mipcount = 1; - int w = pixelWidth; int h = pixelHeight; int d = depth; @@ -123,17 +120,23 @@ void Image::loadData() if (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME) { for (int slice = 0; slice < slices.getSliceCount(mip); slice++) - mipsize += slices.get(slice, mip)->getSize(); + { + auto id = slices.get(slice, mip); + if (id != nullptr) + mipsize += id->getSize(); + } } - GLenum gltarget = OpenGL::getGLTextureType(texType); - glCompressedTexImage3D(gltarget, mip, fmt.internalformat, w, h, d, 0, mipsize, nullptr); + if (mipsize > 0) + { + GLenum gltarget = OpenGL::getGLTextureType(texType); + glCompressedTexImage3D(gltarget, mip, fmt.internalformat, w, h, d, 0, mipsize, nullptr); + } } for (int slice = 0; slice < slicecount; slice++) { love::image::ImageDataBase *id = slices.get(slice, mip); - if (id != nullptr) uploadImageData(id, mip, slice, 0, 0); } diff --git a/src/modules/graphics/opengl/Image.h b/src/modules/graphics/opengl/Image.h index 124e1bbf5..5820d380c 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -50,11 +50,11 @@ public: ptrdiff_t getHandle() const override; void setSamplerState(const SamplerState &s) override; + void generateMipmaps() override; private: void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) override; - void generateMipmaps() override; void loadDefaultTexture(); void loadData(); diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 17dbb2860..31b5a8d85 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -1328,6 +1328,11 @@ bool OpenGL::isBaseVertexSupported() const return baseVertexSupported; } +bool OpenGL::isMultiFormatMRTSupported() const +{ + return getMaxRenderTargets() > 1 && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); +} + int OpenGL::getMax2DTextureSize() const { return std::max(max2DTextureSize, 1); diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 29b7da1ee..9e7b26f55 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -347,6 +347,7 @@ public: bool isDepthCompareSampleSupported() const; bool isSamplerLODBiasSupported() const; bool isBaseVertexSupported() const; + bool isMultiFormatMRTSupported() const; /** * Returns the maximum supported width or height of a texture. diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index f262b9a0a..e15629d4a 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2394,11 +2394,8 @@ int w_getStats(lua_State *L) lua_pushinteger(L, stats.shaderSwitches); lua_setfield(L, -2, "shaderswitches"); - lua_pushinteger(L, stats.canvases); - lua_setfield(L, -2, "canvases"); - - lua_pushinteger(L, stats.images); - lua_setfield(L, -2, "images"); + lua_pushinteger(L, stats.textures); + lua_setfield(L, -2, "textures"); lua_pushinteger(L, stats.fonts); lua_setfield(L, -2, "fonts");