| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #include "AlbumTexture.h"
- #include "RenderContext.h"
- #include "WallpaperEngine/Assets/AssetLoadException.h"
- #include "WallpaperEngine/Data/Utils/ScopeGuard.h"
- #include "WallpaperEngine/Media/MediaSource.h"
- #include "stb_image.h"
- using namespace WallpaperEngine::Render;
- int albumtexture_read (void* user, char* data, int size) {
- auto* stream = static_cast<ReadStream*> (user);
- stream->read (data, size);
- return stream->gcount ();
- }
- void albumtexture_skip (void* user, int n) {
- auto* stream = static_cast<ReadStream*> (user);
- stream->seekg (n, std::ios::cur);
- }
- int albumtexture_eof (void* user) { return static_cast<ReadStream*> (user)->eof (); }
- stbi_io_callbacks album_texture_callbacks
- = { .read = albumtexture_read, .skip = albumtexture_skip, .eof = albumtexture_eof };
- AlbumTexture::AlbumTexture (RenderContext& context) : Helpers::ContextAware (context) {
- this->m_resolution = glm::vec4 (1.0f, 1.0f, 1.0f, 1.0f);
- glGenTextures (1, &this->m_textureID);
- glBindTexture (GL_TEXTURE_2D, this->m_textureID);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 8.0f);
- }
- AlbumTexture::~AlbumTexture () { glDeleteTextures (1, &this->m_textureID); }
- GLuint AlbumTexture::getTextureID (uint32_t imageIndex) const { return this->m_textureID; }
- uint32_t AlbumTexture::getTextureWidth (uint32_t imageIndex) const { return this->m_width; }
- uint32_t AlbumTexture::getTextureHeight (uint32_t imageIndex) const { return this->m_height; }
- uint32_t AlbumTexture::getRealWidth () const { return this->m_width; }
- uint32_t AlbumTexture::getRealHeight () const { return this->m_height; }
- TextureFormat AlbumTexture::getFormat () const { return TextureFormat_ARGB8888; }
- uint32_t AlbumTexture::getFlags () const { return TextureFlags_NoFlags; }
- const std::vector<FrameSharedPtr>& AlbumTexture::getFrames () const { return this->m_frames; }
- const glm::vec4* AlbumTexture::getResolution () const { return &this->m_resolution; }
- bool AlbumTexture::isAnimated () const { return false; }
- uint32_t AlbumTexture::getSpritesheetCols () const { return 1; }
- uint32_t AlbumTexture::getSpritesheetRows () const { return 1; }
- uint32_t AlbumTexture::getSpritesheetFrames () const { return 1; }
- float AlbumTexture::getSpritesheetDuration () const { return 0.0f; }
- void AlbumTexture::incrementUsageCount () const { }
- void AlbumTexture::decrementUsageCount () const { }
- void AlbumTexture::update () const { }
- void AlbumTexture::copyContents (const TextureProvider& other) const noexcept {
- // gpu -> cpu -> gpu fallback copy; RGBA8 texture, 4 bytes per pixel
- size_t bufferSize = other.getTextureWidth (0) * other.getTextureHeight (0) * 4;
- uint8_t* buffer = new uint8_t[bufferSize];
- glBindTexture (GL_TEXTURE_2D, other.getTextureID (0));
- glGetnTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bufferSize, buffer);
- glBindTexture (GL_TEXTURE_2D, this->m_textureID);
- glTexImage2D (
- GL_TEXTURE_2D, 0, GL_RGBA8, other.getTextureWidth (0), other.getTextureHeight (0), 0, GL_RGBA, GL_UNSIGNED_BYTE,
- buffer
- );
- delete[] buffer;
- this->m_width = other.getTextureWidth (0);
- this->m_height = other.getTextureHeight (0);
- this->m_resolution = *other.getResolution ();
- }
- void AlbumTexture::load () const {
- this->m_width = 0;
- this->m_height = 0;
- for (const auto& project : this->getContext ().getApp ().getBackgrounds () | std::views::values) {
- try {
- auto contents = project->assetLocator->read ("$mediaThumbnail");
- int width, height, channels;
- auto* dataptr
- = stbi_load_from_callbacks (&album_texture_callbacks, contents.get (), &width, &height, &channels, 4);
- if (dataptr == nullptr) {
- continue;
- }
- ScopeGuard guard ([dataptr] { stbi_image_free (dataptr); });
- if (width == 0 || height == 0) {
- continue;
- }
- this->m_width = width;
- this->m_height = height;
- this->m_resolution = glm::vec4 (this->m_width, this->m_height, this->m_width, this->m_height);
- glBindTexture (GL_TEXTURE_2D, this->m_textureID);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dataptr);
- return;
- } catch (AssetLoadException&) {
- // this is expected if the thumbnail is not available
- }
- }
- }
- bool AlbumTexture::isReady () const {
- return this->m_width > 0 && this->m_height > 0;
- }
|