| Index: gpu/command_buffer/client/gles2_implementation.cc | 
| diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc | 
| index 19a005f43015f6ecf1b55f43ed478262133acacc..87559cf3a955fdd2e3c80b8075da68b285da4714 100644 | 
| --- a/gpu/command_buffer/client/gles2_implementation.cc | 
| +++ b/gpu/command_buffer/client/gles2_implementation.cc | 
| @@ -3777,6 +3777,125 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( | 
| } | 
| } | 
|  | 
| +void GLES2Implementation::AsyncCompressedTexImage2DCHROMIUM( | 
| +    GLenum target, | 
| +    GLint level, | 
| +    GLint internalformat, | 
| +    GLsizei width, | 
| +    GLsizei height, | 
| +    GLint border, | 
| +    GLsizei imagesize, | 
| +    const void* pixels) { | 
| +  GPU_CLIENT_SINGLE_THREAD_CHECK(); | 
| +  GPU_CLIENT_LOG( | 
| +      "[" << GetLogPrefix() << "] glCompressedTexImage2D(" | 
| +          << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", " | 
| +          << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " | 
| +          << width << ", " << height << ", " << border << ", " << imagesize | 
| +          << ", " << static_cast<const void*>(pixels) << ")"); | 
| +  if (level < 0 || height < 0 || width < 0) { | 
| +    SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "dimension < 0"); | 
| +    return; | 
| +  } | 
| +  if (border != 0) { | 
| +    SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "border != 0"); | 
| +    return; | 
| +  } | 
| + | 
| +  int calculated_imagesize = 0; | 
| +  if (!GLES2Util::ComputeCompressedImageSize(width, height, internalformat, | 
| +                                             &calculated_imagesize) || | 
| +      calculated_imagesize != imagesize) { | 
| +    SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", | 
| +               "imagesize is not consistent"); | 
| +    return; | 
| +  } | 
| + | 
| +  // If there's no data/buffer just issue the AsyncTexImage2D | 
| +  if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) { | 
| +    helper_->AsyncCompressedTexImage2DCHROMIUM( | 
| +        target, level, internalformat, width, height, imagesize, 0, 0, 0, 0, 0); | 
| +    return; | 
| +  } | 
| + | 
| +  if (!EnsureAsyncUploadSync()) { | 
| +    SetGLError(GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory"); | 
| +    return; | 
| +  } | 
| + | 
| +  // Otherwise, async uploads require a transfer buffer to be bound. | 
| +  // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use | 
| +  // the buffer before the transfer is finished. (Currently such | 
| +  // synchronization has to be handled manually.) | 
| +  GLuint offset = ToGLuint(pixels); | 
| +  BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 
| +      bound_pixel_unpack_transfer_buffer_id_, | 
| +      "glAsyncCompressedTexImage2DCHROMIUM", offset, imagesize); | 
| +  if (buffer && buffer->shm_id() != -1) { | 
| +    uint32 async_token = NextAsyncUploadToken(); | 
| +    buffer->set_last_async_upload_token(async_token); | 
| +    helper_->AsyncCompressedTexImage2DCHROMIUM( | 
| +        target, level, internalformat, width, height, imagesize, | 
| +        buffer->shm_id(), buffer->shm_offset() + offset, async_token, | 
| +        async_upload_sync_shm_id_, async_upload_sync_shm_offset_); | 
| +  } | 
| +} | 
| + | 
| +void GLES2Implementation::AsyncCompressedTexSubImage2DCHROMIUM( | 
| +    GLenum target, | 
| +    GLint level, | 
| +    GLint xoffset, | 
| +    GLint yoffset, | 
| +    GLsizei width, | 
| +    GLsizei height, | 
| +    GLenum format, | 
| +    GLsizei imagesize, | 
| +    const void* pixels) { | 
| +  GPU_CLIENT_SINGLE_THREAD_CHECK(); | 
| +  GPU_CLIENT_LOG( | 
| +      "[" << GetLogPrefix() << "] glAsyncCompressedTexSubImage2DCHROMIUM(" | 
| +          << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", " | 
| +          << xoffset << ", " << yoffset << ", " << width << ", " << height | 
| +          << ", " << GLES2Util::GetStringTextureFormat(format) << ", " | 
| +          << imagesize << ", " << static_cast<const void*>(pixels) << ")"); | 
| +  if (level < 0 || height < 0 || width < 0) { | 
| +    SetGLError(GL_INVALID_VALUE, "glAsyncCompressedTexSubImage2DCHROMIUM", | 
| +               "dimension < 0"); | 
| +    return; | 
| +  } | 
| + | 
| +  int calculated_imagesize = 0; | 
| +  if (!GLES2Util::ComputeCompressedImageSize(width, height, format, | 
| +                                             &calculated_imagesize) || | 
| +      calculated_imagesize != imagesize) { | 
| +    SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", | 
| +               "imagesize is not consistent"); | 
| +    return; | 
| +  } | 
| + | 
| +  if (!EnsureAsyncUploadSync()) { | 
| +    SetGLError(GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D", "out of memory"); | 
| +    return; | 
| +  } | 
| + | 
| +  // Async uploads require a transfer buffer to be bound. | 
| +  // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use | 
| +  // the buffer before the transfer is finished. (Currently such | 
| +  // synchronization has to be handled manually.) | 
| +  GLuint offset = ToGLuint(pixels); | 
| +  BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 
| +      bound_pixel_unpack_transfer_buffer_id_, | 
| +      "glAsyncCompressedTexSubImage2DCHROMIUM", offset, imagesize); | 
| +  if (buffer && buffer->shm_id() != -1) { | 
| +    uint32 async_token = NextAsyncUploadToken(); | 
| +    buffer->set_last_async_upload_token(async_token); | 
| +    helper_->AsyncCompressedTexSubImage2DCHROMIUM( | 
| +        target, level, xoffset, yoffset, width, height, format, imagesize, | 
| +        buffer->shm_id(), buffer->shm_offset() + offset, async_token, | 
| +        async_upload_sync_shm_id_, async_upload_sync_shm_offset_); | 
| +  } | 
| +} | 
| + | 
| void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { | 
| GPU_CLIENT_SINGLE_THREAD_CHECK(); | 
| GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" | 
|  |