| 130 | } |
| 131 | |
| 132 | void GameListModel::loadOrGenerateCover(const GameList::Entry* ge) |
| 133 | { |
| 134 | // Why this counter: Every time we change the cover scale, we increment the counter variable. This way if the scale is changed |
| 135 | // while there's outstanding jobs, the old jobs won't proceed (at the wrong size), or get added into the grid. |
| 136 | const u32 counter = m_cover_scale_counter.load(std::memory_order_acquire); |
| 137 | |
| 138 | QFuture<QPixmap> future = QtConcurrent::run([this, entry = *ge, counter]() -> QPixmap { |
| 139 | QPixmap image; |
| 140 | |
| 141 | // Initial check that the scale is unchanged before we run costly image generation. |
| 142 | if (m_cover_scale_counter.load(std::memory_order_acquire) == counter) |
| 143 | { |
| 144 | const std::string cover_path(GameList::GetCoverImagePathForEntry(&entry)); |
| 145 | if (!cover_path.empty()) |
| 146 | image = QPixmap(QString::fromStdString(cover_path)); |
| 147 | |
| 148 | // Create placeholder image if no user-provided cover exists. |
| 149 | if (image.isNull()) |
| 150 | { |
| 151 | const std::string& title = entry.GetTitle(m_prefer_english_titles); |
| 152 | image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, m_dpr, title); |
| 153 | } |
| 154 | // Create resized image from user-provided cover. |
| 155 | else |
| 156 | { |
| 157 | image.setDevicePixelRatio(m_dpr); |
| 158 | QtUtils::resizeAndScalePixmap(&image, getCoverArtWidth(), getCoverArtHeight(), m_dpr, QtUtils::ScalingMode::Fit, 100); |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | // Final check that scale is unchanged before we send out the produced image. |
| 163 | return m_cover_scale_counter.load(std::memory_order_acquire) == counter ? image : QPixmap(); |
| 164 | }); |
| 165 | |
| 166 | // Context must be 'this' so we run on the UI thread. |
| 167 | future.then(this, [this, path = ge->path, counter](QPixmap pm) { |
| 168 | if (m_cover_scale_counter.load(std::memory_order_acquire) != counter) |
| 169 | return; |
| 170 | |
| 171 | m_cover_pixmap_cache.Insert(std::move(path), std::move(pm)); |
| 172 | invalidateCoverForPath(path); |
| 173 | }); |
| 174 | } |
| 175 | |
| 176 | void GameListModel::invalidateCoverForPath(const std::string& path) |
| 177 | { |
no test coverage detected