86
86
dlprintf3("[l]counts: reset = %lu, found = %lu, added = %lu\n",
87
stats_cmd.tile_reset, stats_cmd.tile_found,
88
stats_cmd.tile_added);
87
stats_cmd.tile_reset, stats_cmd.tile_found,
88
stats_cmd.tile_added);
89
89
dlprintf5(" diff 2.5 = %lu, 3 = %lu, 4 = %lu, 2 = %lu, >4 = %lu\n",
90
stats_cmd_diffs[0], stats_cmd_diffs[1], stats_cmd_diffs[2],
91
stats_cmd_diffs[3], stats_cmd_diffs[4]);
90
stats_cmd_diffs[0], stats_cmd_diffs[1], stats_cmd_diffs[2],
91
stats_cmd_diffs[3], stats_cmd_diffs[4]);
92
92
dlprintf2(" same_band = %lu, other_band = %lu\n",
93
stats_cmd.same_band, stats_cmd.other_band);
93
stats_cmd.same_band, stats_cmd.other_band);
94
94
for (ci = 0; ci < 0x100; ci += 0x10) {
95
const char *const *sub = cmd_sub_op_names[ci >> 4];
98
dlprintf1("[l] %s =", cmd_op_names[ci >> 4]);
99
for (cj = ci; cj < ci + 0x10; cj += 2)
100
dprintf6("\n\t%s = %lu(%lu), %s = %lu(%lu)",
102
stats_cmd.op_counts[cj], stats_cmd.op_sizes[cj],
104
stats_cmd.op_counts[cj + 1], stats_cmd.op_sizes[cj + 1]);
106
ulong tcounts = 0, tsizes = 0;
108
for (cj = ci; cj < ci + 0x10; cj++)
109
tcounts += stats_cmd.op_counts[cj],
110
tsizes += stats_cmd.op_sizes[cj];
111
dlprintf3("[l] %s (%lu,%lu) =\n\t",
112
cmd_op_names[ci >> 4], tcounts, tsizes);
113
for (cj = ci; cj < ci + 0x10; cj++)
114
if (stats_cmd.op_counts[cj] == 0)
117
dprintf2(" %lu(%lu)", stats_cmd.op_counts[cj],
118
stats_cmd.op_sizes[cj]);
95
const char *const *sub = cmd_sub_op_names[ci >> 4];
98
dlprintf1("[l] %s =", cmd_op_names[ci >> 4]);
99
for (cj = ci; cj < ci + 0x10; cj += 2)
100
dprintf6("\n\t%s = %lu(%lu), %s = %lu(%lu)",
102
stats_cmd.op_counts[cj], stats_cmd.op_sizes[cj],
104
stats_cmd.op_counts[cj + 1], stats_cmd.op_sizes[cj + 1]);
106
ulong tcounts = 0, tsizes = 0;
108
for (cj = ci; cj < ci + 0x10; cj++)
109
tcounts += stats_cmd.op_counts[cj],
110
tsizes += stats_cmd.op_sizes[cj];
111
dlprintf3("[l] %s (%lu,%lu) =\n\t",
112
cmd_op_names[ci >> 4], tcounts, tsizes);
113
for (cj = ci; cj < ci + 0x10; cj++)
114
if (stats_cmd.op_counts[cj] == 0)
117
dprintf2(" %lu(%lu)", stats_cmd.op_counts[cj],
118
stats_cmd.op_sizes[cj]);
123
123
#endif /* DEBUG */
127
127
/* Write the commands for one band or band range. */
128
128
static int /* ret 0 all ok, -ve error code, or +1 ok w/low-mem warning */
129
129
cmd_write_band(gx_device_clist_writer * cldev, int band_min, int band_max,
130
cmd_list * pcl, gx_band_complexity_t *band_complexity, byte cmd_end)
130
cmd_list * pcl, gx_band_complexity_t *band_complexity, byte cmd_end)
132
132
const cmd_prefix *cp = pcl->head;
136
136
if (cp != 0 || cmd_end != cmd_opv_end_run) {
137
clist_file_ptr cfile = cldev->page_cfile;
138
clist_file_ptr bfile = cldev->page_bfile;
140
byte end = cmd_count_op(cmd_end, 1);
137
clist_file_ptr cfile = cldev->page_cfile;
138
clist_file_ptr bfile = cldev->page_bfile;
140
byte end = cmd_count_op(cmd_end, 1);
142
if (cfile == 0 || bfile == 0)
143
return_error(gs_error_ioerror);
144
cb.band_min = band_min;
145
cb.band_max = band_max;
146
cb.pos = cldev->page_info.io_procs->ftell(cfile);
147
clist_copy_band_complexity(&cb.band_complexity, band_complexity);
148
if_debug4('l', "[l]writing for bands (%d,%d) at %ld K %d \n",
149
band_min, band_max, (long)cb.pos, cb.band_complexity.uses_color);
150
cldev->page_info.io_procs->fwrite_chars(&cb, sizeof(cb), bfile);
152
pcl->tail->next = 0; /* terminate the list */
153
for (; cp != 0; cp = cp->next) {
142
if (cfile == 0 || bfile == 0)
143
return_error(gs_error_ioerror);
144
cb.band_min = band_min;
145
cb.band_max = band_max;
146
cb.pos = cldev->page_info.io_procs->ftell(cfile);
147
clist_copy_band_complexity(&cb.band_complexity, band_complexity);
148
if_debug4('l', "[l]writing for bands (%d,%d) at %ld K %d \n",
149
band_min, band_max, (long)cb.pos, cb.band_complexity.uses_color);
150
cldev->page_info.io_procs->fwrite_chars(&cb, sizeof(cb), bfile);
152
pcl->tail->next = 0; /* terminate the list */
153
for (; cp != 0; cp = cp->next) {
155
if ((const byte *)cp < cldev->cbuf ||
156
(const byte *)cp >= cldev->cend ||
157
cp->size > cldev->cend - (const byte *)cp
159
lprintf1("cmd_write_band error at 0x%lx\n", (ulong) cp);
160
return_error(gs_error_Fatal);
155
if ((const byte *)cp < cldev->cbuf ||
156
(const byte *)cp >= cldev->cend ||
157
cp->size > cldev->cend - (const byte *)cp
159
lprintf1("cmd_write_band error at 0x%lx\n", (ulong) cp);
160
return_error(gs_error_Fatal);
163
if_debug2('L',"[L]Wrote cmd id=%ld at %ld\n", cp->id,
164
(long)cldev->page_info.io_procs->ftell(cfile));
165
cldev->page_info.io_procs->fwrite_chars(cp + 1, cp->size, cfile);
167
pcl->head = pcl->tail = 0;
169
cldev->page_info.io_procs->fwrite_chars(&end, 1, cfile);
170
process_interrupts(cldev->memory);
171
code_b = cldev->page_info.io_procs->ferror_code(bfile);
172
code_c = cldev->page_info.io_procs->ferror_code(cfile);
174
return_error(code_b);
176
return_error(code_c);
163
if_debug2('L',"[L]Wrote cmd id=%ld at %ld\n", cp->id,
164
(long)cldev->page_info.io_procs->ftell(cfile));
165
cldev->page_info.io_procs->fwrite_chars(cp + 1, cp->size, cfile);
167
pcl->head = pcl->tail = 0;
169
cldev->page_info.io_procs->fwrite_chars(&end, 1, cfile);
170
process_interrupts(cldev->memory);
171
code_b = cldev->page_info.io_procs->ferror_code(bfile);
172
code_c = cldev->page_info.io_procs->ferror_code(cfile);
174
return_error(code_b);
176
return_error(code_c);
178
178
return code_b | code_c;
276
276
byte *dp = cldev->cnext;
278
278
if (size + cmd_headroom > cldev->cend - dp) {
279
if ((cldev->error_code =
279
if ((cldev->error_code =
280
280
cmd_write_buffer(cldev, cmd_opv_end_run)) != 0 ||
281
281
(size + cmd_headroom > cldev->cend - cldev->cnext)) {
282
if (cldev->error_code < 0)
283
cldev->error_is_retryable = 0; /* hard error */
285
/* upgrade lo-mem warning into an error */
286
if (!cldev->ignore_lo_mem_warnings)
287
cldev->error_code = gs_note_error(gs_error_VMerror);
288
cldev->error_is_retryable = 1;
293
return cmd_put_list_op(cldev, pcl, size);
282
if (cldev->error_code < 0)
283
cldev->error_is_retryable = 0; /* hard error */
285
/* upgrade lo-mem warning into an error */
286
if (!cldev->ignore_lo_mem_warnings)
287
cldev->error_code = gs_note_error(gs_error_VMerror);
288
cldev->error_is_retryable = 1;
293
return cmd_put_list_op(cldev, pcl, size);
295
295
if (cldev->ccl == pcl) { /* We're adding another command for the same band. */
296
/* Tack it onto the end of the previous one. */
297
cmd_count_add1(stats_cmd.same_band);
296
/* Tack it onto the end of the previous one. */
297
cmd_count_add1(stats_cmd.same_band);
299
if (pcl->tail->size > dp - (byte *) (pcl->tail + 1)) {
300
lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong) pcl->tail);
299
if (pcl->tail->size > dp - (byte *) (pcl->tail + 1)) {
300
lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong) pcl->tail);
303
if_debug2('L', ", to id=%ld , offset=%ld", pcl->tail->id, (long)pcl->tail->size);
304
pcl->tail->size += size;
303
if_debug2('L', ", to id=%ld , offset=%ld", pcl->tail->id, (long)pcl->tail->size);
304
pcl->tail->size += size;
306
/* Skip to an appropriate alignment boundary. */
307
/* (We assume the command buffer itself is aligned.) */
308
cmd_prefix *cp = (cmd_prefix *)
309
(dp + ((cldev->cbuf - dp) & (ARCH_ALIGN_PTR_MOD - 1)));
306
/* Skip to an appropriate alignment boundary. */
307
/* (We assume the command buffer itself is aligned.) */
308
cmd_prefix *cp = (cmd_prefix *)
309
(dp + ((cldev->cbuf - dp) & (ARCH_ALIGN_PTR_MOD - 1)));
311
cmd_count_add1(stats_cmd.other_band);
312
dp = (byte *) (cp + 1);
313
if (pcl->tail != 0) {
311
cmd_count_add1(stats_cmd.other_band);
312
dp = (byte *) (cp + 1);
313
if (pcl->tail != 0) {
315
if (pcl->tail < pcl->head ||
316
pcl->tail->size > dp - (byte *) (pcl->tail + 1)
318
lprintf1("cmd_put_list_op error at 0x%lx\n",
315
if (pcl->tail < pcl->head ||
316
pcl->tail->size > dp - (byte *) (pcl->tail + 1)
318
lprintf1("cmd_put_list_op error at 0x%lx\n",
322
pcl->tail->next = cp;
328
cp->id = cldev->ins_count;
329
if_debug1('L', ", id=%ld ", cldev->ins_count);
322
pcl->tail->next = cp;
328
cp->id = cldev->ins_count;
329
if_debug1('L', ", id=%ld ", cldev->ins_count);
332
332
cldev->cnext = dp + size;
336
/* Request a space in the buffer.
336
/* Request a space in the buffer.
337
337
Writes out the buffer if necessary.
338
338
Returns the size of available space. */
340
340
cmd_get_buffer_space(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)
342
342
if (size + cmd_headroom > cldev->cend - cldev->cnext) {
343
cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
344
if (cldev->error_code < 0) {
345
cldev->error_is_retryable = 0; /* hard error */
346
return cldev->error_code;
343
cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
344
if (cldev->error_code < 0) {
345
cldev->error_is_retryable = 0; /* hard error */
346
return cldev->error_code;
349
349
return cldev->cend - cldev->cnext - cmd_headroom;
363
363
/* Add a command for a range of bands. */
365
365
cmd_put_range_op(gx_device_clist_writer * cldev, int band_min, int band_max,
368
368
if_debug4('L', "[L]band range(%d,%d): size=%u, left=%u",
369
band_min, band_max, size, 0);
370
if (cldev->ccl != 0 &&
371
(cldev->ccl != &cldev->band_range_list ||
372
band_min != cldev->band_range_min ||
373
band_max != cldev->band_range_max)
375
if ((cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run)) != 0) {
376
if (cldev->error_code < 0)
377
cldev->error_is_retryable = 0; /* hard error */
379
/* upgrade lo-mem warning into an error */
380
cldev->error_code = gs_error_VMerror;
381
cldev->error_is_retryable = 1;
385
cldev->band_range_min = band_min;
386
cldev->band_range_max = band_max;
369
band_min, band_max, size, 0);
370
if (cldev->ccl != 0 &&
371
(cldev->ccl != &cldev->band_range_list ||
372
band_min != cldev->band_range_min ||
373
band_max != cldev->band_range_max)
375
if ((cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run)) != 0) {
376
if (cldev->error_code < 0)
377
cldev->error_is_retryable = 0; /* hard error */
379
/* upgrade lo-mem warning into an error */
380
cldev->error_code = gs_error_VMerror;
381
cldev->error_is_retryable = 1;
385
cldev->band_range_min = band_min;
386
cldev->band_range_max = band_max;
388
388
return cmd_put_list_op(cldev, &cldev->band_range_list, size);
538
536
/* If this is a tile color then send tile color type */
539
537
if (select->tile_color) {
540
code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_tile_color, 1);
538
code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_tile_color, 1);
544
542
op = select->set_op;
545
543
op_delta = select->delta_op;
546
544
if (color == gx_no_color_index) {
548
* We must handle this specially, because it may take more
549
* bytes than the color depth.
551
code = set_cmd_put_op(dp, cldev, pcls, op + cmd_no_color_index, 1);
546
* We must handle this specially, because it may take more
547
* bytes than the color depth.
549
code = set_cmd_put_op(dp, cldev, pcls, op + cmd_no_color_index, 1);
555
/* Check if the "delta" mode command can be used. */
556
int num_bytes = (cldev->clist_color_info.depth + 7) >> 3; /* clist_color_info may be different than target device
553
/* Check if the "delta" mode command can be used. */
554
int num_bytes = (cldev->clist_color_info.depth + 7) >> 3; /* clist_color_info may be different than target device
557
555
due to transparency group during clist writing phase */
558
int delta_bytes = (num_bytes + 1) / 2;
559
gx_color_index delta_offset = cmd_delta_offsets[num_bytes];
560
gx_color_index delta_mask = cmd_delta_masks[num_bytes];
561
gx_color_index delta = (diff + delta_offset) & delta_mask;
562
bool use_delta = (color == (*pcolor + delta - delta_offset));
563
int bytes_dropped = 0;
564
gx_color_index data = color;
567
* If we use the full value mode, we do not send low order bytes
568
* which are zero. Determine how many low order bytes are zero.
571
bytes_dropped = num_bytes;
574
while ((data & 0xff) == 0) {
579
/* Now send one of the two command forms */
580
if (use_delta && delta_bytes < (num_bytes - bytes_dropped)) {
581
code = set_cmd_put_op(dp, cldev, pcls,
582
op_delta, delta_bytes + 1);
586
* If we have an odd number of bytes then use extra bits for
587
* the high order three bytes of the color.
589
if ((num_bytes >= 3) && (num_bytes & 1)) {
590
data = delta >> ((num_bytes - 3) * 8);
591
dp[delta_bytes--] = (byte)(((data >> 13) & 0xf8) + ((data >> 11) & 0x07));
592
dp[delta_bytes--] = (byte)(((data >> 3) & 0xe0) + (data & 0x1f));
594
for(; delta_bytes>0; delta_bytes--) {
595
dp[delta_bytes] = (byte)((delta >> 4) + delta);
600
num_bytes -= bytes_dropped;
601
code = set_cmd_put_op(dp, cldev, pcls,
602
(byte)(op + bytes_dropped), num_bytes + 1);
605
for(; num_bytes>0; num_bytes--) {
606
dp[num_bytes] = (byte)data;
556
int delta_bytes = (num_bytes + 1) / 2;
557
gx_color_index delta_offset = cmd_delta_offsets[num_bytes];
558
gx_color_index delta_mask = cmd_delta_masks[num_bytes];
559
gx_color_index delta = (diff + delta_offset) & delta_mask;
560
bool use_delta = (color == (*pcolor + delta - delta_offset));
561
int bytes_dropped = 0;
562
gx_color_index data = color;
565
* If we use the full value mode, we do not send low order bytes
566
* which are zero. Determine how many low order bytes are zero.
569
bytes_dropped = num_bytes;
572
while ((data & 0xff) == 0) {
577
/* Now send one of the two command forms */
578
if (use_delta && delta_bytes < (num_bytes - bytes_dropped)) {
579
code = set_cmd_put_op(dp, cldev, pcls,
580
op_delta, delta_bytes + 1);
584
* If we have an odd number of bytes then use extra bits for
585
* the high order three bytes of the color.
587
if ((num_bytes >= 3) && (num_bytes & 1)) {
588
data = delta >> ((num_bytes - 3) * 8);
589
dp[delta_bytes--] = (byte)(((data >> 13) & 0xf8) + ((data >> 11) & 0x07));
590
dp[delta_bytes--] = (byte)(((data >> 3) & 0xe0) + (data & 0x1f));
592
for(; delta_bytes>0; delta_bytes--) {
593
dp[delta_bytes] = (byte)((delta >> 4) + delta);
598
num_bytes -= bytes_dropped;
599
code = set_cmd_put_op(dp, cldev, pcls,
600
(byte)(op + bytes_dropped), num_bytes + 1);
603
for(; num_bytes>0; num_bytes--) {
604
dp[num_bytes] = (byte)data;
616
613
/* Put out a command to set the tile colors. */
618
615
cmd_set_tile_colors(gx_device_clist_writer * cldev, gx_clist_state * pcls,
619
gx_color_index color0, gx_color_index color1)
616
gx_color_index color0, gx_color_index color1)
623
620
if (color0 != pcls->tile_colors[0]) {
624
code = cmd_put_color(cldev, pcls,
625
&clist_select_tile_color0,
626
color0, &pcls->tile_colors[0]);
621
code = cmd_put_color(cldev, pcls,
622
&clist_select_tile_color0,
623
color0, &pcls->tile_colors[0]);
630
627
if (color1 != pcls->tile_colors[1])
631
code = cmd_put_color(cldev, pcls,
632
&clist_select_tile_color1,
633
color1, &pcls->tile_colors[1]);
628
code = cmd_put_color(cldev, pcls,
629
&clist_select_tile_color1,
630
color1, &pcls->tile_colors[1]);
637
634
/* Put out a command to set the tile phase. */
639
636
cmd_set_tile_phase_generic(gx_device_clist_writer * cldev, gx_clist_state * pcls,
640
int px, int py, bool all_bands)
637
int px, int py, bool all_bands)
747
743
/* Get serialized list's length + try to get it into local var if it fits. */
748
744
param_length = code =
749
gs_param_list_serialize(param_list, local_buf, sizeof(local_buf));
745
gs_param_list_serialize(param_list, local_buf, sizeof(local_buf));
750
746
if (param_length > 0) {
751
/* Get cmd buffer space for serialized */
752
code = set_cmd_put_all_op(dp, cldev, cmd_opv_extend,
753
2 + sizeof(unsigned) + param_length);
757
/* write param list to cmd list: needs to all fit in cmd buffer */
758
if_debug1('l', "[l]put_params, length=%d\n", param_length);
759
dp[1] = cmd_opv_ext_put_params;
761
memcpy(dp, ¶m_length, sizeof(unsigned));
762
dp += sizeof(unsigned);
763
if (param_length > sizeof(local_buf)) {
764
int old_param_length = param_length;
766
param_length = code =
767
gs_param_list_serialize(param_list, dp, old_param_length);
768
if (param_length >= 0)
769
code = (old_param_length != param_length ?
770
gs_note_error(gs_error_unknownerror) : 0);
772
/* error serializing: back out by writing a 0-length parm list */
773
memset(dp - sizeof(unsigned), 0, sizeof(unsigned));
774
cmd_shorten_list_op(cldev, &cldev->band_range_list,
778
memcpy(dp, local_buf, param_length); /* did this when computing length */
747
/* Get cmd buffer space for serialized */
748
code = set_cmd_put_all_op(dp, cldev, cmd_opv_extend,
749
2 + sizeof(unsigned) + param_length);
753
/* write param list to cmd list: needs to all fit in cmd buffer */
754
if_debug1('l', "[l]put_params, length=%d\n", param_length);
755
dp[1] = cmd_opv_ext_put_params;
757
memcpy(dp, ¶m_length, sizeof(unsigned));
758
dp += sizeof(unsigned);
759
if (param_length > sizeof(local_buf)) {
760
int old_param_length = param_length;
762
param_length = code =
763
gs_param_list_serialize(param_list, dp, old_param_length);
764
if (param_length >= 0)
765
code = (old_param_length != param_length ?
766
gs_note_error(gs_error_unknownerror) : 0);
768
/* error serializing: back out by writing a 0-length parm list */
769
memset(dp - sizeof(unsigned), 0, sizeof(unsigned));
770
cmd_shorten_list_op(cldev, &cldev->band_range_list,
774
memcpy(dp, local_buf, param_length); /* did this when computing length */