///////////////////////////////////////////////////////
| 376 | |
| 377 | //////////////////////////////////////////////////////////// |
| 378 | bool Texture::loadFromImage(const Image& image, bool sRgb, const IntRect& area) |
| 379 | { |
| 380 | // Retrieve the image size |
| 381 | const auto size = Vector2i(image.getSize()); |
| 382 | |
| 383 | // Load the entire image if the source area is either empty or contains the whole image |
| 384 | if (area.size.x == 0 || (area.size.y == 0) || |
| 385 | ((area.position.x <= 0) && (area.position.y <= 0) && (area.size.x >= size.x) && (area.size.y >= size.y))) |
| 386 | { |
| 387 | // Load the entire image |
| 388 | if (resize(image.getSize(), sRgb)) |
| 389 | { |
| 390 | update(image); |
| 391 | return true; |
| 392 | } |
| 393 | |
| 394 | // Error message generated in called function. |
| 395 | return false; |
| 396 | } |
| 397 | |
| 398 | // Load a sub-area of the image |
| 399 | assert(area.size.x > 0 && "Area size x cannot be negative"); |
| 400 | assert(area.size.y > 0 && "Area size y cannot be negative"); |
| 401 | assert(area.position.x < size.x && "Area position x is out of image bounds"); |
| 402 | assert(area.position.y < size.y && "Area position y is out of image bounds"); |
| 403 | |
| 404 | // Adjust the rectangle to the size of the image |
| 405 | IntRect rectangle = area; |
| 406 | rectangle.position.x = std::max(rectangle.position.x, 0); |
| 407 | rectangle.position.y = std::max(rectangle.position.y, 0); |
| 408 | rectangle.size.x = std::min(rectangle.size.x, size.x - rectangle.position.x); |
| 409 | rectangle.size.y = std::min(rectangle.size.y, size.y - rectangle.position.y); |
| 410 | |
| 411 | // Create the texture and upload the pixels |
| 412 | if (resize(Vector2u(rectangle.size), sRgb)) |
| 413 | { |
| 414 | const TransientContextLock lock; |
| 415 | |
| 416 | // Make sure that the current texture binding will be preserved |
| 417 | const priv::TextureSaver save; |
| 418 | |
| 419 | // Copy the pixels to the texture, row by row |
| 420 | const std::uint8_t* pixels = image.getPixelsPtr() + 4 * (rectangle.position.x + (size.x * rectangle.position.y)); |
| 421 | glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); |
| 422 | for (int i = 0; i < rectangle.size.y; ++i) |
| 423 | { |
| 424 | glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.size.x, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); |
| 425 | pixels += 4 * size.x; |
| 426 | } |
| 427 | |
| 428 | glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); |
| 429 | m_hasMipmap = false; |
| 430 | |
| 431 | // Force an OpenGL flush, so that the texture will appear updated |
| 432 | // in all contexts immediately (solves problems in multi-threaded apps) |
| 433 | glCheck(glFlush()); |
| 434 | |
| 435 | return true; |
no test coverage detected