AlbumTexture.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "AlbumTexture.h"
  2. #include "RenderContext.h"
  3. #include "WallpaperEngine/Assets/AssetLoadException.h"
  4. #include "WallpaperEngine/Data/Utils/ScopeGuard.h"
  5. #include "WallpaperEngine/Media/MediaSource.h"
  6. #include "stb_image.h"
  7. using namespace WallpaperEngine::Render;
  8. int albumtexture_read (void* user, char* data, int size) {
  9. auto* stream = static_cast<ReadStream*> (user);
  10. stream->read (data, size);
  11. return stream->gcount ();
  12. }
  13. void albumtexture_skip (void* user, int n) {
  14. auto* stream = static_cast<ReadStream*> (user);
  15. stream->seekg (n, std::ios::cur);
  16. }
  17. int albumtexture_eof (void* user) { return static_cast<ReadStream*> (user)->eof (); }
  18. stbi_io_callbacks album_texture_callbacks
  19. = { .read = albumtexture_read, .skip = albumtexture_skip, .eof = albumtexture_eof };
  20. AlbumTexture::AlbumTexture (RenderContext& context) : Helpers::ContextAware (context) {
  21. this->m_resolution = glm::vec4 (1.0f, 1.0f, 1.0f, 1.0f);
  22. glGenTextures (1, &this->m_textureID);
  23. glBindTexture (GL_TEXTURE_2D, this->m_textureID);
  24. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  25. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  26. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  27. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  28. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  29. glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  30. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f);
  31. }
  32. AlbumTexture::~AlbumTexture () { glDeleteTextures (1, &this->m_textureID); }
  33. GLuint AlbumTexture::getTextureID (uint32_t imageIndex) const { return this->m_textureID; }
  34. uint32_t AlbumTexture::getTextureWidth (uint32_t imageIndex) const { return this->m_width; }
  35. uint32_t AlbumTexture::getTextureHeight (uint32_t imageIndex) const { return this->m_height; }
  36. uint32_t AlbumTexture::getRealWidth () const { return this->m_width; }
  37. uint32_t AlbumTexture::getRealHeight () const { return this->m_height; }
  38. TextureFormat AlbumTexture::getFormat () const { return TextureFormat_ARGB8888; }
  39. uint32_t AlbumTexture::getFlags () const { return TextureFlags_NoFlags; }
  40. const std::vector<FrameSharedPtr>& AlbumTexture::getFrames () const { return this->m_frames; }
  41. const glm::vec4* AlbumTexture::getResolution () const { return &this->m_resolution; }
  42. bool AlbumTexture::isAnimated () const { return false; }
  43. uint32_t AlbumTexture::getSpritesheetCols () const { return 1; }
  44. uint32_t AlbumTexture::getSpritesheetRows () const { return 1; }
  45. uint32_t AlbumTexture::getSpritesheetFrames () const { return 1; }
  46. float AlbumTexture::getSpritesheetDuration () const { return 0.0f; }
  47. void AlbumTexture::incrementUsageCount () const { }
  48. void AlbumTexture::decrementUsageCount () const { }
  49. void AlbumTexture::update () const { }
  50. void AlbumTexture::copyContents (const TextureProvider& other) const noexcept {
  51. // gpu -> cpu -> gpu fallback copy; RGBA8 texture, 4 bytes per pixel
  52. size_t bufferSize = other.getTextureWidth (0) * other.getTextureHeight (0) * 4;
  53. uint8_t* buffer = new uint8_t[bufferSize];
  54. glBindTexture (GL_TEXTURE_2D, other.getTextureID (0));
  55. glGetnTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bufferSize, buffer);
  56. glBindTexture (GL_TEXTURE_2D, this->m_textureID);
  57. glTexImage2D (
  58. GL_TEXTURE_2D, 0, GL_RGBA8, other.getTextureWidth (0), other.getTextureHeight (0), 0, GL_RGBA, GL_UNSIGNED_BYTE,
  59. buffer
  60. );
  61. delete[] buffer;
  62. this->m_width = other.getTextureWidth (0);
  63. this->m_height = other.getTextureHeight (0);
  64. this->m_resolution = *other.getResolution ();
  65. }
  66. void AlbumTexture::load () const {
  67. this->m_width = 0;
  68. this->m_height = 0;
  69. for (const auto& project : this->getContext ().getApp ().getBackgrounds () | std::views::values) {
  70. try {
  71. auto contents = project->assetLocator->read ("$mediaThumbnail");
  72. int width, height, channels;
  73. auto* dataptr
  74. = stbi_load_from_callbacks (&album_texture_callbacks, contents.get (), &width, &height, &channels, 4);
  75. if (dataptr == nullptr) {
  76. continue;
  77. }
  78. ScopeGuard guard ([dataptr] { stbi_image_free (dataptr); });
  79. if (width == 0 || height == 0) {
  80. continue;
  81. }
  82. this->m_width = width;
  83. this->m_height = height;
  84. this->m_resolution = glm::vec4 (this->m_width, this->m_height, this->m_width, this->m_height);
  85. glBindTexture (GL_TEXTURE_2D, this->m_textureID);
  86. glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dataptr);
  87. return;
  88. } catch (AssetLoadException&) {
  89. // this is expected if the thumbnail is not available
  90. }
  91. }
  92. }
  93. bool AlbumTexture::isReady () const {
  94. return this->m_width > 0 && this->m_height > 0;
  95. }