mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 21:40:22 +00:00
Merge branch 'gles-texture-colors' into 'master'
Fix uploads of textures in GLES (and make texture uploads better) See merge request GNOME/gtk!2616
This commit is contained in:
commit
c9f6a9f7c5
@ -300,7 +300,6 @@ gdk_cairo_rectangle
|
||||
gdk_cairo_region
|
||||
gdk_cairo_region_create_from_surface
|
||||
gdk_cairo_draw_from_gl
|
||||
gdk_cairo_surface_upload_to_gl
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
@ -61,13 +61,6 @@ void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_cairo_surface_upload_to_gl (cairo_surface_t *surface,
|
||||
int target,
|
||||
int width,
|
||||
int height,
|
||||
GdkGLContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_CAIRO_H__ */
|
||||
|
48
gdk/gdkgl.c
48
gdk/gdkgl.c
@ -438,51 +438,3 @@ out:
|
||||
if (clip_region)
|
||||
cairo_region_destroy (clip_region);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cairo_surface_upload_to_gl:
|
||||
* @surface: a Cairo surface
|
||||
* @target: a GL texture target
|
||||
* @width: the width of the texture @target
|
||||
* @height: the height of the texture @target
|
||||
* @context: (nullable): a #GdkGLContext, or %NULL to use the currently
|
||||
* bound context
|
||||
*
|
||||
* Uploads the contents of a Cairo @surface to a GL texture @target.
|
||||
*/
|
||||
void
|
||||
gdk_cairo_surface_upload_to_gl (cairo_surface_t *surface,
|
||||
int target,
|
||||
int width,
|
||||
int height,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_surface_t *tmp;
|
||||
double device_x_offset, device_y_offset;
|
||||
|
||||
g_return_if_fail (surface != NULL);
|
||||
g_return_if_fail (context == NULL || GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (context == NULL)
|
||||
context = gdk_gl_context_get_current ();
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
|
||||
cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset);
|
||||
|
||||
rect.x = (int) device_x_offset;
|
||||
rect.y = (int) device_y_offset;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
tmp = cairo_surface_map_to_image (surface, &rect);
|
||||
|
||||
gdk_gl_context_upload_texture (context,
|
||||
cairo_image_surface_get_data (tmp),
|
||||
rect.width,
|
||||
rect.height,
|
||||
cairo_image_surface_get_stride (tmp),
|
||||
target);
|
||||
|
||||
cairo_surface_unmap_image (surface, tmp);
|
||||
}
|
||||
|
@ -87,6 +87,7 @@
|
||||
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
@ -227,49 +228,90 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
GdkMemoryFormat data_format,
|
||||
guint texture_target)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
guchar *copy = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
guint bpp;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (priv->use_es)
|
||||
{
|
||||
/* GLES only supports rgba, so convert if necessary */
|
||||
if (data_format != GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
}
|
||||
|
||||
bpp = 4;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bpp = 4;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else /* Fall-back, convert to cairo-surface-format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
bpp = 4;
|
||||
data = copy;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
}
|
||||
|
||||
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
|
||||
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
|
||||
*/
|
||||
if (!priv->use_es ||
|
||||
(priv->use_es && (priv->gl_version >= 30 || priv->has_unpack_subimage)))
|
||||
if (stride == width * bpp)
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / 4);
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
}
|
||||
else if ((!priv->use_es ||
|
||||
(priv->use_es && (priv->gl_version >= 30 || priv->has_unpack_subimage))))
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, bpp);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
|
||||
|
||||
if (priv->use_es)
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
else
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
data);
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
if (priv->use_es)
|
||||
{
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, data + (i * stride));
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data + (i * stride));
|
||||
}
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, NULL);
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
|
||||
}
|
||||
|
||||
g_free (copy);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdkdrawcontextprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -84,6 +85,7 @@ void gdk_gl_context_upload_texture (GdkGLContext
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
GdkMemoryFormat data_format,
|
||||
guint texture_target);
|
||||
GdkGLContextPaintData * gdk_gl_context_get_paint_data (GdkGLContext *context);
|
||||
gboolean gdk_gl_context_use_texture_rectangle (GdkGLContext *context);
|
||||
|
@ -38,13 +38,14 @@ struct _GdkMemoryTextureClass
|
||||
|
||||
G_DEFINE_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK_TYPE_TEXTURE)
|
||||
|
||||
static gsize
|
||||
gsize
|
||||
gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
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:
|
||||
@ -199,6 +200,9 @@ convert_swizzle ## A ## R ## G ## B (guchar *dest_data, \
|
||||
}
|
||||
|
||||
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 \
|
||||
@ -267,6 +271,10 @@ 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)
|
||||
|
||||
typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
@ -275,16 +283,17 @@ typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][2] =
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
{
|
||||
{ convert_memcpy, convert_swizzle3210 },
|
||||
{ convert_swizzle3210, convert_memcpy },
|
||||
{ convert_swizzle_premultiply_3210_3210, convert_swizzle_premultiply_0123_3210 },
|
||||
{ convert_swizzle_premultiply_3210_0123, convert_swizzle_premultiply_0123_0123 },
|
||||
{ convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012 },
|
||||
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321 },
|
||||
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123 },
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321 }
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
void
|
||||
@ -297,7 +306,7 @@ gdk_memory_convert (guchar *dest_data,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
g_assert (dest_format < 2);
|
||||
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);
|
||||
|
@ -34,6 +34,8 @@ G_BEGIN_DECLS
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: 4 bytes; for alpha, red, green, blue.
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: 4 bytes; for red, green, blue, alpha
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_B8G8R8A8: 4 bytes; for blue, green, red, alpha.
|
||||
* @GDK_MEMORY_A8R8G8B8: 4 bytes; for alpha, red, green, blue.
|
||||
* @GDK_MEMORY_R8G8B8A8: 4 bytes; for red, green, blue, alpha.
|
||||
@ -58,6 +60,7 @@ G_BEGIN_DECLS
|
||||
typedef enum {
|
||||
GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
||||
GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
GDK_MEMORY_B8G8R8A8,
|
||||
GDK_MEMORY_A8R8G8B8,
|
||||
GDK_MEMORY_R8G8B8A8,
|
||||
|
@ -31,6 +31,8 @@ G_BEGIN_DECLS
|
||||
|
||||
#define GDK_MEMORY_CAIRO_FORMAT_ARGB32 GDK_MEMORY_DEFAULT
|
||||
|
||||
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);
|
||||
|
@ -130,28 +130,6 @@ gdk_texture_real_download (GdkTexture *self,
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
gdk_texture_real_download_surface (GdkTexture *texture)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t surface_status;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
|
||||
surface_status = cairo_surface_status (surface);
|
||||
if (surface_status != CAIRO_STATUS_SUCCESS)
|
||||
g_warning ("%s: surface error: %s", __FUNCTION__,
|
||||
cairo_status_to_string (surface_status));
|
||||
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
@ -216,7 +194,6 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->download = gdk_texture_real_download;
|
||||
klass->download_surface = gdk_texture_real_download_surface;
|
||||
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
@ -438,7 +415,23 @@ gdk_texture_get_height (GdkTexture *texture)
|
||||
cairo_surface_t *
|
||||
gdk_texture_download_surface (GdkTexture *texture)
|
||||
{
|
||||
return GDK_TEXTURE_GET_CLASS (texture)->download_surface (texture);
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t surface_status;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
|
||||
surface_status = cairo_surface_status (surface);
|
||||
if (surface_status != CAIRO_STATUS_SUCCESS)
|
||||
g_warning ("%s: surface error: %s", __FUNCTION__,
|
||||
cairo_status_to_string (surface_status));
|
||||
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -28,7 +28,6 @@ struct _GdkTextureClass {
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
cairo_surface_t * (* download_surface) (GdkTexture *texture);
|
||||
};
|
||||
|
||||
gpointer gdk_texture_new (const GdkTextureClass *klass,
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkgltextureprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <epoxy/gl.h>
|
||||
@ -58,6 +59,54 @@ struct _GskGLDriver
|
||||
|
||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
upload_gdk_texture (GdkTexture *source_texture,
|
||||
int target,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface = NULL;
|
||||
GdkMemoryFormat data_format;
|
||||
const guchar *data;
|
||||
gsize data_stride;
|
||||
gsize bpp;
|
||||
|
||||
g_return_if_fail (source_texture != NULL);
|
||||
g_return_if_fail (x_offset + width <= gdk_texture_get_width (source_texture));
|
||||
g_return_if_fail (y_offset + height <= gdk_texture_get_height (source_texture));
|
||||
|
||||
/* Note: GdkGLTextures are already handled before we reach this and reused as-is */
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (source_texture))
|
||||
{
|
||||
GdkMemoryTexture *memory_texture = GDK_MEMORY_TEXTURE (source_texture);
|
||||
data = gdk_memory_texture_get_data (memory_texture);
|
||||
data_format = gdk_memory_texture_get_format (memory_texture);
|
||||
data_stride = gdk_memory_texture_get_stride (memory_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to downloading to a surface */
|
||||
surface = gdk_texture_download_surface (source_texture);
|
||||
cairo_surface_flush (surface);
|
||||
data = cairo_image_surface_get_data (surface);
|
||||
data_format = GDK_MEMORY_DEFAULT;
|
||||
data_stride = cairo_image_surface_get_stride (surface);
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
|
||||
gdk_gl_context_upload_texture (gdk_gl_context_get_current (),
|
||||
data + x_offset * bpp + y_offset * data_stride,
|
||||
width, height, data_stride,
|
||||
data_format, target);
|
||||
|
||||
if (surface)
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
static Texture *
|
||||
texture_new (void)
|
||||
{
|
||||
@ -408,32 +457,15 @@ gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
|
||||
slices = g_new0 (TextureSlice, cols * rows);
|
||||
|
||||
/* TODO: (Perf):
|
||||
* We still create a surface here, which should obviously be unnecessary
|
||||
* and we should eventually remove it and upload the data directly.
|
||||
*/
|
||||
for (col = 0; col < cols; col ++)
|
||||
{
|
||||
const int slice_width = MIN (max_texture_size, texture->width - x);
|
||||
const int stride = slice_width * 4;
|
||||
|
||||
for (row = 0; row < rows; row ++)
|
||||
{
|
||||
const int slice_height = MIN (max_texture_size, texture->height - y);
|
||||
const int slice_index = (col * rows) + row;
|
||||
guchar *data;
|
||||
guint texture_id;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
data = g_malloc (sizeof (guchar) * stride * slice_height);
|
||||
|
||||
gdk_texture_download_area (texture,
|
||||
&(GdkRectangle){x, y, slice_width, slice_height},
|
||||
data, stride);
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
slice_width, slice_height,
|
||||
stride);
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
|
||||
@ -442,7 +474,7 @@ gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
#endif
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
gsk_gl_driver_set_texture_parameters (self, GL_NEAREST, GL_NEAREST);
|
||||
gdk_cairo_surface_upload_to_gl (surface, GL_TEXTURE_2D, slice_width, slice_height, NULL);
|
||||
upload_gdk_texture (texture, GL_TEXTURE_2D, x, y, slice_width, slice_height);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.surface_uploads);
|
||||
@ -451,9 +483,6 @@ gsk_gl_driver_slice_texture (GskGLDriver *self,
|
||||
slices[slice_index].rect = (GdkRectangle){x, y, slice_width, slice_height};
|
||||
slices[slice_index].texture_id = texture_id;
|
||||
|
||||
g_free (data);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
y += slice_height;
|
||||
}
|
||||
|
||||
@ -486,7 +515,8 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
cairo_surface_t *surface;
|
||||
GdkTexture *downloaded_texture = NULL;
|
||||
GdkTexture *source_texture;
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
@ -494,14 +524,20 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
|
||||
if (texture_context != self->gl_context)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
/* In this case, we have to temporarily make the texture's context the current one,
|
||||
* download its data into our context and then create a texture from it. */
|
||||
if (texture_context)
|
||||
gdk_gl_context_make_current (texture_context);
|
||||
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
downloaded_texture = gdk_texture_new_for_surface (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
source_texture = downloaded_texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -519,7 +555,7 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
source_texture = texture;
|
||||
}
|
||||
|
||||
t = create_texture (self, gdk_texture_get_width (texture), gdk_texture_get_height (texture));
|
||||
@ -528,15 +564,16 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
t->user = texture;
|
||||
|
||||
gsk_gl_driver_bind_source_texture (self, t->texture_id);
|
||||
gsk_gl_driver_init_texture_with_surface (self,
|
||||
t->texture_id,
|
||||
surface,
|
||||
min_filter,
|
||||
mag_filter);
|
||||
gsk_gl_driver_init_texture (self,
|
||||
t->texture_id,
|
||||
source_texture,
|
||||
min_filter,
|
||||
mag_filter);
|
||||
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, t->texture_id,
|
||||
"GdkTexture<%p> %d", texture, t->texture_id);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
if (downloaded_texture)
|
||||
g_object_unref (downloaded_texture);
|
||||
|
||||
return t->texture_id;
|
||||
}
|
||||
@ -769,11 +806,11 @@ filter_uses_mipmaps (int filter)
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_init_texture_with_surface (GskGLDriver *self,
|
||||
int texture_id,
|
||||
cairo_surface_t *surface,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
gsk_gl_driver_init_texture (GskGLDriver *self,
|
||||
int texture_id,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
|
||||
@ -794,7 +831,7 @@ gsk_gl_driver_init_texture_with_surface (GskGLDriver *self,
|
||||
|
||||
gsk_gl_driver_set_texture_parameters (self, min_filter, mag_filter);
|
||||
|
||||
gdk_cairo_surface_upload_to_gl (surface, GL_TEXTURE_2D, t->width, t->height, NULL);
|
||||
upload_gdk_texture (texture, GL_TEXTURE_2D, 0, 0, t->width, t->height);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.surface_uploads);
|
||||
|
@ -63,9 +63,9 @@ void gsk_gl_driver_init_texture_empty (GskGLDriver *driver
|
||||
int texture_id,
|
||||
int min_filter,
|
||||
int max_filter);
|
||||
void gsk_gl_driver_init_texture_with_surface (GskGLDriver *driver,
|
||||
void gsk_gl_driver_init_texture (GskGLDriver *driver,
|
||||
int texture_id,
|
||||
cairo_surface_t *surface,
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "gskgltextureatlasprivate.h"
|
||||
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkmemorytextureprivate.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include <cairo.h>
|
||||
@ -186,6 +187,10 @@ upload_glyph (GlyphCacheKey *key,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
GskImageRegion r;
|
||||
guchar *pixel_data;
|
||||
guchar *free_data = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
|
||||
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
||||
"Uploading glyph %d",
|
||||
@ -197,15 +202,27 @@ upload_glyph (GlyphCacheKey *key,
|
||||
glBindTexture (GL_TEXTURE_2D, value->texture_id);
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, r.x, r.y, r.width, r.height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
r.data);
|
||||
{
|
||||
pixel_data = free_data = g_malloc (r.width * r.height * 4);
|
||||
gdk_memory_convert (pixel_data, r.width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
r.data, r.width * 4,
|
||||
GDK_MEMORY_DEFAULT, r.width, r.height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, r.x, r.y, r.width, r.height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
r.data);
|
||||
{
|
||||
pixel_data = r.data;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, r.x, r.y, r.width, r.height,
|
||||
gl_format, gl_type, pixel_data);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
g_free (r.data);
|
||||
g_free (free_data);
|
||||
}
|
||||
|
||||
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "gskgliconcacheprivate.h"
|
||||
#include "gskgltextureatlasprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkmemorytextureprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@ -134,7 +135,10 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
int packed_y = 0;
|
||||
cairo_surface_t *surface;
|
||||
unsigned char *surface_data;
|
||||
unsigned char *pixel_data;
|
||||
guchar *free_data = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
|
||||
gsk_gl_texture_atlases_pack (self->atlases, width + 2, height + 2, &atlas, &packed_x, &packed_y);
|
||||
|
||||
@ -158,36 +162,47 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
"Uploading texture");
|
||||
|
||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||
gl_format = GL_RGBA;
|
||||
{
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
surface_data, cairo_image_surface_get_stride (surface),
|
||||
GDK_MEMORY_DEFAULT, width, height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
gl_format = GL_BGRA;
|
||||
{
|
||||
pixel_data = surface_data;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + 1, packed_y + 1,
|
||||
width, height,
|
||||
gl_format,
|
||||
GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding top */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + 1, packed_y,
|
||||
width, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding left */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y + 1,
|
||||
1, height,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding top left */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y,
|
||||
1, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
|
||||
/* Padding right */
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
|
||||
@ -195,14 +210,14 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + width + 1, packed_y + 1,
|
||||
1, height,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding top right */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + width + 1, packed_y,
|
||||
1, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding bottom */
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
@ -210,22 +225,22 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + 1, packed_y + 1 + height,
|
||||
width, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding bottom left */
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x, packed_y + 1 + height,
|
||||
1, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Padding bottom right */
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, width - 1);
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
packed_x + 1 + width, packed_y + 1 + height,
|
||||
1, 1,
|
||||
gl_format, GL_UNSIGNED_BYTE,
|
||||
surface_data);
|
||||
gl_format, gl_type,
|
||||
pixel_data);
|
||||
/* Reset this */
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
@ -236,6 +251,7 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
*out_icon_data = icon_data;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
g_free (free_data);
|
||||
|
||||
#if 0
|
||||
{
|
||||
|
@ -564,6 +564,7 @@ render_fallback_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
const float scale = ops_get_scale (builder);
|
||||
const int surface_width = ceilf (node->bounds.size.width * scale);
|
||||
const int surface_height = ceilf (node->bounds.size.height * scale);
|
||||
@ -645,15 +646,18 @@ render_fallback_node (GskGLRenderer *self,
|
||||
#endif
|
||||
cairo_destroy (cr);
|
||||
|
||||
|
||||
/* Upload the Cairo surface to a GL texture */
|
||||
texture_id = gsk_gl_driver_create_texture (self->gl_driver,
|
||||
surface_width,
|
||||
surface_height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
|
||||
gsk_gl_driver_init_texture_with_surface (self->gl_driver,
|
||||
texture_id,
|
||||
surface,
|
||||
GL_NEAREST, GL_NEAREST);
|
||||
|
||||
texture = gdk_texture_new_for_surface (surface);
|
||||
gsk_gl_driver_init_texture (self->gl_driver,
|
||||
texture_id,
|
||||
texture,
|
||||
GL_NEAREST, GL_NEAREST);
|
||||
|
||||
if (gdk_gl_context_has_debug (self->gl_context))
|
||||
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
|
||||
@ -661,6 +665,7 @@ render_fallback_node (GskGLRenderer *self,
|
||||
g_type_name_from_instance ((GTypeInstance *) node),
|
||||
texture_id);
|
||||
|
||||
g_object_unref (texture);
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_surface_destroy (rendered_surface);
|
||||
|
||||
|
@ -37,6 +37,7 @@ typedef struct _TestData {
|
||||
static MemoryData tests[GDK_MEMORY_N_FORMATS] = {
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(00,FF,00,FF), RGBA(00,00,FF,FF), RGBA(00,00,00,00), RGBA(66,22,44,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(FF,00,FF,00), RGBA(FF,FF,00,00), RGBA(00,00,00,00), RGBA(AA,44,22,66) } },
|
||||
{ 4, FALSE, { RGBA(00,00,FF,FF), RGBA(00,FF,00,FF), RGBA(FF,00,00,FF), RGBA(00,00,00,00), RGBA(44,22,66,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(00,FF,00,FF), RGBA(00,00,FF,FF), RGBA(00,00,00,00), RGBA(99,33,66,AA) } },
|
||||
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(FF,00,FF,00), RGBA(FF,FF,00,00), RGBA(00,00,00,00), RGBA(AA,66,33,99) } },
|
||||
{ 4, FALSE, { RGBA(00,00,FF,FF), RGBA(00,FF,00,FF), RGBA(FF,00,00,FF), RGBA(00,00,00,00), RGBA(66,33,99,AA) } },
|
||||
|
Loading…
Reference in New Issue
Block a user