[gs-cvs] rev 8132 - trunk/gs/src

leonardo at ghostscript.com leonardo at ghostscript.com
Mon Jul 16 14:24:43 PDT 2007


Author: leonardo
Date: 2007-07-16 14:24:42 -0700 (Mon, 16 Jul 2007)
New Revision: 8132

Modified:
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxdevcli.h
   trunk/gs/src/gxshade4.h
   trunk/gs/src/gxshade6.c
   trunk/gs/src/lib.mak
Log:
Banding : Extend clist language with trapezoids, linear color trapezoids and linear color triangles (continued 6).

DETAILS :

This is an initial commit for decomposition of linear color triangles
that the target device can't handle while a clist playback.

The new code is not called with practical cases
because currently we have no devices 
with an intrivial implementation of fill_linear_color_triangle.
We commit this code for future if someone will want
to implement that function in hardware with a smaller number of bits.

To force an execution of the new code
one can change this switch in gxclrast.c :

	if 1 /* Disable to debug gx_fill_triangle_small. */

We debugged the new code with setting this switch to 0.
In this case the decomposition code starts, and calls 
fill_linear_color_triangle again with same arguments
(except converting frac31 colors to 'float', 
rather it doesn't miss precision with comparefiles).
This test works fine with comparefiles.
If the device method would request a further decomposition,
an earlier debugged code works, so we didn't test it now
(Testing it with available implementations would require an additional effort
for rejecting regular triangles by the target device).

For more details see comments in code.

Note the clist playback now calls gxshade6.c .
  
EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2007-07-16 17:39:09 UTC (rev 8131)
+++ trunk/gs/src/gxclrast.c	2007-07-16 21:24:42 UTC (rev 8132)
@@ -48,6 +48,8 @@
 #include "gsserial.h"
 #include "gxdhtserial.h"
 #include "gzht.h"
+#include "gxshade.h"
+#include "gxshade4.h"
 
 extern_gx_device_halftone_list();
 extern_gx_image_type_table();
@@ -311,6 +313,7 @@
     gx_device *const orig_target = target;
     gx_device_clip clipper_dev;
     bool clipper_dev_open;
+    patch_fill_state_t pfs;
 
     cbuf.data = (byte *)cbuf_storage;
     cbuf.size = cbuf_size;
@@ -319,6 +322,7 @@
     set_cb_end(&cbuf, cbuf.data + cbuf.size);
     cbp = cbuf.end;
 
+    pfs.dev = NULL; /* Indicate "not initialized". */
     memset(&ht_buff, 0, sizeof(ht_buff));
 
 in:				/* Initialize for a new page. */
@@ -1484,18 +1488,42 @@
 					} else
 					    cc[i] = NULL;
 				    }
-				    if (options & 4)
+				    if (options & 4) {
+#					if 1 /* Disable to debug gx_fill_triangle_small. */
 					code = dev_proc(ttdev, fill_linear_color_triangle)(ttdev, &fa,
 							&left.start, &left.end, &right.start,
 							cc[0], cc[1], cc[2]);
-				    else
+#					else
+					code = 0;
+#					endif
+					if (code == 0) {
+					    /* Fixme : The target device didn't fill the trapezoid and
+					       requests a decomposition. Call a code from gxshade6.c 
+					       for subdividing into smaller triangles : */
+					    if (pfs.dev == NULL)
+						code = gx_init_patch_fill_state_for_clist(tdev, &pfs, mem);
+					    if (code >= 0) {
+						pfs.dev = ttdev;
+						pfs.rect = clip; /* fixme: eliminate 'clip'. */
+						fa.pfs = &pfs;
+						code = gx_fill_triangle_small(ttdev, &fa,
+							    &left.start, &left.end, &right.start,
+							    cc[0], cc[1], cc[2]);
+					    }
+					}
+				    } else {
 					code = dev_proc(ttdev, fill_linear_color_trapezoid)(ttdev, &fa,
 							&left.start, &left.end, &right.start, &right.end,
 							cc[0], cc[1], cc[2], cc[3]);
-				    if (code == 0) {
-					/* Fixme : The target device didn't fill the trapezoid and
-					   requests a decomposition. Call a code from gxshade6.c . */
-					code = gs_note_error(gs_error_unregistered);
+					if (code == 0) {
+					    /* Fixme : The target device didn't fill the trapezoid and
+					       requests a decomposition. 
+					       Currently we never call it with 4 colors (see gxshade6.c)
+					       and 2 colors must not return 0 - see comment to
+					       dev_t_proc_fill_linear_color_trapezoid in gxdevcli.c .
+					       Must not happen. */
+					    code = gs_note_error(gs_error_unregistered);
+					}
 				    }
 				} else
 				    code = gx_default_fill_trapezoid(ttdev, &left, &right,
@@ -1646,13 +1674,18 @@
 	gs_free_object(target->memory, target, "gxclrast discard compositor");
 	target = orig_target;
     }
