[cairo-commit] src/cairo-os2-surface.c

Peter Weilbacher pmw at kemper.freedesktop.org
Thu Dec 6 07:53:03 PST 2007


 src/cairo-os2-surface.c |  108 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 81 insertions(+), 27 deletions(-)

New commits:
commit a7ae9c45d924effdd61390267eb216302a270d8e
Author: Peter Weilbacher <mozilla at weilbacher.org>
Date:   Thu Dec 6 16:46:28 2007 +0100

    [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.

diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 0d888ed..86ab82c 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);
 


More information about the cairo-commit mailing list