summaryrefslogtreecommitdiff
path: root/src/cairo-os2-surface.c
diff options
context:
space:
mode:
authorPeter Weilbacher <mozilla@weilbacher.org>2007-12-06 16:46:28 +0100
committerPeter Weilbacher <mozilla@weilbacher.org>2007-12-06 16:46:28 +0100
commita7ae9c45d924effdd61390267eb216302a270d8e (patch)
tree866ee4f5d189536bc23be2e2f6a9e2da067d548d /src/cairo-os2-surface.c
parentbe79779331ee29c0bfb74b728227719bb5dead6e (diff)
[os2] add memory allocation wrappers for pixel buffers
Add ability to use OS/2 APIs instead of C library functions to manage pixel buffer allocations. This is to work around heap fragmentation. This implements two wrapper functions which replace _cairo_alloc_abc and free and when compiled with OS2_USE_PLATFORM_ALLOC the OS/2 functions DosAllocMem and DosFreeMem will be used for allocation/deallocation. Also try to minimize the heap when shutting down the cairo library.
Diffstat (limited to 'src/cairo-os2-surface.c')
-rw-r--r--src/cairo-os2-surface.c108
1 files changed, 81 insertions, 27 deletions
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 0d888ed3..86ab82c2 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -135,6 +135,74 @@ cairo_os2_fini (void)
* as much as possible.
*/
_heapshrink ();
+#else
+ /* GCC has a heapmin function that approximately corresponds to
+ * what the Watcom function does
+ */
+ _heapmin ();
+#endif
+}
+
+/*
+ * This function calls the allocation function depending on which
+ * method was compiled into the library: it can be native allocation
+ * (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free).
+ * Actually, for pixel buffers that we use this function for, cairo
+ * uses _cairo_malloc_abc, so we use that here, too. And use the
+ * change to check the size argument
+ */
+void *_buffer_alloc (size_t a, size_t b, const unsigned int size)
+{
+ /* check length like in the _cairo_malloc_abc macro, but we can leave
+ * away the unsigned casts as our arguments are unsigned already
+ */
+ size_t nbytes = b &&
+ a >= INT32_MAX / b ? 0 : size &&
+ a*b >= INT32_MAX / size ? 0 : a * b * size;
+ void *buffer = NULL;
+#ifdef OS2_USE_PLATFORM_ALLOC
+ APIRET rc = NO_ERROR;
+
+ rc = DosAllocMem ((PPVOID)&buffer,
+ nbytes,
+#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */
+ OBJ_ANY | /* we can allocate anywhere! */
+#endif
+ PAG_READ | PAG_WRITE | PAG_COMMIT);
+ if (rc != NO_ERROR) {
+ /* should there for some reason be another error, let's return
+ * a null surface and free the buffer again, because that's
+ * how a malloc failure would look like
+ */
+ if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) {
+ DosFreeMem (buffer);
+ }
+ return NULL;
+ }
+#else
+ buffer = malloc (nbytes);
+#endif
+
+ /* This does not seem to be needed, malloc'd space is usually
+ * already zero'd out!
+ */
+ /*
+ * memset (buffer, 0x00, nbytes);
+ */
+
+ return buffer;
+}
+
+/*
+ * This function selects the free function depending on which
+ * allocation method was compiled into the library
+ */
+void _buffer_free (void *buffer)
+{
+#ifdef OS2_USE_PLATFORM_ALLOC
+ DosFreeMem (buffer);
+#else
+ free (buffer);
#endif
}
@@ -296,9 +364,9 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
ULONG ulPixels;
/* allocate temporary pixel buffer */
- pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
- surface->bitmap_info.cx,
- 3);
+ pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy,
+ surface->bitmap_info.cx,
+ 3);
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
@@ -330,7 +398,7 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
ROP_SRCCOPY,
BBO_IGNORE);
- free (pchPixBuf);
+ _buffer_free (pchPixBuf);
}
/* Restore Y inversion */
@@ -714,7 +782,7 @@ cairo_os2_surface_create (HPS hps_client_window,
local_os2_surface->bitmap_info.cBitCount = 32;
/* Allocate memory for pixels */
- local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
+ local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4);
if (!(local_os2_surface->pixels)) {
/* Not enough memory for the pixels! */
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
@@ -724,13 +792,6 @@ cairo_os2_surface_create (HPS hps_client_window,
return (cairo_surface_t *) &_cairo_surface_nil;
}
- /* This is possibly not needed, malloc'd space is
- * usually zero'd out!
- */
- /*
- memset (local_os2_surface->pixels, 0x00, swpTemp.cx * swpTemp.cy * 4);
- */
-
/* Create image surface from pixel array */
local_os2_surface->image_surface = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (local_os2_surface->pixels,
@@ -741,7 +802,7 @@ cairo_os2_surface_create (HPS hps_client_window,
if (local_os2_surface->image_surface->base.status) {
/* Could not create image surface! */
- free (local_os2_surface->pixels);
+ _buffer_free (local_os2_surface->pixels);
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
free (local_os2_surface);
@@ -784,7 +845,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
}
/* Allocate memory for new stuffs */
- pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4);
+ pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4);
if (!pchNewPixels) {
/* Not enough memory for the pixels!
* Everything remains the same!
@@ -792,13 +853,6 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
- /* This is possibly not needed, malloc'd space is usually
- * already zero'd out!
- */
- /*
- memset (pchNewPixels, 0x00, new_width * new_height * 4);
- */
-
/* Create image surface from new pixel array */
pNewImageSurface = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (pchNewPixels,
@@ -811,7 +865,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
/* Could not create image surface!
* Everything remains the same!
*/
- free (pchNewPixels);
+ _buffer_free (pchNewPixels);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@@ -823,7 +877,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
* Everything remains the same!
*/
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
- free (pchNewPixels);
+ _buffer_free (pchNewPixels);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@@ -839,7 +893,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
if (rc != NO_ERROR) {
/* Either timeout or something wrong... Exit. */
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
- free (pchNewPixels);
+ _buffer_free (pchNewPixels);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
/* Okay, grab mutex and check counter again! */
@@ -850,7 +904,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
* Everything remains the same!
*/
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
- free (pchNewPixels);
+ _buffer_free (pchNewPixels);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
}
@@ -858,7 +912,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
/* Destroy old image surface */
cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
/* Destroy old pixel buffer */
- free (local_os2_surface->pixels);
+ _buffer_free (local_os2_surface->pixels);
/* Set new image surface */
local_os2_surface->image_surface = pNewImageSurface;
/* Set new pixel buffer */
@@ -957,7 +1011,7 @@ _cairo_os2_surface_finish (void *abstract_surface)
/* Destroy old image surface */
cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
/* Destroy old pixel buffer */
- free (local_os2_surface->pixels);
+ _buffer_free (local_os2_surface->pixels);
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);