74563caf47c9cf0bfb2576a49a12b9db9e05eb6b
[profile/ivi/mesa.git] / src / mesa / drivers / dri / r600 / evergreen_render.c
1 /*
2  * Copyright (C) 2008-2010  Advanced Micro Devices, Inc.
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  * 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:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21
22 /*
23  * Authors:
24  *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
25  */
26
27 #include "main/glheader.h"
28 #include "main/state.h"
29 #include "main/imports.h"
30 #include "main/enums.h"
31 #include "main/macros.h"
32 #include "main/context.h"
33 #include "main/dd.h"
34 #include "main/simple_list.h"
35 #include "main/api_arrayelt.h"
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "vbo/vbo.h"
39
40 #include "tnl/tnl.h"
41 #include "tnl/t_vp_build.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_vertex.h"
44 #include "vbo/vbo_context.h"
45
46 #include "r600_context.h"
47 #include "r600_cmdbuf.h"
48
49 #include "evergreen_fragprog.h"
50 #include "evergreen_vertprog.h"
51
52 #include "evergreen_state.h"
53 #include "evergreen_tex.h"
54
55 #include "radeon_buffer_objects.h"
56 #include "radeon_common_context.h"
57
58 static unsigned int evergreenPrimitiveType(int prim) //same
59 {
60     switch (prim & PRIM_MODE_MASK)
61     {
62     case GL_POINTS:
63         return DI_PT_POINTLIST;
64         break;
65     case GL_LINES:
66         return DI_PT_LINELIST;
67         break;
68     case GL_LINE_STRIP:
69         return DI_PT_LINESTRIP;
70         break;
71     case GL_LINE_LOOP:
72         return DI_PT_LINELOOP;
73         break;
74     case GL_TRIANGLES:
75         return DI_PT_TRILIST;
76         break;
77     case GL_TRIANGLE_STRIP:
78         return DI_PT_TRISTRIP;
79         break;
80     case GL_TRIANGLE_FAN:
81         return DI_PT_TRIFAN;
82         break;
83     case GL_QUADS:
84         return DI_PT_QUADLIST;
85         break;
86     case GL_QUAD_STRIP:
87         return DI_PT_QUADSTRIP;
88         break;
89     case GL_POLYGON:
90         return DI_PT_POLYGON;
91         break;
92     default:
93         assert(0);
94         return -1;
95         break;
96     }
97 }
98
99 static int evergreenNumVerts(int num_verts, int prim) //same
100 {
101         int verts_off = 0;
102
103         switch (prim & PRIM_MODE_MASK) {
104         case GL_POINTS:
105                 verts_off = 0;
106                 break;
107         case GL_LINES:
108                 verts_off = num_verts % 2;
109                 break;
110         case GL_LINE_STRIP:
111                 if (num_verts < 2)
112                         verts_off = num_verts;
113                 break;
114         case GL_LINE_LOOP:
115                 if (num_verts < 2)
116                         verts_off = num_verts;
117                 break;
118         case GL_TRIANGLES:
119                 verts_off = num_verts % 3;
120                 break;
121         case GL_TRIANGLE_STRIP:
122                 if (num_verts < 3)
123                         verts_off = num_verts;
124                 break;
125         case GL_TRIANGLE_FAN:
126                 if (num_verts < 3)
127                         verts_off = num_verts;
128                 break;
129         case GL_QUADS:
130                 verts_off = num_verts % 4;
131                 break;
132         case GL_QUAD_STRIP:
133                 if (num_verts < 4)
134                         verts_off = num_verts;
135                 else
136                         verts_off = num_verts % 2;
137                 break;
138         case GL_POLYGON:
139                 if (num_verts < 3)
140                         verts_off = num_verts;
141                 break;
142         default:
143                 assert(0);
144                 return -1;
145                 break;
146         }
147
148         return num_verts - verts_off;
149 }
150
151 static void evergreenRunRenderPrimitive(struct gl_context * ctx, int start, int end, int prim,
152                                         GLint basevertex) //same
153 {
154     context_t *context = EVERGREEN_CONTEXT(ctx);
155     BATCH_LOCALS(&context->radeon);
156     int type, total_emit;
157     int num_indices;
158     uint32_t vgt_draw_initiator = 0;
159     uint32_t vgt_index_type     = 0;
160     uint32_t vgt_primitive_type = 0;
161     uint32_t vgt_num_indices    = 0;
162
163     type = evergreenPrimitiveType(prim);
164     num_indices = evergreenNumVerts(end - start, prim);
165
166     radeon_print(RADEON_RENDER, RADEON_TRACE,
167                  "%s type %x num_indices %d\n",
168                  __func__, type, num_indices);
169
170     if (type < 0 || num_indices <= 0)
171             return;
172
173     SETfield(vgt_primitive_type, type,
174              VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask);
175
176     SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
177
178     if(GL_TRUE != context->ind_buf.is_32bit)
179     {
180             SETfield(vgt_index_type, DI_INDEX_SIZE_16_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
181     }
182
183         /* 16-bit indexes are packed in a 32-bit value */
184         SETfield(vgt_index_type,
185 #if MESA_BIG_ENDIAN
186                         VGT_DMA_SWAP_32_BIT,
187 #else
188                         VGT_DMA_SWAP_NONE,
189 #endif
190                         SWAP_MODE_shift, SWAP_MODE_mask);
191
192     vgt_num_indices = num_indices;
193     SETfield(vgt_draw_initiator, DI_SRC_SEL_DMA, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
194     SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask);
195
196     total_emit =   3  /* VGT_PRIMITIVE_TYPE */
197                  + 2  /* VGT_INDEX_TYPE */
198                  + 2  /* NUM_INSTANCES */
199                  + 4  /* VTX_BASE_VTX_LOC + VTX_START_INST_LOC */
200                  + 5 + 2; /* DRAW_INDEX */
201
202     BEGIN_BATCH_NO_AUTOSTATE(total_emit);
203     // prim
204     R600_OUT_BATCH_REGSEQ(VGT_PRIMITIVE_TYPE, 1);
205     R600_OUT_BATCH(vgt_primitive_type);
206     // index type
207     R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
208     R600_OUT_BATCH(vgt_index_type);
209     // num instances
210     R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
211     R600_OUT_BATCH(1);
212     /* offset */
213     R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 2));
214     R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX);
215     R600_OUT_BATCH(basevertex); //VTX_BASE_VTX_LOC
216     R600_OUT_BATCH(0); //VTX_START_INST_LOC
217     // draw packet
218     R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX, 3));
219     R600_OUT_BATCH(context->ind_buf.bo_offset);
220     R600_OUT_BATCH(0);
221     R600_OUT_BATCH(vgt_num_indices);
222     R600_OUT_BATCH(vgt_draw_initiator);
223     R600_OUT_BATCH_RELOC(context->ind_buf.bo_offset,
224                          context->ind_buf.bo,
225                          context->ind_buf.bo_offset,
226                          RADEON_GEM_DOMAIN_GTT, 0, 0);
227     END_BATCH();
228     COMMIT_BATCH();
229 }
230
231 static void evergreenRunRenderPrimitiveImmediate(struct gl_context * ctx, int start, int end, int prim) //same
232 {
233     context_t *context = EVERGREEN_CONTEXT(ctx);
234     BATCH_LOCALS(&context->radeon);
235     int type, i;
236     uint32_t num_indices, total_emit = 0;
237     uint32_t vgt_draw_initiator = 0;
238     uint32_t vgt_index_type     = 0;
239     uint32_t vgt_primitive_type = 0;
240     uint32_t vgt_num_indices    = 0;
241
242     type = evergreenPrimitiveType(prim);
243     num_indices = evergreenNumVerts(end - start, prim);
244
245     radeon_print(RADEON_RENDER, RADEON_TRACE,
246                  "%s type %x num_indices %d\n",
247                  __func__, type, num_indices);
248
249     if (type < 0 || num_indices <= 0)
250             return;
251
252     SETfield(vgt_primitive_type, type,
253              VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask);
254
255     if (num_indices > 0xffff)
256     {
257             SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
258     }
259     else
260     {
261             SETfield(vgt_index_type, DI_INDEX_SIZE_16_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
262     }
263
264         /* 16-bit indexes are packed in a 32-bit value */
265         SETfield(vgt_index_type,
266 #if MESA_BIG_ENDIAN
267                         VGT_DMA_SWAP_32_BIT,
268 #else
269                         VGT_DMA_SWAP_NONE,
270 #endif
271                         SWAP_MODE_shift, SWAP_MODE_mask);
272
273     vgt_num_indices = num_indices;
274     SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask);
275
276     if (start == 0)
277     {
278         SETfield(vgt_draw_initiator, DI_SRC_SEL_AUTO_INDEX, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
279     }
280     else
281     {
282         if (num_indices > 0xffff)
283         {
284                 total_emit += num_indices;
285         }
286         else
287         {
288                 total_emit += (num_indices + 1) / 2;
289         }
290         SETfield(vgt_draw_initiator, DI_SRC_SEL_IMMEDIATE, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
291     }
292
293     total_emit +=   3 /* VGT_PRIMITIVE_TYPE */
294                   + 2 /* VGT_INDEX_TYPE */
295                   + 2 /* NUM_INSTANCES */
296                   + 4 /* VTX_BASE_VTX_LOC + VTX_START_INST_LOC */
297                   + 3; /* DRAW */              
298
299     BEGIN_BATCH_NO_AUTOSTATE(total_emit);
300     // prim
301     R600_OUT_BATCH_REGSEQ(VGT_PRIMITIVE_TYPE, 1);
302     R600_OUT_BATCH(vgt_primitive_type);
303     // index type
304     R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
305     R600_OUT_BATCH(vgt_index_type);
306     // num instances
307     R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
308     R600_OUT_BATCH(1);
309     /* offset */
310     R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 2));
311     R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX);
312     R600_OUT_BATCH(0); //VTX_BASE_VTX_LOC
313     R600_OUT_BATCH(0); //VTX_START_INST_LOC
314     // draw packet
315     if(start == 0)
316     {
317         R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1));
318         R600_OUT_BATCH(vgt_num_indices);
319         R600_OUT_BATCH(vgt_draw_initiator);
320     }
321     else
322     {
323         if (num_indices > 0xffff)
324         {
325             R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (num_indices + 1)));
326             R600_OUT_BATCH(vgt_num_indices);
327             R600_OUT_BATCH(vgt_draw_initiator);
328             for (i = start; i < (start + num_indices); i++)
329             {
330                 R600_OUT_BATCH(i);
331             }
332         }
333         else
334         {
335             R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (((num_indices + 1) / 2) + 1)));
336             R600_OUT_BATCH(vgt_num_indices);
337             R600_OUT_BATCH(vgt_draw_initiator);
338             for (i = start; i < (start + num_indices); i += 2)
339             {
340                 if ((i + 1) == (start + num_indices))
341                 {
342                     R600_OUT_BATCH(i);
343                 }
344                 else
345                 {
346                     R600_OUT_BATCH(((i + 1) << 16) | (i));
347                 }
348             }
349         }
350     }
351
352     END_BATCH();
353     COMMIT_BATCH();
354 }
355
356 #define CONVERT( TYPE, MACRO ) do {             \
357         GLuint i, j, sz;                                \
358         sz = input->Size;                               \
359         if (input->Normalized) {                        \
360                 for (i = 0; i < count; i++) {           \
361                         const TYPE *in = (TYPE *)src_ptr;               \
362                         for (j = 0; j < sz; j++) {              \
363                                 *dst_ptr++ = MACRO(*in);                \
364                                 in++;                           \
365                         }                                       \
366                         src_ptr += stride;                      \
367                 }                                               \
368         } else {                                        \
369                 for (i = 0; i < count; i++) {           \
370                         const TYPE *in = (TYPE *)src_ptr;               \
371                         for (j = 0; j < sz; j++) {              \
372                                 *dst_ptr++ = (GLfloat)(*in);            \
373                                 in++;                           \
374                         }                                       \
375                         src_ptr += stride;                      \
376                 }                                               \
377         }                                               \
378 } while (0)
379
380 /**
381  * Convert attribute data type to float
382  * If the attribute uses named buffer object replace the bo with newly allocated bo
383  */
384 static void evergreenConvertAttrib(struct gl_context *ctx, int count, 
385                               const struct gl_client_array *input, 
386                               struct StreamDesc *attr)
387 {
388     context_t *context = R700_CONTEXT(ctx);
389     const GLvoid *src_ptr;
390     GLboolean mapped_named_bo = GL_FALSE;
391     GLfloat *dst_ptr;
392     GLuint stride;
393
394     stride = (input->StrideB == 0) ? evergreen_getTypeSize(input->Type) * input->Size : input->StrideB;
395
396     /* Convert value for first element only */
397     if (input->StrideB == 0)
398     {
399         count = 1;
400     }
401
402     if (input->BufferObj->Name) 
403     {
404         if (!input->BufferObj->Pointer) 
405         {
406             ctx->Driver.MapBufferRange(ctx, 0, input->BufferObj->Size,
407                                        GL_MAP_READ_BIT, input->BufferObj);
408             mapped_named_bo = GL_TRUE;
409         }
410
411         src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
412     } 
413     else 
414     {
415         src_ptr = input->Ptr;
416     }
417
418     radeonAllocDmaRegion(&context->radeon, &attr->bo, &attr->bo_offset, 
419                          sizeof(GLfloat) * input->Size * count, 32);
420
421     radeon_bo_map(attr->bo, 1);
422
423     dst_ptr = (GLfloat *)ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
424
425     assert(src_ptr != NULL);
426
427     switch (input->Type) 
428     {
429         case GL_DOUBLE:
430             CONVERT(GLdouble, (GLfloat));
431             break;
432         case GL_UNSIGNED_INT:
433             CONVERT(GLuint, UINT_TO_FLOAT);
434             break;
435         case GL_INT:
436             CONVERT(GLint, INT_TO_FLOAT);
437             break;
438         case GL_UNSIGNED_SHORT:
439             CONVERT(GLushort, USHORT_TO_FLOAT);
440             break;
441         case GL_SHORT:
442             CONVERT(GLshort, SHORT_TO_FLOAT);
443             break;
444         case GL_UNSIGNED_BYTE:
445             assert(input->Format != GL_BGRA);
446             CONVERT(GLubyte, UBYTE_TO_FLOAT);
447             break;
448         case GL_BYTE:
449             CONVERT(GLbyte, BYTE_TO_FLOAT);
450             break;
451         default:
452             assert(0);
453             break;
454     }
455
456     radeon_bo_unmap(attr->bo);
457
458     if (mapped_named_bo) 
459     {
460         ctx->Driver.UnmapBuffer(ctx, input->BufferObj);
461     }
462 }
463
464 static void evergreenFixupIndexBuffer(struct gl_context *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
465 {
466     context_t *context = EVERGREEN_CONTEXT(ctx);
467     GLvoid *src_ptr;
468     GLuint *out;
469     int i;
470     GLboolean mapped_named_bo = GL_FALSE;
471
472     if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer)
473     {
474         ctx->Driver.MapBufferRange(ctx, 0, mesa_ind_buf->obj->Size,
475                                    GL_MAP_READ_BIT, mesa_ind_buf->obj);
476         mapped_named_bo = GL_TRUE;
477         assert(mesa_ind_buf->obj->Pointer != NULL);
478     }
479     src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
480
481     if (mesa_ind_buf->type == GL_UNSIGNED_BYTE)
482     {
483         GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
484         GLubyte *in = (GLubyte *)src_ptr;
485
486         radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
487                              &context->ind_buf.bo_offset, size, 4);
488
489         radeon_bo_map(context->ind_buf.bo, 1);
490         assert(context->ind_buf.bo->ptr != NULL);
491         out = (GLuint *)ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
492
493         for (i = 0; i + 1 < mesa_ind_buf->count; i += 2)
494         {
495             *out++ = in[i] | in[i + 1] << 16;
496         }
497
498         if (i < mesa_ind_buf->count)
499         {
500             *out++ = in[i];
501         }
502
503         radeon_bo_unmap(context->ind_buf.bo);
504 #if MESA_BIG_ENDIAN
505     }
506     else
507     { /* if (mesa_ind_buf->type == GL_UNSIGNED_SHORT) */
508         GLushort *in = (GLushort *)src_ptr;
509         GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
510
511         radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
512                              &context->ind_buf.bo_offset, size, 4);
513
514         radeon_bo_map(context->ind_buf.bo, 1);
515         assert(context->ind_buf.bo->ptr != NULL);
516         out = (GLuint *)ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
517
518         for (i = 0; i + 1 < mesa_ind_buf->count; i += 2)
519         {
520             *out++ = in[i] | in[i + 1] << 16;
521         }
522
523         if (i < mesa_ind_buf->count)
524         {
525             *out++ = in[i];
526         }
527         radeon_bo_unmap(context->ind_buf.bo);
528 #endif
529     }
530
531     context->ind_buf.is_32bit = GL_FALSE;
532     context->ind_buf.count = mesa_ind_buf->count;
533
534     if (mapped_named_bo)
535     {
536         ctx->Driver.UnmapBuffer(ctx, mesa_ind_buf->obj);
537     }
538 }
539
540 static GLboolean evergreen_check_fallbacks(struct gl_context *ctx) //same
541 {
542         if (ctx->RenderMode != GL_RENDER)
543                 return GL_TRUE;
544
545         return GL_FALSE;
546 }
547
548 /* start 3d, idle, cb/db flush */
549 #define PRE_EMIT_STATE_BUFSZ 5 + 5 + 14
550
551 static GLuint evergreenPredictRenderSize(struct gl_context* ctx,
552                                     const struct _mesa_prim *prim,
553                                     const struct _mesa_index_buffer *ib,
554                                     GLuint nr_prims)
555 {
556     context_t *context = EVERGREEN_CONTEXT(ctx);
557     GLboolean flushed;
558     GLuint dwords, i;
559     GLuint state_size;
560
561     dwords = PRE_EMIT_STATE_BUFSZ;
562     if (ib)
563             dwords += nr_prims * 18;
564     else {
565             for (i = 0; i < nr_prims; ++i)
566             {
567                     if (prim[i].start == 0)
568                             dwords += 14;
569                     else if (prim[i].count > 0xffff)
570                             dwords += prim[i].count + 14;
571                     else
572                             dwords += ((prim[i].count + 1) / 2) + 14;
573             }
574     }
575
576     state_size = radeonCountStateEmitSize(&context->radeon);
577     flushed = rcommonEnsureCmdBufSpace(&context->radeon,
578                                        dwords + state_size,
579                                        __FUNCTION__);
580     if (flushed)
581             dwords += radeonCountStateEmitSize(&context->radeon);
582     else
583             dwords += state_size;
584
585     radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s: total prediction size is %d.\n", __FUNCTION__, dwords);
586     return dwords;
587
588 }
589
590 static void evergreenSetupIndexBuffer(struct gl_context *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
591 {
592     context_t *context = EVERGREEN_CONTEXT(ctx);
593
594     if (!mesa_ind_buf) {
595         context->ind_buf.bo = NULL;
596         return;
597     }
598
599 #if MESA_BIG_ENDIAN
600     if (mesa_ind_buf->type == GL_UNSIGNED_INT)
601 #else
602     if (mesa_ind_buf->type != GL_UNSIGNED_BYTE)
603 #endif
604     {
605         const GLvoid *src_ptr;
606         GLvoid *dst_ptr;
607         GLboolean mapped_named_bo = GL_FALSE;
608
609         if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer)
610         {
611                 ctx->Driver.MapBufferRange(ctx, 0, mesa_ind_buf->obj->Size,
612                                            GL_MAP_READ_BIT, mesa_ind_buf->obj);
613                 assert(mesa_ind_buf->obj->Pointer != NULL);
614                 mapped_named_bo = GL_TRUE;
615         }
616
617         src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
618
619         const GLuint size = mesa_ind_buf->count * getTypeSize(mesa_ind_buf->type);
620
621         radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
622                              &context->ind_buf.bo_offset, size, 4);
623         radeon_bo_map(context->ind_buf.bo, 1);
624         assert(context->ind_buf.bo->ptr != NULL);
625         dst_ptr = ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
626
627         memcpy(dst_ptr, src_ptr, size);
628
629         radeon_bo_unmap(context->ind_buf.bo);
630         context->ind_buf.is_32bit = (mesa_ind_buf->type == GL_UNSIGNED_INT);
631         context->ind_buf.count = mesa_ind_buf->count;
632
633         if (mapped_named_bo)
634         {
635                 ctx->Driver.UnmapBuffer(ctx, mesa_ind_buf->obj);
636         }
637     }
638     else
639     {
640             evergreenFixupIndexBuffer(ctx, mesa_ind_buf);
641     }
642 }
643
644 #if 0 /* unused */
645 static void evergreenAlignDataToDword(struct gl_context *ctx, 
646                                  const struct gl_client_array *input, 
647                                  int count, 
648                                  struct StreamDesc *attr)
649 {
650     context_t *context = EVERGREEN_CONTEXT(ctx);
651     const int dst_stride = (input->StrideB + 3) & ~3;
652     const int size = getTypeSize(input->Type) * input->Size * count;
653     GLboolean mapped_named_bo = GL_FALSE;
654
655     radeonAllocDmaRegion(&context->radeon, &attr->bo, &attr->bo_offset, size, 32);
656
657     radeon_bo_map(attr->bo, 1);
658
659     if (!input->BufferObj->Pointer) 
660     {
661         ctx->Driver.MapBufferRange(ctx, 0, input->BufferObj->Size,
662                                    GL_MAP_READ_BIT, input->BufferObj->obj);
663         mapped_named_bo = GL_TRUE;
664     }
665
666     {
667         GLvoid *src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
668         GLvoid *dst_ptr = ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
669         int i;
670
671         for (i = 0; i < count; ++i) 
672         {
673             memcpy(dst_ptr, src_ptr, input->StrideB);
674             src_ptr += input->StrideB;
675             dst_ptr += dst_stride;
676         }
677     }
678
679     radeon_bo_unmap(attr->bo);
680     if (mapped_named_bo) 
681     {
682         ctx->Driver.UnmapBuffer(ctx, input->BufferObj);
683     }
684
685     attr->stride = dst_stride;
686 }
687 #endif
688
689 static void evergreenSetupStreams(struct gl_context *ctx, const struct gl_client_array *input[], int count)
690 {
691         context_t *context = EVERGREEN_CONTEXT(ctx);
692     GLuint stride;
693     int ret;
694     int i, index;
695
696     EVERGREEN_STATECHANGE(context, vtx);
697
698     for(index = 0; index < context->nNumActiveAos; index++) 
699     {
700         struct radeon_aos *aos = &context->radeon.tcl.aos[index];
701         i = context->stream_desc[index].element;
702
703         stride = (input[i]->StrideB == 0) ? getTypeSize(input[i]->Type) * input[i]->Size : input[i]->StrideB;
704
705         if (input[i]->Type == GL_DOUBLE || input[i]->Type == GL_UNSIGNED_INT || input[i]->Type == GL_INT
706 #if MESA_BIG_ENDIAN
707             || getTypeSize(input[i]->Type) != 4
708 #endif
709            )
710         {
711             evergreenConvertAttrib(ctx, count, input[i], &context->stream_desc[index]);
712         } 
713         else 
714         {
715             if (input[i]->BufferObj->Name) 
716             {
717                     context->stream_desc[index].stride = input[i]->StrideB;
718                     context->stream_desc[index].bo_offset = (intptr_t) input[i]->Ptr;
719                     context->stream_desc[index].bo = get_radeon_buffer_object(input[i]->BufferObj)->bo;
720                     context->stream_desc[index].is_named_bo = GL_TRUE;
721             } 
722             else 
723             {
724                 int size;
725                 int local_count = count;
726                 uint32_t *dst;
727
728                 if (input[i]->StrideB == 0) 
729                 {
730                     size = getTypeSize(input[i]->Type) * input[i]->Size;
731                     local_count = 1;
732                 } 
733                 else 
734                 {
735                     size = getTypeSize(input[i]->Type) * input[i]->Size * local_count;
736                 }
737
738                 radeonAllocDmaRegion(&context->radeon, &context->stream_desc[index].bo, 
739                                      &context->stream_desc[index].bo_offset, size, 32);
740
741                 radeon_bo_map(context->stream_desc[index].bo, 1);
742                 assert(context->stream_desc[index].bo->ptr != NULL);
743
744
745                 dst = (uint32_t *)ADD_POINTERS(context->stream_desc[index].bo->ptr, 
746                                                context->stream_desc[index].bo_offset);
747
748                 switch (context->stream_desc[index].dwords) 
749                 {
750                 case 1:                       
751                     radeonEmitVec4(dst, input[i]->Ptr, input[i]->StrideB, local_count);
752                     break;
753                 case 2:                     
754                     radeonEmitVec8(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
755                     break;
756                 case 3:                     
757                     radeonEmitVec12(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
758                     break;
759                 case 4:                     
760                     radeonEmitVec16(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
761                     break;
762                 default: 
763                     assert(0); 
764                     break;
765                 }
766
767                 radeon_bo_unmap(context->stream_desc[index].bo);
768             }
769         }
770
771         aos->count = context->stream_desc[index].stride == 0 ? 1 : count;
772         aos->stride = context->stream_desc[index].stride / sizeof(float);
773         aos->components = context->stream_desc[index].dwords;
774         aos->bo = context->stream_desc[index].bo;
775         aos->offset = context->stream_desc[index].bo_offset;
776
777         if(context->stream_desc[index].is_named_bo) 
778         {
779             radeon_cs_space_add_persistent_bo(context->radeon.cmdbuf.cs, 
780                                               context->stream_desc[index].bo, 
781                                               RADEON_GEM_DOMAIN_GTT, 0);
782         }
783     }
784
785     ret = radeon_cs_space_check_with_bo(context->radeon.cmdbuf.cs, 
786                                         first_elem(&context->radeon.dma.reserved)->bo, 
787                                         RADEON_GEM_DOMAIN_GTT, 0);    
788 }
789
790 static void evergreenFreeData(struct gl_context *ctx)
791 {
792     /* Need to zero tcl.aos[n].bo and tcl.elt_dma_bo
793      * to prevent double unref in radeonReleaseArrays
794      * called during context destroy
795      */
796     context_t *context = EVERGREEN_CONTEXT(ctx);
797
798     int i;
799
800     for (i = 0; i < context->nNumActiveAos; i++)
801     {
802         if (!context->stream_desc[i].is_named_bo)
803         {
804                 radeon_bo_unref(context->stream_desc[i].bo);
805         }
806         context->radeon.tcl.aos[i].bo = NULL;
807     }
808
809     if(context->vp_Constbo != NULL)
810     {
811         radeon_bo_unref(context->vp_Constbo);
812         context->vp_Constbo = NULL;
813     }
814     if(context->fp_Constbo != NULL)
815     {
816         radeon_bo_unref(context->fp_Constbo);
817         context->fp_Constbo = NULL;
818     }
819
820     if (context->ind_buf.bo != NULL)
821     {
822             radeon_bo_unref(context->ind_buf.bo);
823     }
824 }
825
826 static GLboolean evergreenTryDrawPrims(struct gl_context *ctx,
827                                   const struct gl_client_array *arrays[],
828                                   const struct _mesa_prim *prim,
829                                   GLuint nr_prims,
830                                   const struct _mesa_index_buffer *ib,
831                                   GLuint min_index,
832                                   GLuint max_index )
833 {
834     context_t *context = EVERGREEN_CONTEXT(ctx);
835     radeonContextPtr radeon = &context->radeon;
836     GLuint i, id = 0;
837     struct radeon_renderbuffer *rrb;
838
839     if (ctx->NewState)
840         _mesa_update_state( ctx );
841
842     if (evergreen_check_fallbacks(ctx))
843             return GL_FALSE;
844
845     _tnl_UpdateFixedFunctionProgram(ctx);
846     evergreenSetVertexFormat(ctx, arrays, max_index + 1);
847
848
849     /* shaders need to be updated before buffers are validated */
850     evergreenUpdateShaders(ctx);
851     if (!evergreenValidateBuffers(ctx))
852             return GL_FALSE;
853
854     /* always emit CB base to prevent
855      * lock ups on some chips.
856      */
857     EVERGREEN_STATECHANGE(context, cb);
858     /* mark vtx as dirty since it changes per-draw */
859     EVERGREEN_STATECHANGE(context, vtx);
860
861     evergreenSetScissor(context);
862
863     evergreenSetupVertexProgram(ctx);
864     evergreenSetupFragmentProgram(ctx);
865     evergreenUpdateShaderStates(ctx);
866
867     GLuint emit_end = evergreenPredictRenderSize(ctx, prim, ib, nr_prims)
868                     + context->radeon.cmdbuf.cs->cdw;
869
870     /* evergreenPredictRenderSize will call radeonReleaseDmaRegions, so update VP/FP const buf after it. */
871     evergreenSetupVPconstants(ctx);
872     evergreenSetupFPconstants(ctx);
873
874     evergreenSetupIndexBuffer(ctx, ib);
875
876     evergreenSetupStreams(ctx, arrays, max_index + 1);
877
878     radeonEmitState(radeon);
879
880     radeon_debug_add_indent();
881
882     for (i = 0; i < nr_prims; ++i)
883     {
884             if (context->ind_buf.bo)
885                     evergreenRunRenderPrimitive(ctx,
886                                            prim[i].start,
887                                            prim[i].start + prim[i].count,
888                                            prim[i].mode,
889                                            prim[i].basevertex);
890             else
891                     evergreenRunRenderPrimitiveImmediate(ctx,
892                                                     prim[i].start,
893                                                     prim[i].start + prim[i].count,
894                                                     prim[i].mode);
895     }
896
897     radeon_debug_remove_indent();
898
899     /* Flush render op cached for last several quads. */
900     /* XXX drm should handle this in fence submit */
901
902     //evergreeWaitForIdleClean(context);
903
904     rrb = radeon_get_colorbuffer(&context->radeon);
905     if (rrb && rrb->bo)
906             r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
907                          CB_ACTION_ENA_bit | (1 << (id + 6)));
908
909     rrb = radeon_get_depthbuffer(&context->radeon);
910     if (rrb && rrb->bo)
911             r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
912                          DB_ACTION_ENA_bit | DB_DEST_BASE_ENA_bit);
913
914     evergreenFreeData(ctx);
915
916     if (emit_end < context->radeon.cmdbuf.cs->cdw)
917     {
918         WARN_ONCE("Rendering was %d commands larger than predicted size."
919             " We might overflow  command buffer.\n", context->radeon.cmdbuf.cs->cdw - emit_end);
920     }
921
922     return GL_TRUE;
923 }
924
925 static void evergreenDrawPrims(struct gl_context *ctx,
926                           const struct gl_client_array *arrays[],
927                           const struct _mesa_prim *prim,
928                           GLuint nr_prims,
929                           const struct _mesa_index_buffer *ib,
930                           GLboolean index_bounds_valid,
931                           GLuint min_index,
932                           GLuint max_index)
933 {
934         GLboolean retval = GL_FALSE;
935
936         context_t *context = EVERGREEN_CONTEXT(ctx);
937         radeonContextPtr radeon = &context->radeon;
938         radeon_prepare_render(radeon);
939
940         /* This check should get folded into just the places that
941          * min/max index are really needed.
942          */
943         if (!vbo_all_varyings_in_vbos(arrays)) {
944                 if (!index_bounds_valid)
945                         vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
946                 /* do we want to rebase, minimizes the 
947                  * amount of data to upload? */
948                 if (min_index) {
949                         vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, evergreenDrawPrims );
950                         return;
951                 }
952         }
953         /* Make an attempt at drawing */
954         retval = evergreenTryDrawPrims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
955
956         /* If failed run tnl pipeline - it should take care of fallbacks */
957         if (!retval) {
958                 _swsetup_Wakeup(ctx);
959                 _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
960         }
961 }
962
963 void evergreenInitDraw(struct gl_context *ctx)
964 {
965         struct vbo_context *vbo = vbo_context(ctx);
966
967         /* to be enabled */
968         vbo->draw_prims = evergreenDrawPrims;
969 }
970
971