-    if (code < 0)
+    if (code < 0) {
+	if (pfs.dev != NULL)
+	    term_patch_fill_state(&pfs);
 	return_error(code);
+    }
     /* Check whether we have more pages to process. */
     if (playback_action != playback_action_setup && 
 	(cbp < cbuf.end || !seofp(s))
 	)
 	goto in;
+    if (pfs.dev != NULL)
+	term_patch_fill_state(&pfs);
     return code;
 }
 

Modified: trunk/gs/src/gxdevcli.h
===================================================================
--- trunk/gs/src/gxdevcli.h	2007-07-16 17:39:09 UTC (rev 8131)
+++ trunk/gs/src/gxdevcli.h	2007-07-16 21:24:42 UTC (rev 8132)
@@ -141,6 +141,10 @@
 #  define gs_imager_state_DEFINED
 typedef struct gs_imager_state_s gs_imager_state;
 #endif
+#ifndef patch_fill_state_t_DEFINED
+#  define patch_fill_state_t_DEFINED
+typedef struct patch_fill_state_s  patch_fill_state_t;
+#endif
 
 /* We need an abstract type for the image enumeration state, */
 /* for begin[_typed]_image. */
@@ -1275,6 +1279,7 @@
       const gx_device_halftone *ht; /* Reserved for possible use in future. */
       gs_logical_operation_t lop; /* Reserved for possible use in future. */
       fixed ystart, yend; /* Only for X-independent gradients. Base coordinates of the gradient. */
+      patch_fill_state_t *pfs; /* For gx_fill_triangle_small. Clients must not change. */
 } gs_fill_attributes;
 
 /* Fill a linear color scanline. */

Modified: trunk/gs/src/gxshade4.h
===================================================================
--- trunk/gs/src/gxshade4.h	2007-07-16 17:39:09 UTC (rev 8131)
+++ trunk/gs/src/gxshade4.h	2007-07-16 21:24:42 UTC (rev 8132)
@@ -117,8 +117,13 @@
 typedef struct gs_color_index_cache_s gs_color_index_cache_t;
 #endif
 
+#ifndef patch_fill_state_t_DEFINED
+#  define patch_fill_state_t_DEFINED
+typedef struct patch_fill_state_s  patch_fill_state_t;
+#endif
+
 /* Define the common state for rendering Coons and tensor patches. */
