Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
 
2
 *
3
 * Copyright 2007 VMware, Inc.
4
 * Copyright 2012 Marek Olšák 
5
 * All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sub license, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice (including the
16
 * next paragraph) shall be included in all copies or substantial portions
17
 * of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 *
27
 **************************************************************************/
28
29
 
30
 * This converts the VBO's vertex attribute/array information into
31
 * Gallium vertex state and binds it.
32
 *
33
 * Authors:
34
 *   Keith Whitwell 
35
 *   Marek Olšák 
36
 */
37
38
 
39
#include "st_atom.h"
40
#include "st_cb_bufferobjects.h"
41
#include "st_draw.h"
42
#include "st_program.h"
43
44
 
45
#include "util/u_math.h"
46
#include "main/bufferobj.h"
47
#include "main/glformats.h"
48
49
 
50
 
51
   PIPE_FORMAT_R64_FLOAT,
52
   PIPE_FORMAT_R64G64_FLOAT,
53
   PIPE_FORMAT_R64G64B64_FLOAT,
54
   PIPE_FORMAT_R64G64B64A64_FLOAT
55
};
56
57
 
58
   PIPE_FORMAT_R32_FLOAT,
59
   PIPE_FORMAT_R32G32_FLOAT,
60
   PIPE_FORMAT_R32G32B32_FLOAT,
61
   PIPE_FORMAT_R32G32B32A32_FLOAT
62
};
63
64
 
65
   PIPE_FORMAT_R16_FLOAT,
66
   PIPE_FORMAT_R16G16_FLOAT,
67
   PIPE_FORMAT_R16G16B16_FLOAT,
68
   PIPE_FORMAT_R16G16B16A16_FLOAT
69
};
70
71
 
72
   PIPE_FORMAT_R32_UNORM,
73
   PIPE_FORMAT_R32G32_UNORM,
74
   PIPE_FORMAT_R32G32B32_UNORM,
75
   PIPE_FORMAT_R32G32B32A32_UNORM
76
};
77
78
 
79
   PIPE_FORMAT_R32_USCALED,
80
   PIPE_FORMAT_R32G32_USCALED,
81
   PIPE_FORMAT_R32G32B32_USCALED,
82
   PIPE_FORMAT_R32G32B32A32_USCALED
83
};
84
85
 
86
   PIPE_FORMAT_R32_UINT,
87
   PIPE_FORMAT_R32G32_UINT,
88
   PIPE_FORMAT_R32G32B32_UINT,
89
   PIPE_FORMAT_R32G32B32A32_UINT
90
};
91
92
 
93
   PIPE_FORMAT_R32_SNORM,
94
   PIPE_FORMAT_R32G32_SNORM,
95
   PIPE_FORMAT_R32G32B32_SNORM,
96
   PIPE_FORMAT_R32G32B32A32_SNORM
97
};
98
99
 
100
   PIPE_FORMAT_R32_SSCALED,
101
   PIPE_FORMAT_R32G32_SSCALED,
102
   PIPE_FORMAT_R32G32B32_SSCALED,
103
   PIPE_FORMAT_R32G32B32A32_SSCALED
104
};
105
106
 
107
   PIPE_FORMAT_R32_SINT,
108
   PIPE_FORMAT_R32G32_SINT,
109
   PIPE_FORMAT_R32G32B32_SINT,
110
   PIPE_FORMAT_R32G32B32A32_SINT
111
};
112
113
 
114
   PIPE_FORMAT_R16_UNORM,
115
   PIPE_FORMAT_R16G16_UNORM,
116
   PIPE_FORMAT_R16G16B16_UNORM,
117
   PIPE_FORMAT_R16G16B16A16_UNORM
118
};
119
120
 
121
   PIPE_FORMAT_R16_USCALED,
122
   PIPE_FORMAT_R16G16_USCALED,
123
   PIPE_FORMAT_R16G16B16_USCALED,
124
   PIPE_FORMAT_R16G16B16A16_USCALED
125
};
126
127
 
128
   PIPE_FORMAT_R16_UINT,
129
   PIPE_FORMAT_R16G16_UINT,
130
   PIPE_FORMAT_R16G16B16_UINT,
131
   PIPE_FORMAT_R16G16B16A16_UINT
132
};
133
134
 
135
   PIPE_FORMAT_R16_SNORM,
136
   PIPE_FORMAT_R16G16_SNORM,
137
   PIPE_FORMAT_R16G16B16_SNORM,
