#include "config.h"
#include "gskgpumipmapopprivate.h"
#include "gskglimageprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskgpuutilsprivate.h"
#ifdef GDK_RENDERING_VULKAN
#include "gskvulkanimageprivate.h"
#endif
typedef struct _GskGpuMipmapOp GskGpuMipmapOp;
struct _GskGpuMipmapOp
{
GskGpuOp op;
GskGpuImage *image;
};
static void
gsk_gpu_mipmap_op_finish (GskGpuOp *op)
{
GskGpuMipmapOp *self = (GskGpuMipmapOp *) op;
g_object_unref (self->image);
}
static void
gsk_gpu_mipmap_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuMipmapOp *self = (GskGpuMipmapOp *) op;
gsk_gpu_print_op (string, indent, "mipmap" );
gsk_gpu_print_image (string, self->image);
gsk_gpu_print_newline (string);
}
#ifdef GDK_RENDERING_VULKAN
static GskGpuOp *
gsk_gpu_mipmap_op_vk_command (GskGpuOp *op,
GskGpuFrame *frame,
GskVulkanCommandState *state)
{
GskGpuMipmapOp *self = (GskGpuMipmapOp *) op;
GskVulkanImage *image;
VkImage vk_image;
gsize width, height;
guint i, n_levels;
image = GSK_VULKAN_IMAGE (self->image);
vk_image = gsk_vulkan_image_get_vk_image (image);
width = gsk_gpu_image_get_width (self->image);
height = gsk_gpu_image_get_height (self->image);
n_levels = gsk_gpu_mipmap_levels (width, height);
/* optimize me: only transition mipmap layers 1..n, but not 0 */
gsk_vulkan_image_transition (image,
state->semaphores,
state->vk_command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT);
for (i = 0 ; /* we break after the barrier */ ; i++)
{
vkCmdPipelineBarrier (state->vk_command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0 ,
0 , NULL,
0 , NULL,
1 , &(VkImageMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = vk_image,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = i,
.levelCount = 1 ,
.baseArrayLayer = 0 ,
.layerCount = 1
},
});
if (i + 1 == n_levels)
break ;
vkCmdBlitImage (state->vk_command_buffer,
vk_image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
vk_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1 ,
&(VkImageBlit) {
.srcSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = i,
.baseArrayLayer = 0 ,
.layerCount = 1
},
.srcOffsets = {
{
.x = 0 ,
.y = 0 ,
.z = 0 ,
},
{
.x = width,
.y = height,
.z = 1
}
},
.dstSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = i + 1 ,
.baseArrayLayer = 0 ,
.layerCount = 1
},
.dstOffsets = {
{
.x = 0 ,
.y = 0 ,
.z = 0 ,
},
{
.x = MAX (1 , width / 2 ),
.y = MAX (1 , height / 2 ),
.z = 1 ,
}
},
},
VK_FILTER_LINEAR);
width = MAX (1 , width / 2 );
height = MAX (1 , height / 2 );
}
gsk_vulkan_image_set_vk_image_layout (image,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT);
return op->next;
}
#endif
static GskGpuOp *
gsk_gpu_mipmap_op_gl_command (GskGpuOp *op,
GskGpuFrame *frame,
GskGLCommandState *state)
{
GskGpuMipmapOp *self = (GskGpuMipmapOp *) op;
gsk_gl_image_bind_textures (GSK_GL_IMAGE (self->image), GL_TEXTURE0);
/* need to reset the images again */
state->current_images[0 ] = NULL;
glGenerateMipmap (GL_TEXTURE_2D);
return op->next;
}
static const GskGpuOpClass GSK_GPU_MIPMAP_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuMipmapOp),
GSK_GPU_STAGE_PASS,
gsk_gpu_mipmap_op_finish,
gsk_gpu_mipmap_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_mipmap_op_vk_command,
#endif
gsk_gpu_mipmap_op_gl_command
};
void
gsk_gpu_mipmap_op (GskGpuFrame *frame,
GskGpuImage *image)
{
GskGpuMipmapOp *self;
g_assert ((gsk_gpu_image_get_flags (image) & (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP)) == GSK_GPU_IMAGE_CAN_MIPMAP);
self = (GskGpuMipmapOp *) gsk_gpu_frame_alloc_op (frame, &GSK_GPU_MIPMAP_OP_CLASS);
self->image = g_object_ref (image);
gsk_gpu_image_set_flags (image, GSK_GPU_IMAGE_MIPMAP);
}
Messung V0.5 in Prozent C=98 H=95 G=96
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland