2021-09-11 20:50:09 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2021-10-07 03:15:25 +00:00
|
|
|
#include "gsk/gl/gskglrenderer.h"
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
#define N 20
|
2021-09-11 19:19:48 +00:00
|
|
|
|
2021-09-11 20:50:09 +00:00
|
|
|
static GskRenderer *gl_renderer = NULL;
|
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
typedef struct _TextureBuilder TextureBuilder;
|
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
typedef enum {
|
|
|
|
TEXTURE_METHOD_LOCAL,
|
|
|
|
TEXTURE_METHOD_GL,
|
|
|
|
TEXTURE_METHOD_GL_RELEASED,
|
2021-09-14 00:37:50 +00:00
|
|
|
TEXTURE_METHOD_PNG,
|
|
|
|
TEXTURE_METHOD_PNG_PIXBUF,
|
|
|
|
TEXTURE_METHOD_TIFF,
|
|
|
|
TEXTURE_METHOD_TIFF_PIXBUF,
|
2021-09-11 22:11:44 +00:00
|
|
|
|
|
|
|
N_TEXTURE_METHODS
|
|
|
|
} TextureMethod;
|
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
struct _TextureBuilder
|
|
|
|
{
|
|
|
|
GdkMemoryFormat format;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
guchar *pixels;
|
|
|
|
gsize stride;
|
|
|
|
gsize offset;
|
|
|
|
};
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
static gsize
|
|
|
|
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case GDK_MEMORY_R8G8B8:
|
|
|
|
case GDK_MEMORY_B8G8R8:
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_B8G8R8A8:
|
|
|
|
case GDK_MEMORY_A8R8G8B8:
|
|
|
|
case GDK_MEMORY_R8G8B8A8:
|
|
|
|
case GDK_MEMORY_A8B8G8R8:
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
case GDK_MEMORY_R16G16B16:
|
|
|
|
case GDK_MEMORY_R16G16B16_FLOAT:
|
|
|
|
return 6;
|
|
|
|
|
|
|
|
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16:
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
2021-09-11 19:19:48 +00:00
|
|
|
return 8;
|
|
|
|
|
|
|
|
case GDK_MEMORY_R32G32B32_FLOAT:
|
|
|
|
return 12;
|
|
|
|
|
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
2021-09-11 19:19:48 +00:00
|
|
|
return 16;
|
|
|
|
|
|
|
|
case GDK_MEMORY_N_FORMATS:
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_memory_format_has_alpha (GdkMemoryFormat format)
|
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case GDK_MEMORY_R8G8B8:
|
|
|
|
case GDK_MEMORY_B8G8R8:
|
|
|
|
case GDK_MEMORY_R16G16B16:
|
|
|
|
case GDK_MEMORY_R16G16B16_FLOAT:
|
|
|
|
case GDK_MEMORY_R32G32B32_FLOAT:
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
|
|
|
case GDK_MEMORY_B8G8R8A8:
|
|
|
|
case GDK_MEMORY_A8R8G8B8:
|
|
|
|
case GDK_MEMORY_R8G8B8A8:
|
|
|
|
case GDK_MEMORY_A8B8G8R8:
|
|
|
|
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16:
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
2021-09-11 19:19:48 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case GDK_MEMORY_N_FORMATS:
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
static gpointer
|
|
|
|
encode (GdkMemoryFormat format,
|
|
|
|
TextureMethod method)
|
|
|
|
{
|
|
|
|
return GSIZE_TO_POINTER (method * GDK_MEMORY_N_FORMATS + format);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
decode (gconstpointer data,
|
|
|
|
GdkMemoryFormat *format,
|
|
|
|
TextureMethod *method)
|
|
|
|
{
|
|
|
|
gsize value = GPOINTER_TO_SIZE (data);
|
|
|
|
|
|
|
|
*format = value % GDK_MEMORY_N_FORMATS;
|
|
|
|
value /= GDK_MEMORY_N_FORMATS;
|
|
|
|
|
|
|
|
*method = value;
|
|
|
|
}
|
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
static void
|
|
|
|
texture_builder_init (TextureBuilder *builder,
|
|
|
|
GdkMemoryFormat format,
|
|
|
|
int width,
|
|
|
|
int height)
|
|
|
|
{
|
|
|
|
gsize extra_stride;
|
|
|
|
|
|
|
|
builder->format = format;
|
|
|
|
builder->width = width;
|
|
|
|
builder->height = height;
|
|
|
|
|
|
|
|
extra_stride = g_test_rand_bit() ? g_test_rand_int_range (0, 16) : 0;
|
|
|
|
builder->offset = g_test_rand_bit() ? g_test_rand_int_range (0, 128) : 0;
|
|
|
|
builder->stride = width * gdk_memory_format_bytes_per_pixel (format) + extra_stride;
|
|
|
|
builder->pixels = g_malloc0 (builder->offset + builder->stride * height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GdkTexture *
|
|
|
|
texture_builder_finish (TextureBuilder *builder)
|
|
|
|
{
|
|
|
|
GBytes *bytes;
|
|
|
|
GdkTexture *texture;
|
|
|
|
|
|
|
|
bytes = g_bytes_new_with_free_func (builder->pixels + builder->offset,
|
|
|
|
builder->height * builder->stride,
|
|
|
|
g_free,
|
|
|
|
builder->pixels);
|
|
|
|
texture = gdk_memory_texture_new (builder->width,
|
|
|
|
builder->height,
|
|
|
|
builder->format,
|
|
|
|
bytes,
|
|
|
|
builder->stride);
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
set_pixel_u8 (guchar *data,
|
|
|
|
int r,
|
|
|
|
int g,
|
|
|
|
int b,
|
|
|
|
int a,
|
|
|
|
gboolean premultiply,
|
|
|
|
const GdkRGBA *color)
|
|
|
|
{
|
|
|
|
if (a >= 0)
|
|
|
|
data[a] = CLAMP (color->alpha * 256.f, 0.f, 255.f);
|
|
|
|
if (premultiply)
|
|
|
|
{
|
|
|
|
data[r] = CLAMP (color->red * color->alpha * 256.f, 0.f, 255.f);
|
|
|
|
data[g] = CLAMP (color->green * color->alpha * 256.f, 0.f, 255.f);
|
|
|
|
data[b] = CLAMP (color->blue * color->alpha * 256.f, 0.f, 255.f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data[r] = CLAMP (color->red * 256.f, 0.f, 255.f);
|
|
|
|
data[g] = CLAMP (color->green * 256.f, 0.f, 255.f);
|
|
|
|
data[b] = CLAMP (color->blue * 256.f, 0.f, 255.f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline guint16
|
|
|
|
float_to_half (const float x)
|
|
|
|
{
|
|
|
|
const guint b = *(guint*)&x+0x00001000; // round-to-nearest-even
|
|
|
|
const guint e = (b&0x7F800000)>>23; // exponent
|
|
|
|
const guint m = b&0x007FFFFF; // mantissa
|
|
|
|
return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; // sign : normalized : denormalized : saturate
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
texture_builder_set_pixel (TextureBuilder *builder,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
const GdkRGBA *color)
|
|
|
|
{
|
|
|
|
guchar *data;
|
|
|
|
|
|
|
|
g_assert_cmpint (x, >=, 0);
|
|
|
|
g_assert_cmpint (x, <, builder->width);
|
|
|
|
g_assert_cmpint (y, >=, 0);
|
|
|
|
g_assert_cmpint (y, <, builder->height);
|
|
|
|
|
|
|
|
data = builder->pixels
|
|
|
|
+ builder->offset
|
|
|
|
+ y * builder->stride
|
|
|
|
+ x * gdk_memory_format_bytes_per_pixel (builder->format);
|
|
|
|
|
|
|
|
switch (builder->format)
|
|
|
|
{
|
|
|
|
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
|
|
|
set_pixel_u8 (data, 2, 1, 0, 3, TRUE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
|
|
|
set_pixel_u8 (data, 1, 2, 3, 0, TRUE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
|
|
|
set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_B8G8R8A8:
|
|
|
|
set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_A8R8G8B8:
|
|
|
|
set_pixel_u8 (data, 1, 2, 3, 0, FALSE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R8G8B8A8:
|
|
|
|
set_pixel_u8 (data, 0, 1, 2, 3, FALSE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_A8B8G8R8:
|
|
|
|
set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R8G8B8:
|
|
|
|
set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_B8G8R8:
|
|
|
|
set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color);
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R16G16B16:
|
|
|
|
{
|
|
|
|
guint16 pixels[3] = {
|
|
|
|
CLAMP (color->red * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->green * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->blue * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 3 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
|
|
|
{
|
|
|
|
guint16 pixels[4] = {
|
|
|
|
CLAMP (color->red * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->green * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->blue * color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16:
|
|
|
|
{
|
|
|
|
guint16 pixels[4] = {
|
|
|
|
CLAMP (color->red * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->green * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->blue * 65536.f, 0, 65535.f),
|
|
|
|
CLAMP (color->alpha * 65536.f, 0, 65535.f),
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_R16G16B16_FLOAT:
|
|
|
|
{
|
|
|
|
guint16 pixels[3] = {
|
|
|
|
float_to_half (color->red * color->alpha),
|
|
|
|
float_to_half (color->green * color->alpha),
|
|
|
|
float_to_half (color->blue * color->alpha)
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 3 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
|
|
|
{
|
|
|
|
guint16 pixels[4] = {
|
|
|
|
float_to_half (color->red * color->alpha),
|
|
|
|
float_to_half (color->green * color->alpha),
|
|
|
|
float_to_half (color->blue * color->alpha),
|
|
|
|
float_to_half (color->alpha)
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
|
|
|
{
|
|
|
|
guint16 pixels[4] = {
|
|
|
|
float_to_half (color->red),
|
|
|
|
float_to_half (color->green),
|
|
|
|
float_to_half (color->blue),
|
|
|
|
float_to_half (color->alpha)
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (guint16));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_R32G32B32_FLOAT:
|
|
|
|
{
|
|
|
|
float pixels[3] = {
|
|
|
|
color->red * color->alpha,
|
|
|
|
color->green * color->alpha,
|
|
|
|
color->blue * color->alpha
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 3 * sizeof (float));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
|
|
|
{
|
|
|
|
float pixels[4] = {
|
|
|
|
color->red * color->alpha,
|
|
|
|
color->green * color->alpha,
|
|
|
|
color->blue * color->alpha,
|
|
|
|
color->alpha
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (float));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-26 14:47:34 +00:00
|
|
|
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
|
|
|
{
|
|
|
|
float pixels[4] = {
|
|
|
|
color->red,
|
|
|
|
color->green,
|
|
|
|
color->blue,
|
|
|
|
color->alpha
|
|
|
|
};
|
|
|
|
memcpy (data, pixels, 4 * sizeof (float));
|
|
|
|
}
|
|
|
|
break;
|
2021-09-11 19:19:48 +00:00
|
|
|
case GDK_MEMORY_N_FORMATS:
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
texture_builder_fill (TextureBuilder *builder,
|
|
|
|
const GdkRGBA *color)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (y = 0; y < builder->height; y++)
|
|
|
|
for (x = 0; x < builder->width; x++)
|
|
|
|
texture_builder_set_pixel (builder, x, y, color);
|
|
|
|
}
|
|
|
|
|
2018-03-12 04:12:54 +00:00
|
|
|
static void
|
|
|
|
compare_textures (GdkTexture *expected,
|
|
|
|
GdkTexture *test,
|
2021-09-11 19:19:48 +00:00
|
|
|
gboolean has_alpha)
|
2018-03-12 04:12:54 +00:00
|
|
|
{
|
2021-09-11 19:19:48 +00:00
|
|
|
guint32 *expected_data, *test_data;
|
2020-07-24 13:54:49 +00:00
|
|
|
int width, height;
|
|
|
|
int x, y;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
|
|
|
g_assert_cmpint (gdk_texture_get_width (expected), ==, gdk_texture_get_width (test));
|
|
|
|
g_assert_cmpint (gdk_texture_get_height (expected), ==, gdk_texture_get_height (test));
|
|
|
|
|
|
|
|
width = gdk_texture_get_width (expected);
|
|
|
|
height = gdk_texture_get_height (expected);
|
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
expected_data = g_new (guint32, width * height);
|
|
|
|
gdk_texture_download (expected, (guchar *) expected_data, width * 4);
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
test_data = g_new (guint32, width * height);
|
|
|
|
gdk_texture_download (test, (guchar *) test_data, width * 4);
|
2018-03-12 04:12:54 +00:00
|
|
|
|
|
|
|
for (y = 0; y < height; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < width; x++)
|
|
|
|
{
|
2021-09-11 19:19:48 +00:00
|
|
|
if (has_alpha)
|
|
|
|
g_assert_cmphex (expected_data[y * width + x], ==, test_data[y * width + x]);
|
2018-03-12 04:12:54 +00:00
|
|
|
else
|
2021-09-11 19:19:48 +00:00
|
|
|
g_assert_cmphex (expected_data[y * width + x] | 0xFF000000, ==, test_data[y * width + x]);
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (expected_data);
|
|
|
|
g_free (test_data);
|
|
|
|
}
|
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
static GdkTexture *
|
|
|
|
upload_to_gl (GdkTexture *texture)
|
|
|
|
{
|
|
|
|
GskRenderNode *node;
|
|
|
|
GdkTexture *result;
|
|
|
|
|
|
|
|
if (gl_renderer == NULL)
|
|
|
|
return texture;
|
|
|
|
|
|
|
|
node = gsk_texture_node_new (texture,
|
|
|
|
&GRAPHENE_RECT_INIT(
|
|
|
|
0, 0,
|
|
|
|
gdk_texture_get_width (texture),
|
|
|
|
gdk_texture_get_height (texture)
|
|
|
|
));
|
|
|
|
result = gsk_renderer_render_texture (gl_renderer, node, NULL);
|
|
|
|
gsk_render_node_unref (node);
|
|
|
|
g_object_unref (texture);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-03-12 04:12:54 +00:00
|
|
|
static GdkTexture *
|
|
|
|
create_texture (GdkMemoryFormat format,
|
2021-09-11 22:11:44 +00:00
|
|
|
TextureMethod method,
|
2018-03-12 04:12:54 +00:00
|
|
|
int width,
|
|
|
|
int height,
|
2021-09-11 19:19:48 +00:00
|
|
|
const GdkRGBA *color)
|
2018-03-12 04:12:54 +00:00
|
|
|
{
|
2021-09-11 19:19:48 +00:00
|
|
|
TextureBuilder builder;
|
2021-09-11 22:11:44 +00:00
|
|
|
GdkTexture *texture;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 19:19:48 +00:00
|
|
|
texture_builder_init (&builder, format, width, height);
|
|
|
|
texture_builder_fill (&builder, color);
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
texture = texture_builder_finish (&builder);
|
|
|
|
|
|
|
|
switch (method)
|
|
|
|
{
|
|
|
|
case TEXTURE_METHOD_LOCAL:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_METHOD_GL:
|
|
|
|
texture = upload_to_gl (texture);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_METHOD_GL_RELEASED:
|
|
|
|
texture = upload_to_gl (texture);
|
2021-10-18 11:38:35 +00:00
|
|
|
if (GDK_IS_GL_TEXTURE (texture))
|
|
|
|
gdk_gl_texture_release (GDK_GL_TEXTURE (texture));
|
2021-09-11 22:11:44 +00:00
|
|
|
break;
|
|
|
|
|
2021-09-14 00:37:50 +00:00
|
|
|
case TEXTURE_METHOD_PNG:
|
|
|
|
{
|
|
|
|
GBytes *bytes = gdk_texture_save_to_png_bytes (texture);
|
|
|
|
g_assert (bytes);
|
|
|
|
g_object_unref (texture);
|
|
|
|
texture = gdk_texture_new_from_bytes (bytes, NULL);
|
|
|
|
g_assert (texture);
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_METHOD_PNG_PIXBUF:
|
|
|
|
{
|
|
|
|
GInputStream *stream;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
GBytes *bytes;
|
|
|
|
|
|
|
|
bytes = gdk_texture_save_to_png_bytes (texture);
|
|
|
|
g_assert (bytes);
|
|
|
|
g_object_unref (texture);
|
|
|
|
stream = g_memory_input_stream_new_from_bytes (bytes);
|
|
|
|
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
|
|
|
|
g_object_unref (stream);
|
|
|
|
g_assert (pixbuf);
|
|
|
|
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
|
|
|
g_assert (texture);
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_METHOD_TIFF:
|
|
|
|
{
|
|
|
|
GBytes *bytes = gdk_texture_save_to_tiff_bytes (texture);
|
|
|
|
g_assert (bytes);
|
|
|
|
g_object_unref (texture);
|
|
|
|
texture = gdk_texture_new_from_bytes (bytes, NULL);
|
|
|
|
g_assert (texture);
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEXTURE_METHOD_TIFF_PIXBUF:
|
|
|
|
{
|
|
|
|
GInputStream *stream;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
GBytes *bytes;
|
|
|
|
|
|
|
|
bytes = gdk_texture_save_to_png_bytes (texture);
|
|
|
|
g_assert (bytes);
|
|
|
|
g_object_unref (texture);
|
|
|
|
stream = g_memory_input_stream_new_from_bytes (bytes);
|
|
|
|
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
|
|
|
|
g_object_unref (stream);
|
|
|
|
g_assert (pixbuf);
|
|
|
|
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
|
|
|
g_assert (texture);
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
case N_TEXTURE_METHODS:
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return texture;
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-11 20:26:37 +00:00
|
|
|
create_random_color (GdkRGBA *color)
|
2018-03-12 04:12:54 +00:00
|
|
|
{
|
2021-09-11 20:26:37 +00:00
|
|
|
/* Generate colors so that premultiplying will result in values in steps of 1/15th */
|
|
|
|
color->red = g_test_rand_int_range (0, 6) / 5.f;
|
|
|
|
color->green = g_test_rand_int_range (0, 6) / 5.f;
|
|
|
|
color->blue = g_test_rand_int_range (0, 6) / 5.f;
|
|
|
|
color->alpha = g_test_rand_int_range (0, 4) / 3.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-11 22:11:44 +00:00
|
|
|
test_download_1x1 (gconstpointer data)
|
2021-09-11 20:26:37 +00:00
|
|
|
{
|
2021-09-11 22:11:44 +00:00
|
|
|
GdkMemoryFormat format;
|
|
|
|
TextureMethod method;
|
2018-03-12 04:12:54 +00:00
|
|
|
GdkTexture *expected, *test;
|
2021-09-11 20:26:37 +00:00
|
|
|
gsize i;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
decode (data, &format, &method);
|
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
for (i = 0; i < N; i++)
|
|
|
|
{
|
|
|
|
GdkRGBA color;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
create_random_color (&color);
|
2021-09-11 22:11:44 +00:00
|
|
|
expected = create_texture (GDK_MEMORY_DEFAULT, TEXTURE_METHOD_LOCAL, 1, 1, &color);
|
|
|
|
test = create_texture (format, method, 1, 1, &color);
|
2021-09-11 20:26:37 +00:00
|
|
|
|
|
|
|
compare_textures (expected, test, gdk_memory_format_has_alpha (format));
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
g_object_unref (expected);
|
|
|
|
g_object_unref (test);
|
|
|
|
}
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-09-11 22:11:44 +00:00
|
|
|
test_download_4x4 (gconstpointer data)
|
2018-03-12 04:12:54 +00:00
|
|
|
{
|
2021-09-11 22:11:44 +00:00
|
|
|
GdkMemoryFormat format;
|
|
|
|
TextureMethod method;
|
2018-03-12 04:12:54 +00:00
|
|
|
GdkTexture *expected, *test;
|
2021-09-11 20:26:37 +00:00
|
|
|
gsize i;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
decode (data, &format, &method);
|
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
for (i = 0; i < N; i++)
|
|
|
|
{
|
|
|
|
GdkRGBA color;
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
create_random_color (&color);
|
2021-09-11 22:11:44 +00:00
|
|
|
expected = create_texture (GDK_MEMORY_DEFAULT, TEXTURE_METHOD_LOCAL, 4, 4, &color);
|
|
|
|
test = create_texture (format, method, 4, 4, &color);
|
2021-09-11 20:26:37 +00:00
|
|
|
|
|
|
|
compare_textures (expected, test, gdk_memory_format_has_alpha (format));
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-09-11 20:26:37 +00:00
|
|
|
g_object_unref (expected);
|
|
|
|
g_object_unref (test);
|
|
|
|
}
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|
|
|
|
|
2021-10-08 18:15:07 +00:00
|
|
|
/* larger than what NGL puts into the icon cache */
|
|
|
|
static void
|
|
|
|
test_download_192x192 (gconstpointer data)
|
|
|
|
{
|
|
|
|
GdkMemoryFormat format;
|
|
|
|
TextureMethod method;
|
|
|
|
GdkTexture *expected, *test;
|
|
|
|
GdkRGBA color;
|
|
|
|
|
|
|
|
decode (data, &format, &method);
|
|
|
|
|
|
|
|
create_random_color (&color);
|
|
|
|
expected = create_texture (GDK_MEMORY_DEFAULT, TEXTURE_METHOD_LOCAL, 192, 192, &color);
|
|
|
|
test = create_texture (format, method, 192, 192, &color);
|
|
|
|
|
|
|
|
compare_textures (expected, test, gdk_memory_format_has_alpha (format));
|
|
|
|
|
|
|
|
g_object_unref (expected);
|
|
|
|
g_object_unref (test);
|
|
|
|
}
|
|
|
|
|
2018-03-12 04:12:54 +00:00
|
|
|
static void
|
2021-09-11 19:19:48 +00:00
|
|
|
add_test (const char *name,
|
|
|
|
GTestDataFunc func)
|
2018-03-12 04:12:54 +00:00
|
|
|
{
|
|
|
|
GdkMemoryFormat format;
|
2021-09-11 22:11:44 +00:00
|
|
|
TextureMethod method;
|
2018-03-12 04:12:54 +00:00
|
|
|
GEnumClass *enum_class;
|
|
|
|
|
|
|
|
enum_class = g_type_class_ref (GDK_TYPE_MEMORY_FORMAT);
|
|
|
|
|
|
|
|
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
|
|
|
|
{
|
2021-09-11 22:11:44 +00:00
|
|
|
for (method = 0; method < N_TEXTURE_METHODS; method++)
|
|
|
|
{
|
2021-09-14 00:37:50 +00:00
|
|
|
const char *method_names[N_TEXTURE_METHODS] = { "local", "gl", "gl-released", "png", "png-pixbuf", "tiff", "tiff-pixbuf" };
|
2021-09-11 22:11:44 +00:00
|
|
|
char *test_name = g_strdup_printf ("%s/%s/%s",
|
|
|
|
name,
|
|
|
|
g_enum_get_value (enum_class, format)->value_nick,
|
|
|
|
method_names[method]);
|
2021-09-22 19:46:47 +00:00
|
|
|
g_test_add_data_func_full (test_name, encode (format, method), func, NULL);
|
2021-09-11 22:11:44 +00:00
|
|
|
g_free (test_name);
|
|
|
|
}
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|
2021-09-11 19:19:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
|
|
|
{
|
2021-09-11 20:50:09 +00:00
|
|
|
int result;
|
|
|
|
|
|
|
|
gtk_test_init (&argc, &argv, NULL);
|
2021-09-11 19:19:48 +00:00
|
|
|
|
|
|
|
add_test ("/memorytexture/download_1x1", test_download_1x1);
|
|
|
|
add_test ("/memorytexture/download_4x4", test_download_4x4);
|
2021-10-08 18:15:07 +00:00
|
|
|
add_test ("/memorytexture/download_192x192", test_download_192x192);
|
2018-03-12 04:12:54 +00:00
|
|
|
|
2021-10-07 03:15:25 +00:00
|
|
|
gl_renderer = gsk_gl_renderer_new ();
|
2021-10-20 18:33:57 +00:00
|
|
|
if (!gsk_renderer_realize (gl_renderer, NULL, NULL))
|
2021-09-11 20:50:09 +00:00
|
|
|
{
|
|
|
|
g_clear_object (&gl_renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = g_test_run ();
|
|
|
|
|
2021-09-11 22:11:44 +00:00
|
|
|
if (gl_renderer)
|
|
|
|
{
|
|
|
|
gsk_renderer_unrealize (gl_renderer);
|
|
|
|
g_clear_object (&gl_renderer);
|
|
|
|
}
|
2022-01-06 18:08:42 +00:00
|
|
|
gdk_gl_context_clear_current ();
|
2021-09-11 20:50:09 +00:00
|
|
|
|
|
|
|
return result;
|
2018-03-12 04:12:54 +00:00
|
|
|
}
|