diff options
author | Peter Weilbacher <mozilla@weilbacher.org> | 2007-12-06 16:46:28 +0100 |
---|---|---|
committer | Peter Weilbacher <mozilla@weilbacher.org> | 2007-12-06 16:46:28 +0100 |
commit | a7ae9c45d924effdd61390267eb216302a270d8e (patch) | |
tree | 866ee4f5d189536bc23be2e2f6a9e2da067d548d /src/cairo-os2-surface.c | |
parent | be79779331ee29c0bfb74b728227719bb5dead6e (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.c | 108 |
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); |