-typedef struct patch_fill_state_s {
+struct patch_fill_state_s {
     mesh_fill_state_common;
     const gs_function_t *Function;
     int function_arg_shift;
@@ -145,7 +150,7 @@
     byte *color_stack_limit;
     gs_memory_t *memory; /* Where color_buffer is allocated. */
     gs_color_index_cache_t *pcic;
-} patch_fill_state_t;
+} ;
 
 /* Define a structure for mesh or patch vertex. */
 struct shading_vertex_s {
@@ -173,13 +178,11 @@
 
 int init_patch_fill_state(patch_fill_state_t *pfs);
 bool term_patch_fill_state(patch_fill_state_t *pfs);
+int gx_init_patch_fill_state_for_clist(gx_device *dev, patch_fill_state_t *pfs, gs_memory_t *memory);
 
 int mesh_triangle(patch_fill_state_t *pfs, 
     const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2);
 
-int small_mesh_triangle(patch_fill_state_t *pfs, 
-	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2);
-
 int mesh_padding(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1, 
 	    const patch_color_t *c0, const patch_color_t *c1);
 
@@ -204,4 +207,6 @@
 byte *reserve_colors(patch_fill_state_t *pfs, patch_color_t *c0[], int n);
 void release_colors(patch_fill_state_t *pfs, byte *ptr, int n);
 
+dev_proc_fill_linear_color_triangle(gx_fill_triangle_small);
+
 #endif /* gxshade4_INCLUDED */

Modified: trunk/gs/src/gxshade6.c
===================================================================
--- trunk/gs/src/gxshade6.c	2007-07-16 17:39:09 UTC (rev 8131)
+++ trunk/gs/src/gxshade6.c	2007-07-16 21:24:42 UTC (rev 8132)
@@ -195,6 +195,31 @@
     return true;
 }
 
+private int 
+alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
+{
+    int code;
+
+    pfs->memory = memory;
+#   if LAZY_WEDGES
+	code = wedge_vertex_list_elem_buffer_alloc(pfs);
+	if (code < 0)
+	    return code;
+#   endif
+    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
+    code = allocate_color_stack(pfs, memory);
+    if (code < 0)
+	return code;
+    if (pfs->unlinear || pcs == NULL)
+	pfs->pcic = NULL;
+    else {
+	pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pis, true);
+	if (pfs->pcic == NULL)
+	    return_error(gs_error_VMerror);
+    }
+    return 0;
+}
+
 int
 init_patch_fill_state(patch_fill_state_t *pfs)
 {
@@ -231,25 +256,8 @@
     pfs->color_stack_ptr = NULL;
     pfs->color_stack = NULL;
     pfs->color_stack_limit = NULL;
-    pfs->memory = NULL;
     pfs->unlinear = !is_linear_color_applicable(pfs);
-#   if LAZY_WEDGES
-	code = wedge_vertex_list_elem_buffer_alloc(pfs);
-	if (code < 0)
-	    return code;
-#   endif
-    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
-    code = allocate_color_stack(pfs, pfs->pis->memory);
-    if (code < 0)
-	return code;
-    if (pfs->unlinear)
-	pfs->pcic = NULL;
-    else {
-	pfs->pcic = gs_color_index_cache_create(pfs->pis->memory, pcs, pfs->dev, pfs->pis, true);
-	if (pfs->pcic == NULL)
-	    return_error(gs_error_VMerror);
-    }
-    return 0;
+    return alloc_patch_fill_memory(pfs, pfs->pis->memory, pcs);
 }
 
 bool
