Framebuffer clear() needs to consider the situation some draw buffers are disabled.

This is when we expose DrawBuffers extension.

BUG=376951
TEST=the attached test case, webgl conformance
R=kbr@chromium.org,bajones@chromium.org

Review URL: https://codereview.chromium.org/315283002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275338 0039d316-1c4b-4281-b951-d872f2087c98
error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
    uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
  GLuint count = c.count;
  uint32 pnames_size;
  if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
    return error::kOutOfBounds;
  }
  const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
      c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
  if (pnames == NULL) {
    return error::kOutOfBounds;
  }

  scoped_ptr<GLenum[]> enums(new GLenum[count]);
  memcpy(enums.get(), pnames, pnames_size);

  uint32 num_results = 0;
  for (GLuint ii = 0; ii < count; ++ii) {
    uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
    if (num == 0) {
      LOCAL_SET_GL_ERROR_INVALID_ENUM(
          "glGetMultipleCHROMIUM", enums[ii], "pname");
      return error::kNoError;
    }
    DCHECK_LE(num, 4u);
    if (!SafeAddUint32(num_results, num, &num_results)) {
      return error::kOutOfBounds;
    }
  }

  uint32 result_size = 0;
  if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
    return error::kOutOfBounds;
  }

  if (result_size != static_cast<uint32>(c.size)) {
    LOCAL_SET_GL_ERROR(
        GL_INVALID_VALUE,
        "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
    return error::kNoError;
  }

  GLint* results = GetSharedMemoryAs<GLint*>(
      c.results_shm_id, c.results_shm_offset, result_size);
  if (results == NULL) {
    return error::kOutOfBounds;
  }

  for (uint32 ii = 0; ii < num_results; ++ii) {
    if (results[ii]) {
      return error::kInvalidArguments;
    }
  }

  GLint* start = results;
  for (GLuint ii = 0; ii < count; ++ii) {
    GLsizei num_written = 0;
    if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
        !GetHelper(enums[ii], results, &num_written)) {
      DoGetIntegerv(enums[ii], results);
    }
    results += num_written;
  }

  if (static_cast<uint32>(results - start) != num_results) {
    return error::kOutOfBounds;
  }

  return error::kNoError;
}

error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
    uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
  GLuint count = c.count;
  uint32 pnames_size;
  if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
    return error::kOutOfBounds;
  }
  const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
      c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
  if (pnames == NULL) {
    return error::kOutOfBounds;
  }

  scoped_ptr<GLenum[]> enums(new GLenum[count]);
  memcpy(enums.get(), pnames, pnames_size);

  uint32 num_results = 0;
  for (GLuint ii = 0; ii < count; ++ii) {
    uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
    if (num == 0) {
      LOCAL_SET_GL_ERROR_INVALID_ENUM(
          "glGetMultipleCHROMIUM", enums[ii], "pname");
      return error::kNoError;
    }
    DCHECK_LE(num, 4u);
    if (!SafeAddUint32(num_results, num, &num_results)) {
      return error::kOutOfBounds;
    }
  }

  uint32 result_size = 0;
  if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
    return error::kOutOfBounds;
  }

  if (result_size != static_cast<uint32>(c.size)) {
    LOCAL_SET_GL_ERROR(
        GL_INVALID_VALUE,
        "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
    return error::kNoError;
  }

  GLint* results = GetSharedMemoryAs<GLint*>(
      c.results_shm_id, c.results_shm_offset, result_size);
  if (results == NULL) {
    return error::kOutOfBounds;
  }

  for (uint32 ii = 0; ii < num_results; ++ii) {
    if (results[ii]) {
      return error::kInvalidArguments;
    }
  }

  GLint* start = results;
  for (GLuint ii = 0; ii < count; ++ii) {
    GLsizei num_written = 0;
    if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
        !GetHelper(enums[ii], results, &num_written)) {
      DoGetIntegerv(enums[ii], results);
    }
    results += num_written;
  }

  if (static_cast<uint32>(results - start) != num_results) {
    return error::kOutOfBounds;
  }

  return error::kNoError;
}
