30e1c51b33
Using g_memdup() is dangerous due to the type of the size argument. See https://gitlab.gnome.org/GNOME/glib/-/issues/2319 and https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1926 for details. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1708>
290 lines
7.8 KiB
C
290 lines
7.8 KiB
C
/*
|
|
* Cogl
|
|
*
|
|
* A Low Level GPU Graphics and Utilities API
|
|
*
|
|
* Copyright (C) 2011 Intel Corporation.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "cogl-config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "cogl-boxed-value.h"
|
|
#include "cogl-context-private.h"
|
|
|
|
gboolean
|
|
_cogl_boxed_value_equal (const CoglBoxedValue *bva,
|
|
const CoglBoxedValue *bvb)
|
|
{
|
|
const void *pa, *pb;
|
|
|
|
if (bva->type != bvb->type)
|
|
return FALSE;
|
|
|
|
switch (bva->type)
|
|
{
|
|
case COGL_BOXED_NONE:
|
|
return TRUE;
|
|
|
|
case COGL_BOXED_INT:
|
|
if (bva->size != bvb->size || bva->count != bvb->count)
|
|
return FALSE;
|
|
|
|
if (bva->count == 1)
|
|
{
|
|
pa = bva->v.int_value;
|
|
pb = bvb->v.int_value;
|
|
}
|
|
else
|
|
{
|
|
pa = bva->v.int_array;
|
|
pb = bvb->v.int_array;
|
|
}
|
|
|
|
return !memcmp (pa, pb, sizeof (int) * bva->size * bva->count);
|
|
|
|
case COGL_BOXED_FLOAT:
|
|
if (bva->size != bvb->size || bva->count != bvb->count)
|
|
return FALSE;
|
|
|
|
if (bva->count == 1)
|
|
{
|
|
pa = bva->v.float_value;
|
|
pb = bvb->v.float_value;
|
|
}
|
|
else
|
|
{
|
|
pa = bva->v.float_array;
|
|
pb = bvb->v.float_array;
|
|
}
|
|
|
|
return !memcmp (pa, pb, sizeof (float) * bva->size * bva->count);
|
|
|
|
case COGL_BOXED_MATRIX:
|
|
if (bva->size != bvb->size ||
|
|
bva->count != bvb->count)
|
|
return FALSE;
|
|
|
|
if (bva->count == 1)
|
|
{
|
|
pa = bva->v.matrix;
|
|
pb = bvb->v.matrix;
|
|
}
|
|
else
|
|
{
|
|
pa = bva->v.array;
|
|
pb = bvb->v.array;
|
|
}
|
|
|
|
return !memcmp (pa, pb,
|
|
sizeof (float) * bva->size * bva->size * bva->count);
|
|
}
|
|
|
|
g_warn_if_reached ();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_tranpose (float *dst,
|
|
int size,
|
|
const float *src)
|
|
{
|
|
int y, x;
|
|
|
|
/* If the value is transposed we'll just transpose it now as it
|
|
* is copied into the boxed value instead of passing TRUE to
|
|
* glUniformMatrix because that is not supported on GLES and it
|
|
* doesn't seem like the GL driver would be able to do anything
|
|
* much smarter than this anyway */
|
|
|
|
for (y = 0; y < size; y++)
|
|
for (x = 0; x < size; x++)
|
|
*(dst++) = src[y + x * size];
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_set_x (CoglBoxedValue *bv,
|
|
int size,
|
|
int count,
|
|
CoglBoxedType type,
|
|
size_t value_size,
|
|
const void *value,
|
|
gboolean transpose)
|
|
{
|
|
if (count == 1)
|
|
{
|
|
if (bv->count > 1)
|
|
g_free (bv->v.array);
|
|
|
|
if (transpose)
|
|
_cogl_boxed_value_tranpose (bv->v.float_value,
|
|
size,
|
|
value);
|
|
else
|
|
memcpy (bv->v.float_value, value, value_size);
|
|
}
|
|
else
|
|
{
|
|
if (bv->count > 1)
|
|
{
|
|
if (bv->count != count ||
|
|
bv->size != size ||
|
|
bv->type != type)
|
|
{
|
|
g_free (bv->v.array);
|
|
bv->v.array = g_malloc (count * value_size);
|
|
}
|
|
}
|
|
else
|
|
bv->v.array = g_malloc (count * value_size);
|
|
|
|
if (transpose)
|
|
{
|
|
int value_num;
|
|
|
|
for (value_num = 0; value_num < count; value_num++)
|
|
_cogl_boxed_value_tranpose (bv->v.float_array +
|
|
value_num * size * size,
|
|
size,
|
|
(const float *) value +
|
|
value_num * size * size);
|
|
}
|
|
else
|
|
memcpy (bv->v.array, value, count * value_size);
|
|
}
|
|
|
|
bv->type = type;
|
|
bv->size = size;
|
|
bv->count = count;
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_1f (CoglBoxedValue *bv,
|
|
float value)
|
|
{
|
|
_cogl_boxed_value_set_x (bv,
|
|
1, 1, COGL_BOXED_FLOAT,
|
|
sizeof (float), &value, FALSE);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_1i (CoglBoxedValue *bv,
|
|
int value)
|
|
{
|
|
_cogl_boxed_value_set_x (bv,
|
|
1, 1, COGL_BOXED_INT,
|
|
sizeof (int), &value, FALSE);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_float (CoglBoxedValue *bv,
|
|
int n_components,
|
|
int count,
|
|
const float *value)
|
|
{
|
|
_cogl_boxed_value_set_x (bv,
|
|
n_components, count,
|
|
COGL_BOXED_FLOAT,
|
|
sizeof (float) * n_components, value, FALSE);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_int (CoglBoxedValue *bv,
|
|
int n_components,
|
|
int count,
|
|
const int *value)
|
|
{
|
|
_cogl_boxed_value_set_x (bv,
|
|
n_components, count,
|
|
COGL_BOXED_INT,
|
|
sizeof (int) * n_components, value, FALSE);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_matrix (CoglBoxedValue *bv,
|
|
int dimensions,
|
|
int count,
|
|
gboolean transpose,
|
|
const float *value)
|
|
{
|
|
_cogl_boxed_value_set_x (bv,
|
|
dimensions, count,
|
|
COGL_BOXED_MATRIX,
|
|
sizeof (float) * dimensions * dimensions,
|
|
value,
|
|
transpose);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_copy (CoglBoxedValue *dst,
|
|
const CoglBoxedValue *src)
|
|
{
|
|
*dst = *src;
|
|
|
|
if (src->count > 1)
|
|
{
|
|
switch (src->type)
|
|
{
|
|
case COGL_BOXED_NONE:
|
|
break;
|
|
|
|
case COGL_BOXED_INT:
|
|
dst->v.int_array = g_memdup2 (src->v.int_array,
|
|
src->size * src->count * sizeof (int));
|
|
break;
|
|
|
|
case COGL_BOXED_FLOAT:
|
|
dst->v.float_array = g_memdup2 (src->v.float_array,
|
|
src->size *
|
|
src->count *
|
|
sizeof (float));
|
|
break;
|
|
|
|
case COGL_BOXED_MATRIX:
|
|
dst->v.float_array = g_memdup2 (src->v.float_array,
|
|
src->size * src->size *
|
|
src->count * sizeof (float));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_destroy (CoglBoxedValue *bv)
|
|
{
|
|
if (bv->count > 1)
|
|
g_free (bv->v.array);
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_uniform (CoglContext *ctx,
|
|
GLint location,
|
|
const CoglBoxedValue *value)
|
|
{
|
|
ctx->driver_vtable->set_uniform (ctx, location, value);
|
|
}
|