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 db2c9d22c142c3fa90d8e93ba069e37e30e79b9b..a66d8774d679586d76dbcb0bb6923b234bfa6da3 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -12110,38 +12110,62 @@ error::Error GLES2DecoderImpl::HandleScheduleDCLayerCHROMIUM( |
return error::kNoError; |
} |
- gl::GLImage* image = nullptr; |
- GLuint contents_texture_id = c.contents_texture_id; |
- if (contents_texture_id) { |
- TextureRef* ref = texture_manager()->GetTexture(contents_texture_id); |
- if (!ref) { |
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleDCLayerCHROMIUM", |
- "unknown texture"); |
- return error::kNoError; |
- } |
- Texture::ImageState image_state; |
- image = ref->texture()->GetLevelImage(ref->texture()->target(), 0, |
- &image_state); |
- if (!image) { |
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleDCLayerCHROMIUM", |
- "unsupported texture format"); |
- return error::kNoError; |
- } |
+ GLsizei num_textures = c.num_textures; |
+ if (num_textures < 0 || num_textures > 4) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glScheduleDCLayerCHROMIUM", |
+ "number of textures greater than maximum of 4"); |
+ return error::kNoError; |
} |
- const GLfloat* mem = GetSharedMemoryAs<const GLfloat*>(c.shm_id, c.shm_offset, |
- 8 * sizeof(GLfloat)); |
- if (!mem) { |
+ size_t textures_size = num_textures * sizeof(GLuint); |
+ |
+ base::CheckedNumeric<uint32_t> data_size = textures_size; |
+ const uint32_t kRectDataSize = 8 * sizeof(GLfloat); |
+ data_size += kRectDataSize; |
+ if (!data_size.IsValid()) |
+ return error::kOutOfBounds; |
+ const void* data = |
+ GetAddressAndCheckSize(c.shm_id, c.shm_offset, data_size.ValueOrDie()); |
+ if (!data) { |
return error::kOutOfBounds; |
} |
+ const GLfloat* mem = reinterpret_cast<const GLfloat*>(data); |
+ |
gfx::RectF contents_rect(mem[0], mem[1], mem[2], mem[3]); |
gfx::RectF bounds_rect(mem[4], mem[5], mem[6], mem[7]); |
+ const volatile GLuint* texture_ids = reinterpret_cast<const volatile GLuint*>( |
+ static_cast<const volatile char*>(data) + kRectDataSize); |
+ |
+ std::vector<scoped_refptr<gl::GLImage>> images; |
+ for (int i = 0; i < num_textures; ++i) { |
+ GLuint contents_texture_id = texture_ids[i]; |
+ scoped_refptr<gl::GLImage> image; |
+ if (contents_texture_id) { |
+ TextureRef* ref = texture_manager()->GetTexture(contents_texture_id); |
+ if (!ref) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleDCLayerCHROMIUM", |
+ "unknown texture"); |
+ return error::kNoError; |
+ } |
+ Texture::ImageState image_state; |
+ image = ref->texture()->GetLevelImage(ref->texture()->target(), 0, |
+ &image_state); |
+ if (!image) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glScheduleDCLayerCHROMIUM", |
+ "unsupported texture format"); |
+ return error::kNoError; |
+ } |
+ } |
+ images.push_back(image); |
+ } |
+ |
ui::DCRendererLayerParams params = ui::DCRendererLayerParams( |
dc_layer_shared_state_->is_clipped, dc_layer_shared_state_->clip_rect, |
- dc_layer_shared_state_->z_order, dc_layer_shared_state_->transform, image, |
- contents_rect, gfx::ToEnclosingRect(bounds_rect), c.background_color, |
- c.edge_aa_mask, dc_layer_shared_state_->opacity, filter); |
+ dc_layer_shared_state_->z_order, dc_layer_shared_state_->transform, |
+ images, contents_rect, gfx::ToEnclosingRect(bounds_rect), |
+ c.background_color, c.edge_aa_mask, dc_layer_shared_state_->opacity, |
+ filter); |
if (!surface_->ScheduleDCLayer(params)) { |
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glScheduleDCLayerCHROMIUM", |
"failed to schedule DCLayer"); |