138
   PIPE_FORMAT_R16G16B16A16_SNORM
139
};
140
141
 
142
   PIPE_FORMAT_R16_SSCALED,
143
   PIPE_FORMAT_R16G16_SSCALED,
144
   PIPE_FORMAT_R16G16B16_SSCALED,
145
   PIPE_FORMAT_R16G16B16A16_SSCALED
146
};
147
148
 
149
   PIPE_FORMAT_R16_SINT,
150
   PIPE_FORMAT_R16G16_SINT,
151
   PIPE_FORMAT_R16G16B16_SINT,
152
   PIPE_FORMAT_R16G16B16A16_SINT
153
};
154
155
 
156
   PIPE_FORMAT_R8_UNORM,
157
   PIPE_FORMAT_R8G8_UNORM,
158
   PIPE_FORMAT_R8G8B8_UNORM,
159
   PIPE_FORMAT_R8G8B8A8_UNORM
160
};
161
162
 
163
   PIPE_FORMAT_R8_USCALED,
164
   PIPE_FORMAT_R8G8_USCALED,
165
   PIPE_FORMAT_R8G8B8_USCALED,
166
   PIPE_FORMAT_R8G8B8A8_USCALED
167
};
168
169
 
170
   PIPE_FORMAT_R8_UINT,
171
   PIPE_FORMAT_R8G8_UINT,
172
   PIPE_FORMAT_R8G8B8_UINT,
173
   PIPE_FORMAT_R8G8B8A8_UINT
174
};
175
176
 
177
   PIPE_FORMAT_R8_SNORM,
178
   PIPE_FORMAT_R8G8_SNORM,
179
   PIPE_FORMAT_R8G8B8_SNORM,
180
   PIPE_FORMAT_R8G8B8A8_SNORM
181
};
182
183
 
184
   PIPE_FORMAT_R8_SSCALED,
185
   PIPE_FORMAT_R8G8_SSCALED,
186
   PIPE_FORMAT_R8G8B8_SSCALED,
187
   PIPE_FORMAT_R8G8B8A8_SSCALED
188
};
189
190
 
191
   PIPE_FORMAT_R8_SINT,
192
   PIPE_FORMAT_R8G8_SINT,
193
   PIPE_FORMAT_R8G8B8_SINT,
194
   PIPE_FORMAT_R8G8B8A8_SINT
195
};
196
197
 
198
   PIPE_FORMAT_R32_FIXED,
199
   PIPE_FORMAT_R32G32_FIXED,
200
   PIPE_FORMAT_R32G32B32_FIXED,
201
   PIPE_FORMAT_R32G32B32A32_FIXED
202
};
203
204
 
205
 
206
 * Return a PIPE_FORMAT_x for the given GL datatype and size.
207
 */
208
enum pipe_format
209
st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
210
                      GLboolean normalized, GLboolean integer)
211
{
212
   assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
213
          type == GL_FIXED || type == GL_HALF_FLOAT ||
214
          type == GL_INT_2_10_10_10_REV ||
215
          type == GL_UNSIGNED_INT_2_10_10_10_REV ||
216
          type == GL_UNSIGNED_INT_10F_11F_11F_REV);
217
   assert(size >= 1);
218
   assert(size <= 4);
219
   assert(format == GL_RGBA || format == GL_BGRA);
220
221
 
222
       type == GL_UNSIGNED_INT_2_10_10_10_REV) {
223
      assert(size == 4);
224
      assert(!integer);
225
226
 
227
         if (type == GL_INT_2_10_10_10_REV) {
228
            if (normalized)
229
               return PIPE_FORMAT_B10G10R10A2_SNORM;
230
            else
231
               return PIPE_FORMAT_B10G10R10A2_SSCALED;
232
         } else {
233
            if (normalized)
234
               return PIPE_FORMAT_B10G10R10A2_UNORM;
235
            else
236
               return PIPE_FORMAT_B10G10R10A2_USCALED;
237
         }
238
      } else {
239
         if (type == GL_INT_2_10_10_10_REV) {
240
            if (normalized)
241
               return PIPE_FORMAT_R10G10B10A2_SNORM;
242
            else
243
               return PIPE_FORMAT_R10G10B10A2_SSCALED;
244
         } else {
245
            if (normalized)
246
               return PIPE_FORMAT_R10G10B10A2_UNORM;
247
            else
248
               return PIPE_FORMAT_R10G10B10A2_USCALED;
249
         }
250
      }
251
   }
252
253
 
254
      assert(size == 3);
