mesa: initialize "is_layered" variable to silence warning
[mesa.git] / src / mesa / vbo / vbo_exec_array.c
index cadb203c3cf234909e86dca81cc8d838366253ad..16aee3be7a45efe7728e5f4dd3185007c3d91f93 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2003 VMware, Inc.
  * Copyright 2009 VMware, Inc.
  * All Rights Reserved.
  * 
@@ -19,7 +19,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -92,7 +92,7 @@ vbo_get_minmax_index(struct gl_context *ctx,
                     const GLuint count)
 {
    const GLboolean restart = ctx->Array._PrimitiveRestart;
-   const GLuint restartIndex = ctx->Array._RestartIndex;
+   const GLuint restartIndex = _mesa_primitive_restart_index(ctx, ib->type);
    const int index_size = vbo_sizeof_ib_type(ib->type);
    const char *indices;
    GLuint i;
@@ -318,8 +318,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
       }
 
       /* check element j of each enabled array */
-      for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
-         check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
+      for (k = 0; k < Elements(arrayObj->_VertexAttrib); k++) {
+         check_array_data(ctx, &arrayObj->_VertexAttrib[k], k, j);
       }
    }
 
@@ -327,8 +327,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
       ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
    }
 
-   for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
-      unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
+   for (k = 0; k < Elements(arrayObj->_VertexAttrib); k++) {
+      unmap_array_buffer(ctx, &arrayObj->_VertexAttrib[k]);
    }
 }
 
@@ -368,7 +368,7 @@ print_draw_arrays(struct gl_context *ctx,
             exec->array.inputs[i]->Size,
             stride,
             /*exec->array.inputs[i]->Enabled,*/
-            arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
+            arrayObj->_VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
             exec->array.inputs[i]->Ptr,
             bufName);
 
@@ -405,7 +405,7 @@ recalculate_input_bindings(struct gl_context *ctx)
 {
    struct vbo_context *vbo = vbo_context(ctx);
    struct vbo_exec_context *exec = &vbo->exec;
-   struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib;
+   struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->_VertexAttrib;
    const struct gl_client_array **inputs = &exec->array.inputs[0];
    GLbitfield64 const_inputs = 0x0;
    GLuint i;
@@ -442,41 +442,77 @@ recalculate_input_bindings(struct gl_context *ctx)
       break;
 
    case VP_ARB:
-      /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
+      /* There are no shaders in OpenGL ES 1.x, so this code path should be
+       * impossible to reach.  The meta code is careful to not use shaders in
+       * ES1.
+       */
+      assert(ctx->API != API_OPENGLES);
+
+      /* In the compatibility profile of desktop OpenGL, the generic[0]
        * attribute array aliases and overrides the legacy position array.  
-       *
        * Otherwise, legacy attributes available in the legacy slots,
        * generic attributes in the generic slots and materials are not
        * available as per-vertex attributes.
+       *
+       * In all other APIs, only the generic attributes exist, and none of the
+       * slots are considered "magic."
        */
-      if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
-        inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
-      else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
-        inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
-      else {
-        inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
-         const_inputs |= VERT_BIT_POS;
-      }
+      if (ctx->API == API_OPENGL_COMPAT) {
+         if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
+            inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
+         else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
+            inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
+         else {
+            inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
+            const_inputs |= VERT_BIT_POS;
+         }
 
-      for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
-        if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
-           inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
-        else {
-           inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
+         for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
+            if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
+               inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
+            else {
+               inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
+               const_inputs |= VERT_BIT_FF(i);
+            }
+         }
+
+         for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
+            if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
+               inputs[VERT_ATTRIB_GENERIC(i)] =
+                  &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
+            else {
+               inputs[VERT_ATTRIB_GENERIC(i)] =
+                  &vbo->currval[VBO_ATTRIB_GENERIC0+i];
+               const_inputs |= VERT_BIT_GENERIC(i);
+            }
+         }
+
+         inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
+      } else {
+         /* Other parts of the code assume that inputs[0] through
+          * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL.  However, in OpenGL
+          * ES 2.0+ or OpenGL core profile, none of these arrays should ever
+          * be enabled.
+          */
+         for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
+            assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled);
+
+            inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
             const_inputs |= VERT_BIT_FF(i);
          }
