docs: protected void prepareDraw() {
      VertexAttribArrayState previousNio = null;
      int previousElementSize = 0;
  
      if (useNioBuffer == 0 && enabledArrays == previouslyEnabledArrays) {
        return;
      }
  
      for(int i = 0; i < VERTEX_ATTRIB_ARRAY_COUNT; i++) {
        int mask = 1 << i;
        int enabled = enabledArrays & mask;
        if (enabled != (previouslyEnabledArrays & mask)) {
          if (enabled != 0) {
            gl.enableVertexAttribArray(i);
          } else {
            gl.disableVertexAttribArray(i);
          }
        }
        if (enabled != 0 && (useNioBuffer & mask) != 0) {
          VertexAttribArrayState data = vertexAttribArrayState[i];
          if (previousNio != null && previousNio.nioBuffer == data.nioBuffer &&
              previousNio.nioBufferLimit >= data.nioBufferLimit) {
            if (boundArrayBuffer != previousNio.webGlBuffer) {
              gl.bindBuffer(ARRAY_BUFFER, previousNio.webGlBuffer);
              boundArrayBuffer = data.webGlBuffer;
            }
            gl.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride,
                                   data.nioBufferPosition * previousElementSize);
          } else {
            if (boundArrayBuffer != data.webGlBuffer) {
              gl.bindBuffer(ARRAY_BUFFER, data.webGlBuffer);
              boundArrayBuffer = data.webGlBuffer;
            }
            int elementSize = getElementSize(data.nioBuffer);
            int savePosition = data.nioBuffer.position();
            if (data.nioBufferPosition * elementSize < data.stride) {
              data.nioBuffer.position(0);
              gl.bufferData(ARRAY_BUFFER, getTypedArray(data.nioBuffer, data.type, data.nioBufferLimit *
                                                        elementSize), STREAM_DRAW);
              gl.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride,
                                     data.nioBufferPosition * elementSize);
              previousNio = data;
              previousElementSize = elementSize;
            } else {
              data.nioBuffer.position(data.nioBufferPosition);
              gl.bufferData(ARRAY_BUFFER, getTypedArray(data.nioBuffer, data.type,
                                                        (data.nioBufferLimit - data.nioBufferPosition) *
                                                        elementSize), STREAM_DRAW);
              gl.vertexAttribPointer(i, data.size, data.type, data.normalize, data.stride, 0);
            }
            data.nioBuffer.position(savePosition);
          }
        }
      }
      previouslyEnabledArrays = enabledArrays;
    }