[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.
This commit is contained in:
Peter Weilbacher 2007-12-06 16:46:28 +01:00
parent be79779331
commit a7ae9c45d9

View file

@ -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);