/* * Cogl * * An object oriented GL/GLES Abstraction/Utility Layer * * Copyright (C) 2010 Intel Corporation. * * 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 . * * * * Authors: * Neil Roberts */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "cogl-bitmask.h" gboolean _cogl_bitmask_get_from_array (const CoglBitmask *bitmask, unsigned int bit_num) { GArray *array = (GArray *) *bitmask; /* If the index is off the end of the array then assume the bit is not set */ if (bit_num >= sizeof (unsigned int) * 8 * array->len) return FALSE; else return !!(g_array_index (array, unsigned int, bit_num / (sizeof (unsigned int) * 8)) & (1 << (bit_num % (sizeof (unsigned int) * 8)))); } static void _cogl_bitmask_convert_to_array (CoglBitmask *bitmask) { GArray *array; /* Fetch the old values, ignoring the least significant bit */ unsigned int old_values = GPOINTER_TO_UINT (*bitmask) >> 1; array = g_array_new (FALSE, TRUE, sizeof (unsigned int)); /* Copy the old values back in */ g_array_append_val (array, old_values); *bitmask = (struct _CoglBitmaskImaginaryType *) array; } void _cogl_bitmask_set_in_array (CoglBitmask *bitmask, unsigned int bit_num, gboolean value) { GArray *array; unsigned int array_index, new_value_mask; /* If the bitmask is not already an array then we need to allocate one */ if (!_cogl_bitmask_has_array (bitmask)) _cogl_bitmask_convert_to_array (bitmask); array = (GArray *) *bitmask; array_index = bit_num / (sizeof (unsigned int) * 8); /* Grow the array if necessary. This will clear the new data */ if (array_index >= array->len) g_array_set_size (array, array_index + 1); new_value_mask = 1 << (bit_num % (sizeof (unsigned int) * 8)); if (value) g_array_index (array, unsigned int, array_index) |= new_value_mask; else g_array_index (array, unsigned int, array_index) &= ~new_value_mask; } void _cogl_bitmask_set_bits (CoglBitmask *dst, const CoglBitmask *src) { if (_cogl_bitmask_has_array (src)) { GArray *src_array, *dst_array; int i; if (!_cogl_bitmask_has_array (dst)) _cogl_bitmask_convert_to_array (dst); dst_array = (GArray *) *dst; src_array = (GArray *) *src; if (dst_array->len < src_array->len) g_array_set_size (dst_array, src_array->len); for (i = 0; i < src_array->len; i++) g_array_index (dst_array, unsigned int, i) |= g_array_index (src_array, unsigned int, i); } else if (_cogl_bitmask_has_array (dst)) { GArray *dst_array; dst_array = (GArray *) *dst; g_array_index (dst_array, unsigned int, 0) |= (GPOINTER_TO_UINT (*src) >> 1); } else *dst = GUINT_TO_POINTER (GPOINTER_TO_UINT (*dst) | GPOINTER_TO_UINT (*src)); } void _cogl_bitmask_set_range_in_array (CoglBitmask *bitmask, unsigned int n_bits, gboolean value) { GArray *array; unsigned int array_index, bit_index; if (n_bits == 0) return; /* If the bitmask is not already an array then we need to allocate one */ if (!_cogl_bitmask_has_array (bitmask)) _cogl_bitmask_convert_to_array (bitmask); array = (GArray *) *bitmask; /* Get the array index of the top most value that will be touched */ array_index = (n_bits - 1) / (sizeof (unsigned int) * 8); /* Get the bit index of the top most value */ bit_index = (n_bits - 1) % (sizeof (unsigned int) * 8); /* Grow the array if necessary. This will clear the new data */ if (array_index >= array->len) g_array_set_size (array, array_index + 1); if (value) { /* Set the bits that are touching this index */ g_array_index (array, unsigned int, array_index) |= ~(unsigned int) 0 >> (sizeof (unsigned int) * 8 - 1 - bit_index); /* Set all of the bits in any lesser indices */ memset (array->data, 0xff, sizeof (unsigned int) * array_index); } else { /* Clear the bits that are touching this index */ g_array_index (array, unsigned int, array_index) &= ~(unsigned int) 1 << bit_index; /* Clear all of the bits in any lesser indices */ memset (array->data, 0x00, sizeof (unsigned int) * array_index); } } void _cogl_bitmask_clear_bits (CoglBitmask *dst, const CoglBitmask *src) { if (_cogl_bitmask_has_array (src)) { GArray *src_array, *dst_array; int i; if (!_cogl_bitmask_has_array (dst)) _cogl_bitmask_convert_to_array (dst); dst_array = (GArray *) *dst; src_array = (GArray *) *src; if (dst_array->len < src_array->len) g_array_set_size (dst_array, src_array->len); for (i = 0; i < src_array->len; i++) g_array_index (dst_array, unsigned int, i) &= ~g_array_index (src_array, unsigned int, i); } else if (_cogl_bitmask_has_array (dst)) { GArray *dst_array; dst_array = (GArray *) *dst; g_array_index (dst_array, unsigned int, 0) &= ~(GPOINTER_TO_UINT (*src) >> 1); } else *dst = GUINT_TO_POINTER ((GPOINTER_TO_UINT (*dst) & ~GPOINTER_TO_UINT (*src)) | 1); } void _cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask) { GArray *array = (GArray *) *bitmask; memset (array->data, 0, sizeof (unsigned int) * array->len); } void _cogl_bitmask_foreach (const CoglBitmask *bitmask, CoglBitmaskForeachFunc func, gpointer user_data) { if (_cogl_bitmask_has_array (bitmask)) { GArray *array = (GArray *) *bitmask; int array_index; for (array_index = 0; array_index < array->len; array_index++) { unsigned int mask = g_array_index (array, unsigned int, array_index); int bit = 0; while (mask) { if (mask & 1) func (array_index * sizeof (unsigned int) * 8 + bit, user_data); bit++; mask >>= 1; } } } else { unsigned int mask = GPOINTER_TO_UINT (*bitmask) >> 1; int bit = 0; while (mask) { if (mask & 1) func (bit, user_data); bit++; mask >>= 1; } } }