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 b1292f00e5ffbd6dce4b5cb19327644f76f251f0..4f7f4f42741344a2b2c2dc6fb8db60830353f1b4 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -55,6 +55,7 @@ |
| #include "gpu/command_buffer/service/texture_manager.h" |
| #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
| #include "gpu/command_buffer/service/vertex_array_manager.h" |
| +#include "ui/gl/async_pixel_transfer_delegate.h" |
| #include "ui/gl/gl_image.h" |
| #include "ui/gl/gl_implementation.h" |
| #include "ui/gl/gl_surface.h" |
| @@ -3506,10 +3507,32 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { |
| "glBindTexture", "illegal target for stream texture."); |
| return; |
| } |
| - if (info->target() == 0) { |
| - texture_manager()->SetInfoTarget(info, target); |
| + |
| + if (!info->IsAsyncTransferTexture()) { |
| + if (info->target() == 0) { |
| + texture_manager()->SetInfoTarget(info, target); |
| + } |
| + glBindTexture(target, info->service_id()); |
| + } else { |
| + // If the texture has async transfers, they must be complete. |
| + if (info->AsyncTransferIsInProgress()) { |
| + SetGLError(GL_INVALID_OPERATION, |
| + "glBindTexture", "async transfer already in progress"); |
| + return; |
| + } |
| + |
| + if (info->target() == 0) { |
| + texture_manager()->SetInfoTarget(info, target); |
| + } |
| + |
| + // Bind the GL texture, and perform any custom binding. |
| + info->BindAsyncTransferTexture(target); |
| + |
| + // We now know the transfer texture is cleared. |
| + texture_manager()->SetLevelCleared(info, target, 0); |
| } |
| - glBindTexture(target, info->service_id()); |
| + |
| + |
| TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; |
| unit.bind_target = target; |
| switch (target) { |
| @@ -9347,10 +9370,41 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( |
| } |
| } |
| - // TODO(epenner): Do this via an async task. |
| - return DoTexImage2D( |
| - target, level, internal_format, width, height, border, format, type, |
| - pixels, pixels_size); |
| + // We only support async uploads to 2D textures for now. |
| + if (target != GL_TEXTURE_2D) { |
| + SetGLErrorInvalidEnum("glTexSubImage2D", type, "type"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + return error::kNoError; |
| + } |
| + |
| + // We only support uploads to level zero for now. |
| + if (level != 0) { |
| + SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "level != 0"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + return error::kNoError; |
| + } |
| + |
| + // We only support one async transfer in progress. |
| + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); |
| + if (!info || info->AsyncTransferIsInProgress()) { |
| + SetGLError(GL_INVALID_OPERATION, |
| + "glAsyncTexImage2D", "transfer already in progress"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + } |
| + |
| + // We know the memory/size is safe, so get the real shared |
| + // memory since it might need to be duped to prevent |
| + // use-after-free issues. |
| + Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id); |
| + base::SharedMemory* shared_memory = buffer.shared_memory; |
| + uint32 shm_size = buffer.size; |
| + uint32 shm_data_offset = c.pixels_shm_offset; |
| + uint32 shm_data_size = pixels_size; |
| + |
| + gfx::AsyncPixelTransferDelegate::Get()->AsyncTexImage2D( |
| + info->AsyncTransferState(), |
| + target, level, internal_format, |
| + width, height, border, format, type, |
| + shared_memory, shm_size, shm_data_offset, shm_data_size); |
| + |
| + return error::kNoError; |
| } |
| error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( |
| @@ -9395,13 +9449,64 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( |
| SetGLErrorInvalidEnum("glTexSubImage2D", type, "type"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| return error::kNoError; |
| } |
| - if (pixels == NULL) { |
| + |
| + // TexSubImage must have valid pixels. |
| + if (pixels == NULL) |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| return error::kOutOfBounds; |
|
greggman
2012/12/06 06:52:00
Does this need to be death or should it be SetGLEr
epenner
2012/12/08 03:15:04
It's an SetGLError now when no transfer buffer is
|
| + |
| + // We only support async uploads to 2D textures for now. |
| + if (target != GL_TEXTURE_2D) { |
| + SetGLErrorInvalidEnum("glTexSubImage2D", type, "type"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + return error::kNoError; |
| } |
| - // TODO(epenner): Do this via an async task. |
| - DoTexSubImage2D( |
| - target, level, xoffset, yoffset, width, height, format, type, pixels); |
| + // We only support uploads to level zero for now. |
| + if (level != 0) { |
| + SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "level != 0"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + return error::kNoError; |
| + } |
| + |
| + // We only support one async transfer in progress. |
| + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); |
| + if (!info || info->AsyncTransferIsInProgress()) { |
| + SetGLError(GL_INVALID_OPERATION, |
| + "glTexSubImage2D", "transfer already in progress"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + } |
| + |
| + // It would be nice to do this async as well, but that way we can't |
| + // be sure the texture is cleared after this call. So better to do it |
| + // immediately (it's easy to avoid this penalty anyway). |
| + GLsizei tex_width = 0; |
| + GLsizei tex_height = 0; |
| + bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height); |
| + DCHECK(ok); |
| + if (xoffset != 0 || yoffset != 0 || |
| + width != tex_width || height != tex_height) { |
| + if (!texture_manager()->ClearTextureLevel(this, info, target, level)) { |
| + SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big"); |
|
greggman
2012/12/06 06:52:00
"glAsyncTexImage2DCHROMIUM"
epenner
2012/12/08 03:15:04
Done.
|
| + return error::kNoError; |
| + } |
| + // The level is certainly cleared now. In the full update case |
| + // we wait until the texture is used to mark it as cleared, |
| + // since by then the async transfer must be complete. |
| + texture_manager()->SetLevelCleared(info, target, level); |
| + } |
| + |
| + // We know the memory/size is safe, so get the real shared |
| + // memory since it might need to be duped to prevent |
| + // use-after-free issues. |
| + Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id); |
| + base::SharedMemory* shared_memory = buffer.shared_memory; |
| + uint32 shm_size = buffer.size; |
| + uint32 shm_data_offset = c.data_shm_offset; |
| + uint32 shm_data_size = data_size; |
| + |
| + gfx::AsyncPixelTransferDelegate::Get()->AsyncTexSubImage2D( |
| + info->AsyncTransferState(), |
| + target, level, xoffset, yoffset, |
| + width, height, format, type, |
| + shared_memory, shm_size, shm_data_offset, shm_data_size); |
| + |
| return error::kNoError; |
| } |