gpu: Allow uploading of mipmap levels when tiling

This allows uploading less memory but requires computing lod levels on
the CPU which is slow because it reads through all of the memory and so
far entirely not optimized.

However, it uses significantly less VRAM.

This is done by adding a gdk_memory_mipmap() function that does this
task.
The texture upload op now accepts a lod level and if that is >0 it uses
gdk_memory_mipmap() on the source texture.
This commit is contained in:
Benjamin Otte 2024-08-27 04:48:43 +02:00 committed by Matthias Clasen
parent 46559039f3
commit 848c6815d3
8 changed files with 171 additions and 15 deletions

View File

@ -22,7 +22,6 @@
#include "gdkmemoryformatprivate.h"
#include "gdkdmabuffourccprivate.h"
#include "gdkglcontextprivate.h"
#include "gdkcolorstateprivate.h"
#include "gdkparalleltaskprivate.h"
#include "gtk/gtkcolorutilsprivate.h"
@ -314,6 +313,61 @@ ADD_ALPHA_FUNC(r8g8b8_to_b8g8r8a8, 0, 1, 2, 2, 1, 0, 3)
ADD_ALPHA_FUNC(r8g8b8_to_a8r8g8b8, 0, 1, 2, 1, 2, 3, 0)
ADD_ALPHA_FUNC(r8g8b8_to_a8b8g8r8, 0, 1, 2, 3, 2, 1, 0)
#define MIPMAP_FUNC(SumType, DataType, n_units) \
static void \
gdk_mipmap_ ## DataType ## _ ## n_units (guchar *dest, \
gsize dest_stride, \
const guchar *src, \
gsize src_stride, \
gsize src_width, \
gsize src_height, \
guint lod_level) \
{ \
gsize y_dest, y, x_dest, x, i; \
gsize n = 1 << lod_level; \
\
for (y_dest = 0; y_dest < src_height; y_dest += n) \
{ \
DataType *dest_data = (DataType *) dest; \
for (x_dest = 0; x_dest < src_width; x_dest += n) \
{ \
SumType tmp[n_units] = { 0, }; \
\
for (y = 0; y < MIN (n, src_height - y_dest); y++) \
{ \
const DataType *src_data = (const DataType *) (src + y * src_stride); \
for (x = 0; x < MIN (n, src_width - x_dest); x++) \
{ \
for (i = 0; i < n_units; i++) \
tmp[i] += src_data[n_units * (x_dest + x) + i]; \
} \
} \
\
for (i = 0; i < n_units; i++) \
*dest_data++ = tmp[i] / (x * y); \
} \
dest += dest_stride; \
src += src_stride * n; \
} \
}
MIPMAP_FUNC(guint32, guint8, 1)
MIPMAP_FUNC(guint32, guint8, 2)
MIPMAP_FUNC(guint32, guint8, 3)
MIPMAP_FUNC(guint32, guint8, 4)
MIPMAP_FUNC(guint32, guint16, 1)
MIPMAP_FUNC(guint32, guint16, 2)
MIPMAP_FUNC(guint32, guint16, 3)
MIPMAP_FUNC(guint32, guint16, 4)
MIPMAP_FUNC(float, float, 1)
MIPMAP_FUNC(float, float, 3)
MIPMAP_FUNC(float, float, 4)
#define half_float guint16
MIPMAP_FUNC(float, half_float, 1)
MIPMAP_FUNC(float, half_float, 3)
MIPMAP_FUNC(float, half_float, 4)
#undef half_float
struct _GdkMemoryFormatDescription
{
const char *name;
@ -347,6 +401,7 @@ struct _GdkMemoryFormatDescription
/* no premultiplication going on here */
void (* to_float) (float (*)[4], const guchar*, gsize);
void (* from_float) (guchar *, const float (*)[4], gsize);
void (* mipmap) (guchar *, gsize, const guchar *, gsize, gsize, gsize, guint);
};
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
@ -388,6 +443,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = b8g8r8a8_premultiplied_to_float,
.from_float = b8g8r8a8_premultiplied_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
.name = "ARGB8(p)",
@ -419,6 +475,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a8r8g8b8_premultiplied_to_float,
.from_float = a8r8g8b8_premultiplied_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
.name = "RGBA8(p)",
@ -449,6 +506,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r8g8b8a8_premultiplied_to_float,
.from_float = r8g8b8a8_premultiplied_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
.name = "ABGR8(p)",
@ -480,6 +538,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a8b8g8r8_premultiplied_to_float,
.from_float = a8b8g8r8_premultiplied_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_B8G8R8A8] = {
.name = "BGRA8",
@ -511,6 +570,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = b8g8r8a8_to_float,
.from_float = b8g8r8a8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_A8R8G8B8] = {
.name = "ARGB8",
@ -542,6 +602,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a8r8g8b8_to_float,
.from_float = a8r8g8b8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_R8G8B8A8] = {
.name = "RGBA8",
@ -572,6 +633,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r8g8b8a8_to_float,
.from_float = r8g8b8a8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_A8B8G8R8] = {
.name = "ABGR8",
@ -603,6 +665,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a8b8g8r8_to_float,
.from_float = a8b8g8r8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_B8G8R8X8] = {
.name = "BGRX8",
@ -635,6 +698,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = b8g8r8x8_to_float,
.from_float = b8g8r8x8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_X8R8G8B8] = {
.name = "XRGB8",
@ -667,6 +731,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = x8r8g8b8_to_float,
.from_float = x8r8g8b8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_R8G8B8X8] = {
.name = "RGBX8",
@ -698,6 +763,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r8g8b8x8_to_float,
.from_float = r8g8b8x8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_X8B8G8R8] = {
.name = "XBGR8",
@ -730,6 +796,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = x8b8g8r8_to_float,
.from_float = x8b8g8r8_from_float,
.mipmap = gdk_mipmap_guint8_4,
},
[GDK_MEMORY_R8G8B8] = {
.name = "RGB8",
@ -761,6 +828,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r8g8b8_to_float,
.from_float = r8g8b8_from_float,
.mipmap = gdk_mipmap_guint8_3,
},
[GDK_MEMORY_B8G8R8] = {
.name = "BGR8",
@ -793,6 +861,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = b8g8r8_to_float,
.from_float = b8g8r8_from_float,
.mipmap = gdk_mipmap_guint8_3,
},
[GDK_MEMORY_R16G16B16] = {
.name = "RGB16",
@ -827,6 +896,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16_to_float,
.from_float = r16g16b16_from_float,
.mipmap = gdk_mipmap_guint16_3,
},
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
.name = "RGBA16(p)",
@ -860,6 +930,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16a16_to_float,
.from_float = r16g16b16a16_from_float,
.mipmap = gdk_mipmap_guint16_4,
},
[GDK_MEMORY_R16G16B16A16] = {
.name = "RGBA16",
@ -893,6 +964,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16a16_to_float,
.from_float = r16g16b16a16_from_float,
.mipmap = gdk_mipmap_guint16_4,
},
[GDK_MEMORY_R16G16B16_FLOAT] = {
.name = "RGBA16f",
@ -926,6 +998,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16_float_to_float,
.from_float = r16g16b16_float_from_float,
.mipmap = gdk_mipmap_half_float_3,
},
[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
.name = "RGBA16f(p)",
@ -958,6 +1031,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16a16_float_to_float,
.from_float = r16g16b16a16_float_from_float,
.mipmap = gdk_mipmap_half_float_4,
},
[GDK_MEMORY_R16G16B16A16_FLOAT] = {
.name = "RGBA16f",
@ -990,6 +1064,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r16g16b16a16_float_to_float,
.from_float = r16g16b16a16_float_from_float,
.mipmap = gdk_mipmap_half_float_4,
},
[GDK_MEMORY_R32G32B32_FLOAT] = {
.name = "RGB32f",
@ -1023,6 +1098,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r32g32b32_float_to_float,
.from_float = r32g32b32_float_from_float,
.mipmap = gdk_mipmap_float_3,
},
[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
.name = "RGBA32f(p)",
@ -1055,6 +1131,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r32g32b32a32_float_to_float,
.from_float = r32g32b32a32_float_from_float,
.mipmap = gdk_mipmap_float_4,
},
[GDK_MEMORY_R32G32B32A32_FLOAT] = {
.name = "RGBA32f",
@ -1087,6 +1164,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = r32g32b32a32_float_to_float,
.from_float = r32g32b32a32_float_from_float,
.mipmap = gdk_mipmap_float_4,
},
[GDK_MEMORY_G8A8_PREMULTIPLIED] = {
.name = "GA8(p)",
@ -1118,6 +1196,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g8a8_premultiplied_to_float,
.from_float = g8a8_premultiplied_from_float,
.mipmap = gdk_mipmap_guint8_2,
},
[GDK_MEMORY_G8A8] = {
.name = "GA8",
@ -1149,6 +1228,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g8a8_to_float,
.from_float = g8a8_from_float,
.mipmap = gdk_mipmap_guint8_2,
},
[GDK_MEMORY_G8] = {
.name = "G8",
@ -1180,6 +1260,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g8_to_float,
.from_float = g8_from_float,
.mipmap = gdk_mipmap_guint8_1,
},
[GDK_MEMORY_G16A16_PREMULTIPLIED] = {
.name = "GA16(p)",
@ -1214,6 +1295,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g16a16_premultiplied_to_float,
.from_float = g16a16_premultiplied_from_float,
.mipmap = gdk_mipmap_guint16_2,
},
[GDK_MEMORY_G16A16] = {
.name = "GA16",
@ -1248,6 +1330,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g16a16_to_float,
.from_float = g16a16_from_float,
.mipmap = gdk_mipmap_guint16_2,
},
[GDK_MEMORY_G16] = {
.name = "G16",
@ -1282,6 +1365,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = g16_to_float,
.from_float = g16_from_float,
.mipmap = gdk_mipmap_guint16_1,
},
[GDK_MEMORY_A8] = {
.name = "A8",
@ -1313,6 +1397,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a8_to_float,
.from_float = a8_from_float,
.mipmap = gdk_mipmap_guint8_1,
},
[GDK_MEMORY_A16] = {
.name = "A16",
@ -1347,6 +1432,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a16_to_float,
.from_float = a16_from_float,
.mipmap = gdk_mipmap_guint16_1,
},
[GDK_MEMORY_A16_FLOAT] = {
.name = "A16f",
@ -1380,6 +1466,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a16_float_to_float,
.from_float = a16_float_from_float,
.mipmap = gdk_mipmap_half_float_1,
},
[GDK_MEMORY_A32_FLOAT] = {
.name = "A32f",
@ -1413,6 +1500,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
#endif
.to_float = a32_float_to_float,
.from_float = a32_float_from_float,
.mipmap = gdk_mipmap_float_1,
}
};
@ -2296,3 +2384,21 @@ gdk_memory_convert_color_state (guchar *data,
gdk_parallel_task_run (gdk_memory_convert_color_state_generic, &mc);
}
}
void
gdk_memory_mipmap (guchar *dest,
gsize dest_stride,
GdkMemoryFormat format,
const guchar *src,
gsize src_stride,
gsize src_width,
gsize src_height,
guint lod_level)
{
const GdkMemoryFormatDescription *desc = &memory_formats[format];
g_assert (lod_level > 0);
desc->mipmap (dest, dest_stride, src, src_stride, src_width, src_height, lod_level);
}

