12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/vertex_array_object_manager.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/gles2_cmd_helper.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/gles2_implementation.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gpu {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gles2 {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static GLsizei RoundUpToMultipleOf4(GLsizei size) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (size + 3) & ~3;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static GLuint ToGLuint(const void* ptr) {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class tracks VertexAttribPointers and helps emulate client side buffers.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The way client side buffers work is we shadow all the Vertex Attribs so we
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// know which ones are pointing to client side buffers.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// At Draw time, for any attribs pointing to client side buffers we copy them
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to a special VBO and reset the actual vertex attrib pointers to point to this
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// VBO.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This also means we have to catch calls to query those values so that when
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// an attrib is a client side buffer we pass the info back the user expects.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GLES2_IMPL_EXPORT VertexArrayObject {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Info about Vertex Attributes. This is used to track what the user currently
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // has bound on each Vertex Attribute so we can simulate client side buffers
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at glDrawXXX time.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class VertexAttrib {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexAttrib()
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        : enabled_(false),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          buffer_id_(0),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          size_(4),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          type_(GL_FLOAT),
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          normalized_(GL_FALSE),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          pointer_(NULL),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gl_stride_(0),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          divisor_(0) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool enabled() const {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return enabled_;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void set_enabled(bool enabled) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enabled_ = enabled;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint buffer_id() const {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return buffer_id_;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void set_buffer_id(GLuint id) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_id_ = id;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum type() const {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return type_;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLint size() const {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return size_;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei stride() const {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return gl_stride_;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLboolean normalized() const {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return normalized_;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GLvoid* pointer() const {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return pointer_;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool IsClientSide() const {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return buffer_id_ == 0;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint divisor() const {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return divisor_;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void SetInfo(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLuint buffer_id,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLint size,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLenum type,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLboolean normalized,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLsizei gl_stride,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const GLvoid* pointer) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_id_ = buffer_id;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_ = size;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type_ = type;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      normalized_ = normalized;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gl_stride_ = gl_stride;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pointer_ = pointer;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void SetDivisor(GLuint divisor) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      divisor_ = divisor;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   private:
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Whether or not this attribute is enabled.
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool enabled_;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The id of the buffer. 0 = client side buffer.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint buffer_id_;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Number of components (1, 2, 3, 4).
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLint size_;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum type_;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // GL_TRUE or GL_FALSE
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLboolean normalized_;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The pointer/offset into the buffer.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GLvoid* pointer_;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The stride that will be used to access the buffer. This is the bogus GL
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // stride where 0 = compute the stride based on size and type.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei gl_stride_;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Divisor, for geometry instancing.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint divisor_;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::vector<VertexAttrib> VertexAttribs;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit VertexArrayObject(GLuint max_vertex_attribs);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UnbindBuffer(GLuint id);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool BindElementArray(GLuint id);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HaveEnabledClientSideBuffers() const;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetAttribEnable(GLuint index, bool enabled);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetAttribPointer(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint buffer_id,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const void* ptr);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool GetVertexAttrib(
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLuint index, GLenum pname, uint32* param) const;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetAttribDivisor(GLuint index, GLuint divisor);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool GetAttribPointer(GLuint index, GLenum pname, void** ptr) const;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VertexAttribs& vertex_attribs() const {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return vertex_attribs_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLuint bound_element_array_buffer() const {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return bound_element_array_buffer_id_;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VertexAttrib* GetAttrib(GLuint index) const;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_client_side_pointers_enabled_;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The currently bound element array buffer.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLuint bound_element_array_buffer_id_;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VertexAttribs vertex_attribs_;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VertexArrayObject);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VertexArrayObject::VertexArrayObject(GLuint max_vertex_attribs)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : num_client_side_pointers_enabled_(0),
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bound_element_array_buffer_id_(0) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vertex_attribs_.resize(max_vertex_attribs);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObject::UnbindBuffer(GLuint id) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id == 0) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t ii = 0; ii < vertex_attribs_.size(); ++ii) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexAttrib& attrib = vertex_attribs_[ii];
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.buffer_id() == id) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      attrib.set_buffer_id(0);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (attrib.enabled()) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++num_client_side_pointers_enabled_;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bound_element_array_buffer_id_ == id) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound_element_array_buffer_id_ = 0;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObject::BindElementArray(GLuint id) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id == bound_element_array_buffer_id_) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_element_array_buffer_id_ = id;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObject::HaveEnabledClientSideBuffers() const {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return num_client_side_pointers_enabled_ > 0;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObject::SetAttribEnable(GLuint index, bool enabled) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (index < vertex_attribs_.size()) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexAttrib& attrib = vertex_attribs_[index];
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.enabled() != enabled) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (attrib.IsClientSide()) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        num_client_side_pointers_enabled_ += enabled ? 1 : -1;
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        DCHECK_GE(num_client_side_pointers_enabled_, 0);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      attrib.set_enabled(enabled);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObject::SetAttribPointer(
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint buffer_id,
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLint size,
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum type,
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLboolean normalized,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei stride,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const void* ptr) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (index < vertex_attribs_.size()) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexAttrib& attrib = vertex_attribs_[index];
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.IsClientSide() && attrib.enabled()) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      --num_client_side_pointers_enabled_;
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_GE(num_client_side_pointers_enabled_, 0);
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    attrib.SetInfo(buffer_id, size, type, normalized, stride, ptr);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.IsClientSide() && attrib.enabled()) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++num_client_side_pointers_enabled_;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObject::GetVertexAttrib(
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index, GLenum pname, uint32* param) const {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VertexAttrib* attrib = GetAttrib(index);
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!attrib) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (pname) {
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->buffer_id();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->enabled();
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->size();
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->stride();
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->type();
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *param = attrib->normalized();
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;  // pass through to service side.
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObject::SetAttribDivisor(GLuint index, GLuint divisor) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (index < vertex_attribs_.size()) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexAttrib& attrib = vertex_attribs_[index];
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    attrib.SetDivisor(divisor);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets the Attrib pointer for an attrib but only if it's a client side
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// pointer. Returns true if it got the pointer.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObject::GetAttribPointer(
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index, GLenum pname, void** ptr) const {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VertexAttrib* attrib = GetAttrib(index);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (attrib && pname == GL_VERTEX_ATTRIB_ARRAY_POINTER) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *ptr = const_cast<void*>(attrib->pointer());
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets an attrib if it's in range and it's client side.
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const VertexArrayObject::VertexAttrib* VertexArrayObject::GetAttrib(
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index) const {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (index < vertex_attribs_.size()) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const VertexAttrib* attrib = &vertex_attribs_[index];
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return attrib;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VertexArrayObjectManager::VertexArrayObjectManager(
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint max_vertex_attribs,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint array_buffer_id,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint element_array_buffer_id)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : max_vertex_attribs_(max_vertex_attribs),
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      array_buffer_id_(array_buffer_id),
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      array_buffer_size_(0),
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      array_buffer_offset_(0),
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_array_buffer_id_(element_array_buffer_id),
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_array_buffer_size_(0),
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      collection_buffer_size_(0),
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default_vertex_array_object_(new VertexArrayObject(max_vertex_attribs)),
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bound_vertex_array_object_(default_vertex_array_object_) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)VertexArrayObjectManager::~VertexArrayObjectManager() {
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (VertexArrayObjectMap::iterator it = vertex_array_objects_.begin();
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != vertex_array_objects_.end(); ++it) {
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete it->second;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete default_vertex_array_object_;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::IsReservedId(GLuint id) const {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (id != 0 &&
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (id == array_buffer_id_ || id == element_array_buffer_id_));
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLuint VertexArrayObjectManager::bound_element_array_buffer() const {
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bound_vertex_array_object_->bound_element_array_buffer();
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObjectManager::UnbindBuffer(GLuint id) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_vertex_array_object_->UnbindBuffer(id);
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::BindElementArray(GLuint id) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return  bound_vertex_array_object_->BindElementArray(id);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObjectManager::GenVertexArrays(
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei n, const GLuint* arrays) {
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(n, 0);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (GLsizei i = 0; i < n; ++i) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::pair<VertexArrayObjectMap::iterator, bool> result =
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vertex_array_objects_.insert(std::make_pair(
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            arrays[i], new VertexArrayObject(max_vertex_attribs_)));
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(result.second);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObjectManager::DeleteVertexArrays(
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei n, const GLuint* arrays) {
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_GE(n, 0);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (GLsizei i = 0; i < n; ++i) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint id = arrays[i];
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (id) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VertexArrayObjectMap::iterator it = vertex_array_objects_.find(id);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (it != vertex_array_objects_.end()) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (bound_vertex_array_object_ == it->second) {
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          bound_vertex_array_object_ = default_vertex_array_object_;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        delete it->second;
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vertex_array_objects_.erase(it);
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::BindVertexArray(GLuint array, bool* changed) {
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *changed = false;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VertexArrayObject* vertex_array_object = default_vertex_array_object_;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (array != 0) {
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VertexArrayObjectMap::iterator it = vertex_array_objects_.find(array);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it == vertex_array_objects_.end()) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    vertex_array_object = it->second;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *changed = vertex_array_object != bound_vertex_array_object_;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_vertex_array_object_ = vertex_array_object;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::HaveEnabledClientSideBuffers() const {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bound_vertex_array_object_->HaveEnabledClientSideBuffers();
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObjectManager::SetAttribEnable(GLuint index, bool enabled) {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_vertex_array_object_->SetAttribEnable(index, enabled);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::GetVertexAttrib(
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index, GLenum pname, uint32* param) {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bound_vertex_array_object_->GetVertexAttrib(index, pname, param);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::GetAttribPointer(
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index, GLenum pname, void** ptr) const {
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bound_vertex_array_object_->GetAttribPointer(index, pname, ptr);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::SetAttribPointer(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint buffer_id,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint index,
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLint size,
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum type,
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLboolean normalized,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei stride,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const void* ptr) {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Client side arrays are not allowed in vaos.
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buffer_id == 0 && !IsDefaultVAOBound()) {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_vertex_array_object_->SetAttribPointer(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_id, index, size, type, normalized, stride, ptr);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VertexArrayObjectManager::SetAttribDivisor(GLuint index, GLuint divisor) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_vertex_array_object_->SetAttribDivisor(index, divisor);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Collects the data into the collection buffer and returns the number of
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// bytes collected.
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GLsizei VertexArrayObjectManager::CollectData(
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const void* data,
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei bytes_per_element,
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei real_stride,
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei num_elements) {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLsizei bytes_needed = bytes_per_element * num_elements;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (collection_buffer_size_ < bytes_needed) {
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    collection_buffer_.reset(new int8[bytes_needed]);
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    collection_buffer_size_ = bytes_needed;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int8* src = static_cast<const int8*>(data);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int8* dst = collection_buffer_.get();
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int8* end = dst + bytes_per_element * num_elements;
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; dst < end; src += real_stride, dst += bytes_per_element) {
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memcpy(dst, src, bytes_per_element);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bytes_needed;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::IsDefaultVAOBound() const {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bound_vertex_array_object_ == default_vertex_array_object_;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if buffers were setup.
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::SetupSimulatedClientSideBuffers(
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* function_name,
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLES2Implementation* gl,
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLES2CmdHelper* gl_helper,
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei num_elements,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei primcount,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* simulated) {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *simulated = false;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!bound_vertex_array_object_->HaveEnabledClientSideBuffers()) {
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsDefaultVAOBound()) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl->SetGLError(
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GL_INVALID_OPERATION, function_name,
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "client side arrays not allowed with vertex array object");
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *simulated = true;
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLsizei total_size = 0;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute the size of the buffer we need.
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const VertexArrayObject::VertexAttribs& vertex_attribs =
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bound_vertex_array_object_->vertex_attribs();
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (GLuint ii = 0; ii < vertex_attribs.size(); ++ii) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const VertexArrayObject::VertexAttrib& attrib = vertex_attribs[ii];
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.IsClientSide() && attrib.enabled()) {
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_t bytes_per_element =
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GLES2Util::GetGLTypeSizeForTexturesAndBuffers(attrib.type()) *
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          attrib.size();
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLsizei elements = (primcount && attrib.divisor() > 0) ?
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ((primcount - 1) / attrib.divisor() + 1) : num_elements;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_size += RoundUpToMultipleOf4(bytes_per_element * elements);
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gl_helper->BindBuffer(GL_ARRAY_BUFFER, array_buffer_id_);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  array_buffer_offset_ = 0;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (total_size > array_buffer_size_) {
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl->BufferDataHelper(GL_ARRAY_BUFFER, total_size, NULL, GL_DYNAMIC_DRAW);
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    array_buffer_size_ = total_size;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (GLuint ii = 0; ii < vertex_attribs.size(); ++ii) {
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const VertexArrayObject::VertexAttrib& attrib = vertex_attribs[ii];
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (attrib.IsClientSide() && attrib.enabled()) {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_t bytes_per_element =
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GLES2Util::GetGLTypeSizeForTexturesAndBuffers(attrib.type()) *
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          attrib.size();
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLsizei real_stride = attrib.stride() ?
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          attrib.stride() : static_cast<GLsizei>(bytes_per_element);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLsizei elements = (primcount && attrib.divisor() > 0) ?
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ((primcount - 1) / attrib.divisor() + 1) : num_elements;
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GLsizei bytes_collected = CollectData(
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          attrib.pointer(), bytes_per_element, real_stride, elements);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gl->BufferSubDataHelper(
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GL_ARRAY_BUFFER, array_buffer_offset_, bytes_collected,
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          collection_buffer_.get());
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gl_helper->VertexAttribPointer(
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ii, attrib.size(), attrib.type(), attrib.normalized(), 0,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          array_buffer_offset_);
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      array_buffer_offset_ += RoundUpToMultipleOf4(bytes_collected);
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK_LE(array_buffer_offset_, array_buffer_size_);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copies in indices to the service and returns the highest index accessed + 1
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VertexArrayObjectManager::SetupSimulatedIndexAndClientSideBuffers(
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* function_name,
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLES2Implementation* gl,
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLES2CmdHelper* gl_helper,
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei count,
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLenum type,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei primcount,
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const void* indices,
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLuint* offset,
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* simulated) {
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *simulated = false;
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *offset = ToGLuint(indices);
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLsizei num_elements = 0;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bound_vertex_array_object_->bound_element_array_buffer() == 0) {
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *simulated = true;
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *offset = 0;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei max_index = -1;
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (type) {
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case GL_UNSIGNED_BYTE: {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const uint8* src = static_cast<const uint8*>(indices);
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (GLsizei ii = 0; ii < count; ++ii) {
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (src[ii] > max_index) {
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            max_index = src[ii];
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case GL_UNSIGNED_SHORT: {
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const uint16* src = static_cast<const uint16*>(indices);
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (GLsizei ii = 0; ii < count; ++ii) {
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (src[ii] > max_index) {
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            max_index = src[ii];
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case GL_UNSIGNED_INT: {
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uint32 max_glsizei = static_cast<uint32>(
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            std::numeric_limits<GLsizei>::max());
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const uint32* src = static_cast<const uint32*>(indices);
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (GLsizei ii = 0; ii < count; ++ii) {
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Other parts of the API use GLsizei (signed) to store limits.
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // As such, if we encounter a index that cannot be represented with
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // an unsigned int we need to flag it as an error here.
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if(src[ii] > max_glsizei) {
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            gl->SetGLError(
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                GL_INVALID_OPERATION, function_name, "index too large.");
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return false;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GLsizei signed_index = static_cast<GLsizei>(src[ii]);
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (signed_index > max_index) {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            max_index = signed_index;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl_helper->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_array_buffer_id_);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei bytes_per_element =
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLsizei bytes_needed = bytes_per_element * count;
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_needed > element_array_buffer_size_) {
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_array_buffer_size_ = bytes_needed;
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gl->BufferDataHelper(
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GL_ELEMENT_ARRAY_BUFFER, bytes_needed, NULL, GL_DYNAMIC_DRAW);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gl->BufferSubDataHelper(
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GL_ELEMENT_ARRAY_BUFFER, 0, bytes_needed, indices);
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_elements = max_index + 1;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (bound_vertex_array_object_->HaveEnabledClientSideBuffers()) {
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Index buffer is GL buffer. Ask the service for the highest vertex
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // that will be accessed. Note: It doesn't matter if another context
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // changes the contents of any of the buffers. The service will still
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // validate the indices. We just need to know how much to copy across.
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_elements = gl->GetMaxValueInBufferCHROMIUMHelper(
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bound_vertex_array_object_->bound_element_array_buffer(),
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        count, type, ToGLuint(indices)) + 1;
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool simulated_client_side_buffers = false;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetupSimulatedClientSideBuffers(
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function_name, gl, gl_helper, num_elements, primcount,
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &simulated_client_side_buffers);
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *simulated = *simulated || simulated_client_side_buffers;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace gles2
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace gpu
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
641