-      }
 
-      for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
-        if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
-           inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
-        else {
-           inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
-            const_inputs |= VERT_BIT_GENERIC(i);
+         for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
+            if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
+               inputs[VERT_ATTRIB_GENERIC(i)] =
+                  &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
+            else {
+               inputs[VERT_ATTRIB_GENERIC(i)] =
+                  &vbo->currval[VBO_ATTRIB_GENERIC0+i];
+               const_inputs |= VERT_BIT_GENERIC(i);
+            }
          }
       }
 
-      inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
       break;
    }
 
@@ -543,11 +579,11 @@ vbo_handle_primitive_restart(struct gl_context *ctx,
        ctx->Const.PrimitiveRestartInSoftware &&
        ctx->Array._PrimitiveRestart) {
       /* Handle primitive restart in software */
-      vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
+      vbo_sw_primitive_restart(ctx, prim, nr_prims, ib, NULL);
    } else {
       /* Call driver directly for draw_prims */
       vbo->draw_prims(ctx, prim, nr_prims, ib,
-                      index_bounds_valid, min_index, max_index, NULL);
+                      index_bounds_valid, min_index, max_index, NULL, NULL);
    }
 }
 
@@ -575,6 +611,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
    prim[0].mode = mode;
    prim[0].num_instances = numInstances;
    prim[0].base_instance = baseInstance;
+   prim[0].is_indirect = 0;
 
    /* Implement the primitive restart index */
    if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
@@ -612,7 +649,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
          /* draw one or two prims */
          check_buffers_are_unmapped(exec->array.inputs);
          vbo->draw_prims(ctx, prim, primCount, NULL,
-                         GL_TRUE, start, start + count - 1, NULL);
+                         GL_TRUE, start, start + count - 1, NULL, NULL);
       }
    }
    else {
@@ -623,7 +660,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
       check_buffers_are_unmapped(exec->array.inputs);
       vbo->draw_prims(ctx, prim, 1, NULL,
                       GL_TRUE, start, start + count - 1,
-                      NULL);
+                      NULL, NULL);
    }
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
@@ -929,6 +966,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
    prim[0].start = 0;
    prim[0].count = count;
    prim[0].indexed = 1;
+   prim[0].is_indirect = 0;
    prim[0].basevertex = basevertex;
    prim[0].num_instances = numInstances;
    prim[0].base_instance = baseInstance;
@@ -1298,6 +1336,16 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
       }
    }
 
+   /* Draw primitives individually if one count is zero, so we can easily skip
+    * that primitive.
+    */
+   for (i = 0; i < primcount; i++) {
+      if (count[i] == 0) {
+         fallback = GL_TRUE;
+         break;
+      }
+   }
+
    /* If the index buffer isn't in a VBO, then treating the application's
     * subranges of the index buffer as one large index buffer may lead to
     * us reading unmapped memory.
@@ -1322,6 +1370,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
         prim[i].indexed = 1;
          prim[i].num_instances = 1;
          prim[i].base_instance = 0;
+         prim[i].is_indirect = 0;
         if (basevertex != NULL)
            prim[i].basevertex = basevertex[i];
         else
@@ -1334,6 +1383,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
    } else {
       /* render one prim at a time */
       for (i = 0; i < primcount; i++) {
+        if (count[i] == 0)
+           continue;
         ib.count = count[i];
         ib.type = type;
         ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
@@ -1349,6 +1400,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
         prim[0].indexed = 1;
          prim[0].num_instances = 1;
          prim[0].base_instance = 0;
+         prim[0].is_indirect = 0;
         if (basevertex != NULL)
            prim[0].basevertex = basevertex[i];
         else
@@ -1371,7 +1423,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
 static void GLAPIENTRY
 vbo_exec_MultiDrawElements(GLenum mode,
                           const GLsizei *count, GLenum type,
-                          const GLvoid **indices,
+                          const GLvoid * const *indices,
                           GLsizei primcount)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -1416,6 +1468,16 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
       return;
    }
 
+   if (ctx->Driver.GetTransformFeedbackVertexCount &&
+       (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
+        (ctx->Const.PrimitiveRestartInSoftware &&
+         ctx->Array._PrimitiveRestart) ||
+        !vbo_all_varyings_in_vbos(exec->array.inputs))) {
+      GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
+      vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0);
+      return;
+   }
+
    vbo_bind_arrays(ctx);
 
    /* init most fields to zero */
