1 /**************************************************************************
3 * Copyright 2003 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 **************************************************************************/
29 #include "util/u_prim.h"
30 #include "util/u_upload_mgr.h"
33 #include "brw_defines.h"
34 #include "brw_context.h"
35 #include "brw_state.h"
36 #include "brw_debug.h"
37 #include "brw_screen.h"
39 #include "brw_batchbuffer.h"
42 static uint32_t prim_to_hw_prim
[PIPE_PRIM_POLYGON
+1] = {
57 /* When the primitive changes, set a state bit and re-validate. Not
58 * the nicest and would rather deal with this by having all the
59 * programs be immune to the active primitive (ie. cope with all
60 * possibilities). That may not be realistic however.
62 static int brw_set_prim(struct brw_context
*brw
, unsigned prim
)
65 if (BRW_DEBUG
& DEBUG_PRIMS
)
66 debug_printf("PRIM: %s\n", u_prim_name(prim
));
68 if (prim
!= brw
->primitive
) {
69 unsigned reduced_prim
;
71 brw
->primitive
= prim
;
72 brw
->state
.dirty
.brw
|= BRW_NEW_PRIMITIVE
;
74 reduced_prim
= u_reduced_prim(prim
);
75 if (reduced_prim
!= brw
->reduced_primitive
) {
76 brw
->reduced_primitive
= reduced_prim
;
77 brw
->state
.dirty
.brw
|= BRW_NEW_REDUCED_PRIMITIVE
;
81 return prim_to_hw_prim
[prim
];
86 static int brw_emit_prim(struct brw_context
*brw
,
92 struct brw_3d_primitive prim_packet
;
95 prim_packet
.header
.opcode
= CMD_3D_PRIM
;
96 prim_packet
.header
.length
= sizeof(prim_packet
)/4 - 2;
97 prim_packet
.header
.pad
= 0;
98 prim_packet
.header
.topology
= hw_prim
;
99 prim_packet
.header
.indexed
= indexed
;
101 prim_packet
.verts_per_instance
= count
;
102 prim_packet
.start_vert_location
= start
;
104 prim_packet
.start_vert_location
+= brw
->ib
.start_vertex_offset
;
105 prim_packet
.instance_count
= 1;
106 prim_packet
.start_instance_location
= 0;
107 prim_packet
.base_vert_location
= 0; // prim->basevertex; XXX: add this to gallium
110 /* If we're set to always flush, do it before and after the primitive emit.
111 * We want to catch both missed flushes that hurt instruction/state cache
112 * and missed flushes of the render cache as it heads to other parts of
113 * the besides the draw code.
116 BEGIN_BATCH(1, IGNORE_CLIPRECTS
);
117 OUT_BATCH((CMD_MI_FLUSH
<< 16) | BRW_FLUSH_STATE_CACHE
);
120 if (prim_packet
.verts_per_instance
) {
121 ret
= brw_batchbuffer_data( brw
->batch
, &prim_packet
,
122 sizeof(prim_packet
), LOOP_CLIPRECTS
);
127 BEGIN_BATCH(1, IGNORE_CLIPRECTS
);
128 OUT_BATCH((CMD_MI_FLUSH
<< 16) | BRW_FLUSH_STATE_CACHE
);
136 /* May fail if out of video memory for texture or vbo upload, or on
137 * fallback conditions.
140 try_draw_range_elements(struct brw_context
*brw
,
141 struct pipe_buffer
*index_buffer
,
143 unsigned start
, unsigned count
)
147 ret
= brw_validate_state(brw
);
151 /* Check that we can fit our state in with our existing batchbuffer, or
154 ret
= brw
->sws
->check_aperture_space(brw
->sws
,
155 brw
->state
.validated_bos
,
156 brw
->state
.validated_bo_count
);
160 ret
= brw_upload_state(brw
);
164 ret
= brw_emit_prim(brw
, start
, count
, index_buffer
!= NULL
, hw_prim
);
168 if (brw
->flags
.always_flush_batch
)
169 brw_context_flush( brw
);
176 brw_draw_range_elements(struct pipe_context
*pipe
,
177 struct pipe_buffer
*index_buffer
,
181 unsigned mode
, unsigned start
, unsigned count
)
183 struct brw_context
*brw
= brw_context(pipe
);
187 hw_prim
= brw_set_prim(brw
, mode
);
189 if (BRW_DEBUG
& DEBUG_PRIMS
)
190 debug_printf("PRIM: %s %d %d\n", u_prim_name(mode
), start
, count
);
192 /* Potentially trigger upload of new index buffer.
194 * XXX: do we need to go through state validation to achieve this?
195 * Could just call upload code directly.
197 if (brw
->curr
.index_buffer
!= index_buffer
) {
198 pipe_buffer_reference( &brw
->curr
.index_buffer
, index_buffer
);
199 brw
->state
.dirty
.mesa
|= PIPE_NEW_INDEX_BUFFER
;
202 /* XXX: do we really care?
204 if (brw
->curr
.min_index
!= min_index
||
205 brw
->curr
.max_index
!= max_index
)
207 brw
->curr
.min_index
= min_index
;
208 brw
->curr
.max_index
= max_index
;
209 brw
->state
.dirty
.mesa
|= PIPE_NEW_INDEX_RANGE
;
213 /* Make a first attempt at drawing:
215 ret
= try_draw_range_elements(brw
, index_buffer
, hw_prim
, start
, count
);
217 /* Otherwise, flush and retry:
220 brw_context_flush( brw
);
221 ret
= try_draw_range_elements(brw
, index_buffer
, hw_prim
, start
, count
);
229 brw_draw_elements(struct pipe_context
*pipe
,
230 struct pipe_buffer
*index_buffer
,
233 unsigned start
, unsigned count
)
235 return brw_draw_range_elements( pipe
, index_buffer
,
243 brw_draw_arrays(struct pipe_context
*pipe
, unsigned mode
,
244 unsigned start
, unsigned count
)
246 return brw_draw_elements(pipe
, NULL
, 0, mode
, start
, count
);
251 boolean
brw_draw_init( struct brw_context
*brw
)
253 /* Register our drawing function:
255 brw
->base
.draw_arrays
= brw_draw_arrays
;
256 brw
->base
.draw_elements
= brw_draw_elements
;
257 brw
->base
.draw_range_elements
= brw_draw_range_elements
;
259 /* Create helpers for uploading data in user buffers:
261 brw
->vb
.upload_vertex
= u_upload_create( brw
->base
.screen
,
264 PIPE_BUFFER_USAGE_VERTEX
);
265 if (brw
->vb
.upload_vertex
== NULL
)
268 brw
->vb
.upload_index
= u_upload_create( brw
->base
.screen
,
271 PIPE_BUFFER_USAGE_INDEX
);
272 if (brw
->vb
.upload_index
== NULL
)
278 void brw_draw_cleanup( struct brw_context
*brw
)
280 u_upload_destroy( brw
->vb
.upload_vertex
);
281 u_upload_destroy( brw
->vb
.upload_index
);
283 bo_reference(&brw
->ib
.bo
, NULL
);