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. |