int gs_screen_order_init_memory(gx_ht_order * porder, const gs_state * pgs, gs_screen_halftone * phsp, bool accurate, gs_memory_t * mem) { gs_matrix imat; ulong max_size = gx_ht_cache_default_bits_size(); int code; gs_lib_ctx_t *ctx = gs_lib_ctx_get_interp_instance(mem); if (phsp->frequency < 0.1) return_error(gs_error_rangecheck); gs_deviceinitialmatrix(gs_currentdevice(pgs), &imat); code = pick_cell_size(phsp, &imat, max_size, ctx->screen_min_screen_levels, accurate, &porder->params); if (code < 0) return code; gx_compute_cell_values(&porder->params); porder->screen_params.matrix = imat; porder->screen_params.max_size = max_size; return gs_screen_order_alloc(porder, mem); }
/* * Open this printer device in ASYNC (overlapped) mode. * This routine must always called by the concrete device's xx_open routine * in lieu of gdev_prn_open. */ int gdev_prn_async_write_open(gx_device_printer * pwdev, int max_raster, int min_band_height, int max_src_image_row) { gx_device *const pdev = (gx_device *) pwdev; int code; bool writer_is_open = false; gx_device_clist_writer *const pcwdev = &((gx_device_clist *) pwdev)->writer; gx_device_clist_reader *pcrdev = 0; gx_device_printer *prdev = 0; gs_memory_t *render_memory = 0; /* renderer's mem allocator */ pwdev->page_queue = 0; pwdev->bandlist_memory = 0; pwdev->async_renderer = 0; /* allocate & init render memory */ /* The big memory consumers are: */ /* - the buffer used to read images from the command list */ /* - buffer used by gx_real_default_strip_copy_rop() */ /* - line pointer tables for memory devices used in plane extraction */ /* - the halftone cache */ /* - the band rendering buffer */ /* The * 2's in the next statement are a ****** HACK ****** to deal with */ /* sandbars in the memory manager. */ if ((code = alloc_render_memory(&render_memory, pwdev->memory->non_gc_memory, RendererAllocationOverheadBytes + max_raster /* the first * 2 is not a hack */ + (max_raster + sizeof(void *) * 2) * min_band_height + max_src_image_row + gx_ht_cache_default_bits_size() * 2)) < 0) goto open_err; /* Alloc & init bandlist allocators */ /* Bandlist mem is threadsafe & common to rdr/wtr, so it's used */ /* for page queue & cmd list buffers. */ if ((code = alloc_bandlist_memory (&pwdev->bandlist_memory, pwdev->memory->non_gc_memory)) < 0) goto open_err; /* Dictate banding parameters for both renderer & writer */ /* Protect from user change, since user changing these won't be */ /* detected, ergo the necessary close/reallocate/open wouldn't happen. */ pwdev->space_params.banding_type = BandingAlways; pwdev->space_params.params_are_read_only = true; /* Make a copy of device for use as rendering device b4 opening writer */ code = gs_copydevice((gx_device **) & prdev, pdev, render_memory); pcrdev = &((gx_device_clist *) prdev)->reader; if (code < 0) goto open_err; /* -------------- Open cmd list WRITER instance of device ------- */ /* --------------------------------------------------------------- */ /* This is wrong, because it causes the same thing in the renderer */ pwdev->OpenOutputFile = 0; /* Don't open output file in writer */ /* Hack: set this vector to tell gdev_prn_open to allocate for async rendering */ pwdev->free_up_bandlist_memory = &gdev_prn_async_write_free_up_bandlist_memory; /* prevent clist writer from queuing path graphics & force it to split images */ pwdev->clist_disable_mask |= clist_disable_fill_path | clist_disable_stroke_path | clist_disable_complex_clip | clist_disable_nonrect_hl_image | clist_disable_pass_thru_params; if ((code = gdev_prn_open(pdev)) >= 0) { writer_is_open = true; /* set up constant async-specific fields in device */ reinit_printer_into_printera(pwdev); /* keep ptr to renderer device */ pwdev->async_renderer = prdev; /* Allocate the page queue, then initialize it */ /* Use bandlist memory since it's shared between rdr & wtr */ if ((pwdev->page_queue = gx_page_queue_alloc(pwdev->bandlist_memory)) == 0) code = gs_note_error(gs_error_VMerror); else /* Allocate from clist allocator since it is thread-safe */ code = gx_page_queue_init(pwdev->page_queue, pwdev->bandlist_memory); } /* ------------ Open cmd list RENDERER instance of device ------- */ /* --------------------------------------------------------------- */ if (code >= 0) { gx_semaphore_t *open_semaphore; /* Force writer's actual band params into reader's requested params */ prdev->space_params.band = pcwdev->page_info.band_params; /* copydevice has already set up prdev->memory = render_memory */ /* prdev->bandlist_memory = pwdev->bandlist_memory; */ prdev->buffer_memory = prdev->memory; /* enable renderer to accept changes to params computed by writer */ prdev->space_params.params_are_read_only = false; /* page queue is common to both devices */ prdev->page_queue = pwdev->page_queue; /* Start renderer thread & wait for its successful open of device */ if (!(open_semaphore = gx_semaphore_alloc(prdev->memory))) code = gs_note_error(gs_error_VMerror); else { gdev_prn_start_render_params thread_params; thread_params.writer_device = pwdev; thread_params.open_semaphore = open_semaphore; thread_params.open_code = 0; code = (*pwdev->printer_procs.start_render_thread) (&thread_params); if (code >= 0) gx_semaphore_wait(open_semaphore); code = thread_params.open_code; gx_semaphore_free(open_semaphore); } } /* ----- Set the recovery procedure for the mem allocator ----- */ if (code >= 0) { gs_memory_retrying_set_recover( (gs_memory_retrying_t *)pwdev->memory->non_gc_memory, prna_mem_recover, (void *)pcwdev ); } /* --------------------- Wrap up --------------------------------- */ /* --------------------------------------------------------------- */ if (code < 0) { open_err: /* error mop-up */ if (render_memory && !prdev) free_render_memory(render_memory); gdev_prn_dealloc(pwdev); if (writer_is_open) { gdev_prn_close(pdev); pwdev->free_up_bandlist_memory = 0; } } return code; }