diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/util/bitmap.c | 4 | ||||
-rw-r--r-- | src/lib/util/palette.c | 872 | ||||
-rw-r--r-- | src/lib/util/palette.h | 375 |
3 files changed, 495 insertions, 756 deletions
diff --git a/src/lib/util/bitmap.c b/src/lib/util/bitmap.c index 6f826ac6767..4d1f8502f50 100644 --- a/src/lib/util/bitmap.c +++ b/src/lib/util/bitmap.c @@ -271,14 +271,14 @@ void bitmap_t::set_palette(palette_t *palette) // first dereference any existing palette if (m_palette != NULL) { - palette_deref(m_palette); + m_palette->deref(); m_palette = NULL; } // then reference any new palette if (palette != NULL) { - palette_ref(palette); + palette->ref(); m_palette = palette; } } diff --git a/src/lib/util/palette.c b/src/lib/util/palette.c index a72b8c64314..719a832c088 100644 --- a/src/lib/util/palette.c +++ b/src/lib/util/palette.c @@ -14,669 +14,435 @@ -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* object to track dirty states */ -struct dirty_state -{ - UINT32 * dirty; /* bitmap of dirty entries */ - UINT32 mindirty; /* minimum dirty entry */ - UINT32 maxdirty; /* minimum dirty entry */ -}; +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** +//------------------------------------------------- +// adjust_palette_entry - adjust a palette +// entry for brightness +//------------------------------------------------- -/* a single palette client */ -struct palette_client +inline rgb_t palette_t::adjust_palette_entry(rgb_t entry, float brightness, float contrast, const UINT8 *gamma_map) { - palette_client *next; /* pointer to next client */ - palette_t * palette; /* reference to the palette */ - dirty_state live; /* live dirty state */ - dirty_state previous; /* previous dirty state */ -}; - - -/* a palette object */ -struct palette_t -{ - UINT32 refcount; /* reference count on the palette */ - UINT32 numcolors; /* number of colors in the palette */ - UINT32 numgroups; /* number of groups in the palette */ - - float brightness; /* overall brightness value */ - float contrast; /* overall contrast value */ - float gamma; /* overall gamma value */ - UINT8 gamma_map[256]; /* gamma map */ - - rgb_t * entry_color; /* array of raw colors */ - float * entry_contrast; /* contrast value for each entry */ - rgb_t * adjusted_color; /* array of adjusted colors */ - rgb_t * adjusted_rgb15; /* array of adjusted colors as RGB15 */ - - float * group_bright; /* brightness value for each group */ - float * group_contrast; /* contrast value for each group */ - - palette_client *client_list; /* list of clients for this palette */ -}; - - - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -static void internal_palette_free(palette_t *palette); -static void update_adjusted_color(palette_t *palette, UINT32 group, UINT32 index); - - - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - adjust_palette_entry - adjust a palette - entry for brightness --------------------------------------------------*/ - -INLINE rgb_t adjust_palette_entry(rgb_t entry, float brightness, float contrast, const UINT8 *gamma_map) -{ - int r = rgb_clamp((float)gamma_map[RGB_RED(entry)] * contrast + brightness); - int g = rgb_clamp((float)gamma_map[RGB_GREEN(entry)] * contrast + brightness); - int b = rgb_clamp((float)gamma_map[RGB_BLUE(entry)] * contrast + brightness); + int r = rgb_clamp(float(gamma_map[RGB_RED(entry)]) * contrast + brightness); + int g = rgb_clamp(float(gamma_map[RGB_GREEN(entry)]) * contrast + brightness); + int b = rgb_clamp(float(gamma_map[RGB_BLUE(entry)]) * contrast + brightness); int a = RGB_ALPHA(entry); return MAKE_ARGB(a,r,g,b); } -/*************************************************************************** - PALETTE ALLOCATION -***************************************************************************/ +//************************************************************************** +// CLIENT DIRTY LIST MANAGEMENT +//************************************************************************** -/*------------------------------------------------- - palette_alloc - allocate a new palette object - and take a single reference on it --------------------------------------------------*/ +//------------------------------------------------- +// dirty_state - constructor +//------------------------------------------------- -palette_t *palette_alloc(UINT32 numcolors, UINT32 numgroups) +palette_client::dirty_state::dirty_state() + : m_mindirty(0), + m_maxdirty(0) { - palette_t *palette; - UINT32 index; - - /* allocate memory */ - palette = (palette_t *)malloc(sizeof(*palette)); - if (palette == NULL) - goto error; - memset(palette, 0, sizeof(*palette)); - - /* initialize overall controls */ - palette->brightness = 0.0f; - palette->contrast = 1.0f; - palette->gamma = 1.0f; - for (index = 0; index < 256; index++) - palette->gamma_map[index] = index; - - /* allocate an array of palette entries and individual contrasts for each */ - palette->entry_color = (rgb_t *)malloc(sizeof(*palette->entry_color) * numcolors); - palette->entry_contrast = (float *)malloc(sizeof(*palette->entry_contrast) * numcolors); - if (palette->entry_color == NULL || palette->entry_contrast == NULL) - goto error; - - /* initialize the entries */ - for (index = 0; index < numcolors; index++) - { - palette->entry_color[index] = RGB_BLACK; - palette->entry_contrast[index] = 1.0f; - } - - /* allocate an array of brightness and contrast for each group */ - palette->group_bright = (float *)malloc(sizeof(*palette->group_bright) * numgroups); - palette->group_contrast = (float *)malloc(sizeof(*palette->group_contrast) * numgroups); - if (palette->group_bright == NULL || palette->group_contrast == NULL) - goto error; - - /* initialize the entries */ - for (index = 0; index < numgroups; index++) - { - palette->group_bright[index] = 0.0f; - palette->group_contrast[index] = 1.0f; - } - - /* allocate arrays for the adjusted colors */ - palette->adjusted_color = (rgb_t *)malloc(sizeof(*palette->adjusted_color) * (numcolors * numgroups + 2)); - palette->adjusted_rgb15 = (rgb_t *)malloc(sizeof(*palette->adjusted_rgb15) * (numcolors * numgroups + 2)); - if (palette->adjusted_color == NULL || palette->adjusted_rgb15 == NULL) - goto error; - - /* initialize the arrays */ - for (index = 0; index < numcolors * numgroups; index++) - { - palette->adjusted_color[index] = RGB_BLACK; - palette->adjusted_rgb15[index] = rgb_to_rgb15(RGB_BLACK); - } - - /* add black and white as the last two colors */ - palette->adjusted_color[index] = RGB_BLACK; - palette->adjusted_rgb15[index++] = rgb_to_rgb15(RGB_BLACK); - palette->adjusted_color[index] = RGB_WHITE; - palette->adjusted_rgb15[index++] = rgb_to_rgb15(RGB_WHITE); - - /* initialize the remainder of the structure */ - palette->refcount = 1; - palette->numcolors = numcolors; - palette->numgroups = numgroups; - return palette; - -error: - if (palette != NULL) - internal_palette_free(palette); - - return NULL; } -/*------------------------------------------------- - palette_ref - reference a palette object, - incrementing its reference count --------------------------------------------------*/ +//------------------------------------------------- +// dirty_list - return the current list and +// min/max values +//------------------------------------------------- -void palette_ref(palette_t *palette) +const UINT32 *palette_client::dirty_state::dirty_list(UINT32 &mindirty, UINT32 &maxdirty) { - palette->refcount++; -} + // fill in the mindirty/maxdirty + mindirty = m_mindirty; + maxdirty = m_maxdirty; - -/*------------------------------------------------- - palette_deref - dereference a palette object; - if the reference count goes to 0, it is freed --------------------------------------------------*/ - -void palette_deref(palette_t *palette) -{ - /* if the reference count goes to 0, free */ - if (--palette->refcount == 0) - internal_palette_free(palette); + // if nothing to report, report nothing + return (m_mindirty > m_maxdirty) ? NULL : &m_dirty[0]; } +//------------------------------------------------- +// resize - resize the dirty array and mark all +// dirty +//------------------------------------------------- -/*************************************************************************** - PALETTE INFORMATION -***************************************************************************/ - -/*------------------------------------------------- - palette_get_num_colors - return the number of - colors allocated in the palette --------------------------------------------------*/ - -int palette_get_num_colors(palette_t *palette) +void palette_client::dirty_state::resize(UINT32 colors) { - return palette->numcolors; -} - + // resize to the correct number of dwords + UINT32 dirty_dwords = (colors + 31) / 32; + m_dirty.resize(dirty_dwords); -/*------------------------------------------------- - palette_get_num_groups - return the number of - groups managed by the palette --------------------------------------------------*/ + // mark all entries dirty + memset(&m_dirty[0], 0xff, dirty_dwords * sizeof(UINT32)); + m_dirty[dirty_dwords - 1] &= (1 << (colors % 32)) - 1; -int palette_get_num_groups(palette_t *palette) -{ - return palette->numgroups; + // set min/max + m_mindirty = 0; + m_maxdirty = colors - 1; } -/*------------------------------------------------- - palette_get_max_index - return the maximum - allowed index (i.e., length of arrays returned - by palette_entry_list*) --------------------------------------------------*/ +//------------------------------------------------- +// mark_dirty - mark a single entry dirty +//------------------------------------------------- -int palette_get_max_index(palette_t *palette) +void palette_client::dirty_state::mark_dirty(UINT32 index) { - return palette->numcolors * palette->numgroups + 2; + m_dirty[index / 32] |= 1 << (index % 32); + m_mindirty = MIN(m_mindirty, index); + m_maxdirty = MAX(m_maxdirty, index); } -/*------------------------------------------------- - palette_get_black_entry - return the index of - the black entry --------------------------------------------------*/ +//------------------------------------------------- +// reset - clear the dirty array to mark all +// entries as clean +//------------------------------------------------- -UINT32 palette_get_black_entry(palette_t *palette) +void palette_client::dirty_state::reset() { - return palette->numcolors * palette->numgroups + 0; + // erase relevant entries in the new live one + memset(&m_dirty[m_mindirty / 32], 0, ((m_maxdirty / 32) + 1 - (m_mindirty / 32)) * sizeof(UINT32)); + m_mindirty = m_dirty.count() * 32 - 1; + m_maxdirty = 0; } -/*------------------------------------------------- - palette_get_white_entry - return the index of - the white entry --------------------------------------------------*/ - -UINT32 palette_get_white_entry(palette_t *palette) -{ - return palette->numcolors * palette->numgroups + 1; -} +//************************************************************************** +// PALETTE CLIENT +//************************************************************************** +//------------------------------------------------- +// palette_client - constructor +//------------------------------------------------- -/*************************************************************************** - PALETTE CLIENTS -***************************************************************************/ +palette_client::palette_client(palette_t &palette) + : m_palette(palette), + m_next(NULL), + m_live(&m_dirty[0]), + m_previous(&m_dirty[1]) +{ + // add a reference to the palette + palette.ref(); -/*------------------------------------------------- - palette_client_alloc - add a new client to a - palette --------------------------------------------------*/ + // resize the dirty lists + UINT32 total_colors = palette.num_colors() * palette.num_groups(); + m_dirty[0].resize(total_colors); + m_dirty[1].resize(total_colors); -palette_client *palette_client_alloc(palette_t *palette) -{ - UINT32 total_colors = palette->numcolors * palette->numgroups; - UINT32 dirty_dwords = (total_colors + 31) / 32; - palette_client *client; - - /* allocate memory for the client */ - client = (palette_client *)malloc(sizeof(*client)); - if (client == NULL) - goto error; - memset(client, 0, sizeof(*client)); - - /* allocate dirty lists */ - client->live.dirty = (UINT32 *)malloc(dirty_dwords * sizeof(UINT32)); - client->previous.dirty = (UINT32 *)malloc(dirty_dwords * sizeof(UINT32)); - if (client->live.dirty == NULL || client->previous.dirty == NULL) - goto error; - - /* mark everything dirty to start with */ - memset(client->live.dirty, 0xff, dirty_dwords * sizeof(UINT32)); - memset(client->previous.dirty, 0xff, dirty_dwords * sizeof(UINT32)); - client->live.dirty[dirty_dwords - 1] &= (1 << (total_colors % 32)) - 1; - client->previous.dirty[dirty_dwords - 1] &= (1 << (total_colors % 32)) - 1; - - /* initialize the rest of the structure and add a reference to a palette */ - client->palette = palette; - palette_ref(palette); - client->live.mindirty = 0; - client->live.maxdirty = total_colors - 1; - - /* now add us to the list of clients */ - client->next = palette->client_list; - palette->client_list = client; - return client; - -error: - if (client != NULL) - { - if (client->live.dirty != NULL) - free(client->live.dirty); - if (client->previous.dirty != NULL) - free(client->previous.dirty); - free(client); - } - return NULL; + // now add us to the list of clients + m_next = palette.m_client_list; + palette.m_client_list = this; } -/*------------------------------------------------- - palette_client_free - remove a client from a - palette --------------------------------------------------*/ +//------------------------------------------------- +// ~palette_client - destructor +//------------------------------------------------- -void palette_client_free(palette_client *client) +palette_client::~palette_client() { - palette_client **curptr; - - /* first locate and remove ourself from the palette's list */ - for (curptr = &client->palette->client_list; *curptr != NULL; curptr = &(*curptr)->next) - if (*curptr == client) + // first locate and remove ourself from our palette's list + for (palette_client **curptr = &m_palette.m_client_list; *curptr != NULL; curptr = &(*curptr)->m_next) + if (*curptr == this) { - *curptr = client->next; + *curptr = m_next; break; } - /* now deref the palette */ - palette_deref(client->palette); - - /* free our data */ - if (client->live.dirty != NULL) - free(client->live.dirty); - if (client->previous.dirty != NULL) - free(client->previous.dirty); - free(client); -} - - -/*------------------------------------------------- - palette_client_get_palette - return a pointer - to the palette for this client --------------------------------------------------*/ - -palette_t *palette_client_get_palette(palette_client *client) -{ - return client->palette; + // now deref the palette + m_palette.deref(); } -/*------------------------------------------------- - palette_client_get_dirty_list - atomically get - the current dirty list for a client --------------------------------------------------*/ +//------------------------------------------------- +// dirty_list - atomically get the current dirty +// list for a client +//------------------------------------------------- -const UINT32 *palette_client_get_dirty_list(palette_client *client, UINT32 *mindirty, UINT32 *maxdirty) +const UINT32 *palette_client::dirty_list(UINT32 &mindirty, UINT32 &maxdirty) { - dirty_state temp; - - /* fill in the mindirty/maxdirty */ - if (mindirty != NULL) - *mindirty = client->live.mindirty; - if (maxdirty != NULL) - *maxdirty = client->live.maxdirty; - - /* if nothing to report, report nothing and don't swap */ - if (client->live.mindirty > client->live.maxdirty) + // if nothing to report, report nothing and don't swap + const UINT32 *result = m_live->dirty_list(mindirty, maxdirty); + if (result == NULL) return NULL; - /* swap the live and previous lists */ - temp = client->live; - client->live = client->previous; - client->previous = temp; + // swap the live and previous lists + dirty_state *temp = m_live; + m_live = m_previous; + m_previous = temp; - /* erase relevant entries in the new live one */ - if (client->live.mindirty <= client->live.maxdirty) - memset(client->live.dirty, client->live.mindirty / 8, (client->live.maxdirty / 8) + 1 - (client->live.mindirty / 8)); - client->live.mindirty = client->palette->numcolors * client->palette->numgroups; - client->live.maxdirty = 0; - - /* return a pointer to the previous table */ - return client->previous.dirty; + // reset new live one and return the pointer to the previous + m_live->reset(); + return result; } -/*************************************************************************** - PALETTE COLOR MANAGEMENT -***************************************************************************/ - -/*------------------------------------------------- - palette_entry_set_color - set the raw RGB - color for a given palette index --------------------------------------------------*/ - -void palette_entry_set_color(palette_t *palette, UINT32 index, rgb_t rgb) -{ - int groupnum; - - /* if out of range, or unchanged, ignore */ - if (index >= palette->numcolors || palette->entry_color[index] == rgb) - return; - - /* set the color */ - palette->entry_color[index] = rgb; - - /* update across all groups */ - for (groupnum = 0; groupnum < palette->numgroups; groupnum++) - update_adjusted_color(palette, groupnum, index); -} - - -/*------------------------------------------------- - palette_entry_get_color - return the raw RGB - color for a given palette index --------------------------------------------------*/ - -rgb_t palette_entry_get_color(palette_t *palette, UINT32 index) -{ - return (index < palette->numcolors) ? palette->entry_color[index] : RGB_BLACK; -} - - -/*------------------------------------------------- - palette_entry_get_adjusted_color - return the - adjusted RGB color (after all adjustments) for - a given palette index --------------------------------------------------*/ - -rgb_t palette_entry_get_adjusted_color(palette_t *palette, UINT32 index) -{ - return (index < palette->numcolors * palette->numgroups) ? palette->adjusted_color[index] : RGB_BLACK; -} +//************************************************************************** +// PALETTE_T +//************************************************************************** + +//------------------------------------------------- +// palette_t - constructor +//------------------------------------------------- + +palette_t::palette_t(UINT32 numcolors, UINT32 numgroups) + : m_refcount(1), + m_numcolors(numcolors), + m_numgroups(numgroups), + m_brightness(0.0f), + m_contrast(1.0f), + m_gamma(1.0f), + m_entry_color(numcolors), + m_entry_contrast(numcolors), + m_adjusted_color(numcolors * numgroups + 2), + m_adjusted_rgb15(numcolors * numgroups + 2), + m_group_bright(numgroups), + m_group_contrast(numgroups), + m_client_list(NULL) +{ + // initialize gamma map + for (UINT32 index = 0; index < 256; index++) + m_gamma_map[index] = index; + + // initialize the per-entry data + for (UINT32 index = 0; index < numcolors; index++) + { + m_entry_color[index] = RGB_BLACK; + m_entry_contrast[index] = 1.0f; + } + // initialize the per-group data + for (UINT32 index = 0; index < numgroups; index++) + { + m_group_bright[index] = 0.0f; + m_group_contrast[index] = 1.0f; + } -/*------------------------------------------------- - palette_entry_list_raw - return the entire - palette as an array of raw RGB values --------------------------------------------------*/ + // initialize the expanded data + for (UINT32 index = 0; index < numcolors * numgroups; index++) + { + m_adjusted_color[index] = RGB_BLACK; + m_adjusted_rgb15[index] = rgb_to_rgb15(RGB_BLACK); + } -const rgb_t *palette_entry_list_raw(palette_t *palette) -{ - return palette->entry_color; + // add black and white as the last two colors + m_adjusted_color[numcolors * numgroups + 0] = RGB_BLACK; + m_adjusted_rgb15[numcolors * numgroups + 0] = rgb_to_rgb15(RGB_BLACK); + m_adjusted_color[numcolors * numgroups + 1] = RGB_WHITE; + m_adjusted_rgb15[numcolors * numgroups + 1] = rgb_to_rgb15(RGB_WHITE); } -/*------------------------------------------------- - palette_entry_list_adjusted - return the - entire palette as an array of adjusted RGB - values --------------------------------------------------*/ +//------------------------------------------------- +// palette_t - destructor +//------------------------------------------------- -const rgb_t *palette_entry_list_adjusted(palette_t *palette) +palette_t::~palette_t() { - return palette->adjusted_color; } -/*------------------------------------------------- - palette_entry_list_adjusted_rgb15 - return the - entire palette as an array of adjusted RGB-15 - values --------------------------------------------------*/ +//------------------------------------------------- +// deref - dereference a palette object; if the +// reference count goes to 0, it is freed +//------------------------------------------------- -const rgb_t *palette_entry_list_adjusted_rgb15(palette_t *palette) +void palette_t::deref() { - return palette->adjusted_rgb15; + // if the reference count goes to 0, free + if (--m_refcount == 0) + delete this; } +//------------------------------------------------- +// set_brightness - set the overall brightness +// for the palette +//------------------------------------------------- -/*************************************************************************** - PALETTE ADJUSTMENTS -***************************************************************************/ - -/*------------------------------------------------- - palette_set_brightness - set the overall - brightness for the palette --------------------------------------------------*/ - -void palette_set_brightness(palette_t *palette, float brightness) +void palette_t::set_brightness(float brightness) { - int groupnum, index; - - /* convert incoming value to normalized result */ + // convert incoming value to normalized result brightness = (brightness - 1.0f) * 256.0f; - /* set the global brightness if changed */ - if (palette->brightness == brightness) + // set the global brightness if changed + if (m_brightness == brightness) return; - palette->brightness = brightness; + m_brightness = brightness; - /* update across all indices in all groups */ - for (groupnum = 0; groupnum < palette->numgroups; groupnum++) - for (index = 0; index < palette->numcolors; index++) - update_adjusted_color(palette, groupnum, index); + // update across all indices in all groups + for (int groupnum = 0; groupnum < m_numgroups; groupnum++) + for (int index = 0; index < m_numcolors; index++) + update_adjusted_color(groupnum, index); } -/*------------------------------------------------- - palette_set_contrast - set the overall - contrast for the palette --------------------------------------------------*/ +//------------------------------------------------- +// set_contrast - set the overall contrast for +// the palette +//------------------------------------------------- -void palette_set_contrast(palette_t *palette, float contrast) +void palette_t::set_contrast(float contrast) { - int groupnum, index; - - /* set the global contrast if changed */ - if (palette->contrast == contrast) + // set the global contrast if changed + if (m_contrast == contrast) return; - palette->contrast = contrast; + m_contrast = contrast; - /* update across all indices in all groups */ - for (groupnum = 0; groupnum < palette->numgroups; groupnum++) - for (index = 0; index < palette->numcolors; index++) - update_adjusted_color(palette, groupnum, index); + // update across all indices in all groups + for (int groupnum = 0; groupnum < m_numgroups; groupnum++) + for (int index = 0; index < m_numcolors; index++) + update_adjusted_color(groupnum, index); } -/*------------------------------------------------- - palette_set_gamma - set the overall - gamma for the palette --------------------------------------------------*/ +//------------------------------------------------- +// set_gamma - set the overall gamma for the +// palette +//------------------------------------------------- -void palette_set_gamma(palette_t *palette, float gamma) +void palette_t::set_gamma(float gamma) { - int groupnum, index; - - /* set the global gamma if changed */ - if (palette->gamma == gamma) + // set the global gamma if changed + if (m_gamma == gamma) return; - palette->gamma = gamma; + m_gamma = gamma; - /* recompute the gamma map */ + // recompute the gamma map gamma = 1.0f / gamma; - for (index = 0; index < 256; index++) + for (int index = 0; index < 256; index++) { - float fval = (float)index * (1.0f / 255.0f); + float fval = float(index) * (1.0f / 255.0f); float fresult = pow(fval, gamma); - palette->gamma_map[index] = rgb_clamp(255.0f * fresult); + m_gamma_map[index] = rgb_clamp(255.0f * fresult); } - /* update across all indices in all groups */ - for (groupnum = 0; groupnum < palette->numgroups; groupnum++) - for (index = 0; index < palette->numcolors; index++) - update_adjusted_color(palette, groupnum, index); + // update across all indices in all groups + for (int groupnum = 0; groupnum < m_numgroups; groupnum++) + for (int index = 0; index < m_numcolors; index++) + update_adjusted_color(groupnum, index); } -/*------------------------------------------------- - palette_entry_set_contrast - set the contrast - adjustment for a single palette index --------------------------------------------------*/ +//------------------------------------------------- +// entry_set_color - set the raw RGB color for a +// given palette index +//------------------------------------------------- -void palette_entry_set_contrast(palette_t *palette, UINT32 index, float contrast) +void palette_t::entry_set_color(UINT32 index, rgb_t rgb) { - int groupnum; - - /* if out of range, or unchanged, ignore */ - if (index >= palette->numcolors || palette->entry_contrast[index] == contrast) + // if out of range, or unchanged, ignore + if (index >= m_numcolors || m_entry_color[index] == rgb) return; - /* set the contrast */ - palette->entry_contrast[index] = contrast; + // set the color + m_entry_color[index] = rgb; - /* update across all groups */ - for (groupnum = 0; groupnum < palette->numgroups; groupnum++) - update_adjusted_color(palette, groupnum, index); + // update across all groups + for (int groupnum = 0; groupnum < m_numgroups; groupnum++) + update_adjusted_color(groupnum, index); } -/*------------------------------------------------- - palette_entry_get_contrast - return the - contrast adjustment for a single palette index --------------------------------------------------*/ +//------------------------------------------------- +// entry_set_contrast - set the contrast +// adjustment for a single palette index +//------------------------------------------------- -float palette_entry_get_contrast(palette_t *palette, UINT32 index) +void palette_t::entry_set_contrast(UINT32 index, float contrast) { - return (index < palette->numcolors) ? palette->entry_contrast[index] : 1.0f; + // if out of range, or unchanged, ignore + if (index >= m_numcolors || m_entry_contrast[index] == contrast) + return; + + // set the contrast + m_entry_contrast[index] = contrast; + + // update across all groups + for (int groupnum = 0; groupnum < m_numgroups; groupnum++) + update_adjusted_color(groupnum, index); } -/*------------------------------------------------- - palette_group_set_brightness - configure - overall brightness for a palette group --------------------------------------------------*/ +//------------------------------------------------- +// group_set_brightness - configure overall +// brightness for a palette group +//------------------------------------------------- -void palette_group_set_brightness(palette_t *palette, UINT32 group, float brightness) +void palette_t::group_set_brightness(UINT32 group, float brightness) { - int index; - - /* convert incoming value to normalized result */ + // convert incoming value to normalized result brightness = (brightness - 1.0f) * 256.0f; - /* if out of range, or unchanged, ignore */ - if (group >= palette->numgroups || palette->group_bright[group] == brightness) + // if out of range, or unchanged, ignore + if (group >= m_numgroups || m_group_bright[group] == brightness) return; - /* set the contrast */ - palette->group_bright[group] = brightness; + // set the contrast + m_group_bright[group] = brightness; - /* update across all colors */ - for (index = 0; index < palette->numcolors; index++) - update_adjusted_color(palette, group, index); + // update across all colors + for (int index = 0; index < m_numcolors; index++) + update_adjusted_color(group, index); } -/*------------------------------------------------- - palette_group_set_contrast - configure - overall contrast for a palette group --------------------------------------------------*/ +//------------------------------------------------- +// group_set_contrast - configure overall +// contrast for a palette group +//------------------------------------------------- -void palette_group_set_contrast(palette_t *palette, UINT32 group, float contrast) +void palette_t::group_set_contrast(UINT32 group, float contrast) { - int index; - - /* if out of range, or unchanged, ignore */ - if (group >= palette->numgroups || palette->group_contrast[group] == contrast) + // if out of range, or unchanged, ignore + if (group >= m_numgroups || m_group_contrast[group] == contrast) return; - /* set the contrast */ - palette->group_contrast[group] = contrast; + // set the contrast + m_group_contrast[group] = contrast; - /* update across all colors */ - for (index = 0; index < palette->numcolors; index++) - update_adjusted_color(palette, group, index); + // update across all colors + for (int index = 0; index < m_numcolors; index++) + update_adjusted_color(group, index); } +//------------------------------------------------- +// normalize_range - normalize a range of palette +// entries +//------------------------------------------------- -/*************************************************************************** - PALETTE UTILITIES -***************************************************************************/ - -/*------------------------------------------------- - palette_normalize_range - normalize a range - of palette entries --------------------------------------------------*/ - -void palette_normalize_range(palette_t *palette, UINT32 start, UINT32 end, int lum_min, int lum_max) +void palette_t::normalize_range(UINT32 start, UINT32 end, int lum_min, int lum_max) { - INT32 ymin = 1000 * 255, ymax = 0; - INT32 tmin, tmax; - UINT32 index; - - /* clamp within range */ + // clamp within range start = MAX(start, 0); - end = MIN(end, palette->numcolors - 1); + end = MIN(end, m_numcolors - 1); - /* find the minimum and maximum brightness of all the colors in the range */ - for (index = start; index <= end; index++) + // find the minimum and maximum brightness of all the colors in the range + INT32 ymin = 1000 * 255, ymax = 0; + for (UINT32 index = start; index <= end; index++) { - rgb_t rgb = palette->entry_color[index]; + rgb_t rgb = m_entry_color[index]; UINT32 y = 299 * RGB_RED(rgb) + 587 * RGB_GREEN(rgb) + 114 * RGB_BLUE(rgb); ymin = MIN(ymin, y); ymax = MAX(ymax, y); } - /* determine target minimum/maximum */ - tmin = (lum_min < 0) ? ((ymin + 500) / 1000) : lum_min; - tmax = (lum_max < 0) ? ((ymax + 500) / 1000) : lum_max; + // determine target minimum/maximum + INT32 tmin = (lum_min < 0) ? ((ymin + 500) / 1000) : lum_min; + INT32 tmax = (lum_max < 0) ? ((ymax + 500) / 1000) : lum_max; - /* now normalize the palette */ - for (index = start; index <= end; index++) + // now normalize the palette + for (UINT32 index = start; index <= end; index++) { - rgb_t rgb = palette->entry_color[index]; + rgb_t rgb = m_entry_color[index]; INT32 y = 299 * RGB_RED(rgb) + 587 * RGB_GREEN(rgb) + 114 * RGB_BLUE(rgb); INT32 u = ((INT32)RGB_BLUE(rgb)-y /1000)*492 / 1000; INT32 v = ((INT32)RGB_RED(rgb)-y / 1000)*877 / 1000; @@ -684,76 +450,34 @@ void palette_normalize_range(palette_t *palette, UINT32 start, UINT32 end, int l UINT8 r = rgb_clamp(target + 1140 * v / 1000); UINT8 g = rgb_clamp(target - 395 * u / 1000 - 581 * v / 1000); UINT8 b = rgb_clamp(target + 2032 * u / 1000); - palette_entry_set_color(palette, index, MAKE_RGB(r, g, b)); + entry_set_color(index, MAKE_RGB(r, g, b)); } } +//------------------------------------------------- +// update_adjusted_color - update a color index +// by group and index pair +//------------------------------------------------- -/*************************************************************************** - INTERNAL ROUTINES -***************************************************************************/ - -/*------------------------------------------------- - internal_palette_free - free all allocations - from a palette --------------------------------------------------*/ - -static void internal_palette_free(palette_t *palette) +void palette_t::update_adjusted_color(UINT32 group, UINT32 index) { - /* free per-color data */ - if (palette->entry_color != NULL) - free(palette->entry_color); - if (palette->entry_contrast != NULL) - free(palette->entry_contrast); - - /* free per-group data */ - if (palette->group_bright != NULL) - free(palette->group_bright); - if (palette->group_contrast != NULL) - free(palette->group_contrast); - - /* free adjusted data */ - if (palette->adjusted_color != NULL) - free(palette->adjusted_color); - if (palette->adjusted_rgb15 != NULL) - free(palette->adjusted_rgb15); - - /* and the palette itself */ - free(palette); -} - - -/*------------------------------------------------- - update_adjusted_color - update a color index - by group and index pair --------------------------------------------------*/ + // compute the adjusted value + rgb_t adjusted = adjust_palette_entry(m_entry_color[index], + m_group_bright[group] + m_brightness, + m_group_contrast[group] * m_entry_contrast[index] * m_contrast, + m_gamma_map); -static void update_adjusted_color(palette_t *palette, UINT32 group, UINT32 index) -{ - UINT32 finalindex = group * palette->numcolors + index; - palette_client *client; - rgb_t adjusted; - - /* compute the adjusted value */ - adjusted = adjust_palette_entry(palette->entry_color[index], - palette->group_bright[group] + palette->brightness, - palette->group_contrast[group] * palette->entry_contrast[index] * palette->contrast, - palette->gamma_map); - - /* if not different, ignore */ - if (palette->adjusted_color[finalindex] == adjusted) + // if not different, ignore + UINT32 finalindex = group * m_numcolors + index; + if (m_adjusted_color[finalindex] == adjusted) return; - /* otherwise, modify the adjusted color array */ - palette->adjusted_color[finalindex] = adjusted; - palette->adjusted_rgb15[finalindex] = rgb_to_rgb15(adjusted); + // otherwise, modify the adjusted color array + m_adjusted_color[finalindex] = adjusted; + m_adjusted_rgb15[finalindex] = rgb_to_rgb15(adjusted); - /* mark dirty in all clients */ - for (client = palette->client_list; client != NULL; client = client->next) - { - client->live.dirty[finalindex / 32] |= 1 << (finalindex % 32); - client->live.mindirty = MIN(client->live.mindirty, finalindex); - client->live.maxdirty = MAX(client->live.maxdirty, finalindex); - } + // mark dirty in all clients + for (palette_client *client = m_client_list; client != NULL; client = client->next()) + client->mark_dirty(finalindex); } diff --git a/src/lib/util/palette.h b/src/lib/util/palette.h index 46f01f962b5..06370118d05 100644 --- a/src/lib/util/palette.h +++ b/src/lib/util/palette.h @@ -14,162 +14,177 @@ #define __PALETTE_H__ #include "osdcore.h" +#include "coretmpl.h" -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* an rgb_t is a single combined R,G,B (and optionally alpha) value */ -typedef UINT32 rgb_t; - -/* an rgb15_t is a single combined 15-bit R,G,B value */ -typedef UINT16 rgb15_t; - -/* a palette is an opaque, reference counted object */ -struct palette_t; - -/* a palette client is someone who is tracking the dirty state of a palette */ -struct palette_client; - - - -/*************************************************************************** - MACROS -***************************************************************************/ +//************************************************************************** +// MACROS +//************************************************************************** -/* macros to assemble rgb_t values */ -#define MAKE_ARGB(a,r,g,b) ((((rgb_t)(a) & 0xff) << 24) | (((rgb_t)(r) & 0xff) << 16) | (((rgb_t)(g) & 0xff) << 8) | ((rgb_t)(b) & 0xff)) +// macros to assemble rgb_t values */ +#define MAKE_ARGB(a,r,g,b) (((rgb_t(a) & 0xff) << 24) | ((rgb_t(r) & 0xff) << 16) | ((rgb_t(g) & 0xff) << 8) | (rgb_t(b) & 0xff)) #define MAKE_RGB(r,g,b) (MAKE_ARGB(255,r,g,b)) -/* macros to extract components from rgb_t values */ +// macros to extract components from rgb_t values */ #define RGB_ALPHA(rgb) (((rgb) >> 24) & 0xff) #define RGB_RED(rgb) (((rgb) >> 16) & 0xff) #define RGB_GREEN(rgb) (((rgb) >> 8) & 0xff) #define RGB_BLUE(rgb) ((rgb) & 0xff) -/* common colors */ +// common colors */ #define RGB_BLACK (MAKE_ARGB(255,0,0,0)) #define RGB_WHITE (MAKE_ARGB(255,255,255,255)) -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - - -/* ----- palette allocation ----- */ - -/* allocate a new palette object and take a single reference on it */ -palette_t *palette_alloc(UINT32 numcolors, UINT32 numgroups); - -/* reference a palette object, incrementing its reference count */ -void palette_ref(palette_t *palette); - -/* dereference a palette object; if the reference count goes to 0, it is freed */ -void palette_deref(palette_t *palette); - - - -/* ----- palette information ----- */ - -/* return the number of colors managed by the palette */ -int palette_get_num_colors(palette_t *palette); - -/* return the number of groups managed by the palette */ -int palette_get_num_groups(palette_t *palette); - -/* return the maximum allowed index (i.e., length of arrays returned by palette_entry_list*) */ -int palette_get_max_index(palette_t *palette); - -/* return the index of the black entry */ -UINT32 palette_get_black_entry(palette_t *palette); - -/* return the index of the white entry */ -UINT32 palette_get_white_entry(palette_t *palette); - - - -/* ----- palette clients ----- */ - -/* add a new client to a palette */ -palette_client *palette_client_alloc(palette_t *palette); - -/* remove a client from a palette */ -void palette_client_free(palette_client *client); - -/* return a pointer to the palette for this client */ -palette_t *palette_client_get_palette(palette_client *client); - -/* atomically get the current dirty list for a client */ -const UINT32 *palette_client_get_dirty_list(palette_client *client, UINT32 *mindirty, UINT32 *maxdirty); - - - -/* ----- color management ----- */ - -/* set the raw RGB color for a given palette index */ -void palette_entry_set_color(palette_t *palette, UINT32 index, rgb_t rgb); - -/* return the raw RGB color for a given palette index */ -rgb_t palette_entry_get_color(palette_t *palette, UINT32 index); - -/* return the adjusted RGB color (after all adjustments) for a given palette index */ -rgb_t palette_entry_get_adjusted_color(palette_t *palette, UINT32 index); - -/* return the entire palette as an array of raw RGB values */ -const rgb_t *palette_entry_list_raw(palette_t *palette); - -/* return the entire palette as an array of adjusted RGB values */ -const rgb_t *palette_entry_list_adjusted(palette_t *palette); - -/* return the entire palette as an array of adjusted RGB-15 values */ -const rgb_t *palette_entry_list_adjusted_rgb15(palette_t *palette); - - +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** -/* ----- palette adjustments ----- */ - -/* set the overall brightness for the palette */ -void palette_set_brightness(palette_t *palette, float brightness); - -/* set the overall contrast for the palette */ -void palette_set_contrast(palette_t *palette, float contrast); - -/* set the overall gamma for the palette */ -void palette_set_gamma(palette_t *palette, float gamma); - -/* set the contrast adjustment for a single palette index */ -void palette_entry_set_contrast(palette_t *palette, UINT32 index, float contrast); - -/* return the contrast adjustment for a single palette index */ -float palette_entry_get_contrast(palette_t *palette, UINT32 index); - -/* configure overall brightness for a palette group */ -void palette_group_set_brightness(palette_t *palette, UINT32 group, float brightness); - -/* configure overall contrast for a palette group */ -void palette_group_set_contrast(palette_t *palette, UINT32 group, float contrast); - - - -/* ----- palette utilities ----- */ +// an rgb_t is a single combined R,G,B (and optionally alpha) value */ +typedef UINT32 rgb_t; -/* normalize a range of palette entries, mapping minimum brightness to lum_min and maximum - brightness to lum_max; if either value is < 0, that boundary value is not modified */ -void palette_normalize_range(palette_t *palette, UINT32 start, UINT32 end, int lum_min, int lum_max); +// an rgb15_t is a single combined 15-bit R,G,B value */ +typedef UINT16 rgb15_t; +// forward definitions +class palette_t; +// ======================> palette_client -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ +// a single palette client +class palette_client +{ +public: + // construction/destruction + palette_client(palette_t &palette); + ~palette_client(); + + // getters + palette_client *next() const { return m_next; } + palette_t &palette() const { return m_palette; } + const UINT32 *dirty_list(UINT32 &mindirty, UINT32 &maxdirty); + + // dirty marking + void mark_dirty(UINT32 index) { m_live->mark_dirty(index); } + +private: + // internal object to track dirty states + class dirty_state + { + public: + // construction + dirty_state(); + + // operations + const UINT32 *dirty_list(UINT32 &mindirty, UINT32 &maxdirty); + void resize(UINT32 colors); + void mark_dirty(UINT32 index); + void reset(); + + private: + // internal state + dynamic_array<UINT32> m_dirty; // bitmap of dirty entries + UINT32 m_mindirty; // minimum dirty entry + UINT32 m_maxdirty; // minimum dirty entry + }; + + // internal state + palette_t & m_palette; // reference to the palette + palette_client *m_next; // pointer to next client + dirty_state * m_live; // live dirty state + dirty_state * m_previous; // previous dirty state + dirty_state m_dirty[2]; // two dirty states +}; + + +// ======================> palette_t + +// a palette object +class palette_t +{ + friend class palette_client; + +public: + // construction/destruction + palette_t(UINT32 numcolors, UINT32 numgroups = 1); + + // reference counting + void ref() { m_refcount++; } + void deref(); + + // getters + int num_colors() const { return m_numcolors; } + int num_groups() const { return m_numgroups; } + int max_index() const { return m_numcolors * m_numgroups + 2; } + UINT32 black_entry() const { return m_numcolors * m_numgroups + 0; } + UINT32 white_entry() const { return m_numcolors * m_numgroups + 1; } + + // overall adjustments + void set_brightness(float brightness); + void set_contrast(float contrast); + void set_gamma(float gamma); + + // entry getters + rgb_t entry_color(UINT32 index) const { return (index < m_numcolors) ? m_entry_color[index] : RGB_BLACK; } + rgb_t entry_adjusted_color(UINT32 index) const { return (index < m_numcolors * m_numgroups) ? m_adjusted_color[index] : RGB_BLACK; } + float entry_contrast(UINT32 index) const { return (index < m_numcolors) ? m_entry_contrast[index] : 1.0f; } + + // entry setters + void entry_set_color(UINT32 index, rgb_t rgb); + void entry_set_contrast(UINT32 index, float contrast); + + // entry list getters + const rgb_t *entry_list_raw() const { return m_entry_color; } + const rgb_t *entry_list_adjusted() const { return m_adjusted_color; } + const rgb_t *entry_list_adjusted_rgb15() const { return m_adjusted_rgb15; } + + // group adjustments + void group_set_brightness(UINT32 group, float brightness); + void group_set_contrast(UINT32 group, float contrast); + + // utilities + void normalize_range(UINT32 start, UINT32 end, int lum_min = 0, int lum_max = 255); + +private: + // destructor -- can only destruct via + ~palette_t(); + + // internal helpers + rgb_t adjust_palette_entry(rgb_t entry, float brightness, float contrast, const UINT8 *gamma_map); + void update_adjusted_color(UINT32 group, UINT32 index); + + // internal state + UINT32 m_refcount; // reference count on the palette + UINT32 m_numcolors; // number of colors in the palette + UINT32 m_numgroups; // number of groups in the palette + + float m_brightness; // overall brightness value + float m_contrast; // overall contrast value + float m_gamma; // overall gamma value + UINT8 m_gamma_map[256]; // gamma map + + dynamic_array<rgb_t> m_entry_color; // array of raw colors + dynamic_array<float> m_entry_contrast; // contrast value for each entry + dynamic_array<rgb_t> m_adjusted_color; // array of adjusted colors + dynamic_array<rgb_t> m_adjusted_rgb15; // array of adjusted colors as RGB15 + + dynamic_array<float> m_group_bright; // brightness value for each group + dynamic_array<float> m_group_contrast; // contrast value for each group + + palette_client *m_client_list; // list of clients for this palette +}; + + + +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** -/*------------------------------------------------- - rgb_to_rgb15 - convert an RGB triplet to - a 15-bit OSD-specified RGB value --------------------------------------------------*/ +//------------------------------------------------- +// rgb_to_rgb15 - convert an RGB triplet to +// a 15-bit OSD-specified RGB value +//------------------------------------------------- inline rgb15_t rgb_to_rgb15(rgb_t rgb) { @@ -177,9 +192,9 @@ inline rgb15_t rgb_to_rgb15(rgb_t rgb) } -/*------------------------------------------------- - rgb_clamp - clamp an RGB component to 0-255 --------------------------------------------------*/ +//------------------------------------------------- +// rgb_clamp - clamp an RGB component to 0-255 +//------------------------------------------------- inline UINT8 rgb_clamp(INT32 value) { @@ -191,9 +206,9 @@ inline UINT8 rgb_clamp(INT32 value) } -/*------------------------------------------------- - pal1bit - convert a 1-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal1bit - convert a 1-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal1bit(UINT8 bits) { @@ -201,9 +216,9 @@ inline UINT8 pal1bit(UINT8 bits) } -/*------------------------------------------------- - pal2bit - convert a 2-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal2bit - convert a 2-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal2bit(UINT8 bits) { @@ -212,9 +227,9 @@ inline UINT8 pal2bit(UINT8 bits) } -/*------------------------------------------------- - pal3bit - convert a 3-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal3bit - convert a 3-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal3bit(UINT8 bits) { @@ -223,9 +238,9 @@ inline UINT8 pal3bit(UINT8 bits) } -/*------------------------------------------------- - pal4bit - convert a 4-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal4bit - convert a 4-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal4bit(UINT8 bits) { @@ -234,9 +249,9 @@ inline UINT8 pal4bit(UINT8 bits) } -/*------------------------------------------------- - pal5bit - convert a 5-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal5bit - convert a 5-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal5bit(UINT8 bits) { @@ -245,9 +260,9 @@ inline UINT8 pal5bit(UINT8 bits) } -/*------------------------------------------------- - pal6bit - convert a 6-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal6bit - convert a 6-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal6bit(UINT8 bits) { @@ -256,9 +271,9 @@ inline UINT8 pal6bit(UINT8 bits) } -/*------------------------------------------------- - pal7bit - convert a 7-bit value to 8 bits --------------------------------------------------*/ +//------------------------------------------------- +// pal7bit - convert a 7-bit value to 8 bits +//------------------------------------------------- inline UINT8 pal7bit(UINT8 bits) { @@ -285,10 +300,10 @@ inline UINT8 palexpand(UINT8 data) } -/*------------------------------------------------- - pal332 - create a 3-3-2 color by extracting - bits from a UINT32 --------------------------------------------------*/ +//------------------------------------------------- +// pal332 - create a 3-3-2 color by extracting +// bits from a UINT32 +//------------------------------------------------- inline rgb_t pal332(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) { @@ -296,10 +311,10 @@ inline rgb_t pal332(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) } -/*------------------------------------------------- - pal444 - create a 4-4-4 color by extracting - bits from a UINT32 --------------------------------------------------*/ +//------------------------------------------------- +// pal444 - create a 4-4-4 color by extracting +// bits from a UINT32 +//------------------------------------------------- inline rgb_t pal444(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) { @@ -307,10 +322,10 @@ inline rgb_t pal444(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) } -/*------------------------------------------------- - pal555 - create a 5-5-5 color by extracting - bits from a UINT32 --------------------------------------------------*/ +//------------------------------------------------- +// pal555 - create a 5-5-5 color by extracting +// bits from a UINT32 +//------------------------------------------------- inline rgb_t pal555(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) { @@ -318,10 +333,10 @@ inline rgb_t pal555(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) } -/*------------------------------------------------- - pal565 - create a 5-6-5 color by extracting - bits from a UINT32 --------------------------------------------------*/ +//------------------------------------------------- +// pal565 - create a 5-6-5 color by extracting +// bits from a UINT32 +//------------------------------------------------- inline rgb_t pal565(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) { @@ -329,10 +344,10 @@ inline rgb_t pal565(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) } -/*------------------------------------------------- - pal888 - create a 8-8-8 color by extracting - bits from a UINT32 --------------------------------------------------*/ +//------------------------------------------------- +// pal888 - create a 8-8-8 color by extracting +// bits from a UINT32 +//------------------------------------------------- inline rgb_t pal888(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) { @@ -340,4 +355,4 @@ inline rgb_t pal888(UINT32 data, UINT8 rshift, UINT8 gshift, UINT8 bshift) } -#endif /* __PALETTE_H__ */ +#endif // __PALETTE_H__ */ |