Apply the style guide
This commit is contained in:
+2
-2
@@ -150,8 +150,8 @@ std::span<const Action> window_keys();
|
||||
std::span<const Action> browser_keys();
|
||||
std::span<const Action> viewer_keys();
|
||||
|
||||
void copy_files(QMimeData *mime, std::span<const QUrl> urls, bool cut = false);
|
||||
void copy_files(std::span<const QUrl> urls, bool cut = false);
|
||||
void copy_files(QMimeData *mime, std::span<const QUrl> urls, bool cut);
|
||||
void copy_files(std::span<const QUrl> urls, bool cut);
|
||||
bool move_to_trash(const QString &abs_path);
|
||||
|
||||
} // namespace dn
|
||||
|
||||
@@ -163,7 +163,7 @@ sync_hidden(NSMenu *main, id delegate, span<const dn::MenuNode> tree)
|
||||
|
||||
- (BOOL)performKeyEquivalent:(NSEvent *)event
|
||||
{
|
||||
(void)event;
|
||||
(void) event;
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -334,8 +334,8 @@ adopt_app_menu(id target)
|
||||
if ([loader respondsToSelector:@selector(aboutMenuItem)])
|
||||
claim_item([loader aboutMenuItem], Action::About, target, @"", 0);
|
||||
if ([loader respondsToSelector:@selector(preferencesMenuItem)])
|
||||
claim_item([loader preferencesMenuItem], Action::Settings, target,
|
||||
@",", NSEventModifierFlagCommand);
|
||||
claim_item([loader preferencesMenuItem], Action::Settings, target, @",",
|
||||
NSEventModifierFlagCommand);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+3
-4
@@ -305,8 +305,7 @@ void
|
||||
Settings::toggle_bookmark(const string &path)
|
||||
{
|
||||
const string want = canonical_dir(path);
|
||||
const auto it =
|
||||
find(this->bookmarks.begin(), this->bookmarks.end(), want);
|
||||
const auto it = find(this->bookmarks.begin(), this->bookmarks.end(), want);
|
||||
if (it != this->bookmarks.end())
|
||||
this->bookmarks.erase(it);
|
||||
else
|
||||
@@ -350,7 +349,7 @@ App::event(QEvent *event)
|
||||
return true;
|
||||
}
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
open(url_normalized(((QFileOpenEvent *) event)->url()));
|
||||
open(url_normalized(((QFileOpenEvent *) event)->url()), {}, {}, false);
|
||||
return true;
|
||||
}
|
||||
return QGuiApplication::event(event);
|
||||
@@ -473,7 +472,7 @@ App::open(const QUrl &url, const QString &activation_token, BrowseSetup setup,
|
||||
}
|
||||
#endif
|
||||
|
||||
auto window = make_unique<Window>(this);
|
||||
auto window = make_unique<Window>(this, nullptr);
|
||||
if (!window->initialize(resolved, setup, browse))
|
||||
return OpenResult::Internal;
|
||||
apply_activation_token(activation_token);
|
||||
|
||||
+6
-3
@@ -84,7 +84,10 @@ protected:
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
public:
|
||||
App(int &argc, char **argv) : QGuiApplication(argc, argv) {}
|
||||
App(int &argc, char **argv)
|
||||
: QGuiApplication(argc, argv), thumbnailer(nullptr, 0)
|
||||
{
|
||||
}
|
||||
|
||||
QVulkanInstance vulkan_instance;
|
||||
GpuContext gpu;
|
||||
@@ -96,8 +99,8 @@ public:
|
||||
bool needs_csd = false;
|
||||
|
||||
bool init();
|
||||
OpenResult open(const QUrl &url, const QString &activation_token = {},
|
||||
BrowseSetup setup = {}, bool browse = false);
|
||||
OpenResult open(const QUrl &url, const QString &activation_token,
|
||||
BrowseSetup setup, bool browse);
|
||||
void close(const QWindow *top);
|
||||
void close_later(const QWindow *top);
|
||||
// Not quit(): that name is taken by a static QCoreApplication slot,
|
||||
|
||||
+6
-6
@@ -125,7 +125,7 @@ recommended_for(const QString &path)
|
||||
const Handler def = default_for(path);
|
||||
vector<Handler> out;
|
||||
const CFIndex n = CFArrayGetCount(handlers);
|
||||
for (CFIndex i = 0; i < n; ++i) {
|
||||
for (CFIndex i = 0; i < n; i++) {
|
||||
NSString *bid =
|
||||
(__bridge NSString *) CFArrayGetValueAtIndex(handlers, i);
|
||||
NSURL *app_url = app_url_for_bundle_id(bid);
|
||||
@@ -172,11 +172,11 @@ launch(const Handler &app, const QString &path)
|
||||
|
||||
// The launch is asynchronous, so failures can only be reported later,
|
||||
// and the caller has nothing to do with them anyway.
|
||||
[[NSWorkspace sharedWorkspace] openURLs:@[ file ]
|
||||
withApplicationAtURL:app_url
|
||||
configuration:[NSWorkspaceOpenConfiguration
|
||||
configuration]
|
||||
completionHandler:nil];
|
||||
[[NSWorkspace sharedWorkspace]
|
||||
openURLs:@[ file ]
|
||||
withApplicationAtURL:app_url
|
||||
configuration:[NSWorkspaceOpenConfiguration configuration]
|
||||
completionHandler:nil];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+25
-26
@@ -218,19 +218,19 @@ apply_mimeapps(AssocSets &acc, const IniFile &ini, const QString &type)
|
||||
const string type_utf8 = type.toUtf8().toStdString();
|
||||
for (const IniGroup &group : ini.groups) {
|
||||
if (group.name == "Default Applications") {
|
||||
for (const QString &id : split_semicolons(
|
||||
dawn::detail::ini_get(group, type_utf8)))
|
||||
for (const QString &id :
|
||||
split_semicolons(dawn::detail::ini_get(group, type_utf8)))
|
||||
append_unique(acc.defaults, normalize_desktop_id(id));
|
||||
} else if (group.name == "Added Associations") {
|
||||
for (const QString &id : split_semicolons(
|
||||
dawn::detail::ini_get(group, type_utf8))) {
|
||||
for (const QString &id :
|
||||
split_semicolons(dawn::detail::ini_get(group, type_utf8))) {
|
||||
const QString nid = normalize_desktop_id(id);
|
||||
if (!acc.removed.contains(nid))
|
||||
append_unique(acc.added, nid);
|
||||
}
|
||||
} else if (group.name == "Removed Associations") {
|
||||
for (const QString &id : split_semicolons(
|
||||
dawn::detail::ini_get(group, type_utf8))) {
|
||||
for (const QString &id :
|
||||
split_semicolons(dawn::detail::ini_get(group, type_utf8))) {
|
||||
const QString nid = normalize_desktop_id(id);
|
||||
if (find(acc.added.begin(), acc.added.end(), nid) ==
|
||||
acc.added.end())
|
||||
@@ -268,8 +268,8 @@ cache_ids_for_type(const QString &type)
|
||||
for (const IniGroup &group : ini.groups) {
|
||||
if (group.name != "MIME Cache")
|
||||
continue;
|
||||
for (const QString &id : split_semicolons(
|
||||
dawn::detail::ini_get(group, type_utf8)))
|
||||
for (const QString &id :
|
||||
split_semicolons(dawn::detail::ini_get(group, type_utf8)))
|
||||
append_unique(ids, normalize_desktop_id(id));
|
||||
}
|
||||
}
|
||||
@@ -283,7 +283,7 @@ desktop_path_for_name(const QString &dir, QString name, int from)
|
||||
if (QFileInfo::exists(path))
|
||||
return path;
|
||||
|
||||
for (int i = from; i < name.size(); ++i) {
|
||||
for (int i = from; i < name.size(); i++) {
|
||||
if (name[i] != u'-')
|
||||
continue;
|
||||
|
||||
@@ -345,10 +345,10 @@ localized_value(const IniGroup &entry, const QString &key)
|
||||
}
|
||||
if (!item_key.startsWith(prefix) || !item_key.endsWith(u']'))
|
||||
continue;
|
||||
const QString loc = item_key.mid(
|
||||
prefix.size(), item_key.size() - prefix.size() - 1);
|
||||
localized.insert({loc, QString::fromStdString(
|
||||
dawn::detail::desktop_unescape(kv.second))});
|
||||
const QString loc =
|
||||
item_key.mid(prefix.size(), item_key.size() - prefix.size() - 1);
|
||||
localized.insert({loc,
|
||||
QString::fromStdString(dawn::detail::desktop_unescape(kv.second))});
|
||||
}
|
||||
for (const QString &loc : locale_candidates()) {
|
||||
const auto it = localized.find(loc);
|
||||
@@ -434,15 +434,14 @@ load_desktop(const QString &id)
|
||||
if (!entry)
|
||||
return d;
|
||||
|
||||
const QString type = QString::fromStdString(
|
||||
dawn::detail::ini_get(*entry, "Type"))
|
||||
.trimmed();
|
||||
const QString type =
|
||||
QString::fromStdString(dawn::detail::ini_get(*entry, "Type")).trimmed();
|
||||
d.application = type.isEmpty() || type == QLatin1String("Application");
|
||||
d.name = localized_name(*entry);
|
||||
d.icon = QString::fromStdString(dawn::detail::desktop_unescape(
|
||||
dawn::detail::ini_get(*entry, "Icon")));
|
||||
d.exec = QString::fromStdString(dawn::detail::desktop_unescape(
|
||||
dawn::detail::ini_get(*entry, "Exec")));
|
||||
d.icon = QString::fromStdString(
|
||||
dawn::detail::desktop_unescape(dawn::detail::ini_get(*entry, "Icon")));
|
||||
d.exec = QString::fromStdString(
|
||||
dawn::detail::desktop_unescape(dawn::detail::ini_get(*entry, "Exec")));
|
||||
d.try_exec = QString::fromStdString(dawn::detail::desktop_unescape(
|
||||
dawn::detail::ini_get(*entry, "TryExec")));
|
||||
d.hidden = parse_bool(dawn::detail::ini_get(*entry, "Hidden"));
|
||||
@@ -535,7 +534,7 @@ split_exec(const QString &exec)
|
||||
vector<QString> args;
|
||||
QString cur;
|
||||
bool in_quote = false;
|
||||
for (int i = 0; i < exec.size(); ++i) {
|
||||
for (int i = 0; i < exec.size(); i++) {
|
||||
const QChar c = exec[i];
|
||||
if (in_quote) {
|
||||
if (c == u'\\' && i + 1 < exec.size()) {
|
||||
@@ -590,7 +589,7 @@ expand_exec(const Desktop &d, const QString &path)
|
||||
continue;
|
||||
}
|
||||
QString built;
|
||||
for (int i = 0; i < arg.size(); ++i) {
|
||||
for (int i = 0; i < arg.size(); i++) {
|
||||
if (arg[i] != u'%' || i + 1 >= arg.size()) {
|
||||
built += arg[i];
|
||||
continue;
|
||||
@@ -797,10 +796,10 @@ set_last_used(const Handler &app, const QString &path)
|
||||
}
|
||||
};
|
||||
const string type_utf8 = type.toUtf8().toStdString();
|
||||
const QString previous = QString::fromStdString(
|
||||
dawn::detail::ini_get(*added, type_utf8));
|
||||
dawn::detail::ini_set(*added, type_utf8,
|
||||
prepend_id(previous, id).toUtf8().toStdString());
|
||||
const QString previous =
|
||||
QString::fromStdString(dawn::detail::ini_get(*added, type_utf8));
|
||||
dawn::detail::ini_set(
|
||||
*added, type_utf8, prepend_id(previous, id).toUtf8().toStdString());
|
||||
if (removed)
|
||||
drop_id(*removed, type);
|
||||
write_text_file(dest, dawn::detail::ini_serialize(ini));
|
||||
|
||||
@@ -107,7 +107,7 @@ load_from_client(CdClient *client, const QScreen *screen)
|
||||
|
||||
CdDevice *matched = nullptr;
|
||||
string method;
|
||||
for (guint i = 0; i < devices->len; ++i) {
|
||||
for (guint i = 0; i < devices->len; i++) {
|
||||
auto *device = static_cast<CdDevice *>(g_ptr_array_index(devices, i));
|
||||
if (!cd_device_connect_sync(device, nullptr, &error)) {
|
||||
g_clear_error(&error);
|
||||
@@ -123,7 +123,7 @@ load_from_client(CdClient *client, const QScreen *screen)
|
||||
}
|
||||
if (!matched) {
|
||||
if (auto edid_md5 = edid_md5_for_connector(connector)) {
|
||||
for (guint i = 0; i < devices->len; ++i) {
|
||||
for (guint i = 0; i < devices->len; i++) {
|
||||
auto *device =
|
||||
static_cast<CdDevice *>(g_ptr_array_index(devices, i));
|
||||
const char *md5 = cd_device_get_metadata_item(
|
||||
|
||||
@@ -47,7 +47,7 @@ load_display_profile(QScreen *screen)
|
||||
return result;
|
||||
|
||||
MONITORINFOEXW monitor{};
|
||||
monitor.cbSize = sizeof(monitor);
|
||||
monitor.cbSize = sizeof monitor;
|
||||
if (!GetMonitorInfoW(native->handle(), &monitor))
|
||||
return result;
|
||||
HDC dc = CreateDCW(L"DISPLAY", monitor.szDevice, nullptr, nullptr);
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ class InstanceHost : public QObject
|
||||
public:
|
||||
// Takes over the bound listener. Forwards Open requests to app.open.
|
||||
InstanceHost(dawn::ipc::Listener listener, App &app, QString session,
|
||||
QObject *parent = nullptr);
|
||||
QObject *parent);
|
||||
~InstanceHost() override;
|
||||
|
||||
private:
|
||||
|
||||
+31
-30
@@ -270,7 +270,7 @@ url_of(const string &path)
|
||||
static int
|
||||
thumb_size_index(int size)
|
||||
{
|
||||
for (int i = 0; i < kThumbSizeN; ++i) {
|
||||
for (int i = 0; i < kThumbSizeN; i++) {
|
||||
if (kThumbSizes[i] == size)
|
||||
return i;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ profile_from_icc(dawn::Cmm &cmm, const shared_ptr<const vector<uint8_t>> &icc)
|
||||
if (auto profile = cmm.get_profile(*icc))
|
||||
return profile;
|
||||
}
|
||||
return cmm.get_profile_sRGB();
|
||||
return cmm.get_profile_sRGB(false);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -565,7 +565,7 @@ static void
|
||||
copy_bgra16(const dawn::Image &src, uint16_t *dst, uint32_t dw, uint32_t dh)
|
||||
{
|
||||
const size_t packed = size_t(dw) * dawn::kBytesPerPixel;
|
||||
for (uint32_t y = 0; y < dh; ++y)
|
||||
for (uint32_t y = 0; y < dh; y++)
|
||||
memcpy(dst + size_t(y) * dw * 4, dawn::row_u16(src, y), packed);
|
||||
}
|
||||
|
||||
@@ -585,7 +585,7 @@ make_thumb(shared_ptr<dawn::Cmm> cmm, const ThumbJob &job)
|
||||
if (job.pending) {
|
||||
if (const ThumbnailTierPixels *pixels = job.pending->find(tier)) {
|
||||
result.ram = *pixels->pixels;
|
||||
shared_ptr<dawn::Profile> p3 = cmm->get_profile_display_p3();
|
||||
shared_ptr<dawn::Profile> p3 = cmm->get_profile_display_p3(false);
|
||||
if (p3 && screen && !result.ram.empty() &&
|
||||
cmm->transform_bgra16(
|
||||
reinterpret_cast<uint8_t *>(result.ram.data()),
|
||||
@@ -634,7 +634,8 @@ make_thumb(shared_ptr<dawn::Cmm> cmm, const ThumbJob &job)
|
||||
dawn::OpenContext ctx;
|
||||
ctx.uri = job.path;
|
||||
ctx.cmm = cmm;
|
||||
ctx.screen_profile = job.cacheable ? cmm->get_profile_display_p3() : screen;
|
||||
ctx.screen_profile =
|
||||
job.cacheable ? cmm->get_profile_display_p3(false) : screen;
|
||||
ctx.first_frame_only = true;
|
||||
ctx.screen_dpi = 96;
|
||||
|
||||
@@ -722,7 +723,7 @@ display_thumb(Browser *browser, FinishJob job)
|
||||
update.ram_tier = job.tier;
|
||||
|
||||
auto cmm = worker_cmm();
|
||||
shared_ptr<dawn::Profile> p3 = cmm->get_profile_display_p3();
|
||||
shared_ptr<dawn::Profile> p3 = cmm->get_profile_display_p3(false);
|
||||
shared_ptr<dawn::Profile> screen = profile_from_icc(*cmm, job.screen_icc);
|
||||
vector<uint16_t> display = job.pixels ? *job.pixels : vector<uint16_t>{};
|
||||
if (p3 && screen && !display.empty() &&
|
||||
@@ -829,7 +830,7 @@ clear_gpu(Browser &b)
|
||||
static void
|
||||
invalidate_thumbs(Browser &b)
|
||||
{
|
||||
++b.thumb_gen_;
|
||||
b.thumb_gen_++;
|
||||
b.thumbnailer_.set_epoch(b.thumbnail_client_, b.thumb_gen_);
|
||||
b.thumb_inflight_.clear();
|
||||
reset_thumb_atlas(b);
|
||||
@@ -865,7 +866,7 @@ trim_ram(Browser &b)
|
||||
const float pad = row_h(b) * kPrefetchRows;
|
||||
const float mid = b.r.y + b.r.h * 0.5f;
|
||||
vector<int> idx;
|
||||
for (int i = 0; i < int(b.files_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.files_.size()); i++) {
|
||||
const Browser::File &f = b.files_[size_t(i)];
|
||||
if (f.ram.empty() || f.ram_pending || thumb_in_band(b, f, pad))
|
||||
continue;
|
||||
@@ -906,8 +907,8 @@ push_gpu(Browser &b, Browser::File &f, const Sheet::Packed &slot)
|
||||
for (Browser::File &o : b.files_) {
|
||||
if (o.gpu.empty() || o.ram.empty())
|
||||
continue;
|
||||
if (!r->upload_thumb(
|
||||
o.ram.data(), o.ram_w, o.ram_h, o.gpu.x, o.gpu.y, b.sheet_.w))
|
||||
if (!r->upload_thumb(o.ram.data(), o.ram_w, o.ram_h, o.gpu.x, o.gpu.y,
|
||||
b.sheet_.w, nullptr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -954,7 +955,7 @@ repack_atlas(Browser &b, Browser::File &wanted)
|
||||
continue;
|
||||
vector<ThumbUpload> uploads;
|
||||
uploads.reserve(active.size());
|
||||
for (size_t i = 0; i < active.size(); ++i) {
|
||||
for (size_t i = 0; i < active.size(); i++) {
|
||||
Browser::File &f = *active[i];
|
||||
const Sheet::Packed &slot = placements[i];
|
||||
uploads.push_back(
|
||||
@@ -964,7 +965,7 @@ repack_atlas(Browser &b, Browser::File &wanted)
|
||||
return false;
|
||||
for (Browser::File &f : b.files_)
|
||||
f.gpu = {};
|
||||
for (size_t i = 0; i < active.size(); ++i)
|
||||
for (size_t i = 0; i < active.size(); i++)
|
||||
active[i]->gpu = placements[i];
|
||||
b.sheet_ = std::move(fresh);
|
||||
return !wanted.gpu.empty();
|
||||
@@ -1205,7 +1206,7 @@ enqueue_thumbs(Browser &b)
|
||||
const int target_tier = thumbnail_tier_for_height(
|
||||
max(1, int(ceil(double(b.thumb_size_) * double(b.kit_.dpr_)))));
|
||||
vector<int> vis, pre, background;
|
||||
for (int i = 0; i < int(b.files_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.files_.size()); i++) {
|
||||
const Browser::File &f = b.files_[size_t(i)];
|
||||
const bool visible = thumb_in_band(b, f, 0.f);
|
||||
const bool prefetched = !visible && thumb_in_band(b, f, pad);
|
||||
@@ -1324,7 +1325,7 @@ find_cursor_row(const Browser &b)
|
||||
{
|
||||
if (b.cursor_ < 0)
|
||||
return -1;
|
||||
for (int i = 0; i < int(b.rows_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.rows_.size()); i++) {
|
||||
const Browser::GridRow &row = b.rows_[size_t(i)];
|
||||
if (b.cursor_ >= row.first && b.cursor_ < row.first + row.count)
|
||||
return i;
|
||||
@@ -1372,7 +1373,7 @@ static void
|
||||
select_closest(Browser &b, const Browser::GridRow &row, float target_x)
|
||||
{
|
||||
float closest = 1e30f;
|
||||
for (int i = 0; i < row.count; ++i) {
|
||||
for (int i = 0; i < row.count; i++) {
|
||||
const int fi = row.first + i;
|
||||
if (fi < 0 || fi >= int(b.files_.size()))
|
||||
break;
|
||||
@@ -1541,7 +1542,7 @@ layout_grid(Browser &b, Rect area)
|
||||
row_w = 0;
|
||||
};
|
||||
|
||||
for (int i = 0; i < int(b.files_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.files_.size()); i++) {
|
||||
Browser::File &f = b.files_[size_t(i)];
|
||||
// thumb_dest() answers in pixels, which is what the grid wants:
|
||||
// no round trip through points, and nothing to snap back.
|
||||
@@ -1625,8 +1626,8 @@ draw_checkers(Kit &kit, const Rect &tile)
|
||||
kit.draw_fill(tile, bg);
|
||||
const int nx = max(1, (tile.w + kCheck - 1) / kCheck);
|
||||
const int ny = max(1, (tile.h + kCheck - 1) / kCheck);
|
||||
for (int j = 0; j < ny; ++j) {
|
||||
for (int i = 0; i < nx; ++i) {
|
||||
for (int j = 0; j < ny; j++) {
|
||||
for (int i = 0; i < nx; i++) {
|
||||
if (((i + j) & 1) == 0)
|
||||
continue;
|
||||
const int x0 = tile.x + i * kCheck;
|
||||
@@ -1640,7 +1641,7 @@ draw_checkers(Kit &kit, const Rect &tile)
|
||||
static int
|
||||
hit_file(const Browser &b, float x, float y)
|
||||
{
|
||||
for (int i = 0; i < int(b.files_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.files_.size()); i++) {
|
||||
if (b.files_[size_t(i)].tile.contains(x, y))
|
||||
return i;
|
||||
}
|
||||
@@ -1765,7 +1766,7 @@ list_subdirs(const filesystem::path &dir, const BrowseSetup &setup)
|
||||
static int
|
||||
index_of_dir(const vector<string> &dirs, const filesystem::path &self)
|
||||
{
|
||||
for (int i = 0; i < int(dirs.size()); ++i) {
|
||||
for (int i = 0; i < int(dirs.size()); i++) {
|
||||
if (same_path(dirs[size_t(i)], self))
|
||||
return i;
|
||||
}
|
||||
@@ -1980,7 +1981,7 @@ scan_dir(Browser &b)
|
||||
b.files_ = std::move(files);
|
||||
clear_cursor(b);
|
||||
if (!keep.empty()) {
|
||||
for (int i = 0; i < int(b.files_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.files_.size()); i++) {
|
||||
if (b.files_[size_t(i)].path == keep) {
|
||||
b.cursor_ = i;
|
||||
remember_cursor_x(b);
|
||||
@@ -1999,7 +2000,7 @@ scan_dir(Browser &b)
|
||||
// respond to DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE,
|
||||
// and/or maybe just DBT_DEVNODES_CHANGED (trivially reload here).
|
||||
DWORD mask = GetLogicalDrives();
|
||||
for (int i = 0; i < 26; ++i) {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
wchar_t letter = L'A' + i;
|
||||
if (!(mask & (1 << i)))
|
||||
continue;
|
||||
@@ -2103,7 +2104,7 @@ open_directory(
|
||||
}
|
||||
b.dir_url_ = dir;
|
||||
b.size_cache_.clear();
|
||||
++b.thumb_gen_;
|
||||
b.thumb_gen_++;
|
||||
b.thumbnailer_.set_epoch(b.thumbnail_client_, b.thumb_gen_);
|
||||
b.thumb_inflight_.clear();
|
||||
reset_thumb_atlas(b);
|
||||
@@ -2121,7 +2122,7 @@ set_thumb_size(Browser &b, int size)
|
||||
if (size == b.thumb_size_)
|
||||
return;
|
||||
b.thumb_size_ = size;
|
||||
++b.thumb_gen_;
|
||||
b.thumb_gen_++;
|
||||
b.thumbnailer_.set_epoch(b.thumbnail_client_, b.thumb_gen_);
|
||||
b.thumb_inflight_.clear();
|
||||
const int target_tier = thumbnail_tier_for_height(
|
||||
@@ -2366,7 +2367,7 @@ fill_places(Browser &b)
|
||||
b.kit_.forget_tree(list);
|
||||
b.place_items_.clear();
|
||||
list->erase_children();
|
||||
for (int i = 0; i < int(b.side_dirs_.size()); ++i) {
|
||||
for (int i = 0; i < int(b.side_dirs_.size()); i++) {
|
||||
const Browser::DirRow &d = b.side_dirs_[size_t(i)];
|
||||
if (d.path.empty()) {
|
||||
list->add_child(make_unique<Sep>());
|
||||
@@ -2413,7 +2414,7 @@ sync_ui(Browser &b, Page &ui)
|
||||
fill_places(b);
|
||||
else {
|
||||
const size_t n = min(b.place_items_.size(), b.side_dirs_.size());
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (Button *button = b.place_items_[i].button)
|
||||
button->active = b.side_dirs_[i].current;
|
||||
}
|
||||
@@ -2536,7 +2537,7 @@ apply_action(Browser &b, Action action)
|
||||
case Action::Copy:
|
||||
if (b.cursor_ >= 0 && b.cursor_ < int(b.files_.size())) {
|
||||
const QUrl files[] = {b.file_url(b.cursor_)};
|
||||
copy_files(files);
|
||||
copy_files(files, false);
|
||||
}
|
||||
return true;
|
||||
case Action::Trash:
|
||||
@@ -2623,7 +2624,7 @@ Browser::select_file(const QUrl &url)
|
||||
clear_cursor(*this);
|
||||
const string path = url_to_path(url).toStdString();
|
||||
if (!path.empty()) {
|
||||
for (int i = 0; i < int(this->files_.size()); ++i) {
|
||||
for (int i = 0; i < int(this->files_.size()); i++) {
|
||||
if (this->files_[size_t(i)].path == path) {
|
||||
this->cursor_ = i;
|
||||
remember_cursor_x(*this);
|
||||
@@ -2685,7 +2686,7 @@ void
|
||||
Browser::paint(Kit &kit) const
|
||||
{
|
||||
if (kit.renderer_)
|
||||
kit.renderer_->set_view(1.f, 0.f, 0.f, dawn::Orientation::Rotate0);
|
||||
kit.renderer_->set_view(1.f, 0.f, 0.f, dawn::Orientation::Rotate0, 0.f);
|
||||
kit.clip_to(this->r);
|
||||
kit.draw_fill(this->r, kit.colours_[ColourWell]);
|
||||
const int th = kit.px(float(this->thumb_size_));
|
||||
@@ -2694,7 +2695,7 @@ Browser::paint(Kit &kit) const
|
||||
const Colour glow_hot = {ink.r, ink.g, ink.b, ink.a * glow_a};
|
||||
const Colour glow_idle = {ink.r, ink.g, ink.b, ink.a * kGlowAlpha * glow_a};
|
||||
const Colour frame = kit.colours_[ColourFrame];
|
||||
for (int i = 0; i < int(this->files_.size()); ++i) {
|
||||
for (int i = 0; i < int(this->files_.size()); i++) {
|
||||
const File &f = this->files_[size_t(i)];
|
||||
if (!thumb_in_band(*this, f, 0.f))
|
||||
continue;
|
||||
|
||||
+3
-4
@@ -162,7 +162,7 @@ struct Browser : Widget {
|
||||
void init();
|
||||
void destroy();
|
||||
void set_host(float width_pts, float height_pts, float dpr);
|
||||
void open_dir(const QUrl &url, bool record = true);
|
||||
void open_dir(const QUrl &url, bool record);
|
||||
void rescan();
|
||||
bool hist_back();
|
||||
bool hist_forward();
|
||||
@@ -173,9 +173,8 @@ struct Browser : Widget {
|
||||
void file_gone(const QUrl &url);
|
||||
[[nodiscard]] QUrl file_url(int index) const;
|
||||
[[nodiscard]] BrowseSetup browse_setup() const { return this->setup_; }
|
||||
void set_screen_profile(
|
||||
std::shared_ptr<dawn::Cmm> cmm, std::shared_ptr<dawn::Profile> profile,
|
||||
bool force_reload = false);
|
||||
void set_screen_profile(std::shared_ptr<dawn::Cmm> cmm,
|
||||
std::shared_ptr<dawn::Profile> profile, bool force_reload);
|
||||
void present(Page &ui);
|
||||
bool press(Kit &kit, float x, float y, Qt::MouseButton button) override;
|
||||
bool release(Kit &kit, float x, float y, Qt::MouseButton button) override;
|
||||
|
||||
+20
-23
@@ -172,8 +172,8 @@ dialog_action(const QString &text, function<void(Kit &)> on_click)
|
||||
static unique_ptr<Button>
|
||||
dialog_close_action(Dialog &dialog)
|
||||
{
|
||||
return dialog_action(QStringLiteral("_Close"),
|
||||
[&dialog](Kit &kit) { dialog.close(kit); });
|
||||
return dialog_action(
|
||||
QStringLiteral("_Close"), [&dialog](Kit &kit) { dialog.close(kit); });
|
||||
}
|
||||
|
||||
static QString
|
||||
@@ -235,13 +235,12 @@ dialog_about(Kit &kit, Dialog &dialog)
|
||||
col->add_child(
|
||||
dialog_label(QStringLiteral("Colour-managed image browser and viewer."),
|
||||
false, true));
|
||||
dialog.show(
|
||||
kit, std::move(col), 360.f, dialog_close_action(dialog));
|
||||
dialog.show(kit, std::move(col), 360.f, dialog_close_action(dialog));
|
||||
}
|
||||
|
||||
void
|
||||
dialog_location(Kit &kit, Dialog &dialog,
|
||||
function<void(const QString &)> on_open)
|
||||
dialog_location(
|
||||
Kit &kit, Dialog &dialog, function<void(const QString &)> on_open)
|
||||
{
|
||||
auto col = make_unique<Column>();
|
||||
col->gap = 8.f;
|
||||
@@ -346,8 +345,7 @@ dialog_shortcuts(Kit &kit, Dialog &dialog, span<const MenuNode> tree,
|
||||
emit_other(Action::Cancel);
|
||||
if (viewer)
|
||||
emit_other(Action::ZoomLevel);
|
||||
dialog.show(
|
||||
kit, std::move(col), 520.f, dialog_close_action(dialog));
|
||||
dialog.show(kit, std::move(col), 520.f, dialog_close_action(dialog));
|
||||
}
|
||||
|
||||
// --- Settings dialog ---------------------------------------------------------
|
||||
@@ -468,7 +466,7 @@ dialog_settings(Kit &kit, Dialog &dialog, SettingsDraft draft,
|
||||
auto combo = make_unique<Combo>();
|
||||
for (const QString &name : kThumbSizeNames)
|
||||
combo->items.push_back(name);
|
||||
for (int i = 0; i < int(std::size(kThumbSizes)); i++) {
|
||||
for (int i = 0; i < int(size(kThumbSizes)); i++) {
|
||||
if (kThumbSizes[i] == state->thumbnail_size)
|
||||
combo->current = i;
|
||||
}
|
||||
@@ -477,8 +475,8 @@ dialog_settings(Kit &kit, Dialog &dialog, SettingsDraft draft,
|
||||
};
|
||||
col->add_child(settings_row(thumb_label, label_w, std::move(combo)));
|
||||
|
||||
auto names = settings_check("Show _filenames by default",
|
||||
state->show_filenames);
|
||||
auto names =
|
||||
settings_check("Show _filenames by default", state->show_filenames);
|
||||
Checkbox *names_ref = names.get();
|
||||
names->on_click = [state, names_ref](Kit &) {
|
||||
state->show_filenames = names_ref->checked;
|
||||
@@ -494,8 +492,8 @@ dialog_settings(Kit &kit, Dialog &dialog, SettingsDraft draft,
|
||||
};
|
||||
col->add_child(settings_row(icc_label, label_w, std::move(entry)));
|
||||
|
||||
auto dither = settings_check("Disable _dithering on 8-bit swapchains",
|
||||
state->disable_dithering);
|
||||
auto dither = settings_check(
|
||||
"Disable _dithering on 8-bit swapchains", state->disable_dithering);
|
||||
Checkbox *dither_ref = dither.get();
|
||||
dither->on_click = [state, dither_ref](Kit &) {
|
||||
state->disable_dithering = dither_ref->checked;
|
||||
@@ -619,7 +617,7 @@ collect_targets(Widget *w, Rect host, vector<Widget *> &out)
|
||||
if (w->focusable() && visible_rect(w, host).w > 0.f)
|
||||
out.push_back(w);
|
||||
const size_t n = w->child_count();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
collect_targets(w->child(i), host, out);
|
||||
}
|
||||
|
||||
@@ -643,7 +641,7 @@ label_len(int n)
|
||||
int len = 1;
|
||||
int cap = kNChars;
|
||||
while (cap < n && len < 8) {
|
||||
++len;
|
||||
len++;
|
||||
cap *= kNChars;
|
||||
}
|
||||
return len;
|
||||
@@ -757,7 +755,7 @@ Hint::key(Kit &kit, const Key &ev)
|
||||
any = true;
|
||||
if (t.label == next) {
|
||||
exact = &t;
|
||||
++exact_n;
|
||||
exact_n++;
|
||||
}
|
||||
}
|
||||
if (!any)
|
||||
@@ -833,7 +831,7 @@ Hint::collect(Widget *scope)
|
||||
return;
|
||||
|
||||
const Rect well = browser->r;
|
||||
for (int i = 0; i < int(browser->files_.size()); ++i) {
|
||||
for (int i = 0; i < int(browser->files_.size()); i++) {
|
||||
const Browser::File &f = browser->files_[size_t(i)];
|
||||
if (f.tile.empty())
|
||||
continue;
|
||||
@@ -855,7 +853,7 @@ Hint::assign_labels()
|
||||
{
|
||||
const int n = int(this->targets_.size());
|
||||
const int len = label_len(n);
|
||||
for (int i = 0; i < n; ++i)
|
||||
for (int i = 0; i < n; i++)
|
||||
this->targets_[size_t(i)].label = label_at(i, len);
|
||||
}
|
||||
|
||||
@@ -867,8 +865,7 @@ Hint::refresh_rects()
|
||||
for (Target &t : this->targets_) {
|
||||
if (t.widget) {
|
||||
const Rect visible = visible_rect(t.widget, this->page->r);
|
||||
if (!t.widget->focusable() || visible.w <= 0.f ||
|
||||
visible.h <= 0.f)
|
||||
if (!t.widget->focusable() || visible.w <= 0.f || visible.h <= 0.f)
|
||||
continue;
|
||||
t.at = visible;
|
||||
keep.push_back(t);
|
||||
@@ -1121,8 +1118,8 @@ Page::arrange(Kit &kit, Rect alloc)
|
||||
const int sw = kit.px(this->splitter->min_w);
|
||||
// The grab strip straddles the boundary, half on each side.
|
||||
const int sx = (this->sidebar_side == Side::Right
|
||||
? this->well_.x + this->well_.w
|
||||
: this->well_.x) -
|
||||
? this->well_.x + this->well_.w
|
||||
: this->well_.x) -
|
||||
sw / 2;
|
||||
this->splitter->arrange(kit, {sx, body_y, sw, body_h});
|
||||
} else {
|
||||
@@ -1153,7 +1150,7 @@ Page::key(Kit &kit, const Key &ev)
|
||||
}
|
||||
Widget *panes[3];
|
||||
int n = 0, i = 0;
|
||||
for (size_t c = 0; c < child_count(); ++c) {
|
||||
for (size_t c = 0; c < child_count(); c++) {
|
||||
Widget *k = child(c);
|
||||
if (!k || !k->visible ||
|
||||
(k != this->toolbar && k != this->sidebar && k != this->content))
|
||||
|
||||
+2
-2
@@ -73,8 +73,8 @@ struct SettingsDraft {
|
||||
void dialog_about(Kit &kit, Dialog &dialog);
|
||||
void dialog_shortcuts(Kit &kit, Dialog &dialog, std::span<const MenuNode> tree,
|
||||
std::span<const Action> keys);
|
||||
void dialog_location(Kit &kit, Dialog &dialog,
|
||||
std::function<void(const QString &)> on_open);
|
||||
void dialog_location(
|
||||
Kit &kit, Dialog &dialog, std::function<void(const QString &)> on_open);
|
||||
|
||||
// Takes the draft by value: the dialog edits its own copy, and Save is the
|
||||
// only way anything gets back out.
|
||||
|
||||
+11
-11
@@ -82,7 +82,7 @@ locus_path(int w, int h)
|
||||
};
|
||||
QPointF p0 = xy(0);
|
||||
path.moveTo(xy_to_px(p0.x(), p0.y(), w, h));
|
||||
for (int i = 1; i < kCmfN; ++i) {
|
||||
for (int i = 1; i < kCmfN; i++) {
|
||||
QPointF p = xy(i);
|
||||
path.lineTo(xy_to_px(p.x(), p.y(), w, h));
|
||||
}
|
||||
@@ -140,7 +140,7 @@ stroke_poly(
|
||||
return;
|
||||
QPainterPath path;
|
||||
path.moveTo(xy_to_px(c.x[0], c.y[0], w, h));
|
||||
for (int i = 1; i < c.n; ++i)
|
||||
for (int i = 1; i < c.n; i++)
|
||||
path.lineTo(xy_to_px(c.x[i], c.y[i], w, h));
|
||||
path.closeSubpath();
|
||||
p.strokePath(path, pen);
|
||||
@@ -164,11 +164,11 @@ raster_diagram(int w, int h, const dawn::Chromaticities &image,
|
||||
mp.fillPath(locus_path(w, h), Qt::white);
|
||||
}
|
||||
|
||||
for (int py = 0; py < h; ++py) {
|
||||
for (int py = 0; py < h; py++) {
|
||||
auto *dst = (QRgb *) img.scanLine(py);
|
||||
const auto *ms = (const QRgb *) mask.constScanLine(py);
|
||||
const double y = double(kYMax) * (1.0 - (py + 0.5) / h);
|
||||
for (int px = 0; px < w; ++px) {
|
||||
for (int px = 0; px < w; px++) {
|
||||
if (!qAlpha(ms[px]))
|
||||
continue;
|
||||
const double x = double(kXMax) * (px + 0.5) / w;
|
||||
@@ -219,7 +219,7 @@ same_chroma(const dawn::Chromaticities &a, const dawn::Chromaticities &b)
|
||||
return false;
|
||||
if (a.have_white && (a.wx != b.wx || a.wy != b.wy))
|
||||
return false;
|
||||
for (int i = 0; i < a.n; ++i) {
|
||||
for (int i = 0; i < a.n; i++) {
|
||||
if (a.x[i] != b.x[i] || a.y[i] != b.y[i])
|
||||
return false;
|
||||
}
|
||||
@@ -251,8 +251,8 @@ CieDiagram::prepare(Kit &kit)
|
||||
kit.cache_text(kTargetLab, false);
|
||||
|
||||
const int cap = caption_h(kit);
|
||||
const Rect plot = plot_rect(
|
||||
{this->r.x, this->r.y, this->r.w, max(0, this->r.h - cap)});
|
||||
const Rect plot =
|
||||
plot_rect({this->r.x, this->r.y, this->r.w, max(0, this->r.h - cap)});
|
||||
if (plot.w < 8.f || plot.h < 8.f)
|
||||
return;
|
||||
|
||||
@@ -285,8 +285,8 @@ void
|
||||
CieDiagram::paint(Kit &kit) const
|
||||
{
|
||||
const int cap = caption_h(kit);
|
||||
const Rect plot = plot_rect(
|
||||
{this->r.x, this->r.y, this->r.w, max(0, this->r.h - cap)});
|
||||
const Rect plot =
|
||||
plot_rect({this->r.x, this->r.y, this->r.w, max(0, this->r.h - cap)});
|
||||
const int x0 = plot.x > 0 ? plot.x : this->r.x;
|
||||
const int cap_y0 = plot.h >= 8 ? plot.y + plot.h : this->r.y;
|
||||
const int y = cap_y0 + kit.px(kCapGap);
|
||||
@@ -300,8 +300,8 @@ CieDiagram::paint(Kit &kit) const
|
||||
const int cx = x0 + cap_w / 2;
|
||||
const int gap = kit.px(4.f);
|
||||
const int widthS = kit.text_width(kSourceLab, true);
|
||||
kit.emit_text(float(cx - gap - widthS), float(y), kSourceLab, kBlackCol,
|
||||
true);
|
||||
kit.emit_text(
|
||||
float(cx - gap - widthS), float(y), kSourceLab, kBlackCol, true);
|
||||
kit.emit_text(float(cx + gap), float(y), kTargetLab, kWhiteCol, true);
|
||||
}
|
||||
|
||||
|
||||
+34
-39
@@ -194,7 +194,7 @@ static void
|
||||
sync_scale_label(Viewer &v)
|
||||
{
|
||||
char scale_buf[16];
|
||||
snprintf(scale_buf, sizeof(scale_buf), "%.f%%", double(v.scale_ * 100.f));
|
||||
snprintf(scale_buf, sizeof scale_buf, "%.f%%", double(v.scale_ * 100.f));
|
||||
v.scale_text_ = QString::fromUtf8(scale_buf);
|
||||
if (!v.scale_label_)
|
||||
return;
|
||||
@@ -279,7 +279,7 @@ dim_text(uint32_t v)
|
||||
if (!v)
|
||||
return QStringLiteral("-");
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%u", v);
|
||||
snprintf(buf, sizeof buf, "%u", v);
|
||||
return QString::fromUtf8(buf);
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ join_load_text(const vector<string> &warnings, const dawn::Error &error,
|
||||
else if (empty_image && parts.empty())
|
||||
parts.push_back("empty image");
|
||||
string out;
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
for (size_t i = 0; i < parts.size(); i++) {
|
||||
if (i)
|
||||
out += '\n';
|
||||
out += parts[i];
|
||||
@@ -370,14 +370,13 @@ join_load_text(const vector<string> &warnings, const dawn::Error &error,
|
||||
}
|
||||
|
||||
static shared_ptr<dawn::Profile>
|
||||
profile_from_icc(
|
||||
dawn::Cmm &cmm, const shared_ptr<const vector<uint8_t>> &icc)
|
||||
profile_from_icc(dawn::Cmm &cmm, const shared_ptr<const vector<uint8_t>> &icc)
|
||||
{
|
||||
if (icc && !icc->empty()) {
|
||||
if (auto profile = cmm.get_profile(*icc))
|
||||
return profile;
|
||||
}
|
||||
return cmm.get_profile_sRGB();
|
||||
return cmm.get_profile_sRGB(false);
|
||||
}
|
||||
|
||||
static bool apply_action(Viewer &v, Action action);
|
||||
@@ -622,7 +621,7 @@ stop_worker(Viewer &v)
|
||||
{
|
||||
if (!v.worker_)
|
||||
return;
|
||||
++v.load_epoch_;
|
||||
v.load_epoch_++;
|
||||
{
|
||||
lock_guard<mutex> lock(v.worker_->mu);
|
||||
v.worker_->stop = true;
|
||||
@@ -690,8 +689,8 @@ static unique_ptr<Sidebar>
|
||||
make_sidebar(Viewer &v)
|
||||
{
|
||||
// FIXME: This needs proper layouting.
|
||||
const float label_w = v.kit_.text_width(QStringLiteral("Height:"), true)
|
||||
/ v.kit_.dpr_;
|
||||
const float label_w =
|
||||
v.kit_.text_width(QStringLiteral("Height:"), true) / v.kit_.dpr_;
|
||||
|
||||
auto col = make_unique<ScrollColumn>();
|
||||
v.info_ = col.get();
|
||||
@@ -700,8 +699,8 @@ make_sidebar(Viewer &v)
|
||||
col->pad_y = kWinPadX * 2.f;
|
||||
col->grow = true;
|
||||
|
||||
col->add_child(meta_row(QStringLiteral("Name:"), QStringLiteral("-"),
|
||||
label_w, v.name_label_));
|
||||
col->add_child(meta_row(
|
||||
QStringLiteral("Name:"), QStringLiteral("-"), label_w, v.name_label_));
|
||||
col->add_child(meta_row(QStringLiteral("Loader:"), QStringLiteral("-"),
|
||||
label_w, v.loader_label_));
|
||||
col->add_child(meta_row(QStringLiteral("Width:"), QStringLiteral("-"),
|
||||
@@ -794,7 +793,7 @@ sync_ui(Viewer &v, Page &ui)
|
||||
shared_ptr<dawn::Profile> srgb;
|
||||
if (!img.have_primaries) {
|
||||
auto cmm = v.cmm_ ? v.cmm_ : dawn::Cmm::get_default();
|
||||
srgb = cmm->get_profile_sRGB();
|
||||
srgb = cmm->get_profile_sRGB(false);
|
||||
img = profile_chromaticities(srgb.get());
|
||||
image_dashed = true;
|
||||
}
|
||||
@@ -917,25 +916,23 @@ apply_open_result(Viewer &v, OpenLoad result)
|
||||
return;
|
||||
const string current = viewer_local_path(v);
|
||||
if (!v.detached_ && result.key.path != current &&
|
||||
result.key.path != v.previous_path_ &&
|
||||
result.key.path != v.next_path_)
|
||||
result.key.path != v.previous_path_ && result.key.path != v.next_path_)
|
||||
return;
|
||||
auto found = find_if(v.open_cache_.begin(), v.open_cache_.end(),
|
||||
[&](const Viewer::CachedOpen &entry) {
|
||||
return entry.key == result.key;
|
||||
});
|
||||
if (found == v.open_cache_.end()) {
|
||||
v.open_cache_.push_back(
|
||||
{std::move(result.key), std::move(result.image),
|
||||
std::move(result.message)});
|
||||
v.open_cache_.push_back({std::move(result.key), std::move(result.image),
|
||||
std::move(result.message)});
|
||||
found = prev(v.open_cache_.end());
|
||||
} else {
|
||||
found->image = std::move(result.image);
|
||||
found->message = std::move(result.message);
|
||||
}
|
||||
Viewer::CachedOpen *cached = &*found;
|
||||
if (!v.detached_ && cached->key ==
|
||||
Viewer::OpenKey{current, v.enhance_jpeg_})
|
||||
if (!v.detached_ &&
|
||||
cached->key == Viewer::OpenKey{current, v.enhance_jpeg_})
|
||||
apply_open(v, v.open_gen_, cached->image, cached->message);
|
||||
if (v.open_cache_.size() > 3)
|
||||
v.open_cache_.erase(v.open_cache_.begin());
|
||||
@@ -1107,8 +1104,8 @@ make_open_job(const Viewer &v, Viewer::OpenKey key)
|
||||
job.epoch = v.load_epoch_;
|
||||
job.key = std::move(key);
|
||||
job.uri = path_to_url(QString::fromStdString(job.key.path))
|
||||
.toEncoded()
|
||||
.toStdString();
|
||||
.toEncoded()
|
||||
.toStdString();
|
||||
job.dpi = v.kit_.dpi_;
|
||||
job.enable_cms = v.enable_cms_;
|
||||
job.screen_icc = v.enable_cms_ ? v.screen_icc_ : nullptr;
|
||||
@@ -1143,11 +1140,11 @@ start_open(Viewer &v, bool invalidate)
|
||||
if (!v.worker_ || v.url_.isEmpty())
|
||||
return;
|
||||
if (invalidate) {
|
||||
++v.load_epoch_;
|
||||
v.load_epoch_++;
|
||||
v.open_cache_.clear();
|
||||
}
|
||||
++v.open_gen_;
|
||||
++v.scale_gen_;
|
||||
v.open_gen_++;
|
||||
v.scale_gen_++;
|
||||
v.opening_ = true;
|
||||
v.open_done_ = false;
|
||||
v.detached_ = false;
|
||||
@@ -1155,8 +1152,7 @@ start_open(Viewer &v, bool invalidate)
|
||||
v.scale_failed_ = false;
|
||||
const string path = viewer_local_path(v);
|
||||
const Viewer::OpenKey key{path, v.enhance_jpeg_};
|
||||
Viewer::CachedOpen *cached =
|
||||
invalidate ? nullptr : find_cached(v, key);
|
||||
Viewer::CachedOpen *cached = invalidate ? nullptr : find_cached(v, key);
|
||||
{
|
||||
lock_guard lock(v.worker_->mu);
|
||||
v.worker_->epoch = v.load_epoch_;
|
||||
@@ -1251,7 +1247,7 @@ post_scale(Viewer &v)
|
||||
{
|
||||
if (!v.worker_ || !v.current_ || !v.current_->render)
|
||||
return;
|
||||
++v.scale_gen_;
|
||||
v.scale_gen_++;
|
||||
v.scale_job_pending_ = true;
|
||||
v.scale_job_target_ = v.scale_;
|
||||
v.scale_failed_ = false;
|
||||
@@ -1276,7 +1272,7 @@ ensure_vector_frame(Viewer &v)
|
||||
|
||||
if (v.scale_ == 1.f) {
|
||||
if (v.scale_job_pending_) {
|
||||
++v.scale_gen_;
|
||||
v.scale_gen_++;
|
||||
v.scale_job_pending_ = false;
|
||||
if (v.worker_) {
|
||||
lock_guard<mutex> lock(v.worker_->mu);
|
||||
@@ -1594,7 +1590,7 @@ snap_pan_to_pixels(float *pan, float disp, float vp, float scale)
|
||||
static void
|
||||
cancel_scale(Viewer &v)
|
||||
{
|
||||
++v.scale_gen_;
|
||||
v.scale_gen_++;
|
||||
v.scale_job_pending_ = false;
|
||||
v.scale_failed_ = false;
|
||||
v.page_scaled_.reset();
|
||||
@@ -1689,10 +1685,10 @@ copy_image(QMimeData *mime, const dawn::Image &im)
|
||||
const uint32_t w = im.width;
|
||||
const uint32_t h = im.height;
|
||||
vector<uint8_t> bgra(size_t(w) * h * 4);
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
for (uint32_t y = 0; y < h; y++) {
|
||||
const uint16_t *s = row_u16(im, y);
|
||||
uint8_t *d = bgra.data() + size_t(y) * w * 4;
|
||||
for (uint32_t x = 0; x < w; ++x) {
|
||||
for (uint32_t x = 0; x < w; x++) {
|
||||
d[0] = uint8_t(s[0] >> 8);
|
||||
d[1] = uint8_t(s[1] >> 8);
|
||||
d[2] = uint8_t(s[2] >> 8);
|
||||
@@ -1703,10 +1699,10 @@ copy_image(QMimeData *mime, const dawn::Image &im)
|
||||
}
|
||||
dawn::unpremultiply_bgra8(bgra.data(), w, h, size_t(w) * 4);
|
||||
QImage image(int(w), int(h), QImage::Format_ARGB32);
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
for (uint32_t y = 0; y < h; y++) {
|
||||
const uint8_t *s = bgra.data() + size_t(y) * w * 4;
|
||||
auto *d = reinterpret_cast<QRgb *>(image.scanLine(int(y)));
|
||||
for (uint32_t x = 0; x < w; ++x) {
|
||||
for (uint32_t x = 0; x < w; x++) {
|
||||
d[x] = qRgba(s[2], s[1], s[0], s[3]);
|
||||
s += 4;
|
||||
}
|
||||
@@ -1722,7 +1718,7 @@ copy_frame(const Viewer &v)
|
||||
copy_image(mime, *v.frame_);
|
||||
if (!v.url_.isEmpty()) {
|
||||
const QUrl files[] = {v.url_};
|
||||
copy_files(mime, files);
|
||||
copy_files(mime, files, false);
|
||||
}
|
||||
QGuiApplication::clipboard()->setMimeData(mime);
|
||||
}
|
||||
@@ -2059,8 +2055,8 @@ void
|
||||
Viewer::cancel_loads()
|
||||
{
|
||||
const bool discard_current = this->opening_;
|
||||
++this->open_gen_;
|
||||
++this->scale_gen_;
|
||||
this->open_gen_++;
|
||||
this->scale_gen_++;
|
||||
this->opening_ = false;
|
||||
this->open_done_ = false;
|
||||
this->detached_ = true;
|
||||
@@ -2104,9 +2100,8 @@ Viewer::consume_open_done()
|
||||
}
|
||||
|
||||
void
|
||||
Viewer::set_screen_profile(
|
||||
shared_ptr<dawn::Cmm> cmm, shared_ptr<dawn::Profile> profile, bool fallback,
|
||||
bool force_reload)
|
||||
Viewer::set_screen_profile(shared_ptr<dawn::Cmm> cmm,
|
||||
shared_ptr<dawn::Profile> profile, bool fallback, bool force_reload)
|
||||
{
|
||||
auto screen_icc = profile
|
||||
? make_shared<const vector<uint8_t>>(profile->to_bytes())
|
||||
|
||||
+2
-2
@@ -146,8 +146,8 @@ struct Viewer : Widget {
|
||||
[[nodiscard]] bool has_view() const;
|
||||
[[nodiscard]] bool consume_open_done();
|
||||
void set_screen_profile(std::shared_ptr<dawn::Cmm> cmm,
|
||||
std::shared_ptr<dawn::Profile> profile, bool fallback = true,
|
||||
bool force_reload = false);
|
||||
std::shared_ptr<dawn::Profile> profile, bool fallback,
|
||||
bool force_reload);
|
||||
void present(Page &ui);
|
||||
[[nodiscard]] int wake_ms() const override;
|
||||
bool press(Kit &kit, float x, float y, Qt::MouseButton button) override;
|
||||
|
||||
+74
-56
@@ -72,7 +72,7 @@ bake_rgb(dawn::Cmm *cmm, dawn::Profile *target, uint8_t r, uint8_t g, uint8_t b)
|
||||
return colour;
|
||||
uint16_t pixel[4] = {
|
||||
uint16_t(b * 257), uint16_t(g * 257), uint16_t(r * 257), 65535};
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
if (!srgb)
|
||||
return colour;
|
||||
if (!cmm->transform_bgra16(
|
||||
@@ -122,11 +122,11 @@ raster_symbolic(const char *name, int px)
|
||||
|
||||
QImage image(px, px, QImage::Format_ARGB32_Premultiplied);
|
||||
const size_t stride = size_t(px) * 4;
|
||||
for (int y = 0; y < px; ++y) {
|
||||
for (int y = 0; y < px; y++) {
|
||||
auto *row = (QRgb *) image.scanLine(y);
|
||||
const auto *src =
|
||||
(const unsigned char *) (pixmap.data() + size_t(y) * stride);
|
||||
for (int x = 0; x < px; ++x) {
|
||||
for (int x = 0; x < px; x++) {
|
||||
const int a = src[x * 4 + 3];
|
||||
row[x] = qRgba(a, a, a, a);
|
||||
}
|
||||
@@ -212,9 +212,9 @@ raster_glyph(const QRawFont &raw, quint32 gid, float phase, QPoint *origin)
|
||||
painter.end();
|
||||
|
||||
QRect ink;
|
||||
for (int y = 0; y < img.height(); ++y) {
|
||||
for (int y = 0; y < img.height(); y++) {
|
||||
const auto *row = (const QRgb *) img.constScanLine(y);
|
||||
for (int x = 0; x < img.width(); ++x) {
|
||||
for (int x = 0; x < img.width(); x++) {
|
||||
if (qAlpha(row[x]))
|
||||
ink |= QRect(x, y, 1, 1);
|
||||
}
|
||||
@@ -333,18 +333,18 @@ blit(Kit &kit, const Kit::Packed &rect, const QImage &src, bool coverage)
|
||||
|
||||
const int rows = min(rect.h, img.height());
|
||||
const int cols = min(rect.w, img.width());
|
||||
for (int y = 0; y < rows; ++y) {
|
||||
for (int y = 0; y < rows; y++) {
|
||||
uint16_t *dst = kit.atlas_.pixels.data() +
|
||||
(size_t(rect.y + y) * size_t(kit.atlas_.w) + size_t(rect.x)) * 4;
|
||||
if (coverage) {
|
||||
const uchar *row = img.constScanLine(y);
|
||||
for (int x = 0; x < cols; ++x) {
|
||||
for (int x = 0; x < cols; x++) {
|
||||
const uint16_t a = widen8(row[x]);
|
||||
fill_n(dst + x * 4, 4, a);
|
||||
}
|
||||
} else {
|
||||
const auto *row = (const QRgb *) img.constScanLine(y);
|
||||
for (int x = 0; x < cols; ++x) {
|
||||
for (int x = 0; x < cols; x++) {
|
||||
dst[x * 4 + 0] = widen8(uint8_t(qRed(row[x])));
|
||||
dst[x * 4 + 1] = widen8(uint8_t(qGreen(row[x])));
|
||||
dst[x * 4 + 2] = widen8(uint8_t(qBlue(row[x])));
|
||||
@@ -358,7 +358,7 @@ blit(Kit &kit, const Kit::Packed &rect, const QImage &src, bool coverage)
|
||||
static int
|
||||
font_id(Kit &kit, const QRawFont &raw)
|
||||
{
|
||||
for (size_t i = 0; i < kit.fonts_.size(); ++i) {
|
||||
for (size_t i = 0; i < kit.fonts_.size(); i++) {
|
||||
if (kit.fonts_[i] == raw)
|
||||
return int(i);
|
||||
}
|
||||
@@ -401,7 +401,7 @@ cache_ascii(Kit &kit, bool bold)
|
||||
const QRawFont &raw = bold ? kit.raw_bold_ : kit.raw_;
|
||||
if (!raw.isValid())
|
||||
return;
|
||||
for (int cp = 0x20; cp <= 0x7E; ++cp) {
|
||||
for (int cp = 0x20; cp <= 0x7E; cp++) {
|
||||
const QList<quint32> indexes =
|
||||
raw.glyphIndexesForString(QString(QChar(cp)));
|
||||
if (indexes.isEmpty())
|
||||
@@ -432,7 +432,7 @@ cache_text(Kit &kit, const QString &text, bool bold, int wrap)
|
||||
static void
|
||||
rebuild_atlas(Kit &kit)
|
||||
{
|
||||
++kit.atlas_epoch_;
|
||||
kit.atlas_epoch_++;
|
||||
kit.icons_.clear();
|
||||
kit.glyphs_.clear();
|
||||
kit.fonts_.clear();
|
||||
@@ -444,11 +444,11 @@ rebuild_atlas(Kit &kit)
|
||||
if (white.empty())
|
||||
return;
|
||||
kit.white_ = white;
|
||||
for (int y = 0; y < white.h; ++y) {
|
||||
for (int y = 0; y < white.h; y++) {
|
||||
uint16_t *dst = kit.atlas_.pixels.data() +
|
||||
size_t(white.y + y) * size_t(kit.atlas_.w) * 4 +
|
||||
size_t(white.x) * 4;
|
||||
for (int x = 0; x < white.w; ++x) {
|
||||
for (int x = 0; x < white.w; x++) {
|
||||
dst[x * 4 + 0] = 65535;
|
||||
dst[x * 4 + 1] = 65535;
|
||||
dst[x * 4 + 2] = 65535;
|
||||
@@ -465,11 +465,11 @@ rebuild_atlas(Kit &kit)
|
||||
const int y_max = gn - 1;
|
||||
const double x_scale = 1.0 / double(max(1, x_max));
|
||||
const double y_scale = 1.0 / double(max(1, y_max));
|
||||
for (int y = 0; y <= y_max; ++y) {
|
||||
for (int y = 0; y <= y_max; y++) {
|
||||
uint16_t *dst = kit.atlas_.pixels.data() +
|
||||
size_t(glow.y + y) * size_t(kit.atlas_.w) * 4 +
|
||||
size_t(glow.x) * 4;
|
||||
for (int x = 0; x <= x_max; ++x) {
|
||||
for (int x = 0; x <= x_max; x++) {
|
||||
const double xn = x_scale * double(x_max - x);
|
||||
const double yn = y_scale * double(y_max - y);
|
||||
const double v = min(sqrt(xn * xn + yn * yn), 1.0);
|
||||
@@ -520,7 +520,7 @@ emit_text(Kit &kit, float x, float y, const QString &text, Colour colour,
|
||||
const QList<quint32> gids = run.glyphIndexes();
|
||||
const QList<QPointF> pos = run.positions();
|
||||
const int n = int(min(gids.size(), pos.size()));
|
||||
for (int i = 0; i < n; ++i) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
// The shaper positions the pen in fractions of a pixel, and
|
||||
// kerning lives in those fractions. Split one off into the
|
||||
// phase the glyph was rasterised at, so that the quad can stay
|
||||
@@ -610,7 +610,7 @@ void
|
||||
Widget::paint_children(Kit &kit) const
|
||||
{
|
||||
const size_t n = child_count();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (const Widget *k = child(i))
|
||||
k->paint(kit);
|
||||
}
|
||||
@@ -643,7 +643,7 @@ Widget::prepare(Kit &kit)
|
||||
if (!shown())
|
||||
return;
|
||||
const size_t n = child_count();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (Widget *k = child(i))
|
||||
k->prepare(kit);
|
||||
}
|
||||
@@ -1517,6 +1517,12 @@ Splitter::release(Kit &, float, float, Qt::MouseButton button)
|
||||
|
||||
// --- Composite ---------------------------------------------------------------
|
||||
|
||||
Widget *
|
||||
Composite::add_child(unique_ptr<Widget> child)
|
||||
{
|
||||
return add_child(std::move(child), size_t(-1));
|
||||
}
|
||||
|
||||
Widget *
|
||||
Composite::add_child(unique_ptr<Widget> child, size_t at)
|
||||
{
|
||||
@@ -1541,11 +1547,17 @@ Composite::take_child(size_t at)
|
||||
return child;
|
||||
}
|
||||
|
||||
void
|
||||
Composite::erase_children()
|
||||
{
|
||||
erase_children(0);
|
||||
}
|
||||
|
||||
void
|
||||
Composite::erase_children(size_t from)
|
||||
{
|
||||
from = min(from, this->kids.size());
|
||||
for (size_t i = from; i < this->kids.size(); ++i) {
|
||||
for (size_t i = from; i < this->kids.size(); i++) {
|
||||
if (this->kids[i])
|
||||
this->kids[i]->parent_ = nullptr;
|
||||
}
|
||||
@@ -1579,14 +1591,14 @@ Container::measure_pack(Kit &kit, int max_w, int max_h, bool hz)
|
||||
if (!k || !k->shown())
|
||||
continue;
|
||||
if (k->grows()) {
|
||||
++growers;
|
||||
++vis;
|
||||
growers++;
|
||||
vis++;
|
||||
continue;
|
||||
}
|
||||
k->measure(kit, hz ? kUnlim : iw, hz ? ih : kUnlim);
|
||||
used += hz ? k->r.w : k->r.h;
|
||||
cross = max(cross, hz ? k->r.h : k->r.w);
|
||||
++vis;
|
||||
vis++;
|
||||
}
|
||||
const int gaps = kit.px(this->gap) * max(0, vis - 1);
|
||||
if (growers) {
|
||||
@@ -1631,9 +1643,9 @@ Container::arrange_pack(Kit &kit, Rect alloc, bool hz, Align align)
|
||||
Widget *k = child.get();
|
||||
if (!k || !k->shown())
|
||||
continue;
|
||||
++vis;
|
||||
vis++;
|
||||
if (k->grows()) {
|
||||
++growers;
|
||||
growers++;
|
||||
continue;
|
||||
}
|
||||
k->measure(kit, hz ? kUnlim : in.w, hz ? in.h : kUnlim);
|
||||
@@ -1662,7 +1674,7 @@ Container::arrange_pack(Kit &kit, Rect alloc, bool hz, Align align)
|
||||
if (!k || !k->shown())
|
||||
continue;
|
||||
packed += (hz ? k->r.w : k->r.h) + gap;
|
||||
++nv;
|
||||
nv++;
|
||||
}
|
||||
if (nv)
|
||||
packed -= gap;
|
||||
@@ -1745,7 +1757,7 @@ Flow::wrap(Kit &kit, int inner_w, int *total_h, vector<Line> *lines)
|
||||
};
|
||||
|
||||
const size_t n = this->kids.size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Widget *k = this->kids[i].get();
|
||||
// A hidden child keeps whatever rect it had: clearing it here would
|
||||
// be measuring as a side effect, and a width is what focusable()
|
||||
@@ -1767,7 +1779,7 @@ Flow::wrap(Kit &kit, int inner_w, int *total_h, vector<Line> *lines)
|
||||
flush(i);
|
||||
line_w += kept ? need : k->r.w;
|
||||
line_h = max(line_h, k->r.h);
|
||||
++kept;
|
||||
kept++;
|
||||
}
|
||||
flush(n);
|
||||
if (y)
|
||||
@@ -1813,19 +1825,19 @@ Flow::arrange(Kit &kit, Rect alloc)
|
||||
// field then fills its line the way it fills the bar, instead of
|
||||
// sitting at its minimum with a ragged gap after it.
|
||||
int used = 0, growers = 0, vis = 0;
|
||||
for (size_t i = line.first; i < line.first + line.count; ++i) {
|
||||
for (size_t i = line.first; i < line.first + line.count; i++) {
|
||||
Widget *k = this->kids[i].get();
|
||||
if (!k || !k->shown())
|
||||
continue;
|
||||
used += k->r.w;
|
||||
++vis;
|
||||
vis++;
|
||||
if (k->grows())
|
||||
++growers;
|
||||
growers++;
|
||||
}
|
||||
const int slack = max(0, in.w - used - gap * max(0, vis - 1));
|
||||
|
||||
int x = in.x, got = 0;
|
||||
for (size_t i = line.first; i < line.first + line.count; ++i) {
|
||||
for (size_t i = line.first; i < line.first + line.count; i++) {
|
||||
Widget *k = this->kids[i].get();
|
||||
if (!k || !k->shown())
|
||||
continue;
|
||||
@@ -2563,7 +2575,7 @@ collect_focusable(Widget *w, vector<Widget *> &out)
|
||||
if (w->focusable())
|
||||
out.push_back(w);
|
||||
const size_t n = w->child_count();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
collect_focusable(w->child(i), out);
|
||||
}
|
||||
|
||||
@@ -2578,7 +2590,7 @@ collect_mnemonics(Widget *w, QChar letter, vector<Widget *> &out)
|
||||
if (w->mnemonic_key().toLower() == letter)
|
||||
out.push_back(w);
|
||||
const size_t n = w->child_count();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
collect_mnemonics(w->child(i), letter, out);
|
||||
}
|
||||
|
||||
@@ -2650,7 +2662,7 @@ MenuPopup::key(Kit &kit, const Key &ev)
|
||||
switch (ev.key) {
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
kit.cycle_focus(this, ev.key == Qt::Key_Up ? -1 : 1);
|
||||
kit.cycle_focus(this, ev.key == Qt::Key_Up ? -1 : 1, true);
|
||||
focus_item(kit, kit.focus_, true);
|
||||
return true;
|
||||
case Qt::Key_Right:
|
||||
@@ -2790,7 +2802,7 @@ Overflow::step_line(Kit &kit, int dir)
|
||||
const auto it = find(items.begin(), items.end(), kit.focus_);
|
||||
if (it == items.end()) {
|
||||
this->want_x_ = -1;
|
||||
kit.cycle_focus(this, dir);
|
||||
kit.cycle_focus(this, dir, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2813,7 +2825,7 @@ Overflow::step_line(Kit &kit, int dir)
|
||||
const int line_y = items[size_t(j)]->r.y;
|
||||
int best = j;
|
||||
float least = 1e30f;
|
||||
for (int k = 0; k < n; ++k) {
|
||||
for (int k = 0; k < n; k++) {
|
||||
if (items[size_t(k)]->r.y != line_y)
|
||||
continue;
|
||||
const float d = abs(centre_of(items[size_t(k)]) - this->want_x_);
|
||||
@@ -2845,7 +2857,7 @@ Overflow::key(Kit &kit, const Key &ev)
|
||||
case Qt::Key_Right:
|
||||
// The items read as one strip that happens to be folded.
|
||||
this->want_x_ = -1;
|
||||
kit.cycle_focus(this, ev.key == Qt::Key_Left ? -1 : 1);
|
||||
kit.cycle_focus(this, ev.key == Qt::Key_Left ? -1 : 1, true);
|
||||
break;
|
||||
case Qt::Key_Home:
|
||||
this->want_x_ = -1;
|
||||
@@ -2855,7 +2867,7 @@ Overflow::key(Kit &kit, const Key &ev)
|
||||
// Entering the strip backwards from nowhere lands on its last item.
|
||||
this->want_x_ = -1;
|
||||
kit.set_focus(nullptr, true);
|
||||
kit.cycle_focus(this, -1);
|
||||
kit.cycle_focus(this, -1, true);
|
||||
break;
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
@@ -3446,6 +3458,12 @@ ToolbarSlot::ToolbarSlot()
|
||||
Composite::add_child(std::move(button));
|
||||
}
|
||||
|
||||
Widget *
|
||||
ToolbarSlot::add_item(unique_ptr<Widget> item)
|
||||
{
|
||||
return add_item(std::move(item), size_t(-1));
|
||||
}
|
||||
|
||||
Widget *
|
||||
ToolbarSlot::add_item(unique_ptr<Widget> item, size_t at)
|
||||
{
|
||||
@@ -3460,14 +3478,14 @@ ToolbarSlot::add_item(unique_ptr<Widget> item, size_t at)
|
||||
Composite::add_child(std::move(item), at);
|
||||
this->items_.insert(this->items_.begin() + ptrdiff_t(at), raw);
|
||||
if (at < this->split_)
|
||||
++this->split_;
|
||||
this->split_++;
|
||||
return raw;
|
||||
}
|
||||
|
||||
void
|
||||
ToolbarSlot::sync_layout_visible()
|
||||
{
|
||||
for (size_t i = 0; i < this->items_.size(); ++i) {
|
||||
for (size_t i = 0; i < this->items_.size(); i++) {
|
||||
// Only ever one of the two: what is lent starts at the split, so an
|
||||
// item is either shown in the popup's Flow or kept here by the bar.
|
||||
this->items_[i]->layout_visible =
|
||||
@@ -3492,13 +3510,13 @@ ToolbarSlot::lend_to(Overflow &overflow)
|
||||
const size_t end = this->items_.size();
|
||||
size_t a = min(this->split_, end), b = end;
|
||||
while (a < b && is_sep(this->items_[a]))
|
||||
++a;
|
||||
a++;
|
||||
while (b > a && is_sep(this->items_[b - 1]))
|
||||
--b;
|
||||
for (size_t i = a; i < b; ++i) {
|
||||
for (size_t i = a; i < b; i++) {
|
||||
Widget *item = this->items_[i];
|
||||
// Ownership follows the widget: whoever lays it out holds it.
|
||||
for (size_t j = 0; j < this->kids.size(); ++j) {
|
||||
for (size_t j = 0; j < this->kids.size(); j++) {
|
||||
if (this->kids[j].get() != item)
|
||||
continue;
|
||||
overflow.col->add_child(take_child(j));
|
||||
@@ -3529,9 +3547,9 @@ ToolbarSlot::reclaim()
|
||||
// Back in bar order, ahead of more, which is the last child throughout.
|
||||
// Everything below the run stayed here, so that is where it resumes.
|
||||
size_t at = first;
|
||||
for (size_t i = first; i < last; ++i) {
|
||||
for (size_t i = first; i < last; i++) {
|
||||
Widget *item = this->items_[i];
|
||||
for (size_t j = 0; j < overflow->col->kids.size(); ++j) {
|
||||
for (size_t j = 0; j < overflow->col->kids.size(); j++) {
|
||||
if (overflow->col->kids[j].get() != item)
|
||||
continue;
|
||||
Composite::add_child(overflow->col->take_child(j), at++);
|
||||
@@ -3587,7 +3605,7 @@ ToolbarSlot::arrange(Kit &kit, Rect alloc)
|
||||
// decide nothing overflows, and close the popup that is holding them.
|
||||
int total = 0;
|
||||
int shown = 0;
|
||||
for (size_t i = 0; i < end; ++i) {
|
||||
for (size_t i = 0; i < end; i++) {
|
||||
Widget *item = this->items_[i];
|
||||
if (!item->visible)
|
||||
continue;
|
||||
@@ -3605,7 +3623,7 @@ ToolbarSlot::arrange(Kit &kit, Rect alloc)
|
||||
int kept = 0;
|
||||
bool full = false;
|
||||
this->split_ = 0;
|
||||
for (size_t i = 0; i < end; ++i) {
|
||||
for (size_t i = 0; i < end; i++) {
|
||||
Widget *item = this->items_[i];
|
||||
if (!item->visible) {
|
||||
if (!full)
|
||||
@@ -3618,7 +3636,7 @@ ToolbarSlot::arrange(Kit &kit, Rect alloc)
|
||||
continue;
|
||||
}
|
||||
used += need;
|
||||
++kept;
|
||||
kept++;
|
||||
this->split_ = i + 1;
|
||||
}
|
||||
while (this->split_ > 0 && is_sep(this->items_[this->split_ - 1]))
|
||||
@@ -4426,7 +4444,7 @@ Kit::focus_scope() const
|
||||
void
|
||||
Kit::cycle_focus(int dir)
|
||||
{
|
||||
cycle_focus(focus_scope(), dir);
|
||||
cycle_focus(focus_scope(), dir, true);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -4437,7 +4455,7 @@ Kit::cycle_focus(Widget *scope, int dir, bool wrap)
|
||||
if (items.empty())
|
||||
return false;
|
||||
int i = -1;
|
||||
for (int k = 0, n = int(items.size()); k < n; ++k) {
|
||||
for (int k = 0, n = int(items.size()); k < n; k++) {
|
||||
if (items[size_t(k)] == this->focus_) {
|
||||
i = k;
|
||||
break;
|
||||
@@ -4612,7 +4630,7 @@ Kit::mouse_motion(float x, float y)
|
||||
bool
|
||||
Kit::track_popups(float x, float y)
|
||||
{
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); ++it) {
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); it++) {
|
||||
if (*it && (*it)->motion(*this, x, y))
|
||||
return true;
|
||||
}
|
||||
@@ -4718,7 +4736,7 @@ Kit::destroy()
|
||||
this->inited_ = false;
|
||||
this->popups_.clear();
|
||||
this->scrim_.reset();
|
||||
++this->atlas_epoch_;
|
||||
this->atlas_epoch_++;
|
||||
this->icons_.clear();
|
||||
this->glyphs_.clear();
|
||||
this->fonts_.clear();
|
||||
@@ -4955,7 +4973,7 @@ wake_tree(const Widget *w)
|
||||
return -1;
|
||||
int ms = w->wake_ms();
|
||||
const size_t n = w->child_count();
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
ms = sooner(ms, wake_tree(w->child(i)));
|
||||
return ms;
|
||||
}
|
||||
@@ -5044,7 +5062,7 @@ Kit::close_popups()
|
||||
void
|
||||
Kit::close_transient_popups()
|
||||
{
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); ++it) {
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); it++) {
|
||||
if (*it && !(*it)->transient()) {
|
||||
close_above(*it);
|
||||
return;
|
||||
@@ -5097,7 +5115,7 @@ Kit::hit(float x, float y)
|
||||
if (p && p->shown() && p->transient())
|
||||
transient_open = true;
|
||||
}
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); ++it) {
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); it++) {
|
||||
Popup *p = *it;
|
||||
if (!p || !p->shown() || (transient_open && !p->transient()))
|
||||
continue;
|
||||
@@ -5106,7 +5124,7 @@ Kit::hit(float x, float y)
|
||||
}
|
||||
// Before the scrim: pressing the button a list came out of has to reach
|
||||
// the button, which is what closes it again.
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); ++it) {
|
||||
for (auto it = this->popups_.rbegin(); it != this->popups_.rend(); it++) {
|
||||
Popup *p = *it;
|
||||
if (!p || !p->shown())
|
||||
continue;
|
||||
|
||||
+10
-13
@@ -19,8 +19,8 @@
|
||||
#include <Qt>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -194,11 +194,12 @@ struct Widget {
|
||||
struct Composite : Widget {
|
||||
std::vector<std::unique_ptr<Widget>> kids;
|
||||
|
||||
Widget *add_child(
|
||||
std::unique_ptr<Widget> child, std::size_t at = std::size_t(-1));
|
||||
Widget *add_child(std::unique_ptr<Widget> child);
|
||||
Widget *add_child(std::unique_ptr<Widget> child, std::size_t at);
|
||||
// The inverse: detaches one child and hands its ownership back.
|
||||
std::unique_ptr<Widget> take_child(std::size_t at);
|
||||
void erase_children(std::size_t from = 0);
|
||||
void erase_children();
|
||||
void erase_children(std::size_t from);
|
||||
std::size_t child_count() const override { return this->kids.size(); }
|
||||
Widget *child(std::size_t i) const override
|
||||
{
|
||||
@@ -658,8 +659,8 @@ struct ToolbarSlot : Row {
|
||||
std::vector<Widget *> items_;
|
||||
|
||||
ToolbarSlot();
|
||||
Widget *add_item(
|
||||
std::unique_ptr<Widget> item, std::size_t at = std::size_t(-1));
|
||||
Widget *add_item(std::unique_ptr<Widget> item);
|
||||
Widget *add_item(std::unique_ptr<Widget> item, std::size_t at);
|
||||
// Moves everything past the split into the popup, or brings it back.
|
||||
void lend_to(Overflow &overflow);
|
||||
void reclaim();
|
||||
@@ -841,13 +842,12 @@ struct Kit {
|
||||
bool activate_mnemonic(Widget *scope, int key);
|
||||
Widget *focus_scope() const;
|
||||
void cycle_focus(int dir);
|
||||
bool cycle_focus(Widget *scope, int dir, bool wrap = true);
|
||||
bool cycle_focus(Widget *scope, int dir, bool wrap);
|
||||
void focus_first(Widget *scope);
|
||||
bool key(const Key &ev);
|
||||
bool input_method(const QString &commit, const QString &preedit, int caret);
|
||||
[[nodiscard]] bool text_target(TextTarget &out) const;
|
||||
bool mouse_press(
|
||||
float x, float y, Qt::MouseButton button, unsigned mods = 0);
|
||||
bool mouse_press(float x, float y, Qt::MouseButton button, unsigned mods);
|
||||
bool mouse_release(float x, float y, Qt::MouseButton button);
|
||||
bool mouse_motion(float x, float y);
|
||||
bool mouse_scroll(float x, float y, int delta);
|
||||
@@ -865,10 +865,7 @@ struct Kit {
|
||||
float x, float y, const QString &text, Colour colour, bool bold);
|
||||
void draw_glow(Rect w, Colour col);
|
||||
// An inactive window halves whatever alpha its ink already had.
|
||||
[[nodiscard]] float ink_alpha() const
|
||||
{
|
||||
return this->active_ ? 1.f : 0.5f;
|
||||
}
|
||||
[[nodiscard]] float ink_alpha() const { return this->active_ ? 1.f : 0.5f; }
|
||||
void focus_ring(Rect w); // 1pt inset ring
|
||||
void draw_shadow(Rect w); // popup/tooltip drop shadow
|
||||
// Rect-shaped wrappers over the corner-based draw list.
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ main(int argc, char **argv)
|
||||
// Notifiers armed; Qt delivers them only in exec().
|
||||
// A Hello during init may time out (250ms) and isolate.
|
||||
host = make_unique<dn::InstanceHost>(
|
||||
std::move(listen.listener), app, session);
|
||||
std::move(listen.listener), app, session, nullptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -161,7 +161,7 @@ OverlayList::add_thumb(Box b, Uv uv, int transfer, Colour col)
|
||||
this->tex_ = kOverlayTexThumbs;
|
||||
add_quad(b, uv, col, col, col, col);
|
||||
const size_t first = this->mesh_.vertices.size() - 4;
|
||||
for (size_t i = first; i < this->mesh_.vertices.size(); ++i) {
|
||||
for (size_t i = first; i < this->mesh_.vertices.size(); i++) {
|
||||
OverlayVertex &vertex = this->mesh_.vertices[i];
|
||||
vertex.atlas_x0 = uv.u0;
|
||||
vertex.atlas_y0 = uv.v0;
|
||||
@@ -186,7 +186,7 @@ merge_free(vector<Sheet::Packed> &free)
|
||||
});
|
||||
vector<Sheet::Packed> out;
|
||||
out.push_back(free.front());
|
||||
for (size_t i = 1; i < free.size(); ++i) {
|
||||
for (size_t i = 1; i < free.size(); i++) {
|
||||
Sheet::Packed &last = out.back();
|
||||
if (last.x + last.w == free[i].x)
|
||||
last.w += free[i].w;
|
||||
@@ -226,7 +226,7 @@ Sheet::grow(int side)
|
||||
return;
|
||||
vector<uint16_t> next(size_t(nw) * size_t(nh) * 4, 0);
|
||||
if (this->w > 0 && this->h > 0 && !this->pixels.empty()) {
|
||||
for (int y = 0; y < this->h; ++y) {
|
||||
for (int y = 0; y < this->h; y++) {
|
||||
memcpy(next.data() + size_t(y) * size_t(nw) * 4,
|
||||
this->pixels.data() + size_t(y) * size_t(this->w) * 4,
|
||||
size_t(this->w) * 8);
|
||||
@@ -250,7 +250,7 @@ Sheet::alloc(int tw, int th)
|
||||
for (Shelf &shelf : this->shelves_) {
|
||||
if (shelf.h != th)
|
||||
continue;
|
||||
for (size_t i = 0; i < shelf.free.size(); ++i) {
|
||||
for (size_t i = 0; i < shelf.free.size(); i++) {
|
||||
Packed &span = shelf.free[i];
|
||||
if (span.w < tw)
|
||||
continue;
|
||||
@@ -313,7 +313,7 @@ Sheet::blit(Packed slot, const uint16_t *src, int src_w, int src_h, int stride)
|
||||
stride = src_w * int(sizeof(uint16_t) * 4);
|
||||
const int cols = min(slot.w, src_w);
|
||||
const int rows = min(slot.h, src_h);
|
||||
for (int y = 0; y < rows; ++y) {
|
||||
for (int y = 0; y < rows; y++) {
|
||||
uint16_t *dst = this->pixels.data() +
|
||||
(size_t(slot.y + y) * size_t(this->w) + size_t(slot.x)) * 4;
|
||||
const auto *row = (const uint16_t *) ((const uint8_t *) src +
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ struct Sheet {
|
||||
std::vector<Shelf> shelves_;
|
||||
|
||||
Sheet() = default;
|
||||
explicit Sheet(int side, bool keep_pixels = true);
|
||||
explicit Sheet(int side, bool keep_pixels);
|
||||
|
||||
void clear();
|
||||
void grow(int side);
|
||||
|
||||
+131
-135
@@ -37,7 +37,7 @@ check_vk(VkResult result, const char *what)
|
||||
}
|
||||
}
|
||||
|
||||
#define CALL_VK(name, suffix, ...) \
|
||||
#define CALL_VK(name, suffix, ...) \
|
||||
check_vk(vk##name(__VA_ARGS__), "vk" #name suffix)
|
||||
|
||||
[[noreturn]] static void
|
||||
@@ -119,7 +119,7 @@ pick_surface_format(const vector<VkSurfaceFormatKHR> &formats)
|
||||
{
|
||||
VkSurfaceFormatKHR best = formats.front();
|
||||
int best_score = surface_format_score(best);
|
||||
for (size_t i = 1; i < formats.size(); ++i) {
|
||||
for (size_t i = 1; i < formats.size(); i++) {
|
||||
const int score = surface_format_score(formats[i]);
|
||||
if (score > best_score) {
|
||||
best = formats[i];
|
||||
@@ -134,11 +134,11 @@ pick_present_mode(
|
||||
VkPhysicalDevice phys, VkSurfaceKHR surface, VkPresentModeKHR preferred)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
CALL_VK(GetPhysicalDeviceSurfacePresentModesKHR, " count",
|
||||
phys, surface, &count, nullptr);
|
||||
CALL_VK(GetPhysicalDeviceSurfacePresentModesKHR, " count", phys, surface,
|
||||
&count, nullptr);
|
||||
vector<VkPresentModeKHR> modes(count);
|
||||
CALL_VK(GetPhysicalDeviceSurfacePresentModesKHR, "",
|
||||
phys, surface, &count, modes.data());
|
||||
CALL_VK(GetPhysicalDeviceSurfacePresentModesKHR, "", phys, surface, &count,
|
||||
modes.data());
|
||||
if (find(modes.begin(), modes.end(), preferred) != modes.end())
|
||||
return preferred;
|
||||
// TODO: A silent MAILBOX-to-FIFO fallback restores Mesa's legacy Wayland
|
||||
@@ -208,30 +208,30 @@ Renderer::init(const GpuContext &gpu, VkSurfaceKHR surface, Extent pixel,
|
||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = this->queue_family_,
|
||||
};
|
||||
CALL_VK(CreateCommandPool, "",
|
||||
this->device_, &pool_info, nullptr, &this->cmd_pool_);
|
||||
CALL_VK(CreateCommandPool, "", this->device_, &pool_info, nullptr,
|
||||
&this->cmd_pool_);
|
||||
VkCommandBufferAllocateInfo command_info{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.commandPool = this->cmd_pool_,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
CALL_VK(AllocateCommandBuffers, "",
|
||||
this->device_, &command_info, &this->cmd_);
|
||||
CALL_VK(
|
||||
AllocateCommandBuffers, "", this->device_, &command_info, &this->cmd_);
|
||||
|
||||
VkFenceCreateInfo fence_info{
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
|
||||
};
|
||||
CALL_VK(CreateFence, "",
|
||||
this->device_, &fence_info, nullptr, &this->fence_);
|
||||
CALL_VK(
|
||||
CreateFence, "", this->device_, &fence_info, nullptr, &this->fence_);
|
||||
VkSemaphoreCreateInfo semaphore_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
};
|
||||
CALL_VK(CreateSemaphore, " image_available",
|
||||
this->device_, &semaphore_info, nullptr, &this->image_available_);
|
||||
CALL_VK(CreateSemaphore, " render_finished",
|
||||
this->device_, &semaphore_info, nullptr, &this->render_finished_);
|
||||
CALL_VK(CreateSemaphore, " image_available", this->device_, &semaphore_info,
|
||||
nullptr, &this->image_available_);
|
||||
CALL_VK(CreateSemaphore, " render_finished", this->device_, &semaphore_info,
|
||||
nullptr, &this->render_finished_);
|
||||
|
||||
this->want_extent_ = {pixel.width, pixel.height};
|
||||
create_swapchain();
|
||||
@@ -317,8 +317,8 @@ Renderer::create_swapchain()
|
||||
{
|
||||
destroy_swapchain();
|
||||
VkSurfaceCapabilitiesKHR capabilities{};
|
||||
CALL_VK(GetPhysicalDeviceSurfaceCapabilitiesKHR, "",
|
||||
this->phys_, this->surface_, &capabilities);
|
||||
CALL_VK(GetPhysicalDeviceSurfaceCapabilitiesKHR, "", this->phys_,
|
||||
this->surface_, &capabilities);
|
||||
|
||||
this->extent_.width = clamp(this->want_extent_.width,
|
||||
capabilities.minImageExtent.width,
|
||||
@@ -404,18 +404,18 @@ Renderer::create_swapchain()
|
||||
.presentMode = this->present_mode_,
|
||||
.clipped = VK_TRUE,
|
||||
};
|
||||
CALL_VK(CreateSwapchainKHR, "",
|
||||
this->device_, &swapchain_info, nullptr, &this->swapchain_);
|
||||
CALL_VK(CreateSwapchainKHR, "", this->device_, &swapchain_info, nullptr,
|
||||
&this->swapchain_);
|
||||
|
||||
uint32_t count = 0;
|
||||
CALL_VK(GetSwapchainImagesKHR, " count",
|
||||
this->device_, this->swapchain_, &count, nullptr);
|
||||
CALL_VK(GetSwapchainImagesKHR, " count", this->device_, this->swapchain_,
|
||||
&count, nullptr);
|
||||
this->images_.resize(count);
|
||||
CALL_VK(GetSwapchainImagesKHR, "",
|
||||
this->device_, this->swapchain_, &count, this->images_.data());
|
||||
CALL_VK(GetSwapchainImagesKHR, "", this->device_, this->swapchain_, &count,
|
||||
this->images_.data());
|
||||
this->views_.resize(count);
|
||||
this->framebuffers_.resize(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
VkImageViewCreateInfo view_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = this->images_[i],
|
||||
@@ -425,14 +425,14 @@ Renderer::create_swapchain()
|
||||
.levelCount = 1,
|
||||
.layerCount = 1},
|
||||
};
|
||||
CALL_VK(CreateImageView, " swap",
|
||||
this->device_, &view_info, nullptr, &this->views_[i]);
|
||||
CALL_VK(CreateImageView, " swap", this->device_, &view_info, nullptr,
|
||||
&this->views_[i]);
|
||||
}
|
||||
if (dither)
|
||||
create_dither();
|
||||
const VkRenderPass swap_rp =
|
||||
dither ? this->dither_rp_ : this->engine_.dest_render_pass();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
VkFramebufferCreateInfo framebuffer_info{
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = swap_rp,
|
||||
@@ -442,9 +442,8 @@ Renderer::create_swapchain()
|
||||
.height = this->extent_.height,
|
||||
.layers = 1,
|
||||
};
|
||||
CALL_VK(CreateFramebuffer, "",
|
||||
this->device_, &framebuffer_info, nullptr,
|
||||
&this->framebuffers_[i]);
|
||||
CALL_VK(CreateFramebuffer, "", this->device_, &framebuffer_info,
|
||||
nullptr, &this->framebuffers_[i]);
|
||||
}
|
||||
if (this->overlay_format_ != dest_format ||
|
||||
this->overlay_layout_ != dest_layout) {
|
||||
@@ -471,8 +470,8 @@ Renderer::wait_idle() const
|
||||
{
|
||||
if (!this->device_ || !this->fence_)
|
||||
return;
|
||||
CALL_VK(WaitForFences, "",
|
||||
this->device_, 1, &this->fence_, VK_TRUE, UINT64_MAX);
|
||||
CALL_VK(WaitForFences, "", this->device_, 1, &this->fence_, VK_TRUE,
|
||||
UINT64_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -575,8 +574,8 @@ Renderer::draw_frame(const OverlayMesh &mesh)
|
||||
if (!this->device_ || !this->swapchain_ || !this->extent_.width ||
|
||||
!this->extent_.height)
|
||||
return true;
|
||||
CALL_VK(WaitForFences, "",
|
||||
this->device_, 1, &this->fence_, VK_TRUE, UINT64_MAX);
|
||||
CALL_VK(WaitForFences, "", this->device_, 1, &this->fence_, VK_TRUE,
|
||||
UINT64_MAX);
|
||||
uint32_t index = 0;
|
||||
// A hidden Wayland surface has no guaranteed presentation progress, so an
|
||||
// infinite acquire timeout is invalid. Keep the latest frame dirty and let
|
||||
@@ -660,8 +659,7 @@ Renderer::draw_frame(const OverlayMesh &mesh)
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &this->render_finished_,
|
||||
};
|
||||
CALL_VK(QueueSubmit, "",
|
||||
this->queue_, 1, &submit_info, this->fence_);
|
||||
CALL_VK(QueueSubmit, "", this->queue_, 1, &submit_info, this->fence_);
|
||||
VkPresentInfoKHR present_info{
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
@@ -749,13 +747,14 @@ Renderer::create_dither()
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
CALL_VK(CreateImage, " compose",
|
||||
this->device_, &image_info, nullptr, &this->compose_image_);
|
||||
CALL_VK(CreateImage, " compose", this->device_, &image_info, nullptr,
|
||||
&this->compose_image_);
|
||||
VkMemoryRequirements requirements{};
|
||||
vkGetImageMemoryRequirements(
|
||||
this->device_, this->compose_image_, &requirements);
|
||||
const uint32_t type = dawn::vk_memory_type(this->phys_,
|
||||
requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
const uint32_t type =
|
||||
dawn::vk_memory_type(this->phys_, requirements.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, nullptr, nullptr);
|
||||
if (type == UINT32_MAX)
|
||||
die("dither compose: no device-local memory");
|
||||
VkMemoryAllocateInfo allocate{
|
||||
@@ -763,10 +762,10 @@ Renderer::create_dither()
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = type,
|
||||
};
|
||||
CALL_VK(AllocateMemory, " compose",
|
||||
this->device_, &allocate, nullptr, &this->compose_memory_);
|
||||
CALL_VK(BindImageMemory, " compose",
|
||||
this->device_, this->compose_image_, this->compose_memory_, 0);
|
||||
CALL_VK(AllocateMemory, " compose", this->device_, &allocate, nullptr,
|
||||
&this->compose_memory_);
|
||||
CALL_VK(BindImageMemory, " compose", this->device_, this->compose_image_,
|
||||
this->compose_memory_, 0);
|
||||
VkImageViewCreateInfo view_info{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = this->compose_image_,
|
||||
@@ -776,8 +775,8 @@ Renderer::create_dither()
|
||||
.levelCount = 1,
|
||||
.layerCount = 1},
|
||||
};
|
||||
CALL_VK(CreateImageView, " compose",
|
||||
this->device_, &view_info, nullptr, &this->compose_view_);
|
||||
CALL_VK(CreateImageView, " compose", this->device_, &view_info, nullptr,
|
||||
&this->compose_view_);
|
||||
VkFramebufferCreateInfo fb_info{
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = this->engine_.dest_render_pass(),
|
||||
@@ -787,8 +786,8 @@ Renderer::create_dither()
|
||||
.height = this->extent_.height,
|
||||
.layers = 1,
|
||||
};
|
||||
CALL_VK(CreateFramebuffer, " compose",
|
||||
this->device_, &fb_info, nullptr, &this->compose_fb_);
|
||||
CALL_VK(CreateFramebuffer, " compose", this->device_, &fb_info, nullptr,
|
||||
&this->compose_fb_);
|
||||
|
||||
VkAttachmentDescription color{
|
||||
.format = this->format_,
|
||||
@@ -826,8 +825,8 @@ Renderer::create_dither()
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &dependency,
|
||||
};
|
||||
CALL_VK(CreateRenderPass, " dither",
|
||||
this->device_, &rp_info, nullptr, &this->dither_rp_);
|
||||
CALL_VK(CreateRenderPass, " dither", this->device_, &rp_info, nullptr,
|
||||
&this->dither_rp_);
|
||||
|
||||
VkSamplerCreateInfo sampler_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
@@ -838,8 +837,8 @@ Renderer::create_dither()
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
};
|
||||
CALL_VK(CreateSampler, " dither",
|
||||
this->device_, &sampler_info, nullptr, &this->dither_sampler_);
|
||||
CALL_VK(CreateSampler, " dither", this->device_, &sampler_info, nullptr,
|
||||
&this->dither_sampler_);
|
||||
|
||||
VkDescriptorSetLayoutBinding binding{
|
||||
.binding = 0,
|
||||
@@ -852,8 +851,8 @@ Renderer::create_dither()
|
||||
.bindingCount = 1,
|
||||
.pBindings = &binding,
|
||||
};
|
||||
CALL_VK(CreateDescriptorSetLayout, " dither",
|
||||
this->device_, &set_info, nullptr, &this->dither_set_layout_);
|
||||
CALL_VK(CreateDescriptorSetLayout, " dither", this->device_, &set_info,
|
||||
nullptr, &this->dither_set_layout_);
|
||||
VkDescriptorPoolSize pool_size{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
@@ -864,16 +863,16 @@ Renderer::create_dither()
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &pool_size,
|
||||
};
|
||||
CALL_VK(CreateDescriptorPool, " dither",
|
||||
this->device_, &pool_info, nullptr, &this->dither_pool_);
|
||||
CALL_VK(CreateDescriptorPool, " dither", this->device_, &pool_info, nullptr,
|
||||
&this->dither_pool_);
|
||||
VkDescriptorSetAllocateInfo set_alloc{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = this->dither_pool_,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &this->dither_set_layout_,
|
||||
};
|
||||
CALL_VK(AllocateDescriptorSets, " dither",
|
||||
this->device_, &set_alloc, &this->dither_set_);
|
||||
CALL_VK(AllocateDescriptorSets, " dither", this->device_, &set_alloc,
|
||||
&this->dither_set_);
|
||||
VkDescriptorImageInfo image_descriptor{
|
||||
.sampler = this->dither_sampler_,
|
||||
.imageView = this->compose_view_,
|
||||
@@ -894,23 +893,23 @@ Renderer::create_dither()
|
||||
.codeSize = fullscreen_vert_words * sizeof(uint32_t),
|
||||
.pCode = fullscreen_vert,
|
||||
};
|
||||
CALL_VK(CreateShaderModule, " dither vert",
|
||||
this->device_, &vert_info, nullptr, &this->dither_vert_);
|
||||
CALL_VK(CreateShaderModule, " dither vert", this->device_, &vert_info,
|
||||
nullptr, &this->dither_vert_);
|
||||
VkShaderModuleCreateInfo frag_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = dn_dither_frag_words * sizeof(uint32_t),
|
||||
.pCode = dn_dither_frag,
|
||||
};
|
||||
CALL_VK(CreateShaderModule, " dither frag",
|
||||
this->device_, &frag_info, nullptr, &this->dither_frag_);
|
||||
CALL_VK(CreateShaderModule, " dither frag", this->device_, &frag_info,
|
||||
nullptr, &this->dither_frag_);
|
||||
|
||||
VkPipelineLayoutCreateInfo layout_info{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &this->dither_set_layout_,
|
||||
};
|
||||
CALL_VK(CreatePipelineLayout, " dither",
|
||||
this->device_, &layout_info, nullptr, &this->dither_layout_);
|
||||
CALL_VK(CreatePipelineLayout, " dither", this->device_, &layout_info,
|
||||
nullptr, &this->dither_layout_);
|
||||
|
||||
VkPipelineShaderStageCreateInfo stages[2]{};
|
||||
stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
@@ -974,9 +973,8 @@ Renderer::create_dither()
|
||||
.layout = this->dither_layout_,
|
||||
.renderPass = this->dither_rp_,
|
||||
};
|
||||
CALL_VK(CreateGraphicsPipelines, " dither",
|
||||
this->device_, VK_NULL_HANDLE, 1, &pipeline_info, nullptr,
|
||||
&this->dither_pipe_);
|
||||
CALL_VK(CreateGraphicsPipelines, " dither", this->device_, VK_NULL_HANDLE,
|
||||
1, &pipeline_info, nullptr, &this->dither_pipe_);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1046,8 +1044,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
|
||||
.queueFamilyIndex = this->queue_family_,
|
||||
};
|
||||
CALL_VK(CreateCommandPool, " overlay upload",
|
||||
this->device_, &pool_info, nullptr, &this->upload_pool_);
|
||||
CALL_VK(CreateCommandPool, " overlay upload", this->device_, &pool_info,
|
||||
nullptr, &this->upload_pool_);
|
||||
compute_thumb_atlas_max();
|
||||
|
||||
VkAttachmentDescription color{
|
||||
@@ -1087,8 +1085,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &dependency,
|
||||
};
|
||||
CALL_VK(CreateRenderPass, " overlay",
|
||||
this->device_, &render_pass_info, nullptr, &this->render_pass_);
|
||||
CALL_VK(CreateRenderPass, " overlay", this->device_, &render_pass_info,
|
||||
nullptr, &this->render_pass_);
|
||||
|
||||
VkSamplerCreateInfo sampler_info{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
@@ -1100,8 +1098,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.maxLod = 1.f,
|
||||
};
|
||||
CALL_VK(CreateSampler, " overlay",
|
||||
this->device_, &sampler_info, nullptr, &this->sampler_);
|
||||
CALL_VK(CreateSampler, " overlay", this->device_, &sampler_info, nullptr,
|
||||
&this->sampler_);
|
||||
|
||||
VkDescriptorSetLayoutBinding binding{
|
||||
.binding = 0,
|
||||
@@ -1114,8 +1112,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.bindingCount = 1,
|
||||
.pBindings = &binding,
|
||||
};
|
||||
CALL_VK(CreateDescriptorSetLayout, " overlay",
|
||||
this->device_, &layout_info, nullptr, &this->set_layout_);
|
||||
CALL_VK(CreateDescriptorSetLayout, " overlay", this->device_, &layout_info,
|
||||
nullptr, &this->set_layout_);
|
||||
|
||||
VkDescriptorPoolSize pool_size{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
@@ -1127,9 +1125,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &pool_size,
|
||||
};
|
||||
CALL_VK(CreateDescriptorPool, " overlay",
|
||||
this->device_, &descriptor_pool_info, nullptr,
|
||||
&this->descriptor_pool_);
|
||||
CALL_VK(CreateDescriptorPool, " overlay", this->device_,
|
||||
&descriptor_pool_info, nullptr, &this->descriptor_pool_);
|
||||
VkDescriptorSetLayout layouts[2] = {this->set_layout_, this->set_layout_};
|
||||
VkDescriptorSetAllocateInfo allocate_info{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
@@ -1137,8 +1134,8 @@ OverlayVulkan::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
.descriptorSetCount = 2,
|
||||
.pSetLayouts = layouts,
|
||||
};
|
||||
CALL_VK(AllocateDescriptorSets, " overlay",
|
||||
this->device_, &allocate_info, this->descriptor_sets_);
|
||||
CALL_VK(AllocateDescriptorSets, " overlay", this->device_, &allocate_info,
|
||||
this->descriptor_sets_);
|
||||
|
||||
return create_pipeline();
|
||||
}
|
||||
@@ -1161,12 +1158,12 @@ OverlayVulkan::create_pipeline()
|
||||
.codeSize = dn_thumb_frag_words * sizeof(uint32_t),
|
||||
.pCode = dn_thumb_frag,
|
||||
};
|
||||
CALL_VK(CreateShaderModule, " overlay vert",
|
||||
this->device_, &vert_info, nullptr, &this->vert_);
|
||||
CALL_VK(CreateShaderModule, " overlay frag",
|
||||
this->device_, &frag_info, nullptr, &this->frag_);
|
||||
CALL_VK(CreateShaderModule, " thumb frag",
|
||||
this->device_, &thumb_frag_info, nullptr, &this->thumb_frag_);
|
||||
CALL_VK(CreateShaderModule, " overlay vert", this->device_, &vert_info,
|
||||
nullptr, &this->vert_);
|
||||
CALL_VK(CreateShaderModule, " overlay frag", this->device_, &frag_info,
|
||||
nullptr, &this->frag_);
|
||||
CALL_VK(CreateShaderModule, " thumb frag", this->device_, &thumb_frag_info,
|
||||
nullptr, &this->thumb_frag_);
|
||||
|
||||
VkPushConstantRange push{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
@@ -1180,9 +1177,8 @@ OverlayVulkan::create_pipeline()
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &push,
|
||||
};
|
||||
CALL_VK(CreatePipelineLayout, " overlay",
|
||||
this->device_, &pipeline_layout_info, nullptr,
|
||||
&this->pipeline_layout_);
|
||||
CALL_VK(CreatePipelineLayout, " overlay", this->device_,
|
||||
&pipeline_layout_info, nullptr, &this->pipeline_layout_);
|
||||
|
||||
VkPipelineShaderStageCreateInfo stages[2]{};
|
||||
stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
@@ -1289,13 +1285,11 @@ OverlayVulkan::create_pipeline()
|
||||
.layout = this->pipeline_layout_,
|
||||
.renderPass = this->render_pass_,
|
||||
};
|
||||
CALL_VK(CreateGraphicsPipelines, " overlay",
|
||||
this->device_, VK_NULL_HANDLE, 1, &pipeline_info, nullptr,
|
||||
&this->pipeline_);
|
||||
CALL_VK(CreateGraphicsPipelines, " overlay", this->device_, VK_NULL_HANDLE,
|
||||
1, &pipeline_info, nullptr, &this->pipeline_);
|
||||
stages[1].module = this->thumb_frag_;
|
||||
CALL_VK(CreateGraphicsPipelines, " thumbnails",
|
||||
this->device_, VK_NULL_HANDLE, 1, &pipeline_info, nullptr,
|
||||
&this->thumb_pipeline_);
|
||||
CALL_VK(CreateGraphicsPipelines, " thumbnails", this->device_,
|
||||
VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &this->thumb_pipeline_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1309,7 +1303,7 @@ OverlayVulkan::set_swapchain(
|
||||
!extent.width || !extent.height)
|
||||
return;
|
||||
this->framebuffers_.resize(views.size());
|
||||
for (size_t i = 0; i < views.size(); ++i) {
|
||||
for (size_t i = 0; i < views.size(); i++) {
|
||||
VkFramebufferCreateInfo info{
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = this->render_pass_,
|
||||
@@ -1319,8 +1313,8 @@ OverlayVulkan::set_swapchain(
|
||||
.height = extent.height,
|
||||
.layers = 1,
|
||||
};
|
||||
CALL_VK(CreateFramebuffer, " overlay",
|
||||
this->device_, &info, nullptr, &this->framebuffers_[i]);
|
||||
CALL_VK(CreateFramebuffer, " overlay", this->device_, &info, nullptr,
|
||||
&this->framebuffers_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1378,12 +1372,13 @@ OverlayVulkan::create_sampled(
|
||||
if (!this->device_ || width <= 0 || height <= 0 || !image || !memory)
|
||||
return false;
|
||||
const VkImageCreateInfo image_info = sampled_info(width, height);
|
||||
CALL_VK(CreateImage, " overlay tex",
|
||||
this->device_, &image_info, nullptr, image);
|
||||
CALL_VK(CreateImage, " overlay tex", this->device_, &image_info, nullptr,
|
||||
image);
|
||||
VkMemoryRequirements requirements{};
|
||||
vkGetImageMemoryRequirements(this->device_, *image, &requirements);
|
||||
const uint32_t image_type = dawn::vk_memory_type(this->phys_,
|
||||
requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
const uint32_t image_type =
|
||||
dawn::vk_memory_type(this->phys_, requirements.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, nullptr, nullptr);
|
||||
if (image_type == UINT32_MAX) {
|
||||
vkDestroyImage(this->device_, *image, nullptr);
|
||||
*image = VK_NULL_HANDLE;
|
||||
@@ -1394,10 +1389,9 @@ OverlayVulkan::create_sampled(
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = image_type,
|
||||
};
|
||||
CALL_VK(AllocateMemory, " overlay tex",
|
||||
this->device_, &allocate, nullptr, memory);
|
||||
CALL_VK(BindImageMemory, " overlay tex",
|
||||
this->device_, *image, *memory, 0);
|
||||
CALL_VK(AllocateMemory, " overlay tex", this->device_, &allocate, nullptr,
|
||||
memory);
|
||||
CALL_VK(BindImageMemory, " overlay tex", this->device_, *image, *memory, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1415,8 +1409,8 @@ OverlayVulkan::bind_sampled(VkImage image, VkImageView *view,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1},
|
||||
};
|
||||
CALL_VK(CreateImageView, " overlay tex",
|
||||
this->device_, &view_info, nullptr, view);
|
||||
CALL_VK(CreateImageView, " overlay tex", this->device_, &view_info, nullptr,
|
||||
view);
|
||||
if (!set)
|
||||
return;
|
||||
VkDescriptorImageInfo image_descriptor{
|
||||
@@ -1451,15 +1445,16 @@ OverlayVulkan::copy_rgba16(const void *pixels, int width, int height,
|
||||
.size = size,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
};
|
||||
CALL_VK(CreateBuffer, " overlay tex staging",
|
||||
this->device_, &buffer_info, nullptr, &staging);
|
||||
CALL_VK(CreateBuffer, " overlay tex staging", this->device_, &buffer_info,
|
||||
nullptr, &staging);
|
||||
|
||||
VkMemoryRequirements requirements{};
|
||||
vkGetBufferMemoryRequirements(this->device_, staging, &requirements);
|
||||
const uint32_t host_type =
|
||||
dawn::vk_memory_type(this->phys_, requirements.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
nullptr, nullptr);
|
||||
if (host_type == UINT32_MAX) {
|
||||
vkDestroyBuffer(this->device_, staging, nullptr);
|
||||
return false;
|
||||
@@ -1470,13 +1465,13 @@ OverlayVulkan::copy_rgba16(const void *pixels, int width, int height,
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = host_type,
|
||||
};
|
||||
CALL_VK(AllocateMemory, " overlay tex staging",
|
||||
this->device_, &allocate, nullptr, &staging_memory);
|
||||
CALL_VK(BindBufferMemory, " overlay tex staging",
|
||||
this->device_, staging, staging_memory, 0);
|
||||
CALL_VK(AllocateMemory, " overlay tex staging", this->device_, &allocate,
|
||||
nullptr, &staging_memory);
|
||||
CALL_VK(BindBufferMemory, " overlay tex staging", this->device_, staging,
|
||||
staging_memory, 0);
|
||||
void *mapped = nullptr;
|
||||
CALL_VK(MapMemory, " overlay tex staging",
|
||||
this->device_, staging_memory, 0, size, 0, &mapped);
|
||||
CALL_VK(MapMemory, " overlay tex staging", this->device_, staging_memory, 0,
|
||||
size, 0, &mapped);
|
||||
memcpy(mapped, pixels, size_t(size));
|
||||
vkUnmapMemory(this->device_, staging_memory);
|
||||
|
||||
@@ -1487,8 +1482,8 @@ OverlayVulkan::copy_rgba16(const void *pixels, int width, int height,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
CALL_VK(AllocateCommandBuffers, " overlay tex",
|
||||
this->device_, &cmd_info, &cmd);
|
||||
CALL_VK(
|
||||
AllocateCommandBuffers, " overlay tex", this->device_, &cmd_info, &cmd);
|
||||
VkCommandBufferBeginInfo begin{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
@@ -1536,8 +1531,8 @@ OverlayVulkan::copy_rgba16(const void *pixels, int width, int height,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
};
|
||||
CALL_VK(QueueSubmit, " overlay tex",
|
||||
this->queue_, 1, &submit, VK_NULL_HANDLE);
|
||||
CALL_VK(
|
||||
QueueSubmit, " overlay tex", this->queue_, 1, &submit, VK_NULL_HANDLE);
|
||||
CALL_VK(QueueWaitIdle, " overlay tex", this->queue_);
|
||||
vkFreeCommandBuffers(this->device_, this->upload_pool_, 1, &cmd);
|
||||
vkDestroyBuffer(this->device_, staging, nullptr);
|
||||
@@ -1556,7 +1551,7 @@ OverlayVulkan::upload_rgba16(const void *pixels, int width, int height,
|
||||
if (!create_sampled(width, height, image, memory))
|
||||
return false;
|
||||
if (!copy_rgba16(
|
||||
pixels, width, height, *image, VK_IMAGE_LAYOUT_UNDEFINED)) {
|
||||
pixels, width, height, *image, VK_IMAGE_LAYOUT_UNDEFINED, 0, 0)) {
|
||||
destroy_sampled(image, memory, view);
|
||||
return false;
|
||||
}
|
||||
@@ -1703,14 +1698,15 @@ OverlayVulkan::ensure_buffers(
|
||||
.size = *current,
|
||||
.usage = usage,
|
||||
};
|
||||
CALL_VK(CreateBuffer, " overlay",
|
||||
this->device_, &info, nullptr, buffer);
|
||||
CALL_VK(
|
||||
CreateBuffer, " overlay", this->device_, &info, nullptr, buffer);
|
||||
VkMemoryRequirements requirements{};
|
||||
vkGetBufferMemoryRequirements(this->device_, *buffer, &requirements);
|
||||
const uint32_t type =
|
||||
dawn::vk_memory_type(this->phys_, requirements.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
nullptr, nullptr);
|
||||
if (type == UINT32_MAX)
|
||||
return false;
|
||||
VkMemoryAllocateInfo allocate{
|
||||
@@ -1718,10 +1714,10 @@ OverlayVulkan::ensure_buffers(
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = type,
|
||||
};
|
||||
CALL_VK(AllocateMemory, " overlay",
|
||||
this->device_, &allocate, nullptr, memory);
|
||||
CALL_VK(BindBufferMemory, " overlay",
|
||||
this->device_, *buffer, *memory, 0);
|
||||
CALL_VK(AllocateMemory, " overlay", this->device_, &allocate, nullptr,
|
||||
memory);
|
||||
CALL_VK(
|
||||
BindBufferMemory, " overlay", this->device_, *buffer, *memory, 0);
|
||||
return true;
|
||||
};
|
||||
return recreate(&this->vertex_buffer_, &this->vertex_memory_,
|
||||
@@ -1753,10 +1749,10 @@ OverlayVulkan::record(
|
||||
|
||||
void *vertices = nullptr;
|
||||
void *indices = nullptr;
|
||||
CALL_VK(MapMemory, " overlay vtx",
|
||||
this->device_, this->vertex_memory_, 0, vertex_bytes, 0, &vertices);
|
||||
CALL_VK(MapMemory, " overlay idx",
|
||||
this->device_, this->index_memory_, 0, index_bytes, 0, &indices);
|
||||
CALL_VK(MapMemory, " overlay vtx", this->device_, this->vertex_memory_, 0,
|
||||
vertex_bytes, 0, &vertices);
|
||||
CALL_VK(MapMemory, " overlay idx", this->device_, this->index_memory_, 0,
|
||||
index_bytes, 0, &indices);
|
||||
memcpy(vertices, mesh.vertices.data(), size_t(vertex_bytes));
|
||||
memcpy(indices, mesh.indices.data(), size_t(index_bytes));
|
||||
vkUnmapMemory(this->device_, this->vertex_memory_);
|
||||
@@ -1788,7 +1784,7 @@ OverlayVulkan::record(
|
||||
push.translate[0] = -1.f;
|
||||
push.translate[1] = -1.f;
|
||||
vkCmdPushConstants(cmd, this->pipeline_layout_, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, sizeof(push), &push);
|
||||
0, sizeof push, &push);
|
||||
|
||||
uint32_t bound_tex = ~0u;
|
||||
VkPipeline bound_pipeline = VK_NULL_HANDLE;
|
||||
|
||||
+4
-4
@@ -51,7 +51,7 @@ class OverlayVulkan
|
||||
VkImage *image, VkDeviceMemory *memory, VkImageView *view,
|
||||
VkDescriptorSet set, VkComponentMapping swizzle) const;
|
||||
bool copy_rgba16(const void *pixels, int width, int height, VkImage image,
|
||||
VkImageLayout layout, int dst_x = 0, int dst_y = 0) const;
|
||||
VkImageLayout layout, int dst_x, int dst_y) const;
|
||||
bool create_sampled(
|
||||
int width, int height, VkImage *image, VkDeviceMemory *memory) const;
|
||||
void bind_sampled(VkImage image, VkImageView *view, VkDescriptorSet set,
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
bool upload_font(const unsigned char *pixels, int width, int height);
|
||||
[[nodiscard]] int thumb_atlas_max() const { return this->thumb_atlas_max_; }
|
||||
bool upload_thumb(const uint16_t *pixels, int width, int height, int dst_x,
|
||||
int dst_y, int atlas_side, bool *recreated = nullptr);
|
||||
int dst_y, int atlas_side, bool *recreated);
|
||||
bool rebuild_thumbs(
|
||||
const std::vector<ThumbUpload> &uploads, int atlas_side);
|
||||
void reset_thumbs();
|
||||
@@ -206,7 +206,7 @@ public:
|
||||
uint32_t w, uint32_t h, const uint8_t *pixels, size_t stride);
|
||||
void clear_image();
|
||||
void set_view(float scale, float pan_x, float pan_y,
|
||||
dawn::Orientation orientation, float angle = 0.f);
|
||||
dawn::Orientation orientation, float angle);
|
||||
void set_well_colour(float r, float g, float b);
|
||||
void set_prefer_premultiplied(bool enabled)
|
||||
{
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
bool upload_font(const unsigned char *pixels, int width, int height);
|
||||
[[nodiscard]] int thumb_atlas_max() const;
|
||||
bool upload_thumb(const uint16_t *pixels, int width, int height, int dst_x,
|
||||
int dst_y, int atlas_side, bool *recreated = nullptr);
|
||||
int dst_y, int atlas_side, bool *recreated);
|
||||
bool rebuild_thumbs(
|
||||
const std::vector<ThumbUpload> &uploads, int atlas_side);
|
||||
void reset_thumbs();
|
||||
|
||||
@@ -203,7 +203,7 @@ read_wide(const QString &path, const ThumbnailSource &source, int tier,
|
||||
hit.width = image->width;
|
||||
hit.height = image->height;
|
||||
hit.pixels.resize(size_t(hit.width) * hit.height * 4);
|
||||
for (uint32_t y = 0; y < hit.height; ++y)
|
||||
for (uint32_t y = 0; y < hit.height; y++)
|
||||
memcpy(hit.pixels.data() + size_t(y) * hit.width * 4,
|
||||
row_u16(*image, y), size_t(hit.width) * dawn::kBytesPerPixel);
|
||||
hit.tier = tier;
|
||||
@@ -238,7 +238,7 @@ read_png(const QString &path, const ThumbnailSource &source, int tier,
|
||||
if (!valid_metadata(meta, source))
|
||||
return {};
|
||||
|
||||
shared_ptr<dawn::Profile> srgb = cmm->get_profile_sRGB();
|
||||
shared_ptr<dawn::Profile> srgb = cmm->get_profile_sRGB(false);
|
||||
if (!cmm->transform_bgra16(image->data.data(), image->width, image->height,
|
||||
srgb.get(), screen, true, true))
|
||||
return {};
|
||||
@@ -246,7 +246,7 @@ read_png(const QString &path, const ThumbnailSource &source, int tier,
|
||||
hit.width = image->width;
|
||||
hit.height = image->height;
|
||||
hit.pixels.resize(size_t(hit.width) * hit.height * 4);
|
||||
for (uint32_t y = 0; y < hit.height; ++y)
|
||||
for (uint32_t y = 0; y < hit.height; y++)
|
||||
memcpy(hit.pixels.data() + size_t(y) * hit.width * 4,
|
||||
row_u16(*image, y), size_t(hit.width) * dawn::kBytesPerPixel);
|
||||
hit.tier = tier;
|
||||
@@ -414,7 +414,7 @@ thumbnail_cache_write(const ThumbnailSource &source, int tier,
|
||||
for (size_t i = 0, n = size_t(width) * height; i < n; i++) {
|
||||
const uint32_t a = pixels[i * 4 + 3];
|
||||
bgra[i * 4 + 3] = uint8_t((a + 128) / 257);
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
for (int c = 0; c < 3; c++) {
|
||||
const uint32_t straight = a
|
||||
? min(65535u,
|
||||
uint32_t(
|
||||
|
||||
@@ -52,7 +52,7 @@ ThumbnailHit thumbnail_cache_lookup(const ThumbnailSource &source,
|
||||
|
||||
bool thumbnail_cache_write(const ThumbnailSource &source, int tier,
|
||||
const uint16_t *pixels, uint32_t width, uint32_t height,
|
||||
uint32_t image_width, uint32_t image_height, QString *error = nullptr);
|
||||
uint32_t image_width, uint32_t image_height, QString *error);
|
||||
|
||||
void thumbnail_cache_invalidate();
|
||||
|
||||
|
||||
+22
-19
@@ -168,16 +168,16 @@ Thumbnailer::Impl::Impl(Thumbnailer *thumbnailer, unsigned worker_count)
|
||||
[thumbnailer] { thumbnailer->pump(); });
|
||||
|
||||
unsigned count =
|
||||
worker_count ? worker_count : std::thread::hardware_concurrency();
|
||||
worker_count ? worker_count : thread::hardware_concurrency();
|
||||
if (!count)
|
||||
count = 1;
|
||||
this->worker_count = count;
|
||||
background_max = min<size_t>(4, max<size_t>(1, count / 4));
|
||||
workers.reserve(count);
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
workers.emplace_back([this] { worker_loop(); });
|
||||
encoders.reserve(count);
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
encoders.emplace_back([this] { encoder_loop(); });
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ bool
|
||||
Thumbnailer::Impl::have_cpu() const
|
||||
{
|
||||
const bool reserve = worker_count > 1 && cpu_running >= worker_count - 1;
|
||||
for (size_t priority = 0; priority < cpu.size(); ++priority) {
|
||||
for (size_t priority = 0; priority < cpu.size(); priority++) {
|
||||
if (priority == priority_index(Priority::Prefetch) && reserve)
|
||||
continue;
|
||||
if (priority >= priority_index(Priority::Dimensions) &&
|
||||
@@ -238,7 +238,7 @@ Thumbnailer::Impl::have_cpu() const
|
||||
bool
|
||||
Thumbnailer::Impl::pop_cpu(shared_ptr<CpuTask> *task)
|
||||
{
|
||||
for (size_t priority = 0; priority < cpu.size(); ++priority) {
|
||||
for (size_t priority = 0; priority < cpu.size(); priority++) {
|
||||
const bool reserve =
|
||||
worker_count > 1 && cpu_running >= worker_count - 1;
|
||||
if (priority == priority_index(Priority::Prefetch) && reserve)
|
||||
@@ -308,8 +308,8 @@ Thumbnailer::Impl::worker_loop()
|
||||
if (client != clients.end() && completion &&
|
||||
client->second.epoch == task->epoch) {
|
||||
client->second.gui++;
|
||||
gui.push_back({task->client, task->epoch, task->running_priority,
|
||||
std::move(completion)});
|
||||
gui.push_back({task->client, task->epoch,
|
||||
task->running_priority, std::move(completion)});
|
||||
}
|
||||
}
|
||||
task->gate->store(true, memory_order_release);
|
||||
@@ -363,7 +363,7 @@ Thumbnailer::Impl::erase_unpublished(Client id)
|
||||
{
|
||||
for (auto it = bundles.begin(); it != bundles.end();) {
|
||||
if (it->second.client != id || it->second.bundle) {
|
||||
++it;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
bundle_bytes -= it->second.reserved_bytes;
|
||||
@@ -388,7 +388,7 @@ Thumbnailer::Impl::erase_gui(Client id, ClientState &state)
|
||||
state.gui--;
|
||||
it = gui.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -403,7 +403,7 @@ Thumbnailer::Impl::erase_gpu(Client id, ClientState &state)
|
||||
state.gpu--;
|
||||
it = gpu_tasks.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -649,7 +649,8 @@ Thumbnailer::submit_gpu(Client id, uint64_t epoch, Priority priority,
|
||||
impl_->fail_gpu(gpu_id, std::move(path));
|
||||
}
|
||||
return Completion{};
|
||||
})) {
|
||||
},
|
||||
{})) {
|
||||
lock_guard lock(impl_->mu);
|
||||
impl_->drop_gpu(gpu_id);
|
||||
return false;
|
||||
@@ -683,8 +684,8 @@ Thumbnailer::reserve_bundle(Client id, uint64_t epoch,
|
||||
if (!reservation)
|
||||
reservation = impl_->next_reservation++;
|
||||
impl_->bundles.emplace(reservation,
|
||||
Impl::BundleSlot{reservation, id, epoch, source, top_tier, bytes,
|
||||
priority, {}});
|
||||
Impl::BundleSlot{
|
||||
reservation, id, epoch, source, top_tier, bytes, priority, {}});
|
||||
impl_->bundle_bytes += bytes;
|
||||
return reservation;
|
||||
}
|
||||
@@ -787,13 +788,15 @@ Thumbnailer::foreground_busy(Client id) const
|
||||
}
|
||||
for (const auto &[gpu_id, task] : impl_->gpu_tasks) {
|
||||
(void) gpu_id;
|
||||
if (task.client == id && priority_index(task.priority) <
|
||||
priority_index(Priority::Dimensions))
|
||||
if (task.client == id &&
|
||||
priority_index(task.priority) <
|
||||
priority_index(Priority::Dimensions))
|
||||
return true;
|
||||
}
|
||||
for (const Impl::GuiTask &task : impl_->gui)
|
||||
if (task.client == id && priority_index(task.priority) <
|
||||
priority_index(Priority::Dimensions))
|
||||
if (task.client == id &&
|
||||
priority_index(task.priority) <
|
||||
priority_index(Priority::Dimensions))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -836,7 +839,7 @@ Thumbnailer::pump()
|
||||
// CPU completions establish browser state needed by any GPU job they
|
||||
// queued. Always apply them before polling those jobs.
|
||||
size_t gui_count = 0;
|
||||
for (; gui_count < kGuiBatch; ++gui_count) {
|
||||
for (; gui_count < kGuiBatch; gui_count++) {
|
||||
Completion completion;
|
||||
{
|
||||
lock_guard lock(impl_->mu);
|
||||
@@ -874,7 +877,7 @@ Thumbnailer::pump()
|
||||
Impl::GpuTask &task = it->second;
|
||||
if (!task.result ||
|
||||
(task.gate && !task.gate->load(memory_order_acquire))) {
|
||||
++it;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
auto client = impl_->clients.find(task.client);
|
||||
|
||||
+4
-5
@@ -80,25 +80,24 @@ public:
|
||||
Maintenance,
|
||||
};
|
||||
|
||||
explicit Thumbnailer(QObject *parent = nullptr, unsigned workers = 0);
|
||||
explicit Thumbnailer(QObject *parent, unsigned workers);
|
||||
~Thumbnailer() override;
|
||||
|
||||
Thumbnailer(const Thumbnailer &) = delete;
|
||||
Thumbnailer &operator=(const Thumbnailer &) = delete;
|
||||
|
||||
bool init(const GpuContext &gpu);
|
||||
Client add_client(uint64_t epoch = 0, Completion activity = {});
|
||||
Client add_client(uint64_t epoch, Completion activity);
|
||||
void remove_client(Client client);
|
||||
void set_epoch(Client client, uint64_t epoch);
|
||||
|
||||
bool submit(Client client, uint64_t epoch, Priority priority, Work work,
|
||||
std::string key = {});
|
||||
std::string key);
|
||||
bool reprioritize(Client client, uint64_t epoch, Priority priority,
|
||||
const std::string &key);
|
||||
/// Copies owned job pixels on a worker. Safe on the GUI thread.
|
||||
bool submit_gpu(Client client, uint64_t epoch, Priority priority,
|
||||
dawn::ThumbScaler::Job job, GpuCompletion completion,
|
||||
std::string key = {});
|
||||
dawn::ThumbScaler::Job job, GpuCompletion completion, std::string key);
|
||||
Reservation reserve_bundle(Client client, uint64_t epoch,
|
||||
const ThumbnailSource &source, int top_tier, size_t bytes,
|
||||
Priority priority);
|
||||
|
||||
+1
-2
@@ -38,8 +38,7 @@ url_normalized(const QUrl &url)
|
||||
QUrl
|
||||
url_from_user_input(const QString &input, const QString &working_dir)
|
||||
{
|
||||
auto url =
|
||||
QUrl::fromUserInput(input, working_dir, QUrl::AssumeLocalFile);
|
||||
auto url = QUrl::fromUserInput(input, working_dir, QUrl::AssumeLocalFile);
|
||||
if (!url.isValid())
|
||||
url = path_to_url(QDir(working_dir).absoluteFilePath(input));
|
||||
return url_normalized(url);
|
||||
|
||||
@@ -200,8 +200,9 @@ WaylandColorBridge::attach(QWindow *window)
|
||||
// (winId changes meaning across Qt versions.)
|
||||
auto *iface = QGuiApplication::platformNativeInterface();
|
||||
if (iface) {
|
||||
this->surface_ = static_cast<wl_surface *>(
|
||||
iface->nativeResourceForWindow(QByteArrayLiteral("surface"), window));
|
||||
this->surface_ =
|
||||
static_cast<wl_surface *>(iface->nativeResourceForWindow(
|
||||
QByteArrayLiteral("surface"), window));
|
||||
}
|
||||
if (!this->display_ || !this->surface_)
|
||||
return;
|
||||
|
||||
@@ -54,8 +54,7 @@ public:
|
||||
explicit WaylandWindow(App *app);
|
||||
~WaylandWindow() override;
|
||||
|
||||
bool initialize(
|
||||
const QUrl &url, BrowseSetup setup = {}, bool browse = false);
|
||||
bool initialize(const QUrl &url, BrowseSetup setup, bool browse);
|
||||
};
|
||||
|
||||
// What Qt's own CSD does on titlebar right-click, in shell-local coordinates.
|
||||
|
||||
+21
-21
@@ -174,8 +174,8 @@ Window::Window(App *app, QWindow *parent) : QWindow(parent), app_(app)
|
||||
// Wants shell-local logical coordinates, while the kit passes
|
||||
// device pixels; we may also hang off the shell by the glow.
|
||||
const qreal dpr = qreal(host_dpr(*this));
|
||||
const QPoint p = position() +
|
||||
QPoint(int(qreal(x) / dpr), int(qreal(y) / dpr));
|
||||
const QPoint p =
|
||||
position() + QPoint(int(qreal(x) / dpr), int(qreal(y) / dpr));
|
||||
wayland_show_window_menu(shell(), p.x(), p.y());
|
||||
};
|
||||
#endif
|
||||
@@ -237,8 +237,7 @@ Window::initialize(const QUrl &url, BrowseSetup setup, bool browse)
|
||||
// TODO: Pass an explicit presentation policy from WaylandWindow instead of
|
||||
// using parenthood as this platform/role proxy.
|
||||
this->renderer_.set_prefer_premultiplied(this->csd_);
|
||||
this->renderer_.set_dither_enabled(
|
||||
!this->app_->settings.disable_dithering);
|
||||
this->renderer_.set_dither_enabled(!this->app_->settings.disable_dithering);
|
||||
if (!this->renderer_.init(
|
||||
this->app_->gpu, this->surface_, pixel_size(),
|
||||
parent() ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_FIFO_KHR,
|
||||
@@ -343,10 +342,10 @@ Window::bind_host()
|
||||
if (!ui || !ui->dialog)
|
||||
break;
|
||||
|
||||
dialog_location(this->kit_, *ui->dialog,
|
||||
[this](const QString &location) {
|
||||
open_any(url_from_user_input(
|
||||
location, QDir::currentPath()));
|
||||
dialog_location(
|
||||
this->kit_, *ui->dialog, [this](const QString &location) {
|
||||
open_any(url_from_user_input(location, QDir::currentPath()),
|
||||
false);
|
||||
});
|
||||
request_render();
|
||||
break;
|
||||
@@ -387,8 +386,8 @@ Window::bind_host()
|
||||
SettingsDraft draft;
|
||||
draft.thumbnail_size = settings.browser_thumbnail_size;
|
||||
draft.show_filenames = settings.browser_show_filenames;
|
||||
draft.icc_profile_path = QString::fromStdString(
|
||||
settings.icc_profile_override_path);
|
||||
draft.icc_profile_path =
|
||||
QString::fromStdString(settings.icc_profile_override_path);
|
||||
draft.disable_dithering = settings.disable_dithering;
|
||||
draft.loaders = settings.loaders;
|
||||
dialog_settings(this->kit_, *ui->dialog, std::move(draft),
|
||||
@@ -437,7 +436,7 @@ Window::bind_host()
|
||||
BrowseSetup setup;
|
||||
if (this->browser_)
|
||||
setup = this->browser_->browse_setup();
|
||||
this->app_->open(url, {}, setup);
|
||||
this->app_->open(url, {}, setup, false);
|
||||
};
|
||||
this->host_.launch_exiftool = [this](QUrl url) { launch_exiftool(url); };
|
||||
this->host_.trash = [this](QUrl url) { trash_url(url); };
|
||||
@@ -681,7 +680,8 @@ Window::refresh_screen_profile(QScreen *target_screen)
|
||||
label = this->app_->settings.icc_profile_override_path;
|
||||
source = "configuration";
|
||||
} else {
|
||||
qWarning("configuration dn/ICCProfileOverride: invalid ICC profile");
|
||||
qWarning(
|
||||
"configuration dn/ICCProfileOverride: invalid ICC profile");
|
||||
}
|
||||
}
|
||||
if (!next) {
|
||||
@@ -697,7 +697,7 @@ Window::refresh_screen_profile(QScreen *target_screen)
|
||||
}
|
||||
}
|
||||
if (!next)
|
||||
next = this->cmm_->get_profile_sRGB();
|
||||
next = this->cmm_->get_profile_sRGB(false);
|
||||
this->screen_profile_fallback_ = source == "srgb";
|
||||
|
||||
const bool changed =
|
||||
@@ -816,7 +816,7 @@ Window::viewer_file_index(const QUrl &url) const
|
||||
{
|
||||
if (!this->browser_ || url.isEmpty())
|
||||
return -1;
|
||||
for (int n = 0; n < int(this->browser_->files_.size()); ++n) {
|
||||
for (int n = 0; n < int(this->browser_->files_.size()); n++) {
|
||||
if (this->browser_->file_url(n) == url)
|
||||
return n;
|
||||
}
|
||||
@@ -1121,7 +1121,7 @@ Window::event(QEvent *event)
|
||||
event->ignore();
|
||||
return true;
|
||||
}
|
||||
open_any(url);
|
||||
open_any(url, false);
|
||||
drop->acceptProposedAction();
|
||||
return true;
|
||||
}
|
||||
@@ -1257,14 +1257,14 @@ Window::open_any(const QUrl &url, bool browse)
|
||||
const QFileInfo info(path);
|
||||
if (info.isDir()) {
|
||||
if (this->browser_)
|
||||
this->browser_->open_dir(url);
|
||||
this->browser_->open_dir(url, true);
|
||||
cancel_viewer_loads();
|
||||
set_mode(Mode::Browser);
|
||||
} else if (browse) {
|
||||
// A file with --browse is a request to point at it, not to view it:
|
||||
// browse the parent and put the cursor on the file.
|
||||
if (this->browser_) {
|
||||
this->browser_->open_dir(path_to_url(info.absolutePath()));
|
||||
this->browser_->open_dir(path_to_url(info.absolutePath()), true);
|
||||
this->browser_->select_file(url);
|
||||
}
|
||||
cancel_viewer_loads();
|
||||
@@ -1277,7 +1277,7 @@ Window::open_any(const QUrl &url, bool browse)
|
||||
const QFileInfo parent(info.absolutePath());
|
||||
if (parent.exists() && parent.isDir() && parent.isReadable())
|
||||
this->browser_->open_dir(
|
||||
path_to_url(parent.absoluteFilePath()));
|
||||
path_to_url(parent.absoluteFilePath()), true);
|
||||
}
|
||||
sync_viewer_preloads();
|
||||
}
|
||||
@@ -1553,8 +1553,8 @@ Window::wheelEvent(QWheelEvent *event)
|
||||
// those should pan, while a real wheel falls through to discrete zooming.
|
||||
if (event->device()->type() == QInputDevice::DeviceType::TouchPad &&
|
||||
(pix.x() || pix.y())) {
|
||||
if (kit_.pan(x, y, float(pix.x()) / kit_.dpr_,
|
||||
float(pix.y()) / kit_.dpr_)) {
|
||||
if (kit_.pan(
|
||||
x, y, float(pix.x()) / kit_.dpr_, float(pix.y()) / kit_.dpr_)) {
|
||||
request_render();
|
||||
event->accept();
|
||||
return;
|
||||
@@ -1655,7 +1655,7 @@ Window::handle_touch(QTouchEvent *event)
|
||||
x1 = float(p.position().x());
|
||||
y1 = float(p.position().y());
|
||||
}
|
||||
++n;
|
||||
n++;
|
||||
}
|
||||
if (event->type() == QEvent::TouchCancel || n < 2) {
|
||||
this->touch_pinch_ = false;
|
||||
|
||||
+4
-5
@@ -22,8 +22,8 @@
|
||||
#include <libdn.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
class QCloseEvent;
|
||||
class QExposeEvent;
|
||||
@@ -142,13 +142,12 @@ protected:
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
|
||||
public:
|
||||
explicit Window(App *app, QWindow *parent = nullptr);
|
||||
explicit Window(App *app, QWindow *parent);
|
||||
~Window() override;
|
||||
|
||||
bool initialize(
|
||||
const QUrl &url, BrowseSetup setup = {}, bool browse = false);
|
||||
bool initialize(const QUrl &url, BrowseSetup setup, bool browse);
|
||||
void shutdown();
|
||||
void open_any(const QUrl &url, bool browse = false);
|
||||
void open_any(const QUrl &url, bool browse);
|
||||
[[nodiscard]] QUrl current_url() const;
|
||||
[[nodiscard]] HostActions &host() { return this->host_; }
|
||||
[[nodiscard]] Page *active_page() { return active_ui(); }
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace dnthumbd {
|
||||
namespace dnthumbd
|
||||
{
|
||||
|
||||
bool encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
bool
|
||||
encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
vector<uint8_t> *out, string *error)
|
||||
{
|
||||
if (!out || !rgba8 || w == 0 || h == 0) {
|
||||
@@ -61,7 +63,7 @@ bool encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
for (uint32_t x = 0; x < w; x++) {
|
||||
const uint8_t *p = src + x * 4;
|
||||
dst[x] = (uint32_t(p[3]) << 24) | (uint32_t(p[0]) << 16) |
|
||||
(uint32_t(p[1]) << 8) | uint32_t(p[2]);
|
||||
(uint32_t(p[1]) << 8) | uint32_t(p[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +75,7 @@ bool encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
if (!WebPEncode(&config, &picture)) {
|
||||
if (error)
|
||||
*error = string("WebPEncode failed (code ") +
|
||||
to_string(int(picture.error_code)) + ")";
|
||||
to_string(int(picture.error_code)) + ")";
|
||||
WebPPictureFree(&picture);
|
||||
WebPMemoryWriterClear(&writer);
|
||||
return false;
|
||||
@@ -94,4 +96,4 @@ bool encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dnthumbd
|
||||
} // namespace dnthumbd
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dnthumbd {
|
||||
namespace dnthumbd
|
||||
{
|
||||
|
||||
bool encode_webp_rgba8(uint32_t w, uint32_t h, const uint8_t *rgba8,
|
||||
std::vector<uint8_t> *out, std::string *error);
|
||||
|
||||
} // namespace dnthumbd
|
||||
} // namespace dnthumbd
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ process_one(const string &path, dawn::ScaleScaler *scaler)
|
||||
ctx.uri = path;
|
||||
// One Cmm per job — do not share get_default() across worker threads.
|
||||
ctx.cmm = make_shared<dawn::Cmm>();
|
||||
ctx.screen_profile = ctx.cmm->get_profile_sRGB();
|
||||
ctx.screen_profile = ctx.cmm->get_profile_sRGB(false);
|
||||
ctx.first_frame_only = true;
|
||||
|
||||
dawn::Error error;
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace dnthumbd {
|
||||
namespace dnthumbd
|
||||
{
|
||||
|
||||
static bool
|
||||
invert_matrix(const dawn::Matrix &m, dawn::Matrix *out)
|
||||
|
||||
+5
-3
@@ -9,9 +9,11 @@
|
||||
|
||||
#include "libdn.h"
|
||||
|
||||
namespace dnthumbd {
|
||||
namespace dnthumbd
|
||||
{
|
||||
|
||||
/// Bake EXIF orientation into image.data (BGRA16 premul); set orientation Rotate0.
|
||||
/// Bake EXIF orientation into image.data (BGRA16 premul); set orientation
|
||||
/// Rotate0.
|
||||
bool bake_orientation(dawn::Image &image);
|
||||
|
||||
} // namespace dnthumbd
|
||||
} // namespace dnthumbd
|
||||
|
||||
+40
-20
@@ -41,17 +41,27 @@ desktop_unescape(string_view value)
|
||||
{
|
||||
string out;
|
||||
out.reserve(value.size());
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
for (size_t i = 0; i < value.size(); i++) {
|
||||
if (value[i] != '\\' || i + 1 == value.size()) {
|
||||
out += value[i];
|
||||
continue;
|
||||
}
|
||||
switch (value[++i]) {
|
||||
case 'n': out += '\n'; break;
|
||||
case 'r': out += '\r'; break;
|
||||
case 't': out += '\t'; break;
|
||||
case 's': out += ' '; break;
|
||||
default: out += value[i]; break;
|
||||
case 'n':
|
||||
out += '\n';
|
||||
break;
|
||||
case 'r':
|
||||
out += '\r';
|
||||
break;
|
||||
case 't':
|
||||
out += '\t';
|
||||
break;
|
||||
case 's':
|
||||
out += ' ';
|
||||
break;
|
||||
default:
|
||||
out += value[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
@@ -64,11 +74,21 @@ desktop_escape(string_view value)
|
||||
out.reserve(value.size());
|
||||
for (const char c : value) {
|
||||
switch (c) {
|
||||
case '\\': out += "\\\\"; break;
|
||||
case '\n': out += "\\n"; break;
|
||||
case '\r': out += "\\r"; break;
|
||||
case '\t': out += "\\t"; break;
|
||||
default: out += c; break;
|
||||
case '\\':
|
||||
out += "\\\\";
|
||||
break;
|
||||
case '\n':
|
||||
out += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
out += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
out += "\\t";
|
||||
break;
|
||||
default:
|
||||
out += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
@@ -81,16 +101,15 @@ ini_parse(string_view text)
|
||||
IniGroup *group = nullptr;
|
||||
for (size_t offset = 0; offset <= text.size();) {
|
||||
const size_t end = text.find_first_of("\r\n", offset);
|
||||
string line(text.substr(offset,
|
||||
end == string::npos ? string::npos : end - offset));
|
||||
string line(text.substr(
|
||||
offset, end == string::npos ? string::npos : end - offset));
|
||||
const string stripped = trim(line);
|
||||
if (stripped.empty() || stripped[0] == '#') {
|
||||
if (!group)
|
||||
ini.preamble.push_back(line);
|
||||
} else if (stripped.size() >= 2 && stripped.front() == '[' &&
|
||||
stripped.back() == ']' && stripped.find('=') == string::npos) {
|
||||
ini.groups.push_back(
|
||||
{stripped.substr(1, stripped.size() - 2), {}});
|
||||
ini.groups.push_back({stripped.substr(1, stripped.size() - 2), {}});
|
||||
group = &ini.groups.back();
|
||||
} else if (group) {
|
||||
const size_t equals = line.find('=');
|
||||
@@ -103,8 +122,8 @@ ini_parse(string_view text)
|
||||
break;
|
||||
offset = end +
|
||||
(text[end] == '\r' && end + 1 < text.size() && text[end + 1] == '\n'
|
||||
? 2
|
||||
: 1);
|
||||
? 2
|
||||
: 1);
|
||||
}
|
||||
return ini;
|
||||
}
|
||||
@@ -161,8 +180,8 @@ split_key(string_view key)
|
||||
const size_t slash = key.rfind('/');
|
||||
if (slash == string_view::npos || slash == 0 || slash + 1 == key.size())
|
||||
return nullopt;
|
||||
return pair<string, string>{string(key.substr(0, slash)),
|
||||
string(key.substr(slash + 1))};
|
||||
return pair<string, string>{
|
||||
string(key.substr(0, slash)), string(key.substr(slash + 1))};
|
||||
}
|
||||
|
||||
static fs::path
|
||||
@@ -195,7 +214,8 @@ load_ini(const fs::path &path, Error *error)
|
||||
fail(error, "cannot open configuration file");
|
||||
return nullopt;
|
||||
}
|
||||
string text((istreambuf_iterator<char>(input)), istreambuf_iterator<char>());
|
||||
string text(
|
||||
(istreambuf_iterator<char>(input)), istreambuf_iterator<char>());
|
||||
if (input.bad()) {
|
||||
fail(error, "cannot read configuration file");
|
||||
return nullopt;
|
||||
|
||||
+5
-5
@@ -134,7 +134,7 @@ Decoder::take_be(uint64_t &v, size_t width)
|
||||
if (remaining() < width)
|
||||
return fail(DecodeError::Truncated);
|
||||
uint64_t x = 0;
|
||||
for (size_t i = 0; i < width; ++i)
|
||||
for (size_t i = 0; i < width; i++)
|
||||
x = (x << 8) | uint8_t(in_[off_ + i]);
|
||||
off_ += width;
|
||||
v = x;
|
||||
@@ -290,7 +290,7 @@ utf8_validate(string_view s)
|
||||
while (p < end) {
|
||||
const uint8_t c = *p;
|
||||
if (c <= 0x7F) {
|
||||
++p;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
int extra = 0;
|
||||
@@ -313,12 +313,12 @@ utf8_validate(string_view s)
|
||||
}
|
||||
if (end - p < extra + 1)
|
||||
return false;
|
||||
++p;
|
||||
for (int i = 0; i < extra; ++i) {
|
||||
p++;
|
||||
for (int i = 0; i < extra; i++) {
|
||||
if ((*p & 0xC0) != 0x80)
|
||||
return false;
|
||||
cp = (cp << 6) | (*p & 0x3F);
|
||||
++p;
|
||||
p++;
|
||||
}
|
||||
if (cp < min_cp || cp > 0x10FFFF || (cp >= 0xD800 && cp <= 0xDFFF))
|
||||
return false;
|
||||
|
||||
@@ -19,8 +19,7 @@ inline thread_local OpenTiming *open_timing = nullptr;
|
||||
|
||||
struct OpenTimingGuard {
|
||||
OpenTiming *prev;
|
||||
explicit OpenTimingGuard(OpenTiming *t)
|
||||
: prev(open_timing)
|
||||
explicit OpenTimingGuard(OpenTiming *t) : prev(open_timing)
|
||||
{
|
||||
open_timing = t;
|
||||
}
|
||||
|
||||
+13
-11
@@ -515,7 +515,8 @@ ensure_working_premul(
|
||||
if (owned)
|
||||
image.effective_profile = owned;
|
||||
else if (!source) {
|
||||
image.effective_profile = cmm_or_default(ctx)->get_profile_sRGB();
|
||||
image.effective_profile =
|
||||
cmm_or_default(ctx)->get_profile_sRGB(false);
|
||||
image.profile_assumed = true;
|
||||
}
|
||||
}
|
||||
@@ -543,7 +544,8 @@ ensure_working_premul_pages(
|
||||
if (owned)
|
||||
page.effective_profile = owned;
|
||||
else if (!source) {
|
||||
page.effective_profile = cmm_or_default(ctx)->get_profile_sRGB();
|
||||
page.effective_profile =
|
||||
cmm_or_default(ctx)->get_profile_sRGB(false);
|
||||
page.profile_assumed = true;
|
||||
}
|
||||
}
|
||||
@@ -689,7 +691,7 @@ constexpr float kTransferMaxErr = 1.5f / 65535.f;
|
||||
static bool
|
||||
curve_matches(const cmsToneCurve *curve, Transfer transfer)
|
||||
{
|
||||
for (int i = 0; i < kTransferSamples; ++i) {
|
||||
for (int i = 0; i < kTransferSamples; i++) {
|
||||
const float x = float(i) / float(kTransferSamples - 1);
|
||||
const float y = cmsEvalToneCurveFloat(curve, x);
|
||||
if (fabsf(y - transfer_decode(x, transfer)) > kTransferMaxErr)
|
||||
@@ -794,7 +796,7 @@ profile_chromaticities(const Profile *profile)
|
||||
};
|
||||
const uint8_t paper[4] = {0, 0, 0, 0};
|
||||
c.have_white = xf_xy(xf, paper, &c.wx, &c.wy);
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (!xf_xy(xf, corners[i], &c.x[i], &c.y[i])) {
|
||||
cmsDeleteTransform(xf);
|
||||
return c;
|
||||
@@ -818,7 +820,7 @@ profile_chromaticities(const Profile *profile)
|
||||
};
|
||||
const uint8_t white[3] = {255, 255, 255};
|
||||
c.have_white = xf_xy(xf, white, &c.wx, &c.wy);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (!xf_xy(xf, corners[i], &c.x[i], &c.y[i])) {
|
||||
cmsDeleteTransform(xf);
|
||||
return c;
|
||||
@@ -930,7 +932,7 @@ Cmm::get_profile_display_p3(bool cache)
|
||||
|
||||
constexpr size_t samples = 4096;
|
||||
vector<cmsUInt16Number> transfer(samples);
|
||||
for (size_t i = 0; i < samples; ++i) {
|
||||
for (size_t i = 0; i < samples; i++) {
|
||||
const double encoded = double(i) / double(samples - 1);
|
||||
const double linear = encoded <= 0.04045
|
||||
? encoded / 12.92
|
||||
@@ -1119,7 +1121,7 @@ Cmm::transform_bgra16(uint8_t *data, uint32_t width, uint32_t height,
|
||||
{
|
||||
shared_ptr<Profile> src_fallback;
|
||||
if (target && !source) {
|
||||
src_fallback = get_profile_sRGB();
|
||||
src_fallback = get_profile_sRGB(false);
|
||||
source = src_fallback.get();
|
||||
}
|
||||
if (!source || !target)
|
||||
@@ -1140,7 +1142,7 @@ Cmm::transform_bgra8_to_bgra16(const uint8_t *src, uint8_t *dst, uint32_t width,
|
||||
{
|
||||
shared_ptr<Profile> src_fallback;
|
||||
if (target && !source) {
|
||||
src_fallback = get_profile_sRGB();
|
||||
src_fallback = get_profile_sRGB(false);
|
||||
source = src_fallback.get();
|
||||
}
|
||||
if (!src || !dst || !source || !target)
|
||||
@@ -1216,7 +1218,7 @@ Cmm::finish_page(Image &page, Profile *target)
|
||||
if (source)
|
||||
page.effective_profile = source;
|
||||
else {
|
||||
page.effective_profile = get_profile_sRGB();
|
||||
page.effective_profile = get_profile_sRGB(false);
|
||||
page.profile_assumed = true;
|
||||
}
|
||||
}
|
||||
@@ -1696,7 +1698,7 @@ constexpr Loader kLoaders[] = {
|
||||
|
||||
// A subset of shared-mime-info, chiefly motivated by the suckiness of raw
|
||||
// photo formats: someone else will maintain the list of file extensions for us.
|
||||
std::vector<std::string>
|
||||
vector<string>
|
||||
supported_media_types()
|
||||
{
|
||||
vector<string> types;
|
||||
@@ -1717,7 +1719,7 @@ supported_media_types()
|
||||
return types;
|
||||
}
|
||||
|
||||
std::span<const Loader>
|
||||
span<const Loader>
|
||||
loaders()
|
||||
{
|
||||
return kLoaders;
|
||||
|
||||
+7
-20
@@ -78,18 +78,13 @@ struct Error {
|
||||
Code code = Code::Ok;
|
||||
std::string message;
|
||||
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return code != Code::Ok;
|
||||
}
|
||||
explicit operator bool() const { return code != Code::Ok; }
|
||||
};
|
||||
|
||||
/// Read and write an opaque application configuration value.
|
||||
/// A missing value is not an error and returns std::nullopt.
|
||||
std::optional<std::string> config_get(std::string_view key, Error *error = nullptr);
|
||||
bool config_set(
|
||||
std::string_view key, std::string_view value, Error *error = nullptr);
|
||||
std::optional<std::string> config_get(std::string_view key, Error *error);
|
||||
bool config_set(std::string_view key, std::string_view value, Error *error);
|
||||
|
||||
// TODO(p): Why in Hell is this called detail, and what should it be called?
|
||||
namespace detail
|
||||
@@ -269,8 +264,8 @@ public:
|
||||
|
||||
std::shared_ptr<Profile> get_profile(const void *data, size_t len);
|
||||
std::shared_ptr<Profile> get_profile(std::span<const uint8_t> bytes);
|
||||
std::shared_ptr<Profile> get_profile_sRGB(bool cache = false);
|
||||
std::shared_ptr<Profile> get_profile_display_p3(bool cache = false);
|
||||
std::shared_ptr<Profile> get_profile_sRGB(bool cache);
|
||||
std::shared_ptr<Profile> get_profile_display_p3(bool cache);
|
||||
std::shared_ptr<Profile> get_profile_sRGB_gamma(double gamma);
|
||||
std::shared_ptr<Profile> get_profile_parametric(
|
||||
double gamma, double whitepoint[2], double primaries[6]);
|
||||
@@ -306,16 +301,8 @@ public:
|
||||
void finish_page(Image &page, Profile *target);
|
||||
ImagePtr finish(ImagePtr image, Profile *target);
|
||||
|
||||
bool
|
||||
broken_premul() const
|
||||
{
|
||||
return broken_premul_;
|
||||
}
|
||||
void *
|
||||
context()
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
bool broken_premul() const { return broken_premul_; }
|
||||
void *context() { return context_; }
|
||||
};
|
||||
|
||||
struct OpenContext {
|
||||
|
||||
+10
-7
@@ -12,17 +12,19 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dawn {
|
||||
namespace dawn
|
||||
{
|
||||
|
||||
/// Soft cap on device-local bytes for one scale() (tiles + mid + dest).
|
||||
/// Tweak in source; no CLI yet.
|
||||
inline constexpr uint64_t kMaxDeviceBytes = 4ull << 30;
|
||||
|
||||
} // namespace dawn
|
||||
} // namespace dawn
|
||||
|
||||
#include "scale-engine.hpp"
|
||||
|
||||
namespace dawn {
|
||||
namespace dawn
|
||||
{
|
||||
|
||||
struct ScaleOutput {
|
||||
uint32_t width = 0;
|
||||
@@ -32,7 +34,8 @@ struct ScaleOutput {
|
||||
};
|
||||
|
||||
/// Headless Vulkan H→V scaler. `scale()` is internally mutex-serialized.
|
||||
class ScaleScaler {
|
||||
class ScaleScaler
|
||||
{
|
||||
struct Impl;
|
||||
Impl *impl_ = nullptr;
|
||||
|
||||
@@ -43,14 +46,14 @@ public:
|
||||
ScaleScaler(const ScaleScaler &) = delete;
|
||||
ScaleScaler &operator=(const ScaleScaler &) = delete;
|
||||
|
||||
bool init(std::string *error = nullptr);
|
||||
bool init(std::string *error);
|
||||
void destroy();
|
||||
|
||||
/// `pixels` is BGRA_PREMUL_4X16LE; `stride` bytes per row.
|
||||
/// Scales to exactly `out_w`×`out_h` with sRGB-aware filtering.
|
||||
bool scale(uint32_t src_w, uint32_t src_h, const uint8_t *pixels,
|
||||
size_t stride, uint32_t out_w, uint32_t out_h, ScaleOutput *out,
|
||||
std::string *error = nullptr);
|
||||
std::string *error);
|
||||
};
|
||||
|
||||
} // namespace dawn
|
||||
} // namespace dawn
|
||||
|
||||
+2
-2
@@ -204,7 +204,7 @@ parse_exif_profile(Cmm &cmm, span<const uint8_t> exif)
|
||||
|
||||
// If sRGB is claimed, assume all parameters are standard.
|
||||
if (params.colorspace == Exif_ColorSpace_sRGB)
|
||||
return cmm.get_profile_sRGB();
|
||||
return cmm.get_profile_sRGB(false);
|
||||
|
||||
// AdobeRGB Nikon JPEGs provide all of these.
|
||||
if (params.colorspace != Exif_ColorSpace_Uncalibrated ||
|
||||
@@ -555,7 +555,7 @@ load_jpeg_finalize(ImagePtr &image, bool cmyk, bool argb, int bits,
|
||||
if (source)
|
||||
image->effective_profile = source;
|
||||
else if (!cmyk) {
|
||||
image->effective_profile = cmm->get_profile_sRGB();
|
||||
image->effective_profile = cmm->get_profile_sRGB(false);
|
||||
image->profile_assumed = true;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -704,8 +704,8 @@ ScaleEngine::Impl::upload_tiles(const uint8_t *pixels, size_t stride,
|
||||
|
||||
VkMemoryRequirements mr{};
|
||||
vkGetImageMemoryRequirements(device, tile_image, &mr);
|
||||
uint32_t mem_type = vk_memory_type(
|
||||
phys, mr.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error);
|
||||
uint32_t mem_type = vk_memory_type(phys, mr.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error, nullptr);
|
||||
if (mem_type == UINT32_MAX)
|
||||
return false;
|
||||
VkMemoryAllocateInfo mai{
|
||||
@@ -763,7 +763,7 @@ ScaleEngine::Impl::upload_tiles(const uint8_t *pixels, size_t stride,
|
||||
mem_type = vk_memory_type(phys, smr.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
error);
|
||||
error, nullptr);
|
||||
if (mem_type == UINT32_MAX) {
|
||||
vkDestroyBuffer(device, staging, nullptr);
|
||||
return false;
|
||||
@@ -983,8 +983,8 @@ ScaleEngine::Impl::ensure_mid(uint32_t vp_w, uint32_t src_h, string *error)
|
||||
|
||||
VkMemoryRequirements mr{};
|
||||
vkGetImageMemoryRequirements(device, mid_image, &mr);
|
||||
uint32_t mem_type = vk_memory_type(
|
||||
phys, mr.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error);
|
||||
uint32_t mem_type = vk_memory_type(phys, mr.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error, nullptr);
|
||||
if (mem_type == UINT32_MAX)
|
||||
return false;
|
||||
VkMemoryAllocateInfo mai{
|
||||
@@ -1170,7 +1170,7 @@ ScaleEngine::Impl::cmd_h_pass(
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline_layout_tiles, 0, 1, &dset_tiles, 0, nullptr);
|
||||
vkCmdPushConstants(cmd, pipeline_layout_tiles, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(pc), &pc);
|
||||
0, sizeof pc, &pc);
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
vkCmdEndRenderPass(cmd);
|
||||
}
|
||||
@@ -1246,7 +1246,7 @@ ScaleEngine::Impl::cmd_v_pass(VkCommandBuffer cmd, const PushConstants &pc,
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline_layout_horiz, 0, 1, &dset_horiz, 0, nullptr);
|
||||
vkCmdPushConstants(cmd, pipeline_layout_horiz, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(pc), &pc);
|
||||
0, sizeof pc, &pc);
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
vkCmdEndRenderPass(cmd);
|
||||
}
|
||||
@@ -1284,7 +1284,7 @@ ScaleEngine::Impl::cmd_2d_pass(VkCommandBuffer cmd, const PushConstants &pc,
|
||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline_layout_tiles, 0, 1, &dset_tiles, 0, nullptr);
|
||||
vkCmdPushConstants(cmd, pipeline_layout_tiles, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(pc), &pc);
|
||||
0, sizeof pc, &pc);
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
vkCmdEndRenderPass(cmd);
|
||||
}
|
||||
@@ -1706,8 +1706,8 @@ ScaleEngine::create_offscreen(uint32_t w, uint32_t h, VkImage *image,
|
||||
|
||||
VkMemoryRequirements mr{};
|
||||
vkGetImageMemoryRequirements(e.device, *image, &mr);
|
||||
uint32_t mem_type = vk_memory_type(
|
||||
e.phys, mr.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error);
|
||||
uint32_t mem_type = vk_memory_type(e.phys, mr.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, error, nullptr);
|
||||
if (mem_type == UINT32_MAX) {
|
||||
destroy_offscreen(image, mem, view, fb);
|
||||
return false;
|
||||
|
||||
@@ -65,11 +65,11 @@ public:
|
||||
/// readback.
|
||||
bool init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
uint32_t queue_family, VkFormat dest_format,
|
||||
VkImageLayout dest_final_layout, std::string *error = nullptr);
|
||||
VkImageLayout dest_final_layout, std::string *error);
|
||||
void destroy();
|
||||
|
||||
bool set_image(uint32_t w, uint32_t h, const uint8_t *pixels, size_t stride,
|
||||
std::string *error = nullptr);
|
||||
std::string *error);
|
||||
void clear_image();
|
||||
|
||||
[[nodiscard]] uint32_t image_width() const;
|
||||
@@ -77,21 +77,21 @@ public:
|
||||
[[nodiscard]] bool has_image() const;
|
||||
|
||||
bool ensure_viewport(
|
||||
uint32_t viewport_w, uint32_t viewport_h, std::string *error = nullptr);
|
||||
uint32_t viewport_w, uint32_t viewport_h, std::string *error);
|
||||
void set_dest_inset(
|
||||
uint32_t left, uint32_t top, uint32_t right, uint32_t bottom);
|
||||
|
||||
bool record(VkCommandBuffer cmd, VkFramebuffer dest_fb, uint32_t viewport_w,
|
||||
uint32_t viewport_h, const ScaleView &view, const float clear_rgba[4],
|
||||
std::string *error = nullptr);
|
||||
std::string *error);
|
||||
/// Dest-pass CLEAR only (no H/V). For presenting the well with no pixmap.
|
||||
bool record_clear(VkCommandBuffer cmd, VkFramebuffer dest_fb,
|
||||
uint32_t viewport_w, uint32_t viewport_h, const float clear_rgba[4],
|
||||
std::string *error = nullptr);
|
||||
std::string *error);
|
||||
|
||||
bool create_offscreen(uint32_t w, uint32_t h, VkImage *image,
|
||||
VkDeviceMemory *mem, VkImageView *view, VkFramebuffer *fb,
|
||||
std::string *error = nullptr);
|
||||
std::string *error);
|
||||
void destroy_offscreen(VkImage *image, VkDeviceMemory *mem,
|
||||
VkImageView *view, VkFramebuffer *fb);
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ ScaleScaler::Impl::readback_dest(VkImage image, uint32_t out_w, uint32_t out_h,
|
||||
uint32_t mem_type = vk_memory_type(phys, mr.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
error);
|
||||
error, nullptr);
|
||||
if (mem_type == UINT32_MAX) {
|
||||
vkDestroyBuffer(device, staging, nullptr);
|
||||
return false;
|
||||
|
||||
+15
-15
@@ -91,7 +91,7 @@ pick_memory(VkPhysicalDevice phys, uint32_t bits,
|
||||
vkGetPhysicalDeviceMemoryProperties(phys, &props);
|
||||
MemoryType best;
|
||||
int best_score = -1;
|
||||
for (uint32_t i = 0; i < props.memoryTypeCount; ++i) {
|
||||
for (uint32_t i = 0; i < props.memoryTypeCount; i++) {
|
||||
if (!(bits & (1u << i)))
|
||||
continue;
|
||||
const auto flags = props.memoryTypes[i].propertyFlags;
|
||||
@@ -471,7 +471,7 @@ bool
|
||||
ThumbScaler::Impl::alloc_range(uint64_t bytes, Slot *slot)
|
||||
{
|
||||
bytes = align_up(bytes, alignment);
|
||||
for (size_t i = 0; i < free_ranges.size(); ++i) {
|
||||
for (size_t i = 0; i < free_ranges.size(); i++) {
|
||||
Range &r = free_ranges[i];
|
||||
if (r.size < bytes)
|
||||
continue;
|
||||
@@ -548,7 +548,7 @@ ThumbScaler::Impl::choose_k_impl(uint32_t w, uint32_t h, uint32_t *out) const
|
||||
{
|
||||
if (!w || !h || !out || !max_image_dim)
|
||||
return false;
|
||||
for (uint32_t k = 0; k < 32; ++k) {
|
||||
for (uint32_t k = 0; k < 32; k++) {
|
||||
const uint32_t rw = reduced_dim(w, k), rh = reduced_dim(h, k);
|
||||
const uint64_t bytes = uint64_t(rw) * rh * kBytesPerPixel;
|
||||
if (rw <= max_image_dim && rh <= max_image_dim &&
|
||||
@@ -645,7 +645,7 @@ ThumbScaler::Impl::descriptor(Batch &b, const Buffer &in, VkDeviceSize in_off,
|
||||
VkDescriptorBufferInfo info[2] = {
|
||||
{in.handle, in_off, in_size}, {out.handle, out_off, out_size}};
|
||||
VkWriteDescriptorSet writes[2]{};
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
writes[i].dstSet = set;
|
||||
writes[i].dstBinding = i;
|
||||
@@ -690,7 +690,7 @@ ThumbScaler::Impl::record_reduce(
|
||||
const Buffer *input = &b.source;
|
||||
VkDeviceSize input_off = item.source_off;
|
||||
bool linear = false;
|
||||
for (uint32_t level = 0; level < s.info.k; ++level) {
|
||||
for (uint32_t level = 0; level < s.info.k; level++) {
|
||||
const uint32_t dw = ceil_div(sw, 2), dh = ceil_div(sh, 2);
|
||||
const bool last = level + 1 == s.info.k;
|
||||
Buffer *output = last ? &s.reduced : ((level & 1u) ? &b.pong : &b.ping);
|
||||
@@ -706,7 +706,7 @@ ThumbScaler::Impl::record_reduce(
|
||||
last ? item.req.tile_ox >> s.info.k : 0,
|
||||
last ? item.req.tile_oy >> s.info.k : 0, uint32_t(s.info.transfer),
|
||||
s.info.opaque ? 1u : 0u, linear ? 1u : 0u};
|
||||
dispatch(b.cmd, reduce, set, &push, sizeof(push), dw, dh);
|
||||
dispatch(b.cmd, reduce, set, &push, sizeof push, dw, dh);
|
||||
barrier(b.cmd, VK_ACCESS_SHADER_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
@@ -749,7 +749,7 @@ ThumbScaler::Impl::record_h(Batch &b, Item &item, string *error)
|
||||
uint32_t(orientation_or_0(item.req.orientation)),
|
||||
uint32_t(item.req.transfer), item.req.opaque ? 1u : 0u,
|
||||
linear ? 1u : 0u};
|
||||
dispatch(b.cmd, scale_h, set, &push, sizeof(push), item.req.out_w,
|
||||
dispatch(b.cmd, scale_h, set, &push, sizeof push, item.req.out_w,
|
||||
item.display_h);
|
||||
return true;
|
||||
}
|
||||
@@ -770,7 +770,7 @@ ThumbScaler::Impl::record_v(Batch &b, Item &item, string *error)
|
||||
item.req.out_h, item.req.out_w, item.req.out_w,
|
||||
uint32_t(orientation_or_0(item.req.orientation)),
|
||||
uint32_t(item.req.transfer), item.req.opaque ? 1u : 0u, 0};
|
||||
dispatch(b.cmd, scale_v, set, &push, sizeof(push), item.req.out_w,
|
||||
dispatch(b.cmd, scale_v, set, &push, sizeof push, item.req.out_w,
|
||||
item.req.out_h);
|
||||
return true;
|
||||
}
|
||||
@@ -1070,7 +1070,7 @@ ThumbScaler::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
e.destroy_all();
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < kBatchSlots; ++i) {
|
||||
for (uint32_t i = 0; i < kBatchSlots; i++) {
|
||||
e.batches[i].cmd = commands[i];
|
||||
VkFenceCreateInfo fi{.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
||||
if (!check_vk(vkCreateFence(device, &fi, nullptr, &e.batches[i].fence),
|
||||
@@ -1081,7 +1081,7 @@ ThumbScaler::init(VkPhysicalDevice phys, VkDevice device, VkQueue queue,
|
||||
}
|
||||
}
|
||||
VkDescriptorSetLayoutBinding bindings[2]{};
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
bindings[i].binding = i;
|
||||
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[i].descriptorCount = 1;
|
||||
@@ -1261,12 +1261,12 @@ ThumbScaler::Impl::queue_full(const Job &job)
|
||||
bool opaque = true;
|
||||
auto *dst = static_cast<uint8_t *>(slot.mapped);
|
||||
const auto *src = reinterpret_cast<const uint8_t *>(job.pixels->data());
|
||||
for (uint32_t y = 0; y < job.src_h; ++y) {
|
||||
for (uint32_t y = 0; y < job.src_h; y++) {
|
||||
const auto *row =
|
||||
reinterpret_cast<const uint16_t *>(src + y * job.stride);
|
||||
memcpy(dst, row, size_t(row_bytes));
|
||||
if (opaque) {
|
||||
for (uint32_t x = 0; x < job.src_w; ++x) {
|
||||
for (uint32_t x = 0; x < job.src_w; x++) {
|
||||
if (row[x * 4 + 3] != 65535) {
|
||||
opaque = false;
|
||||
break;
|
||||
@@ -1341,7 +1341,7 @@ ThumbScaler::queue(const Job &job)
|
||||
if (!e.claim(tile_row * tile.h, job.user, job.priority, &slot))
|
||||
break;
|
||||
auto *dst = static_cast<uint8_t *>(slot.mapped);
|
||||
for (uint32_t y = 0; y < tile.h; ++y) {
|
||||
for (uint32_t y = 0; y < tile.h; y++) {
|
||||
const uint8_t *src = base + size_t(tile.oy + y) * job.stride +
|
||||
size_t(tile.ox) * kBytesPerPixel;
|
||||
memcpy(dst, src, tile_row);
|
||||
@@ -1412,7 +1412,7 @@ ThumbScaler::cancel(uint64_t user)
|
||||
e.canceled.insert(user);
|
||||
for (auto it = e.pending.begin(); it != e.pending.end();) {
|
||||
if (it->req.user != user) {
|
||||
++it;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
@@ -1474,7 +1474,7 @@ ThumbScaler::flush()
|
||||
it = e.pending.erase(it);
|
||||
item_room -= cost;
|
||||
} else {
|
||||
++it;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
for (auto &entry : e.sessions) {
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ vk_memory_type(VkPhysicalDevice phys, uint32_t bits,
|
||||
VkPhysicalDeviceMemoryProperties properties{};
|
||||
vkGetPhysicalDeviceMemoryProperties(phys, &properties);
|
||||
uint32_t best = UINT32_MAX;
|
||||
for (uint32_t i = 0; i < properties.memoryTypeCount; ++i) {
|
||||
for (uint32_t i = 0; i < properties.memoryTypeCount; i++) {
|
||||
if (!(bits & (1u << i)) ||
|
||||
(properties.memoryTypes[i].propertyFlags & flags) != flags)
|
||||
continue;
|
||||
|
||||
+1
-2
@@ -26,8 +26,7 @@ namespace dawn
|
||||
void vk_add_bundled_driver_files();
|
||||
|
||||
uint32_t vk_memory_type(VkPhysicalDevice phys, uint32_t bits,
|
||||
VkMemoryPropertyFlags flags, std::string *error = nullptr,
|
||||
VkDeviceSize *heap_size = nullptr);
|
||||
VkMemoryPropertyFlags flags, std::string *error, VkDeviceSize *heap_size);
|
||||
|
||||
bool vk_create_graphics_device(VkInstance instance, VkSurfaceKHR surface,
|
||||
std::function<bool(VkPhysicalDevice, uint32_t)> present,
|
||||
|
||||
+7
-10
@@ -33,8 +33,7 @@ usage(const char *argv0)
|
||||
static void
|
||||
fit_size(uint32_t w, uint32_t h, uint32_t *out_w, uint32_t *out_h)
|
||||
{
|
||||
const float scale =
|
||||
min(1.0f, min(512.0f / float(w), 256.0f / float(h)));
|
||||
const float scale = min(1.0f, min(512.0f / float(w), 256.0f / float(h)));
|
||||
*out_w = max(1u, uint32_t(float(w) * scale + 0.5f));
|
||||
*out_h = max(1u, uint32_t(float(h) * scale + 0.5f));
|
||||
}
|
||||
@@ -48,7 +47,7 @@ bench_one(const char *path, bool cms, int repeats, dawn::ScaleScaler *scaler)
|
||||
ctx.first_frame_only = true;
|
||||
ctx.uri = path;
|
||||
if (cms) {
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
if (!srgb) {
|
||||
fprintf(stderr, "%s: get_profile_sRGB failed\n", path);
|
||||
return 1;
|
||||
@@ -70,15 +69,13 @@ bench_one(const char *path, bool cms, int repeats, dawn::ScaleScaler *scaler)
|
||||
rc = 1;
|
||||
continue;
|
||||
}
|
||||
const double open_ms =
|
||||
chrono::duration<double, milli>(t1 - t0).count();
|
||||
const double open_ms = chrono::duration<double, milli>(t1 - t0).count();
|
||||
const double rest_ms = open_ms - st.file_ms - st.decode_ms -
|
||||
st.alloc_ms - st.cms_ms - st.widen_ms;
|
||||
if (repeats > 1)
|
||||
printf("%d ", i + 1);
|
||||
printf(
|
||||
"file %.1f decode %.1f alloc %.1f cms %.1f widen %.1f "
|
||||
"rest %.1f open %.1f %ux%u %s",
|
||||
printf("file %.1f decode %.1f alloc %.1f cms %.1f widen %.1f "
|
||||
"rest %.1f open %.1f %ux%u %s",
|
||||
st.file_ms, st.decode_ms, st.alloc_ms, st.cms_ms, st.widen_ms,
|
||||
rest_ms, open_ms, img->width, img->height, path);
|
||||
if (scaler) {
|
||||
@@ -97,8 +94,8 @@ bench_one(const char *path, bool cms, int repeats, dawn::ScaleScaler *scaler)
|
||||
rc = 1;
|
||||
continue;
|
||||
}
|
||||
printf(" scale %.1f %ux%u\n", scale_ms, scaled.width,
|
||||
scaled.height);
|
||||
printf(
|
||||
" scale %.1f %ux%u\n", scale_ms, scaled.width, scaled.height);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ create_display_p3_profile()
|
||||
{
|
||||
constexpr size_t samples = 4096;
|
||||
vector<cmsUInt16Number> transfer(samples);
|
||||
for (size_t i = 0; i < samples; ++i) {
|
||||
for (size_t i = 0; i < samples; i++) {
|
||||
const double encoded = double(i) / double(samples - 1);
|
||||
const double linear = encoded <= 0.04045
|
||||
? encoded / 12.92
|
||||
@@ -179,9 +179,9 @@ write_display_p3_vs_srgb_red(const fs::path &path)
|
||||
|
||||
vector<uint8_t> raw;
|
||||
raw.reserve(100 * (1 + 200 * 3));
|
||||
for (int y = 0; y < 100; ++y) {
|
||||
for (int y = 0; y < 100; y++) {
|
||||
raw.push_back(0);
|
||||
for (int x = 0; x < 200; ++x) {
|
||||
for (int x = 0; x < 200; x++) {
|
||||
const uint8_t *color = x < 100 ? p3_red : srgb_red_in_p3;
|
||||
raw.insert(raw.end(), color, color + 3);
|
||||
}
|
||||
@@ -386,7 +386,7 @@ write_cmyk_lab_icc(const fs::path &path)
|
||||
cmsWriteTag(h, cmsSigMediaWhitePointTag, &d50);
|
||||
|
||||
cmsUInt16Number tab[16 * 3];
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
tab[i * 3 + 0] = 0xFFFF;
|
||||
tab[i * 3 + 1] = 0x8080;
|
||||
tab[i * 3 + 2] = 0x8080;
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Application
|
||||
}
|
||||
|
||||
public:
|
||||
Application(int &argc, char **argv, const char *name = nullptr)
|
||||
Application(int &argc, char **argv, const char *name)
|
||||
: app_(prepare(argc, cache_, inputs_), argv)
|
||||
{
|
||||
if (name)
|
||||
|
||||
@@ -117,7 +117,7 @@ test_pack_helpers()
|
||||
{
|
||||
// Host-endian 0xAARRGGBB: opaque red
|
||||
const uint32_t word = 0xFFFF0000u;
|
||||
dawn::pack_argb32_words_to_bgra16(*img, &word, sizeof(word));
|
||||
dawn::pack_argb32_words_to_bgra16(*img, &word, sizeof word);
|
||||
expect_bgra("pack_argb32 red", pixel0(*img), 0, 0, 65535, 65535, 0);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ static void
|
||||
test_jpeg_cms_8_to_16()
|
||||
{
|
||||
auto cmm = dawn::Cmm::get_default();
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
CHECK(srgb != nullptr);
|
||||
|
||||
const uint8_t src[4] = {0, 0, 255, 255};
|
||||
@@ -254,7 +254,7 @@ static void
|
||||
test_cmyk_cms_opaque()
|
||||
{
|
||||
auto cmm = dawn::Cmm::get_default();
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
CHECK(srgb != nullptr);
|
||||
|
||||
const fs::path icc = fs::path(DAWN_TEST_FIXTURES_DIR) / "cmyk-lab.icc";
|
||||
@@ -281,7 +281,7 @@ static void
|
||||
test_cms_tiled()
|
||||
{
|
||||
auto cmm = dawn::Cmm::get_default();
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
CHECK(srgb != nullptr);
|
||||
|
||||
// Above the serial threshold so row bands run on more than one worker.
|
||||
@@ -451,7 +451,7 @@ test_chromaticities()
|
||||
dawn::ColorModel::Unknown);
|
||||
|
||||
auto cmm = dawn::Cmm::get_default();
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
CHECK(srgb != nullptr);
|
||||
dawn::Chromaticities s = dawn::profile_chromaticities(srgb.get());
|
||||
CHECK(s.model == dawn::ColorModel::Rgb);
|
||||
@@ -463,7 +463,7 @@ test_chromaticities()
|
||||
CHECK(s.have_white);
|
||||
near_xy("sRGB W", s.wx, s.wy, 0.3127, 0.3290, 0.002);
|
||||
|
||||
auto display_p3 = cmm->get_profile_display_p3();
|
||||
auto display_p3 = cmm->get_profile_display_p3(false);
|
||||
CHECK(display_p3 != nullptr);
|
||||
CHECK(dawn::profile_transfer(display_p3.get()) == dawn::Transfer::Srgb);
|
||||
dawn::Chromaticities d = dawn::profile_chromaticities(display_p3.get());
|
||||
@@ -547,7 +547,7 @@ test_profile_transfer()
|
||||
CHECK(dawn::profile_transfer(nullptr) == dawn::Transfer::Srgb);
|
||||
|
||||
auto cmm = dawn::Cmm::get_default();
|
||||
auto srgb = cmm->get_profile_sRGB();
|
||||
auto srgb = cmm->get_profile_sRGB(false);
|
||||
CHECK(srgb != nullptr);
|
||||
CHECK(dawn::profile_transfer(srgb.get()) == dawn::Transfer::Srgb);
|
||||
|
||||
|
||||
+18
-18
@@ -90,7 +90,7 @@ payload_eq(const vector<byte> &got, span<const uint8_t> want)
|
||||
{
|
||||
if (got.size() != want.size())
|
||||
return false;
|
||||
for (size_t i = 0; i < got.size(); ++i) {
|
||||
for (size_t i = 0; i < got.size(); i++) {
|
||||
if (uint8_t(got[i]) != want[i])
|
||||
return false;
|
||||
}
|
||||
@@ -109,14 +109,14 @@ test_fragmented()
|
||||
CHECK(conn.ok());
|
||||
|
||||
static constexpr uint8_t kPayload[] = {1, 2, 3, 4, 5};
|
||||
uint8_t wire[4 + sizeof(kPayload)];
|
||||
put_u32be(wire, uint32_t(sizeof(kPayload)));
|
||||
memcpy(wire + 4, kPayload, sizeof(kPayload));
|
||||
uint8_t wire[4 + sizeof kPayload];
|
||||
put_u32be(wire, uint32_t(sizeof kPayload));
|
||||
memcpy(wire + 4, kPayload, sizeof kPayload);
|
||||
|
||||
for (size_t i = 0; i < sizeof(wire); ++i) {
|
||||
for (size_t i = 0; i < sizeof wire; i++) {
|
||||
CHECK(write_all(peer, &wire[i], 1));
|
||||
const auto st = conn.read();
|
||||
if (i + 1 < sizeof(wire))
|
||||
if (i + 1 < sizeof wire)
|
||||
CHECK(st == dawn::ipc::Connection::Status::NeedMore);
|
||||
else
|
||||
CHECK(st == dawn::ipc::Connection::Status::Frame);
|
||||
@@ -144,7 +144,7 @@ test_two_frames_one_write()
|
||||
memcpy(wire + 4, kA, 5);
|
||||
put_u32be(wire + 9, 5);
|
||||
memcpy(wire + 13, kB, 5);
|
||||
CHECK(write_all(peer, wire, sizeof(wire)));
|
||||
CHECK(write_all(peer, wire, sizeof wire));
|
||||
|
||||
CHECK(conn.read() == dawn::ipc::Connection::Status::Frame);
|
||||
vector<byte> first;
|
||||
@@ -169,7 +169,7 @@ test_empty_payload()
|
||||
|
||||
uint8_t len[4];
|
||||
put_u32be(len, 0);
|
||||
CHECK(write_all(peer, len, sizeof(len)));
|
||||
CHECK(write_all(peer, len, sizeof len));
|
||||
CHECK(conn.read() == dawn::ipc::Connection::Status::Error);
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ test_oversize_length()
|
||||
|
||||
uint8_t len[4];
|
||||
put_u32be(len, dawn::ipc::Connection::kMaxPayload + 1);
|
||||
CHECK(write_all(peer, len, sizeof(len)));
|
||||
CHECK(write_all(peer, len, sizeof len));
|
||||
CHECK(conn.read() == dawn::ipc::Connection::Status::Error);
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ test_endpoint_roundtrip()
|
||||
// The connect completion may not have been posted yet; an event loop
|
||||
// would be woken by the listener instead of spinning like this.
|
||||
dawn::ipc::Connection server;
|
||||
for (int i = 0; i < 100 && !server.ok(); ++i)
|
||||
for (int i = 0; i < 100 && !server.ok(); i++)
|
||||
server = listen.listener.accept();
|
||||
CHECK(server.ok());
|
||||
if (!server.ok())
|
||||
@@ -377,7 +377,7 @@ Fixture::start()
|
||||
this->conn_id = id;
|
||||
};
|
||||
cfg.on_request = [this](inst::Call call, const inst::RequestView &req) {
|
||||
++this->requests;
|
||||
this->requests++;
|
||||
if (this->handler)
|
||||
this->handler(std::move(call), req);
|
||||
else
|
||||
@@ -392,7 +392,7 @@ Fixture::start()
|
||||
return false;
|
||||
this->peer = std::move(connect.conn);
|
||||
|
||||
for (int i = 0; i < 100 && !this->conn_id; ++i)
|
||||
for (int i = 0; i < 100 && !this->conn_id; i++)
|
||||
this->poll();
|
||||
CHECK(this->conn_id != 0);
|
||||
return this->conn_id != 0;
|
||||
@@ -408,7 +408,7 @@ Fixture::send(const inst::Frame &frame)
|
||||
bool
|
||||
Fixture::recv(inst::FrameView &view, vector<byte> &storage)
|
||||
{
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
for (int i = 0; i < 200; i++) {
|
||||
this->poll();
|
||||
const auto st = this->peer.read();
|
||||
if (st == dawn::ipc::Connection::Status::Frame) {
|
||||
@@ -428,7 +428,7 @@ Fixture::recv(inst::FrameView &view, vector<byte> &storage)
|
||||
bool
|
||||
Fixture::closed()
|
||||
{
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
for (int i = 0; i < 200; i++) {
|
||||
this->poll();
|
||||
const auto st = this->peer.read();
|
||||
if (st == dawn::ipc::Connection::Status::Eof ||
|
||||
@@ -613,7 +613,7 @@ test_instance_out_of_order()
|
||||
CHECK(handshake(f, limit));
|
||||
CHECK(f.send(open_frame(11)));
|
||||
CHECK(f.send(open_frame(12)));
|
||||
for (int i = 0; i < 100 && f.requests < 2; ++i)
|
||||
for (int i = 0; i < 100 && f.requests < 2; i++)
|
||||
f.poll();
|
||||
CHECK(f.requests == 2);
|
||||
CHECK(held.size() == 2);
|
||||
@@ -663,14 +663,14 @@ test_instance_cancel()
|
||||
vector<inst::Call> held;
|
||||
int cancels = 0;
|
||||
f.handler = [&held, &cancels](inst::Call call, const inst::RequestView &) {
|
||||
call.on_cancel([&cancels] { ++cancels; });
|
||||
call.on_cancel([&cancels] { cancels++; });
|
||||
held.push_back(std::move(call));
|
||||
};
|
||||
|
||||
uint32_t limit = 0;
|
||||
CHECK(handshake(f, limit));
|
||||
CHECK(f.send(open_frame(3)));
|
||||
for (int i = 0; i < 100 && f.requests < 1; ++i)
|
||||
for (int i = 0; i < 100 && f.requests < 1; i++)
|
||||
f.poll();
|
||||
CHECK(held.size() == 1);
|
||||
if (held.size() != 1)
|
||||
@@ -678,7 +678,7 @@ test_instance_cancel()
|
||||
CHECK(!held[0].cancelled());
|
||||
|
||||
CHECK(f.send(cancel_frame(3)));
|
||||
for (int i = 0; i < 100 && cancels == 0; ++i)
|
||||
for (int i = 0; i < 100 && cancels == 0; i++)
|
||||
f.poll();
|
||||
CHECK(cancels == 1);
|
||||
CHECK(held[0].cancelled());
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ bytes_eq(span<const byte> got, span<const uint8_t> want)
|
||||
{
|
||||
if (got.size() != want.size())
|
||||
return false;
|
||||
for (size_t i = 0; i < got.size(); ++i) {
|
||||
for (size_t i = 0; i < got.size(); i++) {
|
||||
if (uint8_t(got[i]) != want[i])
|
||||
return false;
|
||||
}
|
||||
@@ -53,7 +53,7 @@ check_golden(
|
||||
return;
|
||||
test::fail(
|
||||
"golden %s: got %zu bytes, want %zu", label, got.size(), want.size());
|
||||
for (size_t i = 0; i < got.size(); ++i)
|
||||
for (size_t i = 0; i < got.size(); i++)
|
||||
fprintf(stderr, " %02x", uint8_t(got[i]));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
@@ -287,7 +287,7 @@ test_truncation()
|
||||
{
|
||||
const vector<byte> full = encoded(inst::Hello{1, "b"});
|
||||
CHECK(!full.empty());
|
||||
for (size_t n = 0; n < full.size(); ++n) {
|
||||
for (size_t n = 0; n < full.size(); n++) {
|
||||
dawn::ipc::Decoder dec(span<const byte>(full.data(), n));
|
||||
inst::HelloView view{};
|
||||
const bool ok = decode(dec, view);
|
||||
|
||||
@@ -112,7 +112,7 @@ test_cache_entries(const QTemporaryDir &inputs)
|
||||
fprintf(stderr, "%s\n", qUtf8Printable(error));
|
||||
|
||||
auto cmm = make_shared<dawn::Cmm>();
|
||||
auto p3 = cmm->get_profile_display_p3();
|
||||
auto p3 = cmm->get_profile_display_p3(false);
|
||||
dn::ThumbnailHit hit = dn::thumbnail_cache_lookup(source, 0, cmm, p3.get());
|
||||
CHECK(!hit.pixels.empty());
|
||||
CHECK(hit.width == 2 && hit.height == 1);
|
||||
|
||||
+44
-36
@@ -19,7 +19,7 @@
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace chrono_literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -56,7 +56,7 @@ test_background_reserve()
|
||||
thumbnailer.background_limit());
|
||||
return false;
|
||||
}
|
||||
const auto client = thumbnailer.add_client();
|
||||
const auto client = thumbnailer.add_client(0, {});
|
||||
WorkGate gate;
|
||||
int background_started = 0;
|
||||
bool visible_started = false;
|
||||
@@ -67,9 +67,9 @@ test_background_reserve()
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
};
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (!thumbnailer.submit(
|
||||
client, 0, dn::Thumbnailer::Priority::Dimensions, background)) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!thumbnailer.submit(client, 0,
|
||||
dn::Thumbnailer::Priority::Dimensions, background, {})) {
|
||||
gate.unblock();
|
||||
return false;
|
||||
}
|
||||
@@ -81,12 +81,14 @@ test_background_reserve()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible, [&] {
|
||||
lock_guard lock(gate.mu);
|
||||
visible_started = true;
|
||||
gate.changed.notify_all();
|
||||
return dn::Thumbnailer::Completion{};
|
||||
}))
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible,
|
||||
[&] {
|
||||
lock_guard lock(gate.mu);
|
||||
visible_started = true;
|
||||
gate.changed.notify_all();
|
||||
return dn::Thumbnailer::Completion{};
|
||||
},
|
||||
{}))
|
||||
return false;
|
||||
{
|
||||
unique_lock lock(gate.mu);
|
||||
@@ -108,7 +110,7 @@ static bool
|
||||
test_visible_reserve()
|
||||
{
|
||||
dn::Thumbnailer thumbnailer(nullptr, 4);
|
||||
const auto client = thumbnailer.add_client();
|
||||
const auto client = thumbnailer.add_client(0, {});
|
||||
WorkGate gate;
|
||||
int prefetch_started = 0;
|
||||
bool visible_started = false;
|
||||
@@ -119,9 +121,9 @@ test_visible_reserve()
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
};
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!thumbnailer.submit(
|
||||
client, 0, dn::Thumbnailer::Priority::Prefetch, prefetch)) {
|
||||
client, 0, dn::Thumbnailer::Priority::Prefetch, prefetch, {})) {
|
||||
gate.unblock();
|
||||
return false;
|
||||
}
|
||||
@@ -133,12 +135,14 @@ test_visible_reserve()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible, [&] {
|
||||
lock_guard lock(gate.mu);
|
||||
visible_started = true;
|
||||
gate.changed.notify_all();
|
||||
return dn::Thumbnailer::Completion{};
|
||||
})) {
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible,
|
||||
[&] {
|
||||
lock_guard lock(gate.mu);
|
||||
visible_started = true;
|
||||
gate.changed.notify_all();
|
||||
return dn::Thumbnailer::Completion{};
|
||||
},
|
||||
{})) {
|
||||
gate.unblock();
|
||||
return false;
|
||||
}
|
||||
@@ -159,17 +163,19 @@ static bool
|
||||
test_reprioritization_order()
|
||||
{
|
||||
dn::Thumbnailer thumbnailer(nullptr, 1);
|
||||
const auto client = thumbnailer.add_client();
|
||||
const auto client = thumbnailer.add_client(0, {});
|
||||
WorkGate gate;
|
||||
bool blocker_started = false;
|
||||
vector<int> order;
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible, [&] {
|
||||
unique_lock lock(gate.mu);
|
||||
blocker_started = true;
|
||||
gate.changed.notify_all();
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
}))
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible,
|
||||
[&] {
|
||||
unique_lock lock(gate.mu);
|
||||
blocker_started = true;
|
||||
gate.changed.notify_all();
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
},
|
||||
{}))
|
||||
return false;
|
||||
{
|
||||
unique_lock lock(gate.mu);
|
||||
@@ -218,7 +224,7 @@ static bool
|
||||
test_bundle_reservations()
|
||||
{
|
||||
dn::Thumbnailer thumbnailer(nullptr, 2);
|
||||
const auto client = thumbnailer.add_client(7);
|
||||
const auto client = thumbnailer.add_client(7, {});
|
||||
dn::ThumbnailSource a;
|
||||
a.uri = QByteArrayLiteral("file:///a");
|
||||
a.mtime = 1;
|
||||
@@ -251,7 +257,7 @@ test_bundle_reservations()
|
||||
static void
|
||||
test_activity_transitions(QCoreApplication &app)
|
||||
{
|
||||
dn::Thumbnailer thumbnailer;
|
||||
dn::Thumbnailer thumbnailer(nullptr, 0);
|
||||
WorkGate gate;
|
||||
bool saw_busy = false;
|
||||
bool saw_idle = false;
|
||||
@@ -265,11 +271,13 @@ test_activity_transitions(QCoreApplication &app)
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible, [&] {
|
||||
unique_lock lock(gate.mu);
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
})) {
|
||||
if (!thumbnailer.submit(client, 0, dn::Thumbnailer::Priority::Visible,
|
||||
[&] {
|
||||
unique_lock lock(gate.mu);
|
||||
gate.changed.wait(lock, [&] { return gate.released; });
|
||||
return dn::Thumbnailer::Completion{};
|
||||
},
|
||||
{})) {
|
||||
test::fail("could not submit thumbnail work");
|
||||
return;
|
||||
}
|
||||
@@ -287,7 +295,7 @@ test_activity_transitions(QCoreApplication &app)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
test::Application application(argc, argv);
|
||||
test::Application application(argc, argv, nullptr);
|
||||
return test::run({
|
||||
{"background worker reserve", [] { CHECK(test_background_reserve()); }},
|
||||
{"visible worker reserve", [] { CHECK(test_visible_reserve()); }},
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ fail(const char *format, ...)
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fputc('\n', stderr);
|
||||
++failures;
|
||||
failures++;
|
||||
}
|
||||
|
||||
inline void
|
||||
|
||||
Reference in New Issue
Block a user