blob: 3a884f4401a17b95ff85f91fabad43b17e0b7f7e [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
#include "base/strings/string_number_conversions.h"
#include "ui/gl/gl_version_info.h"
namespace gpu {
namespace gles2 {
namespace {
template <typename ClientType, typename ServiceType, typename GenFunction>
error::Error GenHelper(GLsizei n,
const volatile ClientType* client_ids,
ClientServiceMap<ClientType, ServiceType>* id_map,
GenFunction gen_function) {
DCHECK(n >= 0);
std::vector<ClientType> client_ids_copy(client_ids, client_ids + n);
for (GLsizei ii = 0; ii < n; ++ii) {
if (id_map->GetServiceID(client_ids_copy[ii], nullptr)) {
return error::kInvalidArguments;
}
}
if (!CheckUniqueAndNonNullIds(n, client_ids_copy.data())) {
return error::kInvalidArguments;
}
std::vector<ServiceType> service_ids(n, 0);
gen_function(n, service_ids.data());
for (GLsizei ii = 0; ii < n; ++ii) {
id_map->SetIDMapping(client_ids_copy[ii], service_ids[ii]);
}
return error::kNoError;
}
template <typename ClientType, typename ServiceType, typename GenFunction>
error::Error CreateHelper(ClientType client_id,
ClientServiceMap<ClientType, ServiceType>* id_map,
GenFunction create_function) {
if (id_map->GetServiceID(client_id, nullptr)) {
return error::kInvalidArguments;
}
ServiceType service_id = create_function();
id_map->SetIDMapping(client_id, service_id);
return error::kNoError;
}
template <typename ClientType, typename ServiceType, typename DeleteFunction>
error::Error DeleteHelper(GLsizei n,
const volatile ClientType* client_ids,
ClientServiceMap<ClientType, ServiceType>* id_map,
DeleteFunction delete_function) {
DCHECK(n >= 0);
std::vector<ServiceType> service_ids(n, 0);
for (GLsizei ii = 0; ii < n; ++ii) {
ClientType client_id = client_ids[ii];
service_ids[ii] = id_map->GetServiceIDOrInvalid(client_id);
id_map->RemoveClientID(client_id);
}
delete_function(n, service_ids.data());
return error::kNoError;
}
template <typename ClientType, typename ServiceType, typename DeleteFunction>
error::Error DeleteHelper(ClientType client_id,
ClientServiceMap<ClientType, ServiceType>* id_map,
DeleteFunction delete_function) {
delete_function(id_map->GetServiceIDOrInvalid(client_id));
id_map->RemoveClientID(client_id);
return error::kNoError;
}
template <typename ClientType, typename ServiceType, typename GenFunction>
ServiceType GetServiceID(ClientType client_id,
ClientServiceMap<ClientType, ServiceType>* id_map,
bool create_if_missing,
GenFunction gen_function) {
ServiceType service_id = id_map->invalid_service_id();
if (id_map->GetServiceID(client_id, &service_id)) {
return service_id;
}
if (create_if_missing) {
service_id = gen_function();
id_map->SetIDMapping(client_id, service_id);
return service_id;
}
return id_map->invalid_service_id();
}
GLuint GetTextureServiceID(GLuint client_id,
PassthroughResources* resources,
bool create_if_missing) {
return GetServiceID(client_id, &resources->texture_id_map, create_if_missing,
[]() {
GLuint service_id = 0;
glGenTextures(1, &service_id);
return service_id;
});
}
GLuint GetBufferServiceID(GLuint client_id,
PassthroughResources* resources,
bool create_if_missing) {
return GetServiceID(client_id, &resources->buffer_id_map, create_if_missing,
[]() {
GLuint service_id = 0;
glGenBuffersARB(1, &service_id);
return service_id;
});
}
GLuint GetRenderbufferServiceID(GLuint client_id,
PassthroughResources* resources,
bool create_if_missing) {
return GetServiceID(client_id, &resources->renderbuffer_id_map,
create_if_missing, []() {
GLuint service_id = 0;
glGenRenderbuffersEXT(1, &service_id);
return service_id;
});
}
GLuint GetFramebufferServiceID(GLuint client_id,
ClientServiceMap<GLuint, GLuint>* id_map,
bool create_if_missing) {
return GetServiceID(client_id, id_map, create_if_missing, []() {
GLuint service_id = 0;
glGenFramebuffersEXT(1, &service_id);
return service_id;
});
}
GLuint GetTransformFeedbackServiceID(GLuint client_id,
ClientServiceMap<GLuint, GLuint>* id_map) {
return id_map->GetServiceIDOrInvalid(client_id);
}
GLuint GetVertexArrayServiceID(GLuint client_id,
ClientServiceMap<GLuint, GLuint>* id_map) {
return id_map->GetServiceIDOrInvalid(client_id);
}
GLuint GetProgramServiceID(GLuint client_id, PassthroughResources* resources) {
return resources->program_id_map.GetServiceIDOrInvalid(client_id);
}
GLuint GetShaderServiceID(GLuint client_id, PassthroughResources* resources) {
return resources->shader_id_map.GetServiceIDOrInvalid(client_id);
}
GLuint GetQueryServiceID(GLuint client_id,
ClientServiceMap<GLuint, GLuint>* id_map) {
return id_map->GetServiceIDOrInvalid(client_id);
}
GLuint GetSamplerServiceID(GLuint client_id, PassthroughResources* resources) {
return resources->sampler_id_map.GetServiceIDOrInvalid(client_id);
}
GLsync GetSyncServiceID(GLuint client_id, PassthroughResources* resources) {
return reinterpret_cast<GLsync>(
resources->sync_id_map.GetServiceIDOrInvalid(client_id));
}
template <typename T>
void InsertValueIntoBuffer(std::vector<uint8_t>* data,
const T& value,
size_t offset) {
DCHECK_LE(offset + sizeof(T), data->size());
memcpy(data->data() + offset, &value, sizeof(T));
}
template <typename T>
void AppendValueToBuffer(std::vector<uint8_t>* data, const T& value) {
const base::CheckedNumeric<size_t> old_size = data->size();
data->resize((old_size + sizeof(T)).ValueOrDie());
memcpy(data->data() + old_size.ValueOrDie(), &value, sizeof(T));
}
void AppendStringToBuffer(std::vector<uint8_t>* data,
const char* str,
size_t len) {
const base::CheckedNumeric<size_t> old_size = data->size();
data->resize((old_size + len).ValueOrDie());
memcpy(data->data() + old_size.ValueOrDie(), str, len);
}
// In order to minimize the amount of data copied, the command buffer client
// unpack pixels before sending the glTex[Sub]Image[2|3]D calls. The only
// parameter it doesn't handle is the alignment. Resetting the unpack state is
// not needed when uploading from a PBO and for compressed formats which the
// client sends untouched. This class handles resetting and restoring the unpack
// state.
// TODO(cwallez@chromium.org) it would be nicer to handle the resetting /
// restoring on the client side.
class ScopedUnpackStateButAlignmentReset {
public:
ScopedUnpackStateButAlignmentReset(bool enable, bool is_3d) {
if (!enable) {
return;
}
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels_);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows_);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length_);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
if (is_3d) {
glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &skip_images_);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height_);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
}
}
~ScopedUnpackStateButAlignmentReset() {
if (skip_pixels_ != 0) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels_);
}
if (skip_rows_ != 0) {
glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows_);
}
if (skip_images_ != 0) {
glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images_);
}
if (row_length_ != 0) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length_);
}
if (image_height_ != 0) {
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height_);
}
}
private:
GLint skip_pixels_ = 0;
GLint skip_rows_ = 0;
GLint skip_images_ = 0;
GLint row_length_ = 0;
GLint image_height_ = 0;
};
} // anonymous namespace
// Implementations of commands
error::Error GLES2DecoderPassthroughImpl::DoActiveTexture(GLenum texture) {
FlushErrors();
glActiveTexture(texture);
if (FlushErrors()) {
return error::kNoError;
}
active_texture_unit_ = static_cast<size_t>(texture) - GL_TEXTURE0;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoAttachShader(GLuint program,
GLuint shader) {
glAttachShader(GetProgramServiceID(program, resources_),
GetShaderServiceID(shader, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindAttribLocation(
GLuint program,
GLuint index,
const char* name) {
glBindAttribLocation(GetProgramServiceID(program, resources_), index, name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindBuffer(GLenum target,
GLuint buffer) {
FlushErrors();
glBindBuffer(
target, GetBufferServiceID(buffer, resources_, bind_generates_resource_));
if (FlushErrors()) {
return error::kNoError;
}
bound_buffers_[target] = buffer;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindBufferBase(GLenum target,
GLuint index,
GLuint buffer) {
glBindBufferBase(target, index, GetBufferServiceID(buffer, resources_,
bind_generates_resource_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindBufferRange(GLenum target,
GLuint index,
GLuint buffer,
GLintptr offset,
GLsizeiptr size) {
glBindBufferRange(target, index, GetBufferServiceID(buffer, resources_,
bind_generates_resource_),
offset, size);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindFramebuffer(
GLenum target,
GLuint framebuffer) {
glBindFramebufferEXT(
target, GetFramebufferServiceID(framebuffer, &framebuffer_id_map_,
bind_generates_resource_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindRenderbuffer(
GLenum target,
GLuint renderbuffer) {
glBindRenderbufferEXT(target,
GetRenderbufferServiceID(renderbuffer, resources_,
bind_generates_resource_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindSampler(GLuint unit,
GLuint sampler) {
glBindSampler(unit, GetSamplerServiceID(sampler, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindTexture(GLenum target,
GLuint texture) {
GLuint service_id =
GetTextureServiceID(texture, resources_, bind_generates_resource_);
FlushErrors();
glBindTexture(target, service_id);
// Only update tracking if no error was generated in the bind call
if (FlushErrors()) {
return error::kNoError;
}
// Track the currently bound textures
DCHECK(bound_textures_.find(target) != bound_textures_.end());
DCHECK(bound_textures_[target].size() > active_texture_unit_);
bound_textures_[target][active_texture_unit_] = texture;
if (service_id != 0) {
// Create a new texture object to track this texture
auto texture_object_iter = resources_->texture_object_map.find(texture);
if (texture_object_iter == resources_->texture_object_map.end()) {
resources_->texture_object_map.insert(
std::make_pair(texture, new TexturePassthrough(service_id, target)));
} else {
// Shouldn't be possible to get here if this texture has a different
// target than the one it was just bound to
DCHECK(texture_object_iter->second->target() == target);
}
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindTransformFeedback(
GLenum target,
GLuint transformfeedback) {
glBindTransformFeedback(
target, GetTransformFeedbackServiceID(transformfeedback,
&transform_feedback_id_map_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendColor(GLclampf red,
GLclampf green,
GLclampf blue,
GLclampf alpha) {
glBlendColor(red, green, blue, alpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendEquation(GLenum mode) {
glBlendEquation(mode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendEquationSeparate(
GLenum modeRGB,
GLenum modeAlpha) {
glBlendEquationSeparate(modeRGB, modeAlpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendFunc(GLenum sfactor,
GLenum dfactor) {
glBlendFunc(sfactor, dfactor);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendFuncSeparate(GLenum srcRGB,
GLenum dstRGB,
GLenum srcAlpha,
GLenum dstAlpha) {
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBufferData(GLenum target,
GLsizeiptr size,
const void* data,
GLenum usage) {
glBufferData(target, size, data, usage);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBufferSubData(GLenum target,
GLintptr offset,
GLsizeiptr size,
const void* data) {
glBufferSubData(target, offset, size, data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCheckFramebufferStatus(
GLenum target,
uint32_t* result) {
*result = glCheckFramebufferStatusEXT(target);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClear(GLbitfield mask) {
glClear(mask);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearBufferfi(GLenum buffer,
GLint drawbuffers,
GLfloat depth,
GLint stencil) {
glClearBufferfi(buffer, drawbuffers, depth, stencil);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearBufferfv(
GLenum buffer,
GLint drawbuffers,
const volatile GLfloat* value) {
glClearBufferfv(buffer, drawbuffers, const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearBufferiv(
GLenum buffer,
GLint drawbuffers,
const volatile GLint* value) {
glClearBufferiv(buffer, drawbuffers, const_cast<const GLint*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearBufferuiv(
GLenum buffer,
GLint drawbuffers,
const volatile GLuint* value) {
glClearBufferuiv(buffer, drawbuffers, const_cast<const GLuint*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearColor(GLclampf red,
GLclampf green,
GLclampf blue,
GLclampf alpha) {
glClearColor(red, green, blue, alpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearDepthf(GLclampf depth) {
glClearDepthf(depth);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClearStencil(GLint s) {
glClearStencil(s);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoClientWaitSync(GLuint sync,
GLbitfield flags,
GLuint64 timeout,
GLenum* result) {
// Force GL_SYNC_FLUSH_COMMANDS_BIT to avoid infinite wait.
GLbitfield modified_flags = flags | GL_SYNC_FLUSH_COMMANDS_BIT;
*result = glClientWaitSync(GetSyncServiceID(sync, resources_), modified_flags,
timeout);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoColorMask(GLboolean red,
GLboolean green,
GLboolean blue,
GLboolean alpha) {
glColorMask(red, green, blue, alpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompileShader(GLuint shader) {
glCompileShader(GetShaderServiceID(shader, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompressedTexImage2D(
GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLsizei image_size,
GLsizei data_size,
const void* data) {
glCompressedTexImage2DRobustANGLE(target, level, internalformat, width,
height, border, image_size, data_size,
data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompressedTexSubImage2D(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLsizei image_size,
GLsizei data_size,
const void* data) {
glCompressedTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width,
height, format, image_size, data_size,
data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompressedTexImage3D(
GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border,
GLsizei image_size,
GLsizei data_size,
const void* data) {
glCompressedTexImage3DRobustANGLE(target, level, internalformat, width,
height, depth, border, image_size,
data_size, data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompressedTexSubImage3D(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLsizei image_size,
GLsizei data_size,
const void* data) {
glCompressedTexSubImage3DRobustANGLE(target, level, xoffset, yoffset, zoffset,
width, height, depth, format, image_size,
data_size, data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopyBufferSubData(
GLenum readtarget,
GLenum writetarget,
GLintptr readoffset,
GLintptr writeoffset,
GLsizeiptr size) {
glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopyTexImage2D(
GLenum target,
GLint level,
GLenum internalformat,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLint border) {
glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopyTexSubImage2D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height) {
glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopyTexSubImage3D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height) {
glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width,
height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCreateProgram(GLuint client_id) {
return CreateHelper(client_id, &resources_->program_id_map,
[]() { return glCreateProgram(); });
}
error::Error GLES2DecoderPassthroughImpl::DoCreateShader(GLenum type,
GLuint client_id) {
return CreateHelper(client_id, &resources_->shader_id_map,
[type]() { return glCreateShader(type); });
}
error::Error GLES2DecoderPassthroughImpl::DoCullFace(GLenum mode) {
glCullFace(mode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteBuffers(
GLsizei n,
const volatile GLuint* buffers) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
return DeleteHelper(n, buffers, &resources_->buffer_id_map,
[this](GLsizei n, GLuint* buffers) {
glDeleteBuffersARB(n, buffers);
for (GLsizei i = 0; i < n; i++)
for (auto buffer_binding : bound_buffers_) {
if (buffer_binding.second == buffers[i]) {
buffer_binding.second = 0;
}
}
});
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteFramebuffers(
GLsizei n,
const volatile GLuint* framebuffers) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
return DeleteHelper(n, framebuffers, &framebuffer_id_map_,
[](GLsizei n, GLuint* framebuffers) {
glDeleteFramebuffersEXT(n, framebuffers);
});
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteProgram(GLuint program) {
return DeleteHelper(program, &resources_->program_id_map,
[](GLuint program) { glDeleteProgram(program); });
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteRenderbuffers(
GLsizei n,
const volatile GLuint* renderbuffers) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
return DeleteHelper(n, renderbuffers, &resources_->renderbuffer_id_map,
[](GLsizei n, GLuint* renderbuffers) {
glDeleteRenderbuffersEXT(n, renderbuffers);
});
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteSamplers(
GLsizei n,
const volatile GLuint* samplers) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
return DeleteHelper(
n, samplers, &resources_->sampler_id_map,
[](GLsizei n, GLuint* samplers) { glDeleteSamplers(n, samplers); });
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteSync(GLuint sync) {
return DeleteHelper(sync, &resources_->sync_id_map, [](uintptr_t sync) {
glDeleteSync(reinterpret_cast<GLsync>(sync));
});
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteShader(GLuint shader) {
return DeleteHelper(shader, &resources_->shader_id_map,
[](GLuint shader) { glDeleteShader(shader); });
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteTextures(
GLsizei n,
const volatile GLuint* textures) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
// Textures that are currently associated with a mailbox are stored in the
// texture_object_map_ and are deleted automatically when they are
// unreferenced. Only delete textures that are not in this map.
std::vector<GLuint> non_mailbox_client_ids;
for (GLsizei ii = 0; ii < n; ++ii) {
GLuint client_id = textures[ii];
auto texture_object_iter = resources_->texture_object_map.find(client_id);
if (texture_object_iter == resources_->texture_object_map.end()) {
// Delete with DeleteHelper
non_mailbox_client_ids.push_back(client_id);
} else {
// Deleted when unreferenced
resources_->texture_id_map.RemoveClientID(client_id);
resources_->texture_object_map.erase(client_id);
}
}
return DeleteHelper(
non_mailbox_client_ids.size(), non_mailbox_client_ids.data(),
&resources_->texture_id_map,
[](GLsizei n, GLuint* textures) { glDeleteTextures(n, textures); });
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteTransformFeedbacks(
GLsizei n,
const volatile GLuint* ids) {
// DeleteHelper requires that n is non-negative because it allocates a copy of
// the IDs
if (n < 0) {
InsertError(GL_INVALID_VALUE, "n cannot be negative.");
return error::kNoError;
}
return DeleteHelper(n, ids, &transform_feedback_id_map_,
[](GLsizei n, GLuint* transform_feedbacks) {
glDeleteTransformFeedbacks(n, transform_feedbacks);
});
}
error::Error GLES2DecoderPassthroughImpl::DoDepthFunc(GLenum func) {
glDepthFunc(func);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDepthMask(GLboolean flag) {
glDepthMask(flag);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDepthRangef(GLclampf zNear,
GLclampf zFar) {
glDepthRangef(zNear, zFar);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDetachShader(GLuint program,
GLuint shader) {
glDetachShader(GetProgramServiceID(program, resources_),
GetShaderServiceID(shader, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDisable(GLenum cap) {
glDisable(cap);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDisableVertexAttribArray(
GLuint index) {
glDisableVertexAttribArray(index);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDrawArrays(GLenum mode,
GLint first,
GLsizei count) {
glDrawArrays(mode, first, count);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDrawElements(GLenum mode,
GLsizei count,
GLenum type,
const void* indices) {
glDrawElements(mode, count, type, indices);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoEnable(GLenum cap) {
glEnable(cap);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoEnableVertexAttribArray(
GLuint index) {
glEnableVertexAttribArray(index);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFenceSync(GLenum condition,
GLbitfield flags,
GLuint client_id) {
if (resources_->sync_id_map.GetServiceID(client_id, nullptr)) {
return error::kInvalidArguments;
}
FlushErrors();
GLsync service_id = glFenceSync(condition, flags);
if (FlushErrors()) {
return error::kInvalidArguments;
}
resources_->sync_id_map.SetIDMapping(client_id,
reinterpret_cast<uintptr_t>(service_id));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFinish() {
glFinish();
return ProcessQueries(true);
}
error::Error GLES2DecoderPassthroughImpl::DoFlush() {
glFlush();
return ProcessQueries(false);
}
error::Error GLES2DecoderPassthroughImpl::DoFlushMappedBufferRange(
GLenum target,
GLintptr offset,
GLsizeiptr size) {
auto bound_buffers_iter = bound_buffers_.find(target);
if (bound_buffers_iter == bound_buffers_.end() ||
bound_buffers_iter->second == 0) {
InsertError(GL_INVALID_OPERATION, "No buffer bound to this target.");
return error::kNoError;
}
GLuint client_buffer = bound_buffers_iter->second;
auto mapped_buffer_info_iter =
resources_->mapped_buffer_map.find(client_buffer);
if (mapped_buffer_info_iter == resources_->mapped_buffer_map.end()) {
InsertError(GL_INVALID_OPERATION, "Buffer is not mapped.");
return error::kNoError;
}
const MappedBuffer& map_info = mapped_buffer_info_iter->second;
if (offset < 0) {
InsertError(GL_INVALID_VALUE, "Offset cannot be negative.");
return error::kNoError;
}
if (size < 0) {
InsertError(GL_INVALID_VALUE, "Size cannot be negative.");
return error::kNoError;
}
base::CheckedNumeric<size_t> range_start(offset);
base::CheckedNumeric<size_t> range_end = offset + size;
if (!range_end.IsValid() && range_end.ValueOrDefault(0) > map_info.size) {
InsertError(GL_INVALID_OPERATION,
"Flush range is not within the original mapping size.");
return error::kNoError;
}
uint8_t* mem = GetSharedMemoryAs<uint8_t*>(
map_info.data_shm_id, map_info.data_shm_offset, map_info.size);
if (!mem) {
return error::kOutOfBounds;
}
memcpy(map_info.map_ptr + offset, mem + offset, size);
glFlushMappedBufferRange(target, offset, size);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFramebufferRenderbuffer(
GLenum target,
GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer) {
glFramebufferRenderbufferEXT(
target, attachment, renderbuffertarget,
GetRenderbufferServiceID(renderbuffer, resources_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2D(
GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture,
GLint level) {
glFramebufferTexture2DEXT(target, attachment, textarget,
GetTextureServiceID(texture, resources_, false),
level);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFramebufferTextureLayer(
GLenum target,
GLenum attachment,
GLuint texture,
GLint level,
GLint layer) {
glFramebufferTextureLayer(target, attachment,
GetTextureServiceID(texture, resources_, false),
level, layer);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFrontFace(GLenum mode) {
glFrontFace(mode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGenBuffers(
GLsizei n,
volatile GLuint* buffers) {
return GenHelper(
n, buffers, &resources_->buffer_id_map,
[](GLsizei n, GLuint* buffers) { glGenBuffersARB(n, buffers); });
}
error::Error GLES2DecoderPassthroughImpl::DoGenerateMipmap(GLenum target) {
glGenerateMipmapEXT(target);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGenFramebuffers(
GLsizei n,
volatile GLuint* framebuffers) {
return GenHelper(n, framebuffers, &framebuffer_id_map_,
[](GLsizei n, GLuint* framebuffers) {
glGenFramebuffersEXT(n, framebuffers);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGenRenderbuffers(
GLsizei n,
volatile GLuint* renderbuffers) {
return GenHelper(n, renderbuffers, &resources_->renderbuffer_id_map,
[](GLsizei n, GLuint* renderbuffers) {
glGenRenderbuffersEXT(n, renderbuffers);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGenSamplers(
GLsizei n,
volatile GLuint* samplers) {
return GenHelper(
n, samplers, &resources_->sampler_id_map,
[](GLsizei n, GLuint* samplers) { glGenSamplers(n, samplers); });
}
error::Error GLES2DecoderPassthroughImpl::DoGenTextures(
GLsizei n,
volatile GLuint* textures) {
return GenHelper(
n, textures, &resources_->texture_id_map,
[](GLsizei n, GLuint* textures) { glGenTextures(n, textures); });
}
error::Error GLES2DecoderPassthroughImpl::DoGenTransformFeedbacks(
GLsizei n,
volatile GLuint* ids) {
return GenHelper(n, ids, &transform_feedback_id_map_,
[](GLsizei n, GLuint* transform_feedbacks) {
glGenTransformFeedbacks(n, transform_feedbacks);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGetActiveAttrib(GLuint program,
GLuint index,
GLint* size,
GLenum* type,
std::string* name,
int32_t* success) {
FlushErrors();
GLuint service_id = GetProgramServiceID(program, resources_);
GLint active_attribute_max_length = 0;
glGetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
&active_attribute_max_length);
if (FlushErrors()) {
*success = 0;
return error::kNoError;
}
std::vector<char> name_buffer(active_attribute_max_length, 0);
glGetActiveAttrib(service_id, index, name_buffer.size(), nullptr, size, type,
name_buffer.data());
*name = std::string(name_buffer.data());
*success = FlushErrors() ? 0 : 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniform(GLuint program,
GLuint index,
GLint* size,
GLenum* type,
std::string* name,
int32_t* success) {
FlushErrors();
GLuint service_id = GetProgramServiceID(program, resources_);
GLint active_uniform_max_length = 0;
glGetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH,
&active_uniform_max_length);
if (FlushErrors()) {
*success = 0;
return error::kNoError;
}
std::vector<char> name_buffer(active_uniform_max_length, 0);
glGetActiveUniform(service_id, index, name_buffer.size(), nullptr, size, type,
name_buffer.data());
*name = std::string(name_buffer.data());
*success = FlushErrors() ? 0 : 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformBlockiv(
GLuint program,
GLuint index,
GLenum pname,
GLsizei bufSize,
GLsizei* length,
GLint* params) {
glGetActiveUniformBlockivRobustANGLE(GetProgramServiceID(program, resources_),
index, pname, bufSize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformBlockName(
GLuint program,
GLuint index,
std::string* name) {
FlushErrors();
GLuint program_service_id = GetProgramServiceID(program, resources_);
GLint max_name_length = 0;
glGetProgramiv(program_service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
&max_name_length);
if (FlushErrors()) {
return error::kNoError;
}
std::vector<GLchar> buffer(max_name_length, 0);
GLsizei length = 0;
glGetActiveUniformBlockName(program_service_id, index, max_name_length,
&length, buffer.data());
DCHECK(length <= max_name_length);
*name = length > 0 ? std::string(buffer.data(), length) : std::string();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformsiv(
GLuint program,
GLsizei count,
const GLuint* indices,
GLenum pname,
GLint* params) {
glGetActiveUniformsiv(GetProgramServiceID(program, resources_), count,
indices, pname, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetAttachedShaders(
GLuint program,
GLsizei maxcount,
GLsizei* count,
GLuint* shaders) {
glGetAttachedShaders(GetProgramServiceID(program, resources_), maxcount,
count, shaders);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetAttribLocation(GLuint program,
const char* name,
GLint* result) {
*result = glGetAttribLocation(GetProgramServiceID(program, resources_), name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetBufferSubDataAsyncCHROMIUM(
GLenum target,
GLintptr offset,
GLsizeiptr size,
uint8_t* mem) {
FlushErrors();
void* mapped_ptr = glMapBufferRange(target, offset, size, GL_MAP_READ_BIT);
if (FlushErrors() || mapped_ptr == nullptr) {
// Had an error while mapping, don't copy any data
return error::kNoError;
}
memcpy(mem, mapped_ptr, size);
glUnmapBuffer(target);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetBooleanv(GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLboolean* params) {
return GetNumericHelper(
pname, bufsize, length, params,
[](GLenum pname, GLsizei bufsize, GLsizei* length, GLboolean* params) {
glGetBooleanvRobustANGLE(pname, bufsize, length, params);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGetBufferParameteri64v(
GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint64* params) {
glGetBufferParameteri64vRobustANGLE(target, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetBufferParameteriv(
GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetBufferParameterivRobustANGLE(target, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetError(uint32_t* result) {
FlushErrors();
*result = PopError();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetFloatv(GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLfloat* params) {
return GetNumericHelper(
pname, bufsize, length, params,
[](GLenum pname, GLsizei bufsize, GLsizei* length, GLfloat* params) {
glGetFloatvRobustANGLE(pname, bufsize, length, params);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGetFragDataLocation(
GLuint program,
const char* name,
GLint* result) {
*result =
glGetFragDataLocation(GetProgramServiceID(program, resources_), name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetFramebufferAttachmentParameteriv(
GLenum target,
GLenum attachment,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
// Get a scratch buffer to hold the result of the query
GLint* scratch_params = GetTypedScratchMemory<GLint>(bufsize);
glGetFramebufferAttachmentParameterivRobustANGLE(
target, attachment, pname, bufsize, length, scratch_params);
// Update the results of the query, if needed
error::Error error = PatchGetFramebufferAttachmentParameter(
target, attachment, pname, *length, scratch_params);
if (error != error::kNoError) {
*length = 0;
return error;
}
// Copy into the destination
DCHECK(*length < bufsize);
std::copy(scratch_params, scratch_params + *length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetInteger64v(GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint64* params) {
return GetNumericHelper(
pname, bufsize, length, params,
[](GLenum pname, GLsizei bufsize, GLsizei* length, GLint64* params) {
glGetInteger64vRobustANGLE(pname, bufsize, length, params);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGetIntegeri_v(GLenum pname,
GLuint index,
GLsizei bufsize,
GLsizei* length,
GLint* data) {
glGetIntegeri_vRobustANGLE(pname, index, bufsize, length, data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetInteger64i_v(GLenum pname,
GLuint index,
GLsizei bufsize,
GLsizei* length,
GLint64* data) {
glGetInteger64i_vRobustANGLE(pname, index, bufsize, length, data);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetIntegerv(GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
return GetNumericHelper(
pname, bufsize, length, params,
[](GLenum pname, GLsizei bufsize, GLsizei* length, GLint* params) {
glGetIntegervRobustANGLE(pname, bufsize, length, params);
});
}
error::Error GLES2DecoderPassthroughImpl::DoGetInternalformativ(GLenum target,
GLenum format,
GLenum pname,
GLsizei bufSize,
GLsizei* length,
GLint* params) {
glGetInternalformativRobustANGLE(target, format, pname, bufSize, length,
params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetProgramiv(GLuint program,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetProgramivRobustANGLE(GetProgramServiceID(program, resources_), pname,
bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetProgramInfoLog(
GLuint program,
std::string* infolog) {
FlushErrors();
GLint info_log_len = 0;
glGetProgramiv(GetProgramServiceID(program, resources_), GL_INFO_LOG_LENGTH,
&info_log_len);
if (FlushErrors()) {
return error::kNoError;
}
std::vector<char> buffer(info_log_len, 0);
GLsizei length = 0;
glGetProgramInfoLog(GetProgramServiceID(program, resources_), info_log_len,
&length, buffer.data());
DCHECK(length <= info_log_len);
*infolog = length > 0 ? std::string(buffer.data(), length) : std::string();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetRenderbufferParameteriv(
GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetRenderbufferParameterivRobustANGLE(target, pname, bufsize, length,
params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetSamplerParameterfv(
GLuint sampler,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLfloat* params) {
glGetSamplerParameterfvRobustANGLE(GetSamplerServiceID(sampler, resources_),
pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetSamplerParameteriv(
GLuint sampler,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetSamplerParameterivRobustANGLE(GetSamplerServiceID(sampler, resources_),
pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetShaderiv(GLuint shader,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetShaderivRobustANGLE(GetShaderServiceID(shader, resources_), pname,
bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetShaderInfoLog(
GLuint shader,
std::string* infolog) {
FlushErrors();
GLuint service_id = GetShaderServiceID(shader, resources_);
GLint info_log_len = 0;
glGetShaderiv(service_id, GL_INFO_LOG_LENGTH, &info_log_len);
if (FlushErrors()) {
return error::kNoError;
}
std::vector<char> buffer(info_log_len, 0);
GLsizei length = 0;
glGetShaderInfoLog(service_id, info_log_len, &length, buffer.data());
DCHECK(length <= info_log_len);
*infolog = length > 0 ? std::string(buffer.data(), length) : std::string();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetShaderPrecisionFormat(
GLenum shadertype,
GLenum precisiontype,
GLint* range,
GLint* precision,
int32_t* success) {
FlushErrors();
glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
*success = FlushErrors() ? 0 : 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetShaderSource(
GLuint shader,
std::string* source) {
FlushErrors();
GLuint shader_service_id = GetShaderServiceID(shader, resources_);
GLint shader_source_length = 0;
glGetShaderiv(shader_service_id, GL_SHADER_SOURCE_LENGTH,
&shader_source_length);
if (FlushErrors()) {
return error::kNoError;
}
std::vector<char> buffer(shader_source_length, 0);
GLsizei length = 0;
glGetShaderSource(shader_service_id, shader_source_length, &length,
buffer.data());
DCHECK(length <= shader_source_length);
*source = shader_source_length > 0 ? std::string(buffer.data(), length)
: std::string();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetString(GLenum name,
const char** result) {
switch (name) {
case GL_VERSION:
*result = GetServiceVersionString(feature_info_.get());
break;
case GL_SHADING_LANGUAGE_VERSION:
*result = GetServiceShadingLanguageVersionString(feature_info_.get());
break;
case GL_EXTENSIONS:
*result = feature_info_->extensions().c_str();
break;
default:
*result = reinterpret_cast<const char*>(glGetString(name));
break;
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetSynciv(GLuint sync,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* values) {
glGetSynciv(GetSyncServiceID(sync, resources_), pname, bufsize, length,
values);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetTexParameterfv(GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLfloat* params) {
glGetTexParameterfvRobustANGLE(target, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetTexParameteriv(GLenum target,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetTexParameterivRobustANGLE(target, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetTransformFeedbackVarying(
GLuint program,
GLuint index,
GLsizei* size,
GLenum* type,
std::string* name,
int32_t* success) {
FlushErrors();
GLuint service_id = GetProgramServiceID(program, resources_);
GLint transform_feedback_varying_max_length = 0;
glGetProgramiv(service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
&transform_feedback_varying_max_length);
if (FlushErrors()) {
*success = 0;
return error::kNoError;
}
std::vector<char> name_buffer(transform_feedback_varying_max_length, 0);
glGetTransformFeedbackVarying(service_id, index, name_buffer.size(), nullptr,
size, type, name_buffer.data());
*name = std::string(name_buffer.data());
*success = FlushErrors() ? 0 : 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformBlockIndex(
GLuint program,
const char* name,
GLint* index) {
*index =
glGetUniformBlockIndex(GetProgramServiceID(program, resources_), name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformfv(GLuint program,
GLint location,
GLsizei bufsize,
GLsizei* length,
GLfloat* params) {
// GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
// points in GL_EXT_robustness
glGetUniformfvRobustANGLE(GetProgramServiceID(program, resources_), location,
bufsize * sizeof(*params), length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformiv(GLuint program,
GLint location,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
// GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
// points in GL_EXT_robustness
glGetUniformivRobustANGLE(GetProgramServiceID(program, resources_), location,
bufsize * sizeof(*params), length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformuiv(GLuint program,
GLint location,
GLsizei bufsize,
GLsizei* length,
GLuint* params) {
// GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
// points in GL_EXT_robustness
glGetUniformuivRobustANGLE(GetProgramServiceID(program, resources_), location,
bufsize * sizeof(*params), length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformIndices(
GLuint program,
GLsizei count,
const char* const* names,
GLsizei bufSize,
GLuint* indices) {
glGetUniformIndices(GetProgramServiceID(program, resources_), count, names,
indices);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformLocation(
GLuint program,
const char* name,
GLint* location) {
*location =
glGetUniformLocation(GetProgramServiceID(program, resources_), name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribfv(GLuint index,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLfloat* params) {
glGetVertexAttribfvRobustANGLE(index, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribiv(GLuint index,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetVertexAttribivRobustANGLE(index, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribIiv(GLuint index,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLint* params) {
glGetVertexAttribIivRobustANGLE(index, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribIuiv(
GLuint index,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLuint* params) {
glGetVertexAttribIuivRobustANGLE(index, pname, bufsize, length, params);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribPointerv(
GLuint index,
GLenum pname,
GLsizei bufsize,
GLsizei* length,
GLuint* pointer) {
std::array<void*, 1> temp_pointers{{nullptr}};
GLsizei temp_length = 0;
glGetVertexAttribPointervRobustANGLE(
index, pname, static_cast<GLsizei>(temp_pointers.size()), &temp_length,
temp_pointers.data());
DCHECK(temp_length >= 0 &&
temp_length <= static_cast<GLsizei>(temp_pointers.size()) &&
temp_length <= bufsize);
for (GLsizei ii = 0; ii < temp_length; ii++) {
pointer[ii] =
static_cast<GLuint>(reinterpret_cast<uintptr_t>(temp_pointers[ii]));
}
*length = temp_length;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoHint(GLenum target, GLenum mode) {
glHint(target, mode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoInvalidateFramebuffer(
GLenum target,
GLsizei count,
const volatile GLenum* attachments) {
// Validate that count is non-negative before allocating a vector
if (count < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<GLenum> attachments_copy(attachments, attachments + count);
glInvalidateFramebuffer(target, count, attachments_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoInvalidateSubFramebuffer(
GLenum target,
GLsizei count,
const volatile GLenum* attachments,
GLint x,
GLint y,
GLsizei width,
GLsizei height) {
// Validate that count is non-negative before allocating a vector
if (count < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<GLenum> attachments_copy(attachments, attachments + count);
glInvalidateSubFramebuffer(target, count, attachments_copy.data(), x, y,
width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsBuffer(GLuint buffer,
uint32_t* result) {
*result = glIsBuffer(GetBufferServiceID(buffer, resources_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsEnabled(GLenum cap,
uint32_t* result) {
*result = glIsEnabled(cap);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsFramebuffer(GLuint framebuffer,
uint32_t* result) {
*result = glIsFramebufferEXT(
GetFramebufferServiceID(framebuffer, &framebuffer_id_map_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsProgram(GLuint program,
uint32_t* result) {
*result = glIsProgram(GetProgramServiceID(program, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsRenderbuffer(GLuint renderbuffer,
uint32_t* result) {
*result = glIsRenderbufferEXT(
GetRenderbufferServiceID(renderbuffer, resources_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsSampler(GLuint sampler,
uint32_t* result) {
*result = glIsSampler(GetSamplerServiceID(sampler, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsShader(GLuint shader,
uint32_t* result) {
*result = glIsShader(GetShaderServiceID(shader, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsSync(GLuint sync,
uint32_t* result) {
*result = glIsSync(GetSyncServiceID(sync, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsTexture(GLuint texture,
uint32_t* result) {
*result = glIsTexture(GetTextureServiceID(texture, resources_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsTransformFeedback(
GLuint transformfeedback,
uint32_t* result) {
*result = glIsTransformFeedback(GetTransformFeedbackServiceID(
transformfeedback, &transform_feedback_id_map_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoLineWidth(GLfloat width) {
glLineWidth(width);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoLinkProgram(GLuint program) {
glLinkProgram(GetProgramServiceID(program, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPauseTransformFeedback() {
glPauseTransformFeedback();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPixelStorei(GLenum pname,
GLint param) {
glPixelStorei(pname, param);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPolygonOffset(GLfloat factor,
GLfloat units) {
glPolygonOffset(factor, units);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoReadBuffer(GLenum src) {
glReadBuffer(src);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoReadPixels(GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
GLsizei bufsize,
GLsizei* length,
GLsizei* columns,
GLsizei* rows,
void* pixels,
int32_t* success) {
FlushErrors();
glReadPixelsRobustANGLE(x, y, width, height, format, type, bufsize, length,
columns, rows, pixels);
*success = FlushErrors() ? 0 : 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoReleaseShaderCompiler() {
glReleaseShaderCompiler();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoRenderbufferStorage(
GLenum target,
GLenum internalformat,
GLsizei width,
GLsizei height) {
glRenderbufferStorageEXT(target, internalformat, width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoResumeTransformFeedback() {
glResumeTransformFeedback();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSampleCoverage(GLclampf value,
GLboolean invert) {
glSampleCoverage(value, invert);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSamplerParameterf(GLuint sampler,
GLenum pname,
GLfloat param) {
glSamplerParameterf(GetSamplerServiceID(sampler, resources_), pname, param);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSamplerParameterfv(
GLuint sampler,
GLenum pname,
const volatile GLfloat* params) {
std::array<GLfloat, 1> params_copy{{params[0]}};
glSamplerParameterfvRobustANGLE(
GetSamplerServiceID(sampler, resources_), pname,
static_cast<GLsizei>(params_copy.size()), params_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSamplerParameteri(GLuint sampler,
GLenum pname,
GLint param) {
glSamplerParameteri(GetSamplerServiceID(sampler, resources_), pname, param);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSamplerParameteriv(
GLuint sampler,
GLenum pname,
const volatile GLint* params) {
std::array<GLint, 1> params_copy{{params[0]}};
glSamplerParameterivRobustANGLE(
GetSamplerServiceID(sampler, resources_), pname,
static_cast<GLsizei>(params_copy.size()), params_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScissor(GLint x,
GLint y,
GLsizei width,
GLsizei height) {
glScissor(x, y, width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoShaderBinary(GLsizei n,
const GLuint* shaders,
GLenum binaryformat,
const void* binary,
GLsizei length) {
std::vector<GLuint> service_shaders(n, 0);
for (GLsizei i = 0; i < n; i++) {
service_shaders[i] = GetShaderServiceID(shaders[i], resources_);
}
glShaderBinary(n, service_shaders.data(), binaryformat, binary, length);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoShaderSource(GLuint shader,
GLsizei count,
const char** string,
const GLint* length) {
glShaderSource(GetShaderServiceID(shader, resources_), count, string, length);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilFunc(GLenum func,
GLint ref,
GLuint mask) {
glStencilFunc(func, ref, mask);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilFuncSeparate(GLenum face,
GLenum func,
GLint ref,
GLuint mask) {
glStencilFuncSeparate(face, func, ref, mask);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilMask(GLuint mask) {
glStencilMask(mask);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilMaskSeparate(GLenum face,
GLuint mask) {
glStencilMaskSeparate(face, mask);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilOp(GLenum fail,
GLenum zfail,
GLenum zpass) {
glStencilOp(fail, zfail, zpass);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilOpSeparate(GLenum face,
GLenum fail,
GLenum zfail,
GLenum zpass) {
glStencilOpSeparate(face, fail, zfail, zpass);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexImage2D(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
GLsizei image_size,
const void* pixels) {
ScopedUnpackStateButAlignmentReset reset_unpack(
image_size != 0 && feature_info_->gl_version_info().is_es3, false);
glTexImage2DRobustANGLE(target, level, internalformat, width, height, border,
format, type, image_size, pixels);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexImage3D(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
GLint border,
GLenum format,
GLenum type,
GLsizei image_size,
const void* pixels) {
ScopedUnpackStateButAlignmentReset reset_unpack(
image_size != 0 && feature_info_->gl_version_info().is_es3, true);
glTexImage3DRobustANGLE(target, level, internalformat, width, height, depth,
border, format, type, image_size, pixels);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexParameterf(GLenum target,
GLenum pname,
GLfloat param) {
glTexParameterf(target, pname, param);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexParameterfv(
GLenum target,
GLenum pname,
const volatile GLfloat* params) {
std::array<GLfloat, 1> params_copy{{params[0]}};
glTexParameterfvRobustANGLE(target, pname,
static_cast<GLsizei>(params_copy.size()),
params_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexParameteri(GLenum target,
GLenum pname,
GLint param) {
glTexParameteri(target, pname, param);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexParameteriv(
GLenum target,
GLenum pname,
const volatile GLint* params) {
std::array<GLint, 1> params_copy{{params[0]}};
glTexParameterivRobustANGLE(target, pname,
static_cast<GLsizei>(params_copy.size()),
params_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexStorage3D(GLenum target,
GLsizei levels,
GLenum internalFormat,
GLsizei width,
GLsizei height,
GLsizei depth) {
glTexStorage3D(target, levels, internalFormat, width, height, depth);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexSubImage2D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
GLsizei image_size,
const void* pixels) {
ScopedUnpackStateButAlignmentReset reset_unpack(
image_size != 0 && feature_info_->gl_version_info().is_es3, false);
glTexSubImage2DRobustANGLE(target, level, xoffset, yoffset, width, height,
format, type, image_size, pixels);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexSubImage3D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLenum type,
GLsizei image_size,
const void* pixels) {
ScopedUnpackStateButAlignmentReset reset_unpack(
image_size != 0 && feature_info_->gl_version_info().is_es3, true);
glTexSubImage3DRobustANGLE(target, level, xoffset, yoffset, zoffset, width,
height, depth, format, type, image_size, pixels);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTransformFeedbackVaryings(
GLuint program,
GLsizei count,
const char** varyings,
GLenum buffermode) {
glTransformFeedbackVaryings(GetProgramServiceID(program, resources_), count,
varyings, buffermode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1f(GLint location,
GLfloat x) {
glUniform1f(location, x);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1fv(
GLint location,
GLsizei count,
const volatile GLfloat* v) {
glUniform1fv(location, count, const_cast<const GLfloat*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1i(GLint location, GLint x) {
glUniform1i(location, x);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1iv(
GLint location,
GLsizei count,
const volatile GLint* v) {
glUniform1iv(location, count, const_cast<const GLint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1ui(GLint location,
GLuint x) {
glUniform1ui(location, x);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform1uiv(
GLint location,
GLsizei count,
const volatile GLuint* v) {
glUniform1uiv(location, count, const_cast<const GLuint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2f(GLint location,
GLfloat x,
GLfloat y) {
glUniform2f(location, x, y);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2fv(
GLint location,
GLsizei count,
const volatile GLfloat* v) {
glUniform2fv(location, count, const_cast<const GLfloat*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2i(GLint location,
GLint x,
GLint y) {
glUniform2i(location, x, y);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2iv(
GLint location,
GLsizei count,
const volatile GLint* v) {
glUniform2iv(location, count, const_cast<const GLint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2ui(GLint location,
GLuint x,
GLuint y) {
glUniform2ui(location, x, y);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform2uiv(
GLint location,
GLsizei count,
const volatile GLuint* v) {
glUniform2uiv(location, count, const_cast<const GLuint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3f(GLint location,
GLfloat x,
GLfloat y,
GLfloat z) {
glUniform3f(location, x, y, z);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3fv(
GLint location,
GLsizei count,
const volatile GLfloat* v) {
glUniform3fv(location, count, const_cast<const GLfloat*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3i(GLint location,
GLint x,
GLint y,
GLint z) {
glUniform3i(location, x, y, z);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3iv(
GLint location,
GLsizei count,
const volatile GLint* v) {
glUniform3iv(location, count, const_cast<const GLint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3ui(GLint location,
GLuint x,
GLuint y,
GLuint z) {
glUniform3ui(location, x, y, z);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform3uiv(
GLint location,
GLsizei count,
const volatile GLuint* v) {
glUniform3uiv(location, count, const_cast<const GLuint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4f(GLint location,
GLfloat x,
GLfloat y,
GLfloat z,
GLfloat w) {
glUniform4f(location, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4fv(
GLint location,
GLsizei count,
const volatile GLfloat* v) {
glUniform4fv(location, count, const_cast<const GLfloat*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4i(GLint location,
GLint x,
GLint y,
GLint z,
GLint w) {
glUniform4i(location, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4iv(
GLint location,
GLsizei count,
const volatile GLint* v) {
glUniform4iv(location, count, const_cast<const GLint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4ui(GLint location,
GLuint x,
GLuint y,
GLuint z,
GLuint w) {
glUniform4ui(location, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniform4uiv(
GLint location,
GLsizei count,
const volatile GLuint* v) {
glUniform4uiv(location, count, const_cast<const GLuint*>(v));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformBlockBinding(
GLuint program,
GLuint index,
GLuint binding) {
glUniformBlockBinding(GetProgramServiceID(program, resources_), index,
binding);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix2fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2x3fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix2x3fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2x4fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix2x4fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix3fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3x2fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix3x2fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3x4fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix3x4fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix4fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4x2fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix4x2fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4x3fv(
GLint location,
GLsizei count,
GLboolean transpose,
const volatile GLfloat* value) {
glUniformMatrix4x3fv(location, count, transpose,
const_cast<const GLfloat*>(value));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUseProgram(GLuint program) {
glUseProgram(GetProgramServiceID(program, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoValidateProgram(GLuint program) {
glValidateProgram(GetProgramServiceID(program, resources_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib1f(GLuint indx,
GLfloat x) {
glVertexAttrib1f(indx, x);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib1fv(
GLuint indx,
const volatile GLfloat* values) {
glVertexAttrib1fv(indx, const_cast<const GLfloat*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib2f(GLuint indx,
GLfloat x,
GLfloat y) {
glVertexAttrib2f(indx, x, y);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib2fv(
GLuint indx,
const volatile GLfloat* values) {
glVertexAttrib2fv(indx, const_cast<const GLfloat*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib3f(GLuint indx,
GLfloat x,
GLfloat y,
GLfloat z) {
glVertexAttrib3f(indx, x, y, z);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib3fv(
GLuint indx,
const volatile GLfloat* values) {
glVertexAttrib3fv(indx, const_cast<const GLfloat*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib4f(GLuint indx,
GLfloat x,
GLfloat y,
GLfloat z,
GLfloat w) {
glVertexAttrib4f(indx, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib4fv(
GLuint indx,
const volatile GLfloat* values) {
glVertexAttrib4fv(indx, const_cast<const GLfloat*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4i(GLuint indx,
GLint x,
GLint y,
GLint z,
GLint w) {
glVertexAttribI4i(indx, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4iv(
GLuint indx,
const volatile GLint* values) {
glVertexAttribI4iv(indx, const_cast<const GLint*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4ui(GLuint indx,
GLuint x,
GLuint y,
GLuint z,
GLuint w) {
glVertexAttribI4ui(indx, x, y, z, w);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4uiv(
GLuint indx,
const volatile GLuint* values) {
glVertexAttribI4uiv(indx, const_cast<const GLuint*>(values));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribIPointer(
GLuint indx,
GLint size,
GLenum type,
GLsizei stride,
const void* ptr) {
glVertexAttribIPointer(indx, size, type, stride, ptr);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribPointer(
GLuint indx,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const void* ptr) {
glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoViewport(GLint x,
GLint y,
GLsizei width,
GLsizei height) {
glViewport(x, y, width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoWaitSync(GLuint sync,
GLbitfield flags,
GLuint64 timeout) {
glWaitSync(GetSyncServiceID(sync, resources_), flags, timeout);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlitFramebufferCHROMIUM(
GLint srcX0,
GLint srcY0,
GLint srcX1,
GLint srcY1,
GLint dstX0,
GLint dstY0,
GLint dstX1,
GLint dstY1,
GLbitfield mask,
GLenum filter) {
glBlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
mask, filter);
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoRenderbufferStorageMultisampleCHROMIUM(
GLenum target,
GLsizei samples,
GLenum internalformat,
GLsizei width,
GLsizei height) {
if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
return error::kUnknownCommand;
}
if (feature_info_->feature_flags().angle_framebuffer_multisample) {
glRenderbufferStorageMultisampleANGLE(target, samples, internalformat,
width, height);
} else {
DCHECK(feature_info_->gl_version_info().is_es3);
glRenderbufferStorageMultisample(target, samples, internalformat, width,
height);
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoRenderbufferStorageMultisampleEXT(
GLenum target,
GLsizei samples,
GLenum internalformat,
GLsizei width,
GLsizei height) {
if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
return error::kUnknownCommand;
}
if (feature_info_->feature_flags().angle_framebuffer_multisample) {
glRenderbufferStorageMultisampleANGLE(target, samples, internalformat,
width, height);
} else {
DCHECK(feature_info_->gl_version_info().is_es3);
glRenderbufferStorageMultisample(target, samples, internalformat, width,
height);
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2DMultisampleEXT(
GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture,
GLint level,
GLsizei samples) {
glFramebufferTexture2DMultisampleEXT(
target, attachment, textarget,
GetTextureServiceID(texture, resources_, false), level, samples);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTexStorage2DEXT(
GLenum target,
GLsizei levels,
GLenum internalFormat,
GLsizei width,
GLsizei height) {
glTexStorage2DEXT(target, levels, internalFormat, width, height);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGenQueriesEXT(
GLsizei n,
volatile GLuint* queries) {
return GenHelper(n, queries, &query_id_map_, [](GLsizei n, GLuint* queries) {
glGenQueries(n, queries);
});
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteQueriesEXT(
GLsizei n,
const volatile GLuint* queries) {
// Validate n is non-negative before allcoating a vector of size n
if (n < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<GLuint> queries_copy(queries, queries + n);
// If any of these queries are pending or active, remove them from the lists
for (GLuint query_client_id : queries_copy) {
GLuint query_service_id = 0;
if (!query_id_map_.GetServiceID(query_client_id, &query_service_id) ||
query_service_id == 0) {
continue;
}
QueryInfo query_info = query_info_map_[query_service_id];
query_info_map_.erase(query_service_id);
if (query_info.type == GL_NONE) {
// Query was never started
continue;
}
auto active_queries_iter = active_queries_.find(query_info.type);
if (active_queries_iter != active_queries_.end()) {
active_queries_.erase(active_queries_iter);
}
RemovePendingQuery(query_service_id);
}
return DeleteHelper(
queries_copy.size(), queries_copy.data(), &query_id_map_,
[](GLsizei n, GLuint* queries) { glDeleteQueries(n, queries); });
}
error::Error GLES2DecoderPassthroughImpl::DoQueryCounterEXT(
GLuint id,
GLenum target,
int32_t sync_shm_id,
uint32_t sync_shm_offset,
uint32_t submit_count) {
if (!feature_info_->feature_flags().ext_disjoint_timer_query) {
return error::kUnknownCommand;
}
GLuint service_id = GetQueryServiceID(id, &query_id_map_);
// Flush all previous errors
FlushErrors();
glQueryCounter(service_id, target);
// Check if a new error was generated
if (FlushErrors()) {
return error::kNoError;
}
QueryInfo* query_info = &query_info_map_[service_id];
query_info->type = target;
// Make sure to stop tracking this query if it was still pending a result from
// a previous glEndQuery
RemovePendingQuery(service_id);
PendingQuery pending_query;
pending_query.target = target;
pending_query.service_id = service_id;
pending_query.shm_id = sync_shm_id;
pending_query.shm_offset = sync_shm_offset;
pending_query.submit_count = submit_count;
pending_queries_.push_back(pending_query);
return ProcessQueries(false);
}
error::Error GLES2DecoderPassthroughImpl::DoBeginQueryEXT(
GLenum target,
GLuint id,
int32_t sync_shm_id,
uint32_t sync_shm_offset) {
GLuint service_id = GetQueryServiceID(id, &query_id_map_);
QueryInfo* query_info = &query_info_map_[service_id];
if (IsEmulatedQueryTarget(target)) {
if (active_queries_.find(target) != active_queries_.end()) {
InsertError(GL_INVALID_OPERATION, "Query already active on target.");
return error::kNoError;
}
if (id == 0) {
InsertError(GL_INVALID_OPERATION, "Query id is 0.");
return error::kNoError;
}
if (query_info->type != GL_NONE && query_info->type != target) {
InsertError(GL_INVALID_OPERATION,
"Query type does not match the target.");
return error::kNoError;
}
} else {
// Flush all previous errors
FlushErrors();
glBeginQuery(target, service_id);
// Check if a new error was generated
if (FlushErrors()) {
return error::kNoError;
}
}
query_info->type = target;
// Make sure to stop tracking this query if it was still pending a result from
// a previous glEndQuery
RemovePendingQuery(service_id);
ActiveQuery query;
query.service_id = service_id;
query.shm_id = sync_shm_id;
query.shm_offset = sync_shm_offset;
active_queries_[target] = query;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBeginTransformFeedback(
GLenum primitivemode) {
glBeginTransformFeedback(primitivemode);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoEndQueryEXT(GLenum target,
uint32_t submit_count) {
if (IsEmulatedQueryTarget(target)) {
if (active_queries_.find(target) == active_queries_.end()) {
InsertError(GL_INVALID_OPERATION, "No active query on target.");
return error::kNoError;
}
} else {
// Flush all previous errors
FlushErrors();
glEndQuery(target);
// Check if a new error was generated
if (FlushErrors()) {
return error::kNoError;
}
}
DCHECK(active_queries_.find(target) != active_queries_.end());
ActiveQuery active_query = active_queries_[target];
active_queries_.erase(target);
PendingQuery pending_query;
pending_query.target = target;
pending_query.service_id = active_query.service_id;
pending_query.shm_id = active_query.shm_id;
pending_query.shm_offset = active_query.shm_offset;
pending_query.submit_count = submit_count;
pending_queries_.push_back(pending_query);
return ProcessQueries(false);
}
error::Error GLES2DecoderPassthroughImpl::DoEndTransformFeedback() {
glEndTransformFeedback();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSetDisjointValueSyncCHROMIUM(
DisjointValueSync* sync) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoInsertEventMarkerEXT(
GLsizei length,
const char* marker) {
if (!feature_info_->feature_flags().ext_debug_marker) {
return error::kUnknownCommand;
}
glInsertEventMarkerEXT(length, marker);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPushGroupMarkerEXT(
GLsizei length,
const char* marker) {
if (!feature_info_->feature_flags().ext_debug_marker) {
return error::kUnknownCommand;
}
glPushGroupMarkerEXT(length, marker);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPopGroupMarkerEXT() {
if (!feature_info_->feature_flags().ext_debug_marker) {
return error::kUnknownCommand;
}
glPopGroupMarkerEXT();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGenVertexArraysOES(
GLsizei n,
volatile GLuint* arrays) {
return GenHelper(
n, arrays, &vertex_array_id_map_,
[](GLsizei n, GLuint* arrays) { glGenVertexArraysOES(n, arrays); });
}
error::Error GLES2DecoderPassthroughImpl::DoDeleteVertexArraysOES(
GLsizei n,
const volatile GLuint* arrays) {
return DeleteHelper(
n, arrays, &vertex_array_id_map_,
[](GLsizei n, GLuint* arrays) { glDeleteVertexArraysOES(n, arrays); });
}
error::Error GLES2DecoderPassthroughImpl::DoIsVertexArrayOES(GLuint array,
uint32_t* result) {
*result =
glIsVertexArrayOES(GetVertexArrayServiceID(array, &vertex_array_id_map_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindVertexArrayOES(GLuint array) {
glBindVertexArrayOES(GetVertexArrayServiceID(array, &vertex_array_id_map_));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSwapBuffers() {
if (offscreen_) {
NOTIMPLEMENTED();
return error::kNoError;
}
gfx::SwapResult result = surface_->SwapBuffers();
if (result == gfx::SwapResult::SWAP_FAILED) {
LOG(ERROR) << "Context lost because SwapBuffers failed.";
}
// TODO(geofflang): force the context loss?
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetMaxValueInBufferCHROMIUM(
GLuint buffer_id,
GLsizei count,
GLenum type,
GLuint offset,
uint32_t* result) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoEnableFeatureCHROMIUM(
const char* feature) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoMapBufferRange(
GLenum target,
GLintptr offset,
GLsizeiptr size,
GLbitfield access,
void* ptr,
int32_t data_shm_id,
uint32_t data_shm_offset,
uint32_t* result) {
FlushErrors();
GLbitfield filtered_access = access;
// Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of undefined
// behaviors.
filtered_access = (filtered_access & ~GL_MAP_UNSYNCHRONIZED_BIT);
if ((filtered_access & GL_MAP_INVALIDATE_BUFFER_BIT) != 0) {
// To be on the safe side, always map GL_MAP_INVALIDATE_BUFFER_BIT to
// GL_MAP_INVALIDATE_RANGE_BIT.
filtered_access = (filtered_access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
filtered_access = (filtered_access | GL_MAP_INVALIDATE_RANGE_BIT);
}
if ((filtered_access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
// If this user intends to use this buffer without invalidating the data, we
// need to also add GL_MAP_READ_BIT to preserve the original data when
// copying it to shared memory.
filtered_access = (filtered_access | GL_MAP_READ_BIT);
}
void* mapped_ptr = glMapBufferRange(target, offset, size, filtered_access);
if (FlushErrors() || mapped_ptr == nullptr) {
// Had an error while mapping, don't copy any data
*result = 0;
return error::kNoError;
}
if ((filtered_access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
memcpy(ptr, mapped_ptr, size);
}
// Track the mapping of this buffer so that data can be synchronized when it
// is unmapped
DCHECK(bound_buffers_.find(target) != bound_buffers_.end());
GLuint client_buffer = bound_buffers_.at(target);
MappedBuffer mapped_buffer_info;
mapped_buffer_info.size = size;
mapped_buffer_info.access = filtered_access;
mapped_buffer_info.map_ptr = static_cast<uint8_t*>(mapped_ptr);
mapped_buffer_info.data_shm_id = data_shm_id;
mapped_buffer_info.data_shm_offset = data_shm_offset;
DCHECK(resources_->mapped_buffer_map.find(client_buffer) ==
resources_->mapped_buffer_map.end());
resources_->mapped_buffer_map.insert(
std::make_pair(client_buffer, mapped_buffer_info));
*result = 1;
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoUnmapBuffer(GLenum target) {
auto bound_buffers_iter = bound_buffers_.find(target);
if (bound_buffers_iter == bound_buffers_.end() ||
bound_buffers_iter->second == 0) {
InsertError(GL_INVALID_OPERATION, "No buffer bound to this target.");
return error::kNoError;
}
GLuint client_buffer = bound_buffers_iter->second;
auto mapped_buffer_info_iter =
resources_->mapped_buffer_map.find(client_buffer);
if (mapped_buffer_info_iter == resources_->mapped_buffer_map.end()) {
InsertError(GL_INVALID_OPERATION, "Buffer is not mapped.");
return error::kNoError;
}
const MappedBuffer& map_info = mapped_buffer_info_iter->second;
if ((map_info.access & GL_MAP_WRITE_BIT) != 0 &&
(map_info.access & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
uint8_t* mem = GetSharedMemoryAs<uint8_t*>(
map_info.data_shm_id, map_info.data_shm_offset, map_info.size);
if (!mem) {
return error::kOutOfBounds;
}
memcpy(map_info.map_ptr, mem, map_info.size);
}
glUnmapBuffer(target);
resources_->mapped_buffer_map.erase(mapped_buffer_info_iter);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoResizeCHROMIUM(GLuint width,
GLuint height,
GLfloat scale_factor,
GLboolean alpha) {
if (offscreen_) {
// TODO: crbug.com/665521
NOTIMPLEMENTED();
} else {
if (!surface_->Resize(gfx::Size(width, height), scale_factor, !!alpha)) {
LOG(ERROR) << "GLES2DecoderImpl: Context lost because resize failed.";
return error::kLostContext;
}
DCHECK(context_->IsCurrent(surface_.get()));
if (!context_->IsCurrent(surface_.get())) {
LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
<< "current after resize callback.";
return error::kLostContext;
}
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetRequestableExtensionsCHROMIUM(
const char** extensions) {
*extensions = reinterpret_cast<const char*>(
glGetString(GL_REQUESTABLE_EXTENSIONS_ANGLE));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoRequestExtensionCHROMIUM(
const char* extension) {
glRequestExtensionANGLE(extension);
// Make sure there are no pending GL errors before re-initializing feature
// info
FlushErrors();
// Make sure newly enabled extensions are exposed and usable.
context_->ReinitializeDynamicBindings();
if (!feature_info_->Initialize(feature_info_->context_type(),
feature_info_->disallowed_features())) {
return error::kLostContext;
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetProgramInfoCHROMIUM(
GLuint program,
std::vector<uint8_t>* data) {
GLuint service_program = 0;
if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
return error::kNoError;
}
GLint num_attributes = 0;
glGetProgramiv(service_program, GL_ACTIVE_ATTRIBUTES, &num_attributes);
GLint num_uniforms = 0;
glGetProgramiv(service_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
const base::CheckedNumeric<size_t> buffer_header_size(
sizeof(ProgramInfoHeader));
const base::CheckedNumeric<size_t> buffer_block_size(
sizeof(ProgramInput));
const base::CheckedNumeric<size_t> attribute_block_size =
buffer_block_size * num_attributes;
const base::CheckedNumeric<size_t> uniform_block_size =
buffer_block_size * num_uniforms;
data->resize((buffer_header_size + attribute_block_size + uniform_block_size)
.ValueOrDie(),
0);
GLint link_status = 0;
glGetProgramiv(service_program, GL_LINK_STATUS, &link_status);
ProgramInfoHeader header;
header.link_status = link_status;
header.num_attribs = num_attributes;
header.num_uniforms = num_uniforms;
InsertValueIntoBuffer(data, header, 0);
GLint active_attribute_max_length = 0;
glGetProgramiv(service_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
&active_attribute_max_length);
std::vector<char> attrib_name_buf(active_attribute_max_length, 0);
for (GLint attrib_index = 0; attrib_index < num_attributes; attrib_index++) {
GLsizei length = 0;
GLint size = 0;
GLenum type = GL_NONE;
glGetActiveAttrib(service_program, attrib_index, attrib_name_buf.size(),
&length, &size, &type, attrib_name_buf.data());
ProgramInput input;
input.size = size;
input.type = type;
int32_t location =
glGetAttribLocation(service_program, attrib_name_buf.data());
input.location_offset = data->size();
AppendValueToBuffer(data, location);
input.name_offset = data->size();
input.name_length = length;
AppendStringToBuffer(data, attrib_name_buf.data(), length);
InsertValueIntoBuffer(
data, input,
(buffer_header_size + (buffer_block_size * attrib_index)).ValueOrDie());
}
GLint active_uniform_max_length = 0;
glGetProgramiv(service_program, GL_ACTIVE_UNIFORM_MAX_LENGTH,
&active_uniform_max_length);
std::vector<char> uniform_name_buf(active_uniform_max_length, 0);
for (GLint uniform_index = 0; uniform_index < num_uniforms; uniform_index++) {
GLsizei length = 0;
GLint size = 0;
GLenum type = GL_NONE;
glGetActiveUniform(service_program, uniform_index, uniform_name_buf.size(),
&length, &size, &type, uniform_name_buf.data());
ProgramInput input;
input.size = size;
input.type = type;
input.location_offset = data->size();
int32_t base_location =
glGetUniformLocation(service_program, uniform_name_buf.data());
AppendValueToBuffer(data, base_location);
GLSLArrayName parsed_service_name(uniform_name_buf.data());
if (size > 1 || parsed_service_name.IsArrayName()) {
for (GLint location_index = 1; location_index < size; location_index++) {
std::string array_element_name = parsed_service_name.base_name() + "[" +
base::IntToString(location_index) +
"]";
int32_t element_location =
glGetUniformLocation(service_program, array_element_name.c_str());
AppendValueToBuffer(data, element_location);
}
}
input.name_offset = data->size();
input.name_length = length;
AppendStringToBuffer(data, uniform_name_buf.data(), length);
InsertValueIntoBuffer(data, input,
(buffer_header_size + attribute_block_size +
(buffer_block_size * uniform_index))
.ValueOrDie());
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformBlocksCHROMIUM(
GLuint program,
std::vector<uint8_t>* data) {
GLuint service_program = 0;
if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
return error::kNoError;
}
GLint num_uniform_blocks = 0;
glGetProgramiv(service_program, GL_ACTIVE_UNIFORM_BLOCKS,
&num_uniform_blocks);
// Resize the data to fit the headers and info objects so that strings can be
// appended.
const base::CheckedNumeric<size_t> buffer_header_size(
sizeof(UniformBlocksHeader));
const base::CheckedNumeric<size_t> buffer_block_size(
sizeof(UniformBlockInfo));
data->resize((buffer_header_size + (num_uniform_blocks * buffer_block_size))
.ValueOrDie(),
0);
UniformBlocksHeader header;
header.num_uniform_blocks = num_uniform_blocks;
InsertValueIntoBuffer(data, header, 0);
GLint active_uniform_block_max_length = 0;
glGetProgramiv(service_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
&active_uniform_block_max_length);
std::vector<char> uniform_block_name_buf(active_uniform_block_max_length, 0);
for (GLint uniform_block_index = 0; uniform_block_index < num_uniform_blocks;
uniform_block_index++) {
UniformBlockInfo block_info;
GLint uniform_block_binding = 0;
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_BINDING, &uniform_block_binding);
block_info.binding = uniform_block_binding;
GLint uniform_block_data_size = 0;
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_DATA_SIZE,
&uniform_block_data_size);
block_info.data_size = uniform_block_data_size;
GLint uniform_block_name_length = 0;
glGetActiveUniformBlockName(
service_program, uniform_block_index, active_uniform_block_max_length,
&uniform_block_name_length, uniform_block_name_buf.data());
DCHECK(uniform_block_name_length + 1 <= active_uniform_block_max_length);
block_info.name_offset = data->size();
block_info.name_length = uniform_block_name_length + 1;
AppendStringToBuffer(data, uniform_block_name_buf.data(),
uniform_block_name_length + 1);
GLint uniform_block_active_uniforms = 0;
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
&uniform_block_active_uniforms);
block_info.active_uniforms = uniform_block_active_uniforms;
std::vector<GLint> uniform_block_indices_buf(uniform_block_active_uniforms,
0);
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
uniform_block_indices_buf.data());
block_info.active_uniform_offset = data->size();
for (GLint uniform_block_uniform_index_index = 0;
uniform_block_uniform_index_index < uniform_block_active_uniforms;
uniform_block_uniform_index_index++) {
AppendValueToBuffer(
data,
static_cast<uint32_t>(
uniform_block_indices_buf[uniform_block_uniform_index_index]));
}
GLint uniform_block_referenced_by_vertex_shader = 0;
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
&uniform_block_referenced_by_vertex_shader);
block_info.referenced_by_vertex_shader =
uniform_block_referenced_by_vertex_shader;
GLint uniform_block_referenced_by_fragment_shader = 0;
glGetActiveUniformBlockiv(service_program, uniform_block_index,
GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
&uniform_block_referenced_by_fragment_shader);
block_info.referenced_by_fragment_shader =
uniform_block_referenced_by_fragment_shader;
InsertValueIntoBuffer(
data, block_info,
(buffer_header_size + (buffer_block_size * uniform_block_index))
.ValueOrDie());
}
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoGetTransformFeedbackVaryingsCHROMIUM(
GLuint program,
std::vector<uint8_t>* data) {
GLuint service_program = 0;
if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
return error::kNoError;
}
GLint transform_feedback_buffer_mode = 0;
glGetProgramiv(service_program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE,
&transform_feedback_buffer_mode);
GLint num_transform_feedback_varyings = 0;
glGetProgramiv(service_program, GL_TRANSFORM_FEEDBACK_VARYINGS,
&num_transform_feedback_varyings);
// Resize the data to fit the headers and info objects so that strings can be
// appended.
const base::CheckedNumeric<size_t> buffer_header_size(
sizeof(TransformFeedbackVaryingsHeader));
const base::CheckedNumeric<size_t> buffer_block_size(
sizeof(TransformFeedbackVaryingInfo));
data->resize((buffer_header_size +
(num_transform_feedback_varyings * buffer_block_size))
.ValueOrDie(),
0);
TransformFeedbackVaryingsHeader header;
header.transform_feedback_buffer_mode = transform_feedback_buffer_mode;
header.num_transform_feedback_varyings = num_transform_feedback_varyings;
InsertValueIntoBuffer(data, header, 0);
GLint max_transform_feedback_varying_length = 0;
glGetProgramiv(service_program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
&max_transform_feedback_varying_length);
std::vector<char> transform_feedback_varying_name_buf(
max_transform_feedback_varying_length, 0);
for (GLint transform_feedback_varying_index = 0;
transform_feedback_varying_index < num_transform_feedback_varyings;
transform_feedback_varying_index++) {
GLsizei length = 0;
GLint size = 0;
GLenum type = GL_NONE;
glGetTransformFeedbackVarying(
service_program, transform_feedback_varying_index,
max_transform_feedback_varying_length, &length, &size, &type,
transform_feedback_varying_name_buf.data());
TransformFeedbackVaryingInfo varying_info;
varying_info.size = size;
varying_info.type = type;
DCHECK(length + 1 <= max_transform_feedback_varying_length);
varying_info.name_length = data->size();
varying_info.name_length = length + 1;
AppendStringToBuffer(data, transform_feedback_varying_name_buf.data(),
length + 1);
InsertValueIntoBuffer(
data, varying_info,
(buffer_header_size +
(buffer_block_size * transform_feedback_varying_index))
.ValueOrDie());
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetUniformsES3CHROMIUM(
GLuint program,
std::vector<uint8_t>* data) {
GLuint service_program = 0;
if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
return error::kNoError;
}
GLint num_uniforms = 0;
glGetProgramiv(service_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
UniformsES3Header header;
header.num_uniforms = num_uniforms;
AppendValueToBuffer(data, header);
for (GLuint uniform_index = 0;
uniform_index < static_cast<GLuint>(num_uniforms); uniform_index++) {
UniformES3Info uniform_info;
GLint uniform_block_index = 0;
glGetActiveUniformsiv(service_program, 1, &uniform_index,
GL_UNIFORM_BLOCK_INDEX, &uniform_block_index);
uniform_info.block_index = uniform_block_index;
GLint uniform_offset = 0;
glGetActiveUniformsiv(service_program, 1, &uniform_index, GL_UNIFORM_OFFSET,
&uniform_offset);
uniform_info.offset = uniform_offset;
GLint uniform_array_stride = 0;
glGetActiveUniformsiv(service_program, 1, &uniform_index,
GL_UNIFORM_ARRAY_STRIDE, &uniform_array_stride);
uniform_info.array_stride = uniform_array_stride;
GLint uniform_matrix_stride = 0;
glGetActiveUniformsiv(service_program, 1, &uniform_index,
GL_UNIFORM_MATRIX_STRIDE, &uniform_matrix_stride);
uniform_info.matrix_stride = uniform_matrix_stride;
GLint uniform_is_row_major = 0;
glGetActiveUniformsiv(service_program, 1, &uniform_index,
GL_UNIFORM_IS_ROW_MAJOR, &uniform_is_row_major);
uniform_info.is_row_major = uniform_is_row_major;
AppendValueToBuffer(data, uniform_info);
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetTranslatedShaderSourceANGLE(
GLuint shader,
std::string* source) {
FlushErrors();
GLuint service_id = GetShaderServiceID(shader, resources_);
GLint translated_source_length = 0;
glGetShaderiv(service_id, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
&translated_source_length);
if (FlushErrors()) {
return error::kNoError;
}
if (translated_source_length > 0) {
std::vector<char> buffer(translated_source_length, 0);
glGetTranslatedShaderSourceANGLE(service_id, translated_source_length,
nullptr, buffer.data());
*source = std::string(buffer.data());
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSwapBuffersWithBoundsCHROMIUM(
GLsizei count,
const volatile GLint* rects) {
if (count < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<gfx::Rect> bounds(count);
for (GLsizei i = 0; i < count; ++i) {
bounds[i] = gfx::Rect(rects[i * 4 + 0], rects[i * 4 + 1], rects[i * 4 + 2],
rects[i * 4 + 3]);
}
gfx::SwapResult result = surface_->SwapBuffersWithBounds(bounds);
if (result == gfx::SwapResult::SWAP_FAILED) {
LOG(ERROR) << "Context lost because SwapBuffersWithBounds failed.";
}
// TODO(geofflang): force the context loss?
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPostSubBufferCHROMIUM(
GLint x,
GLint y,
GLint width,
GLint height) {
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopyTextureCHROMIUM(
GLuint source_id,
GLint source_level,
GLenum dest_target,
GLuint dest_id,
GLint dest_level,
GLint internalformat,
GLenum dest_type,
GLboolean unpack_flip_y,
GLboolean unpack_premultiply_alpha,
GLboolean unpack_unmultiply_alpha) {
if (!feature_info_->feature_flags().chromium_copy_texture) {
return error::kUnknownCommand;
}
glCopyTextureCHROMIUM(GetTextureServiceID(source_id, resources_, false),
source_level, dest_target,
GetTextureServiceID(dest_id, resources_, false),
dest_level, internalformat, dest_type, unpack_flip_y,
unpack_premultiply_alpha, unpack_unmultiply_alpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCopySubTextureCHROMIUM(
GLuint source_id,
GLint source_level,
GLenum dest_target,
GLuint dest_id,
GLint dest_level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLboolean unpack_flip_y,
GLboolean unpack_premultiply_alpha,
GLboolean unpack_unmultiply_alpha) {
if (!feature_info_->feature_flags().chromium_copy_texture) {
return error::kUnknownCommand;
}
glCopySubTextureCHROMIUM(
GetTextureServiceID(source_id, resources_, false), source_level,
dest_target, GetTextureServiceID(dest_id, resources_, false), dest_level,
xoffset, yoffset, x, y, width, height, unpack_flip_y,
unpack_premultiply_alpha, unpack_unmultiply_alpha);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCompressedCopyTextureCHROMIUM(
GLuint source_id,
GLuint dest_id) {
if (!feature_info_->feature_flags().chromium_copy_compressed_texture) {
return error::kUnknownCommand;
}
glCompressedCopyTextureCHROMIUM(
GetTextureServiceID(source_id, resources_, false),
GetTextureServiceID(dest_id, resources_, false));
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDrawArraysInstancedANGLE(
GLenum mode,
GLint first,
GLsizei count,
GLsizei primcount) {
glDrawArraysInstancedANGLE(mode, first, count, primcount);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDrawElementsInstancedANGLE(
GLenum mode,
GLsizei count,
GLenum type,
const void* indices,
GLsizei primcount) {
glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoVertexAttribDivisorANGLE(
GLuint index,
GLuint divisor) {
glVertexAttribDivisorANGLE(index, divisor);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoProduceTextureCHROMIUM(
GLenum target,
const volatile GLbyte* mailbox) {
auto bound_textures_iter = bound_textures_.find(target);
if (bound_textures_iter == bound_textures_.end()) {
InsertError(GL_INVALID_OPERATION, "Invalid texture target.");
return error::kNoError;
}
GLuint texture_client_id = bound_textures_iter->second[active_texture_unit_];
auto texture_object_iter =
resources_->texture_object_map.find(texture_client_id);
if (texture_object_iter == resources_->texture_object_map.end()) {
InsertError(GL_INVALID_OPERATION, "Unknown texture for target.");
return error::kNoError;
}
const Mailbox& mb = Mailbox::FromVolatile(
*reinterpret_cast<const volatile Mailbox*>(mailbox));
mailbox_manager_->ProduceTexture(mb, texture_object_iter->second.get());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoProduceTextureDirectCHROMIUM(
GLuint texture_client_id,
GLenum target,
const volatile GLbyte* mailbox) {
auto texture_object_iter =
resources_->texture_object_map.find(texture_client_id);
if (texture_object_iter == resources_->texture_object_map.end()) {
InsertError(GL_INVALID_OPERATION, "Unknown texture for target.");
return error::kNoError;
}
scoped_refptr<TexturePassthrough> texture = texture_object_iter->second;
if (texture->target() != target) {
InsertError(GL_INVALID_OPERATION, "Texture target does not match.");
return error::kNoError;
}
const Mailbox& mb = Mailbox::FromVolatile(
*reinterpret_cast<const volatile Mailbox*>(mailbox));
mailbox_manager_->ProduceTexture(mb, texture.get());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoConsumeTextureCHROMIUM(
GLenum target,
const volatile GLbyte* mailbox) {
auto bound_textures_iter = bound_textures_.find(target);
if (bound_textures_iter == bound_textures_.end()) {
InsertError(GL_INVALID_OPERATION, "Invalid texture target.");
return error::kNoError;
}
GLuint client_id = bound_textures_iter->second[active_texture_unit_];
if (client_id == 0) {
InsertError(GL_INVALID_OPERATION, "Unknown texture for target.");
return error::kNoError;
}
const Mailbox& mb = Mailbox::FromVolatile(
*reinterpret_cast<const volatile Mailbox*>(mailbox));
scoped_refptr<TexturePassthrough> texture = static_cast<TexturePassthrough*>(
group_->mailbox_manager()->ConsumeTexture(mb));
if (texture == nullptr) {
InsertError(GL_INVALID_OPERATION, "Invalid mailbox name.");
return error::kNoError;
}
if (texture->target() != target) {
InsertError(GL_INVALID_OPERATION, "Texture target does not match.");
return error::kNoError;
}
// Update id mappings
resources_->texture_id_map.RemoveClientID(client_id);
resources_->texture_id_map.SetIDMapping(client_id, texture->service_id());
resources_->texture_object_map.erase(client_id);
resources_->texture_object_map.insert(std::make_pair(client_id, texture));
// Bind the service id that now represents this texture
UpdateTextureBinding(target, client_id, texture->service_id());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCreateAndConsumeTextureINTERNAL(
GLenum target,
GLuint texture_client_id,
const volatile GLbyte* mailbox) {
if (resources_->texture_id_map.GetServiceID(texture_client_id, nullptr)) {
return error::kInvalidArguments;
}
const Mailbox& mb = Mailbox::FromVolatile(
*reinterpret_cast<const volatile Mailbox*>(mailbox));
scoped_refptr<TexturePassthrough> texture = static_cast<TexturePassthrough*>(
group_->mailbox_manager()->ConsumeTexture(mb));
if (texture == nullptr) {
InsertError(GL_INVALID_OPERATION, "Invalid mailbox name.");
return error::kNoError;
}
if (texture->target() != target) {
InsertError(GL_INVALID_OPERATION, "Texture target does not match.");
return error::kNoError;
}
// Update id mappings
resources_->texture_id_map.RemoveClientID(texture_client_id);
resources_->texture_id_map.SetIDMapping(texture_client_id,
texture->service_id());
resources_->texture_object_map.erase(texture_client_id);
resources_->texture_object_map.insert(
std::make_pair(texture_client_id, texture));
// Bind the service id that now represents this texture
UpdateTextureBinding(target, texture_client_id, texture->service_id());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindUniformLocationCHROMIUM(
GLuint program,
GLint location,
const char* name) {
glBindUniformLocationCHROMIUM(GetProgramServiceID(program, resources_),
location, name);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindTexImage2DCHROMIUM(
GLenum target,
GLint imageId) {
return BindTexImage2DCHROMIUMImpl(target, 0, imageId);
}
error::Error
GLES2DecoderPassthroughImpl::DoBindTexImage2DWithInternalformatCHROMIUM(
GLenum target,
GLenum internalformat,
GLint imageId) {
return BindTexImage2DCHROMIUMImpl(target, internalformat, imageId);
}
error::Error GLES2DecoderPassthroughImpl::DoReleaseTexImage2DCHROMIUM(
GLenum target,
GLint imageId) {
if (target != GL_TEXTURE_2D) {
InsertError(GL_INVALID_ENUM, "Invalid target");
return error::kNoError;
}
gl::GLImage* image = image_manager_->LookupImage(imageId);
if (image == nullptr) {
InsertError(GL_INVALID_OPERATION, "No image found with the given ID");
return error::kNoError;
}
image->ReleaseTexImage(target);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTraceBeginCHROMIUM(
const char* category_name,
const char* trace_name) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoTraceEndCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDiscardFramebufferEXT(
GLenum target,
GLsizei count,
const volatile GLenum* attachments) {
if (!feature_info_->feature_flags().ext_discard_framebuffer) {
return error::kUnknownCommand;
}
// Validate that count is non-negative before allocating a vector
if (count < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<GLenum> attachments_copy(attachments, attachments + count);
if (feature_info_->gl_version_info().is_es3) {
glInvalidateFramebuffer(target, count, attachments_copy.data());
} else {
glDiscardFramebufferEXT(target, count, attachments_copy.data());
}
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoLoseContextCHROMIUM(GLenum current,
GLenum other) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDescheduleUntilFinishedCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoInsertFenceSyncCHROMIUM(
GLuint64 release_count) {
if (!fence_sync_release_callback_.is_null())
fence_sync_release_callback_.Run(release_count);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoWaitSyncTokenCHROMIUM(
CommandBufferNamespace namespace_id,
CommandBufferId command_buffer_id,
GLuint64 release_count) {
if (wait_sync_token_callback_.is_null()) {
return error::kNoError;
}
SyncToken sync_token(namespace_id, 0, command_buffer_id, release_count);
return wait_sync_token_callback_.Run(sync_token)
? error::kDeferCommandUntilLater
: error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDrawBuffersEXT(
GLsizei count,
const volatile GLenum* bufs) {
// Validate that count is non-negative before allocating a vector
if (count < 0) {
InsertError(GL_INVALID_VALUE, "count cannot be negative.");
return error::kNoError;
}
std::vector<GLenum> bufs_copy(bufs, bufs + count);
glDrawBuffersARB(count, bufs_copy.data());
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDiscardBackbufferCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleOverlayPlaneCHROMIUM(
GLint plane_z_order,
GLenum plane_transform,
GLuint overlay_texture_id,
GLint bounds_x,
GLint bounds_y,
GLint bounds_width,
GLint bounds_height,
GLfloat uv_x,
GLfloat uv_y,
GLfloat uv_width,
GLfloat uv_height) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerSharedStateCHROMIUM(
GLfloat opacity,
GLboolean is_clipped,
const GLfloat* clip_rect,
GLint sorting_context_id,
const GLfloat* transform) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerCHROMIUM(
GLuint contents_texture_id,
const GLfloat* contents_rect,
GLuint background_color,
GLuint edge_aa_mask,
const GLfloat* bounds_rect) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerInUseQueryCHROMIUM(
GLuint n,
const volatile GLuint* textures) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleDCLayerSharedStateCHROMIUM(
GLfloat opacity,
GLboolean is_clipped,
const GLfloat* clip_rect,
GLint z_order,
const GLfloat* transform) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoScheduleDCLayerCHROMIUM(
GLsizei num_textures,
const volatile GLuint* contents_texture_ids,
const GLfloat* contents_rect,
GLuint background_color,
GLuint edge_aa_mask,
const GLfloat* bounds_rect) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCommitOverlayPlanesCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSwapInterval(GLint interval) {
context_->SetSwapInterval(interval);
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoFlushDriverCachesCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoMatrixLoadfCHROMIUM(
GLenum matrixMode,
const volatile GLfloat* m) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoMatrixLoadIdentityCHROMIUM(
GLenum matrixMode) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGenPathsCHROMIUM(GLuint path,
GLsizei range) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoDeletePathsCHROMIUM(GLuint path,
GLsizei range) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoIsPathCHROMIUM(GLuint path,
uint32_t* result) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPathCommandsCHROMIUM(
GLuint path,
GLsizei numCommands,
const GLubyte* commands,
GLsizei numCoords,
GLenum coordType,
const GLvoid* coords,
GLsizei coords_bufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPathParameterfCHROMIUM(
GLuint path,
GLenum pname,
GLfloat value) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPathParameteriCHROMIUM(
GLuint path,
GLenum pname,
GLint value) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoPathStencilFuncCHROMIUM(
GLenum func,
GLint ref,
GLuint mask) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilFillPathCHROMIUM(
GLuint path,
GLenum fillMode,
GLuint mask) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilStrokePathCHROMIUM(
GLuint path,
GLint reference,
GLuint mask) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCoverFillPathCHROMIUM(
GLuint path,
GLenum coverMode) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCoverStrokePathCHROMIUM(
GLuint path,
GLenum coverMode) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilThenCoverFillPathCHROMIUM(
GLuint path,
GLenum fillMode,
GLuint mask,
GLenum coverMode) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilThenCoverStrokePathCHROMIUM(
GLuint path,
GLint reference,
GLuint mask,
GLenum coverMode) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilFillPathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLenum fillMode,
GLuint mask,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoStencilStrokePathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLint reference,
GLuint mask,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCoverFillPathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCoverStrokePathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoStencilThenCoverFillPathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLenum fillMode,
GLuint mask,
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoStencilThenCoverStrokePathInstancedCHROMIUM(
GLsizei numPaths,
GLenum pathNameType,
const GLvoid* paths,
GLsizei pathsBufsize,
GLuint pathBase,
GLint reference,
GLuint mask,
GLenum coverMode,
GLenum transformType,
const GLfloat* transformValues,
GLsizei transformValuesBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindFragmentInputLocationCHROMIUM(
GLuint program,
GLint location,
const char* name) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoProgramPathFragmentInputGenCHROMIUM(
GLuint program,
GLint location,
GLenum genMode,
GLint components,
const GLfloat* coeffs,
GLsizei coeffsBufsize) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoCoverageModulationCHROMIUM(
GLenum components) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBlendBarrierKHR() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindFragDataLocationIndexedEXT(
GLuint program,
GLuint colorNumber,
GLuint index,
const char* name) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoBindFragDataLocationEXT(
GLuint program,
GLuint colorNumber,
const char* name) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoGetFragDataIndexEXT(
GLuint program,
const char* name,
GLint* index) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error
GLES2DecoderPassthroughImpl::DoUniformMatrix4fvStreamTextureMatrixCHROMIUM(
GLint location,
GLboolean transpose,
const volatile GLfloat* defaultValue) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoOverlayPromotionHintCHROMIUM(
GLuint texture,
GLboolean promotion_hint,
GLint display_x,
GLint display_y) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSetDrawRectangleCHROMIUM(
GLint x,
GLint y,
GLint width,
GLint height) {
NOTIMPLEMENTED();
return error::kNoError;
}
error::Error GLES2DecoderPassthroughImpl::DoSetEnableDCLayersCHROMIUM(
GLboolean enable) {
NOTIMPLEMENTED();
return error::kNoError;
}
} // namespace gles2
} // namespace gpu