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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
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 "nv_object.xml.h"
33 #include "nv30/nv30-40_3d.xml.h"
34 #include "nv30/nv30_context.h"
35 #include "nv30/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
= (uint32_t)vertex_size
* (uint32_t)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
, PIPE_USAGE_STREAM
,
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_range(
95 &r
->nv30
->base
.pipe
, r
->buffer
,
98 PIPE_TRANSFER_DISCARD_RANGE
,
105 nv30_render_unmap_vertices(struct vbuf_render
*render
,
106 ushort min_index
, ushort max_index
)
108 struct nv30_render
*r
= nv30_render(render
);
109 pipe_buffer_unmap(&r
->nv30
->base
.pipe
, r
->transfer
);
114 nv30_render_set_primitive(struct vbuf_render
*render
, unsigned prim
)
116 struct nv30_render
*r
= nv30_render(render
);
118 r
->prim
= nv30_prim_gl(prim
);
122 nv30_render_draw_elements(struct vbuf_render
*render
,
123 const ushort
*indices
, uint count
)
125 struct nv30_render
*r
= nv30_render(render
);
126 struct nv30_context
*nv30
= r
->nv30
;
127 struct nouveau_pushbuf
*push
= nv30
->screen
->base
.pushbuf
;
130 BEGIN_NV04(push
, NV30_3D(VTXBUF(0)), r
->vertex_info
.num_attribs
);
131 for (i
= 0; i
< r
->vertex_info
.num_attribs
; i
++) {
132 PUSH_RESRC(push
, NV30_3D(VTXBUF(i
)), BUFCTX_VTXTMP
,
133 nv04_resource(r
->buffer
), r
->offset
+ r
->vtxptr
[i
],
134 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
, 0, NV30_3D_VTXBUF_DMA1
);
137 if (!nv30_state_validate(nv30
, ~0, false))
140 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
141 PUSH_DATA (push
, r
->prim
);
144 BEGIN_NV04(push
, NV30_3D(VB_ELEMENT_U32
), 1);
145 PUSH_DATA (push
, *indices
++);
150 unsigned npush
= MIN2(count
, NV04_PFIFO_MAX_PACKET_LEN
);
153 BEGIN_NI04(push
, NV30_3D(VB_ELEMENT_U16
), npush
);
155 PUSH_DATA(push
, (indices
[1] << 16) | indices
[0]);
160 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
161 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
162 PUSH_RESET(push
, BUFCTX_VTXTMP
);
166 nv30_render_draw_arrays(struct vbuf_render
*render
, unsigned start
, uint nr
)
168 struct nv30_render
*r
= nv30_render(render
);
169 struct nv30_context
*nv30
= r
->nv30
;
170 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
171 unsigned fn
= nr
>> 8, pn
= nr
& 0xff;
172 unsigned ps
= fn
+ (pn
? 1 : 0);
175 BEGIN_NV04(push
, NV30_3D(VTXBUF(0)), r
->vertex_info
.num_attribs
);
176 for (i
= 0; i
< r
->vertex_info
.num_attribs
; i
++) {
177 PUSH_RESRC(push
, NV30_3D(VTXBUF(i
)), BUFCTX_VTXTMP
,
178 nv04_resource(r
->buffer
), r
->offset
+ r
->vtxptr
[i
],
179 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
, 0, NV30_3D_VTXBUF_DMA1
);
182 if (!nv30_state_validate(nv30
, ~0, false))
185 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
186 PUSH_DATA (push
, r
->prim
);
188 BEGIN_NI04(push
, NV30_3D(VB_VERTEX_BATCH
), ps
);
190 PUSH_DATA (push
, 0xff000000 | start
);
195 PUSH_DATA (push
, ((pn
- 1) << 24) | start
);
197 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
198 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
199 PUSH_RESET(push
, BUFCTX_VTXTMP
);
203 nv30_render_release_vertices(struct vbuf_render
*render
)
205 struct nv30_render
*r
= nv30_render(render
);
206 r
->offset
+= r
->length
;
209 static const struct {
215 [TGSI_SEMANTIC_POSITION
] = { EMIT_4F
, 0, 0, 0x00000000 },
216 [TGSI_SEMANTIC_COLOR
] = { EMIT_4F
, 3, 1, 0x00000001 },
217 [TGSI_SEMANTIC_BCOLOR
] = { EMIT_4F
, 1, 3, 0x00000004 },
218 [TGSI_SEMANTIC_FOG
] = { EMIT_4F
, 5, 5, 0x00000010 },
219 [TGSI_SEMANTIC_PSIZE
] = { EMIT_1F_PSIZE
, 6, 6, 0x00000020 },
220 [TGSI_SEMANTIC_TEXCOORD
] = { EMIT_4F
, 8, 7, 0x00004000 },
224 vroute_add(struct nv30_render
*r
, uint attrib
, uint sem
, uint
*idx
)
226 struct nv30_screen
*screen
= r
->nv30
->screen
;
227 struct nv30_fragprog
*fp
= r
->nv30
->fragprog
.program
;
228 struct vertex_info
*vinfo
= &r
->vertex_info
;
229 enum pipe_format format
;
230 uint emit
= EMIT_OMIT
;
233 if (sem
== TGSI_SEMANTIC_GENERIC
) {
234 uint num_texcoords
= (screen
->eng3d
->oclass
< NV40_3D_CLASS
) ? 8 : 10;
235 for (result
= 0; result
< num_texcoords
; result
++) {
236 if (fp
->texcoord
[result
] == *idx
+ 8) {
237 sem
= TGSI_SEMANTIC_TEXCOORD
;
238 emit
= vroute
[sem
].emit
;
243 emit
= vroute
[sem
].emit
;
246 if (emit
== EMIT_OMIT
)
249 draw_emit_vertex_attr(vinfo
, emit
, attrib
);
250 format
= draw_translate_vinfo_format(emit
);
252 r
->vtxfmt
[attrib
] = nv30_vtxfmt(&screen
->base
.base
, format
)->hw
;
253 r
->vtxptr
[attrib
] = vinfo
->size
;
254 vinfo
->size
+= draw_translate_vinfo_size(emit
);
256 if (screen
->eng3d
->oclass
< NV40_3D_CLASS
) {
257 r
->vtxprog
[attrib
][0] = 0x001f38d8;
258 r
->vtxprog
[attrib
][1] = 0x0080001b | (attrib
<< 9);
259 r
->vtxprog
[attrib
][2] = 0x0836106c;
260 r
->vtxprog
[attrib
][3] = 0x2000f800 | (result
+ vroute
[sem
].vp30
) << 2;
262 r
->vtxprog
[attrib
][0] = 0x401f9c6c;
263 r
->vtxprog
[attrib
][1] = 0x0040000d | (attrib
<< 8);
264 r
->vtxprog
[attrib
][2] = 0x8106c083;
265 r
->vtxprog
[attrib
][3] = 0x6041ff80 | (result
+ vroute
[sem
].vp40
) << 2;
269 *idx
= vroute
[sem
].ow40
<< result
;
271 assert(sem
== TGSI_SEMANTIC_TEXCOORD
);
272 *idx
= 0x00001000 << (result
- 8);
278 nv30_render_validate(struct nv30_context
*nv30
)
280 struct nv30_render
*r
= nv30_render(nv30
->draw
->render
);
281 struct nv30_rasterizer_stateobj
*rast
= nv30
->rast
;
282 struct pipe_screen
*pscreen
= &nv30
->screen
->base
.base
;
283 struct nouveau_pushbuf
*push
= nv30
->screen
->base
.pushbuf
;
284 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
285 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
286 struct vertex_info
*vinfo
= &r
->vertex_info
;
287 unsigned vp_attribs
= 0;
288 unsigned vp_results
= 0;
294 struct nouveau_heap
*heap
= nv30_screen(pscreen
)->vp_exec_heap
;
295 if (nouveau_heap_alloc(heap
, 16, &r
->vertprog
, &r
->vertprog
)) {
296 while (heap
->next
&& heap
->size
< 16) {
297 struct nouveau_heap
**evict
= heap
->next
->priv
;
298 nouveau_heap_free(evict
);
301 if (nouveau_heap_alloc(heap
, 16, &r
->vertprog
, &r
->vertprog
))
306 vinfo
->num_attribs
= 0;
309 /* setup routing for all necessary vp outputs */
310 for (i
= 0; i
< vp
->info
.num_outputs
&& attrib
< 16; i
++) {
311 uint semantic
= vp
->info
.output_semantic_name
[i
];
312 uint index
= vp
->info
.output_semantic_index
[i
];
313 if (vroute_add(r
, attrib
, semantic
, &index
)) {
314 vp_attribs
|= (1 << attrib
++);
319 /* setup routing for replaced point coords not written by vp */
320 if (rast
&& rast
->pipe
.point_quad_rasterization
)
321 pntc
= rast
->pipe
.sprite_coord_enable
& 0x000002ff;
325 while (pntc
&& attrib
< 16) {
326 uint index
= ffs(pntc
) - 1; pntc
&= ~(1 << index
);
327 if (vroute_add(r
, attrib
, TGSI_SEMANTIC_TEXCOORD
, &index
)) {
328 vp_attribs
|= (1 << attrib
++);
333 /* modify vertex format for correct stride, and stub out unused ones */
334 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
335 PUSH_DATA (push
, r
->vertprog
->start
);
336 r
->vtxprog
[attrib
- 1][3] |= 1;
337 for (i
= 0; i
< attrib
; i
++) {
338 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
339 PUSH_DATAp(push
, r
->vtxprog
[i
], 4);
340 r
->vtxfmt
[i
] |= vinfo
->size
<< 8;
343 r
->vtxfmt
[i
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
;
345 BEGIN_NV04(push
, NV30_3D(VIEWPORT_TRANSLATE_X
), 8);
346 PUSH_DATAf(push
, 0.0);
347 PUSH_DATAf(push
, 0.0);
348 PUSH_DATAf(push
, 0.0);
349 PUSH_DATAf(push
, 0.0);
350 PUSH_DATAf(push
, 1.0);
351 PUSH_DATAf(push
, 1.0);
352 PUSH_DATAf(push
, 1.0);
353 PUSH_DATAf(push
, 1.0);
354 BEGIN_NV04(push
, NV30_3D(DEPTH_RANGE_NEAR
), 2);
355 PUSH_DATAf(push
, 0.0);
356 PUSH_DATAf(push
, 1.0);
358 BEGIN_NV04(push
, NV30_3D(VTXFMT(0)), 16);
359 PUSH_DATAp(push
, r
->vtxfmt
, 16);
361 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
362 PUSH_DATA (push
, r
->vertprog
->start
);
363 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
364 PUSH_DATA (push
, 0x00000103);
365 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
366 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
367 PUSH_DATA (push
, vp_attribs
);
368 PUSH_DATA (push
, vp_results
);
376 nv30_render_vbo(struct pipe_context
*pipe
, const struct pipe_draw_info
*info
)
378 struct nv30_context
*nv30
= nv30_context(pipe
);
379 struct draw_context
*draw
= nv30
->draw
;
380 struct pipe_transfer
*transfer
[PIPE_MAX_ATTRIBS
] = {NULL
};
381 struct pipe_transfer
*transferi
= NULL
;
384 nv30_render_validate(nv30
);
386 if (nv30
->draw_dirty
& NV30_NEW_VIEWPORT
)
387 draw_set_viewport_states(draw
, 0, 1, &nv30
->viewport
);
388 if (nv30
->draw_dirty
& NV30_NEW_RASTERIZER
)
389 draw_set_rasterizer_state(draw
, &nv30
->rast
->pipe
, NULL
);
390 if (nv30
->draw_dirty
& NV30_NEW_CLIP
)
391 draw_set_clip_state(draw
, &nv30
->clip
);
392 if (nv30
->draw_dirty
& NV30_NEW_ARRAYS
) {
393 draw_set_vertex_buffers(draw
, 0, nv30
->num_vtxbufs
, nv30
->vtxbuf
);
394 draw_set_vertex_elements(draw
, nv30
->vertex
->num_elements
, nv30
->vertex
->pipe
);
396 if (nv30
->draw_dirty
& NV30_NEW_FRAGPROG
) {
397 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
399 fp
->draw
= draw_create_fragment_shader(draw
, &fp
->pipe
);
400 draw_bind_fragment_shader(draw
, fp
->draw
);
402 if (nv30
->draw_dirty
& NV30_NEW_VERTPROG
) {
403 struct nv30_vertprog
*vp
= nv30
->vertprog
.program
;
405 vp
->draw
= draw_create_vertex_shader(draw
, &vp
->pipe
);
406 draw_bind_vertex_shader(draw
, vp
->draw
);
408 if (nv30
->draw_dirty
& NV30_NEW_VERTCONST
) {
409 if (nv30
->vertprog
.constbuf
) {
410 void *map
= nv04_resource(nv30
->vertprog
.constbuf
)->data
;
411 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 0,
412 map
, nv30
->vertprog
.constbuf_nr
* 16);
414 draw_set_mapped_constant_buffer(draw
, PIPE_SHADER_VERTEX
, 0, NULL
, 0);
418 for (i
= 0; i
< nv30
->num_vtxbufs
; i
++) {
419 const void *map
= nv30
->vtxbuf
[i
].user_buffer
;
421 if (nv30
->vtxbuf
[i
].buffer
)
422 map
= pipe_buffer_map(pipe
, nv30
->vtxbuf
[i
].buffer
,
423 PIPE_TRANSFER_UNSYNCHRONIZED
|
424 PIPE_TRANSFER_READ
, &transfer
[i
]);
426 draw_set_mapped_vertex_buffer(draw
, i
, map
, ~0);
430 const void *map
= nv30
->idxbuf
.user_buffer
;
432 map
= pipe_buffer_map(pipe
, nv30
->idxbuf
.buffer
,
433 PIPE_TRANSFER_UNSYNCHRONIZED
|
434 PIPE_TRANSFER_READ
, &transferi
);
435 draw_set_indexes(draw
,
436 (ubyte
*) map
+ nv30
->idxbuf
.offset
,
437 nv30
->idxbuf
.index_size
, ~0);
439 draw_set_indexes(draw
, NULL
, 0, 0);
442 draw_vbo(draw
, info
);
445 if (info
->indexed
&& transferi
)
446 pipe_buffer_unmap(pipe
, transferi
);
447 for (i
= 0; i
< nv30
->num_vtxbufs
; i
++)
449 pipe_buffer_unmap(pipe
, transfer
[i
]);
451 nv30
->draw_dirty
= 0;
452 nv30_state_release(nv30
);
456 nv30_render_destroy(struct vbuf_render
*render
)
458 struct nv30_render
*r
= nv30_render(render
);
461 pipe_buffer_unmap(&r
->nv30
->base
.pipe
, r
->transfer
);
462 pipe_resource_reference(&r
->buffer
, NULL
);
463 nouveau_heap_free(&r
->vertprog
);
467 static struct vbuf_render
*
468 nv30_render_create(struct nv30_context
*nv30
)
470 struct nv30_render
*r
= CALLOC_STRUCT(nv30_render
);
475 r
->offset
= 1 * 1024 * 1024;
477 r
->base
.max_indices
= 16 * 1024;
478 r
->base
.max_vertex_buffer_bytes
= r
->offset
;
480 r
->base
.get_vertex_info
= nv30_render_get_vertex_info
;
481 r
->base
.allocate_vertices
= nv30_render_allocate_vertices
;
482 r
->base
.map_vertices
= nv30_render_map_vertices
;
483 r
->base
.unmap_vertices
= nv30_render_unmap_vertices
;
484 r
->base
.set_primitive
= nv30_render_set_primitive
;
485 r
->base
.draw_elements
= nv30_render_draw_elements
;
486 r
->base
.draw_arrays
= nv30_render_draw_arrays
;
487 r
->base
.release_vertices
= nv30_render_release_vertices
;
488 r
->base
.destroy
= nv30_render_destroy
;
493 nv30_draw_init(struct pipe_context
*pipe
)
495 struct nv30_context
*nv30
= nv30_context(pipe
);
496 struct vbuf_render
*render
;
497 struct draw_context
*draw
;
498 struct draw_stage
*stage
;
500 draw
= draw_create(pipe
);
504 render
= nv30_render_create(nv30
);
510 stage
= draw_vbuf_stage(draw
, render
);
512 render
->destroy(render
);
517 draw_set_render(draw
, render
);
518 draw_set_rasterize_stage(draw
, stage
);
519 draw_wide_line_threshold(draw
, 10000000.f
);
520 draw_wide_point_threshold(draw
, 10000000.f
);
521 draw_wide_point_sprites(draw
, true);