brw_draw.c revision 2fa2dd3908c783663ca421134cde82e9b6a38a0d
1/**************************************************************************
2 *
3 * Copyright 2003 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#include <stdlib.h>
29
30#include "glheader.h"
31#include "context.h"
32#include "state.h"
33#include "api_validate.h"
34#include "enums.h"
35
36#include "brw_draw.h"
37#include "brw_defines.h"
38#include "brw_context.h"
39#include "brw_state.h"
40#include "brw_fallback.h"
41
42#include "intel_ioctl.h"
43#include "intel_batchbuffer.h"
44#include "intel_buffer_objects.h"
45
46#include "tnl/tnl.h"
47#include "vbo/vbo_context.h"
48#include "swrast/swrast.h"
49#include "swrast_setup/swrast_setup.h"
50
51#define FILE_DEBUG_FLAG DEBUG_BATCH
52
53static GLuint hw_prim[GL_POLYGON+1] = {
54   _3DPRIM_POINTLIST,
55   _3DPRIM_LINELIST,
56   _3DPRIM_LINELOOP,
57   _3DPRIM_LINESTRIP,
58   _3DPRIM_TRILIST,
59   _3DPRIM_TRISTRIP,
60   _3DPRIM_TRIFAN,
61   _3DPRIM_QUADLIST,
62   _3DPRIM_QUADSTRIP,
63   _3DPRIM_POLYGON
64};
65
66
67static const GLenum reduced_prim[GL_POLYGON+1] = {
68   GL_POINTS,
69   GL_LINES,
70   GL_LINES,
71   GL_LINES,
72   GL_TRIANGLES,
73   GL_TRIANGLES,
74   GL_TRIANGLES,
75   GL_TRIANGLES,
76   GL_TRIANGLES,
77   GL_TRIANGLES
78};
79
80
81/* When the primitive changes, set a state bit and re-validate.  Not
82 * the nicest and would rather deal with this by having all the
83 * programs be immune to the active primitive (ie. cope with all
84 * possibilities).  That may not be realistic however.
85 */
86static GLuint brw_set_prim(struct brw_context *brw, GLenum prim, GLboolean *need_flush)
87{
88   int ret;
89   if (INTEL_DEBUG & DEBUG_PRIMS)
90      _mesa_printf("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim));
91
92   /* Slight optimization to avoid the GS program when not needed:
93    */
94   if (prim == GL_QUAD_STRIP &&
95       brw->attribs.Light->ShadeModel != GL_FLAT &&
96       brw->attribs.Polygon->FrontMode == GL_FILL &&
97       brw->attribs.Polygon->BackMode == GL_FILL)
98      prim = GL_TRIANGLE_STRIP;
99
100   if (prim != brw->primitive) {
101      brw->primitive = prim;
102      brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
103
104      if (reduced_prim[prim] != brw->intel.reduced_primitive) {
105	 brw->intel.reduced_primitive = reduced_prim[prim];
106	 brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
107      }
108
109      ret = brw_validate_state(brw);
110      if (ret)
111         *need_flush = GL_TRUE;
112   }
113
114   return hw_prim[prim];
115}
116
117
118static GLuint trim(GLenum prim, GLuint length)
119{
120   if (prim == GL_QUAD_STRIP)
121      return length > 3 ? (length - length % 2) : 0;
122   else if (prim == GL_QUADS)
123      return length - length % 4;
124   else
125      return length;
126}
127
128
129static void brw_emit_prim( struct brw_context *brw,
130			   const struct _mesa_prim *prim )
131
132{
133   struct brw_3d_primitive prim_packet;
134   GLboolean need_flush = GL_FALSE;
135
136   if (INTEL_DEBUG & DEBUG_PRIMS)
137      _mesa_printf("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode),
138		   prim->start, prim->count);
139
140   prim_packet.header.opcode = CMD_3D_PRIM;
141   prim_packet.header.length = sizeof(prim_packet)/4 - 2;
142   prim_packet.header.pad = 0;
143   prim_packet.header.topology = brw_set_prim(brw, prim->mode, &need_flush);
144   prim_packet.header.indexed = prim->indexed;
145
146   prim_packet.verts_per_instance = trim(prim->mode, prim->count);
147   prim_packet.start_vert_location = prim->start;
148   prim_packet.instance_count = 1;
149   prim_packet.start_instance_location = 0;
150   prim_packet.base_vert_location = 0;
151
152   if (prim_packet.verts_per_instance) {
153      intel_batchbuffer_data( brw->intel.batch, &prim_packet,
154			      sizeof(prim_packet), LOOP_CLIPRECTS);
155   }
156
157   assert(need_flush == GL_FALSE);
158}
159
160static void brw_merge_inputs( struct brw_context *brw,
161		       const struct gl_client_array *arrays[])
162{
163   struct brw_vertex_element *inputs = brw->vb.inputs;
164   struct brw_vertex_info old = brw->vb.info;
165   GLuint i;
166
167   memset(inputs, 0, sizeof(*inputs));
168   memset(&brw->vb.info, 0, sizeof(brw->vb.info));
169
170   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
171      brw->vb.inputs[i].glarray = arrays[i];
172
173      /* XXX: metaops passes null arrays */
174      if (arrays[i]) {
175	 if (arrays[i]->StrideB != 0)
176	    brw->vb.info.varying |= 1 << i;
177
178	 brw->vb.info.sizes[i/16] |= (inputs[i].glarray->Size - 1) << ((i%16) * 2);
179      }
180   }
181
182   /* Raise statechanges if input sizes and varying have changed:
183    */
184   if (memcmp(brw->vb.info.sizes, old.sizes, sizeof(old.sizes)) != 0)
185      brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS;
186
187   if (brw->vb.info.varying != old.varying)
188      brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
189}
190
191/* XXX: could split the primitive list to fallback only on the
192 * non-conformant primitives.
193 */
194static GLboolean check_fallbacks( struct brw_context *brw,
195				  const struct _mesa_prim *prim,
196				  GLuint nr_prims )
197{
198   GLuint i;
199
200   if (!brw->intel.strict_conformance)
201      return GL_FALSE;
202
203   if (brw->attribs.Polygon->SmoothFlag) {
204      for (i = 0; i < nr_prims; i++)
205	 if (reduced_prim[prim[i].mode] == GL_TRIANGLES)
206	    return GL_TRUE;
207   }
208
209   /* BRW hardware will do AA lines, but they are non-conformant it
210    * seems.  TBD whether we keep this fallback:
211    */
212   if (brw->attribs.Line->SmoothFlag) {
213      for (i = 0; i < nr_prims; i++)
214	 if (reduced_prim[prim[i].mode] == GL_LINES)
215	    return GL_TRUE;
216   }
217
218   /* Stipple -- these fallbacks could be resolved with a little
219    * bit of work?
220    */
221   if (brw->attribs.Line->StippleFlag) {
222      for (i = 0; i < nr_prims; i++) {
223	 /* GS doesn't get enough information to know when to reset
224	  * the stipple counter?!?
225	  */
226	 if (prim[i].mode == GL_LINE_LOOP)
227	    return GL_TRUE;
228
229	 if (prim[i].mode == GL_POLYGON &&
230	     (brw->attribs.Polygon->FrontMode == GL_LINE ||
231	      brw->attribs.Polygon->BackMode == GL_LINE))
232	    return GL_TRUE;
233      }
234   }
235
236
237   if (brw->attribs.Point->SmoothFlag) {
238      for (i = 0; i < nr_prims; i++)
239	 if (prim[i].mode == GL_POINTS)
240	    return GL_TRUE;
241   }
242
243   return GL_FALSE;
244}
245
246/* May fail if out of video memory for texture or vbo upload, or on
247 * fallback conditions.
248 */
249static GLboolean brw_try_draw_prims( GLcontext *ctx,
250				     const struct gl_client_array *arrays[],
251				     const struct _mesa_prim *prim,
252				     GLuint nr_prims,
253				     const struct _mesa_index_buffer *ib,
254				     GLuint min_index,
255				     GLuint max_index )
256{
257   struct intel_context *intel = intel_context(ctx);
258   struct brw_context *brw = brw_context(ctx);
259   GLboolean retval = GL_FALSE;
260   GLuint i;
261   GLuint ib_offset;
262   dri_bo *ib_bo;
263   GLboolean force_flush = GL_FALSE;
264   int ret;
265
266   if (ctx->NewState)
267      _mesa_update_state( ctx );
268
269   brw_validate_textures( brw );
270
271   /* Bind all inputs, derive varying and size information:
272    */
273   brw_merge_inputs( brw, arrays );
274
275   /* Have to validate state quite late.  Will rebuild tnl_program,
276    * which depends on varying information.
277    *
278    * Note this is where brw->vs->prog_data.inputs_read is calculated,
279    * so can't access it earlier.
280    */
281
282   LOCK_HARDWARE(intel);
283
284   if (brw->intel.numClipRects == 0) {
285      UNLOCK_HARDWARE(intel);
286      return GL_TRUE;
287   }
288
289   {
290      /* Flush the batch if it's approaching full, so that we don't wrap while
291       * we've got validated state that needs to be in the same batch as the
292       * primitives.  This fraction is just a guess (minimal full state plus
293       * a primitive is around 512 bytes), and would be better if we had
294       * an upper bound of how much we might emit in a single
295       * brw_try_draw_prims().
296       */
297   flush:
298      if (force_flush)
299         brw->no_batch_wrap = GL_FALSE;
300
301      if (intel->batch->ptr - intel->batch->map > intel->batch->size * 3 / 4
302	/* brw_emit_prim may change the cliprect_mode to LOOP_CLIPRECTS */
303	  || intel->batch->cliprect_mode != LOOP_CLIPRECTS || (force_flush == GL_TRUE))
304	      intel_batchbuffer_flush(intel->batch);
305
306      force_flush = GL_FALSE;
307      brw->no_batch_wrap = GL_TRUE;
308
309      /* Set the first primitive early, ahead of validate_state:
310       */
311      brw_set_prim(brw, prim[0].mode, &force_flush);
312
313      /* XXX:  Need to separate validate and upload of state.
314       */
315      ret = brw_validate_state( brw );
316      if (ret) {
317         force_flush = GL_TRUE;
318         goto flush;
319      }
320
321      /* need to account for index buffer and vertex buffer */
322      if (ib) {
323         ret = brw_prepare_indices( brw, ib , &ib_bo, &ib_offset);
324         if (ret) {
325            force_flush = GL_TRUE;
326            goto flush;
327         }
328      }
329
330      ret = brw_prepare_vertices( brw, min_index, max_index);
331      if (ret < 0)
332         goto out;
333
334      if (ret > 0) {
335         force_flush = GL_TRUE;
336         goto flush;
337      }
338
339
340
341      /* Various fallback checks:
342       */
343      if (brw->intel.Fallback)
344	 goto out;
345
346      if (check_fallbacks( brw, prim, nr_prims ))
347	 goto out;
348
349      /* Upload index, vertex data:
350       */
351      if (ib)
352	brw_emit_indices( brw, ib, ib_bo, ib_offset);
353
354      brw_emit_vertices( brw, min_index, max_index);
355
356      for (i = 0; i < nr_prims; i++) {
357	 brw_emit_prim(brw, &prim[i]);
358      }
359
360      retval = GL_TRUE;
361   }
362
363 out:
364
365   brw->no_batch_wrap = GL_FALSE;
366
367   UNLOCK_HARDWARE(intel);
368
369   if (!retval)
370      DBG("%s failed\n", __FUNCTION__);
371
372   return retval;
373}
374
375static GLboolean brw_need_rebase( GLcontext *ctx,
376				  const struct gl_client_array *arrays[],
377				  const struct _mesa_index_buffer *ib,
378				  GLuint min_index )
379{
380   if (min_index == 0)
381      return GL_FALSE;
382
383   if (ib) {
384      if (!vbo_all_varyings_in_vbos(arrays))
385	 return GL_TRUE;
386      else
387	 return GL_FALSE;
388   }
389   else {
390      /* Hmm.  This isn't quite what I wanted.  BRW can actually
391       * handle the mixed case well enough that we shouldn't need to
392       * rebase.  However, it's probably not very common, nor hugely
393       * expensive to do it this way:
394       */
395      if (!vbo_all_varyings_in_vbos(arrays))
396	 return GL_TRUE;
397      else
398	 return GL_FALSE;
399   }
400}
401
402
403void brw_draw_prims( GLcontext *ctx,
404		     const struct gl_client_array *arrays[],
405		     const struct _mesa_prim *prim,
406		     GLuint nr_prims,
407		     const struct _mesa_index_buffer *ib,
408		     GLuint min_index,
409		     GLuint max_index )
410{
411   GLboolean retval;
412
413   /* Decide if we want to rebase.  If so we end up recursing once
414    * only into this function.
415    */
416   if (brw_need_rebase( ctx, arrays, ib, min_index )) {
417      vbo_rebase_prims( ctx, arrays,
418			prim, nr_prims,
419			ib, min_index, max_index,
420			brw_draw_prims );
421
422      return;
423   }
424
425
426   /* Make a first attempt at drawing:
427    */
428   retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
429
430   /* Otherwise, we really are out of memory.  Pass the drawing
431    * command to the software tnl module and which will in turn call
432    * swrast to do the drawing.
433    */
434   if (!retval) {
435       _swsetup_Wakeup(ctx);
436      _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
437   }
438}
439
440void brw_draw_init( struct brw_context *brw )
441{
442   GLcontext *ctx = &brw->intel.ctx;
443   struct vbo_context *vbo = vbo_context(ctx);
444
445   /* Register our drawing function:
446    */
447   vbo->draw_prims = brw_draw_prims;
448}
449
450void brw_draw_destroy( struct brw_context *brw )
451{
452   if (brw->vb.upload.bo != NULL) {
453      dri_bo_unreference(brw->vb.upload.bo);
454      brw->vb.upload.bo = NULL;
455   }
456}
457