mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Add love.graphics.copyTextureToBuffer and copyBufferToTexture.
This commit is contained in:
@@ -1640,7 +1640,10 @@ void Graphics::initCapabilities()
|
||||
capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported();
|
||||
capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_TEXEL);
|
||||
capabilities.features[FEATURE_COPY_BUFFER] = gl.isCopyBufferSupported();
|
||||
static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
|
||||
capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = gl.isCopyBufferToTextureSupported();
|
||||
capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = gl.isCopyTextureToBufferSupported();
|
||||
capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = gl.isCopyRenderTargetToBufferSupported();
|
||||
static_assert(FEATURE_MAX_ENUM == 15, "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();
|
||||
|
||||
@@ -1530,6 +1530,24 @@ bool OpenGL::isCopyBufferSupported() const
|
||||
return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0;
|
||||
}
|
||||
|
||||
bool OpenGL::isCopyBufferToTextureSupported() const
|
||||
{
|
||||
// Requires pixel unpack buffer binding support.
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0;
|
||||
}
|
||||
|
||||
bool OpenGL::isCopyTextureToBufferSupported() const
|
||||
{
|
||||
// Requires glGetTextureSubImage support.
|
||||
return GLAD_VERSION_4_5;
|
||||
}
|
||||
|
||||
bool OpenGL::isCopyRenderTargetToBufferSupported() const
|
||||
{
|
||||
// Requires pixel pack buffer binding support.
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0;
|
||||
}
|
||||
|
||||
int OpenGL::getMax2DTextureSize() const
|
||||
{
|
||||
return std::max(max2DTextureSize, 1);
|
||||
|
||||
@@ -372,6 +372,9 @@ public:
|
||||
bool isBaseVertexSupported() const;
|
||||
bool isMultiFormatMRTSupported() const;
|
||||
bool isCopyBufferSupported() const;
|
||||
bool isCopyBufferToTextureSupported() const;
|
||||
bool isCopyTextureToBufferSupported() const;
|
||||
bool isCopyRenderTargetToBufferSupported() const;
|
||||
|
||||
/**
|
||||
* Returns the maximum supported width or height of a texture.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "graphics/Graphics.h"
|
||||
#include "Graphics.h"
|
||||
#include "Buffer.h"
|
||||
#include "common/int.h"
|
||||
|
||||
// STD
|
||||
@@ -524,6 +525,75 @@ void Texture::readbackImageData(love::image::ImageData *data, int slice, int mip
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo);
|
||||
}
|
||||
|
||||
void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect)
|
||||
{
|
||||
// Higher level code does validation.
|
||||
|
||||
GLuint glbuffer = (GLuint) source->getHandle();
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glbuffer);
|
||||
|
||||
if (!isCompressed()) // Not supported in GL with compressed textures...
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, sourcewidth);
|
||||
|
||||
// glTexSubImage and friends copy from the active pixel_unpack_buffer by
|
||||
// treating the pointer as a byte offset.
|
||||
const uint8 *byteoffset = (const uint8 *)(ptrdiff_t)sourceoffset;
|
||||
uploadByteData(format, byteoffset, size, mipmap, slice, rect);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size)
|
||||
{
|
||||
// Higher level code does validation.
|
||||
|
||||
GLuint glbuffer = (GLuint) dest->getHandle();
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, glbuffer);
|
||||
|
||||
if (!isCompressed()) // Not supported in GL with compressed textures...
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, destwidth);
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
bool isSRGB = false;
|
||||
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, isSRGB);
|
||||
|
||||
// glTexSubImage and friends copy from the active pixel_unpack_buffer by
|
||||
// treating the pointer as a byte offset.
|
||||
uint8 *byteoffset = (uint8 *)(ptrdiff_t)destoffset;
|
||||
|
||||
if (GLAD_VERSION_4_5)
|
||||
{
|
||||
if (isCompressed())
|
||||
glGetCompressedTextureSubImage(texture, mipmap, rect.x, rect.y, slice, rect.w, rect.h, 1, size, byteoffset);
|
||||
else
|
||||
glGetTextureSubImage(texture, mipmap, rect.x, rect.y, slice, rect.w, rect.h, 1, fmt.externalformat, fmt.type, size, byteoffset);
|
||||
}
|
||||
else if (fbo)
|
||||
{
|
||||
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, getFBO());
|
||||
|
||||
if (slice > 0 || mipmap > 0)
|
||||
{
|
||||
int layer = texType == TEXTURE_CUBE ? 0 : slice;
|
||||
int face = texType == TEXTURE_CUBE ? slice : 0;
|
||||
gl.framebufferTexture(GL_COLOR_ATTACHMENT0, texType, texture, mipmap, layer, face);
|
||||
}
|
||||
|
||||
glReadPixels(rect.x, rect.y, rect.w, rect.h, fmt.externalformat, fmt.type, byteoffset);
|
||||
|
||||
if (slice > 0 || mipmap > 0)
|
||||
gl.framebufferTexture(GL_COLOR_ATTACHMENT0, texType, texture, 0, 0, 0);
|
||||
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo);
|
||||
}
|
||||
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void Texture::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
if (s.depthSampleMode.hasValue && !gl.isDepthCompareSampleSupported())
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
bool loadVolatile() override;
|
||||
void unloadVolatile() override;
|
||||
|
||||
void copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override;
|
||||
void copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) override;
|
||||
|
||||
void setSamplerState(const SamplerState &s) override;
|
||||
|
||||
ptrdiff_t getHandle() const override;
|
||||
|
||||
Reference in New Issue
Block a user