2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "draw/draw_context.h"
27 #include "draw/draw_vertex.h"
28 #include "draw/draw_pipe.h"
29 #include "draw/draw_vbuf.h"
30 #include "draw/draw_private.h"
32 #include "nouveau/nv_object.xml.h"
33 #include "nv30-40_3d.xml.h"
34 #include "nv30_context.h"
35 #include "nv30_format.h"
38 struct vbuf_render base
;
39 struct nv30_context
*nv30
;
41 struct pipe_transfer
*transfer
;
42 struct pipe_resource
*buffer
;
46 struct vertex_info vertex_info
;
48 struct nouveau_heap
*vertprog
;
49 uint32_t vtxprog
[16][4];
55 static INLINE
struct nv30_render
*
56 nv30_render(struct vbuf_render
*render
)
58 return (struct nv30_render
*)render
;
61 static const struct vertex_info
*
62 nv30_render_get_vertex_info(struct vbuf_render
*render
)
64 return &nv30_render(render
)->vertex_info
;
68 nv30_render_allocate_vertices(struct vbuf_render
*render
,
69 ushort vertex_size
, ushort nr_vertices
)
71 struct nv30_render
*r
= nv30_render(render
);
72 struct nv30_context
*nv30
= r
->nv30
;
74 r
->length
= vertex_size
* nr_vertices
;
76 if (r
->offset
+ r
->length
>= render
->max_vertex_buffer_bytes
) {
77 pipe_resource_reference(&r
->buffer
, NULL
);
78 r
->buffer
= pipe_buffer_create(&nv30
->screen
->base
.base
,
79 PIPE_BIND_VERTEX_BUFFER
, 0,
80 render
->max_vertex_buffer_bytes
);
91 nv30_render_map_vertices(struct vbuf_render
*render
)
93 struct nv30_render
*r
= nv30_render(render
);
94 char *map
= pipe_buffer_map(&r
->nv30
->base
.pipe
, r
->buffer
,
96 PIPE_TRANSFER_UNSYNCHRONIZED
, &r
->transfer
);
97 return map
+ r
->offset
;
101 nv30_render_unmap_vertices(struct vbuf_render
*render
,
102 ushort min_index
, ushort max_index
)
104 struct nv30_render
*r
= nv30_render(render
);
105 pipe_buffer_unmap(&r
->nv30
->base
.pipe
, r
->transfer
);
109 nv30_render_set_primitive(struct vbuf_render
*render
, unsigned prim
)
111 struct nv30_render
*r
= nv30_render(render
);
113 r
->prim
= nv30_prim_gl(prim
);
117 nv30_render_draw_elements(struct vbuf_render
*render
,
118 const ushort
*indices
, uint count
)
120 struct nv30_render
*r
= nv30_render(render
);
121 struct nv30_context
*nv30
= r
->nv30
;
122 struct nouveau_pushbuf
*push
= nv30
->screen
->base
.pushbuf
;
125 BEGIN_NV04(push
, NV30_3D(VTXBUF(0)), r
->vertex_info
.num_attribs
);
126 for (i
= 0; i
< r
->vertex_info
.num_attribs
; i
++) {
127 PUSH_RESRC(push
, NV30_3D(VTXBUF(i
)), BUFCTX_VTXTMP
,
128 nv04_resource(r
->buffer
), r
->offset
+ r
->vtxptr
[i
],
129 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
, 0, 0);
132 if (!nv30_state_validate(nv30
, FALSE
))
135 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
136 PUSH_DATA (push
, r
->prim
);
139 BEGIN_NV04(push
, NV30_3D(VB_ELEMENT_U32
), 1);
140 PUSH_DATA (push
, *indices
++);
145 unsigned npush
= MIN2(count
, NV04_PFIFO_MAX_PACKET_LEN
);
148 BEGIN_NI04(push
, NV30_3D(VB_ELEMENT_U16
), npush
);
150 PUSH_DATA(push
, (indices
[1] << 16) | indices
[0]);
155 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
156 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
157 PUSH_RESET(push
, BUFCTX_VTXTMP
);
161 nv30_render_draw_arrays(struct vbuf_render
*render
, unsigned start
, uint nr
)
163 struct nv30_render
*r
= nv30_render(render
);
164 struct nv30_context
*nv30
= r
->nv30
;
165 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
166 unsigned fn
= nr
>> 8, pn
= nr
& 0xff;
167 unsigned ps
= fn
+ (pn
? 1 : 0);
170 BEGIN_NV04(push
, NV30_3D(VTXBUF(0)), r
->vertex_info
.num_attribs
);
171 for (i
= 0; i
< r
->vertex_info
.num_attribs
; i
++) {
172 PUSH_RESRC(push
, NV30_3D(VTXBUF(i
)), BUFCTX_VTXTMP
,
173 nv04_resource(r
->buffer
), r
->offset
+ r
->vtxptr
[i
],
174 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
, 0, 0);
177 if (!nv30_state_validate(nv30
, FALSE
))
180 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
181 PUSH_DATA (push
, r
->prim
);
183 BEGIN_NI04(push
, NV30_3D(VB_VERTEX_BATCH
), ps
);
185 PUSH_DATA (push
, 0xff000000 | start
);
190 PUSH_DATA (push
, ((pn
- 1) << 24) | start
);
192 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
193 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
194 PUSH_RESET(push
, BUFCTX_VTXTMP
);
198 nv30_render_release_vertices(struct vbuf_render
*render
)
200 struct nv30_render
*r
= nv30_render(render
);
201 r
->offset
+= r
->length
;
204 static const struct {
211 [TGSI_SEMANTIC_POSITION
] = { EMIT_4F
, INTERP_PERSPECTIVE
, 0, 0, 0x00000000 },
212 [TGSI_SEMANTIC_COLOR
] = { EMIT_4F
, INTERP_LINEAR
, 3, 1, 0x00000001 },
213 [TGSI_SEMANTIC_BCOLOR
] = { EMIT_4F
, INTERP_LINEAR
, 1, 3, 0x00000004 },
214 [TGSI_SEMANTIC_FOG
] = { EMIT_4F
, INTERP_PERSPECTIVE
, 5, 5, 0x00000010 },
215 [TGSI_SEMANTIC_PSIZE
] = { EMIT_1F_PSIZE
, INTERP_POS
, 6, 6, 0x00000020 },
216 [TGSI_SEMANTIC_GENERIC
] = { EMIT_4F
, INTERP_PERSPECTIVE
, 8, 7, 0x00004000 }
220 vroute_add(struct nv30_render
*r
, uint attrib
, uint sem
, uint
*idx
)
222 struct pipe_screen
*pscreen
= &r
->nv30
->screen
->base
.base
;
223 struct nv30_fragprog
*fp
= r
->nv30
->fragprog
.program
;
224 struct vertex_info
*vinfo
= &r
->vertex_info
;
225 enum pipe_format format
;
226 uint emit
= EMIT_OMIT
;
229 if (sem
== TGSI_SEMANTIC_GENERIC
&& result
>= 8) {
230 for (result
= 0; result
< 8; result
++) {
231 if (fp
->texcoord
[result
] == *idx
) {
232 emit
= vroute
[sem
].emit
;
237 emit
= vroute
[sem
].emit
;
240 if (emit
== EMIT_OMIT
)
243 draw_emit_vertex_attr(vinfo
, emit
, vroute
[sem
].interp
, attrib
);
244 format
= draw_translate_vinfo_format(emit
);
246 r
->vtxfmt
[attrib
] = nv30_vtxfmt(pscreen
, format
)->hw
;
247 r
->vtxptr
[attrib
] = vinfo
->size
| NV30_3D_VTXBUF_DMA1
;
248 vinfo
->size
+= draw_translate_vinfo_size(emit
);
250 if (nv30_screen(pscreen
)->eng3d
->oclass
< NV40_3D_CLASS
) {
251 r
->vtxprog
[attrib
][0] = 0x001f38d8;
252 r
->vtxprog
[attrib
][1] = 0x0080001b | (attrib
<< 9);
253 r
->vtxprog
[attrib
][2] = 0x0836106c;
254 r
->vtxprog
[attrib
][3] = 0x2000f800 | (result
+ vroute
[sem
].vp30
) << 2;
256 r
->vtxprog
[attrib
][0] = 0x401f9c6c;
257 r
->vtxprog
[attrib
][1] = 0x0040000d | (attrib
<< 8);
258 r
->vtxprog
[attrib
][2] = 0x8106c083;
259 r
->vtxprog
[attrib
][3] = 0x6041ff80 | (result
+ vroute
[sem
].vp40
) << 2;
262 *idx
= vroute
[sem
].ow40
<< result
;
267 nv30_render_validate(struct nv30_context
*nv30
)
269 struct nv30_render
*r
= nv30_render(nv30
->draw
->render
);
270 struct nv30_rasterizer_stateobj
*rast
= nv30
->rast
;
271 struct pipe_screen
*pscreen
= &nv30
->screen
->base
.base
;
272 struct nouveau_pushbuf
*push
= nv30
->screen
->base
.pushbuf
;
273 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
274 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
275 struct vertex_info
*vinfo
= &r
->vertex_info
;
276 unsigned vp_attribs
= 0;
277 unsigned vp_results
= 0;
283 struct nouveau_heap
*heap
= nv30_screen(pscreen
)->vp_exec_heap
;
284 if (nouveau_heap_alloc(heap
, 16, &r
->vertprog
, &r
->vertprog
)) {
285 while (heap
->next
&& heap
->size
< 16) {
286 struct nouveau_heap
**evict
= heap
->next
->priv
;
287 nouveau_heap_free(evict
);
290 if (nouveau_heap_alloc(heap
, 16, &r
->vertprog
, &r
->vertprog
))
295 vinfo
->num_attribs
= 0;
298 /* setup routing for all necessary vp outputs */
299 for (i
= 0; i
< vp
->info
.num_outputs
&& attrib
< 16; i
++) {
300 uint semantic
= vp
->info
.output_semantic_name
[i
];
301 uint index
= vp
->info
.output_semantic_index
[i
];
302 if (vroute_add(r
, attrib
, semantic
, &index
)) {
303 vp_attribs
|= (1 << attrib
++);
308 /* setup routing for replaced point coords not written by vp */
309 if (rast
&& rast
->pipe
.point_quad_rasterization
)
310 pntc
= rast
->pipe
.sprite_coord_enable
& 0x000002ff;
314 while (pntc
&& attrib
< 16) {
315 uint index
= ffs(pntc
) - 1; pntc
&= ~(1 << index
);
316 if (vroute_add(r
, attrib
, TGSI_SEMANTIC_GENERIC
, &index
)) {
317 vp_attribs
|= (1 << attrib
++);
322 /* modify vertex format for correct stride, and stub out unused ones */
323 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
324 PUSH_DATA (push
, r
->vertprog
->start
);
325 r
->vtxprog
[attrib
- 1][3] |= 1;
326 for (i
= 0; i
< attrib
; i
++) {
327 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
328 PUSH_DATAp(push
, r
->vtxprog
[i
], 4);
329 r
->vtxfmt
[i
] |= vinfo
->size
<< 8;
332 r
->vtxfmt
[i
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
;
334 BEGIN_NV04(push
, NV30_3D(VIEWPORT_TRANSLATE_X
), 8);
335 PUSH_DATAf(push
, 0.0);
336 PUSH_DATAf(push
, 0.0);
337 PUSH_DATAf(push
, 0.0);
338 PUSH_DATAf(push
, 0.0);
339 PUSH_DATAf(push
, 1.0);
340 PUSH_DATAf(push
, 1.0);
341 PUSH_DATAf(push
, 1.0);
342 PUSH_DATAf(push
, 1.0);
343 BEGIN_NV04(push
, NV30_3D(DEPTH_RANGE_NEAR
), 2);
344 PUSH_DATAf(push
, 0.0);
345 PUSH_DATAf(push
, 1.0);
347 BEGIN_NV04(push
, NV30_3D(VTXFMT(0)), 16);
348 PUSH_DATAp(push
, r
->vtxfmt
, 16);
350 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
351 PUSH_DATA (push
, r
->vertprog
->start
);
352 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
353 PUSH_DATA (push
, 0x00000103);
354 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
355 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
356 PUSH_DATA (push
, vp_attribs
);
357 PUSH_DATA (push
, vp_results
);
365 nv30_render_vbo(struct pipe_context
*pipe
, const struct pipe_draw_info
*info
)
367 struct nv30_context
*nv30
= nv30_context(pipe
);
368 struct draw_context
*draw
= nv30
->draw
;
369 struct pipe_transfer
*transfer
[PIPE_MAX_ATTRIBS
] = {NULL
};
370 struct pipe_transfer
*transferi
= NULL
;
373 nv30_render_validate(nv30
);
375 if (nv30
->draw_dirty
& NV30_NEW_VIEWPORT
)
376 draw_set_viewport_state(draw
, &nv30
->viewport
);
377 if (nv30
->draw_dirty
& NV30_NEW_RASTERIZER
)
378 draw_set_rasterizer_state(draw
, &nv30
->rast
->pipe
, NULL
);
379 if (nv30
->draw_dirty
& NV30_NEW_CLIP
)
380 draw_set_clip_state(draw
, &nv30
->clip
);
381 if (nv30
->draw_dirty
& NV30_NEW_ARRAYS
) {
382 draw_set_vertex_buffers(draw
, nv30
->num_vtxbufs
, nv30
->vtxbuf
);
383 draw_set_vertex_elements(draw
, nv30
->vertex
->num_elements
, nv30
->vertex
->pipe
);
385 if (nv30
->draw_dirty
& NV30_NEW_FRAGPROG
) {
386 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
388 fp
->draw
= draw_create_fragment_shader(draw
, &fp
->pipe
);
389 draw_bind_fragment_shader(draw
, fp
->draw
);
391 if (nv30
->draw_dirty
& NV30_NEW_VERTPROG
) {
392 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
394 vp
->draw
= draw_create_vertex_shader(draw
, &vp
->pipe
);
395 draw_bind_vertex_shader(draw
, vp
->draw
);
397 if (nv30
->draw_dirty
& NV30_NEW_VERTCONST
) {
398 if (nv30
->vertprog
.constbuf
) {
399 void *map
= nv04_resource(nv30
->vertprog
.constbuf
)->data
;
400 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 0,
401 map
, nv30
->vertprog
.constbuf_nr
);
405 for (i
= 0; i
< nv30
->num_vtxbufs
; i
++) {
406 const void *map
= nv30
->vtxbuf
[i
].user_buffer
;
408 map
= pipe_buffer_map(pipe
, nv30
->vtxbuf
[i
].buffer
,
409 PIPE_TRANSFER_UNSYNCHRONIZED
|
410 PIPE_TRANSFER_READ
, &transfer
[i
]);
411 draw_set_mapped_vertex_buffer(draw
, i
, map
);
415 const void *map
= nv30
->idxbuf
.user_buffer
;
417 pipe_buffer_map(pipe
, nv30
->idxbuf
.buffer
,
418 PIPE_TRANSFER_UNSYNCHRONIZED
|
419 PIPE_TRANSFER_READ
, &transferi
);
420 draw_set_indexes(draw
,
421 (ubyte
*) map
+ nv30
->idxbuf
.offset
,
422 nv30
->idxbuf
.index_size
);
424 draw_set_indexes(draw
, NULL
, 0);
427 draw_vbo(draw
, info
);
430 if (info
->indexed
&& transferi
)
431 pipe_buffer_unmap(pipe
, transferi
);
432 for (i
= 0; i
< nv30
->num_vtxbufs
; i
++)
434 pipe_buffer_unmap(pipe
, transfer
[i
]);
436 nv30
->draw_dirty
= 0;
437 nv30_state_release(nv30
);
441 nv30_render_destroy(struct vbuf_render
*render
)
446 static struct vbuf_render
*
447 nv30_render_create(struct nv30_context
*nv30
)
449 struct nv30_render
*r
= CALLOC_STRUCT(nv30_render
);
454 r
->offset
= 1 * 1024 * 1024;
456 r
->base
.max_indices
= 16 * 1024;
457 r
->base
.max_vertex_buffer_bytes
= r
->offset
;
459 r
->base
.get_vertex_info
= nv30_render_get_vertex_info
;
460 r
->base
.allocate_vertices
= nv30_render_allocate_vertices
;
461 r
->base
.map_vertices
= nv30_render_map_vertices
;
462 r
->base
.unmap_vertices
= nv30_render_unmap_vertices
;
463 r
->base
.set_primitive
= nv30_render_set_primitive
;
464 r
->base
.draw_elements
= nv30_render_draw_elements
;
465 r
->base
.draw_arrays
= nv30_render_draw_arrays
;
466 r
->base
.release_vertices
= nv30_render_release_vertices
;
467 r
->base
.destroy
= nv30_render_destroy
;
472 nv30_draw_init(struct pipe_context
*pipe
)
474 struct nv30_context
*nv30
= nv30_context(pipe
);
475 struct vbuf_render
*render
;
476 struct draw_context
*draw
;
477 struct draw_stage
*stage
;
479 draw
= draw_create(pipe
);
483 render
= nv30_render_create(nv30
);
489 stage
= draw_vbuf_stage(draw
, render
);
491 render
->destroy(render
);
496 draw_set_render(draw
, render
);
497 draw_set_rasterize_stage(draw
, stage
);
498 draw_wide_line_threshold(draw
, 10000000.f
);
499 draw_wide_point_threshold(draw
, 10000000.f
);
500 draw_wide_point_sprites(draw
, TRUE
);