[gs-cvs] rev 8425 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Wed Dec 5 15:39:43 PST 2007
Author: leonardo
Date: 2007-12-05 15:39:42 -0800 (Wed, 05 Dec 2007)
New Revision: 8425
Modified:
trunk/gs/src/gxclrast.c
trunk/gs/src/gxcomp.h
Log:
Fix (clist interpreter) : Skip idle compositors, step 2.
DETAILS :
The clist writer writes the 'create compositor' operation to all bands,
including ones that are not covered by a transparency.
It does so because this operation changes the number of color components.
When rendering a specific band, it frequently happens that a compositor
is created and then immediately destroyed. Such thing happens outside
the transparency bbox, and within the transparency bbox if
the band has no transparent objects. When compositor is created,
it allocates a big raster buffer and cleans it.
Due to that we observe a significant CPU time expence
when running the test case of the bug 689155.
This patch is a preparation for further improvements.
The change is algorithmically equivalent.
It implements a compositor queue for a delayed applying of compositors.
Nevertheless currently the compositors are still applied immediately
due to stubs in is_null_compositor_op, is_closing_compositor.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c 2007-12-05 16:40:41 UTC (rev 8424)
+++ trunk/gs/src/gxclrast.c 2007-12-05 23:39:42 UTC (rev 8425)
@@ -265,6 +265,51 @@
const gx_drawing_color *,
gs_logical_operation_t);
+
+static inline void
+enqueue_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last, gs_composite_t *pcomp)
+{
+ if (*ppcomp_last == NULL) {
+ pcomp->prev = NULL;
+ *ppcomp_last = *ppcomp_first = pcomp;
+ } else {
+ pcomp->prev = *ppcomp_last;
+ *ppcomp_last = pcomp;
+ }
+}
+
+static inline gs_composite_t *
+dequeue_last_compositor(gs_composite_t **ppcomp_first, gs_composite_t **ppcomp_last)
+{
+ gs_composite_t *pcomp = *ppcomp_last;
+
+ if (*ppcomp_first == *ppcomp_last)
+ *ppcomp_first = *ppcomp_last = NULL;
+ else {
+ *ppcomp_last = (*ppcomp_last)->prev;
+ }
+ return pcomp;
+}
+
+static inline void
+free_compositor(gs_composite_t *pcomp)
+{
+ /* Fixme: todo. */
+}
+
+static inline bool
+is_null_compositor_op(const byte *cbp, int *length)
+{
+ /* Fixme: todo. */
+ return false;
+}
+
+is_closing_compositor(gs_composite_t *pcomp0, gs_composite_t *pcomp1)
+{
+ /* Fixme: todo. */
+ return false;
+}
+
int
clist_playback_band(clist_playback_action playback_action,
gx_device_clist_reader *cdev, stream *s,
@@ -333,7 +378,7 @@
bool clipper_dev_open;
patch_fill_state_t pfs;
stream_state *st = s->state; /* Save because s_close resets s->state. */
- gs_composite_t *pcomp;
+ gs_composite_t *pcomp_first = NULL, *pcomp_last = NULL;
cbuf.data = (byte *)cbuf_storage;
cbuf.size = cbuf_size;
@@ -1274,15 +1319,50 @@
*/
gx_imager_setscreenphase(&imager_state,
-x0, -y0, gs_color_select_all);
- code = read_create_compositor(&cbuf, mem, &pcomp);
- if (code < 0)
- goto out;
- cbp = cbuf.ptr;
- if (pcomp != NULL) {
- code = apply_create_compositor(cdev, &imager_state, mem, pcomp, &target);
- if (code < 0)
- goto out;
- tdev = target;
+ cbp -= 2; /* Step back to simplify the cycle invariant below. */
+ for (;;) {
+ int len;
+
+ if (cbp[0] == cmd_opv_extend && cbp[1] == cmd_opv_ext_create_compositor) {
+ gs_composite_t *pcomp;
+
+ cbuf.ptr = cbp += 2;
+ code = read_create_compositor(&cbuf, mem, &pcomp);
+ if (code < 0)
+ goto out;
+ cbp = cbuf.ptr;
+ if (pcomp == NULL)
+ continue;
+ if (pcomp_last != NULL && is_closing_compositor(pcomp_last, pcomp)) {
+ /* Annigilate the 2 compositors. */
+ free_compositor(pcomp);
+ pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
+ free_compositor(pcomp);
+ } else
+ enqueue_compositor(&pcomp_first, &pcomp_last, pcomp);
+ } else if (is_null_compositor_op(cbp, &len)) {
+ cbuf.ptr = cbp += len;
+ } else if (pcomp_first != NULL) {
+ gs_composite_t *pcomp = pcomp_last, *pcomp_ahead, *pcomp_back = NULL;
+
+ /* Reverse the queue: */
+ while (pcomp != NULL) {
+ pcomp_ahead = pcomp->prev;
+ pcomp->prev = pcomp_back;
+ pcomp_back = pcomp;
+ pcomp = pcomp_ahead;
+ }
+ /* Apply and clean the queue: */
+ while (pcomp_last != NULL) {
+ pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
+ code = apply_create_compositor(cdev, &imager_state,
+ mem, pcomp, &target); /* Releases the compositor. */
+ if (code < 0)
+ goto out;
+ tdev = target;
+ }
+ break;
+ }
}
break;
case cmd_opv_ext_put_halftone:
@@ -1713,6 +1793,13 @@
ht_buff.ht_size = 0;
ht_buff.read_size = 0;
+ /* Release the compositor queue. */
+ while (pcomp_last != NULL) {
+ gs_composite_t *pcomp = dequeue_last_compositor(&pcomp_first, &pcomp_last);
+
+ free_compositor(pcomp);
+ }
+
rc_decrement(pcs, "clist_playback_band");
gx_cpath_free(&clip_path, "clist_render_band exit");
gx_path_free(&path, "clist_render_band exit");
Modified: trunk/gs/src/gxcomp.h
===================================================================
--- trunk/gs/src/gxcomp.h 2007-12-05 16:40:41 UTC (rev 8424)
+++ trunk/gs/src/gxcomp.h 2007-12-05 23:39:42 UTC (rev 8425)
@@ -148,7 +148,9 @@
#define gs_composite_common\
const gs_composite_type_t *type;\
gs_id id; /* see gscompt.h */\
- rc_header rc
+ rc_header rc; \
+ struct gs_composite_s *prev /* A queue link for clist_playback_band. */
+
struct gs_composite_s {
gs_composite_common;
};
More information about the gs-cvs
mailing list