255
      assert(!integer);
256
      assert(format == GL_RGBA);
257
258
 
259
   }
260
261
 
262
      /* this is an odd-ball case */
263
      assert(type == GL_UNSIGNED_BYTE);
264
      assert(normalized);
265
      return PIPE_FORMAT_B8G8R8A8_UNORM;
266
   }
267
268
 
269
      switch (type) {
270
      case GL_INT: return int_types_int[size-1];
271
      case GL_SHORT: return short_types_int[size-1];
272
      case GL_BYTE: return byte_types_int[size-1];
273
      case GL_UNSIGNED_INT: return uint_types_int[size-1];
274
      case GL_UNSIGNED_SHORT: return ushort_types_int[size-1];
275
      case GL_UNSIGNED_BYTE: return ubyte_types_int[size-1];
276
      default: assert(0); return 0;
277
      }
278
   }
279
   else if (normalized) {
280
      switch (type) {
281
      case GL_DOUBLE: return double_types[size-1];
282
      case GL_FLOAT: return float_types[size-1];
283
      case GL_HALF_FLOAT: return half_float_types[size-1];
284
      case GL_INT: return int_types_norm[size-1];
285
      case GL_SHORT: return short_types_norm[size-1];
286
      case GL_BYTE: return byte_types_norm[size-1];
287
      case GL_UNSIGNED_INT: return uint_types_norm[size-1];
288
      case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
289
      case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
290
      case GL_FIXED: return fixed_types[size-1];
291
      default: assert(0); return 0;
292
      }
293
   }
294
   else {
295
      switch (type) {
296
      case GL_DOUBLE: return double_types[size-1];
297
      case GL_FLOAT: return float_types[size-1];
298
      case GL_HALF_FLOAT: return half_float_types[size-1];
299
      case GL_INT: return int_types_scale[size-1];
300
      case GL_SHORT: return short_types_scale[size-1];
301
      case GL_BYTE: return byte_types_scale[size-1];
302
      case GL_UNSIGNED_INT: return uint_types_scale[size-1];
303
      case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
304
      case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
305
      case GL_FIXED: return fixed_types[size-1];
306
      default: assert(0); return 0;
307
      }
308
   }
309
   return PIPE_FORMAT_NONE; /* silence compiler warning */
310
}
311
312
 
313
get_client_array(const struct st_vertex_program *vp,
314
                 const struct gl_client_array **arrays,
315
                 int attr)
316
{
317
   const GLuint mesaAttr = vp->index_to_input[attr];
318
   /* st_program uses 0xffffffff to denote a double placeholder attribute */
319
   if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
320
      return NULL;
321
   return arrays[mesaAttr];
322
}
323
324
 
325
 * Examine the active arrays to determine if we have interleaved
326
 * vertex arrays all living in one VBO, or all living in user space.
327
 */
328
static GLboolean
329
is_interleaved_arrays(const struct st_vertex_program *vp,
330
                      const struct st_vp_variant *vpv,
331
                      const struct gl_client_array **arrays)
332
{
333
   GLuint attr;
334
   const struct gl_buffer_object *firstBufObj = NULL;
335
   GLint firstStride = -1;
336
   const GLubyte *firstPtr = NULL;
337
   GLboolean userSpaceBuffer = GL_FALSE;
338
339
 
340
      const struct gl_client_array *array;
341
      const struct gl_buffer_object *bufObj;
342
      GLsizei stride;
343
344
 
345
      if (!array)
346
	 continue;
347
348
 
349
      bufObj = array->BufferObj;
350
      if (attr == 0) {
351
         /* save info about the first array */
352
         firstStride = stride;
353
         firstPtr = array->Ptr;
354
         firstBufObj = bufObj;
355
         userSpaceBuffer = !bufObj || !bufObj->Name;
356
      }
357
      else {
358
         /* check if other arrays interleave with the first, in same buffer */
359
         if (stride != firstStride)
360
            return GL_FALSE; /* strides don't match */
361
362
 
363
            return GL_FALSE; /* arrays in different VBOs */
364
365
 
366
            return GL_FALSE; /* arrays start too far apart */
367
368
 
369
            return GL_FALSE; /* mix of VBO and user-space arrays */
370
      }
371
   }
372
373
 
374
}
375
376
 
377
                          int src_offset, int format,
378
                          int instance_divisor, int vbo_index)
379
{
380
   velement->src_offset = src_offset;
381
   velement->src_format = format;
382
   velement->instance_divisor = instance_divisor;
383
   velement->vertex_buffer_index = vbo_index;
384
   assert(velement->src_format);
385
}
386
387
 