@@ -627,7 +635,7 @@
 wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t *pfs)
 {
     const int max_level = LAZY_WEDGES_MAX_LEVEL;
-    gs_memory_t *memory = pfs->pis->memory;
+    gs_memory_t *memory = pfs->memory;
 
     /* We have 'max_level' levels, each of which divides 1 or 3 sides.
        LAZY_WEDGES stores all 2^level divisions until 
@@ -653,7 +661,7 @@
 void
 wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
 {
-    gs_memory_t *memory = pfs->pis->memory;
+    gs_memory_t *memory = pfs->memory;
 
     gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer, 
 		"wedge_vertex_list_elem_buffer_free");
@@ -958,6 +966,7 @@
 
 	    for (j = 0; j < cinfo->num_components; j++)
 		frac_values[j] = (frac31)c->cc.paint.values[j];
+	    pdevc->type = &gx_dc_type_data_pure;
 	}
     }
     return 0;
@@ -1675,26 +1684,29 @@
 	return 2;
     if (!wedge) {
 	const gs_color_space *cs = pfs->direct_space;
-	float s0, s1, s2, s01, s012;
 
-	s0 = function_linearity(pfs, p0->c, p1->c);
-	if (s0 > pfs->smoothness)
-	    return 1;
-	s1 = function_linearity(pfs, p1->c, p2->c);
-	if (s1 > pfs->smoothness)
-	    return 1;
-	s2 = function_linearity(pfs, p2->c, p0->c);
-	if (s2 > pfs->smoothness)
-	    return 1;
-	/* fixme: check an inner color ? */
-	s01 = max(s0, s1);
-	s012 = max(s01, s2);
-	code = cs_is_linear(cs, pfs->pis, pfs->dev, 
-			    &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL, pfs->smoothness - s012);
-	if (code < 0)
-	    return code;
-	if (code == 0)
-	    return 1;
+	if (cs != NULL) {
+	    float s0, s1, s2, s01, s012;
+
+	    s0 = function_linearity(pfs, p0->c, p1->c);
+	    if (s0 > pfs->smoothness)
+		return 1;
+	    s1 = function_linearity(pfs, p1->c, p2->c);
+	    if (s1 > pfs->smoothness)
+		return 1;
+	    s2 = function_linearity(pfs, p2->c, p0->c);
+	    if (s2 > pfs->smoothness)
+		return 1;
+	    /* fixme: check an inner color ? */
+	    s01 = max(s0, s1);
+	    s012 = max(s01, s2);
+	    code = cs_is_linear(cs, pfs->pis, pfs->dev, 
+				&p0->c->cc, &p1->c->cc, &p2->c->cc, NULL, pfs->smoothness - s012);
+	    if (code < 0)
+		return code;
+	    if (code == 0)
+		return 1;
+	}
     }
     {   gx_device *pdev = pfs->dev;
 	frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
@@ -2603,7 +2615,7 @@
     return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
 }
 
