
In the next commit, we will add a DriverGL that those two drivers would inherit from to share the common infrastructure. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4132>
469 lines
12 KiB
C
469 lines
12 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 "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "cogl/cogl-boxed-value.h"
|
|
#include "cogl/cogl-context-private.h"
|
|
|
|
static void
|
|
_cogl_boxed_value_append_type_to_string (GString *buf,
|
|
const CoglBoxedValue *bv)
|
|
{
|
|
switch (bv->type)
|
|
{
|
|
case COGL_BOXED_INT:
|
|
if (bv->size == 1)
|
|
g_string_append (buf, "int");
|
|
else
|
|
g_string_append_printf (buf, "ivec%i", bv->size);
|
|
return;
|
|
case COGL_BOXED_FLOAT:
|
|
if (bv->size == 1)
|
|
g_string_append (buf, "float");
|
|
else
|
|
g_string_append_printf (buf, "vec%i", bv->size);
|
|
return;
|
|
case COGL_BOXED_MATRIX:
|
|
g_string_append_printf (buf, "mat%i", bv->size);
|
|
return;
|
|
case COGL_BOXED_NONE:
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_append_value_to_string (GString *buf,
|
|
const CoglBoxedValue *bv,
|
|
int count)
|
|
{
|
|
int i, j;
|
|
int offset;
|
|
|
|
if (bv->size > 1)
|
|
{
|
|
_cogl_boxed_value_append_type_to_string (buf, bv);
|
|
g_string_append (buf, "(");
|
|
}
|
|
|
|
switch (bv->type)
|
|
{
|
|
case COGL_BOXED_INT:
|
|
for (i = 0; i < bv->size; i++)
|
|
{
|
|
if (bv->count > 1)
|
|
g_string_append_printf (buf, "%i, ", bv->v.int_array[(count * bv->size) + i]);
|
|
else
|
|
g_string_append_printf (buf, "%i, ", bv->v.int_value[i]);
|
|
}
|
|
break;
|
|
case COGL_BOXED_FLOAT:
|
|
for (i = 0; i < bv->size; i++)
|
|
{
|
|
if (bv->count > 1)
|
|
g_string_append_printf (buf, "%f, ", bv->v.float_array[(count * bv->size) + i]);
|
|
else
|
|
g_string_append_printf (buf, "%f, ", bv->v.float_value[i]);
|
|
}
|
|
break;
|
|
case COGL_BOXED_MATRIX:
|
|
offset = count * bv->size * bv->size;
|
|
|
|
for (i = 0; i < bv->size; i++)
|
|
{
|
|
g_string_append (buf, "(");
|
|
|
|
for (j = 0; j < bv->size; j++)
|
|
{
|
|
if (bv->count > 1)
|
|
g_string_append_printf (buf, "%f, ", bv->v.float_array[
|
|
offset + (i * bv->size) + j]);
|
|
else
|
|
g_string_append_printf (buf, "%f, ", bv->v.matrix[(i * bv->size) + j]);
|
|
}
|
|
|
|
g_string_erase (buf, buf->len - 2, 2);
|
|
g_string_append (buf, "), ");
|
|
}
|
|
break;
|
|
case COGL_BOXED_NONE:
|
|
return;
|
|
}
|
|
|
|
g_string_erase (buf, buf->len - 2, 2);
|
|
|
|
if (bv->size > 1)
|
|
g_string_append (buf, ")");
|
|
}
|
|
|
|
char *
|
|
_cogl_boxed_value_to_string (const CoglBoxedValue *bv,
|
|
const char *name)
|
|
{
|
|
GString *buf;
|
|
int i;
|
|
|
|
buf = g_string_new (NULL);
|
|
for (i = 0; i < bv->count; i++)
|
|
{
|
|
_cogl_boxed_value_append_type_to_string (buf, bv);
|
|
|
|
g_string_append_printf (buf, " %s", name);
|
|
|
|
if (bv->count > 1)
|
|
g_string_append_printf (buf, "[%i] = ", i);
|
|
else
|
|
g_string_append (buf, " = ");
|
|
|
|
_cogl_boxed_value_append_value_to_string (buf, bv, i);
|
|
}
|
|
|
|
return g_string_free_and_steal (buf);
|
|
}
|
|
|
|
gboolean
|
|
_cogl_boxed_value_equal (const CoglBoxedValue *bva,
|
|
const CoglBoxedValue *bvb)
|
|
{
|
|
const void *pa, *pb;
|
|
|
|
if (bva == NULL || bvb == NULL)
|
|
return bva == bvb;
|
|
|
|
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.float_array;
|
|
pb = bvb->v.float_array;
|
|
}
|
|
|
|
return !memcmp (pa, pb,
|
|
sizeof (float) * bva->size * bva->size * bva->count);
|
|
}
|
|
|
|
g_warn_if_reached ();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_array_alloc (CoglBoxedValue *bv,
|
|
size_t value_size,
|
|
int count,
|
|
CoglBoxedType type)
|
|
{
|
|
if (count > 1)
|
|
{
|
|
switch (type)
|
|
{
|
|
case COGL_BOXED_INT:
|
|
bv->v.int_array = g_malloc (count * value_size);
|
|
return;
|
|
|
|
case COGL_BOXED_FLOAT:
|
|
case COGL_BOXED_MATRIX:
|
|
bv->v.float_array = g_malloc (count * value_size);
|
|
return;
|
|
|
|
case COGL_BOXED_NONE:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_copy_transposed_value (CoglBoxedValue *bv,
|
|
int size,
|
|
int count,
|
|
const float *src)
|
|
{
|
|
int value_num;
|
|
int y, x;
|
|
float *dst;
|
|
const float *src_start = src;
|
|
|
|
if (count > 1)
|
|
dst = bv->v.float_array;
|
|
else
|
|
dst = bv->v.matrix;
|
|
|
|
/* 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 (value_num = 0; value_num < count; value_num++)
|
|
{
|
|
src = src_start + value_num * size * size;
|
|
for (y = 0; y < size; y++)
|
|
for (x = 0; x < size; x++)
|
|
*(dst++) = src[y + x * size];
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_boxed_value_copy_value (CoglBoxedValue *bv,
|
|
size_t value_size,
|
|
int count,
|
|
const void *value,
|
|
CoglBoxedType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case COGL_BOXED_INT:
|
|
if (count > 1)
|
|
memcpy (bv->v.int_array, value, count * value_size);
|
|
else
|
|
memcpy (bv->v.int_value, value, value_size);
|
|
return;
|
|
|
|
case COGL_BOXED_FLOAT:
|
|
if (count > 1)
|
|
memcpy (bv->v.float_array, value, count * value_size);
|
|
else
|
|
memcpy (bv->v.float_value, value, value_size);
|
|
return;
|
|
|
|
case COGL_BOXED_MATRIX:
|
|
if (count > 1)
|
|
memcpy (bv->v.float_array, value, count * value_size);
|
|
else
|
|
memcpy (bv->v.matrix, value, value_size);
|
|
return;
|
|
|
|
case COGL_BOXED_NONE:
|
|
return;
|
|
}
|
|
}
|
|
|
|
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 (bv->count != count ||
|
|
bv->size != size ||
|
|
bv->type != type)
|
|
{
|
|
_cogl_boxed_value_destroy (bv);
|
|
_cogl_boxed_value_array_alloc (bv, value_size, count, type);
|
|
}
|
|
|
|
if (transpose)
|
|
_cogl_boxed_value_copy_transposed_value (bv, size, count, value);
|
|
else
|
|
_cogl_boxed_value_copy_value (bv, value_size, count, value, type);
|
|
|
|
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)
|
|
{
|
|
switch (bv->type)
|
|
{
|
|
case COGL_BOXED_INT:
|
|
g_free (bv->v.int_array);
|
|
return;
|
|
|
|
case COGL_BOXED_FLOAT:
|
|
case COGL_BOXED_MATRIX:
|
|
g_free (bv->v.float_array);
|
|
return;
|
|
|
|
case COGL_BOXED_NONE:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_cogl_boxed_value_set_uniform (CoglContext *ctx,
|
|
GLint location,
|
|
const CoglBoxedValue *value)
|
|
{
|
|
CoglDriverClass *driver_klass = COGL_DRIVER_GET_CLASS (ctx->driver);
|
|
|
|
driver_klass->set_uniform (ctx->driver, ctx, location, value);
|
|
}
|