mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 14:38:13 +02:00
[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:
parent
be79779331
commit
a7ae9c45d9
1 changed files with 81 additions and 27 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue