summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/bitmap.c
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2012-01-14 20:28:09 +0000
committer Aaron Giles <aaron@aarongiles.com>2012-01-14 20:28:09 +0000
commitbc3996fde63a863452a26050ee0b9551863a0fd7 (patch)
treeaf0d6e448e9d10d5a9bf86aad843f2b2ec6f9350 /src/lib/util/bitmap.c
parentb12f0240a81cac755ab89b66b8f3bc58f4e12005 (diff)
Cleanup of bitmap classes now that formats and bpp are dictated
strictly by the type. Also added code to more aggressively align the bitmap base and rowbytes, and create a resize method which attempts to re-use existing memory rather than always reallocating.
Diffstat (limited to 'src/lib/util/bitmap.c')
-rw-r--r--src/lib/util/bitmap.c178
1 files changed, 108 insertions, 70 deletions
diff --git a/src/lib/util/bitmap.c b/src/lib/util/bitmap.c
index 86784d43584..a90d3ee3db1 100644
--- a/src/lib/util/bitmap.c
+++ b/src/lib/util/bitmap.c
@@ -39,67 +39,100 @@
#include "bitmap.h"
-#include <stdlib.h>
-
-#ifdef __cplusplus
#include <new>
-#endif
+
//**************************************************************************
-// BITMAP ALLOCATION/CONFIGURATION
+// CONSTANTS
+//**************************************************************************
+
+// alignment values; 128 bytes is the largest cache line on typical
+// architectures today
+const UINT32 BITMAP_OVERALL_ALIGN = 128;
+const UINT32 BITMAP_ROWBYTES_ALIGN = 128;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
-// bitmap_t - basic constructor
+// compute_rowpixels - compute an aligned
+// rowpixels value
//-------------------------------------------------
-bitmap_t::bitmap_t()
- : m_alloc(NULL),
- m_palette(NULL)
+inline INT32 bitmap_t::compute_rowpixels(int width, int xslop)
{
- // deallocate intializes all other fields
- reset();
+ int rowpixels_align = BITMAP_ROWBYTES_ALIGN / (m_bpp / 8);
+ return ((width + 2 * xslop + (rowpixels_align - 1)) / rowpixels_align) * rowpixels_align;
+}
+
+
+//-------------------------------------------------
+// compute_base - compute an aligned bitmap base
+// address with the given slop values
+//-------------------------------------------------
+
+inline void bitmap_t::compute_base(int xslop, int yslop)
+{
+ m_base = m_alloc + (m_rowpixels * yslop + xslop) * (m_bpp / 8);
+ UINT64 aligned_base = ((reinterpret_cast<UINT64>(m_base) + (BITMAP_OVERALL_ALIGN - 1)) / BITMAP_OVERALL_ALIGN) * BITMAP_OVERALL_ALIGN;
+ m_base = reinterpret_cast<void *>(aligned_base);
}
-bitmap_t::bitmap_t(int width, int height, bitmap_format format, int xslop, int yslop)
+
+//**************************************************************************
+// BITMAP ALLOCATION/CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// bitmap_t - basic constructor
+//-------------------------------------------------
+
+bitmap_t::bitmap_t(bitmap_format format, int bpp, int width, int height, int xslop, int yslop)
: m_alloc(NULL),
+ m_allocbytes(0),
+ m_format(format),
+ m_bpp(bpp),
m_palette(NULL)
{
// allocate intializes all other fields
- allocate(width, height, format, xslop, yslop);
+ allocate(width, height, xslop, yslop);
}
-bitmap_t::bitmap_t(void *base, int width, int height, int rowpixels, bitmap_format format)
+bitmap_t::bitmap_t(bitmap_format format, int bpp, void *base, int width, int height, int rowpixels)
: m_alloc(NULL),
+ m_allocbytes(0),
m_base(base),
m_rowpixels(rowpixels),
m_width(width),
m_height(height),
m_format(format),
- m_bpp(format_to_bpp(format)),
+ m_bpp(bpp),
m_palette(NULL),
m_cliprect(0, width - 1, 0, height - 1)
{
- // fail if invalid format
- if (m_bpp == 0)
- throw std::bad_alloc();
}
-bitmap_t::bitmap_t(bitmap_t &source, const rectangle &subrect)
+bitmap_t::bitmap_t(bitmap_format format, int bpp, bitmap_t &source, const rectangle &subrect)
: m_alloc(NULL),
+ m_allocbytes(0),
m_base(source.raw_pixptr(subrect.min_y, subrect.min_x)),
m_rowpixels(source.m_rowpixels),
m_width(subrect.width()),
m_height(subrect.height()),
- m_format(source.m_format),
- m_bpp(source.m_bpp),
+ m_format(format),
+ m_bpp(bpp),
m_palette(NULL),
m_cliprect(0, subrect.width() - 1, 0, subrect.height() - 1)
{
+ assert(format == source.m_format);
+ assert(bpp == source.m_bpp);
assert(source.cliprect().contains(subrect));
}
@@ -121,30 +154,69 @@ bitmap_t::~bitmap_t()
// already exists
//-------------------------------------------------
-void bitmap_t::allocate(int width, int height, bitmap_format format, int xslop, int yslop)
+void bitmap_t::allocate(int width, int height, int xslop, int yslop)
{
+ assert(m_format != BITMAP_FORMAT_INVALID);
+ assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64);
+
// delete any existing stuff
reset();
+
+ // handle empty requests cleanly
+ if (width <= 0 || height <= 0)
+ return;
// initialize fields
- m_rowpixels = (width + 2 * xslop + 7) & ~7;
+ m_rowpixels = compute_rowpixels(width, xslop);
m_width = width;
m_height = height;
- m_format = format;
- m_bpp = format_to_bpp(format);
- if (m_bpp == 0)
- throw std::bad_alloc();
m_cliprect.set(0, width - 1, 0, height - 1);
// allocate memory for the bitmap itself
- size_t allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8;
- m_alloc = new UINT8[allocbytes];
+ m_allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8;
+ m_allocbytes += BITMAP_OVERALL_ALIGN - 1;
+ m_alloc = new UINT8[m_allocbytes];
// clear to 0 by default
- memset(m_alloc, 0, allocbytes);
+ memset(m_alloc, 0, m_allocbytes);
// compute the base
- m_base = m_alloc + (m_rowpixels * yslop + xslop) * (m_bpp / 8);
+ compute_base(xslop, yslop);
+}
+
+
+//-------------------------------------------------
+// resize -- resize a bitmap, reusing existing
+// memory if the new size is smaller than the
+// current size
+//-------------------------------------------------
+
+void bitmap_t::resize(int width, int height, int xslop, int yslop)
+{
+ assert(m_format != BITMAP_FORMAT_INVALID);
+ assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64);
+
+ // handle empty requests cleanly
+ if (width <= 0 || height <= 0)
+ width = height = 0;
+
+ // determine how much memory we need for the new bitmap
+ int new_rowpixels = compute_rowpixels(width, xslop);
+ UINT32 new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
+ new_allocbytes += BITMAP_OVERALL_ALIGN - 1;
+
+ // if we need more memory, just realloc
+ if (new_allocbytes > m_allocbytes)
+ return allocate(width, height, xslop, yslop);
+
+ // otherwise, reconfigure
+ m_rowpixels = new_rowpixels;
+ m_width = width;
+ m_height = height;
+ m_cliprect.set(0, width - 1, 0, height - 1);
+
+ // re-compute the base
+ compute_base(xslop, yslop);
}
@@ -165,8 +237,6 @@ void bitmap_t::reset()
m_rowpixels = 0;
m_width = 0;
m_height = 0;
- m_format = BITMAP_FORMAT_INVALID;
- m_bpp = 0;
m_cliprect.set(0, -1, 0, -1);
}
@@ -176,7 +246,7 @@ void bitmap_t::reset()
// bitmap does not own the memory
//-------------------------------------------------
-void bitmap_t::wrap(void *base, int width, int height, int rowpixels, bitmap_format format)
+void bitmap_t::wrap(void *base, int width, int height, int rowpixels)
{
// delete any existing stuff
reset();
@@ -186,8 +256,6 @@ void bitmap_t::wrap(void *base, int width, int height, int rowpixels, bitmap_for
m_rowpixels = rowpixels;
m_width = width;
m_height = height;
- m_format = format;
- m_bpp = format_to_bpp(format);
m_cliprect.set(0, m_width - 1, 0, m_height - 1);
}
@@ -200,17 +268,18 @@ void bitmap_t::wrap(void *base, int width, int height, int rowpixels, bitmap_for
void bitmap_t::wrap(bitmap_t &source, const rectangle &subrect)
{
+ assert(m_format == source.m_format);
+ assert(m_bpp == source.m_bpp);
+ assert(source.cliprect().contains(subrect));
+
// delete any existing stuff
reset();
// copy relevant fields
- assert(source.cliprect().contains(subrect));
m_base = source.raw_pixptr(subrect.min_y, subrect.min_x);
m_rowpixels = source.m_rowpixels;
m_width = subrect.width();
m_height = subrect.height();
- m_format = source.m_format;
- m_bpp = source.m_bpp;
set_palette(source.m_palette);
m_cliprect.set(0, m_width - 1, 0, m_height - 1);
}
@@ -333,34 +402,3 @@ void bitmap_t::fill(UINT32 color, const rectangle &cliprect)
break;
}
}
-
-
-//-------------------------------------------------
-// format_to_bpp - given a format, return the bpp
-//-------------------------------------------------
-
-UINT8 bitmap_t::format_to_bpp(bitmap_format format)
-{
- // choose a depth for the format
- switch (format)
- {
- case BITMAP_FORMAT_IND8:
- return 8;
-
- case BITMAP_FORMAT_IND16:
- case BITMAP_FORMAT_YUY16:
- return 16;
-
- case BITMAP_FORMAT_IND32:
- case BITMAP_FORMAT_RGB32:
- case BITMAP_FORMAT_ARGB32:
- return 32;
-
- case BITMAP_FORMAT_IND64:
- return 64;
-
- default:
- break;
- }
- return 0;
-}