| 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 40f5c63f5eacf92a34f0ad249c536f857c99e617..0c5b0aeb23ea1269b19b16666c93b082f64f0fd9 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -1038,6 +1038,16 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
|
|
|
| void DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id, GLint fence_id);
|
| void DoReleaseTexImage2DCHROMIUM(GLenum target, GLint image_id);
|
| + void DoCopyImageSubDataCHROMIUM(GLint source_image_id,
|
| + GLint dest_texture_id,
|
| + GLint xoffset,
|
| + GLint yoffset,
|
| + GLint x,
|
| + GLint y,
|
| + GLsizei width,
|
| + GLsizei height,
|
| + GLint in_fence_id,
|
| + GLint out_fence_id);
|
|
|
| void DoTraceEndCHROMIUM(void);
|
|
|
| @@ -16934,6 +16944,152 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(GLenum target,
|
| Texture::UNBOUND);
|
| }
|
|
|
| +void GLES2DecoderImpl::DoCopyImageSubDataCHROMIUM(GLint source_image_id,
|
| + GLint dest_texture_id,
|
| + GLint xoffset,
|
| + GLint yoffset,
|
| + GLint x,
|
| + GLint y,
|
| + GLsizei width,
|
| + GLsizei height,
|
| + GLint in_fence_id,
|
| + GLint out_fence_id) {
|
| + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyImageSubDataCHROMIUM");
|
| +
|
| + TextureRef* dest_texture_ref = GetTexture(dest_texture_id);
|
| + Texture* dest_texture = dest_texture_ref->texture();
|
| + GLenum dest_target = dest_texture->target();
|
| + GLenum dest_type = 0;
|
| + GLenum dest_internal_format = 0;
|
| + bool dest_level_defined = dest_texture->GetLevelType(
|
| + dest_target, 0, &dest_type, &dest_internal_format);
|
| + if (!dest_level_defined) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "destination texture is not defined");
|
| + return;
|
| + }
|
| + if (dest_target != GL_TEXTURE_2D) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyImageSubDataCHROMIUM",
|
| + "destination texture bad target.");
|
| + return;
|
| + }
|
| + if (!dest_texture->ValidForTexture(dest_target, 0, xoffset, yoffset, 0, width,
|
| + height, 1)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyImageSubDataCHROMIUM",
|
| + "destination texture bad dimensions.");
|
| + return;
|
| + }
|
| + int dest_width = 0;
|
| + int dest_height = 0;
|
| + bool ok = dest_texture->GetLevelSize(dest_target, 0, &dest_width,
|
| + &dest_height, nullptr);
|
| + DCHECK(ok);
|
| + if (xoffset != 0 || yoffset != 0 || width != dest_width ||
|
| + height != dest_height) {
|
| + gfx::Rect cleared_rect;
|
| + if (TextureManager::CombineAdjacentRects(
|
| + dest_texture->GetLevelClearedRect(dest_target, 0),
|
| + gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) {
|
| + DCHECK_GE(
|
| + cleared_rect.size().GetArea(),
|
| + dest_texture->GetLevelClearedRect(dest_target, 0).size().GetArea());
|
| + texture_manager()->SetLevelClearedRect(dest_texture_ref, dest_target, 0,
|
| + cleared_rect);
|
| + } else {
|
| + // Otherwise clear part of texture level that is not already cleared.
|
| + if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref,
|
| + dest_target, 0)) {
|
| + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyImageSubDataCHROMIUM",
|
| + "destination texture dimensions too big");
|
| + return;
|
| + }
|
| + }
|
| + } else {
|
| + texture_manager()->SetLevelCleared(dest_texture_ref, dest_target, 0, true);
|
| + }
|
| +
|
| + gl::GLImage* image = image_manager()->LookupImage(source_image_id);
|
| + if (!image) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "no image found with the given ID");
|
| + return;
|
| + }
|
| +
|
| + gl::GLFence* in_fence = nullptr;
|
| + if (in_fence_id) {
|
| + in_fence = fence_manager()->LookupFence(in_fence_id);
|
| + if (!in_fence) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "no fence found with the given ID");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + gl::GLFence* out_fence = nullptr;
|
| + if (out_fence_id) {
|
| + out_fence = fence_manager()->LookupFence(out_fence_id);
|
| + if (!out_fence) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "no fence found with the given ID");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + if (image->CopySubImageData(
|
| + dest_texture->service_id(), gfx::Point(xoffset, yoffset),
|
| + gfx::Rect(x, y, width, height), in_fence, out_fence)) {
|
| + return;
|
| + }
|
| +
|
| + if (!InitializeCopyTextureCHROMIUM("glCopyImageSubDataCHROMIUM"))
|
| + return;
|
| +
|
| + // Output fence must have support for client side signaling.
|
| + if (out_fence && !out_fence->SignalSupported()) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "bad output fence");
|
| + return;
|
| + }
|
| +
|
| + if (!features().oes_egl_image_external) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "oes_egl_image_external missing");
|
| + return;
|
| + }
|
| +
|
| + GLuint temp_texture = 0;
|
| + glGenTextures(1, &temp_texture);
|
| + ScopedTextureBinder binder(&state_, temp_texture, GL_TEXTURE_EXTERNAL_OES);
|
| +
|
| + if (!image->BindTexImage(GL_TEXTURE_EXTERNAL_OES, in_fence)) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyImageSubDataCHROMIUM",
|
| + "BindTexImage failed");
|
| + glDeleteTextures(1, &temp_texture);
|
| + return;
|
| + }
|
| +
|
| + gfx::Size image_size = image->GetSize();
|
| + copy_texture_CHROMIUM_->DoCopySubTexture(
|
| + this, GL_TEXTURE_EXTERNAL_OES, temp_texture, image->GetInternalFormat(),
|
| + dest_target, dest_texture->service_id(), dest_internal_format, xoffset,
|
| + yoffset, x, y, width, height, dest_width, dest_height, image_size.width(),
|
| + image_size.height(), false, false, false);
|
| +
|
| + glDeleteTextures(1, &temp_texture);
|
| +
|
| + if (out_fence) {
|
| + gl::GLSurface* surface = gl::GLSurface::GetCurrent();
|
| + if (surface->SupportsInsertFence()) {
|
| + // Insert fence and forward signal to |out_fence|.
|
| + surface->InsertFence(base::Bind(&gl::GLFence::Signal, out_fence));
|
| + } else {
|
| + LOG(WARNING) << "Fence support missing, using glFinish()";
|
| + glFinish();
|
| + out_fence->Signal();
|
| + }
|
| + }
|
| +}
|
| +
|
| error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
|
| uint32_t immediate_data_size,
|
| const volatile void* cmd_data) {
|
|
|