| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| index 9c66e44063e2a2849da6a897fae1e267ec7570c7..8c800ead17bd76007f115e66ca7b23a8074f7492 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -51,6 +51,7 @@
|
| #include "gpu/command_buffer/service/image_manager.h"
|
| #include "gpu/command_buffer/service/mailbox_manager.h"
|
| #include "gpu/command_buffer/service/memory_tracking.h"
|
| +#include "gpu/command_buffer/service/path_manager.h"
|
| #include "gpu/command_buffer/service/program_manager.h"
|
| #include "gpu/command_buffer/service/query_manager.h"
|
| #include "gpu/command_buffer/service/renderbuffer_manager.h"
|
| @@ -789,6 +790,8 @@ class GLES2DecoderImpl : public GLES2Decoder,
|
| void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
|
| bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
|
| void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
|
| + bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
|
| + bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
|
|
|
| // Helper for async upload token completion notification callback.
|
| base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
|
| @@ -821,6 +824,8 @@ class GLES2DecoderImpl : public GLES2Decoder,
|
| return group_->valuebuffer_manager();
|
| }
|
|
|
| + PathManager* path_manager() { return group_->path_manager(); }
|
| +
|
| ProgramManager* program_manager() {
|
| return group_->program_manager();
|
| }
|
| @@ -1551,6 +1556,7 @@ class GLES2DecoderImpl : public GLES2Decoder,
|
| bool DoIsShader(GLuint client_id);
|
| bool DoIsTexture(GLuint client_id);
|
| bool DoIsVertexArrayOES(GLuint client_id);
|
| + bool DoIsPathCHROMIUM(GLuint client_id);
|
|
|
| // Wrapper for glLinkProgram
|
| void DoLinkProgram(GLuint program);
|
| @@ -3328,6 +3334,44 @@ bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
|
| return true;
|
| }
|
|
|
| +bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
|
| + GLsizei range) {
|
| + GLuint last_client_id;
|
| + if (!SafeAddUint32(first_client_id, range - 1, &last_client_id)) {
|
| + return false;
|
| + }
|
| +
|
| + if (path_manager()->HasPathsInRange(first_client_id, last_client_id)) {
|
| + return false;
|
| + }
|
| +
|
| + GLuint first_service_id = glGenPathsNV(range);
|
| + if (first_service_id == 0) {
|
| + // We have to fail the connection here, because client has already
|
| + // succeeded in allocating the ids. This happens if we allocate
|
| + // the whole path id space (two allocations of 0x7FFFFFFF paths, for
|
| + // example). Currently so many allocations hang the client-side
|
| + // id allocator, so this should not be a practical issue.
|
| + return false;
|
| + }
|
| +
|
| + path_manager()->CreatePathRange(first_client_id, last_client_id,
|
| + first_service_id);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
|
| + GLsizei range) {
|
| + GLuint last_client_id;
|
| + if (!SafeAddUint32(first_client_id, range - 1, &last_client_id)) {
|
| + return false;
|
| + }
|
| +
|
| + path_manager()->RemovePaths(first_client_id, last_client_id);
|
| + return true;
|
| +}
|
| +
|
| void GLES2DecoderImpl::DeleteBuffersHelper(
|
| GLsizei n, const GLuint* client_ids) {
|
| for (GLsizei ii = 0; ii < n; ++ii) {
|
| @@ -11719,6 +11763,15 @@ bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
|
| return vao && vao->IsValid() && !vao->IsDeleted();
|
| }
|
|
|
| +bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(client_id, &service_id)) {
|
| + return false;
|
| + }
|
| +
|
| + return glIsPathNV(service_id);
|
| +}
|
| +
|
| #if defined(OS_MACOSX)
|
| void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
|
| TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
|
| @@ -13426,6 +13479,477 @@ void GLES2DecoderImpl::OnOutOfMemoryError() {
|
| }
|
| }
|
|
|
| +error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::GenPathsCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGenPathsCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLsizei range = static_cast<GLsizei>(c.range);
|
| + if (range < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glGenPathsCHROMIUM", "range < 0");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
|
| + if (first_client_id == 0) {
|
| + return error::kInvalidArguments;
|
| + }
|
| +
|
| + if (range == 0) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + if (!GenPathsCHROMIUMHelper(first_client_id, range)) {
|
| + return error::kInvalidArguments;
|
| + }
|
| +
|
| + return error::kNoError;
|
| +}
|
| +error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
|
| + uint32_t immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::DeletePathsCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGenPathsCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLsizei range = static_cast<GLsizei>(c.range);
|
| + if (range < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeletePathsCHROMIUM", "range < 0");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + if (range == 0) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLuint first_client_id = c.first_client_id;
|
| + // first_client_id can be 0, because non-existing path ids are skipped.
|
| +
|
| + if (!DeletePathsCHROMIUMHelper(first_client_id, range)) {
|
| + return error::kInvalidArguments;
|
| + }
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::PathCommandsCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathCommandsCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathCommandsCHROMIUM",
|
| + "invalid path name");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
|
| + if (num_commands < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glPathCommandsCHROMIUM",
|
| + "numCommands < 0");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLsizei num_coords = static_cast<uint32>(c.numCoords);
|
| + if (num_coords < 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glPathCommandsCHROMIUM",
|
| + "numCoords < 0");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLenum coord_type = static_cast<uint32>(c.coordType);
|
| + uint32 coord_type_size = GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
|
| + if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type)) ||
|
| + coord_type_size == 0) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, "glPathCommandsCHROMIUM",
|
| + "invalid coordType");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + uint32 coords_size = 0;
|
| + if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size)) {
|
| + return error::kOutOfBounds;
|
| + }
|
| +
|
| + uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
|
| + uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
|
| +
|
| + const GLubyte* commands = NULL;
|
| + if (commands_shm_id != 0 || commands_shm_offset != 0) {
|
| + commands = GetSharedMemoryAs<const GLubyte*>(
|
| + commands_shm_id, commands_shm_offset, num_commands);
|
| + if (!commands) {
|
| + return error::kOutOfBounds;
|
| + }
|
| + }
|
| +
|
| + if (num_commands && !commands) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathCommandsCHROMIUM",
|
| + "missing commands");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLsizei num_coords_expected = 0;
|
| + for (GLsizei i = 0; i < num_commands; ++i) {
|
| + switch (commands[i]) {
|
| + case GL_CLOSE_PATH_CHROMIUM:
|
| + // Close has no coords.
|
| + break;
|
| + case GL_MOVE_TO_CHROMIUM:
|
| + // Fallthrough.
|
| + case GL_LINE_TO_CHROMIUM:
|
| + num_coords_expected += 2;
|
| + break;
|
| + case GL_QUADRATIC_CURVE_TO_CHROMIUM:
|
| + num_coords_expected += 4;
|
| + break;
|
| + case GL_CUBIC_CURVE_TO_CHROMIUM:
|
| + num_coords_expected += 6;
|
| + break;
|
| + case GL_CONIC_CURVE_TO_CHROMIUM:
|
| + num_coords_expected += 5;
|
| + break;
|
| + default:
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, "glPathCommandsCHROMIUM",
|
| + "invalid command");
|
| + return error::kNoError;
|
| + }
|
| + }
|
| +
|
| + if (num_coords != num_coords_expected) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathCommandsCHROMIUM",
|
| + "numCoords does not match commands");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
|
| + uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
|
| +
|
| + const void* coords = NULL;
|
| + if (coords_shm_id != 0 || coords_shm_offset != 0) {
|
| + coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
|
| + coords_size);
|
| + if (!coords) {
|
| + return error::kOutOfBounds;
|
| + }
|
| + }
|
| +
|
| + if (num_coords && !coords) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathCommandsCHROMIUM",
|
| + "missing coords");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
|
| + coords);
|
| +
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::PathParameterfCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathParameterfCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathParameterfCHROMIUM",
|
| + "invalid path name");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLenum pname = static_cast<GLenum>(c.pname);
|
| + GLfloat value = static_cast<GLfloat>(c.value);
|
| + bool hasValueError = false;
|
| +
|
| + switch (pname) {
|
| + case GL_PATH_STROKE_WIDTH_CHROMIUM:
|
| + case GL_PATH_MITER_LIMIT_CHROMIUM:
|
| + hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
|
| + break;
|
| + case GL_PATH_STROKE_BOUND_CHROMIUM:
|
| + value = std::max(std::min(1.0f, value), 0.0f);
|
| + break;
|
| + case GL_PATH_END_CAPS_CHROMIUM:
|
| + hasValueError = !validators_->path_parameter_cap_values.IsValid(
|
| + static_cast<GLint>(value));
|
| + break;
|
| + case GL_PATH_JOIN_STYLE_CHROMIUM:
|
| + hasValueError = !validators_->path_parameter_join_values.IsValid(
|
| + static_cast<GLint>(value));
|
| + break;
|
| + default:
|
| + DCHECK(!validators_->path_parameter.IsValid(pname));
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glPathParameterfCHROMIUM", pname,
|
| + "pname");
|
| + return error::kNoError;
|
| + }
|
| + DCHECK(validators_->path_parameter.IsValid(pname));
|
| +
|
| + if (hasValueError) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glPathParameterfCHROMIUM",
|
| + "value not correct");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + glPathParameterfNV(service_id, pname, value);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::PathParameteriCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathParameteriCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPathParameteriCHROMIUM",
|
| + "invalid path name");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLenum pname = static_cast<GLenum>(c.pname);
|
| + GLint value = static_cast<GLint>(c.value);
|
| + bool hasValueError = false;
|
| +
|
| + switch (pname) {
|
| + case GL_PATH_STROKE_WIDTH_CHROMIUM:
|
| + case GL_PATH_MITER_LIMIT_CHROMIUM:
|
| + hasValueError = value < 0;
|
| + break;
|
| + case GL_PATH_STROKE_BOUND_CHROMIUM:
|
| + value = std::max(std::min(1, value), 0);
|
| + break;
|
| + case GL_PATH_END_CAPS_CHROMIUM:
|
| + hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
|
| + break;
|
| + case GL_PATH_JOIN_STYLE_CHROMIUM:
|
| + hasValueError = !validators_->path_parameter_join_values.IsValid(value);
|
| + break;
|
| + default:
|
| + DCHECK(!validators_->path_parameter.IsValid(pname));
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glPathParameteriCHROMIUM", pname,
|
| + "pname");
|
| + return error::kNoError;
|
| + }
|
| + DCHECK(validators_->path_parameter.IsValid(pname));
|
| +
|
| + if (hasValueError) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glPathParameteriCHROMIUM",
|
| + "value not correct");
|
| + return error::kNoError;
|
| + }
|
| +
|
| + glPathParameteriNV(service_id, pname, value);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::StencilFillPathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glStencilFillPathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLenum fill_mode = static_cast<GLenum>(c.fillMode);
|
| + if (!validators_->path_fill_mode.IsValid(fill_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glStencilFillPathCHROMIUM", fill_mode,
|
| + "fillMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint mask = static_cast<GLuint>(c.mask);
|
| + if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
|
| + fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
|
| + GLES2Util::IsNPOT(mask + 1)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glStencilFillPathCHROMIUM",
|
| + "mask is not power of two");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + // "If /path/ does not name an existing path object, the command does
|
| + // nothing (and no error is generated)."
|
| + // This holds for other rendering functions, too.
|
| + return error::kNoError;
|
| + }
|
| + ApplyDirtyState();
|
| + glStencilFillPathNV(service_id, fill_mode, mask);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::StencilStrokePathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glStencilStrokePathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + return error::kNoError;
|
| + }
|
| + GLint reference = static_cast<GLint>(c.reference);
|
| + GLuint mask = static_cast<GLuint>(c.mask);
|
| + ApplyDirtyState();
|
| + glStencilStrokePathNV(service_id, reference, mask);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::CoverFillPathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCoverFillPathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode);
|
| + if (!validators_->path_cover_mode.IsValid(cover_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCoverFillPathCHROMIUM", cover_mode,
|
| + "coverMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + ApplyDirtyState();
|
| + glCoverFillPathNV(service_id, cover_mode);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::CoverStrokePathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCoverStrokePathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode);
|
| + if (!validators_->path_cover_mode.IsValid(cover_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glCoverStrokePathCHROMIUM", cover_mode,
|
| + "coverMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + ApplyDirtyState();
|
| + glCoverStrokePathNV(service_id, cover_mode);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
|
| + cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
|
| + "glStencilThenCoverFillPathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLenum fill_mode = static_cast<GLenum>(c.fillMode);
|
| + if (!validators_->path_fill_mode.IsValid(fill_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glStencilThenCoverFillPathCHROMIUM",
|
| + fill_mode, "fillMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint mask = static_cast<GLuint>(c.mask);
|
| + if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
|
| + fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
|
| + GLES2Util::IsNPOT(mask + 1)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glStencilThenCoverFillPathCHROMIUM",
|
| + "mask is not power of two");
|
| + return error::kNoError;
|
| + }
|
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode);
|
| + if (!validators_->path_cover_mode.IsValid(cover_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glStencilThenCoverFillPathCHROMIUM",
|
| + cover_mode, "coverMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + return error::kNoError;
|
| + }
|
| + ApplyDirtyState();
|
| + glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
|
| + uint32 immediate_data_size,
|
| + const void* cmd_data) {
|
| + const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
|
| + *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
|
| + cmd_data);
|
| + if (!features().chromium_path_rendering) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
|
| + "glStencilThenCoverStrokePathCHROMIUM",
|
| + "function not available");
|
| + return error::kNoError;
|
| + }
|
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode);
|
| + if (!validators_->path_cover_mode.IsValid(cover_mode)) {
|
| + LOCAL_SET_GL_ERROR_INVALID_ENUM("glStencilThenCoverStrokePathCHROMIUM",
|
| + cover_mode, "coverMode");
|
| + return error::kNoError;
|
| + }
|
| + GLuint service_id = 0;
|
| + if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
|
| + return error::kNoError;
|
| + }
|
| +
|
| + GLint reference = static_cast<GLint>(c.reference);
|
| + GLuint mask = static_cast<GLuint>(c.mask);
|
| + ApplyDirtyState();
|
| + glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
|
| + return error::kNoError;
|
| +}
|
| +
|
| // Include the auto-generated part of this file. We split this because it means
|
| // we can easily edit the non-auto generated parts right here in this file
|
| // instead of having to edit some template or the code generator.
|
|
|