Move some Canvas code to Texture, devirtualize Texture::draw.

This commit is contained in:
Alex Szpakowski
2020-02-03 19:02:58 -04:00
parent f9248d478c
commit b46b3ed552
19 changed files with 136 additions and 128 deletions
+29 -38
View File
@@ -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<Graphics>(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
-2
View File
@@ -68,8 +68,6 @@ public:
return fbo;
}
static bool isMultiFormatMultiCanvasSupported();
private:
GLuint fbo;
+5 -5
View File
@@ -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)
+1 -1
View File
@@ -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;
+10 -7
View File
@@ -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);
}
+1 -1
View File
@@ -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();
+5
View File
@@ -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);
+1
View File
@@ -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.