r300_render.c revision ef513776b5bdd11968d2ca03862e9d1ac48e099f
1/*
2 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
3 *
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23/* r300_render: Vertex and index buffer primitive emission. Contains both
24 * HW TCL fastpath rendering, and SW TCL Draw-assisted rendering. */
25
26#include "draw/draw_context.h"
27#include "draw/draw_vbuf.h"
28
29#include "pipe/p_inlines.h"
30
31#include "util/u_memory.h"
32#include "util/u_prim.h"
33
34#include "r300_cs.h"
35#include "r300_context.h"
36#include "r300_emit.h"
37#include "r300_reg.h"
38#include "r300_render.h"
39#include "r300_state_derived.h"
40#include "r300_vbo.h"
41
42/* r300_render: Vertex and index buffer primitive emission. */
43#define R300_MAX_VBO_SIZE  (1024 * 1024)
44
45uint32_t r300_translate_primitive(unsigned prim)
46{
47    switch (prim) {
48        case PIPE_PRIM_POINTS:
49            return R300_VAP_VF_CNTL__PRIM_POINTS;
50        case PIPE_PRIM_LINES:
51            return R300_VAP_VF_CNTL__PRIM_LINES;
52        case PIPE_PRIM_LINE_LOOP:
53            return R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
54        case PIPE_PRIM_LINE_STRIP:
55            return R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
56        case PIPE_PRIM_TRIANGLES:
57            return R300_VAP_VF_CNTL__PRIM_TRIANGLES;
58        case PIPE_PRIM_TRIANGLE_STRIP:
59            return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
60        case PIPE_PRIM_TRIANGLE_FAN:
61            return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
62        case PIPE_PRIM_QUADS:
63            return R300_VAP_VF_CNTL__PRIM_QUADS;
64        case PIPE_PRIM_QUAD_STRIP:
65            return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
66        case PIPE_PRIM_POLYGON:
67            return R300_VAP_VF_CNTL__PRIM_POLYGON;
68        default:
69            return 0;
70    }
71}
72
73static void r300_emit_draw_arrays(struct r300_context *r300,
74                                  unsigned mode,
75                                  unsigned count)
76{
77    CS_LOCALS(r300);
78
79    BEGIN_CS(4);
80    OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count);
81    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
82    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
83           r300_translate_primitive(mode));
84    END_CS;
85}
86
87static void r300_emit_draw_elements(struct r300_context *r300,
88                                    struct pipe_buffer* indexBuffer,
89                                    unsigned indexSize,
90                                    unsigned minIndex,
91                                    unsigned maxIndex,
92                                    unsigned mode,
93                                    unsigned start,
94                                    unsigned count)
95{
96    uint32_t count_dwords;
97    uint32_t offset_dwords = indexSize * start / sizeof(uint32_t);
98    CS_LOCALS(r300);
99
100    /* XXX most of these are stupid */
101    assert(indexSize == 4 || indexSize == 2);
102    assert((start * indexSize)  % 4 == 0);
103    assert(offset_dwords == 0);
104
105    BEGIN_CS(10);
106    OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex);
107    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0);
108    if (indexSize == 4) {
109        count_dwords = count + start;
110        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
111               R300_VAP_VF_CNTL__INDEX_SIZE_32bit |
112               r300_translate_primitive(mode));
113    } else {
114        count_dwords = (count + start + 1) / 2;
115        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
116               r300_translate_primitive(mode));
117    }
118
119    /* INDX_BUFFER is a truly special packet3.
120     * Unlike most other packet3, where the offset is after the count,
121     * the order is reversed, so the relocation ends up carrying the
122     * size of the indexbuf instead of the offset.
123     *
124     * XXX Fix offset
125     */
126    OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2);
127    OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) |
128           (0 << R300_INDX_BUFFER_SKIP_SHIFT));
129    OUT_CS(offset_dwords);
130    OUT_CS_RELOC(indexBuffer, count_dwords,
131        RADEON_GEM_DOMAIN_GTT, 0, 0);
132
133    END_CS;
134}
135
136
137static boolean r300_setup_vertex_buffers(struct r300_context *r300)
138{
139    unsigned vbuf_count = r300->aos_count;
140    struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
141    struct pipe_vertex_element *velem = r300->vertex_element;
142
143validate:
144    for (int i = 0; i < vbuf_count; i++) {
145        if (!r300->winsys->add_buffer(r300->winsys,
146                vbuf[velem[i].vertex_buffer_index].buffer,
147            RADEON_GEM_DOMAIN_GTT, 0)) {
148            r300->context.flush(&r300->context, 0, NULL);
149            goto validate;
150        }
151    }
152
153    if (!r300->winsys->validate(r300->winsys)) {
154        r300->context.flush(&r300->context, 0, NULL);
155        return r300->winsys->validate(r300->winsys);
156    }
157
158    return TRUE;
159}
160
161/* This is the fast-path drawing & emission for HW TCL. */
162boolean r300_draw_range_elements(struct pipe_context* pipe,
163                                 struct pipe_buffer* indexBuffer,
164                                 unsigned indexSize,
165                                 unsigned minIndex,
166                                 unsigned maxIndex,
167                                 unsigned mode,
168                                 unsigned start,
169                                 unsigned count)
170{
171    struct r300_context* r300 = r300_context(pipe);
172
173    if (!u_trim_pipe_prim(mode, &count)) {
174        return FALSE;
175    }
176
177    if (count > 65535) {
178        return FALSE;
179    }
180
181    r300_update_derived_state(r300);
182
183    if (!r300_setup_vertex_buffers(r300)) {
184        return FALSE;
185    }
186
187    setup_vertex_attributes(r300);
188
189    setup_index_buffer(r300, indexBuffer, indexSize);
190
191    r300_emit_dirty_state(r300);
192
193    r300_emit_aos(r300, 0);
194
195    r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex,
196                            mode, start, count);
197
198    return TRUE;
199}
200
201/* Simple helpers for context setup. Should probably be moved to util. */
202boolean r300_draw_elements(struct pipe_context* pipe,
203                           struct pipe_buffer* indexBuffer,
204                           unsigned indexSize, unsigned mode,
205                           unsigned start, unsigned count)
206{
207    return pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0,
208                                     mode, start, count);
209}
210
211boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
212                         unsigned start, unsigned count)
213{
214    struct r300_context* r300 = r300_context(pipe);
215
216    if (!u_trim_pipe_prim(mode, &count)) {
217        return FALSE;
218    }
219
220    if (count > 65535) {
221        return FALSE;
222    }
223
224    r300_update_derived_state(r300);
225
226    if (!r300_setup_vertex_buffers(r300)) {
227        return FALSE;
228    }
229
230    setup_vertex_attributes(r300);
231
232    r300_emit_dirty_state(r300);
233
234    r300_emit_aos(r300, start);
235
236    r300_emit_draw_arrays(r300, mode, count);
237
238    return TRUE;
239}
240
241/****************************************************************************
242 * The rest of this file is for SW TCL rendering only. Please be polite and *
243 * keep these functions separated so that they are easier to locate. ~C.    *
244 ***************************************************************************/
245
246/* Draw-based drawing for SW TCL chipsets. */
247boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe,
248                                       struct pipe_buffer* indexBuffer,
249                                       unsigned indexSize,
250                                       unsigned minIndex,
251                                       unsigned maxIndex,
252                                       unsigned mode,
253                                       unsigned start,
254                                       unsigned count)
255{
256    assert(0);
257#if 0
258    struct r300_context* r300 = r300_context(pipe);
259    int i;
260
261    if (!u_trim_pipe_prim(mode, &count)) {
262        return FALSE;
263    }
264
265    for (i = 0; i < r300->vertex_buffer_count; i++) {
266        void* buf = pipe_buffer_map(pipe->screen,
267                                    r300->vertex_buffers[i].buffer,
268                                    PIPE_BUFFER_USAGE_CPU_READ);
269        draw_set_mapped_vertex_buffer(r300->draw, i, buf);
270    }
271
272    if (indexBuffer) {
273        void* indices = pipe_buffer_map(pipe->screen, indexBuffer,
274                                        PIPE_BUFFER_USAGE_CPU_READ);
275        draw_set_mapped_element_buffer_range(r300->draw, indexSize,
276                                             minIndex, maxIndex, indices);
277    } else {
278        draw_set_mapped_element_buffer(r300->draw, 0, NULL);
279    }
280
281    draw_set_mapped_constant_buffer(r300->draw,
282            r300->shader_constants[PIPE_SHADER_VERTEX].constants,
283            r300->shader_constants[PIPE_SHADER_VERTEX].count *
284                (sizeof(float) * 4));
285
286    draw_arrays(r300->draw, mode, start, count);
287
288    for (i = 0; i < r300->vertex_buffer_count; i++) {
289        pipe_buffer_unmap(pipe->screen, r300->vertex_buffers[i].buffer);
290        draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
291    }
292
293    if (indexBuffer) {
294        pipe_buffer_unmap(pipe->screen, indexBuffer);
295        draw_set_mapped_element_buffer_range(r300->draw, 0, start,
296                                             start + count - 1, NULL);
297    }
298#endif
299    return TRUE;
300}
301
302/* Object for rendering using Draw. */
303struct r300_render {
304    /* Parent class */
305    struct vbuf_render base;
306
307    /* Pipe context */
308    struct r300_context* r300;
309
310    /* Vertex information */
311    size_t vertex_size;
312    unsigned prim;
313    unsigned hwprim;
314
315    /* VBO */
316    struct pipe_buffer* vbo;
317    size_t vbo_size;
318    size_t vbo_offset;
319    size_t vbo_max_used;
320    void * vbo_ptr;
321};
322
323static INLINE struct r300_render*
324r300_render(struct vbuf_render* render)
325{
326    return (struct r300_render*)render;
327}
328
329static const struct vertex_info*
330r300_render_get_vertex_info(struct vbuf_render* render)
331{
332    struct r300_render* r300render = r300_render(render);
333    struct r300_context* r300 = r300render->r300;
334
335    r300_update_derived_state(r300);
336
337    return &r300->vertex_info->vinfo;
338}
339
340static boolean r300_render_allocate_vertices(struct vbuf_render* render,
341                                                   ushort vertex_size,
342                                                   ushort count)
343{
344    struct r300_render* r300render = r300_render(render);
345    struct r300_context* r300 = r300render->r300;
346    struct pipe_screen* screen = r300->context.screen;
347    size_t size = (size_t)vertex_size * (size_t)count;
348
349    if (size + r300render->vbo_offset > r300render->vbo_size)
350    {
351        pipe_buffer_reference(&r300->vbo, NULL);
352        r300render->vbo = pipe_buffer_create(screen,
353                                             64,
354                                             PIPE_BUFFER_USAGE_VERTEX,
355                                             R300_MAX_VBO_SIZE);
356        r300render->vbo_offset = 0;
357        r300render->vbo_size = R300_MAX_VBO_SIZE;
358    }
359
360    r300render->vertex_size = vertex_size;
361    r300->vbo = r300render->vbo;
362    r300->vbo_offset = r300render->vbo_offset;
363
364    return (r300render->vbo) ? TRUE : FALSE;
365}
366
367static void* r300_render_map_vertices(struct vbuf_render* render)
368{
369    struct r300_render* r300render = r300_render(render);
370    struct pipe_screen* screen = r300render->r300->context.screen;
371
372    r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo,
373                                          PIPE_BUFFER_USAGE_CPU_WRITE);
374
375    return (r300render->vbo_ptr + r300render->vbo_offset);
376}
377
378static void r300_render_unmap_vertices(struct vbuf_render* render,
379                                             ushort min,
380                                             ushort max)
381{
382    struct r300_render* r300render = r300_render(render);
383    struct pipe_screen* screen = r300render->r300->context.screen;
384    CS_LOCALS(r300render->r300);
385    BEGIN_CS(2);
386    OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max);
387    END_CS;
388
389    r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
390                                    r300render->vertex_size * (max + 1));
391    pipe_buffer_unmap(screen, r300render->vbo);
392}
393
394static void r300_render_release_vertices(struct vbuf_render* render)
395{
396    struct r300_render* r300render = r300_render(render);
397
398    r300render->vbo_offset += r300render->vbo_max_used;
399    r300render->vbo_max_used = 0;
400}
401
402static boolean r300_render_set_primitive(struct vbuf_render* render,
403                                               unsigned prim)
404{
405    struct r300_render* r300render = r300_render(render);
406
407    r300render->prim = prim;
408    r300render->hwprim = r300_translate_primitive(prim);
409
410    return TRUE;
411}
412
413static void r300_render_draw_arrays(struct vbuf_render* render,
414                                          unsigned start,
415                                          unsigned count)
416{
417    struct r300_render* r300render = r300_render(render);
418    struct r300_context* r300 = r300render->r300;
419
420    CS_LOCALS(r300);
421
422    r300_emit_dirty_state(r300);
423
424    DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
425
426    BEGIN_CS(2);
427    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
428    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
429           r300render->hwprim);
430    END_CS;
431}
432
433static void r300_render_draw(struct vbuf_render* render,
434                                   const ushort* indices,
435                                   uint count)
436{
437    struct r300_render* r300render = r300_render(render);
438    struct r300_context* r300 = r300render->r300;
439    int i;
440
441    CS_LOCALS(r300);
442
443    r300_emit_dirty_state(r300);
444
445    BEGIN_CS(2 + (count+1)/2);
446    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2);
447    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
448           r300render->hwprim);
449    for (i = 0; i < count-1; i += 2) {
450        OUT_CS(indices[i+1] << 16 | indices[i]);
451    }
452    if (count % 2) {
453        OUT_CS(indices[count-1]);
454    }
455    END_CS;
456}
457
458static void r300_render_destroy(struct vbuf_render* render)
459{
460    FREE(render);
461}
462
463static struct vbuf_render* r300_render_create(struct r300_context* r300)
464{
465    struct r300_render* r300render = CALLOC_STRUCT(r300_render);
466
467    r300render->r300 = r300;
468
469    /* XXX find real numbers plz */
470    r300render->base.max_vertex_buffer_bytes = 128 * 1024;
471    r300render->base.max_indices = 16 * 1024;
472
473    r300render->base.get_vertex_info = r300_render_get_vertex_info;
474    r300render->base.allocate_vertices = r300_render_allocate_vertices;
475    r300render->base.map_vertices = r300_render_map_vertices;
476    r300render->base.unmap_vertices = r300_render_unmap_vertices;
477    r300render->base.set_primitive = r300_render_set_primitive;
478    r300render->base.draw = r300_render_draw;
479    r300render->base.draw_arrays = r300_render_draw_arrays;
480    r300render->base.release_vertices = r300_render_release_vertices;
481    r300render->base.destroy = r300_render_destroy;
482
483    r300render->vbo = NULL;
484    r300render->vbo_size = 0;
485    r300render->vbo_offset = 0;
486
487    return &r300render->base;
488}
489
490struct draw_stage* r300_draw_stage(struct r300_context* r300)
491{
492    struct vbuf_render* render;
493    struct draw_stage* stage;
494
495    render = r300_render_create(r300);
496
497    if (!render) {
498        return NULL;
499    }
500
501    stage = draw_vbuf_stage(r300->draw, render);
502
503    if (!stage) {
504        render->destroy(render);
505        return NULL;
506    }
507
508    draw_set_render(r300->draw, render);
509
510    return stage;
511}
512