View File

@ -110,6 +110,14 @@ void gdk_memory_convert_color_state (guchar
GdkColorState *dest_color_state,
gsize width,
gsize height);
void gdk_memory_mipmap (guchar *dest,
gsize dest_stride,
GdkMemoryFormat format,
const guchar *src,
gsize src_stride,
gsize src_width,
gsize src_height,
guint lod_level);
G_END_DECLS

View File

@ -537,6 +537,7 @@ struct _GskGpuCachedTile
GskGpuCached parent;
GdkTexture *texture;
guint lod_level;
gsize tile_id;
/* atomic */ int use_count; /* We count the use by the cache (via the linked
@ -630,7 +631,7 @@ gsk_gpu_cached_tile_hash (gconstpointer 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);
}
static gboolean
@ -641,12 +642,14 @@ gsk_gpu_cached_tile_equal (gconstpointer data_a,
const GskGpuCachedTile *b = data_b;
return a->texture == b->texture &&
a->lod_level == b->lod_level &&
a->tile_id == b->tile_id;
}
static GskGpuCachedTile *
gsk_gpu_cached_tile_new (GskGpuCache *cache,
GdkTexture *texture,
guint lod_level,
guint tile_id,
GskGpuImage *image,
GdkColorState *color_state)
@ -655,6 +658,7 @@ gsk_gpu_cached_tile_new (GskGpuCache *cache,
self = gsk_gpu_cached_new (cache, &GSK_GPU_CACHED_TILE_CLASS);
self->texture = texture;
self->lod_level = lod_level;
self->tile_id = tile_id;
self->image = g_object_ref (image);
self->color_state = gdk_color_state_ref (color_state);
@ -675,12 +679,14 @@ gsk_gpu_cached_tile_new (GskGpuCache *cache,
GskGpuImage *
gsk_gpu_cache_lookup_tile (GskGpuCache *self,
GdkTexture *texture,
guint lod_level,
gsize tile_id,
GdkColorState **out_color_state)
{
GskGpuCachedTile *tile;
GskGpuCachedTile lookup = {
.texture = texture,
.lod_level = lod_level,
.tile_id = tile_id
};
@ -701,13 +707,14 @@ gsk_gpu_cache_lookup_tile (GskGpuCache *self,
void
gsk_gpu_cache_cache_tile (GskGpuCache *self,
GdkTexture *texture,
guint tile_id,
guint lod_level,
gsize tile_id,
GskGpuImage *image,
GdkColorState *color_state)
{
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, tile_id, image, color_state);
gsk_gpu_cached_use (self, (GskGpuCached *) tile);
}

View File

@ -77,11 +77,13 @@ void gsk_gpu_cache_cache_texture_image (GskGpuC
GdkColorState *color_state);
GskGpuImage * gsk_gpu_cache_lookup_tile (GskGpuCache *self,
GdkTexture *texture,
guint lod_level,
gsize tile_id,
GdkColorState **out_color_state);
void gsk_gpu_cache_cache_tile (GskGpuCache *self,
GdkTexture *texture,
guint tile_id,
guint lod_level,
gsize tile_id,
GskGpuImage *image,
GdkColorState *color_state);

View File

@ -107,7 +107,7 @@ gsk_gpu_frame_default_upload_texture (GskGpuFrame *self,
{
GskGpuImage *image;
image = gsk_gpu_upload_texture_op_try (self, with_mipmap, texture);
image = gsk_gpu_upload_texture_op_try (self, with_mipmap, 0, texture);
return image;
}

View File

@ -1964,18 +1964,26 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
gboolean need_mipmap;
GdkMemoryTexture *memtex;
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;
graphene_rect_t clip_bounds;
guint lod_level;
device = gsk_gpu_frame_get_device (self->frame);
cache = gsk_gpu_device_get_cache (device);
sampler = gsk_gpu_sampler_for_scaling_filter (scaling_filter);
need_mipmap = scaling_filter == GSK_SCALING_FILTER_TRILINEAR;
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);
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_height = (height + tile_size - 1) / tile_size;
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))
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, y * n_width + x, &tile_cs);
if (tile == NULL)
{
@ -2005,7 +2013,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
y * tile_size,
MIN (tile_size, width - x * 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, subtex);
g_object_unref (subtex);
if (tile == NULL)
{
@ -2021,7 +2029,7 @@ gsk_gpu_node_processor_draw_texture_tiles (GskGpuNodeProcessor *self,
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, y * n_width + x, tile, tile_cs);
}
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_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, y * n_width + x, tile, tile_cs);
}
if (need_mipmap && !(gsk_gpu_image_get_flags (tile) & GSK_GPU_IMAGE_MIPMAP))
gsk_gpu_mipmap_op (self->frame, tile);

View File

@ -214,6 +214,7 @@ struct _GskGpuUploadTextureOp
GskGpuImage *image;
GskGpuBuffer *buffer;
GdkTexture *texture;
guint lod_level;
};
static void
@ -236,6 +237,8 @@ gsk_gpu_upload_texture_op_print (GskGpuOp *op,
gsk_gpu_print_op (string, indent, "upload-texture");
gsk_gpu_print_image (string, self->image);
if (self->lod_level > 0)
g_string_append_printf (string, " @%ux ", 1 << self->lod_level);
gsk_gpu_print_newline (string);
}
@ -250,7 +253,26 @@ gsk_gpu_upload_texture_op_draw (GskGpuOp *op,
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_download_into (downloader, data, stride);
if (self->lod_level == 0)
{
gdk_texture_downloader_download_into (downloader, data, stride);
}
else
{
GBytes *bytes;
gsize src_stride;
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_width (self->texture),
gdk_texture_get_height (self->texture),
self->lod_level);
g_bytes_unref (bytes);
}
gdk_texture_downloader_free (downloader);
}
@ -298,6 +320,7 @@ static const GskGpuOpClass GSK_GPU_UPLOAD_TEXTURE_OP_CLASS = {
GskGpuImage *
gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
gboolean with_mipmap,
guint lod_level,
GdkTexture *texture)
{
GskGpuUploadTextureOp *self;
@ -311,8 +334,8 @@ gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
format,
gdk_memory_format_alpha (format) != GDK_MEMORY_ALPHA_PREMULTIPLIED &&
gdk_color_state_get_no_srgb_tf (gdk_texture_get_color_state (texture)) != NULL,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
(gdk_texture_get_width (texture) + (1 << lod_level) - 1) >> lod_level,
(gdk_texture_get_height (texture) + (1 << lod_level) - 1) >> lod_level);
if (image == NULL)
return NULL;
@ -343,6 +366,7 @@ gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
self = (GskGpuUploadTextureOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_UPLOAD_TEXTURE_OP_CLASS);
self->texture = g_object_ref (texture);
self->lod_level = lod_level;
self->image = image;
return g_object_ref (self->image);

View File

@ -11,6 +11,7 @@ typedef void (* GskGpuCairoFunc) (gpointe
GskGpuImage * gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
gboolean with_mipmap,
guint lod_level,
GdkTexture *texture);
GskGpuImage * gsk_gpu_upload_cairo_op (GskGpuFrame *frame,