[gs-cvs] rev 8197 - trunk/gs/src
ray at ghostscript.com
ray at ghostscript.com
Mon Aug 20 10:10:51 PDT 2007
Author: ray
Date: 2007-08-20 10:10:51 -0700 (Mon, 20 Aug 2007)
New Revision: 8197
Modified:
trunk/gs/src/gdevwts.c
Log:
Use the color lookup cache in wtsimdi_contone_get_bits_rectangle.
This results in a 6% overall performance improvement on the 12
performance test files, and up to a 38% improvement on WW2KA122.prn
Also clean up the MSVC and gcc warnings. Customer #951.
DETAILS:
There is a note about the allocation of cmyk_buffer relying on
the alignment when using gs_malloc. The note also describes the
method to remove this reliance on the alignment assumption.
EXPECTED DIFFERENCES:
None. The wtsimdi device is not tested, but I did test with the
12 customer performance test files.
Modified: trunk/gs/src/gdevwts.c
===================================================================
--- trunk/gs/src/gdevwts.c 2007-08-17 20:54:32 UTC (rev 8196)
+++ trunk/gs/src/gdevwts.c 2007-08-20 17:10:51 UTC (rev 8197)
@@ -23,6 +23,7 @@
#include "string_.h"
#include "gdevprn.h"
+#include "gdevmem.h"
#include "gsdevice.h"
#include "gxfrac.h"
#include "gsht.h"
@@ -353,7 +354,6 @@
wtscmyk_print_page(gx_device_printer *pdev, FILE *prn_stream)
{
gx_device_wts *wdev = (gx_device_wts *)pdev;
- gx_device_wtsimdi *idev = (gx_device_wtsimdi *)pdev;
int cmyk_bytes = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
/* Output bytes have to be padded to 16 bits. */
int y;
@@ -362,9 +362,9 @@
int code = 0;
int pbm_bytes;
int n_planes = pdev->color_info.num_components;
- byte *dst;
+ byte *dst = NULL;
FILE *ostream[4] = {0};
- int i, unused_color_cache_slots;
+ int i;
/* Initialize the wts halftones. */
code = wts_init_halftones(wdev, n_planes);
@@ -375,15 +375,6 @@
code = GS_NOTE_ERROR(pdev->memory, gs_error_VMerror);
goto out;
}
- /* allocate 1 more for sytems that return NULL if requested count is 0 */
- idev->color_cache = (cached_color *)gs_malloc(idev->memory, COLOR_CACHE_SIZE + 1,
- sizeof(cached_color), "wtscmyk_print_page(color_cache)");
-#ifdef DEBUG
- idev->color_cache_hit = idev->color_cache_collision =
- idev->color_is_current = idev->cache_fill_empty = 0;
-#endif
- for (i=0; i<COLOR_CACHE_SIZE; i++) /* clear cache to empty */
- idev->color_cache[i].color_index = gx_no_color_index;
pbm_bytes = (pdev->width + 7) >> 3;
dst = gs_malloc(pdev->memory, pbm_bytes * n_planes, 1,
"wtscmyk_print_page");
@@ -424,19 +415,8 @@
fwrite(dst + i * pbm_bytes, 1, pbm_bytes, ostream[i]);
}
out:
-#ifdef DEBUG
- for (i=0,unused_color_cache_slots=0; i<COLOR_CACHE_SIZE; i++)
- if (idev->color_cache[i].color_index == gx_no_color_index)
- unused_color_cache_slots++;
- if_debug5(':',"wtscmyk_print_page color cache stats: current=%ld, hits=%ld,"
- " collisions=%ld, fill=%ld, unused_slots=%d\n",
- idev->color_is_current, idev->color_cache_hit, idev->color_cache_collision,
- idev->cache_fill_empty, unused_color_cache_slots);
-#endif
/* Clean up... */
gs_free(pdev->memory, cmyk_line, cmyk_bytes, 1, "wtscmyk_print_page(in)");
- gs_free(pdev->memory, idev->color_cache, COLOR_CACHE_SIZE + 1, sizeof(cached_color),
- "wtscmyk_print_page(color_cache)");
gs_free(pdev->memory, dst, pbm_bytes, 1, "wtscmyk_print_page");
for (i = 1; i < n_planes; i++) {
/* Don't close ostream[0], because gdev_prn_close will. */
@@ -473,7 +453,7 @@
wtsimdi_open_device(gx_device *dev)
{
gx_device_wtsimdi *idev = (gx_device_wtsimdi*)dev;
- int code;
+ int i, code;
icColorSpaceSignature ins, outs;
int inn, outn;
@@ -492,7 +472,7 @@
wtsimdi_create_buf_device;
/* Open and read profile */
- fp = new_icmFileStd_name(LINK_ICC_NAME, "rb");
+ fp = new_icmFileStd_name((char *)LINK_ICC_NAME, (char *)"rb");
if (!fp)
return gs_throw1(-1, "could not open file '%s'", LINK_ICC_NAME);
@@ -535,7 +515,14 @@
idev->icco = icco;
idev->luo = luo;
idev->mdo = mdo;
- idev->color_cache = NULL;
+ /* allocate at least 1 for sytems that return NULL if requested count is 0 */
+ idev->color_cache = (cached_color *)gs_malloc(idev->memory, max(COLOR_CACHE_SIZE, 1),
+ sizeof(cached_color), "wtsimdi_open_device(color_cache)");
+ if (idev->color_cache == NULL) {
+ return_error(gs_error_VMerror);
+ }
+ for (i=0; i<COLOR_CACHE_SIZE; i++) /* clear cache to empty */
+ idev->color_cache[i].color_index = gx_no_color_index;
idev->current_color.color_index = gx_no_color_index;
/* guarantee the device bands */
@@ -557,7 +544,8 @@
idev->luo->del(idev->luo);
idev->icco->del(idev->icco);
idev->fp->del(idev->fp);
-
+ gs_free(dev->memory, idev->color_cache, COLOR_CACHE_SIZE,
+ sizeof(cached_color), "wtsimdi_close_device(color_cache)");
return gdev_prn_close(dev);
}
@@ -620,13 +608,12 @@
((mdev->target) ? (gx_device_wts *)(mdev->target)
: (gx_device_wts *)dev);
wts_cooked_halftone * wch = idev->wcooked;
- int n_planes = 4;
int code, comp_value;
int halftoned_bytes = (idev-> width + 7) >> 3;
int width_padded, imax;
- byte * dst, * base, halftoned_data;
+ byte * dst, * base;
byte * samples;
- uint raster, plane_ix, bit_loc, xi;
+ uint raster, plane_ix;
int first_byte, end_x;
fit_fill(dev, x, y, w, h);
@@ -725,13 +712,12 @@
((mdev->target) ? (gx_device_wts *)(mdev->target)
: (gx_device_wts *)dev);
wts_cooked_halftone * wch = idev->wcooked;
- int n_planes = 4;
int code, comp_value;
int halftoned_bytes = (idev-> width + 7) >> 3;
int width_padded, imax;
- byte * dst, * base, halftoned_data;
+ byte * dst, * base;
byte * samples;
- uint raster, plane_ix, bit_loc, xi;
+ uint raster, plane_ix;
int first_byte, end_x;
const byte *src;
int sshift;
@@ -849,6 +835,7 @@
* GB_HALFTONED to the parameter options. This will tell the buffer
* device to halftone the data (if it is not already halftoned).
*/
+int
wtsimdi_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
{ /*
* Hand off to get_bits_rectangle, being careful to avoid a
@@ -918,43 +905,38 @@
int width = dev->width;
int n_planes = 4;
int r_last = -1, g_last = -1, b_last = -1, r, g, b;
- int c, m, y, k, x;
- double rgb[3];
- double cmyk[4];
+ int x;
byte * src = params->data[0];
- byte * cmyk_buffer = gs_malloc(dev->memory,
- (width + 7) * n_planes, 1,
+ /* Note that the following relies on objects being allocated to
+ * at least a 4-byte boundary for efficiency on x86 and to prevent
+ * alignment errors on CPU's that gripe about it. We know this is
+ * true due to object headers requiring alignment. In the future
+ * if we want to remove this invariant, we can use 'obj_align_mod'
+ * to allocate a slightly larger buffer and offset 'cmyk_data'
+ * to the proper alignment within the buffer.
+ */
+ uint32_t * cmyk_buffer = gs_malloc(dev->memory,
+ (width + 7), sizeof(uint32_t),
"wtsimdi_contone_get_bits(cmyk_buffer)");
- byte * cmyk_data = cmyk_buffer;
+ uint32_t* cmyk_data = cmyk_buffer;
if (cmyk_data == NULL)
return_error(gs_error_VMerror);
- /*
- */
+
for (x = 0; x < width; x++) {
r = *src++;
g = *src++;
b = *src++;
if (r != r_last || g != g_last || b != b_last) {
+ gx_color_index color = (((r<<8) | g) << 8) | b;
+
r_last = r, g_last = g, b_last = b;
- rgb[0] = r * (1 / 255.0);
- rgb[1] = g * (1 / 255.0);
- rgb[2] = b * (1 / 255.0);
- code = idev->luo->lookup(idev->luo, cmyk, rgb);
- if (code > 1)
- return_error(gs_error_unknownerror);
- c = cmyk[0] * 255 + 0.5;
- m = cmyk[1] * 255 + 0.5;
- y = cmyk[2] * 255 + 0.5;
- k = cmyk[3] * 255 + 0.5;
+ wtsimdi_resolve_one(idev, color);
}
- *cmyk_data++ = c;
- *cmyk_data++ = m;
- *cmyk_data++ = y;
- *cmyk_data++ = k;
+ *cmyk_data++ = (uint32_t)idev->current_color.cmyk;
}
wts_halftone_line_8(idev->wcooked, original_y, width, n_planes,
- idev->band_offset_x, idev->band_offset_y, buffer, cmyk_buffer);
+ idev->band_offset_x, idev->band_offset_y, buffer, (const byte *)cmyk_buffer);
params->data[0] = buffer;
gs_free(dev->memory, cmyk_buffer, halftoned_bytes * n_planes, 1,
"wtsimdi_print_page(halftoned_data)");
@@ -971,7 +953,6 @@
const gx_render_plane_t *render_plane, gs_memory_t *mem,
gx_band_complexity_t *band_complexity)
{
- gx_device_printer *ptarget = (gx_device_printer *)target;
int code = gx_default_create_buf_device(pbdev, target,
render_plane, mem, band_complexity);
/* Now set our custom device procedures. */
@@ -1067,8 +1048,7 @@
byte * halftoned_data;
byte * halftoned_buffer = NULL;
int halftoned_bytes, y;
- int i, code = 0;
- int unused_color_cache_slots;
+ int code = 0;
int width = pdev->width;
int height = pdev->height;
dev_proc_get_bits((*save_get_bits)) = dev_proc(pdev, get_bits);
@@ -1098,20 +1078,17 @@
code = GS_NOTE_ERROR(pdev->memory, gs_error_VMerror);
goto cleanup;
}
- /* allocate 1 more for sytems that return NULL if requested count is 0 */
- idev->color_cache = (cached_color *)gs_malloc(idev->memory, COLOR_CACHE_SIZE + 1,
- sizeof(cached_color), "wtscmyk_print_page(color_cache)");
#ifdef DEBUG
+ /* Collect stats on each page. With the allocation now done once in 'open' the
+ * statistics won't be the same if other pages have been printed */
idev->color_cache_hit = idev->color_cache_collision =
idev->color_is_current = idev->cache_fill_empty = 0;
#endif
- for (i=0; i<COLOR_CACHE_SIZE; i++) /* clear cache to empty */
- idev->color_cache[i].color_index = gx_no_color_index;
/* Initialize output file header. */
if (!output_is_nul) {
fprintf(prn_stream, "P6\n%d %d\n", width, height);
- fprintf(prn_stream, "# Image generated by %s %d.%02d (device=wtsimdi)\n",
+ fprintf(prn_stream, "# Image generated by %s %ld.%02ld (device=wtsimdi)\n",
gs_program_name(), gs_revision_number() / 100,
gs_revision_number() % 100);
fprintf(prn_stream, "%d\n", 255);
@@ -1132,6 +1109,9 @@
cleanup:
if (idev->color_cache != NULL) {
#ifdef DEBUG
+ {
+ int i, unused_color_cache_slots;
+
for (i=0,unused_color_cache_slots=0; i<COLOR_CACHE_SIZE; i++)
if (idev->color_cache[i].color_index == gx_no_color_index)
unused_color_cache_slots++;
@@ -1141,9 +1121,8 @@
idev->color_is_current, idev->color_cache_hit,
idev->color_cache_collision, idev->cache_fill_empty,
unused_color_cache_slots);
+ }
#endif
- gs_free(pdev->memory, idev->color_cache, COLOR_CACHE_SIZE,
- sizeof(cached_color), "wtscmyk_print_page(color_cache)");
}
if (halftoned_buffer != NULL)
gs_free(pdev->memory, halftoned_buffer, halftoned_bytes * n_planes, 1,
More information about the gs-cvs
mailing list