-int 
+private int 
 small_mesh_triangle(patch_fill_state_t *pfs, 
 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
 {
@@ -2623,6 +2635,91 @@
     return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
 }
 
+int 
+gx_init_patch_fill_state_for_clist(gx_device *dev, patch_fill_state_t *pfs, gs_memory_t *memory)
+{
+    int i;
+
+    pfs->dev = dev;
+    pfs->pis = NULL;
+    pfs->direct_space = NULL;
+    pfs->num_components = dev->color_info.num_components;
+    /* pfs->cc_max_error[GS_CLIENT_COLOR_MAX_COMPONENTS] unused */
+    pfs->pshm = NULL;
+    pfs->Function = NULL;
+    pfs->function_arg_shift = 0;
+    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
+    pfs->n_color_args = 1; /* unused. */
+    pfs->max_small_coord = 0; /* unused. */
+    pfs->wedge_vertex_list_elem_buffer = NULL; /* fixme */
+    pfs->free_wedge_vertex = NULL; /* fixme */
+    pfs->wedge_vertex_list_elem_count = 0; /* fixme */
+    pfs->wedge_vertex_list_elem_count_max = 0; /* fixme */
+    for (i = 0; i < pfs->num_components; i++)
+	pfs->color_domain.paint.values[i] = (float)0x7fffffff;
+    /* decomposition_limit must be same as one in init_patch_fill_state */
+    pfs->decomposition_limit = float2fixed(min(pfs->dev->HWResolution[0], 
+					       pfs->dev->HWResolution[1]) / 72);
+    pfs->fixed_flat = 0; /* unused */
+    pfs->smoothness = 0; /* unused */
+    pfs->maybe_self_intersecting = false; /* unused */
+    pfs->monotonic_color = true;
+    pfs->linear_color = true;
+    pfs->unlinear = false; /* Because it is used when fill_linear_color_triangle was called. */
+    pfs->inside = false;
+    pfs->color_stack_size = 0;
+    pfs->color_stack_step = dev->color_info.num_components;
+    pfs->color_stack_ptr = NULL; /* fixme */
+    pfs->color_stack = NULL; /* fixme */
+    pfs->color_stack_limit = NULL; /* fixme */
+    pfs->pcic = NULL; /* Will do someday. */
+    return alloc_patch_fill_memory(pfs, memory, NULL);
+}
+
+/* A method for filling a small triangle that the device can't handle. 
+   Used by clist playback. */
+int 
+gx_fill_triangle_small(gx_device *dev, const gs_fill_attributes *fa,
+	const gs_fixed_point *p0, const gs_fixed_point *p1,
+	const gs_fixed_point *p2,
+	const frac31 *c0, const frac31 *c1, const frac31 *c2)
+{
+    patch_fill_state_t *pfs = fa->pfs;
+    patch_color_t c[3];
+    shading_vertex_t p[3];
+    int i;
+
+    /* pfs->rect = *fa->clip; unused ? */
+    p[0].p = *p0;
+    p[1].p = *p1;
+    p[2].p = *p2;
+    p[0].c = &c[0];
+    p[1].c = &c[1];
+    p[2].c = &c[2];
+    c[0].t[0] = c[0].t[1] = c[1].t[0] = c[1].t[1] = c[2].t[0] = c[2].t[1] = 0; /* Dummy - not used. */
+    for (i = 0; i < dev->color_info.num_components; i++) {
+	c[0].cc.paint.values[i] = (float)c0[i];
+	c[1].cc.paint.values[i] = (float)c1[i];
+	c[2].cc.paint.values[i] = (float)c2[i];
+    }
+    /* fixme: the cycle above converts frac31 values into floats.
+       We don't like this because (1) it misses lower bits,
+       and (2) fixed point values can be faster on some platforms.
+       We could fix it with coding a template for small_mesh_triangle
+       and its callees until patch_color_to_device_color_inline.
+    */
+    /* fixme : this function is called from gxclrast.c
+       after dev->procs.fill_linear_color_triangle returns 0 - "subdivide".
+       After few moments small_mesh_triangle indirectly calls
+       same function with same arguments as a part of
+       try_device_linear_color in triangle_by_4.
+       Obviusly it will return zero again.
+       Actually we don't need the second call, 
+       so optimize with skipping the second call.
+     */
+    return small_mesh_triangle(pfs, &p[0], &p[1], &p[2]);
+}
+
 private int
 mesh_triangle_rec(patch_fill_state_t *pfs, 
 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)

Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak	2007-07-16 17:39:09 UTC (rev 8131)
+++ trunk/gs/src/lib.mak	2007-07-16 21:24:42 UTC (rev 8132)
@@ -1631,7 +1631,7 @@
 
 clbase1_=$(GLOBJ)gxclist.$(OBJ) $(GLOBJ)gxclbits.$(OBJ) $(GLOBJ)gxclpage.$(OBJ)
 clbase2_=$(GLOBJ)gxclrast.$(OBJ) $(GLOBJ)gxclread.$(OBJ) $(GLOBJ)gxclrect.$(OBJ)
-clbase3_=$(GLOBJ)gxclutil.$(OBJ) $(GLOBJ)gsparams.$(OBJ)
+clbase3_=$(GLOBJ)gxclutil.$(OBJ) $(GLOBJ)gsparams.$(OBJ) $(GLOBJ)gxshade6.$(OBJ)
 # gxclrect.c requires rop_proc_table, so we need gsroptab here.
 clbase4_=$(GLOBJ)gsroptab.$(OBJ) $(GLOBJ)stream.$(OBJ)
 clpath_=$(GLOBJ)gxclimag.$(OBJ) $(GLOBJ)gxclpath.$(OBJ) $(GLOBJ)gxdhtserial.$(OBJ)
@@ -1678,7 +1678,7 @@
  $(gxpaint_h) $(gxhttile_h) $(gxiparam_h) $(gximask_h)\
  $(gzpath_h) $(gxcpath_h) $(gzacpath_h)\
  $(stream_h) $(strimpl_h) $(gxcomp_h)\
- $(gsserial_h) $(gxdhtserial_h) $(gzht_h)
+ $(gsserial_h) $(gxdhtserial_h) $(gzht_h) $(gxshade_h) $(gxshade4_h)
 	$(GLCC) $(GLO_)gxclrast.$(OBJ) $(C_) $(GLSRC)gxclrast.c
 
 $(GLOBJ)gxclread.$(OBJ) : $(GLSRC)gxclread.c $(GXERR)\



More information about the gs-cvs mailing list