388
                                  struct pipe_vertex_element *velements,
389
                                  int src_offset, int format,
390
                                  int instance_divisor, int vbo_index,
391
                                  int nr_components, GLboolean doubles,
392
                                  GLuint *attr_idx)
393
{
394
   int idx = *attr_idx;
395
   if (doubles) {
396
      int lower_format;
397
398
 
399
         lower_format = PIPE_FORMAT_R32G32_UINT;
400
      else if (nr_components >= 2)
401
         lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
402
403
 
404
                    lower_format, instance_divisor, vbo_index);
405
      idx++;
406
407
 
408
         if (nr_components == 3)
409
            lower_format = PIPE_FORMAT_R32G32_UINT;
410
         else if (nr_components >= 4)
411
            lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
412
413
 
414
                       lower_format, instance_divisor, vbo_index);
415
         idx++;
416
      }
417
   } else {
418
      init_velement(&velements[idx], src_offset,
419
                    format, instance_divisor, vbo_index);
420
      idx++;
421
   }
422
   *attr_idx = idx;
423
}
424
425
 
426
 * Set up for drawing interleaved arrays that all live in one VBO
427
 * or all live in user space.
428
 * \param vbuffer  returns vertex buffer info
429
 * \param velements  returns vertex element info
430
 */
431
static boolean
432
setup_interleaved_attribs(struct st_context *st,
433
                          const struct st_vertex_program *vp,
434
                          const struct st_vp_variant *vpv,
435
                          const struct gl_client_array **arrays,
436
                          struct pipe_vertex_buffer *vbuffer,
437
                          struct pipe_vertex_element velements[],
438
                          unsigned *num_velements)
439
{
440
   GLuint attr, attr_idx;
441
   const GLubyte *low_addr = NULL;
442
   GLboolean usingVBO;      /* all arrays in a VBO? */
443
   struct gl_buffer_object *bufobj;
444
   GLsizei stride;
445
446
 
447
    * Init bufobj and stride.
448
    */
449
   if (vpv->num_inputs) {
450
      const struct gl_client_array *array;
451
452
 
453
      assert(array);
454
455
 
456
       * one buffer object and the stride will be the same for all arrays.
457
       * Grab them now.
458
       */
459
      bufobj = array->BufferObj;
460
      stride = array->StrideB;
461
462
 
463
464
 
465
         const GLubyte *start;
466
         array = get_client_array(vp, arrays, attr);
467
         if (!array)
468
            continue;
469
         start = array->Ptr;
470
         low_addr = MIN2(low_addr, start);
471
      }
472
   }
473
   else {
474
      /* not sure we'll ever have zero inputs, but play it safe */
475
      bufobj = NULL;
476
      stride = 0;
477
      low_addr = 0;
478
   }
479
480
 
481
   usingVBO = _mesa_is_bufferobj(bufobj);
482
483
 
484
   for (attr = 0; attr < vpv->num_inputs; attr++) {
485
      const struct gl_client_array *array;
486
      unsigned src_offset;
487
      unsigned src_format;
488
489
 
490
      if (!array)
491
         continue;
492
493
 
494
      assert(array->_ElementSize ==
495
             _mesa_bytes_per_vertex_attrib(array->Size, array->Type));
496
497
 
498
                                         array->Size,
499
                                         array->Format,
500
                                         array->Normalized,
501
                                         array->Integer);
502
503
 
504
                            array->InstanceDivisor, 0,
505
                            array->Size, array->Doubles, &attr_idx);
506
   }
507
508
 
509
510
 
511
    * Return the vbuffer info and setup user-space attrib info, if needed.
512
    */
513
   if (vpv->num_inputs == 0) {
514
      /* just defensive coding here */
515
      vbuffer->buffer = NULL;
516
      vbuffer->user_buffer = NULL;
517
      vbuffer->buffer_offset = 0;
518
      vbuffer->stride = 0;
519
   }
520
   else if (usingVBO) {
521
      /* all interleaved arrays in a VBO */
522
      struct st_buffer_object *stobj = st_buffer_object(bufobj);
523
524
 
525
         return FALSE; /* out-of-memory error probably */
526
      }
527
528
 
529
      vbuffer->user_buffer = NULL;
530
      vbuffer->buffer_offset = pointer_to_offset(low_addr);
531
      vbuffer->stride = stride;
532
   }
