Home | History | Annotate | Download | only in vbo
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2005  Brian Paul   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 "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Keith Whitwell <keithw (at) vmware.com>
     26  */
     27 
     28 #include "main/mtypes.h"
     29 #include "main/bufferobj.h"
     30 #include "math/m_eval.h"
     31 #include "vbo.h"
     32 #include "vbo_context.h"
     33 
     34 
     35 static GLuint
     36 check_size(const GLfloat *attr)
     37 {
     38    if (attr[3] != 1.0F)
     39       return 4;
     40    if (attr[2] != 0.0F)
     41       return 3;
     42    if (attr[1] != 0.0F)
     43       return 2;
     44    return 1;
     45 }
     46 
     47 
     48 /**
     49  * Helper for initializing a vertex array.
     50  */
     51 static void
     52 init_array(struct gl_context *ctx, struct gl_vertex_array *cl,
     53            unsigned size, const void *pointer)
     54 {
     55    memset(cl, 0, sizeof(*cl));
     56 
     57    cl->Size = size;
     58    cl->Type = GL_FLOAT;
     59    cl->Format = GL_RGBA;
     60    cl->StrideB = 0;
     61    cl->_ElementSize = cl->Size * sizeof(GLfloat);
     62    cl->Ptr = pointer;
     63 
     64    _mesa_reference_buffer_object(ctx, &cl->BufferObj,
     65                                  ctx->Shared->NullBufferObj);
     66 }
     67 
     68 
     69 /**
     70  * Set up the vbo->currval arrays to point at the context's current
     71  * vertex attributes (with strides = 0).
     72  */
     73 static void
     74 init_legacy_currval(struct gl_context *ctx)
     75 {
     76    struct vbo_context *vbo = vbo_context(ctx);
     77    GLuint i;
     78 
     79    /* Set up a constant (StrideB == 0) array for each current
     80     * attribute:
     81     */
     82    for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
     83       struct gl_vertex_array *cl = &vbo->currval[VERT_ATTRIB_FF(i)];
     84 
     85       init_array(ctx, cl,
     86                  check_size(ctx->Current.Attrib[i]),
     87                  ctx->Current.Attrib[i]);
     88    }
     89 }
     90 
     91 
     92 static void
     93 init_generic_currval(struct gl_context *ctx)
     94 {
     95    struct vbo_context *vbo = vbo_context(ctx);
     96    GLuint i;
     97 
     98    for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
     99       struct gl_vertex_array *cl = &vbo->currval[VBO_ATTRIB_GENERIC0 + i];
    100 
    101       init_array(ctx, cl, 1, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]);
    102    }
    103 }
    104 
    105 
    106 static void
    107 init_mat_currval(struct gl_context *ctx)
    108 {
    109    struct vbo_context *vbo = vbo_context(ctx);
    110    GLuint i;
    111 
    112    /* Set up a constant (StrideB == 0) array for each current
    113     * attribute:
    114     */
    115    for (i = 0; i < MAT_ATTRIB_MAX; i++) {
    116       struct gl_vertex_array *cl =
    117          &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT + i];
    118       unsigned size;
    119 
    120       /* Size is fixed for the material attributes, for others will
    121        * be determined at runtime:
    122        */
    123       switch (i) {
    124       case MAT_ATTRIB_FRONT_SHININESS:
    125       case MAT_ATTRIB_BACK_SHININESS:
    126          size = 1;
    127          break;
    128       case MAT_ATTRIB_FRONT_INDEXES:
    129       case MAT_ATTRIB_BACK_INDEXES:
    130          size = 3;
    131          break;
    132       default:
    133          size = 4;
    134          break;
    135       }
    136 
    137       init_array(ctx, cl, size, ctx->Light.Material.Attrib[i]);
    138    }
    139 }
    140 
    141 static void
    142 vbo_draw_indirect_prims(struct gl_context *ctx,
    143                         GLuint mode,
    144                         struct gl_buffer_object *indirect_data,
    145                         GLsizeiptr indirect_offset,
    146                         unsigned draw_count,
    147                         unsigned stride,
    148                         struct gl_buffer_object *indirect_params,
    149                         GLsizeiptr indirect_params_offset,
    150                         const struct _mesa_index_buffer *ib)
    151 {
    152    struct vbo_context *vbo = vbo_context(ctx);
    153    struct _mesa_prim *prim;
    154    GLsizei i;
    155 
    156    prim = calloc(draw_count, sizeof(*prim));
    157    if (prim == NULL) {
    158       _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
    159                   (draw_count > 1) ? "Multi" : "",
    160                   ib ? "Elements" : "Arrays",
    161                   indirect_params ? "CountARB" : "");
    162       return;
    163    }
    164 
    165    prim[0].begin = 1;
    166    prim[draw_count - 1].end = 1;
    167    for (i = 0; i < draw_count; ++i, indirect_offset += stride) {
    168       prim[i].mode = mode;
    169       prim[i].indexed = !!ib;
    170       prim[i].indirect_offset = indirect_offset;
    171       prim[i].is_indirect = 1;
    172       prim[i].draw_id = i;
    173    }
    174 
    175    vbo->draw_prims(ctx, prim, draw_count,
    176                    ib, false, 0, ~0,
    177                    NULL, 0,
    178                    ctx->DrawIndirectBuffer);
    179 
    180    free(prim);
    181 }
    182 
    183 
    184 GLboolean
    185 _vbo_CreateContext(struct gl_context *ctx)
    186 {
    187    struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
    188 
    189    ctx->vbo_context = vbo;
    190 
    191    /* Initialize the arrayelt helper
    192     */
    193    if (!ctx->aelt_context &&
    194        !_ae_create_context(ctx)) {
    195       return GL_FALSE;
    196    }
    197 
    198    init_legacy_currval(ctx);
    199    init_generic_currval(ctx);
    200    init_mat_currval(ctx);
    201    vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims);
    202 
    203    /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
    204     * of vertex program active.
    205     */
    206    {
    207       GLuint i;
    208 
    209       /* make sure all VBO_ATTRIB_ values can fit in an unsigned byte */
    210       STATIC_ASSERT(VBO_ATTRIB_MAX <= 255);
    211 
    212       /* identity mapping */
    213       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_none); i++)
    214          vbo->map_vp_none[i] = i;
    215       /* map material attribs to generic slots */
    216       for (i = 0; i < MAT_ATTRIB_MAX; i++)
    217          vbo->map_vp_none[VERT_ATTRIB_GENERIC(i)]
    218             = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
    219 
    220       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_arb); i++)
    221          vbo->map_vp_arb[i] = i;
    222    }
    223 
    224 
    225    /* Hook our functions into exec and compile dispatch tables.  These
    226     * will pretty much be permanently installed, which means that the
    227     * vtxfmt mechanism can be removed now.
    228     */
    229    vbo_exec_init(ctx);
    230    if (ctx->API == API_OPENGL_COMPAT)
    231       vbo_save_init(ctx);
    232 
    233    _math_init_eval();
    234 
    235    return GL_TRUE;
    236 }
    237 
    238 
    239 void
    240 _vbo_DestroyContext(struct gl_context *ctx)
    241 {
    242    struct vbo_context *vbo = vbo_context(ctx);
    243 
    244    if (ctx->aelt_context) {
    245       _ae_destroy_context(ctx);
    246       ctx->aelt_context = NULL;
    247    }
    248 
    249    if (vbo) {
    250       GLuint i;
    251 
    252       for (i = 0; i < VBO_ATTRIB_MAX; i++) {
    253          _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
    254       }
    255 
    256       vbo_exec_destroy(ctx);
    257       if (ctx->API == API_OPENGL_COMPAT)
    258          vbo_save_destroy(ctx);
    259       free(vbo);
    260       ctx->vbo_context = NULL;
    261    }
    262 }
    263 
    264 
    265 void
    266 vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
    267 {
    268    struct vbo_context *vbo = vbo_context(ctx);
    269    vbo->draw_prims = func;
    270 }
    271 
    272 
    273 void
    274 vbo_set_indirect_draw_func(struct gl_context *ctx,
    275                            vbo_indirect_draw_func func)
    276 {
    277    struct vbo_context *vbo = vbo_context(ctx);
    278    vbo->draw_indirect_prims = func;
    279 }
    280