2 * Mesa 3-D graphics library
4 * Copyright (C) 2013 LunarG, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "util/u_prim.h"
29 #include "intel_winsys.h"
31 #include "ilo_context.h"
33 #include "ilo_state.h"
34 #include "ilo_3d_pipeline_gen6.h"
35 #include "ilo_3d_pipeline_gen7.h"
36 #include "ilo_3d_pipeline.h"
39 struct sample_position
{
43 /* \see gen6_get_sample_position() */
44 static const struct sample_position sample_position_1x
[1] = {
48 static const struct sample_position sample_position_4x
[4] = {
49 { 6, 2 }, /* distance from the center is sqrt(40) */
50 { 14, 6 }, /* distance from the center is sqrt(40) */
51 { 2, 10 }, /* distance from the center is sqrt(40) */
52 { 10, 14 }, /* distance from the center is sqrt(40) */
55 static const struct sample_position sample_position_8x
[8] = {
56 { 7, 9 }, /* distance from the center is sqrt(2) */
57 { 9, 13 }, /* distance from the center is sqrt(26) */
58 { 11, 3 }, /* distance from the center is sqrt(34) */
59 { 13, 11 }, /* distance from the center is sqrt(34) */
60 { 1, 7 }, /* distance from the center is sqrt(50) */
61 { 5, 1 }, /* distance from the center is sqrt(58) */
62 { 15, 5 }, /* distance from the center is sqrt(58) */
63 { 3, 15 }, /* distance from the center is sqrt(74) */
66 struct ilo_3d_pipeline
*
67 ilo_3d_pipeline_create(struct ilo_cp
*cp
, const struct ilo_dev_info
*dev
)
69 struct ilo_3d_pipeline
*p
;
72 p
= CALLOC_STRUCT(ilo_3d_pipeline
);
79 switch (p
->dev
->gen
) {
81 ilo_3d_pipeline_init_gen6(p
);
84 ilo_3d_pipeline_init_gen7(p
);
87 assert(!"unsupported GEN");
93 p
->invalidate_flags
= ILO_3D_PIPELINE_INVALIDATE_ALL
;
95 p
->workaround_bo
= p
->cp
->winsys
->alloc_buffer(p
->cp
->winsys
,
96 "PIPE_CONTROL workaround", 4096, 0);
97 if (!p
->workaround_bo
) {
98 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
103 p
->packed_sample_position_1x
=
104 sample_position_1x
[0].x
<< 4 |
105 sample_position_1x
[0].y
;
107 /* pack into dwords */
108 for (i
= 0; i
< 4; i
++) {
109 p
->packed_sample_position_4x
|=
110 sample_position_4x
[i
].x
<< (8 * i
+ 4) |
111 sample_position_4x
[i
].y
<< (8 * i
);
113 p
->packed_sample_position_8x
[0] |=
114 sample_position_8x
[i
].x
<< (8 * i
+ 4) |
115 sample_position_8x
[i
].y
<< (8 * i
);
117 p
->packed_sample_position_8x
[1] |=
118 sample_position_8x
[4 + i
].x
<< (8 * i
+ 4) |
119 sample_position_8x
[4 + i
].y
<< (8 * i
);
126 ilo_3d_pipeline_destroy(struct ilo_3d_pipeline
*p
)
128 if (p
->workaround_bo
)
129 p
->workaround_bo
->unreference(p
->workaround_bo
);
135 handle_invalid_batch_bo(struct ilo_3d_pipeline
*p
, bool unset
)
137 if (p
->invalidate_flags
& ILO_3D_PIPELINE_INVALIDATE_BATCH_BO
) {
138 if (p
->dev
->gen
== ILO_GEN(6))
139 p
->state
.has_gen6_wa_pipe_control
= false;
142 p
->invalidate_flags
&= ~ILO_3D_PIPELINE_INVALIDATE_BATCH_BO
;
146 /* XXX move to u_prim.h */
148 prim_count(unsigned prim
, unsigned num_verts
)
152 u_trim_pipe_prim(prim
, &num_verts
);
155 case PIPE_PRIM_POINTS
:
156 num_prims
= num_verts
;
158 case PIPE_PRIM_LINES
:
159 num_prims
= num_verts
/ 2;
161 case PIPE_PRIM_LINE_LOOP
:
162 num_prims
= num_verts
;
164 case PIPE_PRIM_LINE_STRIP
:
165 num_prims
= num_verts
- 1;
167 case PIPE_PRIM_TRIANGLES
:
168 num_prims
= num_verts
/ 3;
170 case PIPE_PRIM_TRIANGLE_STRIP
:
171 case PIPE_PRIM_TRIANGLE_FAN
:
172 num_prims
= num_verts
- 2;
174 case PIPE_PRIM_QUADS
:
175 num_prims
= (num_verts
/ 4) * 2;
177 case PIPE_PRIM_QUAD_STRIP
:
178 num_prims
= (num_verts
/ 2 - 1) * 2;
180 case PIPE_PRIM_POLYGON
:
181 num_prims
= num_verts
- 2;
183 case PIPE_PRIM_LINES_ADJACENCY
:
184 num_prims
= num_verts
/ 4;
186 case PIPE_PRIM_LINE_STRIP_ADJACENCY
:
187 num_prims
= num_verts
- 3;
189 case PIPE_PRIM_TRIANGLES_ADJACENCY
:
190 /* u_trim_pipe_prim is wrong? */
193 num_prims
= num_verts
/ 6;
195 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
:
196 /* u_trim_pipe_prim is wrong? */
198 num_verts
-= (num_verts
% 2);
202 num_prims
= (num_verts
/ 2 - 2);
205 assert(!"unknown pipe prim");
214 * Emit context states and 3DPRIMITIVE.
217 ilo_3d_pipeline_emit_draw(struct ilo_3d_pipeline
*p
,
218 const struct ilo_context
*ilo
,
219 const struct pipe_draw_info
*info
,
220 int *prim_generated
, int *prim_emitted
)
222 const bool so_enabled
= (ilo
->stream_output_targets
.num_targets
> 0);
225 if (ilo
->dirty
& ILO_DIRTY_STREAM_OUTPUT_TARGETS
&&
226 so_enabled
&& !ilo
->stream_output_targets
.append_bitmask
) {
228 * We keep track of the SVBI in the driver, so that we can restore it
229 * when the HW context is invalidated (by another process). The value
230 * needs to be reset when stream output is enabled and the targets are
233 p
->state
.so_num_vertices
= 0;
235 /* on GEN7+, we need SOL_RESET to reset the SO write offsets */
236 if (p
->dev
->gen
>= ILO_GEN(7))
237 ilo_cp_set_one_off_flags(p
->cp
, INTEL_EXEC_GEN7_SOL_RESET
);
242 struct ilo_cp_jmp_buf jmp
;
245 /* we will rewind if aperture check below fails */
246 ilo_cp_setjmp(p
->cp
, &jmp
);
248 handle_invalid_batch_bo(p
, false);
251 ilo_cp_assert_no_implicit_flush(p
->cp
, true);
252 p
->emit_draw(p
, ilo
, info
);
253 ilo_cp_assert_no_implicit_flush(p
->cp
, false);
255 err
= ilo
->winsys
->check_aperture_space(ilo
->winsys
, &p
->cp
->bo
, 1);
262 ilo_cp_longjmp(p
->cp
, &jmp
);
264 if (ilo_cp_empty(p
->cp
)) {
269 /* flush and try again */
275 const int num_verts
= u_vertices_per_prim(u_reduced_prim(info
->mode
));
277 (p
->state
.so_max_vertices
- p
->state
.so_num_vertices
) / num_verts
;
278 const int generated
= prim_count(info
->mode
, info
->count
);
279 const int emitted
= MIN2(generated
, max_emit
);
281 p
->state
.so_num_vertices
+= emitted
* num_verts
;
284 *prim_generated
= generated
;
287 *prim_emitted
= emitted
;
290 p
->invalidate_flags
= 0x0;
296 * Emit PIPE_CONTROL to flush all caches.
299 ilo_3d_pipeline_emit_flush(struct ilo_3d_pipeline
*p
)
301 handle_invalid_batch_bo(p
, true);
306 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_TIMESTAMP post-sync op.
309 ilo_3d_pipeline_emit_write_timestamp(struct ilo_3d_pipeline
*p
,
310 struct intel_bo
*bo
, int index
)
312 handle_invalid_batch_bo(p
, true);
313 p
->emit_write_timestamp(p
, bo
, index
);
317 * Emit PIPE_CONTROL with PIPE_CONTROL_WRITE_DEPTH_COUNT post-sync op.
320 ilo_3d_pipeline_emit_write_depth_count(struct ilo_3d_pipeline
*p
,
321 struct intel_bo
*bo
, int index
)
323 handle_invalid_batch_bo(p
, true);
324 p
->emit_write_depth_count(p
, bo
, index
);
328 ilo_3d_pipeline_get_sample_position(struct ilo_3d_pipeline
*p
,
329 unsigned sample_count
,
330 unsigned sample_index
,
333 const struct sample_position
*pos
;
335 switch (sample_count
) {
337 assert(sample_index
< Elements(sample_position_1x
));
338 pos
= sample_position_1x
;
341 assert(sample_index
< Elements(sample_position_4x
));
342 pos
= sample_position_4x
;
345 assert(sample_index
< Elements(sample_position_8x
));
346 pos
= sample_position_8x
;
349 assert(!"unknown sample count");
356 *x
= (float) pos
[sample_index
].x
/ 16.0f
;
357 *y
= (float) pos
[sample_index
].y
/ 16.0f
;