1/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29#include "draw/draw_pipe.h"
30#include "util/u_math.h"
31#include "util/u_memory.h"
32#include "util/u_pack_color.h"
33
34#include "i915_context.h"
35#include "i915_reg.h"
36#include "i915_state.h"
37#include "i915_batch.h"
38
39
40
41/**
42 * Primitive emit to hardware.  No support for vertex buffers or any
43 * nice fast paths.
44 */
45struct setup_stage {
46   struct draw_stage stage; /**< This must be first (base class) */
47
48   struct i915_context *i915;
49};
50
51
52
53/**
54 * Basically a cast wrapper.
55 */
56static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
57{
58   return (struct setup_stage *)stage;
59}
60
61
62/**
63 * Extract the needed fields from vertex_header and emit i915 dwords.
64 * Recall that the vertices are constructed by the 'draw' module and
65 * have a couple of slots at the beginning (1-dword header, 4-dword
66 * clip pos) that we ignore here.
67 */
68static INLINE void
69emit_hw_vertex( struct i915_context *i915,
70                const struct vertex_header *vertex)
71{
72   const struct vertex_info *vinfo = &i915->current.vertex_info;
73   uint i;
74   uint count = 0;  /* for debug/sanity */
75
76   assert(!i915->dirty);
77
78   for (i = 0; i < vinfo->num_attribs; i++) {
79      const uint j = vinfo->attrib[i].src_index;
80      const float *attrib = vertex->data[j];
81      switch (vinfo->attrib[i].emit) {
82      case EMIT_1F:
83         OUT_BATCH( fui(attrib[0]) );
84         count++;
85         break;
86      case EMIT_2F:
87         OUT_BATCH( fui(attrib[0]) );
88         OUT_BATCH( fui(attrib[1]) );
89         count += 2;
90         break;
91      case EMIT_3F:
92         OUT_BATCH( fui(attrib[0]) );
93         OUT_BATCH( fui(attrib[1]) );
94         OUT_BATCH( fui(attrib[2]) );
95         count += 3;
96         break;
97      case EMIT_4F:
98         OUT_BATCH( fui(attrib[0]) );
99         OUT_BATCH( fui(attrib[1]) );
100         OUT_BATCH( fui(attrib[2]) );
101         OUT_BATCH( fui(attrib[3]) );
102         count += 4;
103         break;
104      case EMIT_4UB:
105         OUT_BATCH( pack_ub4(float_to_ubyte( attrib[0] ),
106                             float_to_ubyte( attrib[1] ),
107                             float_to_ubyte( attrib[2] ),
108                             float_to_ubyte( attrib[3] )) );
109         count += 1;
110         break;
111      case EMIT_4UB_BGRA:
112         OUT_BATCH( pack_ub4(float_to_ubyte( attrib[2] ),
113                             float_to_ubyte( attrib[1] ),
114                             float_to_ubyte( attrib[0] ),
115                             float_to_ubyte( attrib[3] )) );
116         count += 1;
117         break;
118      default:
119         assert(0);
120      }
121   }
122   assert(count == vinfo->size);
123}
124
125
126
127static INLINE void
128emit_prim( struct draw_stage *stage,
129	   struct prim_header *prim,
130	   unsigned hwprim,
131	   unsigned nr )
132{
133   struct i915_context *i915 = setup_stage(stage)->i915;
134   unsigned vertex_size;
135   unsigned i;
136
137   if (i915->dirty)
138      i915_update_derived( i915 );
139
140   if (i915->hardware_dirty)
141      i915_emit_hardware_state( i915 );
142
143   /* need to do this after validation! */
144   vertex_size = i915->current.vertex_info.size * 4; /* in bytes */
145   assert(vertex_size >= 12); /* never smaller than 12 bytes */
146
147   if (!BEGIN_BATCH( 1 + nr * vertex_size / 4)) {
148      FLUSH_BATCH(NULL);
149
150      /* Make sure state is re-emitted after a flush:
151       */
152      i915_emit_hardware_state( i915 );
153
154      if (!BEGIN_BATCH( 1 + nr * vertex_size / 4)) {
155	 assert(0);
156	 return;
157      }
158   }
159
160   /* Emit each triangle as a single primitive.  I told you this was
161    * simple.
162    */
163   OUT_BATCH(_3DPRIMITIVE |
164	     hwprim |
165	     ((4 + vertex_size * nr)/4 - 2));
166
167   for (i = 0; i < nr; i++)
168      emit_hw_vertex(i915, prim->v[i]);
169}
170
171
172static void
173setup_tri( struct draw_stage *stage, struct prim_header *prim )
174{
175   emit_prim( stage, prim, PRIM3D_TRILIST, 3 );
176}
177
178
179static void
180setup_line(struct draw_stage *stage, struct prim_header *prim)
181{
182   emit_prim( stage, prim, PRIM3D_LINELIST, 2 );
183}
184
185
186static void
187setup_point(struct draw_stage *stage, struct prim_header *prim)
188{
189   emit_prim( stage, prim, PRIM3D_POINTLIST, 1 );
190}
191
192
193static void setup_flush( struct draw_stage *stage, unsigned flags )
194{
195}
196
197static void reset_stipple_counter( struct draw_stage *stage )
198{
199}
200
201static void render_destroy( struct draw_stage *stage )
202{
203   FREE( stage );
204}
205
206
207/**
208 * Create a new primitive setup/render stage.  This gets plugged into
209 * the 'draw' module's pipeline.
210 */
211struct draw_stage *i915_draw_render_stage( struct i915_context *i915 )
212{
213   struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
214
215   setup->i915 = i915;
216   setup->stage.draw = i915->draw;
217   setup->stage.point = setup_point;
218   setup->stage.line = setup_line;
219   setup->stage.tri = setup_tri;
220   setup->stage.flush = setup_flush;
221   setup->stage.reset_stipple_counter = reset_stipple_counter;
222   setup->stage.destroy = render_destroy;
223
224   return &setup->stage;
225}
226