OSDN Git Service

baf35a6a50a7c4388d67dc7ebdb3e4af3f461b6c
[android-x86/external-mesa.git] / src / mesa / drivers / dri / i965 / brw_draw_upload.c
1 /**************************************************************************
2  * 
3  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27
28 #undef NDEBUG
29
30 #include "main/glheader.h"
31 #include "main/bufferobj.h"
32 #include "main/context.h"
33 #include "main/enums.h"
34
35 #include "brw_draw.h"
36 #include "brw_defines.h"
37 #include "brw_context.h"
38 #include "brw_state.h"
39
40 #include "intel_batchbuffer.h"
41 #include "intel_buffer_objects.h"
42
43 static GLuint double_types[5] = {
44    0,
45    BRW_SURFACEFORMAT_R64_FLOAT,
46    BRW_SURFACEFORMAT_R64G64_FLOAT,
47    BRW_SURFACEFORMAT_R64G64B64_FLOAT,
48    BRW_SURFACEFORMAT_R64G64B64A64_FLOAT
49 };
50
51 static GLuint float_types[5] = {
52    0,
53    BRW_SURFACEFORMAT_R32_FLOAT,
54    BRW_SURFACEFORMAT_R32G32_FLOAT,
55    BRW_SURFACEFORMAT_R32G32B32_FLOAT,
56    BRW_SURFACEFORMAT_R32G32B32A32_FLOAT
57 };
58
59 static GLuint half_float_types[5] = {
60    0,
61    BRW_SURFACEFORMAT_R16_FLOAT,
62    BRW_SURFACEFORMAT_R16G16_FLOAT,
63    BRW_SURFACEFORMAT_R16G16B16A16_FLOAT,
64    BRW_SURFACEFORMAT_R16G16B16A16_FLOAT
65 };
66
67 static GLuint uint_types_norm[5] = {
68    0,
69    BRW_SURFACEFORMAT_R32_UNORM,
70    BRW_SURFACEFORMAT_R32G32_UNORM,
71    BRW_SURFACEFORMAT_R32G32B32_UNORM,
72    BRW_SURFACEFORMAT_R32G32B32A32_UNORM
73 };
74
75 static GLuint uint_types_scale[5] = {
76    0,
77    BRW_SURFACEFORMAT_R32_USCALED,
78    BRW_SURFACEFORMAT_R32G32_USCALED,
79    BRW_SURFACEFORMAT_R32G32B32_USCALED,
80    BRW_SURFACEFORMAT_R32G32B32A32_USCALED
81 };
82
83 static GLuint int_types_norm[5] = {
84    0,
85    BRW_SURFACEFORMAT_R32_SNORM,
86    BRW_SURFACEFORMAT_R32G32_SNORM,
87    BRW_SURFACEFORMAT_R32G32B32_SNORM,
88    BRW_SURFACEFORMAT_R32G32B32A32_SNORM
89 };
90
91 static GLuint int_types_scale[5] = {
92    0,
93    BRW_SURFACEFORMAT_R32_SSCALED,
94    BRW_SURFACEFORMAT_R32G32_SSCALED,
95    BRW_SURFACEFORMAT_R32G32B32_SSCALED,
96    BRW_SURFACEFORMAT_R32G32B32A32_SSCALED
97 };
98
99 static GLuint ushort_types_norm[5] = {
100    0,
101    BRW_SURFACEFORMAT_R16_UNORM,
102    BRW_SURFACEFORMAT_R16G16_UNORM,
103    BRW_SURFACEFORMAT_R16G16B16_UNORM,
104    BRW_SURFACEFORMAT_R16G16B16A16_UNORM
105 };
106
107 static GLuint ushort_types_scale[5] = {
108    0,
109    BRW_SURFACEFORMAT_R16_USCALED,
110    BRW_SURFACEFORMAT_R16G16_USCALED,
111    BRW_SURFACEFORMAT_R16G16B16_USCALED,
112    BRW_SURFACEFORMAT_R16G16B16A16_USCALED
113 };
114
115 static GLuint short_types_norm[5] = {
116    0,
117    BRW_SURFACEFORMAT_R16_SNORM,
118    BRW_SURFACEFORMAT_R16G16_SNORM,
119    BRW_SURFACEFORMAT_R16G16B16_SNORM,
120    BRW_SURFACEFORMAT_R16G16B16A16_SNORM
121 };
122
123 static GLuint short_types_scale[5] = {
124    0,
125    BRW_SURFACEFORMAT_R16_SSCALED,
126    BRW_SURFACEFORMAT_R16G16_SSCALED,
127    BRW_SURFACEFORMAT_R16G16B16_SSCALED,
128    BRW_SURFACEFORMAT_R16G16B16A16_SSCALED
129 };
130
131 static GLuint ubyte_types_norm[5] = {
132    0,
133    BRW_SURFACEFORMAT_R8_UNORM,
134    BRW_SURFACEFORMAT_R8G8_UNORM,
135    BRW_SURFACEFORMAT_R8G8B8_UNORM,
136    BRW_SURFACEFORMAT_R8G8B8A8_UNORM
137 };
138
139 static GLuint ubyte_types_scale[5] = {
140    0,
141    BRW_SURFACEFORMAT_R8_USCALED,
142    BRW_SURFACEFORMAT_R8G8_USCALED,
143    BRW_SURFACEFORMAT_R8G8B8_USCALED,
144    BRW_SURFACEFORMAT_R8G8B8A8_USCALED
145 };
146
147 static GLuint byte_types_norm[5] = {
148    0,
149    BRW_SURFACEFORMAT_R8_SNORM,
150    BRW_SURFACEFORMAT_R8G8_SNORM,
151    BRW_SURFACEFORMAT_R8G8B8_SNORM,
152    BRW_SURFACEFORMAT_R8G8B8A8_SNORM
153 };
154
155 static GLuint byte_types_scale[5] = {
156    0,
157    BRW_SURFACEFORMAT_R8_SSCALED,
158    BRW_SURFACEFORMAT_R8G8_SSCALED,
159    BRW_SURFACEFORMAT_R8G8B8_SSCALED,
160    BRW_SURFACEFORMAT_R8G8B8A8_SSCALED
161 };
162
163
164 /**
165  * Given vertex array type/size/format/normalized info, return
166  * the appopriate hardware surface type.
167  * Format will be GL_RGBA or possibly GL_BGRA for GLubyte[4] color arrays.
168  */
169 static GLuint get_surface_type( GLenum type, GLuint size,
170                                 GLenum format, GLboolean normalized )
171 {
172    if (unlikely(INTEL_DEBUG & DEBUG_VERTS))
173       printf("type %s size %d normalized %d\n", 
174                    _mesa_lookup_enum_by_nr(type), size, normalized);
175
176    if (normalized) {
177       switch (type) {
178       case GL_DOUBLE: return double_types[size];
179       case GL_FLOAT: return float_types[size];
180       case GL_HALF_FLOAT: return half_float_types[size];
181       case GL_INT: return int_types_norm[size];
182       case GL_SHORT: return short_types_norm[size];
183       case GL_BYTE: return byte_types_norm[size];
184       case GL_UNSIGNED_INT: return uint_types_norm[size];
185       case GL_UNSIGNED_SHORT: return ushort_types_norm[size];
186       case GL_UNSIGNED_BYTE:
187          if (format == GL_BGRA) {
188             /* See GL_EXT_vertex_array_bgra */
189             assert(size == 4);
190             return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
191          }
192          else {
193             return ubyte_types_norm[size];
194          }
195       default: assert(0); return 0;
196       }      
197    }
198    else {
199       assert(format == GL_RGBA); /* sanity check */
200       switch (type) {
201       case GL_DOUBLE: return double_types[size];
202       case GL_FLOAT: return float_types[size];
203       case GL_HALF_FLOAT: return half_float_types[size];
204       case GL_INT: return int_types_scale[size];
205       case GL_SHORT: return short_types_scale[size];
206       case GL_BYTE: return byte_types_scale[size];
207       case GL_UNSIGNED_INT: return uint_types_scale[size];
208       case GL_UNSIGNED_SHORT: return ushort_types_scale[size];
209       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size];
210       default: assert(0); return 0;
211       }      
212    }
213 }
214
215
216 static GLuint get_size( GLenum type )
217 {
218    switch (type) {
219    case GL_DOUBLE: return sizeof(GLdouble);
220    case GL_FLOAT: return sizeof(GLfloat);
221    case GL_HALF_FLOAT: return sizeof(GLhalfARB);
222    case GL_INT: return sizeof(GLint);
223    case GL_SHORT: return sizeof(GLshort);
224    case GL_BYTE: return sizeof(GLbyte);
225    case GL_UNSIGNED_INT: return sizeof(GLuint);
226    case GL_UNSIGNED_SHORT: return sizeof(GLushort);
227    case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
228    default: return 0;
229    }      
230 }
231
232 static GLuint get_index_type(GLenum type) 
233 {
234    switch (type) {
235    case GL_UNSIGNED_BYTE:  return BRW_INDEX_BYTE;
236    case GL_UNSIGNED_SHORT: return BRW_INDEX_WORD;
237    case GL_UNSIGNED_INT:   return BRW_INDEX_DWORD;
238    default: assert(0); return 0;
239    }
240 }
241
242 static void
243 copy_array_to_vbo_array(struct brw_context *brw,
244                         struct brw_vertex_element *element,
245                         int min, int max,
246                         struct brw_vertex_buffer *buffer,
247                         GLuint dst_stride)
248 {
249    int src_stride = element->glarray->StrideB;
250    const unsigned char *src = element->glarray->Ptr + min * src_stride;
251    int count = max - min + 1;
252    GLuint size = count * dst_stride;
253
254    if (dst_stride == src_stride) {
255       intel_upload_data(&brw->intel, src, size, dst_stride,
256                         &buffer->bo, &buffer->offset);
257    } else {
258       char * const map = intel_upload_map(&brw->intel, size, dst_stride);
259       char *dst = map;
260
261       while (count--) {
262          memcpy(dst, src, dst_stride);
263          src += src_stride;
264          dst += dst_stride;
265       }
266       intel_upload_unmap(&brw->intel, map, size, dst_stride,
267                          &buffer->bo, &buffer->offset);
268    }
269    buffer->stride = dst_stride;
270 }
271
272 static void brw_prepare_vertices(struct brw_context *brw)
273 {
274    struct gl_context *ctx = &brw->intel.ctx;
275    struct intel_context *intel = intel_context(ctx);
276    GLbitfield vs_inputs = brw->vs.prog_data->inputs_read;
277    const unsigned char *ptr = NULL;
278    GLuint interleaved = 0, total_size = 0;
279    unsigned int min_index = brw->vb.min_index;
280    unsigned int max_index = brw->vb.max_index;
281    int i, j;
282
283    struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
284    GLuint nr_uploads = 0;
285
286    /* First build an array of pointers to ve's in vb.inputs_read
287     */
288    if (0)
289       printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
290
291    /* Accumulate the list of enabled arrays. */
292    brw->vb.nr_enabled = 0;
293    while (vs_inputs) {
294       GLuint i = _mesa_ffsll(vs_inputs) - 1;
295       struct brw_vertex_element *input = &brw->vb.inputs[i];
296
297       vs_inputs &= ~(1 << i);
298       brw->vb.enabled[brw->vb.nr_enabled++] = input;
299    }
300
301    if (brw->vb.nr_enabled == 0)
302       return;
303
304    if (brw->vb.nr_buffers)
305       goto validate;
306
307    /* XXX: In the rare cases where this happens we fallback all
308     * the way to software rasterization, although a tnl fallback
309     * would be sufficient.  I don't know of *any* real world
310     * cases with > 17 vertex attributes enabled, so it probably
311     * isn't an issue at this point.
312     */
313    if (brw->vb.nr_enabled >= BRW_VEP_MAX) {
314       intel->Fallback = GL_TRUE; /* boolean, not bitfield */
315       return;
316    }
317
318    for (i = j = 0; i < brw->vb.nr_enabled; i++) {
319       struct brw_vertex_element *input = brw->vb.enabled[i];
320       const struct gl_client_array *glarray = input->glarray;
321       int type_size = get_size(glarray->Type);
322
323       input->element_size = type_size * glarray->Size;
324
325       if (_mesa_is_bufferobj(glarray->BufferObj)) {
326          struct intel_buffer_object *intel_buffer =
327             intel_buffer_object(glarray->BufferObj);
328          int k;
329
330          for (k = 0; k < i; k++) {
331             const struct gl_client_array *other = brw->vb.enabled[k]->glarray;
332             if (glarray->BufferObj == other->BufferObj &&
333                 glarray->StrideB == other->StrideB &&
334                 (uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB)
335             {
336                input->buffer = brw->vb.enabled[k]->buffer;
337                input->offset = glarray->Ptr - other->Ptr;
338                break;
339             }
340          }
341          if (k == i) {
342             struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
343
344             /* Named buffer object: Just reference its contents directly. */
345             buffer->bo = intel_bufferobj_source(intel, intel_buffer,
346                                                 &buffer->offset);
347             drm_intel_bo_reference(buffer->bo);
348             buffer->offset += (uintptr_t)glarray->Ptr;
349             buffer->stride = glarray->StrideB;
350
351             input->buffer = j++;
352             input->offset = 0;
353          }
354
355          /* This is a common place to reach if the user mistakenly supplies
356           * a pointer in place of a VBO offset.  If we just let it go through,
357           * we may end up dereferencing a pointer beyond the bounds of the
358           * GTT.  We would hope that the VBO's max_index would save us, but
359           * Mesa appears to hand us min/max values not clipped to the
360           * array object's _MaxElement, and _MaxElement frequently appears
361           * to be wrong anyway.
362           *
363           * The VBO spec allows application termination in this case, and it's
364           * probably a service to the poor programmer to do so rather than
365           * trying to just not render.
366           */
367          assert(input->offset < brw->vb.buffers[input->buffer].bo->size);
368       } else {
369          /* Queue the buffer object up to be uploaded in the next pass,
370           * when we've decided if we're doing interleaved or not.
371           */
372          if (nr_uploads == 0) {
373             /* Position array not properly enabled:
374              */
375             if (input->attrib == VERT_ATTRIB_POS && glarray->StrideB == 0) {
376                intel->Fallback = GL_TRUE; /* boolean, not bitfield */
377                return;
378             }
379
380             interleaved = glarray->StrideB;
381             ptr = glarray->Ptr;
382          }
383          else if (interleaved != glarray->StrideB ||
384                   (uintptr_t)(glarray->Ptr - ptr) > interleaved)
385          {
386             interleaved = 0;
387          }
388          else if ((uintptr_t)(glarray->Ptr - ptr) & (type_size -1))
389          {
390             /* enforce natural alignment (for doubles) */
391             interleaved = 0;
392          }
393
394          upload[nr_uploads++] = input;
395          total_size = ALIGN(total_size, type_size);
396          total_size += input->element_size;
397       }
398    }
399
400    /* If we need to upload all the arrays, then we can trim those arrays to
401     * only the used elements [min_index, max_index] so long as we adjust all
402     * the values used in the 3DPRIMITIVE i.e. by setting the vertex bias.
403     */
404    if (nr_uploads == brw->vb.nr_enabled) {
405       brw->vb.start_vertex_bias = min_index;
406    } else {
407       brw->vb.start_vertex_bias = 0;
408       min_index = 0;
409    }
410
411    /* Handle any arrays to be uploaded. */
412    if (nr_uploads > 1) {
413       if (interleaved && interleaved <= 2*total_size) {
414          /* All uploads are interleaved, so upload the arrays together as
415           * interleaved.  First, upload the contents and set up upload[0].
416           */
417          copy_array_to_vbo_array(brw, upload[0], min_index, max_index,
418                                  &brw->vb.buffers[j], interleaved);
419
420          for (i = 0; i < nr_uploads; i++) {
421             /* Then, just point upload[i] at upload[0]'s buffer. */
422             upload[i]->offset =
423                ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
424             upload[i]->buffer = j;
425          }
426          j++;
427
428          nr_uploads = 0;
429       }
430       else if (total_size < 2048) {
431          /* Upload non-interleaved arrays into a single interleaved array */
432          struct brw_vertex_buffer *buffer;
433          int count = max_index - min_index + 1;
434          int offset;
435          char *map;
436
437          map = intel_upload_map(&brw->intel, total_size * count, total_size);
438          for (i = offset = 0; i < nr_uploads; i++) {
439             const unsigned char *src = upload[i]->glarray->Ptr;
440             int size = upload[i]->element_size;
441             int stride = upload[i]->glarray->StrideB;
442             char *dst;
443             int n;
444
445             offset = ALIGN(offset, get_size(upload[i]->glarray->Type));
446             dst = map + offset;
447             src += min_index * stride;
448
449             for (n = 0; n < count; n++) {
450                memcpy(dst, src, size);
451                src += stride;
452                dst += total_size;
453             }
454
455             upload[i]->offset = offset;
456             upload[i]->buffer = j;
457
458             offset += size;
459          }
460          assert(offset == total_size);
461          buffer = &brw->vb.buffers[j++];
462          intel_upload_unmap(&brw->intel, map, offset * count, offset,
463                             &buffer->bo, &buffer->offset);
464          buffer->stride = offset;
465
466          nr_uploads = 0;
467       }
468    }
469    /* Upload non-interleaved arrays */
470    for (i = 0; i < nr_uploads; i++) {
471       copy_array_to_vbo_array(brw, upload[i], min_index, max_index,
472                               &brw->vb.buffers[j], upload[i]->element_size);
473       upload[i]->buffer = j++;
474       upload[i]->offset = 0;
475    }
476
477    /* can we simply extend the current vb? */
478    if (j == brw->vb.nr_current_buffers) {
479       int delta = 0;
480       for (i = 0; i < j; i++) {
481          int d;
482
483          if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle ||
484              brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride)
485             break;
486
487          d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset;
488          if (delta == 0)
489             delta = d / brw->vb.current_buffers[i].stride;
490          if (delta * brw->vb.current_buffers[i].stride != d)
491             break;
492       }
493
494       if (i == j) {
495          brw->vb.start_vertex_bias += delta;
496          while (--j >= 0)
497             drm_intel_bo_unreference(brw->vb.buffers[j].bo);
498          j = 0;
499       }
500    }
501
502    brw->vb.nr_buffers = j;
503
504 validate:
505    brw_prepare_query_begin(brw);
506    for (i = 0; i < brw->vb.nr_buffers; i++) {
507       brw_add_validated_bo(brw, brw->vb.buffers[i].bo);
508    }
509 }
510
511 static void brw_emit_vertices(struct brw_context *brw)
512 {
513    struct gl_context *ctx = &brw->intel.ctx;
514    struct intel_context *intel = intel_context(ctx);
515    GLuint i;
516
517    brw_emit_query_begin(brw);
518
519    /* If the VS doesn't read any inputs (calculating vertex position from
520     * a state variable for some reason, for example), emit a single pad
521     * VERTEX_ELEMENT struct and bail.
522     *
523     * The stale VB state stays in place, but they don't do anything unless
524     * a VE loads from them.
525     */
526    if (brw->vb.nr_enabled == 0) {
527       BEGIN_BATCH(3);
528       OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1);
529       if (intel->gen >= 6) {
530          OUT_BATCH((0 << GEN6_VE0_INDEX_SHIFT) |
531                    GEN6_VE0_VALID |
532                    (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
533                    (0 << BRW_VE0_SRC_OFFSET_SHIFT));
534       } else {
535          OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) |
536                    BRW_VE0_VALID |
537                    (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
538                    (0 << BRW_VE0_SRC_OFFSET_SHIFT));
539       }
540       OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) |
541                 (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
542                 (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
543                 (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT));
544       CACHED_BATCH();
545       return;
546    }
547
548    /* Now emit VB and VEP state packets.
549     */
550
551    if (brw->vb.nr_buffers) {
552       BEGIN_BATCH(1 + 4*brw->vb.nr_buffers);
553       OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1));
554       for (i = 0; i < brw->vb.nr_buffers; i++) {
555          struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
556          uint32_t dw0;
557
558          if (intel->gen >= 6) {
559             dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT);
560          } else {
561             dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT);
562          }
563
564          OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT));
565          OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset);
566          if (intel->gen >= 5) {
567             OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1);
568          } else
569             OUT_BATCH(buffer->bo->size / buffer->stride);
570          OUT_BATCH(0); /* Instance data step rate */
571
572          brw->vb.current_buffers[i].handle = buffer->bo->handle;
573          brw->vb.current_buffers[i].offset = buffer->offset;
574          brw->vb.current_buffers[i].stride = buffer->stride;
575       }
576       brw->vb.nr_current_buffers = i;
577       ADVANCE_BATCH();
578    }
579
580    BEGIN_BATCH(1 + brw->vb.nr_enabled * 2);
581    OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | (2*brw->vb.nr_enabled - 1));
582    for (i = 0; i < brw->vb.nr_enabled; i++) {
583       struct brw_vertex_element *input = brw->vb.enabled[i];
584       uint32_t format = get_surface_type(input->glarray->Type,
585                                          input->glarray->Size,
586                                          input->glarray->Format,
587                                          input->glarray->Normalized);
588       uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
589       uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
590       uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC;
591       uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC;
592
593       switch (input->glarray->Size) {
594       case 0: comp0 = BRW_VE1_COMPONENT_STORE_0;
595       case 1: comp1 = BRW_VE1_COMPONENT_STORE_0;
596       case 2: comp2 = BRW_VE1_COMPONENT_STORE_0;
597       case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT;
598          break;
599       }
600
601       if (intel->gen >= 6) {
602          OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) |
603                    GEN6_VE0_VALID |
604                    (format << BRW_VE0_FORMAT_SHIFT) |
605                    (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
606       } else {
607          OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) |
608                    BRW_VE0_VALID |
609                    (format << BRW_VE0_FORMAT_SHIFT) |
610                    (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
611       }
612
613       if (intel->gen >= 5)
614           OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
615                     (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
616                     (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
617                     (comp3 << BRW_VE1_COMPONENT_3_SHIFT));
618       else
619           OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
620                     (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
621                     (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
622                     (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
623                     ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
624    }
625    CACHED_BATCH();
626 }
627
628 const struct brw_tracked_state brw_vertices = {
629    .dirty = {
630       .mesa = 0,
631       .brw = BRW_NEW_BATCH | BRW_NEW_VERTICES,
632       .cache = 0,
633    },
634    .prepare = brw_prepare_vertices,
635    .emit = brw_emit_vertices,
636 };
637
638 static void brw_prepare_indices(struct brw_context *brw)
639 {
640    struct gl_context *ctx = &brw->intel.ctx;
641    struct intel_context *intel = &brw->intel;
642    const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
643    GLuint ib_size;
644    drm_intel_bo *bo = NULL;
645    struct gl_buffer_object *bufferobj;
646    GLuint offset;
647    GLuint ib_type_size;
648
649    if (index_buffer == NULL)
650       return;
651
652    ib_type_size = get_size(index_buffer->type);
653    ib_size = ib_type_size * index_buffer->count;
654    bufferobj = index_buffer->obj;
655
656    /* Turn into a proper VBO:
657     */
658    if (!_mesa_is_bufferobj(bufferobj)) {
659
660       /* Get new bufferobj, offset:
661        */
662       intel_upload_data(&brw->intel, index_buffer->ptr, ib_size, ib_type_size,
663                         &bo, &offset);
664       brw->ib.start_vertex_offset = offset / ib_type_size;
665       offset = 0;
666    } else {
667       offset = (GLuint) (unsigned long) index_buffer->ptr;
668
669       /* If the index buffer isn't aligned to its element size, we have to
670        * rebase it into a temporary.
671        */
672        if ((get_size(index_buffer->type) - 1) & offset) {
673            GLubyte *map = ctx->Driver.MapBuffer(ctx,
674                                                 GL_ELEMENT_ARRAY_BUFFER_ARB,
675                                                 GL_DYNAMIC_DRAW_ARB,
676                                                 bufferobj);
677            map += offset;
678
679            intel_upload_data(&brw->intel, map, ib_size, ib_type_size,
680                              &bo, &offset);
681            brw->ib.start_vertex_offset = offset / ib_type_size;
682            offset = 0;
683
684            ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj);
685        } else {
686           /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading
687            * the index buffer state when we're just moving the start index
688            * of our drawing.
689            */
690           brw->ib.start_vertex_offset = offset / ib_type_size;
691
692           bo = intel_bufferobj_source(intel, intel_buffer_object(bufferobj),
693                                       &offset);
694           drm_intel_bo_reference(bo);
695        }
696    }
697
698    if (brw->ib.bo != bo || brw->ib.offset != offset) {
699       drm_intel_bo_unreference(brw->ib.bo);
700       brw->ib.bo = bo;
701       brw->ib.offset = offset;
702
703       brw_add_validated_bo(brw, brw->ib.bo);
704       brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
705    } else {
706       drm_intel_bo_unreference(bo);
707    }
708 }
709
710 const struct brw_tracked_state brw_indices = {
711    .dirty = {
712       .mesa = 0,
713       .brw = BRW_NEW_INDICES,
714       .cache = 0,
715    },
716    .prepare = brw_prepare_indices,
717 };
718
719 static void brw_emit_index_buffer(struct brw_context *brw)
720 {
721    struct intel_context *intel = &brw->intel;
722    const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
723
724    if (index_buffer == NULL)
725       return;
726
727    BEGIN_BATCH(3);
728    OUT_BATCH(CMD_INDEX_BUFFER << 16 |
729              /* cut index enable << 10 */
730              get_index_type(index_buffer->type) << 8 |
731              1);
732    OUT_RELOC(brw->ib.bo,
733              I915_GEM_DOMAIN_VERTEX, 0,
734              brw->ib.offset);
735    OUT_RELOC(brw->ib.bo,
736              I915_GEM_DOMAIN_VERTEX, 0,
737              brw->ib.bo->size - 1);
738    ADVANCE_BATCH();
739 }
740
741 const struct brw_tracked_state brw_index_buffer = {
742    .dirty = {
743       .mesa = 0,
744       .brw = BRW_NEW_BATCH | BRW_NEW_INDEX_BUFFER,
745       .cache = 0,
746    },
747    .emit = brw_emit_index_buffer,
748 };