Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  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.  
  25. #include <stdbool.h>
  26. #include "glheader.h"
  27. #include "api_validate.h"
  28. #include "bufferobj.h"
  29. #include "context.h"
  30. #include "imports.h"
  31. #include "mtypes.h"
  32. #include "enums.h"
  33. #include "vbo/vbo.h"
  34. #include "transformfeedback.h"
  35. #include <stdbool.h>
  36.  
  37.  
  38. /**
  39.  * \return  number of bytes in array [count] of type.
  40.  */
  41. static GLsizei
  42. index_bytes(GLenum type, GLsizei count)
  43. {
  44.    if (type == GL_UNSIGNED_INT) {
  45.       return count * sizeof(GLuint);
  46.    }
  47.    else if (type == GL_UNSIGNED_BYTE) {
  48.       return count * sizeof(GLubyte);
  49.    }
  50.    else {
  51.       ASSERT(type == GL_UNSIGNED_SHORT);
  52.       return count * sizeof(GLushort);
  53.    }
  54. }
  55.  
  56.  
  57. /**
  58.  * Find the max index in the given element/index buffer
  59.  */
  60. GLuint
  61. _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type,
  62.                        const void *indices,
  63.                        struct gl_buffer_object *elementBuf)
  64. {
  65.    const GLubyte *map = NULL;
  66.    GLuint max = 0;
  67.    GLuint i;
  68.  
  69.    if (_mesa_is_bufferobj(elementBuf)) {
  70.       /* elements are in a user-defined buffer object.  need to map it */
  71.       map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size,
  72.                                        GL_MAP_READ_BIT, elementBuf);
  73.       /* Actual address is the sum of pointers */
  74.       indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
  75.    }
  76.  
  77.    if (type == GL_UNSIGNED_INT) {
  78.       for (i = 0; i < count; i++)
  79.          if (((GLuint *) indices)[i] > max)
  80.             max = ((GLuint *) indices)[i];
  81.    }
  82.    else if (type == GL_UNSIGNED_SHORT) {
  83.       for (i = 0; i < count; i++)
  84.          if (((GLushort *) indices)[i] > max)
  85.             max = ((GLushort *) indices)[i];
  86.    }
  87.    else {
  88.       ASSERT(type == GL_UNSIGNED_BYTE);
  89.       for (i = 0; i < count; i++)
  90.          if (((GLubyte *) indices)[i] > max)
  91.             max = ((GLubyte *) indices)[i];
  92.    }
  93.  
  94.    if (map) {
  95.       ctx->Driver.UnmapBuffer(ctx, elementBuf);
  96.    }
  97.  
  98.    return max;
  99. }
  100.  
  101.  
  102. /**
  103.  * Check if OK to draw arrays/elements.
  104.  */
  105. static GLboolean
  106. check_valid_to_render(struct gl_context *ctx, const char *function)
  107. {
  108.    if (!_mesa_valid_to_render(ctx, function)) {
  109.       return GL_FALSE;
  110.    }
  111.  
  112.    switch (ctx->API) {
  113.    case API_OPENGLES2:
  114.       /* For ES2, we can draw if any vertex array is enabled (and we
  115.        * should always have a vertex program/shader). */
  116.       if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current)
  117.          return GL_FALSE;
  118.       break;
  119.  
  120.    case API_OPENGLES:
  121.       /* For OpenGL ES, only draw if we have vertex positions
  122.        */
  123.       if (!ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
  124.          return GL_FALSE;
  125.       break;
  126.  
  127.    case API_OPENGL_COMPAT:
  128.    case API_OPENGL_CORE:
  129.       {
  130.          const struct gl_shader_program *vsProg =
  131.             ctx->Shader.CurrentVertexProgram;
  132.          GLboolean haveVertexShader = (vsProg && vsProg->LinkStatus);
  133.          GLboolean haveVertexProgram = ctx->VertexProgram._Enabled;
  134.          if (haveVertexShader || haveVertexProgram) {
  135.             /* Draw regardless of whether or not we have any vertex arrays.
  136.              * (Ex: could draw a point using a constant vertex pos)
  137.              */
  138.             return GL_TRUE;
  139.          }
  140.          else {
  141.             /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
  142.              * array [0]).
  143.              */
  144.             return (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled ||
  145.                     ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled);
  146.          }
  147.       }
  148.       break;
  149.  
  150.    default:
  151.       assert(!"Invalid API value in check_valid_to_render()");
  152.    }
  153.  
  154.    return GL_TRUE;
  155. }
  156.  
  157.  
  158. /**
  159.  * Do bounds checking on array element indexes.  Check that the vertices
  160.  * pointed to by the indices don't lie outside buffer object bounds.
  161.  * \return GL_TRUE if OK, GL_FALSE if any indexed vertex goes is out of bounds
  162.  */
  163. static GLboolean
  164. check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type,
  165.                    const GLvoid *indices, GLint basevertex)
  166. {
  167.    struct _mesa_prim prim;
  168.    struct _mesa_index_buffer ib;
  169.    GLuint min, max;
  170.  
  171.    /* Only the X Server needs to do this -- otherwise, accessing outside
  172.     * array/BO bounds allows application termination.
  173.     */
  174.    if (!ctx->Const.CheckArrayBounds)
  175.       return GL_TRUE;
  176.  
  177.    memset(&prim, 0, sizeof(prim));
  178.    prim.count = count;
  179.  
  180.    memset(&ib, 0, sizeof(ib));
  181.    ib.type = type;
  182.    ib.ptr = indices;
  183.    ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
  184.  
  185.    vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1);
  186.  
  187.    if ((int)(min + basevertex) < 0 ||
  188.        max + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
  189.       /* the max element is out of bounds of one or more enabled arrays */
  190.       _mesa_warning(ctx, "glDrawElements() index=%u is out of bounds (max=%u)",
  191.                     max, ctx->Array.ArrayObj->_MaxElement);
  192.       return GL_FALSE;
  193.    }
  194.  
  195.    return GL_TRUE;
  196. }
  197.  
  198.  
  199. /**
  200.  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
  201.  * etc?  The set of legal values depends on whether geometry shaders/programs
  202.  * are supported.
  203.  * Note: This may be called during display list compilation.
  204.  */
  205. bool
  206. _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode)
  207. {
  208.    switch (mode) {
  209.    case GL_POINTS:
  210.    case GL_LINES:
  211.    case GL_LINE_LOOP:
  212.    case GL_LINE_STRIP:
  213.    case GL_TRIANGLES:
  214.    case GL_TRIANGLE_STRIP:
  215.    case GL_TRIANGLE_FAN:
  216.       return true;
  217.    case GL_QUADS:
  218.    case GL_QUAD_STRIP:
  219.    case GL_POLYGON:
  220.       return (ctx->API == API_OPENGL_COMPAT);
  221.    case GL_LINES_ADJACENCY:
  222.    case GL_LINE_STRIP_ADJACENCY:
  223.    case GL_TRIANGLES_ADJACENCY:
  224.    case GL_TRIANGLE_STRIP_ADJACENCY:
  225.       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;
  226.    default:
  227.       return false;
  228.    }
  229. }
  230.  
  231.  
  232. /**
  233.  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
  234.  * etc?  Also, do additional checking related to transformation feedback.
  235.  * Note: this function cannot be called during glNewList(GL_COMPILE) because
  236.  * this code depends on current transform feedback state.
  237.  */
  238. GLboolean
  239. _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
  240. {
  241.    bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode);
  242.  
  243.    if (!valid_enum) {
  244.       _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode);
  245.       return GL_FALSE;
  246.    }
  247.  
  248.    /* From the GL_EXT_transform_feedback spec:
  249.     *
  250.     *     "The error INVALID_OPERATION is generated if Begin, or any command
  251.     *      that performs an explicit Begin, is called when:
  252.     *
  253.     *      * a geometry shader is not active and <mode> does not match the
  254.     *        allowed begin modes for the current transform feedback state as
  255.     *        given by table X.1.
  256.     *
  257.     *      * a geometry shader is active and the output primitive type of the
  258.     *        geometry shader does not match the allowed begin modes for the
  259.     *        current transform feedback state as given by table X.1.
  260.     *
  261.     */
  262.    if (_mesa_is_xfb_active_and_unpaused(ctx)) {
  263.       GLboolean pass = GL_TRUE;
  264.  
  265.       switch (mode) {
  266.       case GL_POINTS:
  267.          pass = ctx->TransformFeedback.Mode == GL_POINTS;
  268.          break;
  269.       case GL_LINES:
  270.       case GL_LINE_STRIP:
  271.       case GL_LINE_LOOP:
  272.          pass = ctx->TransformFeedback.Mode == GL_LINES;
  273.          break;
  274.       default:
  275.          pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
  276.          break;
  277.       }
  278.       if (!pass) {
  279.          _mesa_error(ctx, GL_INVALID_OPERATION,
  280.                      "%s(mode=%s vs transform feedback %s)",
  281.                      name,
  282.                      _mesa_lookup_prim_by_nr(mode),
  283.                      _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
  284.          return GL_FALSE;
  285.       }
  286.    }
  287.  
  288.    return GL_TRUE;
  289. }
  290.  
  291. /**
  292.  * Verify that the element type is valid.
  293.  *
  294.  * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
  295.  */
  296. static bool
  297. valid_elements_type(struct gl_context *ctx, GLenum type, const char *name)
  298. {
  299.    switch (type) {
  300.    case GL_UNSIGNED_BYTE:
  301.    case GL_UNSIGNED_SHORT:
  302.    case GL_UNSIGNED_INT:
  303.       return true;
  304.  
  305.    default:
  306.       _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name,
  307.                   _mesa_lookup_enum_by_nr(type));
  308.       return false;
  309.    }
  310. }
  311.  
  312. /**
  313.  * Error checking for glDrawElements().  Includes parameter checking
  314.  * and VBO bounds checking.
  315.  * \return GL_TRUE if OK to render, GL_FALSE if error found
  316.  */
  317. GLboolean
  318. _mesa_validate_DrawElements(struct gl_context *ctx,
  319.                             GLenum mode, GLsizei count, GLenum type,
  320.                             const GLvoid *indices, GLint basevertex)
  321. {
  322.    FLUSH_CURRENT(ctx, 0);
  323.  
  324.    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
  325.     * Primitive Capture):
  326.     *
  327.     *   The error INVALID_OPERATION is also generated by DrawElements,
  328.     *   DrawElementsInstanced, and DrawRangeElements while transform feedback
  329.     *   is active and not paused, regardless of mode.
  330.     */
  331.    if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
  332.       _mesa_error(ctx, GL_INVALID_OPERATION,
  333.                   "glDrawElements(transform feedback active)");
  334.       return GL_FALSE;
  335.    }
  336.  
  337.    if (count <= 0) {
  338.       if (count < 0)
  339.          _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
  340.       return GL_FALSE;
  341.    }
  342.  
  343.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElements")) {
  344.       return GL_FALSE;
  345.    }
  346.  
  347.    if (!valid_elements_type(ctx, type, "glDrawElements"))
  348.       return GL_FALSE;
  349.  
  350.    if (!check_valid_to_render(ctx, "glDrawElements"))
  351.       return GL_FALSE;
  352.  
  353.    /* Vertex buffer object tests */
  354.    if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
  355.       /* use indices in the buffer object */
  356.       /* make sure count doesn't go outside buffer bounds */
  357.       if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
  358.          _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
  359.          return GL_FALSE;
  360.       }
  361.    }
  362.    else {
  363.       /* not using a VBO */
  364.       if (!indices)
  365.          return GL_FALSE;
  366.    }
  367.  
  368.    if (!check_index_bounds(ctx, count, type, indices, basevertex))
  369.       return GL_FALSE;
  370.  
  371.    return GL_TRUE;
  372. }
  373.  
  374.  
  375. /**
  376.  * Error checking for glMultiDrawElements().  Includes parameter checking
  377.  * and VBO bounds checking.
  378.  * \return GL_TRUE if OK to render, GL_FALSE if error found
  379.  */
  380. GLboolean
  381. _mesa_validate_MultiDrawElements(struct gl_context *ctx,
  382.                                  GLenum mode, const GLsizei *count,
  383.                                  GLenum type, const GLvoid * const *indices,
  384.                                  GLuint primcount, const GLint *basevertex)
  385. {
  386.    unsigned i;
  387.  
  388.    FLUSH_CURRENT(ctx, 0);
  389.  
  390.    for (i = 0; i < primcount; i++) {
  391.       if (count[i] <= 0) {
  392.          if (count[i] < 0)
  393.             _mesa_error(ctx, GL_INVALID_VALUE,
  394.                         "glMultiDrawElements(count)" );
  395.          return GL_FALSE;
  396.       }
  397.    }
  398.  
  399.    if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
  400.       return GL_FALSE;
  401.    }
  402.  
  403.    if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
  404.       return GL_FALSE;
  405.  
  406.    if (!check_valid_to_render(ctx, "glMultiDrawElements"))
  407.       return GL_FALSE;
  408.  
  409.    /* Vertex buffer object tests */
  410.    if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
  411.       /* use indices in the buffer object */
  412.       /* make sure count doesn't go outside buffer bounds */
  413.       for (i = 0; i < primcount; i++) {
  414.          if (index_bytes(type, count[i]) >
  415.              ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
  416.             _mesa_warning(ctx,
  417.                           "glMultiDrawElements index out of buffer bounds");
  418.             return GL_FALSE;
  419.          }
  420.       }
  421.    }
  422.    else {
  423.       /* not using a VBO */
  424.       for (i = 0; i < primcount; i++) {
  425.          if (!indices[i])
  426.             return GL_FALSE;
  427.       }
  428.    }
  429.  
  430.    for (i = 0; i < primcount; i++) {
  431.       if (!check_index_bounds(ctx, count[i], type, indices[i],
  432.                               basevertex ? basevertex[i] : 0))
  433.          return GL_FALSE;
  434.    }
  435.  
  436.    return GL_TRUE;
  437. }
  438.  
  439.  
  440. /**
  441.  * Error checking for glDrawRangeElements().  Includes parameter checking
  442.  * and VBO bounds checking.
  443.  * \return GL_TRUE if OK to render, GL_FALSE if error found
  444.  */
  445. GLboolean
  446. _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
  447.                                  GLuint start, GLuint end,
  448.                                  GLsizei count, GLenum type,
  449.                                  const GLvoid *indices, GLint basevertex)
  450. {
  451.    FLUSH_CURRENT(ctx, 0);
  452.  
  453.    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
  454.     * Primitive Capture):
  455.     *
  456.     *   The error INVALID_OPERATION is also generated by DrawElements,
  457.     *   DrawElementsInstanced, and DrawRangeElements while transform feedback
  458.     *   is active and not paused, regardless of mode.
  459.     */
  460.    if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
  461.       _mesa_error(ctx, GL_INVALID_OPERATION,
  462.                   "glDrawElements(transform feedback active)");
  463.       return GL_FALSE;
  464.    }
  465.  
  466.    if (count <= 0) {
  467.       if (count < 0)
  468.          _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
  469.       return GL_FALSE;
  470.    }
  471.  
  472.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawRangeElements")) {
  473.       return GL_FALSE;
  474.    }
  475.  
  476.    if (end < start) {
  477.       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
  478.       return GL_FALSE;
  479.    }
  480.  
  481.    if (!valid_elements_type(ctx, type, "glDrawRangeElements"))
  482.       return GL_FALSE;
  483.  
  484.    if (!check_valid_to_render(ctx, "glDrawRangeElements"))
  485.       return GL_FALSE;
  486.  
  487.    /* Vertex buffer object tests */
  488.    if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
  489.       /* use indices in the buffer object */
  490.       /* make sure count doesn't go outside buffer bounds */
  491.       if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
  492.          _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
  493.          return GL_FALSE;
  494.       }
  495.    }
  496.    else {
  497.       /* not using a VBO */
  498.       if (!indices)
  499.          return GL_FALSE;
  500.    }
  501.  
  502.    if (!check_index_bounds(ctx, count, type, indices, basevertex))
  503.       return GL_FALSE;
  504.  
  505.    return GL_TRUE;
  506. }
  507.  
  508.  
  509. /**
  510.  * Called from the tnl module to error check the function parameters and
  511.  * verify that we really can draw something.
  512.  * \return GL_TRUE if OK to render, GL_FALSE if error found
  513.  */
  514. GLboolean
  515. _mesa_validate_DrawArrays(struct gl_context *ctx,
  516.                           GLenum mode, GLint start, GLsizei count)
  517. {
  518.    struct gl_transform_feedback_object *xfb_obj
  519.       = ctx->TransformFeedback.CurrentObject;
  520.    FLUSH_CURRENT(ctx, 0);
  521.  
  522.    if (count <= 0) {
  523.       if (count < 0)
  524.          _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  525.       return GL_FALSE;
  526.    }
  527.  
  528.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArrays")) {
  529.       return GL_FALSE;
  530.    }
  531.  
  532.    if (!check_valid_to_render(ctx, "glDrawArrays"))
  533.       return GL_FALSE;
  534.  
  535.    if (ctx->Const.CheckArrayBounds) {
  536.       if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
  537.          return GL_FALSE;
  538.    }
  539.  
  540.    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
  541.     * Primitive Capture):
  542.     *
  543.     *   The error INVALID_OPERATION is generated by DrawArrays and
  544.     *   DrawArraysInstanced if recording the vertices of a primitive to the
  545.     *   buffer objects being used for transform feedback purposes would result
  546.     *   in either exceeding the limits of any buffer object’s size, or in
  547.     *   exceeding the end position offset + size − 1, as set by
  548.     *   BindBufferRange.
  549.     *
  550.     * This is in contrast to the behaviour of desktop GL, where the extra
  551.     * primitives are silently dropped from the transform feedback buffer.
  552.     */
  553.    if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
  554.       size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1);
  555.       if (xfb_obj->GlesRemainingPrims < prim_count) {
  556.          _mesa_error(ctx, GL_INVALID_OPERATION,
  557.                      "glDrawArrays(exceeds transform feedback size)");
  558.          return GL_FALSE;
  559.       }
  560.       xfb_obj->GlesRemainingPrims -= prim_count;
  561.    }
  562.  
  563.    return GL_TRUE;
  564. }
  565.  
  566.  
  567. GLboolean
  568. _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
  569.                                    GLsizei count, GLsizei numInstances)
  570. {
  571.    struct gl_transform_feedback_object *xfb_obj
  572.       = ctx->TransformFeedback.CurrentObject;
  573.    FLUSH_CURRENT(ctx, 0);
  574.  
  575.    if (count <= 0) {
  576.       if (count < 0)
  577.          _mesa_error(ctx, GL_INVALID_VALUE,
  578.                      "glDrawArraysInstanced(count=%d)", count);
  579.       return GL_FALSE;
  580.    }
  581.  
  582.    if (first < 0) {
  583.       _mesa_error(ctx, GL_INVALID_VALUE,
  584.                   "glDrawArraysInstanced(start=%d)", first);
  585.       return GL_FALSE;
  586.    }
  587.  
  588.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArraysInstanced")) {
  589.       return GL_FALSE;
  590.    }
  591.  
  592.    if (numInstances <= 0) {
  593.       if (numInstances < 0)
  594.          _mesa_error(ctx, GL_INVALID_VALUE,
  595.                      "glDrawArraysInstanced(numInstances=%d)", numInstances);
  596.       return GL_FALSE;
  597.    }
  598.  
  599.    if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)"))
  600.       return GL_FALSE;
  601.  
  602.    if (ctx->Const.CheckArrayBounds) {
  603.       if (first + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
  604.          return GL_FALSE;
  605.    }
  606.  
  607.    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
  608.     * Primitive Capture):
  609.     *
  610.     *   The error INVALID_OPERATION is generated by DrawArrays and
  611.     *   DrawArraysInstanced if recording the vertices of a primitive to the
  612.     *   buffer objects being used for transform feedback purposes would result
  613.     *   in either exceeding the limits of any buffer object’s size, or in
  614.     *   exceeding the end position offset + size − 1, as set by
  615.     *   BindBufferRange.
  616.     *
  617.     * This is in contrast to the behaviour of desktop GL, where the extra
  618.     * primitives are silently dropped from the transform feedback buffer.
  619.     */
  620.    if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
  621.       size_t prim_count
  622.          = vbo_count_tessellated_primitives(mode, count, numInstances);
  623.       if (xfb_obj->GlesRemainingPrims < prim_count) {
  624.          _mesa_error(ctx, GL_INVALID_OPERATION,
  625.                      "glDrawArraysInstanced(exceeds transform feedback size)");
  626.          return GL_FALSE;
  627.       }
  628.       xfb_obj->GlesRemainingPrims -= prim_count;
  629.    }
  630.  
  631.    return GL_TRUE;
  632. }
  633.  
  634.  
  635. GLboolean
  636. _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
  637.                                      GLenum mode, GLsizei count, GLenum type,
  638.                                      const GLvoid *indices, GLsizei numInstances,
  639.                                      GLint basevertex)
  640. {
  641.    FLUSH_CURRENT(ctx, 0);
  642.  
  643.    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
  644.     * Primitive Capture):
  645.     *
  646.     *   The error INVALID_OPERATION is also generated by DrawElements,
  647.     *   DrawElementsInstanced, and DrawRangeElements while transform feedback
  648.     *   is active and not paused, regardless of mode.
  649.     */
  650.    if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
  651.       _mesa_error(ctx, GL_INVALID_OPERATION,
  652.                   "glDrawElements(transform feedback active)");
  653.       return GL_FALSE;
  654.    }
  655.  
  656.    if (count <= 0) {
  657.       if (count < 0)
  658.          _mesa_error(ctx, GL_INVALID_VALUE,
  659.                      "glDrawElementsInstanced(count=%d)", count);
  660.       return GL_FALSE;
  661.    }
  662.  
  663.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElementsInstanced")) {
  664.       return GL_FALSE;
  665.    }
  666.  
  667.    if (!valid_elements_type(ctx, type, "glDrawElementsInstanced"))
  668.       return GL_FALSE;
  669.  
  670.    if (numInstances <= 0) {
  671.       if (numInstances < 0)
  672.          _mesa_error(ctx, GL_INVALID_VALUE,
  673.                      "glDrawElementsInstanced(numInstances=%d)", numInstances);
  674.       return GL_FALSE;
  675.    }
  676.  
  677.    if (!check_valid_to_render(ctx, "glDrawElementsInstanced"))
  678.       return GL_FALSE;
  679.  
  680.    /* Vertex buffer object tests */
  681.    if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
  682.       /* use indices in the buffer object */
  683.       /* make sure count doesn't go outside buffer bounds */
  684.       if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
  685.          _mesa_warning(ctx,
  686.                        "glDrawElementsInstanced index out of buffer bounds");
  687.          return GL_FALSE;
  688.       }
  689.    }
  690.    else {
  691.       /* not using a VBO */
  692.       if (!indices)
  693.          return GL_FALSE;
  694.    }
  695.  
  696.    if (!check_index_bounds(ctx, count, type, indices, basevertex))
  697.       return GL_FALSE;
  698.  
  699.    return GL_TRUE;
  700. }
  701.  
  702.  
  703. GLboolean
  704. _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
  705.                                      GLenum mode,
  706.                                      struct gl_transform_feedback_object *obj,
  707.                                      GLuint stream,
  708.                                      GLsizei numInstances)
  709. {
  710.    FLUSH_CURRENT(ctx, 0);
  711.  
  712.    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
  713.       return GL_FALSE;
  714.    }
  715.  
  716.    if (!obj) {
  717.       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
  718.       return GL_FALSE;
  719.    }
  720.  
  721.    if (!obj->EndedAnytime) {
  722.       _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
  723.       return GL_FALSE;
  724.    }
  725.  
  726.    if (stream >= ctx->Const.MaxVertexStreams) {
  727.       _mesa_error(ctx, GL_INVALID_VALUE,
  728.                   "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
  729.       return GL_FALSE;
  730.    }
  731.  
  732.    if (numInstances <= 0) {
  733.       if (numInstances < 0)
  734.          _mesa_error(ctx, GL_INVALID_VALUE,
  735.                      "glDrawTransformFeedback*Instanced(numInstances=%d)",
  736.                      numInstances);
  737.       return GL_FALSE;
  738.    }
  739.  
  740.    if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
  741.       return GL_FALSE;
  742.    }
  743.  
  744.    return GL_TRUE;
  745. }
  746.