Chromium Code Reviews| 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 8574d5fca57e1ee2900d1fa12f8b5098776b4c3a..a0804c4291cb3188e4e6bda2c60a8060e8a83916 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -217,6 +217,16 @@ bool CombineAdjacentRects(const gfx::Rect& rect1, |
| return false; |
| } |
| +bool IsValidPathCommandMask(GLenum fill_mode, GLuint mask) { |
| + /* The error INVALID_VALUE |
| + is generated if /fillMode/ is COUNT_UP_CHROMIUM or COUNT_DOWN_CHROMIUM and |
| + the effective /mask/+1 is not an integer power of two |
| + */ |
| + return (fill_mode != GL_COUNT_UP_CHROMIUM && |
| + fill_mode != GL_COUNT_DOWN_CHROMIUM) || |
| + !GLES2Util::IsNPOT(mask + 1); |
|
Zhenyao Mo
2015/10/06 22:51:01
overflow check for mask + 1
Kimmo Kinnunen
2015/10/08 09:28:29
While not terribly useful, I think overflow is int
|
| +} |
| + |
| } // namespace |
| class GLES2DecoderImpl; |
| @@ -1913,6 +1923,31 @@ class GLES2DecoderImpl : public GLES2Decoder, |
| void ProcessPendingReadPixels(bool did_finish); |
| void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer); |
| + bool PrepareInstancedPathCommand(GLsizei num_paths, |
| + GLenum path_name_type, |
| + uint32 paths_shm_id, |
| + uint32 paths_shm_offset, |
| + GLuint path_base, |
| + GLenum transform_type, |
| + uint32 transforms_shm_id, |
| + uint32 transforms_shm_offset, |
| + error::Error* out_error, |
| + GLuint** out_paths, |
| + const GLfloat** out_transforms, |
| + scoped_ptr<GLuint[]>* out_temp_path_buffer); |
| + template <typename T> |
| + bool PrepareInstancedPathCommand(GLsizei num_paths, |
| + uint32 paths_shm_id, |
| + uint32 paths_shm_offset, |
| + GLuint path_base, |
| + GLenum transform_type, |
| + uint32 transforms_shm_id, |
| + uint32 transforms_shm_offset, |
| + error::Error* out_error, |
| + GLuint** out_paths, |
| + const GLfloat** out_transforms, |
| + scoped_ptr<GLuint[]>* out_temp_path_buffer); |
| + |
| // Generate a member function prototype for each command in an automated and |
| // typesafe way. |
| #define GLES2_CMD_OP(name) \ |
| @@ -14901,9 +14936,7 @@ error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM( |
| 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)) { |
| + if (!IsValidPathCommandMask(fill_mode, mask)) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| "mask + 1 is not power of two"); |
| return error::kNoError; |
| @@ -15010,9 +15043,7 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM( |
| 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)) { |
| + if (!IsValidPathCommandMask(fill_mode, mask)) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| "mask + 1 is not power of two"); |
| return error::kNoError; |
| @@ -15059,6 +15090,572 @@ error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM( |
| return error::kNoError; |
| } |
| +bool GLES2DecoderImpl::PrepareInstancedPathCommand( |
| + GLsizei num_paths, |
| + GLenum path_name_type, |
| + uint32 paths_shm_id, |
| + uint32 paths_shm_offset, |
| + GLuint path_base, |
| + GLenum transform_type, |
| + uint32 transforms_shm_id, |
| + uint32 transforms_shm_offset, |
| + error::Error* out_error, |
| + GLuint** out_paths, |
| + const GLfloat** out_transforms, |
| + scoped_ptr<GLuint[]>* out_temp_path_buffer) { |
| + if (path_name_type == GL_BYTE) { |
|
Zhenyao Mo
2015/10/06 22:51:00
A switch (path_name_type) is much cleaner here.
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLbyte>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } else if (path_name_type == GL_UNSIGNED_BYTE) { |
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLubyte>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } else if (path_name_type == GL_SHORT) { |
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLshort>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } else if (path_name_type == GL_UNSIGNED_SHORT) { |
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLushort>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } else if (path_name_type == GL_INT) { |
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLint>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } else if (path_name_type == GL_UNSIGNED_INT) { |
| + DCHECK(validators_->path_name_type.IsValid(path_name_type)); |
| + return PrepareInstancedPathCommand<GLuint>( |
| + num_paths, paths_shm_id, paths_shm_offset, path_base, transform_type, |
| + transforms_shm_id, transforms_shm_offset, out_error, out_paths, |
| + out_transforms, out_temp_path_buffer); |
| + } |
| + |
| + DCHECK(!validators_->path_name_type.IsValid(path_name_type)); |
| + NOTREACHED(); |
| + |
| + *out_error = error::kOutOfBounds; |
| + return false; |
| +} |
| + |
| +template <typename T> |
| +bool GLES2DecoderImpl::PrepareInstancedPathCommand( |
| + GLsizei num_paths, |
| + uint32 paths_shm_id, |
| + uint32 paths_shm_offset, |
| + GLuint path_base, |
| + GLenum transform_type, |
| + uint32 transforms_shm_id, |
| + uint32 transforms_shm_offset, |
| + error::Error* out_error, |
| + GLuint** out_paths, |
| + const GLfloat** out_transforms, |
| + scoped_ptr<GLuint[]>* out_temp_path_buffer) { |
| + if (num_paths == 0) { |
| + // No GL error, just nothing to do. |
| + *out_error = error::kNoError; |
| + return false; |
| + } |
| + uint32 paths_size = 0; |
| + if (!SafeMultiplyUint32(num_paths, sizeof(T), &paths_size)) { |
| + *out_error = error::kOutOfBounds; |
| + return false; |
| + } |
| + |
| + T* paths = NULL; |
|
Zhenyao Mo
2015/10/06 22:51:00
const T*
Kimmo Kinnunen
2015/10/08 09:28:29
Still left this as is, see below. (The optimizatio
|
| + if (paths_shm_id != 0 || paths_shm_offset != 0) |
| + paths = GetSharedMemoryAs<T*>(paths_shm_id, paths_shm_offset, paths_size); |
| + |
| + if (!paths) { |
| + *out_error = error::kOutOfBounds; |
| + return false; |
| + } |
| + |
| + const GLfloat* transforms = NULL; |
| + |
| + if (transform_type != GL_NONE) { |
| + uint32 transforms_component_count = |
| + GLES2Util::GetComponentCountForGLTransformType(transform_type); |
| + // Below multiplication will not overflow. |
| + DCHECK(transforms_component_count <= 12); |
| + uint32 one_transform_size = sizeof(GLfloat) * transforms_component_count; |
| + |
| + uint32 transforms_size = 0; |
| + if (!SafeMultiplyUint32(one_transform_size, num_paths, &transforms_size)) { |
| + *out_error = error::kOutOfBounds; |
| + return false; |
| + } |
| + if (transforms_shm_id != 0 || transforms_shm_offset != 0) |
| + transforms = GetSharedMemoryAs<const GLfloat*>( |
| + transforms_shm_id, transforms_shm_offset, transforms_size); |
| + |
| + if (!transforms) { |
| + *out_error = error::kOutOfBounds; |
| + return false; |
| + } |
| + } |
| + |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + GLuint* result_paths; |
| + if (sizeof(T) == sizeof(GLuint)) { |
|
Zhenyao Mo
2015/10/06 22:51:00
I think this optimization is unnecessary and makes
Kimmo Kinnunen
2015/10/08 09:28:28
I tried to make this less ugly. If it is still ugl
|
| + result_paths = reinterpret_cast<GLuint*>(paths); |
| + } else { |
| + result_paths = new GLuint[num_paths]; |
| + temp_path_buffer.reset(result_paths); |
| + } |
| + bool has_paths = false; |
| + for (GLsizei i = 0; i < num_paths; ++i) { |
| + GLuint service_id = 0; |
| + uint32 client_id = 0; |
| + if (!SafeAddUint32(paths[i], path_base, &client_id)) { |
| + *out_error = error::kOutOfBounds; |
|
Zhenyao Mo
2015/10/06 22:51:01
This is incorrect. You should generate an INVALID
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + return false; |
| + } |
| + |
| + if (path_manager()->GetPath(client_id, &service_id)) |
| + has_paths = true; |
| + |
| + // Will use path 0 if the path is not found. This is in line |
| + // of the spec: missing paths will produce nothing, let |
| + // the instanced draw continue. |
| + result_paths[i] = service_id; |
| + } |
| + |
| + if (!has_paths) { |
| + *out_error = error::kNoError; |
| + return false; |
| + } |
| + *out_error = error::kNoError; |
| + *out_paths = result_paths; |
| + *out_transforms = transforms; |
| + out_temp_path_buffer->swap(temp_path_buffer); |
| + return true; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleStencilFillPathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = "glStencilFillPathInstancedCHROMIUM"; |
| + const gles2::cmds::StencilFillPathInstancedCHROMIUM& c = |
| + *static_cast<const gles2::cmds::StencilFillPathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:01
no GL error, but return error::kUnknownCommand ins
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
|
Zhenyao Mo
2015/10/06 22:51:00
It looks to me that the validation of num_paths, p
Kimmo Kinnunen
2015/10/08 09:28:28
The order of the error checking is significant.
I
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + 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(kFunctionName, fill_mode, "fillMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint mask = static_cast<GLuint>(c.mask); |
| + if (!IsValidPathCommandMask(fill_mode, mask)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| + "mask+1 is not power of two"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glStencilFillPathInstancedNV(num_paths, path_name_type, paths, 0, fill_mode, |
|
Zhenyao Mo
2015/10/06 22:51:01
Should you always use GL_UNSIGNED_INT here as the
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + mask, transform_type, transforms); |
| + |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleStencilStrokePathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = "glStencilStrokePathInstancedCHROMIUM"; |
| + const gles2::cmds::StencilStrokePathInstancedCHROMIUM& c = |
| + *static_cast<const gles2::cmds::StencilStrokePathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:01
Same here, no GL error, but return error::kUnknown
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + GLuint ref = static_cast<GLuint>(c.reference); |
|
Zhenyao Mo
2015/10/06 22:51:00
In the spec, reference is defined as GLint, not GL
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + GLuint mask = static_cast<GLuint>(c.mask); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glStencilStrokePathInstancedNV(num_paths, path_name_type, paths, 0, ref, mask, |
| + transform_type, transforms); |
| + |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleCoverFillPathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = "glCoverFillPathInstancedCHROMIUM"; |
| + const gles2::cmds::CoverFillPathInstancedCHROMIUM& c = |
| + *static_cast<const gles2::cmds::CoverFillPathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:01
Same here, no GL error, but return error::kUnknown
Kimmo Kinnunen
2015/10/08 09:28:28
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum cover_mode = static_cast<GLuint>(c.coverMode); |
| + if (!validators_->path_instanced_cover_mode.IsValid(cover_mode)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glCoverFillPathInstancedNV(num_paths, path_name_type, paths, 0, cover_mode, |
| + transform_type, transforms); |
| + |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleCoverStrokePathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = "glCoverStrokePathInstancedCHROMIUM"; |
| + const gles2::cmds::CoverStrokePathInstancedCHROMIUM& c = |
| + *static_cast<const gles2::cmds::CoverStrokePathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:01
Same here, no GL error, but return error::kUnknown
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode); |
| + if (!validators_->path_instanced_cover_mode.IsValid(cover_mode)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glCoverStrokePathInstancedNV(num_paths, path_name_type, paths, 0, cover_mode, |
| + transform_type, transforms); |
| + |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = |
| + "glStencilThenCoverFillPathInstancedCHROMIUM"; |
| + const gles2::cmds::StencilThenCoverFillPathInstancedCHROMIUM& c = |
| + *static_cast< |
| + const gles2::cmds::StencilThenCoverFillPathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:01
Same here, no GL error, but return error::kUnknown
Kimmo Kinnunen
2015/10/08 09:28:28
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + 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(kFunctionName, fill_mode, "fillMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint mask = static_cast<GLuint>(c.mask); |
| + if (!IsValidPathCommandMask(fill_mode, mask)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| + "mask+1 is not power of two"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode); |
| + if (!validators_->path_instanced_cover_mode.IsValid(cover_mode)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glStencilThenCoverFillPathInstancedNV(num_paths, path_name_type, paths, 0, |
| + fill_mode, mask, cover_mode, |
| + transform_type, transforms); |
| + |
| + return error::kNoError; |
| +} |
| + |
| +error::Error |
| +GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + static const char kFunctionName[] = |
| + "glStencilThenCoverStrokeInstancedCHROMIUM"; |
| + const gles2::cmds::StencilThenCoverStrokePathInstancedCHROMIUM& c = |
| + *static_cast< |
| + const gles2::cmds::StencilThenCoverStrokePathInstancedCHROMIUM*>( |
| + cmd_data); |
| + if (!features().chromium_path_rendering) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
|
Zhenyao Mo
2015/10/06 22:51:00
Same here, no GL error, but return error::kUnknown
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + "function not available"); |
| + return error::kNoError; |
| + } |
| + |
| + GLsizei num_paths = static_cast<GLsizei>(c.numPaths); |
| + if (num_paths < 0) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numPaths < 0"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum path_name_type = static_cast<GLsizei>(c.pathNameType); |
| + if (!validators_->path_name_type.IsValid(path_name_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, path_name_type, |
| + "pathNameType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum cover_mode = static_cast<GLenum>(c.coverMode); |
| + if (!validators_->path_instanced_cover_mode.IsValid(cover_mode)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode"); |
| + return error::kNoError; |
| + } |
| + |
| + GLenum transform_type = static_cast<GLenum>(c.transformType); |
| + if (!validators_->path_transform_type.IsValid(transform_type)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, transform_type, |
| + "transformType"); |
| + return error::kNoError; |
| + } |
| + |
| + GLuint path_base = static_cast<GLuint>(c.pathBase); |
| + GLuint reference = static_cast<GLuint>(c.reference); |
|
Zhenyao Mo
2015/10/06 22:51:00
GLint instead of GLuint
Kimmo Kinnunen
2015/10/08 09:28:29
Done.
|
| + GLuint mask = static_cast<GLuint>(c.mask); |
| + |
| + uint32 paths_shm_id = static_cast<uint32>(c.paths_shm_id); |
| + uint32 paths_shm_offset = static_cast<uint32>(c.paths_shm_offset); |
| + uint32 transforms_shm_id = static_cast<uint32>(c.transformValues_shm_id); |
| + uint32 transforms_shm_offset = |
| + static_cast<uint32>(c.transformValues_shm_offset); |
| + |
| + GLuint* paths = NULL; |
| + const GLfloat* transforms = NULL; |
| + error::Error prepare_error = error::kNoError; |
| + scoped_ptr<GLuint[]> temp_path_buffer; |
| + if (!PrepareInstancedPathCommand( |
| + num_paths, path_name_type, paths_shm_id, paths_shm_offset, path_base, |
| + transform_type, transforms_shm_id, transforms_shm_offset, |
| + &prepare_error, &paths, &transforms, &temp_path_buffer)) { |
| + return prepare_error; |
| + } |
| + |
| + ApplyDirtyState(); |
| + glStencilThenCoverStrokePathInstancedNV(num_paths, path_name_type, paths, 0, |
| + reference, mask, cover_mode, |
| + transform_type, transforms); |
| + |
| + 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. |