Ejemplo n.º 1
0
/* This is also exported for teardown after background printing */
void
teardown_device_and_mem_for_thread(gx_device *dev, gp_thread_id thread_id, bool bg_print)
{
    gx_device_clist_common *thread_cdev = (gx_device_clist_common *)dev;
    gx_device_clist_reader *thread_crdev = (gx_device_clist_reader *)dev;
    gs_memory_t *thread_memory = dev->memory;

    /* First finish the thread */
    gp_thread_finish(thread_id);

    if (bg_print) {
        /* we are cleaning up a background printing thread, so we clean up similarly to */
        /* what is done  by clist_finish_page, but without re-opening the clist files.  */
        clist_teardown_render_threads(dev);	/* we may have used multiple threads */
        /* free the thread's icc_table since this was not done by clist_finish_page */
        clist_free_icc_table(thread_crdev->icc_table, thread_memory);
        thread_crdev->icc_table = NULL;
        /* NB: gdev_prn_free_memory below will free the color_usage_array */
    } else {
        /* make sure this doesn't get freed by gdev_prn_free_memory below */
        ((gx_device_clist_reader *)thread_cdev)->color_usage_array = NULL;
    }
    rc_decrement(thread_crdev->icc_cache_cl, "teardown_render_thread");
    thread_crdev->icc_cache_cl = NULL;
    /*
     * Free the BufferSpace, close the band files, optionally unlinking them.
     * We unlink the files if this call is cleaning up from bg printing.
     * Note that the BufferSpace is freed using 'ppdev->buf' so the 'data'
     * pointer doesn't need to be the one that the thread started with
     */
    /* If this thread was being used for background printing and NumRenderingThreads > 0 */
    /* the clist_setup_render_threads may have already closed these files                */
    if (thread_cdev->page_info.cfile != NULL)
        thread_cdev->page_info.io_procs->fclose(thread_cdev->page_info.bfile, thread_cdev->page_info.bfname, bg_print);
    if (thread_cdev->page_info.bfile != NULL)
        thread_cdev->page_info.io_procs->fclose(thread_cdev->page_info.cfile, thread_cdev->page_info.cfname, bg_print);
    thread_cdev->do_not_open_or_close_bandfiles = true; /* we already closed the files */

    gdev_prn_free_memory((gx_device *)thread_cdev);
    /* Free the device copy this thread used.  Note that the
       deviceN stuff if was allocated and copied earlier for the device
       will be freed with this call and the icc_struct ref count will be decremented. */
    gs_free_object(thread_memory, thread_cdev, "clist_teardown_render_threads");
#ifdef DEBUG
    dmprintf(thread_memory, "rendering thread ending memory state...\n");
    gs_memory_chunk_dump_memory(thread_memory);
    dmprintf(thread_memory, "                                    memory dump done.\n");
#endif
    gs_memory_chunk_release(thread_memory);
}
Ejemplo n.º 2
0
static int
clist_process_page_mt(gx_device *dev, gx_process_page_options_t *options)
{
    gx_device_printer *pdev = (gx_device_printer *)dev;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_clist_reader *crdev = &cldev->reader;
    int band_height = crdev->page_info.band_params.BandHeight;
    int band;
    int num_bands = (dev->height + band_height-1)/band_height;
    int code;
    int reverse = !!(options->options & GX_PROCPAGE_BOTTOM_UP);

    /* This page might not want multiple threads */
    /* Also we don't support plane extraction using multiple threads */
    if (pdev->num_render_threads_requested < 1)
        return clist_process_page(dev, options);

    if ((code = clist_close_writer_and_init_reader(cldev)) < 0)
        return code;	/* can't recover from this */

    /* Haven't done any rendering yet, try to set up the threads */
    if (clist_setup_render_threads(dev, reverse ? dev->height-1 : 0, options) < 0)
        /* problem setting up the threads, revert to single threaded */
        return clist_process_page(dev, options);

    if (reverse)
    {
        for (band = num_bands-1; band > 0; band--)
        {
            code = clist_get_band_from_thread(dev, band, options);
            if (code < 0)
                goto free_thread_out;
        }
    }
    else
    {
        for (band = 0; band < num_bands; band++)
        {
            code = clist_get_band_from_thread(dev, band, options);
            if (code < 0)
                goto free_thread_out;
        }
    }

    /* Always free up thread stuff before exiting*/
free_thread_out:
    clist_teardown_render_threads(dev);
    return code;
}
Ejemplo n.º 3
0
/* rendering adjacent to the first band (forward or backward) */
static int
clist_get_bits_rect_mt(gx_device *dev, const gs_int_rect * prect,
			 gs_get_bits_params_t *params, gs_int_rect **unread)
{
    gx_device_printer *pdev = (gx_device_printer *)dev;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_clist_common *cdev = (gx_device_clist_common *)dev;
    gx_device_clist_reader *crdev = &cldev->reader;
    gs_memory_t *mem = cdev->bandlist_memory;
    gs_get_bits_options_t options = params->options;
    int y = prect->p.y;
    int end_y = prect->q.y;
    int line_count = end_y - y;
    int band_height = crdev->page_info.band_params.BandHeight;
    int band = y / band_height;
    gs_int_rect band_rect;
    int lines_rasterized;
    gx_device *bdev;
    byte *mdata;
    uint raster = bitmap_raster(dev->width * dev->color_info.depth);
    int my;
    int code = 0;

    /* This page might not want multiple threads */
    /* Also we don't support plane extraction using multiple threads */
    if (pdev->num_render_threads_requested < 1 || (options & GB_SELECT_PLANES))
	return clist_get_bits_rectangle(dev, prect, params, unread);

    if (prect->p.x < 0 || prect->q.x > dev->width ||
	y < 0 || end_y > dev->height
	)
	return_error(gs_error_rangecheck);
    if (line_count <= 0 || prect->p.x >= prect->q.x)
	return 0;

    if (crdev->ymin < 0) {
	if ((code = clist_close_writer_and_init_reader(cldev)) < 0)
	    return code;
	if (clist_setup_render_threads(dev, y) < 0) 
	    /* problem setting up the threads, revert to single threaded */
	    return clist_get_bits_rectangle(dev, prect, params, unread);
    }
    else {
	if (crdev->render_threads == NULL) {
            /* If we get here with with ymin >=0, it's because we closed the threads */
	    /* while doing a page due to an error. Use single threaded mode.         */
	    return clist_get_bits_rectangle(dev, prect, params, unread);
	}
    }
    /* If we already have the band's data, just return it */
    if (y < crdev->ymin || end_y > crdev->ymax)
	code = clist_get_band_from_thread(dev, band);
    if (code < 0)
	goto free_thread_out;
    mdata = crdev->data + crdev->page_tile_cache_size;
    if ((code = gdev_create_buf_device(cdev->buf_procs.create_buf_device,
				  &bdev, cdev->target, y, NULL,
				  mem, clist_get_band_complexity(dev,y))) < 0 ||
	(code = crdev->buf_procs.setup_buf_device(bdev, mdata, raster, NULL,
			    y - crdev->ymin, line_count, crdev->ymax - crdev->ymin)) < 0)
	goto free_thread_out;

    lines_rasterized = min(band_height, line_count);
    /* Return as much of the rectangle as falls within the rasterized lines. */
    band_rect = *prect;
    band_rect.p.y = 0;
    band_rect.q.y = lines_rasterized;
    code = dev_proc(bdev, get_bits_rectangle)
	(bdev, &band_rect, params, unread);
    cdev->buf_procs.destroy_buf_device(bdev);
    if (code < 0)
	goto free_thread_out;

    /* Note that if called via 'get_bits', the line count will always be 1 */
    if (lines_rasterized == line_count) {
	return code;		
    }

/***** TODO: Handle the below with data from the threads *****/
    /*
     * We'll have to return the rectangle in pieces.  Force GB_RETURN_COPY
     * rather than GB_RETURN_POINTER, and require all subsequent pieces to
     * use the same values as the first piece for all of the other format
     * options.  If copying isn't allowed, or if there are any unread
     * rectangles, punt.
     */
    if (!(options & GB_RETURN_COPY) || code > 0)
	return gx_default_get_bits_rectangle(dev, prect, params, unread);
    options = params->options;
    if (!(options & GB_RETURN_COPY)) {
	/* Redo the first piece with copying. */
	params->options = options =
	    (params->options & ~GB_RETURN_ALL) | GB_RETURN_COPY;
	lines_rasterized = 0;
    }
    {
	gs_get_bits_params_t band_params;
	uint raster = gx_device_raster(bdev, true);

	code = gdev_create_buf_device(cdev->buf_procs.create_buf_device,
				      &bdev, cdev->target, y, NULL,
				      mem, clist_get_band_complexity(dev, y));
	if (code < 0)
	    return code;
	band_params = *params;
	while ((y += lines_rasterized) < end_y) {
	    /* Increment data pointer by lines_rasterized. */
	    if (band_params.data)
		band_params.data[0] += raster * lines_rasterized;
	    line_count = end_y - y;
	    code = clist_rasterize_lines(dev, y, line_count, bdev, NULL, &my);
	    if (code < 0)
		break;
	    lines_rasterized = min(code, line_count);
	    band_rect.p.y = my;
	    band_rect.q.y = my + lines_rasterized;
	    code = dev_proc(bdev, get_bits_rectangle)
		(bdev, &band_rect, &band_params, unread);
	    if (code < 0)
		break;
	    params->options = options = band_params.options;
	    if (lines_rasterized == line_count)
		break;
	}
	cdev->buf_procs.destroy_buf_device(bdev);
    }
    return code;

/* Free up thread stuff */
free_thread_out:
    clist_teardown_render_threads(dev);
    return code;
}