533
   else {
534
      /* all interleaved arrays in user memory */
535
      vbuffer->buffer = NULL;
536
      vbuffer->user_buffer = low_addr;
537
      vbuffer->buffer_offset = 0;
538
      vbuffer->stride = stride;
539
   }
540
   return TRUE;
541
}
542
543
 
544
 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
545
 * vertex attribute.
546
 * \param vbuffer  returns vertex buffer info
547
 * \param velements  returns vertex element info
548
 */
549
static boolean
550
setup_non_interleaved_attribs(struct st_context *st,
551
                              const struct st_vertex_program *vp,
552
                              const struct st_vp_variant *vpv,
553
                              const struct gl_client_array **arrays,
554
                              struct pipe_vertex_buffer vbuffer[],
555
                              struct pipe_vertex_element velements[],
556
                              unsigned *num_velements)
557
{
558
   struct gl_context *ctx = st->ctx;
559
   GLuint attr, attr_idx = 0;
560
561
 
562
      const GLuint mesaAttr = vp->index_to_input[attr];
563
      const struct gl_client_array *array;
564
      struct gl_buffer_object *bufobj;
565
      GLsizei stride;
566
      unsigned src_format;
567
568
 
569
      if (!array)
570
         continue;
571
572
 
573
      bufobj = array->BufferObj;
574
      assert(array->_ElementSize ==
575
             _mesa_bytes_per_vertex_attrib(array->Size, array->Type));
576
577
 
578
         /* Attribute data is in a VBO.
579
          * Recall that for VBOs, the gl_client_array->Ptr field is
580
          * really an offset from the start of the VBO, not a pointer.
581
          */
582
         struct st_buffer_object *stobj = st_buffer_object(bufobj);
583
584
 
585
            return FALSE; /* out-of-memory error probably */
586
         }
587
588
 
589
         vbuffer[attr].user_buffer = NULL;
590
         vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
591
      }
592
      else {
593
         /* wrap user data */
594
         void *ptr;
595
596
 
597
            ptr = (void *) array->Ptr;
598
         }
599
         else {
600
            /* no array, use ctx->Current.Attrib[] value */
601
            ptr = (void *) ctx->Current.Attrib[mesaAttr];
602
            stride = 0;
603
         }
604
605
 
606
607
 
608
         vbuffer[attr].user_buffer = ptr;
609
         vbuffer[attr].buffer_offset = 0;
610
      }
611
612
 
613
      vbuffer[attr].stride = stride; /* in bytes */
614
615
 
616
                                         array->Size,
617
                                         array->Format,
618
                                         array->Normalized,
619
                                         array->Integer);
620
621
 
622
                            array->InstanceDivisor, attr,
623
                            array->Size, array->Doubles, &attr_idx);
624
625
 
626
627
 
628
   return TRUE;
629
}
630
631
 
632
{
633
   struct gl_context *ctx = st->ctx;
634
   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
635
   const struct st_vertex_program *vp;
636
   const struct st_vp_variant *vpv;
637
   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
638
   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
639
   unsigned num_vbuffers, num_velements;
640
641
 
642
643
 
644
   if (!arrays)
645
      return;
646
647
 
648
   vp = st->vp;
649
   vpv = st->vp_variant;
650
651
 
652
653
 
654
    * Setup the vbuffer[] and velements[] arrays.
655
    */
656
   if (is_interleaved_arrays(vp, vpv, arrays)) {
657
      if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
658
         st->vertex_array_out_of_memory = TRUE;
659
         return;
660
      }
661
662
 
663
      if (num_velements == 0)
664
         num_vbuffers = 0;
665
   }
666
   else {
667
      if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
668
                                         velements, &num_velements)) {
669
         st->vertex_array_out_of_memory = TRUE;
670
         return;
671
      }
672
673
 
674
   }
675
676
 
677
   if (st->last_num_vbuffers > num_vbuffers) {
678
      /* Unbind remaining buffers, if any. */
679
      cso_set_vertex_buffers(st->cso_context, num_vbuffers,
680
                             st->last_num_vbuffers - num_vbuffers, NULL);
681
   }
682
   st->last_num_vbuffers = num_vbuffers;
683
   cso_set_vertex_elements(st->cso_context, num_velements, velements);
684
}
685
686
 
687
 
688
   "st_update_array",					/* name */
689
   {							/* dirty */
690
      _NEW_CURRENT_ATTRIB,                              /* mesa */
691
      ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM,     /* st */
692
   },
693
   update_array						/* update */
694
};
695