@@ -1425,6 +1487,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
    prim[0].mode = mode;
    prim[0].num_instances = numInstances;
    prim[0].base_instance = 0;
+   prim[0].is_indirect = 0;
 
    /* Maybe we should do some primitive splitting for primitive restart
     * (like in DrawArrays), but we have no way to know how many vertices
@@ -1432,7 +1495,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
 
    check_buffers_are_unmapped(exec->array.inputs);
    vbo->draw_prims(ctx, prim, 1, NULL,
-                   GL_TRUE, 0, 0, obj);
+                   GL_TRUE, 0, 0, obj, NULL);
 
    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
       _mesa_flush(ctx);
@@ -1506,6 +1569,252 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
    vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
 }
 
+static void
+vbo_validated_drawarraysindirect(struct gl_context *ctx,
+                                 GLenum mode, const GLvoid *indirect)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   struct _mesa_prim prim[1];
+
+   vbo_bind_arrays(ctx);
+
+   memset(prim, 0, sizeof(prim));
+   prim[0].begin = 1;
+   prim[0].end = 1;
+   prim[0].mode = mode;
+   prim[0].is_indirect = 1;
+   prim[0].indirect_offset = (GLsizeiptr)indirect;
+
+   /* NOTE: We do NOT want to handle primitive restart here, nor perform any
+    * other checks that require knowledge of the values in the command buffer.
+    * That would defeat the whole purpose of this function.
+    */
+
+   check_buffers_are_unmapped(exec->array.inputs);
+   vbo->draw_prims(ctx, prim, 1,
+                   NULL, GL_TRUE, 0, ~0,
+                   NULL,
+                   ctx->DrawIndirectBuffer);
+
+   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
+      _mesa_flush(ctx);
+}
+
+static void
+vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
+                                      GLenum mode,
+                                      const GLvoid *indirect,
+                                      GLsizei primcount, GLsizei stride)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   struct _mesa_prim *prim;
+   GLsizei i;
+   GLsizeiptr offset = (GLsizeiptr)indirect;
+
+   if (primcount == 0)
+      return;
+   prim = calloc(primcount, sizeof(*prim));
+   if (prim == NULL) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
+      return;
+   }
+
+   vbo_bind_arrays(ctx);
+
+   prim[0].begin = 1;
+   prim[primcount - 1].end = 1;
+   for (i = 0; i < primcount; ++i, offset += stride) {
+      prim[i].mode = mode;
+      prim[i].indirect_offset = offset;
+      prim[i].is_indirect = 1;
+   }
+
+   check_buffers_are_unmapped(exec->array.inputs);
+   vbo->draw_prims(ctx, prim, primcount,
+                   NULL, GL_TRUE, 0, ~0,
+                   NULL,
+                   ctx->DrawIndirectBuffer);
+
+   free(prim);
+
+   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
+      _mesa_flush(ctx);
+}
+
+static void
+vbo_validated_drawelementsindirect(struct gl_context *ctx,
+                                   GLenum mode, GLenum type,
+                                   const GLvoid *indirect)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   struct _mesa_index_buffer ib;
+   struct _mesa_prim prim[1];
+
+   vbo_bind_arrays(ctx);
+
+   ib.count = 0; /* unknown */
+   ib.type = type;
+   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
+   ib.ptr = NULL;
+
+   memset(prim, 0, sizeof(prim));
+   prim[0].begin = 1;
+   prim[0].end = 1;
+   prim[0].mode = mode;
+   prim[0].indexed = 1;
+   prim[0].indirect_offset = (GLsizeiptr)indirect;
+   prim[0].is_indirect = 1;
+
+   check_buffers_are_unmapped(exec->array.inputs);
+   vbo->draw_prims(ctx, prim, 1,
+                   &ib, GL_TRUE, 0, ~0,
+                   NULL,
+                   ctx->DrawIndirectBuffer);
+
+   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
+      _mesa_flush(ctx);
+}
+
+static void
+vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
+                                        GLenum mode, GLenum type,
+                                        const GLvoid *indirect,
+                                        GLsizei primcount, GLsizei stride)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   struct _mesa_index_buffer ib;
+   struct _mesa_prim *prim;
+   GLsizei i;
+   GLsizeiptr offset = (GLsizeiptr)indirect;
+
+   if (primcount == 0)
+      return;
+   prim = calloc(primcount, sizeof(*prim));
+   if (prim == NULL) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
+      return;
+   }
+
+   vbo_bind_arrays(ctx);
+
+   /* NOTE: ElementArrayBufferObj is guaranteed to be a VBO. */
+
+   ib.count = 0; /* unknown */
+   ib.type = type;
+   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
+   ib.ptr = NULL;
+
+   prim[0].begin = 1;
+   prim[primcount - 1].end = 1;
+   for (i = 0; i < primcount; ++i, offset += stride) {
+      prim[i].mode = mode;
+      prim[i].indexed = 1;
+      prim[i].indirect_offset = offset;
+      prim[i].is_indirect = 1;
+   }
+
+   check_buffers_are_unmapped(exec->array.inputs);
+   vbo->draw_prims(ctx, prim, primcount,
+                   &ib, GL_TRUE, 0, ~0,
+                   NULL,
+                   ctx->DrawIndirectBuffer);
+
+   free(prim);
+
+   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
+      _mesa_flush(ctx);
+}
+
+/**
+ * Like [Multi]DrawArrays/Elements, but they take most arguments from
+ * a buffer object.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_DRAW)
+      _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
+                  _mesa_lookup_enum_by_nr(mode), indirect);
+
+   if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
+      return;
+
+   vbo_validated_drawarraysindirect(ctx, mode, indirect);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type,
+                              const GLvoid *indirect)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_DRAW)
+      _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
+                  _mesa_lookup_enum_by_nr(mode),
+                  _mesa_lookup_enum_by_nr(type), indirect);
+
+   if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
+      return;
+
+   vbo_validated_drawelementsindirect(ctx, mode, type, indirect);
+}
+
+static void GLAPIENTRY
+vbo_exec_MultiDrawArraysIndirect(GLenum mode,
+                                 const GLvoid *indirect,
+                                 GLsizei primcount, GLsizei stride)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_DRAW)
+      _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
+                  _mesa_lookup_enum_by_nr(mode), indirect, primcount, stride);
+
+   /* If <stride> is zero, the array elements are treated as tightly packed. */
+   if (stride == 0)
+      stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
+
+   if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode,
+                                               indirect,
+                                               primcount, stride))
+      return;
+
+   vbo_validated_multidrawarraysindirect(ctx, mode,
+                                         indirect,
+                                         primcount, stride);
+}
+
+static void GLAPIENTRY
+vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
+                                   const GLvoid *indirect,
+                                   GLsizei primcount, GLsizei stride)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_DRAW)
+      _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
+                  _mesa_lookup_enum_by_nr(mode),
+                  _mesa_lookup_enum_by_nr(type), indirect, primcount, stride);
+
+   /* If <stride> is zero, the array elements are treated as tightly packed. */
+   if (stride == 0)
+      stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
+
+   if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type,
+                                                 indirect,
+                                                 primcount, stride))
+      return;
+
+   vbo_validated_multidrawelementsindirect(ctx, mode, type,
+                                           indirect,
+                                           primcount, stride);
+}
 
 /**
  * Initialize the dispatch table with the VBO functions for drawing.
@@ -1539,6 +1848,13 @@ vbo_initialize_exec_dispatch(const struct gl_context *ctx,
       SET_DrawElementsInstancedBaseVertexBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance);
    }
 
+   if (ctx->API == API_OPENGL_CORE) {
+      SET_DrawArraysIndirect(exec, vbo_exec_DrawArraysIndirect);
+      SET_DrawElementsIndirect(exec, vbo_exec_DrawElementsIndirect);
+      SET_MultiDrawArraysIndirect(exec, vbo_exec_MultiDrawArraysIndirect);
+      SET_MultiDrawElementsIndirect(exec, vbo_exec_MultiDrawElementsIndirect);
+   }
+
    if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
       SET_DrawArraysInstancedARB(exec, vbo_exec_DrawArraysInstanced);
       SET_DrawElementsInstancedARB(exec, vbo_exec_DrawElementsInstanced);