/* 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; }
int clist_process_page(gx_device *dev, gx_process_page_options_t *options) { gx_device_clist *cldev = (gx_device_clist *)dev; gx_device_clist_reader *crdev = &cldev->reader; gx_device_clist_common *cdev = (gx_device_clist_common *)dev; int y; int line_count; int band_height = crdev->page_band_height; gs_int_rect band_rect; int lines_rasterized; gx_device *bdev; gx_render_plane_t render_plane; int my; int code; void *buffer = NULL; if (0 > (code = clist_close_writer_and_init_reader(cldev))) return code; if (options->init_buffer_fn) { code = options->init_buffer_fn(options->arg, dev, dev->memory, dev->width, band_height, &buffer); if (code < 0) return code; } render_plane.index = -1; for (y = 0; y < dev->height; y += lines_rasterized) { line_count = band_height; if (line_count > dev->height - y) line_count = dev->height - y; code = gdev_create_buf_device(cdev->buf_procs.create_buf_device, &bdev, cdev->target, y, &render_plane, dev->memory, &(crdev->color_usage_array[y/band_height])); if (code < 0) return code; code = clist_rasterize_lines(dev, y, line_count, bdev, &render_plane, &my); if (code >= 0) { lines_rasterized = min(code, line_count); /* Return as much of the rectangle as falls within the rasterized lines. */ band_rect.p.x = 0; band_rect.p.y = y; band_rect.q.x = dev->width; band_rect.q.y = y + lines_rasterized; if (options->process_fn) code = options->process_fn(options->arg, dev, bdev, &band_rect, buffer); } if (code >= 0 && options->output_fn) code = options->output_fn(options->arg, dev, buffer); cdev->buf_procs.destroy_buf_device(bdev); if (code < 0) break; } if (options->free_buffer_fn) { options->free_buffer_fn(options->arg, dev, dev->memory, buffer); } return code; }