mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 22:41:43 +00:00
Merge branch 'wip/matthiasc/gsk-hdr' into 'master'
texture: Add hdr api See merge request GNOME/gtk!4036
This commit is contained in:
commit
8d9c3920bb
@ -34,7 +34,7 @@ gdk_broadway_cairo_context_dispose (GObject *object)
|
||||
|
||||
static void
|
||||
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
|
||||
|
@ -34,7 +34,7 @@ gdk_broadway_draw_context_dispose (GObject *object)
|
||||
|
||||
static void
|
||||
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
|
||||
|
@ -129,7 +129,7 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
|
||||
{ "hdr", GDK_DEBUG_HDR, "Use HDR rendering if possible", TRUE },
|
||||
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible", TRUE },
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,11 +91,7 @@ void
|
||||
gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
|
||||
const GdkPixbuf *pixbuf)
|
||||
{
|
||||
int width, height;
|
||||
guchar *gdk_pixels, *cairo_pixels;
|
||||
int gdk_rowstride, cairo_stride;
|
||||
int n_channels;
|
||||
int j;
|
||||
GdkTexture *texture;
|
||||
|
||||
if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
|
||||
return;
|
||||
@ -111,71 +107,11 @@ gdk_cairo_surface_paint_pixbuf (cairo_surface_t *surface,
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
|
||||
cairo_stride = cairo_image_surface_get_stride (surface);
|
||||
cairo_pixels = cairo_image_surface_get_data (surface);
|
||||
|
||||
for (j = height; j; j--)
|
||||
{
|
||||
guchar *p = gdk_pixels;
|
||||
guchar *q = cairo_pixels;
|
||||
|
||||
if (n_channels == 3)
|
||||
{
|
||||
guchar *end = p + 3 * width;
|
||||
|
||||
while (p < end)
|
||||
{
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
q[0] = p[2];
|
||||
q[1] = p[1];
|
||||
q[2] = p[0];
|
||||
q[3] = 0xFF;
|
||||
#else
|
||||
q[0] = 0xFF;
|
||||
q[1] = p[0];
|
||||
q[2] = p[1];
|
||||
q[3] = p[2];
|
||||
#endif
|
||||
p += 3;
|
||||
q += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
guchar *end = p + 4 * width;
|
||||
guint t1,t2,t3;
|
||||
|
||||
#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
|
||||
|
||||
while (p < end)
|
||||
{
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
MULT(q[0], p[2], p[3], t1);
|
||||
MULT(q[1], p[1], p[3], t2);
|
||||
MULT(q[2], p[0], p[3], t3);
|
||||
q[3] = p[3];
|
||||
#else
|
||||
q[0] = p[3];
|
||||
MULT(q[1], p[0], p[3], t1);
|
||||
MULT(q[2], p[1], p[3], t2);
|
||||
MULT(q[3], p[2], p[3], t3);
|
||||
#endif
|
||||
|
||||
p += 4;
|
||||
q += 4;
|
||||
}
|
||||
|
||||
#undef MULT
|
||||
}
|
||||
|
||||
gdk_pixels += gdk_rowstride;
|
||||
cairo_pixels += cairo_stride;
|
||||
}
|
||||
texture = gdk_texture_new_for_pixbuf (GDK_PIXBUF (pixbuf));
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
g_object_unref (texture);
|
||||
|
||||
cairo_surface_mark_dirty (surface);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ typedef enum {
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
|
||||
GDK_DEBUG_HDR = 1 << 24,
|
||||
GDK_DEBUG_HIGH_DEPTH = 1 << 24,
|
||||
} GdkDebugFlags;
|
||||
|
||||
extern guint _gdk_debug_flags;
|
||||
|
@ -93,7 +93,7 @@ struct _GdkDisplayPrivate {
|
||||
#ifdef HAVE_EGL
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
EGLConfig egl_config_hdr;
|
||||
EGLConfig egl_config_high_depth;
|
||||
#endif
|
||||
|
||||
guint rgba : 1;
|
||||
@ -1439,11 +1439,11 @@ gdk_display_get_egl_config (GdkDisplay *self)
|
||||
}
|
||||
|
||||
gpointer
|
||||
gdk_display_get_egl_config_hdr (GdkDisplay *self)
|
||||
gdk_display_get_egl_config_high_depth (GdkDisplay *self)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
return priv->egl_config_hdr;
|
||||
return priv->egl_config_high_depth;
|
||||
}
|
||||
|
||||
static EGLDisplay
|
||||
@ -1721,16 +1721,16 @@ gdk_display_init_egl (GdkDisplay *self,
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_pixel_format_float");
|
||||
|
||||
if (self->have_egl_no_config_context)
|
||||
priv->egl_config_hdr = gdk_display_create_egl_config (self,
|
||||
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
|
||||
GDK_EGL_CONFIG_HDR,
|
||||
error);
|
||||
if (priv->egl_config_hdr == NULL)
|
||||
priv->egl_config_hdr = priv->egl_config;
|
||||
if (priv->egl_config_high_depth == NULL)
|
||||
priv->egl_config_high_depth = priv->egl_config;
|
||||
|
||||
GDK_DISPLAY_NOTE (self, OPENGL, {
|
||||
char *ext = describe_extensions (priv->egl_display);
|
||||
char *sdr_cfg = describe_egl_config (priv->egl_display, priv->egl_config);
|
||||
char *hdr_cfg = describe_egl_config (priv->egl_display, priv->egl_config_hdr);
|
||||
char *std_cfg = describe_egl_config (priv->egl_display, priv->egl_config);
|
||||
char *hd_cfg = describe_egl_config (priv->egl_display, priv->egl_config_high_depth);
|
||||
g_message ("EGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Version: %s\n"
|
||||
@ -1738,15 +1738,15 @@ gdk_display_init_egl (GdkDisplay *self,
|
||||
" - Extensions:\n"
|
||||
"\t%s\n"
|
||||
" - Selected fbconfig: %s\n"
|
||||
" HDR fbconfig: %s",
|
||||
" high depth: %s",
|
||||
major, minor,
|
||||
eglQueryString (priv->egl_display, EGL_VENDOR),
|
||||
eglQueryString (priv->egl_display, EGL_VERSION),
|
||||
eglQueryString (priv->egl_display, EGL_CLIENT_APIS),
|
||||
ext, sdr_cfg,
|
||||
priv->egl_config_hdr == priv->egl_config ? "none" : hdr_cfg);
|
||||
g_free (hdr_cfg);
|
||||
g_free (sdr_cfg);
|
||||
ext, std_cfg,
|
||||
priv->egl_config_high_depth == priv->egl_config ? "none" : hd_cfg);
|
||||
g_free (hd_cfg);
|
||||
g_free (std_cfg);
|
||||
g_free (ext);
|
||||
});
|
||||
|
||||
|
@ -226,7 +226,8 @@ gboolean gdk_display_init_egl (GdkDisplay *display
|
||||
GError **error);
|
||||
gpointer gdk_display_get_egl_display (GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config (GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config_hdr (GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config_high_depth
|
||||
(GdkDisplay *display);
|
||||
|
||||
void gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba);
|
||||
|
@ -315,28 +315,30 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
|
||||
}
|
||||
|
||||
/*
|
||||
* @request_hdr: %TRUE to request high dynamic range.
|
||||
* @prefers_high_depth: %TRUE to request a higher bit depth
|
||||
*
|
||||
* If HDR is requested, GDK will see about providing a rendering target
|
||||
* that supports high dynamic range. Typically this means a target supporting
|
||||
* 16bit floating point pixels, but that is not guaranteed.
|
||||
* If high depth is preferred, GDK will see about providing a rendering target
|
||||
* that supports higher bit depth than 8 bits per channel. Typically this means
|
||||
* a target supporting 16bit floating point pixels, but that is not guaranteed.
|
||||
*
|
||||
* This is only a request and if the GDK backend does not support HDR rendering
|
||||
* or does not consider it worthwhile, it may choose to not honor the request.
|
||||
* It may also choose to provide HDR even if it was not requested.
|
||||
* It may also choose to provide high depth even if it was not requested.
|
||||
* Typically the steps undertaken by a backend are:
|
||||
* 1. Check if HDR is supported by this drawing backend.
|
||||
* 2. Check if the compositor supports HDR.
|
||||
* 3. Check if the compositor prefers SDR. This is usually the case when the attached
|
||||
* monitors do not support HDR content or when the system is resource constrained.
|
||||
* 1. Check if high depth is supported by this drawing backend.
|
||||
* 2. Check if the compositor supports high depth.
|
||||
* 3. Check if the compositor prefers regular bit depth. This is usually the case
|
||||
* when the attached monitors do not support high depth content or when the
|
||||
* system is resource constrained.
|
||||
* In either of those cases, the context will usually choose to not honor the request.
|
||||
*
|
||||
* The rendering code must be able to deal with HDR and SDR content, no matter if HDR
|
||||
* was requested. The request is only a hint and GDK is free to choose.
|
||||
* The rendering code must be able to deal with content in any bit depth, no matter
|
||||
* the preference. The prefers_high_depth argument is only a hint and GDK is free
|
||||
* to choose.
|
||||
*/
|
||||
void
|
||||
gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
|
||||
@ -362,13 +364,13 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
return;
|
||||
}
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (priv->display, HDR))
|
||||
request_hdr = TRUE;
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (priv->display, HIGH_DEPTH))
|
||||
prefers_high_depth = TRUE;
|
||||
|
||||
priv->frame_region = cairo_region_copy (region);
|
||||
priv->surface->paint_context = g_object_ref (context);
|
||||
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, request_hdr, priv->frame_region);
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYSPROF
|
||||
|
@ -41,7 +41,7 @@ struct _GdkDrawContextClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* begin_frame) (GdkDrawContext *context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area);
|
||||
void (* end_frame) (GdkDrawContext *context,
|
||||
cairo_region_t *painted);
|
||||
@ -51,7 +51,7 @@ struct _GdkDrawContextClass
|
||||
void gdk_draw_context_surface_resized (GdkDrawContext *context);
|
||||
|
||||
void gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
const cairo_region_t *region);
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include "gdkdebug.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
@ -238,80 +239,39 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
guchar *copy = NULL;
|
||||
GLint gl_internalformat;
|
||||
GLint gl_format;
|
||||
GLint gl_type;
|
||||
GLenum gl_internalformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
gsize bpp;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (!priv->use_es && data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
if (!gdk_memory_format_gl_format (data_format,
|
||||
priv->use_es,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type))
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (priv->use_es && data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB16F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB32F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA32F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else /* Fall-back, convert to GLES format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
copy = g_malloc_n (width * 4, height);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
data, stride, data_format,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
data, stride,
|
||||
data_format,
|
||||
width, height);
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
if (!gdk_memory_format_gl_format (data_format,
|
||||
priv->use_es,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copy = NULL;
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
@ -629,7 +589,7 @@ gdk_gl_context_real_make_current (GdkGLContext *context,
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
@ -642,7 +602,7 @@ gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (priv->egl_context)
|
||||
gdk_surface_ensure_egl_surface (surface, request_hdr);
|
||||
gdk_surface_ensure_egl_surface (surface, prefers_high_depth);
|
||||
#endif
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
@ -139,82 +140,29 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self,
|
||||
data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_texture (gpointer texture_,
|
||||
gpointer result_)
|
||||
{
|
||||
GdkTexture *texture = texture_;
|
||||
GdkTexture **result = result_;
|
||||
GdkMemoryFormat format;
|
||||
GLint internal_format, gl_format, gl_type;
|
||||
guint gl_internalformat, gl_format, gl_type;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
|
||||
if (!gdk_memory_format_gl_format (texture->format,
|
||||
gdk_gl_context_get_use_es (gdk_gl_context_get_current ()),
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
switch (internal_format)
|
||||
{
|
||||
case GL_RGB8:
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16:
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGB16F:
|
||||
format = GDK_MEMORY_R16G16B16_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16F:
|
||||
format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGB32F:
|
||||
format = GDK_MEMORY_R32G32B32_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA32F:
|
||||
format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
|
||||
/* fallback to the dumbest possible format
|
||||
* so that even age old GLES can do it */
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
|
||||
stride = gdk_memory_format_bytes_per_pixel (format) * texture->width;
|
||||
data = g_malloc (stride * texture->height);
|
||||
stride = gdk_memory_format_bytes_per_pixel (texture->format) * texture->width;
|
||||
data = g_malloc_n (stride, texture->height);
|
||||
|
||||
gdk_gl_texture_get_tex_image (texture_,
|
||||
gl_format,
|
||||
@ -224,7 +172,7 @@ gdk_gl_texture_do_download_texture (gpointer texture_,
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
*result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
texture->format,
|
||||
bytes,
|
||||
stride);
|
||||
|
||||
@ -377,6 +325,58 @@ gdk_gl_texture_release (GdkGLTexture *self)
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_determine_format (gpointer texture_,
|
||||
gpointer unused)
|
||||
{
|
||||
GdkTexture *texture = texture_;
|
||||
GLint internal_format;
|
||||
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
|
||||
|
||||
switch (internal_format)
|
||||
{
|
||||
case GL_RGB8:
|
||||
texture->format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
texture->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
texture->format = GDK_MEMORY_R16G16B16;
|
||||
break;
|
||||
|
||||
case GL_RGBA16:
|
||||
texture->format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case GL_RGB16F:
|
||||
texture->format = GDK_MEMORY_R16G16B16_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16F:
|
||||
texture->format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case GL_RGB32F:
|
||||
texture->format = GDK_MEMORY_R32G32B32_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA32F:
|
||||
texture->format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
|
||||
/* fallback to the dumbest possible format
|
||||
* so that even age old GLES can do it */
|
||||
texture->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_new:
|
||||
* @context: a `GdkGLContext`
|
||||
@ -420,6 +420,8 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
self->destroy = destroy;
|
||||
self->data = data;
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_determine_format, NULL);
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
}
|
||||
|
||||
|
467
gdk/gdkmemoryformat.c
Normal file
467
gdk/gdkmemoryformat.c
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* Copyright © 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription;
|
||||
|
||||
typedef enum {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
GDK_MEMORY_ALPHA_OPAQUE
|
||||
} GdkMemoryAlpha;
|
||||
|
||||
#define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \
|
||||
static void \
|
||||
name ## _to_float (float *dest, \
|
||||
const guchar *src_data, \
|
||||
gsize n) \
|
||||
{ \
|
||||
for (gsize i = 0; i < n; i++) \
|
||||
{ \
|
||||
T *src = (T *) (src_data + i * bpp); \
|
||||
dest[0] = (float) src[R] / scale; \
|
||||
dest[1] = (float) src[G] / scale; \
|
||||
dest[2] = (float) src[B] / scale; \
|
||||
if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \
|
||||
dest += 4; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
name ## _from_float (guchar *dest_data, \
|
||||
const float *src, \
|
||||
gsize n) \
|
||||
{ \
|
||||
for (gsize i = 0; i < n; i++) \
|
||||
{ \
|
||||
T *dest = (T *) (dest_data + i * bpp); \
|
||||
dest[R] = CLAMP (src[0] * scale + 0.5, 0, scale); \
|
||||
dest[G] = CLAMP (src[1] * scale + 0.5, 0, scale); \
|
||||
dest[B] = CLAMP (src[2] * scale + 0.5, 0, scale); \
|
||||
if (A >= 0) dest[A] = CLAMP (src[3] * scale + 0.5, 0, scale); \
|
||||
src += 4; \
|
||||
} \
|
||||
}
|
||||
|
||||
TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
|
||||
TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
|
||||
TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
|
||||
TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
|
||||
TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
|
||||
TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
|
||||
TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
|
||||
TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
|
||||
TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
|
||||
TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
|
||||
TYPED_FUNCS (r16g16b16a16, guint16, 0, 1, 2, 3, 8, 65535)
|
||||
|
||||
static void
|
||||
r16g16b16_float_to_float (float *dest,
|
||||
const guchar *src_data,
|
||||
gsize n)
|
||||
{
|
||||
guint16 *src = (guint16 *) src_data;
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
half_to_float (src, dest, 3);
|
||||
dest[3] = 1.0;
|
||||
dest += 4;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r16g16b16_float_from_float (guchar *dest_data,
|
||||
const float *src,
|
||||
gsize n)
|
||||
{
|
||||
guint16 *dest = (guint16 *) dest_data;
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
float_to_half (src, dest, 3);
|
||||
dest += 3;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r16g16b16a16_float_to_float (float *dest,
|
||||
const guchar *src,
|
||||
gsize n)
|
||||
{
|
||||
half_to_float ((const guint16 *) src, dest, 4 * n);
|
||||
}
|
||||
|
||||
static void
|
||||
r16g16b16a16_float_from_float (guchar *dest,
|
||||
const float *src,
|
||||
gsize n)
|
||||
{
|
||||
float_to_half (src, (guint16 *) dest, 4 * n);
|
||||
}
|
||||
|
||||
static void
|
||||
r32g32b32_float_to_float (float *dest,
|
||||
const guchar *src_data,
|
||||
gsize n)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 1.0;
|
||||
dest += 4;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r32g32b32_float_from_float (guchar *dest_data,
|
||||
const float *src,
|
||||
gsize n)
|
||||
{
|
||||
float *dest = (float *) dest_data;
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest += 3;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
r32g32b32a32_float_to_float (float *dest,
|
||||
const guchar *src,
|
||||
gsize n)
|
||||
{
|
||||
memcpy (dest, src, sizeof (float) * n * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
r32g32b32a32_float_from_float (guchar *dest,
|
||||
const float *src,
|
||||
gsize n)
|
||||
{
|
||||
memcpy (dest, src, sizeof (float) * n * 4);
|
||||
}
|
||||
|
||||
struct _GdkMemoryFormatDescription
|
||||
{
|
||||
GdkMemoryAlpha alpha;
|
||||
gsize bytes_per_pixel;
|
||||
gsize alignment;
|
||||
gboolean prefers_high_depth;
|
||||
gboolean supports_gles;
|
||||
struct {
|
||||
guint internal_format;
|
||||
guint format;
|
||||
guint type;
|
||||
} gl;
|
||||
/* no premultiplication going on here */
|
||||
void (* to_float) (float *, const guchar*, gsize);
|
||||
void (* from_float) (guchar *, const float *, gsize);
|
||||
};
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
# define GDK_GL_UNSIGNED_BYTE_FLIPPED GL_UNSIGNED_INT_8_8_8_8
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
# define GDK_GL_UNSIGNED_BYTE_FLIPPED GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
#else
|
||||
# error "Define the right GL flags here"
|
||||
#endif
|
||||
|
||||
static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
|
||||
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
|
||||
b8g8r8a8_premultiplied_to_float,
|
||||
b8g8r8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
|
||||
a8r8g8b8_premultiplied_to_float,
|
||||
a8r8g8b8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
TRUE,
|
||||
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
|
||||
r8g8b8a8_premultiplied_to_float,
|
||||
r8g8b8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8A8] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE },
|
||||
b8g8r8a8_to_float,
|
||||
b8g8r8a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8R8G8B8] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
|
||||
a8r8g8b8_to_float,
|
||||
a8r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8A8] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
TRUE,
|
||||
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
|
||||
r8g8b8a8_to_float,
|
||||
r8g8b8a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8B8G8R8] = {
|
||||
GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
4,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED },
|
||||
a8b8g8r8_to_float,
|
||||
a8b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
3,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
TRUE,
|
||||
{ GL_RGBA8, GL_RGB, GL_UNSIGNED_BYTE },
|
||||
r8g8b8_to_float,
|
||||
r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
3,
|
||||
G_ALIGNOF (guchar),
|
||||
FALSE,
|
||||
FALSE,
|
||||
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE },
|
||||
b8g8r8_to_float,
|
||||
b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
6,
|
||||
G_ALIGNOF (guint16),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT },
|
||||
r16g16b16_to_float,
|
||||
r16g16b16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
|
||||
r16g16b16a16_to_float,
|
||||
r16g16b16a16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16_FLOAT] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
6,
|
||||
G_ALIGNOF (guint16),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGB16F, GL_RGB, GL_HALF_FLOAT },
|
||||
r16g16b16_float_to_float,
|
||||
r16g16b16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
8,
|
||||
G_ALIGNOF (guint16),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
|
||||
r16g16b16a16_float_to_float,
|
||||
r16g16b16a16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R32G32B32_FLOAT] = {
|
||||
GDK_MEMORY_ALPHA_OPAQUE,
|
||||
12,
|
||||
G_ALIGNOF (float),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGB32F, GL_RGB, GL_FLOAT },
|
||||
r32g32b32_float_to_float,
|
||||
r32g32b32_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
|
||||
GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
16,
|
||||
G_ALIGNOF (float),
|
||||
TRUE,
|
||||
TRUE,
|
||||
{ GL_RGBA32F, GL_RGBA, GL_FLOAT },
|
||||
r32g32b32a32_float_to_float,
|
||||
r32g32b32a32_float_from_float,
|
||||
}
|
||||
};
|
||||
|
||||
gsize
|
||||
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].bytes_per_pixel;
|
||||
}
|
||||
|
||||
gsize
|
||||
gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].alignment;
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_memory_format_prefers_high_depth:
|
||||
* @format: a memory format
|
||||
*
|
||||
* Checks if the given format benefits from being rendered
|
||||
* in bit depths higher than 8bits per pixel. See
|
||||
* gsk_render_node_prefers_high_depth() for more information
|
||||
* on this.
|
||||
* Usually this is the case when
|
||||
* gdk_memory_format_bytes_per_pixel() is larger than 4.
|
||||
*
|
||||
* Returns: %TRUE if the format benefits from being
|
||||
* composited in hgiher bit depths.
|
||||
**/
|
||||
gboolean
|
||||
gdk_memory_format_prefers_high_depth (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].prefers_high_depth;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint *out_internal_format,
|
||||
guint *out_format,
|
||||
guint *out_type)
|
||||
{
|
||||
*out_internal_format = memory_formats[format].gl.internal_format;
|
||||
*out_format = memory_formats[format].gl.format;
|
||||
*out_type = memory_formats[format].gl.type;
|
||||
|
||||
if (memory_formats[format].alpha == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
return FALSE;
|
||||
|
||||
if (gles && !memory_formats[format].supports_gles)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply (float *rgba,
|
||||
gsize n)
|
||||
{
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
rgba[0] *= rgba[3];
|
||||
rgba[1] *= rgba[3];
|
||||
rgba[2] *= rgba[3];
|
||||
rgba += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpremultiply (float *rgba,
|
||||
gsize n)
|
||||
{
|
||||
for (gsize i = 0; i < n; i++)
|
||||
{
|
||||
if (rgba[3] > 1/255.0)
|
||||
{
|
||||
rgba[0] /= rgba[3];
|
||||
rgba[1] /= rgba[3];
|
||||
rgba[2] /= rgba[3];
|
||||
}
|
||||
rgba += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
|
||||
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
|
||||
float *tmp;
|
||||
gsize y;
|
||||
|
||||
g_assert (dest_format < GDK_MEMORY_N_FORMATS);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
tmp = g_new (float, width * 4);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src_desc->to_float (tmp, src_data, width);
|
||||
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
unpremultiply (tmp, width);
|
||||
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
premultiply (tmp, width);
|
||||
dest_desc->from_float (dest_data, tmp, width);
|
||||
src_data += src_stride;
|
||||
dest_data += dest_stride;
|
||||
}
|
||||
|
||||
g_free (tmp);
|
||||
}
|
48
gdk/gdkmemoryformatprivate.h
Normal file
48
gdk/gdkmemoryformatprivate.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright © 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MEMORY_CONVERT_PRIVATE_H__
|
||||
#define __GDK_MEMORY_CONVERT_PRIVATE_H__
|
||||
|
||||
#include "gdkmemorytexture.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gboolean gdk_memory_format_prefers_high_depth(GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gboolean gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
guint *out_internal_format,
|
||||
guint *out_format,
|
||||
guint *out_type);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MEMORY_CONVERT_PRIVATE_H__ */
|
@ -20,6 +20,8 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
|
||||
/**
|
||||
@ -32,8 +34,6 @@ struct _GdkMemoryTexture
|
||||
{
|
||||
GdkTexture parent_instance;
|
||||
|
||||
GdkMemoryFormat format;
|
||||
|
||||
GBytes *bytes;
|
||||
gsize stride;
|
||||
};
|
||||
@ -45,80 +45,6 @@ struct _GdkMemoryTextureClass
|
||||
|
||||
G_DEFINE_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK_TYPE_TEXTURE)
|
||||
|
||||
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:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return 8;
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return 12;
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return 16;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static gsize
|
||||
gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
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 G_ALIGNOF (guchar);
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (float);
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return G_ALIGNOF (double);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_dispose (GObject *object)
|
||||
{
|
||||
@ -143,10 +69,10 @@ gdk_memory_texture_download (GdkTexture *texture,
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
texture->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
@ -158,12 +84,14 @@ gdk_memory_texture_download_float (GdkTexture *texture,
|
||||
{
|
||||
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));
|
||||
gdk_memory_convert ((guchar *) data,
|
||||
stride * sizeof (float),
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
texture->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -254,19 +182,13 @@ gdk_memory_texture_new (int width,
|
||||
"height", height,
|
||||
NULL);
|
||||
|
||||
self->format = format;
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
self->bytes = bytes;
|
||||
self->stride = stride;
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_memory_texture_get_format (GdkMemoryTexture *self)
|
||||
{
|
||||
return self->format;
|
||||
}
|
||||
|
||||
const guchar *
|
||||
gdk_memory_texture_get_data (GdkMemoryTexture *self)
|
||||
{
|
||||
@ -279,429 +201,3 @@ gdk_memory_texture_get_stride (GdkMemoryTexture *self)
|
||||
return self->stride;
|
||||
}
|
||||
|
||||
static void
|
||||
convert_memcpy (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
gsize y;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (dest_data + y * dest_stride, src_data + y * src_stride, 4 * width);
|
||||
}
|
||||
|
||||
#define SWIZZLE(A,R,G,B) \
|
||||
static void \
|
||||
convert_swizzle ## A ## R ## G ## B (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
dest_data[4 * x + A] = src_data[4 * x + 0]; \
|
||||
dest_data[4 * x + R] = src_data[4 * x + 1]; \
|
||||
dest_data[4 * x + G] = src_data[4 * x + 2]; \
|
||||
dest_data[4 * x + B] = src_data[4 * x + 3]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
SWIZZLE(3,2,1,0)
|
||||
SWIZZLE(2,1,0,3)
|
||||
SWIZZLE(3,0,1,2)
|
||||
SWIZZLE(1,2,3,0)
|
||||
|
||||
#define SWIZZLE_OPAQUE(A,R,G,B) \
|
||||
static void \
|
||||
convert_swizzle_opaque_## A ## R ## G ## B (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
dest_data[4 * x + A] = 0xFF; \
|
||||
dest_data[4 * x + R] = src_data[3 * x + 0]; \
|
||||
dest_data[4 * x + G] = src_data[3 * x + 1]; \
|
||||
dest_data[4 * x + B] = src_data[3 * x + 2]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
SWIZZLE_OPAQUE(3,2,1,0)
|
||||
SWIZZLE_OPAQUE(3,0,1,2)
|
||||
SWIZZLE_OPAQUE(0,1,2,3)
|
||||
SWIZZLE_OPAQUE(0,3,2,1)
|
||||
|
||||
#define PREMULTIPLY(d,c,a) G_STMT_START { guint t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
|
||||
#define SWIZZLE_PREMULTIPLY(A,R,G,B, A2,R2,G2,B2) \
|
||||
static void \
|
||||
convert_swizzle_premultiply_ ## A ## R ## G ## B ## _ ## A2 ## R2 ## G2 ## B2 \
|
||||
(guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
dest_data[4 * x + A] = src_data[4 * x + A2]; \
|
||||
PREMULTIPLY(dest_data[4 * x + R], src_data[4 * x + R2], src_data[4 * x + A2]); \
|
||||
PREMULTIPLY(dest_data[4 * x + G], src_data[4 * x + G2], src_data[4 * x + A2]); \
|
||||
PREMULTIPLY(dest_data[4 * x + B], src_data[4 * x + B2], src_data[4 * x + A2]); \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
SWIZZLE_PREMULTIPLY (3,2,1,0, 3,2,1,0)
|
||||
SWIZZLE_PREMULTIPLY (0,1,2,3, 3,2,1,0)
|
||||
SWIZZLE_PREMULTIPLY (3,2,1,0, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (0,1,2,3, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (3,2,1,0, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (0,1,2,3, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (3,2,1,0, 0,3,2,1)
|
||||
SWIZZLE_PREMULTIPLY (0,1,2,3, 0,3,2,1)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 3,2,1,0)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
|
||||
|
||||
#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
|
||||
static void \
|
||||
convert_ ## name ## _to_ ## suffix (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
guchar conv[4]; \
|
||||
convert_pixel_ ## name (conv, src_data + step * x); \
|
||||
dest_data[4 * x + R] = conv[0]; \
|
||||
dest_data[4 * x + G] = conv[1]; \
|
||||
dest_data[4 * x + B] = conv[2]; \
|
||||
dest_data[4 * x + A] = conv[3]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONVERT_FUNCS(name,step) \
|
||||
CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
|
||||
CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
|
||||
CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = (guchar)(src[3] >> 8);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
half_to_float4(tmp, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
half_to_float4((const guint16 *) src_data, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
|
||||
|
||||
typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
|
||||
{
|
||||
{ convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
|
||||
{ convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
|
||||
{ convert_swizzle2103, convert_swizzle1230, convert_memcpy },
|
||||
{ convert_swizzle_premultiply_3210_3210, convert_swizzle_premultiply_0123_3210, convert_swizzle_premultiply_3012_3210, },
|
||||
{ convert_swizzle_premultiply_3210_0123, convert_swizzle_premultiply_0123_0123, convert_swizzle_premultiply_3012_0123 },
|
||||
{ convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 },
|
||||
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, convert_swizzle_premultiply_3012_0321 },
|
||||
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
|
||||
{ convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
|
||||
{ convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
|
||||
{ convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
|
||||
{ convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
|
||||
{ convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
|
||||
{ convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
|
||||
};
|
||||
|
||||
void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
g_assert (dest_format < 3);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
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
|
||||
|
||||
#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
func (dest_data + 4 * x, src_data + step * x); \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
static inline void
|
||||
convert_rgb16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = src[3] / 65535.f;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
tmp[3] = FP16_ONE;
|
||||
half_to_float4 (tmp, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
half_to_float4 ((const guint16 *) src_data, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
}
|
||||
|
||||
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_R16G16B16:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
@ -29,45 +29,9 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
typedef enum {
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
|
||||
GDK_MEMORY_N_CONVERSIONS
|
||||
} GdkMemoryConversion;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
|
||||
#else
|
||||
#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
|
||||
#endif
|
||||
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format);
|
||||
|
||||
GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *self);
|
||||
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
|
||||
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
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
|
||||
|
||||
|
@ -71,7 +71,7 @@ struct _GdkSurfacePrivate
|
||||
gpointer egl_native_window;
|
||||
#ifdef HAVE_EGL
|
||||
EGLSurface egl_surface;
|
||||
gboolean egl_surface_hdr;
|
||||
gboolean egl_surface_high_depth;
|
||||
#endif
|
||||
|
||||
gpointer widget;
|
||||
@ -1109,16 +1109,16 @@ gdk_surface_get_egl_surface (GdkSurface *self)
|
||||
|
||||
void
|
||||
gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
gboolean hdr)
|
||||
gboolean high_depth)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
|
||||
GdkDisplay *display = gdk_surface_get_display (self);
|
||||
|
||||
g_return_if_fail (priv->egl_native_window != NULL);
|
||||
|
||||
if (priv->egl_surface_hdr != hdr &&
|
||||
if (priv->egl_surface_high_depth != high_depth &&
|
||||
priv->egl_surface != NULL &&
|
||||
gdk_display_get_egl_config_hdr (display) != gdk_display_get_egl_config (display))
|
||||
gdk_display_get_egl_config_high_depth (display) != gdk_display_get_egl_config (display))
|
||||
{
|
||||
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
|
||||
priv->egl_surface = NULL;
|
||||
@ -1127,11 +1127,11 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
if (priv->egl_surface == NULL)
|
||||
{
|
||||
priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
|
||||
hdr ? gdk_display_get_egl_config_hdr (display)
|
||||
: gdk_display_get_egl_config (display),
|
||||
high_depth ? gdk_display_get_egl_config_high_depth (display)
|
||||
: gdk_display_get_egl_config (display),
|
||||
(EGLNativeWindowType) priv->egl_native_window,
|
||||
NULL);
|
||||
priv->egl_surface_hdr = hdr;
|
||||
priv->egl_surface_high_depth = high_depth;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -808,6 +808,12 @@ gdk_texture_download_texture (GdkTexture *texture)
|
||||
return texture;
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_texture_get_format (GdkTexture *self)
|
||||
{
|
||||
return self->format;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_texture_set_render_data (GdkTexture *self,
|
||||
gpointer key,
|
||||
@ -972,4 +978,3 @@ gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
|
||||
|
||||
return gdk_save_tiff (texture);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "gdktexture.h"
|
||||
|
||||
#include "gdkmemorytexture.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_TEXTURE, GdkTextureClass))
|
||||
@ -13,6 +15,7 @@ struct _GdkTexture
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkMemoryFormat format;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
@ -42,6 +45,7 @@ cairo_surface_t * gdk_texture_download_surface (GdkTexture
|
||||
/* NB: GdkMemoryTexture */
|
||||
GdkTexture * gdk_texture_download_texture (GdkTexture *texture);
|
||||
|
||||
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self);
|
||||
gboolean gdk_texture_set_render_data (GdkTexture *self,
|
||||
gpointer key,
|
||||
gpointer data,
|
||||
|
@ -425,7 +425,7 @@ device_supports_incremental_present (VkPhysicalDevice device)
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexture.h"
|
||||
@ -480,7 +481,7 @@ gdk_save_png (GdkTexture *texture)
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
mtexture = gdk_texture_download_texture (texture);
|
||||
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (mtexture));
|
||||
format = gdk_texture_get_format (mtexture);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "gdktiffprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexture.h"
|
||||
@ -283,7 +284,7 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
memory_texture = gdk_texture_download_texture (texture);
|
||||
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (memory_texture));
|
||||
format = gdk_texture_get_format (memory_texture);
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
|
||||
|
@ -291,7 +291,7 @@ opaque_region_covers_surface (GdkMacosGLContext *self)
|
||||
|
||||
static void
|
||||
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
|
||||
@ -345,7 +345,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
|
||||
[self->gl_context update];
|
||||
}
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, request_hdr, painted);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, prefers_high_depth, painted);
|
||||
|
||||
if (!self->is_attached)
|
||||
{
|
||||
|
@ -30,6 +30,7 @@ gdk_public_sources = files([
|
||||
'gdkhsla.c',
|
||||
'gdkkeys.c',
|
||||
'gdkkeyuni.c',
|
||||
'gdkmemoryformat.c',
|
||||
'gdkmemorytexture.c',
|
||||
'gdkmonitor.c',
|
||||
'gdkpaintable.c',
|
||||
|
@ -144,7 +144,7 @@ gdk_wayland_cairo_context_create_surface (GdkWaylandCairoContext *self)
|
||||
|
||||
static void
|
||||
gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context);
|
||||
|
@ -47,12 +47,12 @@ G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
gdk_wayland_surface_ensure_wl_egl_window (gdk_draw_context_get_surface (draw_context));
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, request_hdr, region);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, prefers_high_depth, region);
|
||||
|
||||
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ create_cairo_surface_for_surface (GdkSurface *surface,
|
||||
|
||||
static void
|
||||
gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkWin32CairoContext *self = GDK_WIN32_CAIRO_CONTEXT (draw_context);
|
||||
|
@ -471,12 +471,12 @@ gdk_win32_gl_context_egl_make_current (GdkGLContext *context,
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, request_hdr, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -118,12 +118,12 @@ gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, request_hdr, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -68,12 +68,12 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
|
||||
|
||||
static void
|
||||
gdk_win32_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, request_hdr, update_area);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_vulkan_context_parent_class)->begin_frame (draw_context, prefers_high_depth, update_area);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -55,7 +55,7 @@ create_cairo_surface_for_surface (GdkSurface *surface)
|
||||
|
||||
static void
|
||||
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
|
||||
|
@ -61,10 +61,10 @@ gdk_x11_display_get_egl_display (GdkDisplay *display)
|
||||
|
||||
static void
|
||||
gdk_x11_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
|
||||
gboolean request_hdr,
|
||||
gboolean prefers_high_depth,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->begin_frame (draw_context, request_hdr, region);
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->begin_frame (draw_context, prefers_high_depth, region);
|
||||
|
||||
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
|
||||
}
|
||||
|
@ -725,3 +725,8 @@ gsk_value_dup_render_node (const GValue *value)
|
||||
return gsk_render_node_ref (value->data[0].v_pointer);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_render_node_prefers_high_depth (const GskRenderNode *node)
|
||||
{
|
||||
return node->prefers_high_depth;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "gsktransformprivate.h"
|
||||
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
#include "gdk/gdk-private.h"
|
||||
|
||||
#include <hb-ot.h>
|
||||
@ -1560,6 +1561,8 @@ gsk_texture_node_new (GdkTexture *texture,
|
||||
self->texture = g_object_ref (texture);
|
||||
graphene_rect_init_from_rect (&node->bounds, bounds);
|
||||
|
||||
node->prefers_high_depth = gdk_memory_format_prefers_high_depth (gdk_texture_get_format (texture));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -2730,11 +2733,13 @@ gsk_container_node_new (GskRenderNode **children,
|
||||
|
||||
self->children[0] = gsk_render_node_ref (children[0]);
|
||||
graphene_rect_init_from_rect (&bounds, &(children[0]->bounds));
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (children[0]);
|
||||
|
||||
for (guint i = 1; i < n_children; i++)
|
||||
{
|
||||
self->children[i] = gsk_render_node_ref (children[i]);
|
||||
graphene_rect_union (&bounds, &(children[i]->bounds), &bounds);
|
||||
node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
|
||||
}
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, &bounds);
|
||||
@ -2965,6 +2970,8 @@ gsk_transform_node_new (GskRenderNode *child,
|
||||
&child->bounds,
|
||||
&node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3100,6 +3107,8 @@ gsk_opacity_node_new (GskRenderNode *child,
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3302,6 +3311,8 @@ gsk_color_matrix_node_new (GskRenderNode *child,
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3451,6 +3462,8 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
|
||||
else
|
||||
graphene_rect_init_from_rect (&self->child_bounds, &child->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3582,6 +3595,8 @@ gsk_clip_node_new (GskRenderNode *child,
|
||||
|
||||
graphene_rect_intersection (&self->clip, &child->bounds, &node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3713,6 +3728,8 @@ gsk_rounded_clip_node_new (GskRenderNode *child,
|
||||
|
||||
graphene_rect_intersection (&self->clip.bounds, &child->bounds, &node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -3932,6 +3949,8 @@ gsk_shadow_node_new (GskRenderNode *child,
|
||||
|
||||
gsk_shadow_node_get_bounds (self, &node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4125,6 +4144,8 @@ gsk_blend_node_new (GskRenderNode *bottom,
|
||||
|
||||
graphene_rect_union (&bottom->bounds, &top->bounds, &node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (bottom) || gsk_render_node_prefers_high_depth (top);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4273,6 +4294,8 @@ gsk_cross_fade_node_new (GskRenderNode *start,
|
||||
|
||||
graphene_rect_union (&start->bounds, &end->bounds, &node->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (start) || gsk_render_node_prefers_high_depth (end);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4864,6 +4887,8 @@ gsk_blur_node_new (GskRenderNode *child,
|
||||
- clip_radius,
|
||||
- clip_radius);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -4986,6 +5011,8 @@ gsk_debug_node_new (GskRenderNode *child,
|
||||
|
||||
graphene_rect_init_from_rect (&node->bounds, &child->bounds);
|
||||
|
||||
node->prefers_high_depth = gsk_render_node_prefers_high_depth (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -5150,7 +5177,10 @@ gsk_gl_shader_node_new (GskGLShader *shader,
|
||||
{
|
||||
self->children = g_malloc_n (n_children, sizeof (GskRenderNode *));
|
||||
for (guint i = 0; i < n_children; i++)
|
||||
self->children[i] = gsk_render_node_ref (children[i]);
|
||||
{
|
||||
self->children[i] = gsk_render_node_ref (children[i]);
|
||||
node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -27,6 +27,8 @@ struct _GskRenderNode
|
||||
gatomicrefcount ref_count;
|
||||
|
||||
graphene_rect_t bounds;
|
||||
|
||||
guint prefers_high_depth : 1;
|
||||
};
|
||||
|
||||
struct _GskRenderNodeClass
|
||||
@ -109,6 +111,7 @@ GskRenderNode ** gsk_container_node_get_children (const GskRenderNode *no
|
||||
void gsk_transform_node_get_translate (const GskRenderNode *node,
|
||||
float *dx,
|
||||
float *dy);
|
||||
gboolean gsk_render_node_prefers_high_depth (const GskRenderNode *node);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gsk/gskdebugprivate.h>
|
||||
@ -1231,6 +1232,7 @@ gboolean
|
||||
gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint *out_fbo_id,
|
||||
@ -1247,6 +1249,7 @@ gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
|
||||
|
||||
texture_id = gsk_ngl_command_queue_create_texture (self,
|
||||
width, height,
|
||||
format,
|
||||
min_filter, mag_filter);
|
||||
|
||||
if (texture_id == -1)
|
||||
@ -1272,6 +1275,7 @@ int
|
||||
gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
@ -1296,9 +1300,9 @@ gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context))
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
else
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
/* Restore the previous texture if it was set */
|
||||
if (self->attachments->textures[0].id != 0)
|
||||
@ -1353,7 +1357,7 @@ gsk_ngl_command_queue_upload_texture (GskNglCommandQueue *self,
|
||||
height = MAX (height, self->max_texture_size);
|
||||
}
|
||||
|
||||
texture_id = gsk_ngl_command_queue_create_texture (self, width, height, min_filter, mag_filter);
|
||||
texture_id = gsk_ngl_command_queue_create_texture (self, width, height, GL_RGBA8, min_filter, mag_filter);
|
||||
if (texture_id == -1)
|
||||
return texture_id;
|
||||
|
||||
@ -1361,7 +1365,7 @@ gsk_ngl_command_queue_upload_texture (GskNglCommandQueue *self,
|
||||
{
|
||||
GdkMemoryTexture *memory_texture = GDK_MEMORY_TEXTURE (texture);
|
||||
data = gdk_memory_texture_get_data (memory_texture);
|
||||
data_format = gdk_memory_texture_get_format (memory_texture);
|
||||
data_format = gdk_texture_get_format (texture);
|
||||
data_stride = gdk_memory_texture_get_stride (memory_texture);
|
||||
}
|
||||
else
|
||||
|
@ -290,12 +290,14 @@ int gsk_ngl_command_queue_upload_texture (GskNglCommandQue
|
||||
int gsk_ngl_command_queue_create_texture (GskNglCommandQueue *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
guint gsk_ngl_command_queue_create_framebuffer (GskNglCommandQueue *self);
|
||||
gboolean gsk_ngl_command_queue_create_render_target (GskNglCommandQueue *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint *out_fbo_id,
|
||||
|
@ -183,6 +183,7 @@ gsk_ngl_driver_create_atlas (GskNglDriver *self)
|
||||
atlas->texture_id = gsk_ngl_command_queue_create_texture (self->command_queue,
|
||||
atlas->width,
|
||||
atlas->height,
|
||||
GL_RGBA8,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR);
|
||||
|
||||
@ -750,6 +751,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
guint texture_id;
|
||||
int height;
|
||||
int width;
|
||||
int format;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_NGL_DRIVER (self), 0);
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
|
||||
@ -757,6 +759,8 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
|
||||
context = self->command_queue->context;
|
||||
|
||||
format = GL_RGBA8;
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
@ -799,7 +803,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
mag_filter);
|
||||
|
||||
t = gsk_ngl_texture_new (texture_id,
|
||||
width, height, min_filter, mag_filter,
|
||||
width, height, format, min_filter, mag_filter,
|
||||
self->current_frame_id);
|
||||
|
||||
g_hash_table_insert (self->textures, GUINT_TO_POINTER (texture_id), t);
|
||||
@ -820,6 +824,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
* @self: a `GskNglDriver`
|
||||
* @width: the width of the texture
|
||||
* @height: the height of the texture
|
||||
* @format: format for the texture
|
||||
* @min_filter: GL_NEAREST or GL_LINEAR
|
||||
* @mag_filter: GL_NEAREST or GL_FILTER
|
||||
*
|
||||
@ -827,6 +832,8 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
* to upload data, map to a framebuffer, or other uses which may
|
||||
* modify the texture immediately.
|
||||
*
|
||||
* Typical examples for @format are GK_RGBA8, GL_RGBA16F or GL_RGBA32F.
|
||||
*
|
||||
* Use gsk_ngl_driver_release_texture() to release this texture back into
|
||||
* the pool so it may be reused later in the pipeline.
|
||||
*
|
||||
@ -837,6 +844,7 @@ GskNglTexture *
|
||||
gsk_ngl_driver_create_texture (GskNglDriver *self,
|
||||
float width,
|
||||
float height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
@ -847,9 +855,11 @@ gsk_ngl_driver_create_texture (GskNglDriver *self,
|
||||
|
||||
texture_id = gsk_ngl_command_queue_create_texture (self->command_queue,
|
||||
width, height,
|
||||
format,
|
||||
min_filter, mag_filter);
|
||||
texture = gsk_ngl_texture_new (texture_id,
|
||||
width, height,
|
||||
format,
|
||||
min_filter, mag_filter,
|
||||
self->current_frame_id);
|
||||
g_hash_table_insert (self->textures,
|
||||
@ -896,6 +906,7 @@ gsk_ngl_driver_release_texture (GskNglDriver *self,
|
||||
* @self: a `GskNglDriver`
|
||||
* @width: the width for the render target
|
||||
* @height: the height for the render target
|
||||
* @format: the format to use
|
||||
* @min_filter: the min filter to use for the texture
|
||||
* @mag_filter: the mag filter to use for the texture
|
||||
* @out_render_target: (out): a location for the render target
|
||||
@ -904,6 +915,8 @@ gsk_ngl_driver_release_texture (GskNglDriver *self,
|
||||
* bound to that framebuffer of the size @width x @height and using the
|
||||
* appropriate filters.
|
||||
*
|
||||
* Typical examples for @format are GK_RGBA8, GL_RGBA16F or GL_RGBA32F.
|
||||
*
|
||||
* Use gsk_ngl_driver_release_render_target() when you are finished with
|
||||
* the render target to release it. You may steal the texture from the
|
||||
* render target when releasing it.
|
||||
@ -915,6 +928,7 @@ gboolean
|
||||
gsk_ngl_driver_create_render_target (GskNglDriver *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
GskNglRenderTarget **out_render_target)
|
||||
@ -947,6 +961,7 @@ gsk_ngl_driver_create_render_target (GskNglDriver *self,
|
||||
|
||||
if (gsk_ngl_command_queue_create_render_target (self->command_queue,
|
||||
width, height,
|
||||
format,
|
||||
min_filter, mag_filter,
|
||||
&framebuffer_id, &texture_id))
|
||||
{
|
||||
@ -955,6 +970,7 @@ gsk_ngl_driver_create_render_target (GskNglDriver *self,
|
||||
render_target = g_slice_new0 (GskNglRenderTarget);
|
||||
render_target->min_filter = min_filter;
|
||||
render_target->mag_filter = mag_filter;
|
||||
render_target->format = format;
|
||||
render_target->width = width;
|
||||
render_target->height = height;
|
||||
render_target->framebuffer_id = framebuffer_id;
|
||||
@ -1014,6 +1030,7 @@ gsk_ngl_driver_release_render_target (GskNglDriver *self,
|
||||
texture = gsk_ngl_texture_new (render_target->texture_id,
|
||||
render_target->width,
|
||||
render_target->height,
|
||||
render_target->format,
|
||||
render_target->min_filter,
|
||||
render_target->mag_filter,
|
||||
self->current_frame_id);
|
||||
@ -1266,6 +1283,7 @@ gsk_ngl_driver_add_texture_slices (GskNglDriver *self,
|
||||
/* Allocate one Texture for the entire thing. */
|
||||
t = gsk_ngl_texture_new (0,
|
||||
tex_width, tex_height,
|
||||
GL_RGBA8,
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
self->current_frame_id);
|
||||
|
||||
|
@ -88,6 +88,7 @@ struct _GskNglRenderTarget
|
||||
guint texture_id;
|
||||
int min_filter;
|
||||
int mag_filter;
|
||||
int format;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
@ -144,6 +145,7 @@ GdkGLContext *gsk_ngl_driver_get_context (GskNglDriver
|
||||
gboolean gsk_ngl_driver_create_render_target (GskNglDriver *self,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
GskNglRenderTarget **render_target);
|
||||
@ -166,6 +168,7 @@ guint gsk_ngl_driver_load_texture (GskNglDriver
|
||||
GskNglTexture *gsk_ngl_driver_create_texture (GskNglDriver *self,
|
||||
float width,
|
||||
float height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
void gsk_ngl_driver_release_texture (GskNglDriver *self,
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
|
||||
#include "gsknglcommandqueueprivate.h"
|
||||
@ -237,7 +237,7 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary *self,
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data,
|
||||
width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
cairo_image_surface_get_data (surface),
|
||||
width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
|
||||
@ -115,7 +115,7 @@ gsk_ngl_icon_library_add (GskNglIconLibrary *self,
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
surface_data, cairo_image_surface_get_stride (surface),
|
||||
GDK_MEMORY_DEFAULT, width, height);
|
||||
gl_format = GL_RGBA;
|
||||
|
@ -22,8 +22,11 @@
|
||||
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdksurfaceprivate.h>
|
||||
#include <gsk/gskdebugprivate.h>
|
||||
#include <gsk/gskrendererprivate.h>
|
||||
#include <gsk/gskrendernodeprivate.h>
|
||||
|
||||
#include "gsknglcommandqueueprivate.h"
|
||||
#include "gskngldriverprivate.h"
|
||||
@ -201,7 +204,9 @@ gsk_ngl_renderer_render (GskRenderer *renderer,
|
||||
viewport.size.height = gdk_surface_get_height (surface) * scale_factor;
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->context), update_area);
|
||||
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->context),
|
||||
gsk_render_node_prefers_high_depth (root),
|
||||
update_area);
|
||||
|
||||
/* Must be called *AFTER* gdk_draw_context_begin_frame() */
|
||||
render_region = get_render_region (surface, self->context);
|
||||
@ -236,6 +241,7 @@ gsk_ngl_renderer_render_texture (GskRenderer *renderer,
|
||||
guint texture_id;
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
|
||||
g_assert (GSK_IS_NGL_RENDERER (renderer));
|
||||
g_assert (root != NULL);
|
||||
@ -243,8 +249,11 @@ gsk_ngl_renderer_render_texture (GskRenderer *renderer,
|
||||
width = ceilf (viewport->size.width);
|
||||
height = ceilf (viewport->size.height);
|
||||
|
||||
format = gsk_render_node_prefers_high_depth (root) ? GL_RGBA32F : GL_RGBA8;
|
||||
|
||||
if (gsk_ngl_driver_create_render_target (self->driver,
|
||||
width, height,
|
||||
format,
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&render_target))
|
||||
{
|
||||
|
@ -162,6 +162,11 @@ struct _GskNglRenderJob
|
||||
|
||||
/* If we should be rendering red zones over fallback nodes */
|
||||
guint debug_fallback : 1;
|
||||
|
||||
/* Format we want to use for intermediate textures, determined by
|
||||
* looking at the format of the framebuffer we are rendering on.
|
||||
*/
|
||||
int target_format;
|
||||
};
|
||||
|
||||
typedef struct _GskNglRenderOffscreen
|
||||
@ -198,6 +203,16 @@ static gboolean gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob
|
||||
const GskRenderNode *node,
|
||||
GskNglRenderOffscreen *offscreen);
|
||||
|
||||
static inline int
|
||||
get_target_format (GskNglRenderJob *job,
|
||||
const GskRenderNode *node)
|
||||
{
|
||||
if (gsk_render_node_prefers_high_depth (node))
|
||||
return job->target_format;
|
||||
|
||||
return GL_RGBA8;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_full_texture_region (GskNglRenderOffscreen *offscreen)
|
||||
{
|
||||
@ -1258,6 +1273,7 @@ blur_offscreen (GskNglRenderJob *job,
|
||||
if (!gsk_ngl_driver_create_render_target (job->driver,
|
||||
MAX (texture_to_blur_width, 1),
|
||||
MAX (texture_to_blur_height, 1),
|
||||
job->target_format,
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&pass1))
|
||||
return 0;
|
||||
@ -1268,6 +1284,7 @@ blur_offscreen (GskNglRenderJob *job,
|
||||
if (!gsk_ngl_driver_create_render_target (job->driver,
|
||||
texture_to_blur_width,
|
||||
texture_to_blur_height,
|
||||
job->target_format,
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&pass2))
|
||||
return gsk_ngl_driver_release_render_target (job->driver, pass1, FALSE);
|
||||
@ -2179,6 +2196,7 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job,
|
||||
|
||||
if (!gsk_ngl_driver_create_render_target (job->driver,
|
||||
texture_width, texture_height,
|
||||
get_target_format (job, node),
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&render_target))
|
||||
g_assert_not_reached ();
|
||||
@ -2449,6 +2467,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job,
|
||||
|
||||
gsk_ngl_driver_create_render_target (job->driver,
|
||||
texture_width, texture_height,
|
||||
get_target_format (job, node),
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&render_target);
|
||||
|
||||
@ -3856,6 +3875,7 @@ gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob *job,
|
||||
|
||||
if (!gsk_ngl_driver_create_render_target (job->driver,
|
||||
scaled_width, scaled_height,
|
||||
get_target_format (job, node),
|
||||
filter, filter,
|
||||
&render_target))
|
||||
g_assert_not_reached ();
|
||||
@ -3954,6 +3974,7 @@ gsk_ngl_render_job_render_flipped (GskNglRenderJob *job,
|
||||
if (!gsk_ngl_command_queue_create_render_target (job->command_queue,
|
||||
MAX (1, job->viewport.size.width),
|
||||
MAX (1, job->viewport.size.height),
|
||||
job->target_format,
|
||||
GL_NEAREST, GL_NEAREST,
|
||||
&framebuffer_id, &texture_id))
|
||||
return;
|
||||
@ -4044,6 +4065,22 @@ gsk_ngl_render_job_set_debug_fallback (GskNglRenderJob *job,
|
||||
job->debug_fallback = !!debug_fallback;
|
||||
}
|
||||
|
||||
static int
|
||||
get_framebuffer_format (guint framebuffer)
|
||||
{
|
||||
int size;
|
||||
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
|
||||
glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size);
|
||||
|
||||
if (size >= 32)
|
||||
return GL_RGBA32F;
|
||||
else if (size >= 16)
|
||||
return GL_RGBA16F;
|
||||
else
|
||||
return GL_RGBA8;
|
||||
}
|
||||
|
||||
GskNglRenderJob *
|
||||
gsk_ngl_render_job_new (GskNglDriver *driver,
|
||||
const graphene_rect_t *viewport,
|
||||
@ -4070,6 +4107,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver,
|
||||
job->scale_x = scale_factor;
|
||||
job->scale_y = scale_factor;
|
||||
job->viewport = *viewport;
|
||||
job->target_format = get_framebuffer_format (framebuffer);
|
||||
|
||||
gsk_ngl_render_job_set_alpha (job, 1.0f);
|
||||
gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL);
|
||||
|
@ -59,6 +59,7 @@ GskNglTexture *
|
||||
gsk_ngl_texture_new (guint texture_id,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
gint64 frame_id)
|
||||
@ -70,6 +71,7 @@ gsk_ngl_texture_new (guint texture_id,
|
||||
texture->link.data = texture;
|
||||
texture->min_filter = min_filter;
|
||||
texture->mag_filter = mag_filter;
|
||||
texture->format = format;
|
||||
texture->width = width;
|
||||
texture->height = height;
|
||||
texture->last_used_in_frame = frame_id;
|
||||
|
@ -228,7 +228,7 @@ gsk_ngl_texture_library_pack_one (GskNglTextureLibrary *self,
|
||||
height = MIN (height, self->driver->command_queue->max_texture_size);
|
||||
}
|
||||
|
||||
texture = gsk_ngl_driver_create_texture (self->driver, width, height, GL_LINEAR, GL_LINEAR);
|
||||
texture = gsk_ngl_driver_create_texture (self->driver, width, height, GL_RGBA8, GL_LINEAR, GL_LINEAR);
|
||||
texture->permanent = TRUE;
|
||||
|
||||
return texture;
|
||||
|
@ -67,6 +67,7 @@ struct _GskNglTexture
|
||||
int height;
|
||||
int min_filter;
|
||||
int mag_filter;
|
||||
int format;
|
||||
|
||||
/* Set when used by an atlas so we don't drop the texture */
|
||||
guint permanent : 1;
|
||||
@ -75,6 +76,7 @@ struct _GskNglTexture
|
||||
GskNglTexture *gsk_ngl_texture_new (guint texture_id,
|
||||
int width,
|
||||
int height,
|
||||
int format,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
gint64 frame_id);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <gtk.h>
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
compare_pixels (int width,
|
||||
int height,
|
||||
guchar *data1,
|
||||
@ -8,15 +8,17 @@ compare_pixels (int width,
|
||||
guchar *data2,
|
||||
gsize stride2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < height; i++)
|
||||
int x, y;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
gconstpointer p1 = data1 + i * stride1;
|
||||
gconstpointer p2 = data2 + i * stride2;
|
||||
if (memcmp (p1, p2, width * 4) != 0)
|
||||
return FALSE;
|
||||
const guint32 *p1 = (const guint32*) (data1 + y * stride1);
|
||||
const guint32 *p2 = (const guint32*) (data2 + y * stride2);
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
g_assert_cmphex (p1[x], ==, p2[x]);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -55,10 +57,10 @@ test_texture_from_pixbuf (void)
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
g_assert_true (compare_pixels (width, height,
|
||||
data, stride,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface)));
|
||||
compare_pixels (width, height,
|
||||
data, stride,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
g_free (data);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user