Add methods to make use of GPU local texture data copying bypassing a roundtrip to the CPU and back, add sf::Texture::swap to enable swapping texture contents, fixed sf::Font::cleanup not shrinking its allocated pixel buffer storage when the user loads a new font using the same sf::Font object.

This commit is contained in:
binary1248 2016-07-31 14:08:31 +02:00 committed by Lukas Dürrenberger
parent f053871a6c
commit 6b71456a55
7 changed files with 246 additions and 31 deletions

View File

@ -276,6 +276,43 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y); void update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y);
////////////////////////////////////////////////////////////
/// \brief Update a part of this texture from another texture
///
/// Although the source texture can be smaller than this texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has (x, y) additional arguments,
/// is more convenient for updating a sub-area of this texture.
///
/// No additional check is performed on the size of the passed
/// texture, passing a texture bigger than this texture
/// will lead to an undefined behavior.
///
/// This function does nothing if either texture was not
/// previously created.
///
/// \param texture Source texture to copy to this texture
///
////////////////////////////////////////////////////////////
void update(const Texture& texture);
////////////////////////////////////////////////////////////
/// \brief Update a part of this texture from another texture
///
/// No additional check is performed on the size of the texture,
/// passing an invalid combination of texture size and offset
/// will lead to an undefined behavior.
///
/// This function does nothing if either texture was not
/// previously created.
///
/// \param texture Source texture to copy to this texture
/// \param x X offset in this texture where to copy the source texture
/// \param y Y offset in this texture where to copy the source texture
///
////////////////////////////////////////////////////////////
void update(const Texture& texture, unsigned int x, unsigned int y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Update the texture from an image /// \brief Update the texture from an image
/// ///
@ -480,6 +517,14 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Texture& operator =(const Texture& right); Texture& operator =(const Texture& right);
////////////////////////////////////////////////////////////
/// \brief Swap the contents of this texture with those of another
///
/// \param right Instance to swap with
///
////////////////////////////////////////////////////////////
void swap(Texture& right);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the underlying OpenGL handle of the texture. /// \brief Get the underlying OpenGL handle of the texture.
/// ///

View File

@ -504,7 +504,7 @@ void Font::cleanup()
m_streamRec = NULL; m_streamRec = NULL;
m_refCount = NULL; m_refCount = NULL;
m_pages.clear(); m_pages.clear();
m_pixelBuffer.clear(); std::vector<Uint8>().swap(m_pixelBuffer);
} }
@ -583,11 +583,14 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
// pollute them with pixels from neighbors // pollute them with pixels from neighbors
const unsigned int padding = 1; const unsigned int padding = 1;
width += 2 * padding;
height += 2 * padding;
// Get the glyphs page corresponding to the character size // Get the glyphs page corresponding to the character size
Page& page = m_pages[characterSize]; Page& page = m_pages[characterSize];
// Find a good position for the new glyph into the texture // Find a good position for the new glyph into the texture
glyph.textureRect = findGlyphRect(page, width + 2 * padding, height + 2 * padding); glyph.textureRect = findGlyphRect(page, width, height);
// Make sure the texture data is positioned in the center // Make sure the texture data is positioned in the center
// of the allocated texture rectangle // of the allocated texture rectangle
@ -602,19 +605,32 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
glyph.bounds.width = static_cast<float>(face->glyph->metrics.width) / static_cast<float>(1 << 6) + outlineThickness * 2; glyph.bounds.width = static_cast<float>(face->glyph->metrics.width) / static_cast<float>(1 << 6) + outlineThickness * 2;
glyph.bounds.height = static_cast<float>(face->glyph->metrics.height) / static_cast<float>(1 << 6) + outlineThickness * 2; glyph.bounds.height = static_cast<float>(face->glyph->metrics.height) / static_cast<float>(1 << 6) + outlineThickness * 2;
// Resize the pixel buffer to the new size and fill it with transparent white pixels
m_pixelBuffer.resize(width * height * 4);
Uint8* current = &m_pixelBuffer[0];
Uint8* end = current + width * height * 4;
while (current != end)
{
(*current++) = 255;
(*current++) = 255;
(*current++) = 255;
(*current++) = 0;
}
// Extract the glyph's pixels from the bitmap // Extract the glyph's pixels from the bitmap
m_pixelBuffer.resize(width * height * 4, 255);
const Uint8* pixels = bitmap.buffer; const Uint8* pixels = bitmap.buffer;
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
{ {
// Pixels are 1 bit monochrome values // Pixels are 1 bit monochrome values
for (int y = 0; y < height; ++y) for (int y = padding; y < height - padding; ++y)
{ {
for (int x = 0; x < width; ++x) for (int x = padding; x < width - padding; ++x)
{ {
// The color channels remain white, just fill the alpha channel // The color channels remain white, just fill the alpha channel
std::size_t index = (x + y * width) * 4 + 3; std::size_t index = x + y * width;
m_pixelBuffer[index] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0; m_pixelBuffer[index * 4 + 3] = ((pixels[(x - padding) / 8]) & (1 << (7 - ((x - padding) % 8)))) ? 255 : 0;
} }
pixels += bitmap.pitch; pixels += bitmap.pitch;
} }
@ -622,23 +638,23 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
else else
{ {
// Pixels are 8 bits gray levels // Pixels are 8 bits gray levels
for (int y = 0; y < height; ++y) for (int y = padding; y < height - padding; ++y)
{ {
for (int x = 0; x < width; ++x) for (int x = padding; x < width - padding; ++x)
{ {
// The color channels remain white, just fill the alpha channel // The color channels remain white, just fill the alpha channel
std::size_t index = (x + y * width) * 4 + 3; std::size_t index = x + y * width;
m_pixelBuffer[index] = pixels[x]; m_pixelBuffer[index * 4 + 3] = pixels[x - padding];
} }
pixels += bitmap.pitch; pixels += bitmap.pitch;
} }
} }
// Write the pixels to the texture // Write the pixels to the texture
unsigned int x = glyph.textureRect.left; unsigned int x = glyph.textureRect.left - padding;
unsigned int y = glyph.textureRect.top; unsigned int y = glyph.textureRect.top - padding;
unsigned int w = glyph.textureRect.width; unsigned int w = glyph.textureRect.width + 2 * padding;
unsigned int h = glyph.textureRect.height; unsigned int h = glyph.textureRect.height + 2 * padding;
page.texture.update(&m_pixelBuffer[0], w, h, x, y); page.texture.update(&m_pixelBuffer[0], w, h, x, y);
} }
@ -689,10 +705,10 @@ IntRect Font::findGlyphRect(Page& page, unsigned int width, unsigned int height)
if ((textureWidth * 2 <= Texture::getMaximumSize()) && (textureHeight * 2 <= Texture::getMaximumSize())) if ((textureWidth * 2 <= Texture::getMaximumSize()) && (textureHeight * 2 <= Texture::getMaximumSize()))
{ {
// Make the texture 2 times bigger // Make the texture 2 times bigger
Image newImage; Texture newTexture;
newImage.create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0)); newTexture.create(textureWidth * 2, textureHeight * 2);
newImage.copy(page.texture.copyToImage(), 0, 0); newTexture.update(page.texture);
page.texture.loadFromImage(newImage); page.texture.swap(newTexture);
} }
else else
{ {

View File

@ -111,6 +111,9 @@
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
// Core since 3.0
#define GLEXT_framebuffer_blit false
// Core since 3.0 - EXT_sRGB // Core since 3.0 - EXT_sRGB
#ifdef GL_EXT_sRGB #ifdef GL_EXT_sRGB
#define GLEXT_texture_sRGB GL_EXT_sRGB #define GLEXT_texture_sRGB GL_EXT_sRGB
@ -243,6 +246,14 @@
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
// Core since 3.0 - EXT_framebuffer_blit
#define GLEXT_framebuffer_blit sfogl_ext_EXT_framebuffer_blit
#define GLEXT_glBlitFramebuffer glBlitFramebufferEXT
#define GLEXT_GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_EXT
#define GLEXT_GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_EXT
#define GLEXT_GL_DRAW_FRAMEBUFFER_BINDING GL_DRAW_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_READ_FRAMEBUFFER_BINDING GL_READ_FRAMEBUFFER_BINDING_EXT
// Core since 3.2 - ARB_geometry_shader4 // Core since 3.2 - ARB_geometry_shader4
#define GLEXT_geometry_shader4 sfogl_ext_ARB_geometry_shader4 #define GLEXT_geometry_shader4 sfogl_ext_ARB_geometry_shader4
#define GLEXT_GL_GEOMETRY_SHADER GL_GEOMETRY_SHADER_ARB #define GLEXT_GL_GEOMETRY_SHADER GL_GEOMETRY_SHADER_ARB

View File

@ -15,4 +15,5 @@ ARB_texture_non_power_of_two
EXT_blend_equation_separate EXT_blend_equation_separate
EXT_texture_sRGB EXT_texture_sRGB
EXT_framebuffer_object EXT_framebuffer_object
EXT_framebuffer_blit
ARB_geometry_shader4 ARB_geometry_shader4

View File

@ -47,6 +47,7 @@ int sfogl_ext_ARB_texture_non_power_of_two = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED; int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED; int sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED; int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED; int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
void (GL_FUNCPTR *sf_ptrc_glBlendEquationEXT)(GLenum) = NULL; void (GL_FUNCPTR *sf_ptrc_glBlendEquationEXT)(GLenum) = NULL;
@ -800,6 +801,19 @@ static int Load_EXT_framebuffer_object()
return numFailed; return numFailed;
} }
void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum) = NULL;
static int Load_EXT_framebuffer_blit()
{
int numFailed = 0;
sf_ptrc_glBlitFramebufferEXT = reinterpret_cast<void (GL_FUNCPTR *)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)>(glLoaderGetProcAddress("glBlitFramebufferEXT"));
if (!sf_ptrc_glBlitFramebufferEXT)
numFailed++;
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint) = NULL; void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum) = NULL; void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureFaceARB)(GLenum, GLenum, GLuint, GLint, GLenum) = NULL;
void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint) = NULL; void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureLayerARB)(GLenum, GLenum, GLuint, GLint, GLint) = NULL;
@ -836,7 +850,7 @@ typedef struct sfogl_StrToExtMap_s
PFN_LOADFUNCPOINTERS LoadExtension; PFN_LOADFUNCPOINTERS LoadExtension;
} sfogl_StrToExtMap; } sfogl_StrToExtMap;
static sfogl_StrToExtMap ExtensionMap[15] = { static sfogl_StrToExtMap ExtensionMap[16] = {
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL}, {"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL}, {"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax}, {"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
@ -851,10 +865,11 @@ static sfogl_StrToExtMap ExtensionMap[15] = {
{"GL_EXT_blend_equation_separate", &sfogl_ext_EXT_blend_equation_separate, Load_EXT_blend_equation_separate}, {"GL_EXT_blend_equation_separate", &sfogl_ext_EXT_blend_equation_separate, Load_EXT_blend_equation_separate},
{"GL_EXT_texture_sRGB", &sfogl_ext_EXT_texture_sRGB, NULL}, {"GL_EXT_texture_sRGB", &sfogl_ext_EXT_texture_sRGB, NULL},
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object}, {"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object},
{"GL_EXT_framebuffer_blit", &sfogl_ext_EXT_framebuffer_blit, Load_EXT_framebuffer_blit},
{"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4} {"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4}
}; };
static int g_extensionMapSize = 15; static int g_extensionMapSize = 16;
static void ClearExtensionVars() static void ClearExtensionVars()
@ -873,6 +888,7 @@ static void ClearExtensionVars()
sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED; sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED; sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED; sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED; sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
} }

