gpu: create SRGB images

If desired, try creating GL_SRGB images. Pass a try_srgb boolean down to
the image creation functions and have them attempt to create images like
that.

When it is not possible to create srgb images in the given format, just
fall back to regular images. The calling code is meant to check the
GSK_GPU_IMAGE_SRGB flags to determine the actual format of the resulting
image.
This commit is contained in:
Benjamin Otte
2024-06-26 18:17:56 +02:00
parent 527f305690
commit d85ec2cbb4
10 changed files with 118 additions and 18 deletions

View File

@@ -76,6 +76,7 @@ gsk_gl_device_create_offscreen_image (GskGpuDevice *device,
return gsk_gl_image_new (self,
gdk_memory_depth_get_format (depth),
gdk_memory_depth_is_srgb (depth),
GSK_GPU_IMAGE_RENDERABLE | GSK_GPU_IMAGE_FILTERABLE,
width,
height);
@@ -85,6 +86,7 @@ static GskGpuImage *
gsk_gl_device_create_upload_image (GskGpuDevice *device,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height)
{
@@ -92,6 +94,7 @@ gsk_gl_device_create_upload_image (GskGpuDevice *device,
return gsk_gl_image_new (self,
format,
try_srgb,
0,
width,
height);
@@ -107,6 +110,7 @@ gsk_gl_device_create_download_image (GskGpuDevice *device,
return gsk_gl_image_new (self,
gdk_memory_depth_get_format (depth),
gdk_memory_depth_is_srgb (depth),
GSK_GPU_IMAGE_RENDERABLE,
width,
height);
@@ -121,6 +125,7 @@ gsk_gl_device_create_atlas_image (GskGpuDevice *device,
return gsk_gl_image_new (self,
GDK_MEMORY_DEFAULT,
FALSE,
GSK_GPU_IMAGE_RENDERABLE,
width,
height);

View File

@@ -125,6 +125,7 @@ gsk_gl_image_new_backbuffer (GskGLDevice *device,
GskGpuImage *
gsk_gl_image_new (GskGLDevice *device,
GdkMemoryFormat format,
gboolean try_srgb,
GskGpuImageFlags required_flags,
gsize width,
gsize height)
@@ -152,7 +153,15 @@ gsk_gl_image_new (GskGLDevice *device,
&self->gl_type,
swizzle);
self->gl_internal_format = gl_internal_format;
if (try_srgb && gl_internal_srgb_format != -1)
{
self->gl_internal_format = gl_internal_srgb_format;
flags |= GSK_GPU_IMAGE_SRGB;
}
else
{
self->gl_internal_format = gl_internal_format;
}
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
flags,

View File

@@ -18,6 +18,7 @@ GskGpuImage * gsk_gl_image_new_backbuffer (GskGLDe
gsize height);
GskGpuImage * gsk_gl_image_new (GskGLDevice *device,
GdkMemoryFormat format,
gboolean try_srgb,
GskGpuImageFlags required_flags,
gsize width,
gsize height);

View File

@@ -829,7 +829,7 @@ gsk_gpu_cache_lookup_glyph_image (GskGpuCache *self,
}
else
{
image = gsk_gpu_device_create_upload_image (self->device, GDK_MEMORY_DEFAULT, FALSE, rect.size.width, rect.size.height),
image = gsk_gpu_device_create_upload_image (self->device, FALSE, GDK_MEMORY_DEFAULT, FALSE, rect.size.width, rect.size.height),
rect.origin.x = 0;
rect.origin.y = 0;
padding = 0;

View File

@@ -230,10 +230,11 @@ GskGpuImage *
gsk_gpu_device_create_upload_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height)
{
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, with_mipmap, format, width, height);
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, with_mipmap, format, try_srgb, width, height);
}
GskGpuImage *

View File

@@ -35,6 +35,7 @@ struct _GskGpuDeviceClass
GskGpuImage * (* create_upload_image) (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height);
GskGpuImage * (* create_download_image) (GskGpuDevice *self,
@@ -67,6 +68,7 @@ GskGpuImage * gsk_gpu_device_create_atlas_image (GskGpuD
GskGpuImage * gsk_gpu_device_create_upload_image (GskGpuDevice *self,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height);
GskGpuImage * gsk_gpu_device_create_download_image (GskGpuDevice *self,

View File

@@ -12,6 +12,7 @@
#include "gskvulkanimageprivate.h"
#endif
#include "gdk/gdkcolorstateprivate.h"
#include "gdk/gdkglcontextprivate.h"
#include "gsk/gskdebugprivate.h"
@@ -304,6 +305,7 @@ gsk_gpu_upload_texture_op_try (GskGpuFrame *frame,
image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
with_mipmap,
gdk_texture_get_format (texture),
gdk_color_state_get_no_srgb_tf (gdk_texture_get_color_state (texture)) != NULL,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
if (image == NULL)
@@ -470,6 +472,7 @@ gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
FALSE,
GDK_MEMORY_DEFAULT,
gdk_color_state_get_no_srgb_tf (GDK_COLOR_STATE_SRGB) != NULL,
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
self->viewport = *viewport;

View File

@@ -371,6 +371,7 @@ gsk_vulkan_device_create_offscreen_image (GskGpuDevice *device,
return gsk_vulkan_image_new_for_offscreen (self,
with_mipmap,
gdk_memory_depth_get_format (depth),
gdk_memory_depth_is_srgb (depth),
width,
height);
}
@@ -391,6 +392,7 @@ static GskGpuImage *
gsk_vulkan_device_create_upload_image (GskGpuDevice *device,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height)
{
@@ -399,6 +401,7 @@ gsk_vulkan_device_create_upload_image (GskGpuDevice *device,
return gsk_vulkan_image_new_for_upload (self,
with_mipmap,
format,
try_srgb,
width,
height);
}
@@ -415,6 +418,7 @@ gsk_vulkan_device_create_download_image (GskGpuDevice *device,
#ifdef HAVE_DMABUF
image = gsk_vulkan_image_new_dmabuf (self,
gdk_memory_depth_get_format (depth),
gdk_memory_depth_is_srgb (depth),
width,
height);
if (image != NULL)
@@ -424,6 +428,7 @@ gsk_vulkan_device_create_download_image (GskGpuDevice *device,
image = gsk_vulkan_image_new_for_offscreen (self,
FALSE,
gdk_memory_depth_get_format (depth),
gdk_memory_depth_is_srgb (depth),
width,
height);

View File

@@ -243,6 +243,7 @@ gsk_vulkan_device_check_format (GskVulkanDevice *device,
static GskVulkanImage *
gsk_vulkan_image_new (GskVulkanDevice *device,
GdkMemoryFormat format,
gboolean try_srgb,
GskGpuImageFlags required_flags,
gsize width,
gsize height,
@@ -257,22 +258,42 @@ gsk_vulkan_image_new (GskVulkanDevice *device,
GskVulkanImage *self;
VkDevice vk_device;
GskGpuImageFlags flags;
VkFormat vk_format;
VkFormat vk_format, vk_srgb_format;
VkComponentMapping vk_components;
g_assert (width > 0 && height > 0);
vk_srgb_format = VK_FORMAT_UNDEFINED;
/* First, try the actual format */
vk_format = gdk_memory_format_vk_format (format, &vk_components);
if (!gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (format);
if (gsk_vulkan_device_check_format (device, vk_srgb_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
vk_format = vk_srgb_format;
}
else if (!gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
GdkMemoryFormat rgba_format;
/* Second, try the potential RGBA format */
vk_format = gdk_memory_format_vk_rgba_format (format, NULL, &vk_components);
if (!gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
vk_format = gdk_memory_format_vk_rgba_format (format, &rgba_format, &vk_components);
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (rgba_format);
if (gsk_vulkan_device_check_format (device, vk_srgb_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
vk_format = vk_srgb_format;
}
else if (!gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
const GdkMemoryFormat *fallbacks;
gsize i;
@@ -282,9 +303,19 @@ gsk_vulkan_image_new (GskVulkanDevice *device,
for (i = 0; fallbacks[i] != -1; i++)
{
vk_format = gdk_memory_format_vk_format (fallbacks[i], &vk_components);
if (gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (fallbacks[i]);
if (gsk_vulkan_device_check_format (device, vk_srgb_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
vk_format = vk_srgb_format;
format = fallbacks[i];
break;
}
else if (gsk_vulkan_device_check_format (device, vk_format, &vk_components, required_flags,
tiling, usage, width, height,
&tiling, &flags))
{
format = fallbacks[i];
break;
@@ -297,6 +328,9 @@ gsk_vulkan_image_new (GskVulkanDevice *device,
}
}
if (vk_format == vk_srgb_format)
flags |= GSK_GPU_IMAGE_SRGB;
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
flags |= GSK_GPU_IMAGE_STRAIGHT_ALPHA;
@@ -369,6 +403,7 @@ GskGpuImage *
gsk_vulkan_image_new_for_upload (GskVulkanDevice *device,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height)
{
@@ -376,6 +411,7 @@ gsk_vulkan_image_new_for_upload (GskVulkanDevice *device,
self = gsk_vulkan_image_new (device,
format,
try_srgb,
with_mipmap ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_RENDERABLE | GSK_GPU_IMAGE_FILTERABLE) : 0,
width,
height,
@@ -482,6 +518,7 @@ gsk_vulkan_image_new_for_atlas (GskVulkanDevice *device,
self = gsk_vulkan_image_new (device,
GDK_MEMORY_DEFAULT,
TRUE,
GSK_GPU_IMAGE_FILTERABLE | GSK_GPU_IMAGE_RENDERABLE,
width,
height,
@@ -499,6 +536,7 @@ GskGpuImage *
gsk_vulkan_image_new_for_offscreen (GskVulkanDevice *device,
gboolean with_mipmap,
GdkMemoryFormat preferred_format,
gboolean try_srgb,
gsize width,
gsize height)
{
@@ -506,6 +544,7 @@ gsk_vulkan_image_new_for_offscreen (GskVulkanDevice *device,
self = gsk_vulkan_image_new (device,
preferred_format,
try_srgb,
GSK_GPU_IMAGE_RENDERABLE |
(with_mipmap ? GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_FILTERABLE : 0),
width,
@@ -623,12 +662,13 @@ gsk_vulkan_device_check_dmabuf_format (GskVulkanDevice *device,
GskGpuImage *
gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height)
{
uint64_t modifiers[100];
VkDevice vk_device;
VkFormat vk_format;
VkFormat vk_format, vk_srgb_format;
VkComponentMapping vk_components;
VkMemoryRequirements requirements;
GskVulkanImage *self;
@@ -639,20 +679,41 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
if (!gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_DMABUF))
return NULL;
vk_srgb_format = VK_FORMAT_UNDEFINED;
vk_device = gsk_vulkan_device_get_vk_device (device);
/* First, try the actual format */
vk_format = gdk_memory_format_vk_format (format, &vk_components);
if (!gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (format);
if (gsk_vulkan_device_check_dmabuf_format (device, vk_srgb_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
vk_format = vk_srgb_format;
}
else if (!gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
/* Second, try the potential RGBA format, but as a fallback */
GdkMemoryFormat rgba_format;
vk_format = gdk_memory_format_vk_rgba_format (format, &rgba_format, NULL);
if (vk_format != VK_FORMAT_UNDEFINED)
vk_format = gdk_memory_format_vk_format (rgba_format, &vk_components);
if (gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
{
vk_format = gdk_memory_format_vk_format (rgba_format, &vk_components);
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (format);
}
else
vk_srgb_format = VK_FORMAT_UNDEFINED;
if (gsk_vulkan_device_check_dmabuf_format (device, vk_srgb_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
vk_format = vk_srgb_format;
format = rgba_format;
}
else if (gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
format = rgba_format;
}
@@ -666,8 +727,17 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
for (i = 0; fallbacks[i] != -1; i++)
{
vk_format = gdk_memory_format_vk_format (fallbacks[i], &vk_components);
if (gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
if (try_srgb)
vk_srgb_format = gdk_memory_format_vk_srgb_format (format);
if (gsk_vulkan_device_check_dmabuf_format (device, vk_srgb_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
vk_format = vk_srgb_format;
format = fallbacks[i];
break;
}
else if (gsk_vulkan_device_check_dmabuf_format (device, vk_format, &vk_components, width, height,
modifiers, &flags, &n_modifiers))
{
format = fallbacks[i];
break;
@@ -692,6 +762,7 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
flags | GSK_GPU_IMAGE_EXTERNAL |
(vk_format == vk_srgb_format ? GSK_GPU_IMAGE_SRGB : 0) |
(gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0) |
(gsk_component_mapping_is_framebuffer_compatible (&vk_components) ? 0 : GSK_GPU_IMAGE_NO_BLIT),
format,

View File

@@ -24,16 +24,19 @@ GskGpuImage * gsk_vulkan_image_new_for_atlas (GskVulk
GskGpuImage * gsk_vulkan_image_new_for_offscreen (GskVulkanDevice *device,
gboolean with_mipmap,
GdkMemoryFormat preferred_format,
gboolean try_srgb,
gsize width,
gsize height);
GskGpuImage * gsk_vulkan_image_new_for_upload (GskVulkanDevice *device,
gboolean with_mipmap,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height);
#ifdef HAVE_DMABUF
GskGpuImage * gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
GdkMemoryFormat format,
gboolean try_srgb,
gsize width,
gsize height);
GskGpuImage * gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,