Compare commits
4 Commits
inline-vec
...
gpu-2d-typ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdc6ef5b8b | ||
|
|
81da31d662 | ||
|
|
f3c2cdb94d | ||
|
|
0ae2c1a8a7 |
497
gsk/boxprivate.h
Normal file
497
gsk/boxprivate.h
Normal file
@@ -0,0 +1,497 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
#include <math.h>
|
||||
#include "gsktypesprivate.h"
|
||||
#include "scaleprivate.h"
|
||||
#include "pointprivate.h"
|
||||
|
||||
#ifndef USE_SIMD
|
||||
|
||||
struct _Box
|
||||
{
|
||||
float x0, y0, x1, y1;
|
||||
};
|
||||
|
||||
static inline float
|
||||
box_x0 (const Box box)
|
||||
{
|
||||
return box.x0;
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_y0 (const Box box)
|
||||
{
|
||||
return box.y0;
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_x1 (const Box box)
|
||||
{
|
||||
return box.x1;
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_y1 (const Box box)
|
||||
{
|
||||
return box.y1;
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_width (const Box box)
|
||||
{
|
||||
return box.x1 - box.x0;
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_height (const Box box)
|
||||
{
|
||||
return box.y1 - box.y0;
|
||||
}
|
||||
|
||||
/* Assumes x0 <= x1 && y0 <= y1 */
|
||||
static inline Box
|
||||
box (float x0,
|
||||
float y0,
|
||||
float x1,
|
||||
float y1)
|
||||
{
|
||||
return (Box) { .x0 = x0, .y0 = y0, .x1 = x1, .y1 = y1 };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_from_rect (float x,
|
||||
float y,
|
||||
float w,
|
||||
float h)
|
||||
{
|
||||
return box (x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_from_graphene (const graphene_rect_t *rect)
|
||||
{
|
||||
return box_from_rect (rect->origin.x,
|
||||
rect->origin.y,
|
||||
rect->size.width,
|
||||
rect->size.height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_to_graphene (const Box box,
|
||||
graphene_rect_t *rect)
|
||||
{
|
||||
graphene_rect_init (rect, box.x0, box.y0, box.x1 - box.x0, box.y1 - box.y0);
|
||||
}
|
||||
|
||||
/* Assumes p0.x <= p1.x && p0.y <= p1.y */
|
||||
static inline Box
|
||||
box_from_points (Point p0,
|
||||
Point p1)
|
||||
{
|
||||
return box (p0.x, p0.y, p1.x, p1.y);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
box_origin (const Box box)
|
||||
{
|
||||
return point (box.x0, box.y0);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
box_opposite (const Box box)
|
||||
{
|
||||
return point (box.x1, box.y1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_to_float (const Box box,
|
||||
float v[4])
|
||||
{
|
||||
v[0] = box.x0;
|
||||
v[1] = box.y0;
|
||||
v[2] = box.x1 - box.x0;
|
||||
v[3] = box.y1 - box.y0;
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_inset (const Box box,
|
||||
float dx,
|
||||
float dy)
|
||||
{
|
||||
return (Box) { .x0 = box.x0 + dx, .y0 = box.y0 + dy,
|
||||
.x1 = box.x1 - dx, .y1 = box.y1 - dy };
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_intersect (const Box box1,
|
||||
const Box box2,
|
||||
Box *box)
|
||||
{
|
||||
Box b;
|
||||
|
||||
b.x0 = MAX (box1.x0, box2.x0);
|
||||
b.y0 = MAX (box1.y0, box2.y0);
|
||||
b.x1 = MIN (box1.x1, box2.x1);
|
||||
b.y1 = MIN (box1.y1, box2.y1);
|
||||
|
||||
if (b.x0 <= b.x1 && b.y0 <= b.x1)
|
||||
{
|
||||
if (box)
|
||||
*box = b;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_equal (const Box box1,
|
||||
const Box box2)
|
||||
{
|
||||
return memcmp (&box1, &box2, sizeof (Box)) == 0;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_contains (const Box box1,
|
||||
const Box box2)
|
||||
{
|
||||
Box box;
|
||||
|
||||
if (box_intersect (box1, box2, &box))
|
||||
return box_equal (box, box2);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_empty (const Box box)
|
||||
{
|
||||
return box.x0 == box.x1 || box.y0 == box.y1;
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_add (const Box box,
|
||||
const Point offset)
|
||||
{
|
||||
return (Box) { .x0 = box.x0 + offset.x, .y0 = box.y0 + offset.y,
|
||||
.x1 = box.x1 + offset.x, .y1 = box.y1 + offset.y };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_sub (const Box box,
|
||||
const Point offset)
|
||||
{
|
||||
return (Box) { .x0 = box.x0 - offset.x, .y0 = box.y0 - offset.y,
|
||||
.x1 = box.x1 - offset.x, .y1 = box.y1 - offset.y };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_mul (const Box box,
|
||||
const Scale scale)
|
||||
{
|
||||
Box b = (Box) { .x0 = box.x0 * scale.x, .y0 = box.y0 * scale.y,
|
||||
.x1 = box.x1 * scale.x, .y1 = box.y1 * scale.y };
|
||||
|
||||
if (G_UNLIKELY (scale.x < 0 || scale.y < 0))
|
||||
return (Box) { .x0 = MIN (b.x0, b.x1), .y0 = MIN (b.y0, b.y1),
|
||||
.x1 = MAX (b.x0, b.x1), .y1 = MAX (b.y0, b.y1) };
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_div (const Box box,
|
||||
const Scale scale)
|
||||
{
|
||||
return box_mul (box, scale_inv (scale));
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_offset_to_float (const Box box,
|
||||
const Point offset,
|
||||
float v[4])
|
||||
{
|
||||
box_to_float (box_add (box, offset), v);
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_round_larger (const Box box)
|
||||
{
|
||||
return (Box) { .x0 = floorf (box.x0), .y0 = floorf (box.y0),
|
||||
.x1 = ceilf (box.x1), .y1 = ceilf (box.y1) };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_round_to_pixels (const Box box,
|
||||
const Scale scale,
|
||||
const Point offset)
|
||||
{
|
||||
return box_sub (box_div (box_round_larger (box_mul (box_add (box, offset), scale)), scale), offset);
|
||||
}
|
||||
|
||||
#else /* USE_SIMD */
|
||||
|
||||
struct _Box
|
||||
{
|
||||
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
|
||||
};
|
||||
|
||||
static inline float
|
||||
box_x0 (const Box box)
|
||||
{
|
||||
return graphene_simd4f_get_x (box.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_y0 (const Box box)
|
||||
{
|
||||
return graphene_simd4f_get_y (box.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_x1 (const Box box)
|
||||
{
|
||||
return graphene_simd4f_get_z (box.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_y1 (const Box box)
|
||||
{
|
||||
return graphene_simd4f_get_w (box.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_width (const Box box)
|
||||
{
|
||||
return box_x1 (box) - box_x0 (box);
|
||||
}
|
||||
|
||||
static inline float
|
||||
box_height (const Box box)
|
||||
{
|
||||
return box_y1 (box) - box_y0 (box);
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box (float x0,
|
||||
float y0,
|
||||
float x1,
|
||||
float y1)
|
||||
{
|
||||
return (Box) { .v = graphene_simd4f_init (x0, y0, x1, y1) };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_from_rect (float x,
|
||||
float y,
|
||||
float w,
|
||||
float h)
|
||||
{
|
||||
return box (x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_from_graphene (const graphene_rect_t *rect)
|
||||
{
|
||||
return box_from_rect (rect->origin.x,
|
||||
rect->origin.y,
|
||||
rect->size.width,
|
||||
rect->size.height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_to_graphene (const Box box,
|
||||
graphene_rect_t *rect)
|
||||
{
|
||||
graphene_rect_init (rect, box_x0 (box),
|
||||
box_y0 (box),
|
||||
box_x1 (box) - box_x0 (box),
|
||||
box_y1 (box) - box_y0 (box));
|
||||
}
|
||||
|
||||
/* Assumes p0.x <= p1.x && p0.y <= p1.y */
|
||||
/* { a[0], a[1], b[0], b[1] } */
|
||||
# define graphene_simd4f_splat_xyxy(a,b) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_shuffle_ps ((a), (b), _MM_SHUFFLE (1, 0, 1, 0)); \
|
||||
}))
|
||||
|
||||
static inline Box
|
||||
box_from_points (Point p0,
|
||||
Point p1)
|
||||
{
|
||||
return (Box) { .v = graphene_simd4f_splat_xyxy (p0.v, p1.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
box_origin (const Box box)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_zero_zw (box.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
box_opposite (const Box box)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_zero_zw (graphene_simd4f_shuffle_zwxy (box.v)) };
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_to_float (const Box box,
|
||||
float v[4])
|
||||
{
|
||||
graphene_simd4f_dup_4f (box.v, v);
|
||||
v[2] -= v[0];
|
||||
v[3] -= v[1];
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_inset (const Box box,
|
||||
float dx,
|
||||
float dy)
|
||||
{
|
||||
return (Box) { .v = graphene_simd4f_add (box.v, graphene_simd4f_init (dx, dy, -dx, -dy)) };
|
||||
}
|
||||
|
||||
/* return a[0] < b[0] && a[1] < b[1] */
|
||||
#ifndef graphene_simd4f_cmple_xy
|
||||
# define graphene_simd4f_cmple_xy(a,b) \
|
||||
(__extension__ ({ \
|
||||
__m128i __res = (__m128i) _mm_cmple_ps ((a), (b)); \
|
||||
(bool) ((_mm_movemask_epi8 (__res) & 0xff) == 0xff); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
static inline gboolean
|
||||
box_intersect (const Box box1,
|
||||
const Box box2,
|
||||
Box *box)
|
||||
{
|
||||
graphene_simd4f_t s, t, t1;
|
||||
|
||||
s = graphene_simd4f_max (box1.v, box2.v);
|
||||
t = graphene_simd4f_min (box1.v, box2.v);
|
||||
t1 = graphene_simd4f_shuffle_zwxy (t);
|
||||
|
||||
if (graphene_simd4f_cmple_xy (s, t1))
|
||||
{
|
||||
if (box)
|
||||
box->v = graphene_simd4f_splat_xyxy (s, t);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_equal (const Box box1,
|
||||
const Box box2)
|
||||
{
|
||||
return (gboolean) !!graphene_simd4f_cmp_eq (box1.v, box2.v);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_contains (const Box box1,
|
||||
const Box box2)
|
||||
{
|
||||
Box box;
|
||||
|
||||
if (box_intersect (box1, box2, &box))
|
||||
return box_equal (box, box2);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
box_empty (const Box box)
|
||||
{
|
||||
/* FIXME simd */
|
||||
return box_x0 (box) == box_x1 (box) || box_y0 (box) == box_y1 (box);
|
||||
}
|
||||
|
||||
/* a splat variation */
|
||||
#ifndef graphene_simd4f_shuffle_xyxy
|
||||
# define graphene_simd4f_shuffle_xyxy(v) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_shuffle_ps ((v), (v), _MM_SHUFFLE (1, 0, 1, 0)); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
static inline Box
|
||||
box_add (const Box box,
|
||||
const Point offset)
|
||||
{
|
||||
return (Box) { .v = graphene_simd4f_add (box.v, graphene_simd4f_shuffle_xyxy (offset.v)) };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_sub (const Box box,
|
||||
const Point offset)
|
||||
{
|
||||
return (Box) { .v = graphene_simd4f_sub (box.v, graphene_simd4f_shuffle_xyxy (offset.v)) };
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_mul (const Box box,
|
||||
const Scale scale)
|
||||
{
|
||||
Box b = (Box) { .v = graphene_simd4f_mul (box.v, graphene_simd4f_shuffle_xyxy (scale.v)) };
|
||||
|
||||
if (G_UNLIKELY (!graphene_simd4f_cmple_xy (graphene_simd4f_init (0, 0, 0, 0), scale.v)))
|
||||
{
|
||||
graphene_simd4f_t v = graphene_simd4f_shuffle_zwxy (b.v);
|
||||
graphene_simd4f_t s = graphene_simd4f_min (b.v, v);
|
||||
graphene_simd4f_t t = graphene_simd4f_max (b.v, v);
|
||||
|
||||
return (Box) { .v = graphene_simd4f_splat_xyxy (s, t) };
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline Box
|
||||
box_div (const Box box,
|
||||
const Scale scale)
|
||||
{
|
||||
return box_mul (box, scale_inv (scale));
|
||||
}
|
||||
|
||||
static inline void
|
||||
box_offset_to_float (const Box box,
|
||||
const Point offset,
|
||||
float v[4])
|
||||
{
|
||||
box_to_float (box_add (box, offset), v);
|
||||
}
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
|
||||
static inline Box
|
||||
box_round_larger (const Box box)
|
||||
{
|
||||
return { (Box) .v = graphene_simd4f_splat_xyxy (graphene_simd4f_floor (b.v), graphene_simd4f_ceil (b.v)) };
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline Box
|
||||
box_round_larger (const Box b)
|
||||
{
|
||||
return box (floorf (box_x0 (b)),
|
||||
floorf (box_y0 (b)),
|
||||
ceilf (box_x1 (b)),
|
||||
ceilf (box_y1 (b)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline Box
|
||||
box_round_to_pixels (const Box box,
|
||||
const Scale scale,
|
||||
const Point offset)
|
||||
{
|
||||
return box_sub (box_div (box_round_larger (box_mul (box_add (box, offset), scale)), scale), offset);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskpath.h"
|
||||
#include "gskrectprivate.h"
|
||||
#include "gskvec2private.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
@@ -46,6 +45,10 @@
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdksubsurfaceprivate.h"
|
||||
|
||||
#include "gsk/scaleprivate.h"
|
||||
#include "gsk/pointprivate.h"
|
||||
#include "gsk/boxprivate.h"
|
||||
|
||||
/* the epsilon we allow pixels to be off due to rounding errors.
|
||||
* Chosen rather randomly.
|
||||
*/
|
||||
@@ -196,9 +199,9 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
||||
|
||||
self->modelview = NULL;
|
||||
gsk_gpu_image_get_projection_matrix (target, &self->projection);
|
||||
gsk_vec2_init (&self->scale,
|
||||
width / viewport->size.width,
|
||||
height / viewport->size.height);
|
||||
graphene_vec2_init (&self->scale,
|
||||
width / viewport->size.width,
|
||||
height / viewport->size.height);
|
||||
self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x,
|
||||
-viewport->origin.y);
|
||||
self->opacity = 1.0;
|
||||
@@ -320,8 +323,8 @@ rect_round_to_pixels (const graphene_rect_t *src,
|
||||
{
|
||||
float x, y, xscale, yscale, inv_xscale, inv_yscale;
|
||||
|
||||
xscale = gsk_vec2_get_x (pixel_scale);
|
||||
yscale = gsk_vec2_get_y (pixel_scale);
|
||||
xscale = graphene_vec2_get_x (pixel_scale);
|
||||
yscale = graphene_vec2_get_y (pixel_scale);
|
||||
inv_xscale = 1.0f / xscale;
|
||||
inv_yscale = 1.0f / yscale;
|
||||
|
||||
@@ -346,8 +349,8 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
|
||||
|
||||
area.x = 0;
|
||||
area.y = 0;
|
||||
area.width = ceilf (gsk_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
||||
area.height = ceilf (gsk_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
||||
area.width = ceilf (graphene_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
||||
area.height = ceilf (graphene_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
||||
|
||||
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
@@ -630,8 +633,8 @@ gsk_gpu_node_processor_rect_is_integer (GskGpuNodeProcessor *self,
|
||||
cairo_rectangle_int_t *int_rect)
|
||||
{
|
||||
graphene_rect_t transformed_rect;
|
||||
float scale_x = gsk_vec2_get_x (&self->scale);
|
||||
float scale_y = gsk_vec2_get_y (&self->scale);
|
||||
float scale_x = graphene_vec2_get_x (&self->scale);
|
||||
float scale_y = graphene_vec2_get_y (&self->scale);
|
||||
|
||||
switch (gsk_transform_get_category (self->modelview))
|
||||
{
|
||||
@@ -1031,7 +1034,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
||||
|
||||
gsk_gpu_node_processor_sync_globals (&other, 0);
|
||||
|
||||
gsk_vec2_init (&direction, blur_radius, 0.0f);
|
||||
graphene_vec2_init (&direction, blur_radius, 0.0f);
|
||||
gsk_gpu_blur_op (other.frame,
|
||||
gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &intermediate_rect),
|
||||
source_desc,
|
||||
@@ -1045,7 +1048,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
||||
|
||||
real_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow_offset->x,
|
||||
self->offset.y + shadow_offset->y);
|
||||
gsk_vec2_init (&direction, 0.0f, blur_radius);
|
||||
graphene_vec2_init (&direction, 0.0f, blur_radius);
|
||||
intermediate_descriptor = gsk_gpu_node_processor_add_image (self, intermediate, GSK_GPU_SAMPLER_TRANSPARENT);
|
||||
if (shadow_color)
|
||||
{
|
||||
@@ -1582,8 +1585,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
||||
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||
gsk_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
self->modelview = gsk_transform_scale (self->modelview,
|
||||
scale_x / fabs (scale_x),
|
||||
scale_y / fabs (scale_y));
|
||||
@@ -1643,15 +1646,15 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
old_modelview = gsk_transform_ref (self->modelview);
|
||||
|
||||
self->modelview = gsk_transform_scale (self->modelview,
|
||||
gsk_vec2_get_x (&self->scale),
|
||||
gsk_vec2_get_y (&self->scale));
|
||||
graphene_vec2_get_x (&self->scale),
|
||||
graphene_vec2_get_y (&self->scale));
|
||||
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
|
||||
gsk_transform_unref (clip_transform);
|
||||
|
||||
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
|
||||
|
||||
old_pixels = MAX (gsk_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||
gsk_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
|
||||
old_pixels = MAX (graphene_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||
graphene_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
|
||||
new_pixels = MAX (scale_x * self->clip.rect.bounds.size.width,
|
||||
scale_y * self->clip.rect.bounds.size.height);
|
||||
|
||||
@@ -1664,7 +1667,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
}
|
||||
|
||||
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
|
||||
gsk_vec2_init (&self->scale, scale_x, scale_y);
|
||||
graphene_vec2_init (&self->scale, scale_x, scale_y);
|
||||
self->offset = *graphene_point_zero ();
|
||||
}
|
||||
break;
|
||||
@@ -1736,8 +1739,8 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
|
||||
self->bounds.size.width *= inv_sx;
|
||||
self->bounds.size.height *= inv_sy;
|
||||
self->offset = GRAPHENE_POINT_INIT (0, 0);
|
||||
gsk_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
||||
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
graphene_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1821,8 +1824,8 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
scale_x = gsk_vec2_get_x (&self->scale);
|
||||
scale_y = gsk_vec2_get_y (&self->scale);
|
||||
scale_x = graphene_vec2_get_x (&self->scale);
|
||||
scale_y = graphene_vec2_get_y (&self->scale);
|
||||
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
||||
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
||||
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, graphene_point_zero(), &clipped);
|
||||
@@ -1949,8 +1952,8 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||
}
|
||||
|
||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
||||
{
|
||||
guint32 descriptor;
|
||||
|
||||
@@ -2016,8 +2019,8 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self,
|
||||
}
|
||||
|
||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
||||
{
|
||||
image = gsk_gpu_node_processor_ensure_image (self->frame,
|
||||
image,
|
||||
@@ -2061,7 +2064,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
gboolean need_mipmap, need_offscreen;
|
||||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
gsk_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||
if (need_offscreen)
|
||||
{
|
||||
GskGpuImage *offscreen;
|
||||
@@ -2997,12 +3000,13 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
GskGpuDevice *device;
|
||||
const PangoGlyphInfo *glyphs;
|
||||
PangoFont *font;
|
||||
graphene_point_t offset;
|
||||
Point offset;
|
||||
Scale s, pango_scale, s4, ss;
|
||||
guint i, num_glyphs;
|
||||
float scale, inv_scale;
|
||||
GdkRGBA color;
|
||||
gboolean glyph_align;
|
||||
gboolean hinting;
|
||||
unsigned int mask;
|
||||
|
||||
if (self->opacity < 1.0 &&
|
||||
gsk_text_node_has_color_glyphs (node))
|
||||
@@ -3018,72 +3022,66 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||
glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
font = gsk_text_node_get_font (node);
|
||||
offset = *gsk_text_node_get_offset (node);
|
||||
offset.x += self->offset.x;
|
||||
offset.y += self->offset.y;
|
||||
|
||||
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
offset = point_add (point_from_graphene (gsk_text_node_get_offset (node)),
|
||||
point_from_graphene (&self->offset));
|
||||
s = scale_max (scale_from_graphene (&self->scale));
|
||||
s4 = scale_mul (s, scale_from_float (4));
|
||||
pango_scale = scale_from_float (PANGO_SCALE);
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
ss = scale (scale_x (s4), scale_y (s));
|
||||
mask = 3;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
ss = s4;
|
||||
mask = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss = s;
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
Point origin;
|
||||
graphene_rect_t glyph_bounds, glyph_tex_rect;
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
guint32 descriptor;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
origin = point_add (offset, point_div (point (glyphs[i].geometry.x_offset, glyphs[i].geometry.y_offset), pango_scale));
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
/* Force glyph_origin.y to be device pixel aligned.
|
||||
* The hinter expects that.
|
||||
*/
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3) |
|
||||
(((int) glyph_origin.y & 3) << 2);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
flags = 0;
|
||||
}
|
||||
origin = point_round (point_mul (origin, ss));
|
||||
flags = (((int) point_x (origin) & 3) | (((int) point_y (origin) & 3) << 2)) & mask;
|
||||
origin = point_div (origin, ss);
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
font,
|
||||
glyphs[i].glyph,
|
||||
flags,
|
||||
scale,
|
||||
scale_x (s),
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
|
||||
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x * inv_scale,
|
||||
-glyph_bounds.origin.y * inv_scale,
|
||||
gsk_gpu_image_get_width (image) * inv_scale,
|
||||
gsk_gpu_image_get_height (image) * inv_scale);
|
||||
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x / scale_x (s),
|
||||
-glyph_bounds.origin.y / scale_y (s),
|
||||
gsk_gpu_image_get_width (image) / scale_x (s),
|
||||
gsk_gpu_image_get_height (image) / scale_y (s));
|
||||
glyph_bounds = GRAPHENE_RECT_INIT (0,
|
||||
0,
|
||||
glyph_bounds.size.width * inv_scale,
|
||||
glyph_bounds.size.height * inv_scale);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
glyph_bounds.size.width / scale_x (s),
|
||||
glyph_bounds.size.height / scale_y (s));
|
||||
|
||||
point_to_graphene (point_sub (origin, point_div (point_from_graphene (&glyph_offset), s)),
|
||||
&glyph_origin);
|
||||
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
|
||||
@@ -3136,7 +3134,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
offset.x += self->offset.x;
|
||||
offset.y += self->offset.y;
|
||||
|
||||
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_GLYPHS);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gsk/gskdebugprivate.h"
|
||||
#include "gskvec2private.h"
|
||||
|
||||
static GskGpuOp *
|
||||
gsk_gpu_upload_op_gl_command_with_area (GskGpuOp *op,
|
||||
@@ -466,8 +465,8 @@ gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
|
||||
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
ceil (gsk_vec2_get_x (scale) * viewport->size.width),
|
||||
ceil (gsk_vec2_get_y (scale) * viewport->size.height));
|
||||
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
|
||||
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
|
||||
self->viewport = *viewport;
|
||||
self->func = func;
|
||||
self->user_data = user_data;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
static inline void G_GNUC_PURE
|
||||
gsk_point_interpolate (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2,
|
||||
float t,
|
||||
graphene_point_t *p)
|
||||
{
|
||||
p->x = p1->x * (1 - t) + p2->x * t;
|
||||
p->Y = p1->y * (1 - t) + p2->y * t;
|
||||
}
|
||||
|
||||
static inline float G_GNUC_PURE
|
||||
gsk_point_distance (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2)
|
||||
{
|
||||
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
|
||||
}
|
||||
22
gsk/gsktypesprivate.h
Normal file
22
gsk/gsktypesprivate.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* GSK - The GTK Scene Kit
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* 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 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct _Scale Scale;
|
||||
typedef struct _Point Point;
|
||||
typedef struct _Box Box;
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
#include <math.h>
|
||||
|
||||
static inline float
|
||||
gsk_vec2_get_x (const graphene_vec2_t *v)
|
||||
{
|
||||
return graphene_simd4f_get_x (v->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline float
|
||||
gsk_vec2_get_y (const graphene_vec2_t *v)
|
||||
{
|
||||
return graphene_simd4f_get_y (v->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline graphene_vec2_t *
|
||||
gsk_vec2_init (graphene_vec2_t *v,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
v->__graphene_private_value = graphene_simd4f_init (x, y, 0.f, 0.f);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_vec2_multiply (const graphene_vec2_t *a,
|
||||
const graphene_vec2_t *b,
|
||||
graphene_vec2_t *res)
|
||||
{
|
||||
res->__graphene_private_value = graphene_simd4f_mul (a->__graphene_private_value,
|
||||
b->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
gsk_vec2_equal (const graphene_vec2_t *v1,
|
||||
const graphene_vec2_t *v2)
|
||||
{
|
||||
return graphene_simd4f_cmp_eq (v1->__graphene_private_value, v2->__graphene_private_value);
|
||||
}
|
||||
|
||||
268
gsk/pointprivate.h
Normal file
268
gsk/pointprivate.h
Normal file
@@ -0,0 +1,268 @@
|
||||
#pragma once
|
||||
|
||||
#include "gsktypesprivate.h"
|
||||
#include <graphene.h>
|
||||
#include <math.h>
|
||||
#include <smmintrin.h>
|
||||
|
||||
#include "scaleprivate.h"
|
||||
|
||||
#ifndef USE_SIMD
|
||||
|
||||
struct _Point
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
static inline float
|
||||
point_x (const Point p)
|
||||
{
|
||||
return p.x;
|
||||
}
|
||||
|
||||
static inline float
|
||||
point_y (const Point p)
|
||||
{
|
||||
return p.y;
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point (float x,
|
||||
float y)
|
||||
{
|
||||
return (Point) { .x = x, .y = y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_from_graphene (const graphene_point_t *p)
|
||||
{
|
||||
return point (p->x, p->y);
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_to_graphene (const Point p,
|
||||
graphene_point_t *v)
|
||||
{
|
||||
v->x = p.x;
|
||||
v->y = p.y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_to_float (const Point p,
|
||||
float v[2])
|
||||
{
|
||||
v[0] = p.x;
|
||||
v[1] = p.y;
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_zero (void)
|
||||
{
|
||||
return point (0, 0);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_neg (const Point p)
|
||||
{
|
||||
return (Point) { .x = -p.x, .y = -p.y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_mul (const Point p,
|
||||
const Scale s)
|
||||
{
|
||||
return (Point) { .x = p.x * s.x, .y = p.y * s.y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_div (const Point p,
|
||||
const Scale s)
|
||||
{
|
||||
return (Point) { .x = p.x / s.x, .y = p.y / s.y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_add (const Point p1,
|
||||
const Point p2)
|
||||
{
|
||||
return (Point) { .x = p1.x + p2.x, .y = p1.y + p2.y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_sub (const Point p1,
|
||||
const Point p2)
|
||||
{
|
||||
return (Point) { .x = p1.x - p2.x, .y = p1.y - p2.y };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_floor (const Point p)
|
||||
{
|
||||
return (Point) { .x = floorf (p.x), .y = floorf (p.y) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_ceil (const Point p)
|
||||
{
|
||||
return (Point) { .x = ceilf (p.x), .y = ceilf (p.y) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_round (const Point p)
|
||||
{
|
||||
return (Point) { .x = roundf (p.x), .y = roundf (p.y) };
|
||||
}
|
||||
|
||||
#else /* USE_SIMD */
|
||||
|
||||
#include <smmintrin.h>
|
||||
|
||||
struct _Point
|
||||
{
|
||||
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
|
||||
};
|
||||
|
||||
static inline float
|
||||
point_x (const Point p)
|
||||
{
|
||||
return graphene_simd4f_get_x (p.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
point_y (const Point p)
|
||||
{
|
||||
return graphene_simd4f_get_y (p.v);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point (float x,
|
||||
float y)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_init (x, y, 0.f, 0.f) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_from_graphene (const graphene_point_t *p)
|
||||
{
|
||||
return point (p->x, p->y);
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_to_graphene (const Point p,
|
||||
graphene_point_t *v)
|
||||
{
|
||||
v->x = p.x;
|
||||
v->y = p.y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_to_float (const Point p,
|
||||
float v[2])
|
||||
{
|
||||
graphene_simd4f_dup_2f (p.v, v);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_zero (void)
|
||||
{
|
||||
return point (0, 0);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_neg (const Point p)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_neg (p.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_mul (const Point p,
|
||||
const Scale s)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_mul (p.v, s.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_div (const Point p,
|
||||
const Scale s)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_div (p.v, s.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_add (const Point p1,
|
||||
const Point p2)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_add (p1.v, p2.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_sub (const Point p1,
|
||||
const Point p2)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_sub (p1.v, p2.v) };
|
||||
}
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
|
||||
#ifndef graphene_simd4f_floor
|
||||
# define graphene_simd4f_floor(v) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_floor_ps ((v)); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
#ifndef graphene_simd4f_ceil
|
||||
# define graphene_simd4f_ceil(v) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_ceil_ps ((v)); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
#ifndef graphene_simd4f_round
|
||||
# define graphene_simd4f_round(v) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_round_ps ((v)); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
static inline Point
|
||||
point_floor (const Point p)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_floor (p.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_ceil (const Point p)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_ceil (p.v) };
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_round (const Point p)
|
||||
{
|
||||
return (Point) { .v = graphene_simd4f_round (p.v) };
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline Point
|
||||
point_floor (const Point p)
|
||||
{
|
||||
return point (floorf (point_x (p)), floorf (point_y (p)));
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_ceil (const Point p)
|
||||
{
|
||||
return point (ceilf (point_x (p)), ceilf (point_y (p)));
|
||||
}
|
||||
|
||||
static inline Point
|
||||
point_round (const Point p)
|
||||
{
|
||||
return point (roundf (point_x (p)), roundf (point_y (p)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
197
gsk/scaleprivate.h
Normal file
197
gsk/scaleprivate.h
Normal file
@@ -0,0 +1,197 @@
|
||||
#pragma once
|
||||
|
||||
#include "gsktypesprivate.h"
|
||||
#include <graphene.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef USE_SIMD
|
||||
|
||||
struct _Scale
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
static inline float
|
||||
scale_x (const Scale s)
|
||||
{
|
||||
return s.x;
|
||||
}
|
||||
|
||||
static inline float
|
||||
scale_y (const Scale s)
|
||||
{
|
||||
return s.y;
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale (float x,
|
||||
float y)
|
||||
{
|
||||
return (Scale) { .x = x, .y = y };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_from_float (float s)
|
||||
{
|
||||
return scale (s, s);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_from_graphene (const graphene_vec2_t *v)
|
||||
{
|
||||
return (Scale) { .x = graphene_vec2_get_x (v), .y = graphene_vec2_get_y (v) };
|
||||
}
|
||||
|
||||
static inline void
|
||||
scale_to_graphene (const Scale s,
|
||||
graphene_vec2_t *v)
|
||||
{
|
||||
graphene_vec2_init (v, s.x, s.y);
|
||||
}
|
||||
|
||||
static inline void
|
||||
scale_to_float (const Scale s,
|
||||
float v[2])
|
||||
{
|
||||
v[0] = s.x;
|
||||
v[1] = s.y;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
scale_equal (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (gboolean) (s1.x == s2.x && s1.y == s2.y);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_one (void)
|
||||
{
|
||||
return scale (1, 1);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_inv (const Scale s)
|
||||
{
|
||||
return (Scale) { .x = 1 / s.x, .y = 1 / s.y };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_mul (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (Scale) { .x = s1.x * s2.x, .y = s1.y * s2.y };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_div (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (Scale) { .x = s1.x / s2.x, .y = s1.y / s2.y };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_max (const Scale s)
|
||||
{
|
||||
return (Scale) { .x = MAX (s.x, s.y), .y = MAX (s.x, s.y) };
|
||||
}
|
||||
|
||||
#else /* USE_SIMD */
|
||||
|
||||
struct _Scale
|
||||
{
|
||||
GRAPHENE_ALIGNED_DECL (graphene_simd4f_t v, 16);
|
||||
};
|
||||
|
||||
static inline float
|
||||
scale_x (const Scale s)
|
||||
{
|
||||
return graphene_simd4f_get_x (s.v);
|
||||
}
|
||||
|
||||
static inline float
|
||||
scale_y (const Scale s)
|
||||
{
|
||||
return graphene_simd4f_get_y (s.v);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale (float x,
|
||||
float y)
|
||||
{
|
||||
return (Scale) { .v = graphene_simd4f_init (x, y, 0.f, 0.f) };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_from_float (float s)
|
||||
{
|
||||
return scale (s, s);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_from_graphene (const graphene_vec2_t *v)
|
||||
{
|
||||
return (Scale) { .v = v->__graphene_private_value };
|
||||
}
|
||||
|
||||
static inline void
|
||||
scale_to_graphene (const Scale s,
|
||||
graphene_vec2_t *v)
|
||||
{
|
||||
v->__graphene_private_value = s.v;
|
||||
}
|
||||
|
||||
static inline void
|
||||
scale_to_float (const Scale s,
|
||||
float v[2])
|
||||
{
|
||||
graphene_simd4f_dup_2f (s.v, v);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
scale_equal (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (gboolean) graphene_simd4f_cmp_eq (s1.v, s2.v);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_one (void)
|
||||
{
|
||||
return scale (1, 1);
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_inv (const Scale s)
|
||||
{
|
||||
return (Scale) { .v = graphene_simd4f_reciprocal (s.v) };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_mul (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (Scale) { .v = graphene_simd4f_mul (s1.v, s2.v) };
|
||||
}
|
||||
|
||||
static inline Scale
|
||||
scale_div (const Scale s1,
|
||||
const Scale s2)
|
||||
{
|
||||
return (Scale) { .v = graphene_simd4f_div (s1.v, s2.v) };
|
||||
}
|
||||
|
||||
#ifndef graphene_simd4f_shuffle_yxzw
|
||||
# define graphene_simd4f_shuffle_yxzw(v) \
|
||||
(__extension__ ({ \
|
||||
(graphene_simd4f_t) _mm_shuffle_ps ((v), (v), _MM_SHUFFLE (3, 2, 0, 1)); \
|
||||
}))
|
||||
#endif
|
||||
|
||||
static inline Scale
|
||||
scale_max (const Scale s)
|
||||
{
|
||||
return (Scale) { .v = graphene_simd4f_max (graphene_simd4f_shuffle_yxzw (s.v), s.v) };
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user