View File

@ -184,6 +184,7 @@ extern int sfogl_ext_ARB_texture_non_power_of_two;
extern int sfogl_ext_EXT_blend_equation_separate; extern int sfogl_ext_EXT_blend_equation_separate;
extern int sfogl_ext_EXT_texture_sRGB; extern int sfogl_ext_EXT_texture_sRGB;
extern int sfogl_ext_EXT_framebuffer_object; extern int sfogl_ext_EXT_framebuffer_object;
extern int sfogl_ext_EXT_framebuffer_blit;
extern int sfogl_ext_ARB_geometry_shader4; extern int sfogl_ext_ARB_geometry_shader4;
#define GL_CLAMP_TO_EDGE_SGIS 0x812F #define GL_CLAMP_TO_EDGE_SGIS 0x812F
@ -379,6 +380,11 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_STENCIL_INDEX4_EXT 0x8D47 #define GL_STENCIL_INDEX4_EXT 0x8D47
#define GL_STENCIL_INDEX8_EXT 0x8D48 #define GL_STENCIL_INDEX8_EXT 0x8D48
#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 #define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
@ -1242,6 +1248,12 @@ extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageEXT)(GLenum, GLenum, GLsiz
#define glRenderbufferStorageEXT sf_ptrc_glRenderbufferStorageEXT #define glRenderbufferStorageEXT sf_ptrc_glRenderbufferStorageEXT
#endif // GL_EXT_framebuffer_object #endif // GL_EXT_framebuffer_object
#ifndef GL_EXT_framebuffer_blit
#define GL_EXT_framebuffer_blit 1
extern void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
#define glBlitFramebufferEXT sf_ptrc_glBlitFramebufferEXT
#endif // GL_EXT_framebuffer_blit
#ifndef GL_ARB_geometry_shader4 #ifndef GL_ARB_geometry_shader4
#define GL_ARB_geometry_shader4 1 #define GL_ARB_geometry_shader4 1
extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint); extern void (GL_FUNCPTR *sf_ptrc_glFramebufferTextureARB)(GLenum, GLenum, GLuint, GLint);

