forked from AuroraMiddleware/gtk
texture: Add gdk_texture_download_float()
This commit is contained in:
parent
cbe6d0da76
commit
53275481a5
@ -179,6 +179,60 @@ gdk_gl_texture_download (GdkTexture *texture,
|
||||
glBindTexture (GL_TEXTURE_2D, active_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_float (GdkTexture *texture,
|
||||
float *data)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
int active_texture;
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
glGetIntegerv (GL_TEXTURE_BINDING_2D, &active_texture);
|
||||
glBindTexture (GL_TEXTURE_2D, self->id);
|
||||
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
data);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, active_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
int width, height, y;
|
||||
float *copy;
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download_float (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
if (stride == width * 4)
|
||||
{
|
||||
gdk_gl_texture_do_download_float (texture, data);
|
||||
return;
|
||||
}
|
||||
|
||||
copy = g_new (float, width * height * 4);
|
||||
|
||||
gdk_gl_texture_do_download_float (texture, copy);
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (data + y * stride, copy + y * 4 * width, 4 * width);
|
||||
|
||||
g_free (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
||||
{
|
||||
@ -187,6 +241,7 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
||||
|
||||
texture_class->download_texture = gdk_gl_texture_download_texture;
|
||||
texture_class->download = gdk_gl_texture_download;
|
||||
texture_class->download_float = gdk_gl_texture_download_float;
|
||||
gobject_class->dispose = gdk_gl_texture_dispose;
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,21 @@ gdk_memory_texture_download (GdkTexture *texture,
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert_to_float (data, stride,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
|
||||
{
|
||||
@ -109,6 +124,7 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
|
||||
|
||||
texture_class->download_texture = gdk_memory_texture_download_texture;
|
||||
texture_class->download = gdk_memory_texture_download;
|
||||
texture_class->download_float = gdk_memory_texture_download_float;
|
||||
gobject_class->dispose = gdk_memory_texture_dispose;
|
||||
}
|
||||
|
||||
@ -323,3 +339,82 @@ gdk_memory_convert (guchar *dest_data,
|
||||
|
||||
converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
|
||||
}
|
||||
|
||||
#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
if (A >= 0) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
|
||||
if (premultiply) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = 1.0; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
void
|
||||
gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
switch (src_format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
CONVERT_FLOAT (3, 2, 1, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
CONVERT_FLOAT (0, 1, 2, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
CONVERT_FLOAT (2, 1, 0, -1, FALSE);
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,14 @@ void gdk_memory_convert (guchar
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
void gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -134,6 +134,18 @@ gdk_texture_real_download (GdkTexture *texture,
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download_float (GdkTexture *self,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (self);
|
||||
gdk_texture_download_float (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
@ -199,6 +211,7 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
|
||||
klass->download_texture = gdk_texture_real_download_texture;
|
||||
klass->download = gdk_texture_real_download;
|
||||
klass->download_float = gdk_texture_real_download_float;
|
||||
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
@ -485,6 +498,45 @@ gdk_texture_download (GdkTexture *texture,
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download_float:
|
||||
* @texture: a `GdkTexture`
|
||||
* @data: (array): pointer to enough memory to be filled with the
|
||||
* downloaded data of @texture
|
||||
* @stride: rowstride in elements, will usually be equal to
|
||||
* gdk_texture_get_width() * 4
|
||||
*
|
||||
* Downloads the @texture into local memory in a high dynamic range format.
|
||||
*
|
||||
* This may be an expensive operation, as the actual texture data
|
||||
* may reside on a GPU or on a remote display server and because the data
|
||||
* may need to be upsampled if it was not already available in this
|
||||
* format.
|
||||
*
|
||||
* You may want to use [method@Gdk.Texture.download] instead if you don't
|
||||
* need high dynamic range support.
|
||||
*
|
||||
* The data format of the downloaded data is equivalent to
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, so every downloaded
|
||||
* pixel requires 16 bytes of memory.
|
||||
*
|
||||
* Note that the caller is responsible to provide sufficiently
|
||||
* aligned memory to access the resulting data directly as floats.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
void
|
||||
gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
|
@ -59,6 +59,10 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
void gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename);
|
||||
|
@ -30,6 +30,9 @@ struct _GdkTextureClass {
|
||||
void (* download) (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
void (* download_float) (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
};
|
||||
|
||||
gpointer gdk_texture_new (const GdkTextureClass *klass,
|
||||
|
Loading…
Reference in New Issue
Block a user