Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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