1 /* Copyright (C) 2001-2006 Artifex Software, Inc. 2 All Rights Reserved. 3 4 This software is provided AS-IS with no warranty, either express or 5 implied. 6 7 This software is distributed under license and may not be copied, modified 8 or distributed except as expressly authorized under the terms of that 9 license. Refer to licensing information at http://www.artifex.com/ 10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, 11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. 12 */ 13 14 /* $Id: gdevprna.h 8022 2007-06-05 22:23:38Z giles $ */ 15 /* Generic asynchronous printer driver support */ 16 17 /* Initial version 2/1/1998 by John Desrosiers (soho@crl.com) */ 18 /* 7/28/98 ghost@aladdin.com - Updated to Ghostscript coding standards. */ 19 20 #ifndef gdevprna_INCLUDED 21 # define gdevprna_INCLUDED 22 23 # include "gdevprn.h" 24 # include "gxsync.h" 25 26 /* 27 * General 28 * ------- 29 * Async drivers actually create two separate instances of the device at 30 * the same time. The first (the writer instance) is only used in the 31 * interpretation operation; it feeds rendering commands into the command 32 * lists. The second device instance is used only for rendering the 33 * commands placed into the command list by the writer. 34 35 * The writer builds a command list for an entire page; the command list 36 * is only queued for rendering once a page's command list is completely 37 * built. The only exception to this rule is when the interpreter runs 38 * out of memory, or when no free command list memory is available. In 39 * such cases, the interpreter queues a "partial page" consisting of all 40 * command list data written so far, plus a command indicating that the 41 * page description is not complete. After queuing the partial page, the 42 * interpereter waits until the rendering process has freed enough 43 * command list memory to enable the interpreter to proceed. 44 45 * To avoid deadlocks when the system runs out of memory, special 46 * memory allocation provisions are made on both the writer and 47 * renderer sides. On the writer side, enough "reserve" bandlist 48 * memory is set aside at startup time to cover the needs of queuing a 49 * partial page to the renderer. The renderer operates out of a fixed 50 * memory space; that way, it can always complete rendering pages with 51 * the memory it has. To this end, the writer protects the renderer 52 * from consuming unbounded amounts of memory by a) never putting 53 * complex paths into the command list, b) pre-clipping any output 54 * unless the clip path consists of a single rectangle, c) never putting 55 * high-level images into the clip path unless the image in question 56 * meets some very stringent requirements, such as only being rotated by 57 * even multiples of 90 degrees and having source-image data rows which 58 * fit into the command buffer in one piece. These restrictions are what 59 * dictate the "restricted bandlist format." 60 61 * Note that the renderer's instance of the device driver uses the 62 * renderer's memory. That implies that it must also operate in a small, 63 * fixed amount of memory, and must do all memory allocation using the 64 * memory allocator pointed to by the render device's ->memory member. 65 66 * Opening the Device 67 * ------------------ 68 * The writer instance is opened first. This occurs when the system 69 * calls the "standard" open procedure via the device's procedure 70 * vector. The driver must implement the open function, but must call 71 * down to gdev_prn_async_write_open instead of calling down to 72 * gdev_prn_open. Before calling down to gdev_prn_async_write_open, the 73 * driver must: 74 * a - init several procedure vectors, to wit: start_render_thread, 75 * buffer_page, print_page_copies, 76 * b - init space_params.band.BandWidth, space_params.band.BandHeight, 77 * space_params.BufferSpace (see extended comments in gdevasyn.c 78 * for details on computing appropriate values). 79 * c - if it implements those functions, the driver must init the 80 * procedure vectors for: put_params, get_hardware_params, 81 * output_page, open_render_device. 82 * Notice that there are two procedure vectors: the usual std_procs, and 83 * the printer-specific printer_procs. 84 85 * Since partial page support imposes extra requirements on drivers, 86 * such support can be disabled by zeroing out (in the async writer open 87 * routine, after calling down to gdev_prn_async_write_open) the 88 * free_up_bandlist_memory member of the driver structure. Doing so 89 * will, of course, cause interpretation to fail if memory runs out. 90 91 * Once the driver calls down to gdev_prn_async_write_open, the async 92 * support logic will create a second instance of the driver for 93 * rendering, but will not open it just yet. Instead, the async logic 94 * will attempt to synchronize the two device instances. 95 96 * Synchrnonizing the instances 97 * ---------------------------- 98 * While still in the gdev_prn_async_write_open routine, the async logic 99 * will call printer_procs.start_render_thread (which the driver is 100 * required to implement). start_render_thread must somehow either start a new 101 * thread or rendez-vous with an existing thread for use in rendering, 102 * then return. start_render_thread must also have caused the render thread 103 * to call gdev_prn_async_render_thread, passing it as an argument a magic 104 * cookie passed to start_render_thread. start_render_thread will only 105 * return once the device has been closed and all renering has been 106 * completed. 107 108 * The render device will be opened on the render device's thread, by 109 * calling printer_procs.open_render_device. 110 111 * Rendering Operation 112 * ------------------- 113 * During rendering, the device will not see rendering operations -- the 114 * first "rendering" operations the driver will see is when the renderer 115 * instance's print_page_copies or buffer_page routines get called. In 116 * both cases, the appropriate routine must then perform get_bits calls 117 * on the async logic in order to retrieve rendered bits, then transmit 118 * them to the appropriate device buffers. 119 120 * The complication that is introduced is that which is related to partial 121 * pages: A buffer_page call instructs the driver to grab the rendered bits, 122 * but to keep the rendered bits available for later instead of marking on 123 * media. This implies that a buffer_page call opens a context where 124 * subsequent buffer_page's and print_page_copies' must first initialize the 125 * rendering buffers with the previous rendering results before calling 126 * get_bits. The first print_page_copies closes the context that was opened 127 * by the initial buffer_page -- the driver must go back to normal rendering 128 * until a new buffer_page comes along. 129 */ 130 131 /* -------------- Type declarations --------------- */ 132 133 /* typedef is in gdevprn.h */ 134 /* typedef struct gdev_prn_start_render_params_s gdev_prn_start_render_params;*/ 135 struct gdev_prn_start_render_params_s { 136 gx_device_printer *writer_device;/* writer dev that points to render dev */ 137 gx_semaphore_t *open_semaphore; /* signal this once open_code is set */ 138 int open_code; /* RETURNS status of open of reader device */ 139 }; 140 141 /* -------- Macros used to initialize render-specific structures ------ */ 142 143 #define init_async_render_procs(xpdev, xstart_render_thread,\ 144 xbuffer_page, xprint_page_copies)\ 145 BEGIN\ 146 (xpdev)->printer_procs.start_render_thread = (xstart_render_thread);\ 147 (xpdev)->printer_procs.buffer_page = (xbuffer_page);\ 148 (xpdev)->printer_procs.print_page_copies = (xprint_page_copies);\ 149 END 150 151 /* -------------- Global procedure declarations --------- */ 152 153 /* Open this printer device in ASYNC (overlapped) mode. 154 * 155 * This routine is always called by the concrete device's xx_open routine 156 * in lieu of gdev_prn_open. 157 */ 158 int gdev_prn_async_write_open(gx_device_printer *pdev, int max_raster, 159 int min_band_height, int max_src_image_row); 160 161 /* Open the render portion of a printer device in ASYNC (overlapped) mode. 162 * 163 * This routine is always called by concrete device's xx_open_render_device 164 * in lieu of gdev_prn_open. 165 */ 166 int gdev_prn_async_render_open(gx_device_printer *prdev); 167 168 /* 169 * Must be called by async device driver implementation (see 170 * gdevprna.h under "Synchronizing the Instances"). This is the 171 * rendering loop, which requires its own thread for as long as 172 * the device is open. This proc only returns after the device is closed. 173 */ 174 int /* rets 0 ok, -ve error code */ 175 gdev_prn_async_render_thread(gdev_prn_start_render_params *); 176 177 #endif /* gdevprna_INCLUDED */ 178