1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "pipe/p_util.h"
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "draw/draw_pt.h"
39 #define CACHE_MAX 1024
40 #define FETCH_MAX 4096
41 #define DRAW_MAX (16*1024)
43 struct vcache_frontend {
44 struct draw_pt_front_end base;
45 struct draw_context *draw;
47 unsigned in[CACHE_MAX];
48 ushort out[CACHE_MAX];
50 ushort draw_elts[DRAW_MAX];
51 unsigned fetch_elts[FETCH_MAX];
56 struct draw_pt_middle_end *middle;
62 static void vcache_flush( struct vcache_frontend *vcache )
64 if (vcache->draw_count) {
65 vcache->middle->run( vcache->middle,
72 memset(vcache->in, ~0, sizeof(vcache->in));
73 vcache->fetch_count = 0;
74 vcache->draw_count = 0;
77 static void vcache_check_flush( struct vcache_frontend *vcache )
79 if ( vcache->draw_count + 6 >= DRAW_MAX ||
80 vcache->fetch_count + 4 >= FETCH_MAX )
82 vcache_flush( vcache );
87 static INLINE void vcache_elt( struct vcache_frontend *vcache,
91 unsigned idx = felt % CACHE_MAX;
93 if (vcache->in[idx] != felt) {
94 assert(vcache->fetch_count < FETCH_MAX);
96 vcache->in[idx] = felt;
97 vcache->out[idx] = (ushort)vcache->fetch_count;
98 vcache->fetch_elts[vcache->fetch_count++] = felt;
101 vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
106 static void vcache_triangle( struct vcache_frontend *vcache,
111 vcache_elt(vcache, i0, 0);
112 vcache_elt(vcache, i1, 0);
113 vcache_elt(vcache, i2, 0);
114 vcache_check_flush(vcache);
118 static void vcache_triangle_flags( struct vcache_frontend *vcache,
124 vcache_elt(vcache, i0, flags);
125 vcache_elt(vcache, i1, 0);
126 vcache_elt(vcache, i2, 0);
127 vcache_check_flush(vcache);
130 static void vcache_line( struct vcache_frontend *vcache,
134 vcache_elt(vcache, i0, 0);
135 vcache_elt(vcache, i1, 0);
136 vcache_check_flush(vcache);
140 static void vcache_line_flags( struct vcache_frontend *vcache,
145 vcache_elt(vcache, i0, flags);
146 vcache_elt(vcache, i1, 0);
147 vcache_check_flush(vcache);
151 static void vcache_point( struct vcache_frontend *vcache,
154 vcache_elt(vcache, i0, 0);
155 vcache_check_flush(vcache);
158 static void vcache_quad( struct vcache_frontend *vcache,
164 vcache_triangle( vcache, i0, i1, i3 );
165 vcache_triangle( vcache, i1, i2, i3 );
168 static void vcache_ef_quad( struct vcache_frontend *vcache,
174 vcache_triangle_flags( vcache,
175 ( DRAW_PIPE_RESET_STIPPLE |
176 DRAW_PIPE_EDGE_FLAG_0 |
177 DRAW_PIPE_EDGE_FLAG_2 ),
180 vcache_triangle_flags( vcache,
181 ( DRAW_PIPE_EDGE_FLAG_0 |
182 DRAW_PIPE_EDGE_FLAG_1 ),
186 /* At least for now, we're back to using a template include file for
187 * this. The two paths aren't too different though - it may be
188 * possible to reunify them.
190 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
191 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
192 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
193 #define POINT(vc,i0) vcache_point(vc,i0)
194 #define FUNC vcache_run_extras
195 #include "draw_pt_vcache_tmp.h"
197 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
198 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
199 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
200 #define POINT(vc,i0) vcache_point(vc,i0)
201 #define FUNC vcache_run
202 #include "draw_pt_vcache_tmp.h"
204 static void translate_uint_elts( const unsigned *src,
211 for (i = 0; i < count; i++)
212 dest[i] = (ushort)(src[i] + delta);
215 static void translate_ushort_elts( const ushort *src,
222 for (i = 0; i < count; i++)
223 dest[i] = (ushort)(src[i] + delta);
226 static void translate_ubyte_elts( const ubyte *src,
233 for (i = 0; i < count; i++)
234 dest[i] = (ushort)(src[i] + delta);
238 static enum pipe_format format_from_get_elt( pt_elt_func get_elt )
240 switch (draw->pt.user.eltSize) {
241 case 1: return PIPE_FORMAT_R8_UNORM;
242 case 2: return PIPE_FORMAT_R16_UNORM;
243 case 4: return PIPE_FORMAT_R32_UNORM;
244 default: return PIPE_FORMAT_NONE;
249 static void vcache_check_run( struct draw_pt_front_end *frontend,
252 unsigned draw_count )
254 struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
255 struct draw_context *draw = vcache->draw;
256 unsigned min_index = draw->pt.user.min_index;
257 unsigned max_index = draw->pt.user.max_index;
258 unsigned index_size = draw->pt.user.eltSize;
259 unsigned fetch_count = max_index + 1 - min_index;
260 const ushort *transformed_elts;
261 ushort *storage = NULL;
264 if (0) debug_printf("fetch_count %d draw_count %d\n", fetch_count, draw_count);
266 if (max_index == 0xffffffff ||
267 fetch_count >= FETCH_MAX ||
268 fetch_count > draw_count) {
269 if (0) debug_printf("fail\n");
274 if (min_index == 0 &&
277 transformed_elts = (const ushort *)elts;
281 storage = MALLOC( draw_count * sizeof(ushort) );
287 translate_ubyte_elts( (const ubyte *)elts,
294 translate_ushort_elts( (const ushort *)elts,
301 translate_uint_elts( (const uint *)elts,
311 transformed_elts = storage;
314 vcache->middle->run_linear_elts( vcache->middle,
315 min_index, /* start */
324 vcache_run( frontend, get_elt, elts, draw_count );
330 static void vcache_prepare( struct draw_pt_front_end *frontend,
332 struct draw_pt_middle_end *middle,
335 struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
337 if (opt & PT_PIPELINE)
339 vcache->base.run = vcache_run_extras;
343 vcache->base.run = vcache_check_run;
346 vcache->input_prim = prim;
347 vcache->output_prim = draw_pt_reduced_prim(prim);
349 vcache->middle = middle;
350 middle->prepare( middle, vcache->output_prim, opt );
356 static void vcache_finish( struct draw_pt_front_end *frontend )
358 struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
359 vcache->middle->finish( vcache->middle );
360 vcache->middle = NULL;
363 static void vcache_destroy( struct draw_pt_front_end *frontend )
369 struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
371 struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
375 vcache->base.prepare = vcache_prepare;
376 vcache->base.run = NULL;
377 vcache->base.finish = vcache_finish;
378 vcache->base.destroy = vcache_destroy;
381 memset(vcache->in, ~0, sizeof(vcache->in));
383 return &vcache->base;