Index: content/common/gpu/texture_image_transport_surface.cc |
diff --git a/content/common/gpu/texture_image_transport_surface.cc b/content/common/gpu/texture_image_transport_surface.cc |
index 7e221139c65d7c862a8636f36d170df31df04549..c5fb0aaae3a0279f24061ac0e5c2c292d19f11e5 100644 |
--- a/content/common/gpu/texture_image_transport_surface.cc |
+++ b/content/common/gpu/texture_image_transport_surface.cc |
@@ -67,6 +67,10 @@ TextureImageTransportSurface::TextureImageTransportSurface( |
stub_destroyed_(false), |
backbuffer_suggested_allocation_(true), |
frontbuffer_suggested_allocation_(true), |
+ frontbuffer_is_protected_(true), |
+ ui_may_not_have_frontbuffer_handle_(false), |
+ current_valid_release_front_request_id_(0), |
+ next_unique_release_front_request_id_(0), |
parent_stub_(NULL) { |
GpuChannel* parent_channel = manager->LookupChannel(handle.parent_client_id); |
DCHECK(parent_channel); |
@@ -168,13 +172,25 @@ void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
if (backbuffer_suggested_allocation_) |
CreateBackTexture(textures_[back()].size); |
else |
- ReleaseBackTexture(); |
+ ReleaseTexture(back()); |
} |
void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
if (frontbuffer_suggested_allocation_ == allocation) |
return; |
frontbuffer_suggested_allocation_ = allocation; |
+ AdjustFrontBufferAllocation(0); |
+} |
+ |
+void TextureImageTransportSurface::AdjustFrontBufferAllocation( |
+ int retry_count) { |
+ if (!helper_->MakeCurrent()) |
+ return; |
+ |
+ if (!frontbuffer_suggested_allocation_ && |
+ textures_[front()].info->service_id() && |
+ !frontbuffer_is_protected_) |
+ RequestReleaseFrontTexture(retry_count); |
} |
void* TextureImageTransportSurface::GetShareHandle() { |
@@ -210,6 +226,7 @@ void TextureImageTransportSurface::OnWillDestroyStub( |
} |
bool TextureImageTransportSurface::SwapBuffers() { |
+ current_valid_release_front_request_id_ = 0; |
DCHECK(backbuffer_suggested_allocation_); |
if (!frontbuffer_suggested_allocation_) |
return true; |
@@ -220,12 +237,12 @@ bool TextureImageTransportSurface::SwapBuffers() { |
glFlush(); |
front_ = back(); |
- previous_damage_rect_ = gfx::Rect(textures_[front_].size); |
+ previous_damage_rect_ = gfx::Rect(textures_[front()].size); |
- DCHECK(textures_[front_].client_id != 0); |
+ DCHECK(textures_[front()].client_id != 0); |
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
- params.surface_handle = textures_[front_].client_id; |
+ params.surface_handle = textures_[front()].client_id; |
helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
helper_->SetScheduled(false); |
return true; |
@@ -233,6 +250,7 @@ bool TextureImageTransportSurface::SwapBuffers() { |
bool TextureImageTransportSurface::PostSubBuffer( |
int x, int y, int width, int height) { |
+ current_valid_release_front_request_id_ = 0; |
DCHECK(backbuffer_suggested_allocation_); |
if (!frontbuffer_suggested_allocation_) |
return true; |
@@ -245,21 +263,18 @@ bool TextureImageTransportSurface::PostSubBuffer( |
return false; |
} |
- DCHECK(textures_[back()].info); |
- int back_texture_service_id = textures_[back()].info->service_id(); |
- |
- DCHECK(textures_[front_].info); |
- int front_texture_service_id = textures_[front_].info->service_id(); |
- |
- gfx::Size expected_size = textures_[back()].size; |
- bool surfaces_same_size = textures_[front_].size == expected_size; |
- |
const gfx::Rect new_damage_rect(x, y, width, height); |
// An empty damage rect is a successful no-op. |
if (new_damage_rect.IsEmpty()) |
return true; |
+ int back_texture_service_id = textures_[back()].info->service_id(); |
+ int front_texture_service_id = textures_[front()].info->service_id(); |
+ |
+ gfx::Size expected_size = textures_[back()].size; |
+ bool surfaces_same_size = textures_[front()].size == expected_size; |
+ |
if (surfaces_same_size) { |
std::vector<gfx::Rect> regions_to_copy; |
GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); |
@@ -286,17 +301,18 @@ bool TextureImageTransportSurface::PostSubBuffer( |
glFlush(); |
front_ = back(); |
+ previous_damage_rect_ = new_damage_rect; |
+ |
+ DCHECK(textures_[front()].client_id != 0); |
GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
- params.surface_handle = textures_[front_].client_id; |
+ params.surface_handle = textures_[front()].client_id; |
params.x = x; |
params.y = y; |
params.width = width; |
params.height = height; |
helper_->SendAcceleratedSurfacePostSubBuffer(params); |
helper_->SetScheduled(false); |
- |
- previous_damage_rect_ = new_damage_rect; |
return true; |
} |
@@ -321,10 +337,42 @@ void TextureImageTransportSurface::OnNewSurfaceACK( |
uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) { |
} |
+void TextureImageTransportSurface::OnSetFrontSurfaceIsProtected( |
+ bool is_protected) { |
+ if (frontbuffer_is_protected_ == is_protected) |
+ return; |
+ frontbuffer_is_protected_ = is_protected; |
+ AdjustFrontBufferAllocation(0); |
+} |
+ |
+void TextureImageTransportSurface::OnRequestReleaseFrontACK( |
+ int request_id, int retry_count, bool was_released) { |
+ if (!was_released) { |
+ // If the browser ignored out request, but the request id is still valid, |
+ // call AdjustFrontBufferAllocation, which will send another request only if |
+ // it still makes sense to do so. This can happen with visibility ABA |
+ // transitions. |
+ if (request_id == current_valid_release_front_request_id_ && |
+ retry_count < kMaxRequestReleaseFrontRetries) |
+ AdjustFrontBufferAllocation(retry_count + 1); |
+ return; |
+ } |
+ if (frontbuffer_suggested_allocation_ || frontbuffer_is_protected_ || |
+ request_id != current_valid_release_front_request_id_) |
+ return; |
+ Texture& texture = textures_[front()]; |
+ texture.sent_to_client = false; |
+ ReleaseTexture(front()); |
+} |
+ |
void TextureImageTransportSurface::OnBuffersSwappedACK() { |
if (helper_->MakeCurrent()) { |
- if (textures_[front_].size != textures_[back()].size) { |
- CreateBackTexture(textures_[front_].size); |
+ if (textures_[front()].size != textures_[back()].size || |
+ !textures_[back()].info->service_id() || |
+ !textures_[back()].sent_to_client || |
+ ui_may_not_have_frontbuffer_handle_) { |
+ CreateBackTexture(textures_[front()].size); |
+ ui_may_not_have_frontbuffer_handle_ = false; |
} else { |
AttachBackTextureToFBO(); |
} |
@@ -343,10 +391,30 @@ void TextureImageTransportSurface::OnResizeViewACK() { |
NOTREACHED(); |
} |
-void TextureImageTransportSurface::ReleaseBackTexture() { |
+void TextureImageTransportSurface::RequestReleaseFrontTexture(int retry_count) { |
+ Texture& texture = textures_[front()]; |
+ DCHECK(texture.info); |
+ DCHECK(texture.info->service_id()); |
+ if (!texture.sent_to_client) { |
+ ReleaseTexture(front()); |
+ return; |
+ } |
+ if (!retry_count) |
+ current_valid_release_front_request_id_ = |
+ ++next_unique_release_front_request_id_; |
+ GpuHostMsg_AcceleratedSurfaceRequestReleaseFront_Params params; |
+ params.identifier = texture.client_id; |
+ params.request_id = current_valid_release_front_request_id_; |
+ params.retry_count = retry_count; |
+ helper_->SendAcceleratedSurfaceRequestReleaseFront(params); |
+ ui_may_not_have_frontbuffer_handle_ = true; |
+} |
+ |
+void TextureImageTransportSurface::ReleaseTexture(int id) { |
if (!parent_stub_) |
return; |
- TextureInfo* info = textures_[back()].info; |
+ Texture& texture = textures_[id]; |
+ TextureInfo* info = texture.info; |
DCHECK(info); |
GLuint service_id = info->service_id(); |
@@ -371,7 +439,8 @@ void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { |
GLuint service_id = info->service_id(); |
- if (service_id && texture.size == size) |
+ if (service_id && texture.size == size && |
+ !ui_may_not_have_frontbuffer_handle_ && texture.sent_to_client) |
return; |
if (!service_id) { |
@@ -422,13 +491,14 @@ void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { |
void TextureImageTransportSurface::AttachBackTextureToFBO() { |
if (!parent_stub_) |
return; |
- DCHECK(textures_[back()].info); |
+ TextureInfo* info = textures_[back()].info; |
+ DCHECK(info); |
ScopedFrameBufferBinder fbo_binder(fbo_id_); |
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
GL_COLOR_ATTACHMENT0, |
GL_TEXTURE_2D, |
- textures_[back()].info->service_id(), |
+ info->service_id(), |
0); |
glFlush(); |
CHECK_GL_ERROR(); |