mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-08 09:40:10 +00:00
Merge branch 'wip/otte/cpu-mipmap' into 'main'
gpu: Allow uploading of mipmap levels when tiling See merge request GNOME/gtk!7657
This commit is contained in:
commit
0274294a6f
@ -454,6 +454,9 @@
|
|||||||
<file>icons/16x16/categories/applications-other.png</file>
|
<file>icons/16x16/categories/applications-other.png</file>
|
||||||
<file>icons/48x48/status/starred.png</file>
|
<file>icons/48x48/status/starred.png</file>
|
||||||
<file alias="icons/scalable/apps/org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
|
<file alias="icons/scalable/apps/org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
|
||||||
|
<file>portland-rose-thumbnail.png</file>
|
||||||
|
<file>large-image-thumbnail.png</file>
|
||||||
|
<file compressed="true">large-image.png</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
<gresource prefix="/org/gtk/Demo4/gtk">
|
<gresource prefix="/org/gtk/Demo4/gtk">
|
||||||
<file preprocess="xml-stripblanks">help-overlay.ui</file>
|
<file preprocess="xml-stripblanks">help-overlay.ui</file>
|
||||||
|
@ -14,6 +14,103 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "demo3widget.h"
|
#include "demo3widget.h"
|
||||||
|
|
||||||
|
static GtkWidget *window = NULL;
|
||||||
|
static GCancellable *cancellable = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_texture (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cable)
|
||||||
|
{
|
||||||
|
GFile *file = task_data;
|
||||||
|
GdkTexture *texture;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
texture = gdk_texture_new_from_file (file, &error);
|
||||||
|
|
||||||
|
if (texture)
|
||||||
|
g_task_return_pointer (task, texture, g_object_unref);
|
||||||
|
else
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_wait_cursor (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
gtk_widget_set_cursor_from_name (GTK_WIDGET (gtk_widget_get_root (widget)), "wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unset_wait_cursor (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
gtk_widget_set_cursor (GTK_WIDGET (gtk_widget_get_root (widget)), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
texture_loaded (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GdkTexture *texture;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
texture = g_task_propagate_pointer (G_TASK (result), &error);
|
||||||
|
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
g_print ("%s\n", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
g_object_unref (texture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset_wait_cursor (GTK_WIDGET (data));
|
||||||
|
|
||||||
|
g_object_set (G_OBJECT (data), "texture", texture, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_file_async (GFile *file,
|
||||||
|
GtkWidget *demo)
|
||||||
|
{
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
|
set_wait_cursor (demo);
|
||||||
|
|
||||||
|
task = g_task_new (demo, cancellable, texture_loaded, demo);
|
||||||
|
g_task_set_task_data (task, g_object_ref (file), g_object_unref);
|
||||||
|
g_task_run_in_thread (task, load_texture);
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_portland_rose (GtkWidget *button,
|
||||||
|
GtkWidget *demo)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
|
||||||
|
file = g_file_new_for_uri ("resource:///transparent/portland-rose.jpg");
|
||||||
|
open_file_async (file, demo);
|
||||||
|
g_object_unref (file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_large_image (GtkWidget *button,
|
||||||
|
GtkWidget *demo)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
|
||||||
|
file = g_file_new_for_uri ("resource:///org/gtk/Demo4/large-image.png");
|
||||||
|
open_file_async (file, demo);
|
||||||
|
g_object_unref (file);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
file_opened (GObject *source,
|
file_opened (GObject *source,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
@ -21,7 +118,6 @@ file_opened (GObject *source,
|
|||||||
{
|
{
|
||||||
GFile *file;
|
GFile *file;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GdkTexture *texture;
|
|
||||||
|
|
||||||
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
||||||
|
|
||||||
@ -32,17 +128,9 @@ file_opened (GObject *source,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture = gdk_texture_new_from_file (file, &error);
|
open_file_async (file, data);
|
||||||
g_object_unref (file);
|
|
||||||
if (!texture)
|
|
||||||
{
|
|
||||||
g_print ("%s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_set (G_OBJECT (data), "texture", texture, NULL);
|
g_object_unref (file);
|
||||||
g_object_unref (texture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -116,11 +204,26 @@ transform_from (GBinding *binding,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_cancellable (gpointer data)
|
||||||
|
{
|
||||||
|
g_cancellable_cancel (cancellable);
|
||||||
|
g_clear_object (&cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cancel_load (GtkWidget *widget,
|
||||||
|
GVariant *args,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
unset_wait_cursor (widget);
|
||||||
|
g_cancellable_cancel (G_CANCELLABLE (data));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
do_image_scaling (GtkWidget *do_widget)
|
do_image_scaling (GtkWidget *do_widget)
|
||||||
{
|
{
|
||||||
static GtkWidget *window = NULL;
|
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
GtkWidget *box;
|
GtkWidget *box;
|
||||||
@ -130,6 +233,7 @@ do_image_scaling (GtkWidget *do_widget)
|
|||||||
GtkWidget *scale;
|
GtkWidget *scale;
|
||||||
GtkWidget *dropdown;
|
GtkWidget *dropdown;
|
||||||
GtkWidget *button;
|
GtkWidget *button;
|
||||||
|
GtkEventController *controller;
|
||||||
|
|
||||||
window = gtk_window_new ();
|
window = gtk_window_new ();
|
||||||
gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
|
gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
|
||||||
@ -138,6 +242,20 @@ do_image_scaling (GtkWidget *do_widget)
|
|||||||
gtk_widget_get_display (do_widget));
|
gtk_widget_get_display (do_widget));
|
||||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||||
|
|
||||||
|
cancellable = g_cancellable_new ();
|
||||||
|
g_object_set_data_full (G_OBJECT (window), "cancellable",
|
||||||
|
cancellable, free_cancellable);
|
||||||
|
|
||||||
|
controller = gtk_shortcut_controller_new ();
|
||||||
|
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||||
|
gtk_shortcut_new (
|
||||||
|
gtk_keyval_trigger_new (GDK_KEY_Escape, 0),
|
||||||
|
gtk_callback_action_new (cancel_load, cancellable, NULL)
|
||||||
|
));
|
||||||
|
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
|
||||||
|
GTK_SHORTCUT_SCOPE_GLOBAL);
|
||||||
|
gtk_widget_add_controller (window, controller);
|
||||||
|
|
||||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||||
|
|
||||||
@ -156,6 +274,22 @@ do_image_scaling (GtkWidget *do_widget)
|
|||||||
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
|
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
|
||||||
gtk_box_append (GTK_BOX (box2), button);
|
gtk_box_append (GTK_BOX (box2), button);
|
||||||
|
|
||||||
|
button = gtk_button_new ();
|
||||||
|
gtk_button_set_child (GTK_BUTTON (button),
|
||||||
|
gtk_image_new_from_resource ("/org/gtk/Demo4/portland-rose-thumbnail.png"));
|
||||||
|
gtk_widget_add_css_class (button, "image-button");
|
||||||
|
gtk_widget_set_tooltip_text (button, "Portland Rose");
|
||||||
|
g_signal_connect (button, "clicked", G_CALLBACK (open_portland_rose), widget);
|
||||||
|
gtk_box_append (GTK_BOX (box2), button);
|
||||||
|
|
||||||
|
button = gtk_button_new ();
|
||||||
|
gtk_button_set_child (GTK_BUTTON (button),
|
||||||
|
gtk_image_new_from_resource ("/org/gtk/Demo4/large-image-thumbnail.png"));
|
||||||
|
gtk_widget_add_css_class (button, "image-button");
|
||||||
|
gtk_widget_set_tooltip_text (button, "Large image");
|
||||||
|
g_signal_connect (button, "clicked", G_CALLBACK (open_large_image), widget);
|
||||||
|
gtk_box_append (GTK_BOX (box2), button);
|
||||||
|
|
||||||
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
|
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
|
||||||
gtk_widget_set_tooltip_text (button, "Rotate");
|
gtk_widget_set_tooltip_text (button, "Rotate");
|
||||||
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
|
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
|
||||||
@ -191,7 +325,9 @@ do_image_scaling (GtkWidget *do_widget)
|
|||||||
if (!gtk_widget_get_visible (window))
|
if (!gtk_widget_get_visible (window))
|
||||||
gtk_widget_set_visible (window, TRUE);
|
gtk_widget_set_visible (window, TRUE);
|
||||||
else
|
else
|
||||||
gtk_window_destroy (GTK_WINDOW (window));
|
{
|
||||||
|
gtk_window_destroy (GTK_WINDOW (window));
|
||||||
|
}
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
BIN
demos/gtk-demo/large-image-thumbnail.png
Normal file
BIN
demos/gtk-demo/large-image-thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
demos/gtk-demo/large-image.png
Normal file
BIN
demos/gtk-demo/large-image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 622 KiB |
BIN
demos/gtk-demo/portland-rose-thumbnail.png
Normal file
BIN
demos/gtk-demo/portland-rose-thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
File diff suppressed because it is too large
Load Diff
@ -110,6 +110,16 @@ void gdk_memory_convert_color_state (guchar
|
|||||||
GdkColorState *dest_color_state,
|
GdkColorState *dest_color_state,
|
||||||
gsize width,
|
gsize width,
|
||||||
gsize height);
|
gsize height);
|
||||||
|
void gdk_memory_mipmap (guchar *dest,
|
||||||
|
gsize dest_stride,
|
||||||
|
GdkMemoryFormat dest_format,
|
||||||
|
const guchar *src,
|
||||||
|
gsize src_stride,
|
||||||
|
GdkMemoryFormat src_format,
|
||||||
|
gsize src_width,
|
||||||
|
gsize src_height,
|
||||||
|
guint lod_level,
|
||||||
|
gboolean linear);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
86
gdk/gdkparalleltask.c
Normal file
86
gdk/gdkparalleltask.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2024 Benjamin Otte
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: Benjamin Otte <otte@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdkparalleltaskprivate.h"
|
||||||
|
|
||||||
|
typedef struct _TaskData TaskData;
|
||||||
|
|
||||||
|
struct _TaskData
|
||||||
|
{
|
||||||
|
GdkTaskFunc task_func;
|
||||||
|
gpointer task_data;
|
||||||
|
int n_running_tasks;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_parallel_task_thread_func (gpointer data,
|
||||||
|
gpointer unused)
|
||||||
|
{
|
||||||
|
TaskData *task = data;
|
||||||
|
|
||||||
|
task->task_func (task->task_data);
|
||||||
|
|
||||||
|
g_atomic_int_add (&task->n_running_tasks, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_parallel_task_run:
|
||||||
|
* @task_func: the function to spawn
|
||||||
|
* @task_data: data to pass to the function
|
||||||
|
*
|
||||||
|
* Spawns the given function in many threads.
|
||||||
|
* Once all functions have exited, this function returns.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_parallel_task_run (GdkTaskFunc task_func,
|
||||||
|
gpointer task_data)
|
||||||
|
{
|
||||||
|
static GThreadPool *pool;
|
||||||
|
TaskData task = {
|
||||||
|
.task_func = task_func,
|
||||||
|
.task_data = task_data,
|
||||||
|
};
|
||||||
|
int i, n_tasks;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&pool))
|
||||||
|
{
|
||||||
|
GThreadPool *the_pool = g_thread_pool_new (gdk_parallel_task_thread_func,
|
||||||
|
NULL,
|
||||||
|
MAX (2, g_get_num_processors ()) - 1,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
g_once_init_leave (&pool, the_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
n_tasks = g_get_num_processors ();
|
||||||
|
task.n_running_tasks = n_tasks;
|
||||||
|
/* Start with 1 because we run 1 task ourselves */
|
||||||
|
for (i = 1; i < n_tasks; i++)
|
||||||
|
{
|
||||||
|
g_thread_pool_push (pool, &task, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_parallel_task_thread_func (&task, NULL);
|
||||||
|
|
||||||
|
while (g_atomic_int_get (&task.n_running_tasks) > 0)
|
||||||
|
g_thread_yield ();
|
||||||
|
}
|
||||||
|
|
32
gdk/gdkparalleltaskprivate.h
Normal file
32
gdk/gdkparalleltaskprivate.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2024 Benjamin Otte
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: Benjamin Otte <otte@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef void (* GdkTaskFunc) (gpointer user_data);
|
||||||
|
|
||||||
|
void gdk_parallel_task_run (GdkTaskFunc task_func,
|
||||||
|
gpointer task_data);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
@ -33,7 +33,18 @@
|
|||||||
*
|
*
|
||||||
* `GdkTexture` is an immutable object: That means you cannot change
|
* `GdkTexture` is an immutable object: That means you cannot change
|
||||||
* anything about it other than increasing the reference count via
|
* anything about it other than increasing the reference count via
|
||||||
* [method@GObject.Object.ref], and consequently, it is a thread-safe object.
|
* [method@GObject.Object.ref], and consequently, it is a threadsafe object.
|
||||||
|
*
|
||||||
|
* GDK provides a number of threadsafe texture loading functions:
|
||||||
|
* [ctor@Gdk.Texture.new_from_resource],
|
||||||
|
* [ctor@Gdk.Texture.new_from_bytes],
|
||||||
|
* [ctor@Gdk.Texture.new_from_file],
|
||||||
|
* [ctor@Gdk.Texture.new_from_filename],
|
||||||
|
* [ctor@Gdk.Texture.new_for_pixbuf]. Note that these are meant for loading
|
||||||
|
* icons and resources that are shipped with the toolkit or application. It
|
||||||
|
* is recommended that you use a dedicated image loading framework such as
|
||||||
|
* [glycin](https://lib.rs/crates/glycin), if you need to load untrusted image
|
||||||
|
* data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -52,23 +52,24 @@ gdk_public_sources = files([
|
|||||||
'gdkmonitor.c',
|
'gdkmonitor.c',
|
||||||
'gdkpaintable.c',
|
'gdkpaintable.c',
|
||||||
'gdkpango.c',
|
'gdkpango.c',
|
||||||
|
'gdkparalleltask.c',
|
||||||
'gdkpipeiostream.c',
|
'gdkpipeiostream.c',
|
||||||
|
'gdkpopup.c',
|
||||||
|
'gdkpopuplayout.c',
|
||||||
|
'gdkprofiler.c',
|
||||||
'gdkrectangle.c',
|
'gdkrectangle.c',
|
||||||
'gdkrgba.c',
|
'gdkrgba.c',
|
||||||
'gdkseat.c',
|
'gdkseat.c',
|
||||||
'gdkseatdefault.c',
|
'gdkseatdefault.c',
|
||||||
'gdksnapshot.c',
|
'gdksnapshot.c',
|
||||||
'gdktexture.c',
|
|
||||||
'gdktexturedownloader.c',
|
|
||||||
'gdkvulkancontext.c',
|
|
||||||
'gdksubsurface.c',
|
'gdksubsurface.c',
|
||||||
'gdksurface.c',
|
'gdksurface.c',
|
||||||
'gdkpopuplayout.c',
|
'gdktexture.c',
|
||||||
'gdkprofiler.c',
|
'gdktexturedownloader.c',
|
||||||
'gdkpopup.c',
|
|
||||||
'gdktoplevellayout.c',
|
'gdktoplevellayout.c',
|
||||||
'gdktoplevelsize.c',
|
'gdktoplevelsize.c',
|
||||||
'gdktoplevel.c',
|
'gdktoplevel.c',
|
||||||
|
'gdkvulkancontext.c',
|
||||||
'loaders/gdkpng.c',
|
'loaders/gdkpng.c',
|
||||||
'loaders/gdktiff.c',
|
'loaders/gdktiff.c',
|
||||||
'loaders/gdkjpeg.c',
|
'loaders/gdkjpeg.c',
|
||||||
|
@ -537,6 +537,8 @@ struct _GskGpuCachedTile
|
|||||||
GskGpuCached parent;
|
GskGpuCached parent;
|
||||||
|
|
||||||
GdkTexture *texture;
|
GdkTexture *texture;
|
||||||
|
guint lod_level;
|
||||||
|
gboolean lod_linear;
|
||||||
gsize tile_id;
|
gsize tile_id;
|
||||||
|
|
||||||
/* atomic */ int use_count; /* We count the use by the cache (via the linked
|
/* atomic */ int use_count; /* We count the use by the cache (via the linked
|
||||||
@ -630,7 +632,10 @@ gsk_gpu_cached_tile_hash (gconstpointer data)
|
|||||||
{
|
{
|
||||||
const GskGpuCachedTile *self = data;
|
const GskGpuCachedTile *self = data;
|
||||||
|
|
||||||
return g_direct_hash (self->texture) ^ self->tile_id;
|
return g_direct_hash (self->texture) ^
|
||||||
|
self->tile_id ^
|
||||||
|
(self->lod_level << 24) ^
|
||||||
|
(self->lod_linear << 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -641,12 +646,16 @@ gsk_gpu_cached_tile_equal (gconstpointer data_a,
|
|||||||
const GskGpuCachedTile *b = data_b;
|
const GskGpuCachedTile *b = data_b;
|
||||||
|
|
||||||
return a->texture == b->texture &&
|
return a->texture == b->texture &&
|
||||||
|
a->lod_level == b->lod_level &&
|
||||||
|
a->lod_linear == b->lod_linear &&
|
||||||
a->tile_id == b->tile_id;
|
a->tile_id == b->tile_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskGpuCachedTile *
|
static GskGpuCachedTile *
|
||||||
gsk_gpu_cached_tile_new (GskGpuCache *cache,
|
gsk_gpu_cached_tile_new (GskGpuCache *cache,
|
||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
|
guint lod_level,
|
||||||
|
gboolean lod_linear,
|
||||||
guint tile_id,
|
guint tile_id,
|
||||||
GskGpuImage *image,
|
GskGpuImage *image,
|
||||||
GdkColorState *color_state)
|
GdkColorState *color_state)
|
||||||
@ -655,6 +664,8 @@ gsk_gpu_cached_tile_new (GskGpuCache *cache,
|
|||||||
|
|
||||||
self = gsk_gpu_cached_new (cache, &GSK_GPU_CACHED_TILE_CLASS);
|
self = gsk_gpu_cached_new (cache, &GSK_GPU_CACHED_TILE_CLASS);
|
||||||
self->texture = texture;
|
self->texture = texture;
|
||||||
|
self->lod_level = lod_level;
|
||||||
|
self->lod_linear = lod_linear;
|
||||||
self->tile_id = tile_id;
|
self->tile_id = tile_id;
|
||||||
self->image = g_object_ref (image);
|
self->image = g_object_ref (image);
|
||||||
self->color_state = gdk_color_state_ref (color_state);
|
self->color_state = gdk_color_state_ref (color_state);
|
||||||
@ -673,14 +684,18 @@ gsk_gpu_cached_tile_new (GskGpuCache *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GskGpuImage *
|
GskGpuImage *
|
||||||
gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
gsize tile_id,
|
guint lod_level,
|
||||||
GdkColorState **out_color_state)
|
GskScalingFilter lod_filter,
|
||||||
|
gsize tile_id,
|
||||||
|
GdkColorState **out_color_state)
|
||||||
{
|
{
|
||||||
GskGpuCachedTile *tile;
|
GskGpuCachedTile *tile;
|
||||||
GskGpuCachedTile lookup = {
|
GskGpuCachedTile lookup = {
|
||||||
.texture = texture,
|
.texture = texture,
|
||||||
|
.lod_level = lod_level,
|
||||||
|
.lod_linear = lod_filter == GSK_SCALING_FILTER_TRILINEAR,
|
||||||
.tile_id = tile_id
|
.tile_id = tile_id
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -699,15 +714,23 @@ gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_gpu_cache_cache_tile (GskGpuCache *self,
|
gsk_gpu_cache_cache_tile (GskGpuCache *self,
|
||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
guint tile_id,
|
guint lod_level,
|
||||||
GskGpuImage *image,
|
GskScalingFilter lod_filter,
|
||||||
GdkColorState *color_state)
|
gsize tile_id,
|
||||||
|
GskGpuImage *image,
|
||||||
|
GdkColorState *color_state)
|
||||||
{
|
{
|
||||||
GskGpuCachedTile *tile;
|
GskGpuCachedTile *tile;
|
||||||
|
|
||||||
tile = gsk_gpu_cached_tile_new (self, texture, tile_id, image, color_state);
|
tile = gsk_gpu_cached_tile_new (self,
|
||||||
|
texture,
|
||||||
|
lod_level,
|
||||||
|
lod_filter == GSK_SCALING_FILTER_TRILINEAR,
|
||||||
|
tile_id,
|
||||||
|
image,
|
||||||
|
color_state);
|
||||||
|
|
||||||
gsk_gpu_cached_use (self, (GskGpuCached *) tile);
|
gsk_gpu_cached_use (self, (GskGpuCached *) tile);
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,15 @@ void gsk_gpu_cache_cache_texture_image (GskGpuC
|
|||||||
GdkColorState *color_state);
|
GdkColorState *color_state);
|
||||||
GskGpuImage * gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
GskGpuImage * gsk_gpu_cache_lookup_tile (GskGpuCache *self,
|
||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
|
guint lod_level,
|
||||||
|
GskScalingFilter lod_filter,
|
||||||
gsize tile_id,
|
gsize tile_id,
|
||||||
GdkColorState **out_color_state);
|
GdkColorState **out_color_state);
|
||||||
void gsk_gpu_cache_cache_tile (GskGpuCache *self,
|
void gsk_gpu_cache_cache_tile (GskGpuCache *self,
|
||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
guint tile_id,
|
guint lod_level,
|
||||||
|
GskScalingFilter lod_filter,
|
||||||
|
gsize tile_id,
|
||||||
GskGpuImage *image,
|
GskGpuImage *image,
|
||||||
GdkColorState *color_state);
|
GdkColorState *color_state);
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ gsk_gpu_frame_default_upload_texture (GskGpuFrame *self,
|
|||||||
{
|
{
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
|
|
||||||
image = gsk_gpu_upload_texture_op_try (self, with_mipmap, texture);
|
image = gsk_gpu_upload_texture_op_try (self, with_mipmap, 0, GSK_SCALING_FILTER_NEAREST, texture);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -1964,18 +1964,26 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
|||||||
gboolean need_mipmap;
|
gboolean need_mipmap;
|
||||||
GdkMemoryTexture *memtex;
|
GdkMemoryTexture *memtex;
|
||||||
GdkTexture *subtex;
|
GdkTexture *subtex;
|
||||||
float scaled_tile_width, scaled_tile_height;
|
float scale_factor, scaled_tile_width, scaled_tile_height;
|
||||||
gsize tile_size, width, height, n_width, n_height, x, y;
|
gsize tile_size, width, height, n_width, n_height, x, y;
|
||||||
graphene_rect_t clip_bounds;
|
graphene_rect_t clip_bounds;
|
||||||
|
guint lod_level;
|
||||||
|
|
||||||
device = gsk_gpu_frame_get_device (self->frame);
|
device = gsk_gpu_frame_get_device (self->frame);
|
||||||
cache = gsk_gpu_device_get_cache (device);
|
cache = gsk_gpu_device_get_cache (device);
|
||||||
sampler = gsk_gpu_sampler_for_scaling_filter (scaling_filter);
|
sampler = gsk_gpu_sampler_for_scaling_filter (scaling_filter);
|
||||||
need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR;
|
need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR;
|
||||||
gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds);
|
gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds);
|
||||||
tile_size = gsk_gpu_device_get_tile_size (device);
|
|
||||||
width = gdk_texture_get_width (texture);
|
width = gdk_texture_get_width (texture);
|
||||||
height = gdk_texture_get_height (texture);
|
height = gdk_texture_get_height (texture);
|
||||||
|
tile_size = gsk_gpu_device_get_tile_size (device);
|
||||||
|
scale_factor = MIN (width / MAX (tile_size, texture_bounds->size.width),
|
||||||
|
height / MAX (tile_size, texture_bounds->size.height));
|
||||||
|
if (scale_factor <= 1.0)
|
||||||
|
lod_level = 0;
|
||||||
|
else
|
||||||
|
lod_level = floor (log2f (scale_factor));
|
||||||
|
tile_size <<= lod_level;
|
||||||
n_width = (width + tile_size - 1) / tile_size;
|
n_width = (width + tile_size - 1) / tile_size;
|
||||||
n_height = (height + tile_size - 1) / tile_size;
|
n_height = (height + tile_size - 1) / tile_size;
|
||||||
scaled_tile_width = texture_bounds->size.width * tile_size / width;
|
scaled_tile_width = texture_bounds->size.width * tile_size / width;
|
||||||
@ -1994,7 +2002,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
|||||||
!gsk_rect_intersects (&clip_bounds, &tile_rect))
|
!gsk_rect_intersects (&clip_bounds, &tile_rect))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tile = gsk_gpu_cache_lookup_tile (cache, texture, y * n_width + x, &tile_cs);
|
tile = gsk_gpu_cache_lookup_tile (cache, texture, lod_level, scaling_filter, y * n_width + x, &tile_cs);
|
||||||
|
|
||||||
if (tile == NULL)
|
if (tile == NULL)
|
||||||
{
|
{
|
||||||
@ -2005,7 +2013,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
|||||||
y * tile_size,
|
y * tile_size,
|
||||||
MIN (tile_size, width - x * tile_size),
|
MIN (tile_size, width - x * tile_size),
|
||||||
MIN (tile_size, height - y * tile_size));
|
MIN (tile_size, height - y * tile_size));
|
||||||
tile = gsk_gpu_upload_texture_op_try (self->frame, need_mipmap, subtex);
|
tile = gsk_gpu_upload_texture_op_try (self->frame, need_mipmap, lod_level, scaling_filter, subtex);
|
||||||
g_object_unref (subtex);
|
g_object_unref (subtex);
|
||||||
if (tile == NULL)
|
if (tile == NULL)
|
||||||
{
|
{
|
||||||
@ -2021,7 +2029,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
|||||||
g_assert (tile_cs);
|
g_assert (tile_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
gsk_gpu_cache_cache_tile (cache, texture, y * n_width + x, tile, tile_cs);
|
gsk_gpu_cache_cache_tile (cache, texture, lod_level, scaling_filter, y * n_width + x, tile, tile_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_mipmap &&
|
if (need_mipmap &&
|
||||||
@ -2029,7 +2037,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
|
|||||||
{
|
{
|
||||||
tile = gsk_gpu_copy_image (self->frame, self->ccs, tile, tile_cs, TRUE);
|
tile = gsk_gpu_copy_image (self->frame, self->ccs, tile, tile_cs, TRUE);
|
||||||
tile_cs = self->ccs;
|
tile_cs = self->ccs;
|
||||||
gsk_gpu_cache_cache_tile (cache, texture, y * n_width + x, tile, tile_cs);
|
gsk_gpu_cache_cache_tile (cache, texture, lod_level, scaling_filter, y * n_width + x, tile, tile_cs);
|
||||||
}
|
}
|
||||||
if (need_mipmap && !(gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_MIPMAP))
|
if (need_mipmap && !(gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_MIPMAP))
|
||||||
gsk_gpu_mipmap_op (self->frame, tile);
|
gsk_gpu_mipmap_op (self->frame, tile);
|
||||||
|
@ -214,6 +214,8 @@ struct _GskGpuUploadTextureOp
|
|||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
GskGpuBuffer *buffer;
|
GskGpuBuffer *buffer;
|
||||||
GdkTexture *texture;
|
GdkTexture *texture;
|
||||||
|
guint lod_level;
|
||||||
|
GskScalingFilter lod_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -236,6 +238,10 @@ gsk_gpu_upload_texture_op_print (GskGpuOp *op,
|
|||||||
|
|
||||||
gsk_gpu_print_op (string, indent, "upload-texture");
|
gsk_gpu_print_op (string, indent, "upload-texture");
|
||||||
gsk_gpu_print_image (string, self->image);
|
gsk_gpu_print_image (string, self->image);
|
||||||
|
if (self->lod_level > 0)
|
||||||
|
g_string_append_printf (string, " @%ux %s",
|
||||||
|
1 << self->lod_level,
|
||||||
|
self->lod_filter == GSK_SCALING_FILTER_TRILINEAR ? "linear" : "nearest");
|
||||||
gsk_gpu_print_newline (string);
|
gsk_gpu_print_newline (string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,9 +254,31 @@ gsk_gpu_upload_texture_op_draw (GskGpuOp *op,
|
|||||||
GdkTextureDownloader *downloader;
|
GdkTextureDownloader *downloader;
|
||||||
|
|
||||||
downloader = gdk_texture_downloader_new (self->texture);
|
downloader = gdk_texture_downloader_new (self->texture);
|
||||||
gdk_texture_downloader_set_format (downloader, gsk_gpu_image_get_format (self->image));
|
|
||||||
gdk_texture_downloader_set_color_state (downloader, gdk_texture_get_color_state (self->texture));
|
gdk_texture_downloader_set_color_state (downloader, gdk_texture_get_color_state (self->texture));
|
||||||
gdk_texture_downloader_download_into (downloader, data, stride);
|
if (self->lod_level == 0)
|
||||||
|
{
|
||||||
|
gdk_texture_downloader_set_format (downloader, gsk_gpu_image_get_format (self->image));
|
||||||
|
gdk_texture_downloader_download_into (downloader, data, stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GBytes *bytes;
|
||||||
|
gsize src_stride;
|
||||||
|
|
||||||
|
gdk_texture_downloader_set_format (downloader, gdk_texture_get_format (self->texture));
|
||||||
|
bytes = gdk_texture_downloader_download_bytes (downloader, &src_stride);
|
||||||
|
gdk_memory_mipmap (data,
|
||||||
|
stride,
|
||||||
|
gsk_gpu_image_get_format (self->image),
|
||||||
|
g_bytes_get_data (bytes, NULL),
|
||||||
|
src_stride,
|
||||||
|
gdk_texture_get_format (self->texture),
|
||||||
|
gdk_texture_get_width (self->texture),
|
||||||
|
gdk_texture_get_height (self->texture),
|
||||||
|
self->lod_level,
|
||||||
|
self->lod_filter == GSK_SCALING_FILTER_TRILINEAR ? TRUE : FALSE);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
}
|
||||||
gdk_texture_downloader_free (downloader);
|
gdk_texture_downloader_free (downloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,9 +324,11 @@ static const GskGpuOpClass GSK_GPU_UPLOAD_TEXTURE_OP_CLASS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GskGpuImage *
|
GskGpuImage *
|
||||||
gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
||||||
gboolean with_mipmap,
|
gboolean with_mipmap,
|
||||||
GdkTexture *texture)
|
guint lod_level,
|
||||||
|
GskScalingFilter lod_filter,
|
||||||
|
GdkTexture *texture)
|
||||||
{
|
{
|
||||||
GskGpuUploadTextureOp *self;
|
GskGpuUploadTextureOp *self;
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
@ -311,8 +341,8 @@ gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
|||||||
format,
|
format,
|
||||||
gdk_memory_format_alpha (format) != GDK_MEMORY_ALPHA_PREMULTIPLIED &&
|
gdk_memory_format_alpha (format) != GDK_MEMORY_ALPHA_PREMULTIPLIED &&
|
||||||
gdk_color_state_get_no_srgb_tf (gdk_texture_get_color_state (texture)) != NULL,
|
gdk_color_state_get_no_srgb_tf (gdk_texture_get_color_state (texture)) != NULL,
|
||||||
gdk_texture_get_width (texture),
|
(gdk_texture_get_width (texture) + (1 << lod_level) - 1) >> lod_level,
|
||||||
gdk_texture_get_height (texture));
|
(gdk_texture_get_height (texture) + (1 << lod_level) - 1) >> lod_level);
|
||||||
if (image == NULL)
|
if (image == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -343,6 +373,8 @@ gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
|||||||
self = (GskGpuUploadTextureOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_UPLOAD_TEXTURE_OP_CLASS);
|
self = (GskGpuUploadTextureOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_UPLOAD_TEXTURE_OP_CLASS);
|
||||||
|
|
||||||
self->texture = g_object_ref (texture);
|
self->texture = g_object_ref (texture);
|
||||||
|
self->lod_level = lod_level;
|
||||||
|
self->lod_filter = lod_filter;
|
||||||
self->image = image;
|
self->image = image;
|
||||||
|
|
||||||
return g_object_ref (self->image);
|
return g_object_ref (self->image);
|
||||||
|
@ -11,6 +11,8 @@ typedef void (* GskGpuCairoFunc) (gpointe
|
|||||||
|
|
||||||
GskGpuImage * gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
GskGpuImage * gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
|
||||||
gboolean with_mipmap,
|
gboolean with_mipmap,
|
||||||
|
guint lod_level,
|
||||||
|
GskScalingFilter lod_filter,
|
||||||
GdkTexture *texture);
|
GdkTexture *texture);
|
||||||
|
|
||||||
GskGpuImage * gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
|
GskGpuImage * gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
|
||||||
|
Loading…
Reference in New Issue
Block a user