mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Move some Canvas code to Texture, devirtualize Texture::draw.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -68,8 +68,6 @@ public:
|
||||
return fbo;
|
||||
}
|
||||
|
||||
static bool isMultiFormatMultiCanvasSupported();
|
||||
|
||||
private:
|
||||
|
||||
GLuint fbo;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user