/*************************************************************************** bitmap.c Core bitmap routines. Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #include "bitmap.h" /*************************************************************************** BITMAP ALLOCATION/CONFIGURATION ***************************************************************************/ /*------------------------------------------------- bitmap_alloc -- allocate memory for a new bitmap of the given format -------------------------------------------------*/ bitmap_t *bitmap_alloc(int width, int height, bitmap_format format) { return bitmap_alloc_slop(width, height, 0, 0, format); } /*------------------------------------------------- bitmap_alloc_slop -- allocate a new bitmap with additional slop on the borders -------------------------------------------------*/ bitmap_t *bitmap_alloc_slop(int width, int height, int xslop, int yslop, bitmap_format format) { int bpp = bitmap_format_to_bpp(format); size_t allocbytes; bitmap_t *bitmap; int rowpixels; /* fail if invalid format */ if (bpp == 0) return NULL; /* allocate the bitmap itself */ bitmap = malloc(sizeof(*bitmap)); if (bitmap == NULL) return NULL; memset(bitmap, 0, sizeof(*bitmap)); /* round the width to a multiple of 8 and add some padding */ rowpixels = (width + 2 * xslop + 7) & ~7; /* allocate memory for the bitmap itself */ allocbytes = rowpixels * (height + 2 * yslop) * bpp / 8; bitmap->alloc = malloc(allocbytes); if (bitmap->alloc == NULL) { free(bitmap); return NULL; } /* clear to 0 by default */ memset(bitmap->alloc, 0, allocbytes); /* fill in the data */ bitmap->format = format; bitmap->width = width; bitmap->height = height; bitmap->bpp = bpp; bitmap->rowpixels = rowpixels; bitmap->base = (UINT8 *)bitmap->alloc + (rowpixels * yslop + xslop) * (bpp / 8); return bitmap; } /*------------------------------------------------- bitmap_wrap -- wrap an existing memory buffer as a bitmap -------------------------------------------------*/ bitmap_t *bitmap_wrap(void *base, int width, int height, int rowpixels, bitmap_format format) { int bpp = bitmap_format_to_bpp(format); bitmap_t *bitmap; /* fail if invalid format */ if (bpp == 0) return NULL; /* allocate memory */ bitmap = malloc(sizeof(*bitmap)); if (bitmap == NULL) return NULL; memset(bitmap, 0, sizeof(*bitmap)); /* fill in the data */ bitmap->format = format; bitmap->width = width; bitmap->height = height; bitmap->bpp = bpp; bitmap->rowpixels = rowpixels; bitmap->base = base; return bitmap; } /*------------------------------------------------- bitmap_set_palette -- associate a palette with a bitmap -------------------------------------------------*/ void bitmap_set_palette(bitmap_t *bitmap, palette_t *palette) { /* first dereference any existing palette */ if (bitmap->palette != NULL) { palette_deref(bitmap->palette); bitmap->palette = NULL; } /* then reference any new palette */ if (palette != NULL) { palette_ref(palette); bitmap->palette = palette; } } /*------------------------------------------------- bitmap_free -- release memory allocated for a bitmap -------------------------------------------------*/ void bitmap_free(bitmap_t *bitmap) { /* dereference the palette */ if (bitmap->palette != NULL) palette_deref(bitmap->palette); /* free any allocated memory */ if (bitmap->alloc != NULL) free(bitmap->alloc); /* free the bitmap */ free(bitmap); } /*************************************************************************** BITMAP DRAWING ***************************************************************************/ /*------------------------------------------------- bitmap_fill -- fill a bitmap with a solid color -------------------------------------------------*/ void bitmap_fill(bitmap_t *dest, const rectangle *cliprect, UINT32 color) { rectangle fill; int x, y; /* default to the whole bitmap */ fill.min_x = fill.min_y = 0; fill.max_x = dest->width - 1; fill.max_y = dest->height - 1; /* if we have a cliprect, intersect with that */ if (cliprect != NULL) sect_rect(&fill, cliprect); /* early out if nothing to do */ if (fill.min_x > fill.max_x || fill.min_y > fill.max_y) return; /* based on the bpp go from there */ switch (dest->bpp) { case 8: /* 8bpp always uses memset */ for (y = fill.min_y; y <= fill.max_y; y++) memset(BITMAP_ADDR8(dest, y, fill.min_x), (UINT8)color, fill.max_x + 1 - fill.min_x); break; case 16: /* 16bpp can use memset if the bytes are equal */ if ((UINT8)(color >> 8) == (UINT8)color) { for (y = fill.min_y; y <= fill.max_y; y++) memset(BITMAP_ADDR16(dest, y, fill.min_x), (UINT8)color, (fill.max_x + 1 - fill.min_x) * 2); } else { UINT16 *destrow, *destrow0; /* Fill the first line the hard way */ destrow = BITMAP_ADDR16(dest, fill.min_y, 0); for (x = fill.min_x; x <= fill.max_x; x++) destrow[x] = (UINT16)color; /* For the other lines, just copy the first one */ destrow0 = BITMAP_ADDR16(dest, fill.min_y, fill.min_x); for (y = fill.min_y + 1; y <= fill.max_y; y++) { destrow = BITMAP_ADDR16(dest, y, fill.min_x); memcpy(destrow, destrow0, (fill.max_x + 1 - fill.min_x) * 2); } } break; case 32: /* 32bpp can use memset if the bytes are equal */ if ((UINT8)(color >> 8) == (UINT8)color && (UINT16)(color >> 16) == (UINT16)color) { for (y = fill.min_y; y <= fill.max_y; y++) memset(BITMAP_ADDR32(dest, y, fill.min_x), (UINT8)color, (fill.max_x + 1 - fill.min_x) * 4); } else { UINT32 *destrow, *destrow0; /* Fill the first line the hard way */ destrow = BITMAP_ADDR32(dest, fill.min_y, 0); for (x = fill.min_x; x <= fill.max_x; x++) destrow[x] = (UINT32)color; /* For the other lines, just copy the first one */ destrow0 = BITMAP_ADDR32(dest, fill.min_y, fill.min_x); for (y = fill.min_y + 1; y <= fill.max_y; y++) { destrow = BITMAP_ADDR32(dest, y, fill.min_x); memcpy(destrow, destrow0, (fill.max_x + 1 - fill.min_x) * 4); } } break; } } /*************************************************************************** BITMAP UTILITIES ***************************************************************************/ /*------------------------------------------------- bitmap_format_to_bpp - given a format, return the bpp -------------------------------------------------*/ int bitmap_format_to_bpp(bitmap_format format) { /* choose a depth for the format */ switch (format) { case BITMAP_FORMAT_INDEXED8: return 8; case BITMAP_FORMAT_INDEXED16: case BITMAP_FORMAT_RGB15: case BITMAP_FORMAT_YUY16: return 16; case BITMAP_FORMAT_INDEXED32: case BITMAP_FORMAT_RGB32: case BITMAP_FORMAT_ARGB32: return 32; default: break; } return 0; }