///////////////////////////////////////////////////////
| 449 | |
| 450 | //////////////////////////////////////////////////////////// |
| 451 | Image Texture::copyToImage() const |
| 452 | { |
| 453 | // Easy case: empty texture |
| 454 | if (!m_texture) |
| 455 | return {}; |
| 456 | |
| 457 | const TransientContextLock lock; |
| 458 | |
| 459 | // Make sure that the current texture binding will be preserved |
| 460 | const priv::TextureSaver save; |
| 461 | |
| 462 | // Create an array of pixels |
| 463 | std::vector<std::uint8_t> pixels(m_size.x * m_size.y * 4); |
| 464 | |
| 465 | #ifdef SFML_OPENGL_ES |
| 466 | |
| 467 | // OpenGL ES doesn't have the glGetTexImage function, the only way to read |
| 468 | // from a texture is to bind it to a FBO and use glReadPixels |
| 469 | GLuint frameBuffer = 0; |
| 470 | glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer)); |
| 471 | if (frameBuffer) |
| 472 | { |
| 473 | GLint previousFrameBuffer = 0; |
| 474 | glCheck(glGetIntegerv(GLEXT_GL_FRAMEBUFFER_BINDING, &previousFrameBuffer)); |
| 475 | |
| 476 | glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, frameBuffer)); |
| 477 | glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0)); |
| 478 | glCheck(glReadPixels(0, |
| 479 | 0, |
| 480 | static_cast<GLsizei>(m_size.x), |
| 481 | static_cast<GLsizei>(m_size.y), |
| 482 | GL_RGBA, |
| 483 | GL_UNSIGNED_BYTE, |
| 484 | pixels.data())); |
| 485 | glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer)); |
| 486 | |
| 487 | glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, static_cast<GLuint>(previousFrameBuffer))); |
| 488 | |
| 489 | if (m_pixelsFlipped) |
| 490 | { |
| 491 | // Flip the texture vertically |
| 492 | const auto stride = static_cast<std::ptrdiff_t>(m_size.x * 4); |
| 493 | auto currentRowIterator = pixels.begin(); |
| 494 | auto nextRowIterator = pixels.begin() + stride; |
| 495 | auto reverseRowIterator = pixels.begin() + (stride * static_cast<std::ptrdiff_t>(m_size.y - 1)); |
| 496 | for (unsigned int i = 0; i < m_size.y / 2; ++i) |
| 497 | { |
| 498 | std::swap_ranges(currentRowIterator, nextRowIterator, reverseRowIterator); |
| 499 | currentRowIterator = nextRowIterator; |
| 500 | nextRowIterator += stride; |
| 501 | reverseRowIterator -= stride; |
| 502 | } |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | #else |
| 507 | |
| 508 | if ((m_size == m_actualSize) && !m_pixelsFlipped) |
no test coverage detected