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/imports.h"
     29 #include "main/mtypes.h"
     30 #include "main/api_arrayelt.h"
     31 #include "main/bufferobj.h"
     32 #include "math/m_eval.h"
     33 #include "vbo.h"
     34 #include "vbo_context.h"
     35 
     36 
     37 static GLuint check_size( const GLfloat *attr )
     38 {
     39    if (attr[3] != 1.0F) return 4;
     40    if (attr[2] != 0.0F) return 3;
     41    if (attr[1] != 0.0F) return 2;
     42    return 1;
     43 }
     44 
     45 
     46 /**
     47  * Helper for initializing a vertex array.
     48  */
     49 static void
     50 init_array(struct gl_context *ctx, struct gl_vertex_array *cl,
     51            unsigned size, const void *pointer)
     52 {
     53    memset(cl, 0, sizeof(*cl));
     54 
     55    cl->Size = size;
     56    cl->Type = GL_FLOAT;
     57    cl->Format = GL_RGBA;
     58    cl->StrideB = 0;
     59    cl->_ElementSize = cl->Size * sizeof(GLfloat);
     60    cl->Ptr = pointer;
     61 
     62    _mesa_reference_buffer_object(ctx, &cl->BufferObj,
     63                                  ctx->Shared->NullBufferObj);
     64 }
     65 
     66 
     67 /**
     68  * Set up the vbo->currval arrays to point at the context's current
     69  * vertex attributes (with strides = 0).
     70  */
     71 static void init_legacy_currval(struct gl_context *ctx)
     72 {
     73    struct vbo_context *vbo = vbo_context(ctx);
     74    GLuint i;
     75 
     76    /* Set up a constant (StrideB == 0) array for each current
     77     * attribute:
     78     */
     79    for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
     80       struct gl_vertex_array *cl = &vbo->currval[VERT_ATTRIB_FF(i)];
     81 
     82       init_array(ctx, cl,
     83                  check_size(ctx->Current.Attrib[i]),
     84                  ctx->Current.Attrib[i]);
     85    }
     86 }
     87 
     88 
     89 static void init_generic_currval(struct gl_context *ctx)
     90 {
     91    struct vbo_context *vbo = vbo_context(ctx);
     92    GLuint i;
     93 
     94    for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
     95       struct gl_vertex_array *cl = &vbo->currval[VBO_ATTRIB_GENERIC0 + i];
     96 
     97       init_array(ctx, cl, 1, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]);
     98    }
     99 }
    100 
    101 
    102 static void init_mat_currval(struct gl_context *ctx)
    103 {
    104    struct vbo_context *vbo = vbo_context(ctx);
    105    GLuint i;
    106 
    107    /* Set up a constant (StrideB == 0) array for each current
    108     * attribute:
    109     */
    110    for (i = 0; i < MAT_ATTRIB_MAX; i++) {
    111       struct gl_vertex_array *cl =
    112          &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT + i];
    113       unsigned size;
    114 
    115       /* Size is fixed for the material attributes, for others will
    116        * be determined at runtime:
    117        */
    118       switch (i) {
    119       case MAT_ATTRIB_FRONT_SHININESS:
    120       case MAT_ATTRIB_BACK_SHININESS:
    121          size = 1;
    122          break;
    123       case MAT_ATTRIB_FRONT_INDEXES:
    124       case MAT_ATTRIB_BACK_INDEXES:
    125          size = 3;
    126          break;
    127       default:
    128          size = 4;
    129          break;
    130       }
    131 
    132       init_array(ctx, cl, size, ctx->Light.Material.Attrib[i]);
    133    }
    134 }
    135 
    136 static void
    137 vbo_draw_indirect_prims(struct gl_context *ctx,
    138                         GLuint mode,
    139                         struct gl_buffer_object *indirect_data,
    140                         GLsizeiptr indirect_offset,
    141                         unsigned draw_count,
    142                         unsigned stride,
    143                         struct gl_buffer_object *indirect_params,
    144                         GLsizeiptr indirect_params_offset,
    145                         const struct _mesa_index_buffer *ib)
    146 {
    147    struct vbo_context *vbo = vbo_context(ctx);
    148    struct _mesa_prim *prim;
    149    GLsizei i;
    150 
    151    prim = calloc(draw_count, sizeof(*prim));
    152    if (prim == NULL) {
    153       _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
    154                   (draw_count > 1) ? "Multi" : "",
    155                   ib ? "Elements" : "Arrays",
    156                   indirect_params ? "CountARB" : "");
    157       return;
    158    }
    159 
    160    prim[0].begin = 1;
    161    prim[draw_count - 1].end = 1;
    162    for (i = 0; i < draw_count; ++i, indirect_offset += stride) {
    163       prim[i].mode = mode;
    164       prim[i].indexed = !!ib;
    165       prim[i].indirect_offset = indirect_offset;
    166       prim[i].is_indirect = 1;
    167       prim[i].draw_id = i;
    168    }
    169 
    170    vbo->draw_prims(ctx, prim, draw_count,
    171                    ib, false, ~0, ~0,
    172                    NULL, 0,
    173                    ctx->DrawIndirectBuffer);
    174 
    175    free(prim);
    176 }
    177 
    178 
    179 GLboolean _vbo_CreateContext( struct gl_context *ctx )
    180 {
    181    struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
    182 
    183    ctx->vbo_context = vbo;
    184 
    185    /* Initialize the arrayelt helper
    186     */
    187    if (!ctx->aelt_context &&
    188        !_ae_create_context( ctx )) {
    189       return GL_FALSE;
    190    }
    191 
    192    init_legacy_currval( ctx );
    193    init_generic_currval( ctx );
    194    init_mat_currval( ctx );
    195    vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims);
    196 
    197    /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
    198     * of vertex program active.
    199     */
    200    {
    201       GLuint i;
    202 
    203       /* identity mapping */
    204       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_none); i++)
    205 	 vbo->map_vp_none[i] = i;
    206       /* map material attribs to generic slots */
    207       for (i = 0; i < MAT_ATTRIB_MAX; i++)
    208 	 vbo->map_vp_none[VERT_ATTRIB_GENERIC(i)]
    209             = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
    210 
    211       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_arb); i++)
    212 	 vbo->map_vp_arb[i] = i;
    213    }
    214 
    215 
    216    /* Hook our functions into exec and compile dispatch tables.  These
    217     * will pretty much be permanently installed, which means that the
    218     * vtxfmt mechanism can be removed now.
    219     */
    220    vbo_exec_init( ctx );
    221    if (ctx->API == API_OPENGL_COMPAT)
    222       vbo_save_init( ctx );
    223 
    224    _math_init_eval();
    225 
    226    return GL_TRUE;
    227 }
    228 
    229 
    230 void _vbo_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
    231 {
    232    vbo_exec_invalidate_state(ctx, new_state);
    233 }
    234 
    235 
    236 void _vbo_DestroyContext( struct gl_context *ctx )
    237 {
    238    struct vbo_context *vbo = vbo_context(ctx);
    239 
    240    if (ctx->aelt_context) {
    241       _ae_destroy_context( ctx );
    242       ctx->aelt_context = NULL;
    243    }
    244 
    245    if (vbo) {
    246       GLuint i;
    247 
    248       for (i = 0; i < VBO_ATTRIB_MAX; i++) {
    249          _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
    250       }
    251 
    252       vbo_exec_destroy(ctx);
    253       if (ctx->API == API_OPENGL_COMPAT)
    254          vbo_save_destroy(ctx);
    255       free(vbo);
    256       ctx->vbo_context = NULL;
    257    }
    258 }
    259 
    260 
    261 void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
    262 {
    263    struct vbo_context *vbo = vbo_context(ctx);
    264    vbo->draw_prims = func;
    265 }
    266 
    267 
    268 void vbo_set_indirect_draw_func(struct gl_context *ctx,
    269                                 vbo_indirect_draw_func func)
    270 {
    271    struct vbo_context *vbo = vbo_context(ctx);
    272    vbo->draw_indirect_prims = func;
    273 }
    274