View File

@ -88,7 +88,20 @@ m_hasMipmap (false),
m_cacheId (getUniqueId()) m_cacheId (getUniqueId())
{ {
if (copy.m_texture) if (copy.m_texture)
loadFromImage(copy.copyToImage()); {
if (create(copy.getSize().x, copy.getSize().y))
{
update(copy);
// Force an OpenGL flush, so that the texture will appear updated
// in all contexts immediately (solves problems in multi-threaded apps)
glCheck(glFlush());
}
else
{
err() << "Failed to copy texture, failed to create new texture" << std::endl;
}
}
} }
@ -422,6 +435,97 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
} }
////////////////////////////////////////////////////////////
void Texture::update(const Texture& texture)
{
// Update the whole texture
update(texture, 0, 0);
}
////////////////////////////////////////////////////////////
void Texture::update(const Texture& texture, unsigned int x, unsigned int y)
{
assert(x + texture.m_size.x <= m_size.x);
assert(y + texture.m_size.x <= m_size.y);
if (!m_texture || !texture.m_texture)
return;
#ifndef SFML_OPENGL_ES
{
TransientContextLock lock;
// Make sure that extensions are initialized
priv::ensureExtensionsInit();
}
if (GLEXT_framebuffer_object && GLEXT_framebuffer_blit)
{
TransientContextLock lock;
// Save the current bindings so we can restore them after we are done
GLint readFramebuffer = 0;
GLint drawFramebuffer = 0;
glCheck(glGetIntegerv(GLEXT_GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer));
glCheck(glGetIntegerv(GLEXT_GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer));
// Create the framebuffers
GLuint sourceFrameBuffer = 0;
GLuint destFrameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &sourceFrameBuffer));
glCheck(GLEXT_glGenFramebuffers(1, &destFrameBuffer));
if (!sourceFrameBuffer || !destFrameBuffer)
{
err() << "Cannot copy texture, failed to create a frame buffer object" << std::endl;
return;
}
// Link the source texture to the source frame buffer
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, sourceFrameBuffer));
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_READ_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_texture, 0));
// Link the destination texture to the destination frame buffer
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, destFrameBuffer));
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_DRAW_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0));
// A final check, just to be sure...
GLenum sourceStatus;
glCheck(sourceStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_READ_FRAMEBUFFER));
GLenum destStatus;
glCheck(destStatus = GLEXT_glCheckFramebufferStatus(GLEXT_GL_DRAW_FRAMEBUFFER));
if ((sourceStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE) && (destStatus == GLEXT_GL_FRAMEBUFFER_COMPLETE))
{
// Blit the texture contents from the source to the destination texture
glCheck(GLEXT_glBlitFramebuffer(0, 0, texture.m_size.x, texture.m_size.y, x, y, x + texture.m_size.x, y + texture.m_size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST));
}
else
{
err() << "Cannot copy texture, failed to link texture to frame buffer" << std::endl;
}
// Restore previously bound framebuffers
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_READ_FRAMEBUFFER, readFramebuffer));
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, drawFramebuffer));
// Delete the framebuffers
glCheck(GLEXT_glDeleteFramebuffers(1, &sourceFrameBuffer));
glCheck(GLEXT_glDeleteFramebuffers(1, &destFrameBuffer));
return;
}
#endif // SFML_OPENGL_ES
update(texture.copyToImage(), x, y);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Texture::update(const Image& image) void Texture::update(const Image& image)
{ {
@ -695,20 +799,30 @@ Texture& Texture::operator =(const Texture& right)
{ {
Texture temp(right); Texture temp(right);
std::swap(m_size, temp.m_size); swap(temp);
std::swap(m_actualSize, temp.m_actualSize);
std::swap(m_texture, temp.m_texture);
std::swap(m_isSmooth, temp.m_isSmooth);
std::swap(m_isRepeated, temp.m_isRepeated);
std::swap(m_pixelsFlipped, temp.m_pixelsFlipped);
std::swap(m_fboAttachment, temp.m_fboAttachment);
std::swap(m_hasMipmap, temp.m_hasMipmap);
m_cacheId = getUniqueId();
return *this; return *this;
} }
////////////////////////////////////////////////////////////
void Texture::swap(Texture& right)
{
std::swap(m_size, right.m_size);
std::swap(m_actualSize, right.m_actualSize);
std::swap(m_texture, right.m_texture);
std::swap(m_isSmooth, right.m_isSmooth);
std::swap(m_sRgb, right.m_sRgb);
std::swap(m_isRepeated, right.m_isRepeated);
std::swap(m_pixelsFlipped, right.m_pixelsFlipped);
std::swap(m_fboAttachment, right.m_fboAttachment);
std::swap(m_hasMipmap, right.m_hasMipmap);
m_cacheId = getUniqueId();
right.m_cacheId = getUniqueId();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int Texture::getNativeHandle() const unsigned int Texture::getNativeHandle() const
{ {