Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Unified Diff: content/common/gpu/texture_image_transport_surface.cc

Issue 14188053: gpu: Change Produce/ConsumeTexture to allow texture sharing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 858c023f700b9aaa2ba35f74f83cf4bdccfe7b27..766dac50b6a0af73b8a1c1bff9abe68beaf4dd2f 100644
--- a/content/common/gpu/texture_image_transport_surface.cc
+++ b/content/common/gpu/texture_image_transport_surface.cc
@@ -18,10 +18,12 @@
#include "ui/gl/scoped_binders.h"
using gpu::gles2::ContextGroup;
+using gpu::gles2::GLES2Decoder;
using gpu::gles2::MailboxManager;
using gpu::gles2::MailboxName;
-using gpu::gles2::TextureDefinition;
+using gpu::gles2::Texture;
using gpu::gles2::TextureManager;
+using gpu::gles2::TextureRef;
namespace content {
@@ -30,7 +32,7 @@ TextureImageTransportSurface::TextureImageTransportSurface(
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& handle)
: fbo_id_(0),
- backbuffer_(CreateTextureDefinition(gfx::Size(), 0)),
+ current_size_(1, 1),
stub_destroyed_(false),
backbuffer_suggested_allocation_(true),
frontbuffer_suggested_allocation_(true),
@@ -91,41 +93,19 @@ bool TextureImageTransportSurface::DeferDraws() {
return false;
}
-bool TextureImageTransportSurface::Resize(const gfx::Size&) {
- return true;
-}
-
bool TextureImageTransportSurface::IsOffscreen() {
return true;
}
-bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
- if (stub_destroyed_) {
- // Early-exit so that we don't recreate the fbo. We still want to return
- // true, so that the context is made current and the GLES2DecoderImpl can
- // release its own resources.
- return true;
- }
-
- context_ = context;
-
+unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
if (!fbo_id_) {
glGenFramebuffersEXT(1, &fbo_id_);
glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
- current_size_ = gfx::Size(1, 1);
helper_->stub()->AddDestructionObserver(this);
- }
-
- // We could be receiving non-deferred GL commands, that is anything that does
- // not need a framebuffer.
- if (!backbuffer_->service_id() && !is_swap_buffers_pending_ &&
- backbuffer_suggested_allocation_) {
CreateBackTexture();
}
- return true;
-}
-unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() {
return fbo_id_;
}
@@ -136,7 +116,7 @@ bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) {
backbuffer_suggested_allocation_ = allocation;
if (backbuffer_suggested_allocation_) {
- DCHECK(!backbuffer_->service_id());
+ DCHECK(!backbuffer_);
CreateBackTexture();
} else {
ReleaseBackTexture();
@@ -150,9 +130,15 @@ void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
return;
frontbuffer_suggested_allocation_ = allocation;
- if (!frontbuffer_suggested_allocation_) {
- GpuHostMsg_AcceleratedSurfaceRelease_Params params;
- helper_->SendAcceleratedSurfaceRelease(params);
+ // If a swapbuffers is in flight, wait for the ack before releasing the front
+ // buffer:
+ // - we don't know yet which texture the browser will want to keep
+ // - we want to ensure we don't destroy a texture that is in flight before the
+ // browser got a reference on it.
+ if (!frontbuffer_suggested_allocation_ &&
+ !is_swap_buffers_pending_ &&
+ helper_->MakeCurrent()) {
+ ReleaseFrontTexture();
}
}
@@ -169,20 +155,21 @@ void* TextureImageTransportSurface::GetConfig() {
}
void TextureImageTransportSurface::OnResize(gfx::Size size) {
+ DCHECK_GE(size.width(), 1);
+ DCHECK_GE(size.height(), 1);
current_size_ = size;
CreateBackTexture();
}
void TextureImageTransportSurface::OnWillDestroyStub() {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
helper_->stub()->RemoveDestructionObserver(this);
- GpuHostMsg_AcceleratedSurfaceRelease_Params params;
- helper_->SendAcceleratedSurfaceRelease(params);
-
- ReleaseBackTexture();
-
// We are losing the stub owning us, this is our last chance to clean up the
// resources we allocated in the stub's context.
+ ReleaseBackTexture();
+ ReleaseFrontTexture();
+
if (fbo_id_) {
glDeleteFramebuffersEXT(1, &fbo_id_);
CHECK_GL_ERROR();
@@ -198,12 +185,13 @@ void TextureImageTransportSurface::SetLatencyInfo(
}
bool TextureImageTransportSurface::SwapBuffers() {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
DCHECK(backbuffer_suggested_allocation_);
if (!frontbuffer_suggested_allocation_)
return true;
- if (!backbuffer_->service_id()) {
+ if (!backbuffer_) {
LOG(ERROR) << "Swap without valid backing.";
return true;
}
@@ -212,14 +200,10 @@ bool TextureImageTransportSurface::SwapBuffers() {
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
params.size = backbuffer_size();
params.mailbox_name.assign(
- reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_));
+ reinterpret_cast<const char*>(&back_mailbox_name_),
+ sizeof(back_mailbox_name_));
glFlush();
- ProduceTexture();
-
- // Do not allow destruction while we are still waiting for a swap ACK,
- // so we do not leak a texture in the mailbox.
- AddRef();
params.latency_info = latency_info_;
helper_->SendAcceleratedSurfaceBuffersSwapped(params);
@@ -231,6 +215,7 @@ bool TextureImageTransportSurface::SwapBuffers() {
bool TextureImageTransportSurface::PostSubBuffer(
int x, int y, int width, int height) {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
DCHECK(backbuffer_suggested_allocation_);
if (!frontbuffer_suggested_allocation_)
return true;
@@ -241,7 +226,7 @@ bool TextureImageTransportSurface::PostSubBuffer(
if (new_damage_rect.IsEmpty())
return true;
- if (!backbuffer_->service_id()) {
+ if (!backbuffer_) {
LOG(ERROR) << "Swap without valid backing.";
return true;
}
@@ -254,14 +239,10 @@ bool TextureImageTransportSurface::PostSubBuffer(
params.width = width;
params.height = height;
params.mailbox_name.assign(
- reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_));
+ reinterpret_cast<const char*>(&back_mailbox_name_),
+ sizeof(back_mailbox_name_));
glFlush();
- ProduceTexture();
-
- // Do not allow destruction while we are still waiting for a swap ACK,
- // so we do not leak a texture in the mailbox.
- AddRef();
params.latency_info = latency_info_;
helper_->SendAcceleratedSurfacePostSubBuffer(params);
@@ -280,11 +261,7 @@ std::string TextureImageTransportSurface::GetExtensions() {
}
gfx::Size TextureImageTransportSurface::GetSize() {
- gfx::Size size = current_size_;
-
- // OSMesa expects a non-zero size.
- return gfx::Size(size.width() == 0 ? 1 : size.width(),
- size.height() == 0 ? 1 : size.height());
+ return current_size_;
}
void* TextureImageTransportSurface::GetHandle() {
@@ -306,45 +283,40 @@ void TextureImageTransportSurface::OnBufferPresented(
this,
params.mailbox_name));
}
-
- // Careful, we might get deleted now if we were only waiting for
- // a final swap ACK.
- Release();
}
void TextureImageTransportSurface::BufferPresentedImpl(
const std::string& mailbox_name) {
- DCHECK(!backbuffer_->service_id());
- if (!mailbox_name.empty()) {
- DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM);
- mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_),
- sizeof(MailboxName));
- ConsumeTexture();
- }
-
- if (stub_destroyed_ && backbuffer_->service_id()) {
- // TODO(sievers): Remove this after changes to the mailbox to take ownership
- // of the service ids.
- DCHECK(context_.get() && surface_.get());
- uint32 service_id = backbuffer_->ReleaseServiceId();
- if (context_->MakeCurrent(surface_))
- glDeleteTextures(1, &service_id);
-
- return;
- }
-
DCHECK(is_swap_buffers_pending_);
is_swap_buffers_pending_ = false;
-
// We should not have allowed the backbuffer to be discarded while the ack
// was pending.
DCHECK(backbuffer_suggested_allocation_);
+ DCHECK(backbuffer_);
+
+ bool swap = true;
+ if (!mailbox_name.empty()) {
+ DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM);
+ if (!memcmp(mailbox_name.data(),
+ &back_mailbox_name_,
+ mailbox_name.length())) {
+ // The browser has skipped the frame to unblock the GPU process, waiting
+ // for one of the right size, and returned the back buffer, so don't swap.
+ swap = false;
+ }
+ }
+ if (swap) {
+ std::swap(backbuffer_, frontbuffer_);
+ std::swap(back_mailbox_name_, front_mailbox_name_);
+ }
// We're relying on the fact that the parent context is
- // finished with it's context when it inserts the sync point that
+ // finished with its context when it inserts the sync point that
// triggers this callback.
if (helper_->MakeCurrent()) {
- if (backbuffer_size() != current_size_ || !backbuffer_->service_id())
+ if (frontbuffer_ && !frontbuffer_suggested_allocation_)
+ ReleaseFrontTexture();
+ if (!backbuffer_ || backbuffer_size() != current_size_)
CreateBackTexture();
else
AttachBackTextureToFBO();
@@ -363,67 +335,90 @@ void TextureImageTransportSurface::OnResizeViewACK() {
}
void TextureImageTransportSurface::ReleaseBackTexture() {
- if (!backbuffer_->service_id())
- return;
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
+ backbuffer_ = NULL;
+ back_mailbox_name_ = MailboxName();
+ glFlush();
+ CHECK_GL_ERROR();
+}
- uint32 service_id = backbuffer_->ReleaseServiceId();
- glDeleteTextures(1, &service_id);
- backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0));
- mailbox_name_ = MailboxName();
+void TextureImageTransportSurface::ReleaseFrontTexture() {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
+ frontbuffer_ = NULL;
+ front_mailbox_name_ = MailboxName();
glFlush();
CHECK_GL_ERROR();
+ GpuHostMsg_AcceleratedSurfaceRelease_Params params;
+ helper_->SendAcceleratedSurfaceRelease(params);
}
void TextureImageTransportSurface::CreateBackTexture() {
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
// If |is_swap_buffers_pending| we are waiting for our backbuffer
// in the mailbox, so we shouldn't be reallocating it now.
DCHECK(!is_swap_buffers_pending_);
- if (backbuffer_->service_id() && backbuffer_size() == current_size_)
+ if (backbuffer_ && backbuffer_size() == current_size_)
return;
- uint32 service_id = backbuffer_->ReleaseServiceId();
-
VLOG(1) << "Allocating new backbuffer texture";
// On Qualcomm we couldn't resize an FBO texture past a certain
// size, after we allocated it as 1x1. So here we simply delete
// the previous texture on resize, to insure we don't 'run out of
// memory'.
- if (service_id &&
+ if (backbuffer_ &&
helper_->stub()
->decoder()
->GetContextGroup()
->feature_info()
->workarounds()
.delete_instead_of_resize_fbo) {
- glDeleteTextures(1, &service_id);
- service_id = 0;
- mailbox_name_ = MailboxName();
+ ReleaseBackTexture();
}
-
- if (!service_id) {
- MailboxName new_mailbox_name;
- MailboxName& name = mailbox_name_;
- // This slot should be uninitialized.
- DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName)));
- mailbox_manager_->GenerateMailboxName(&new_mailbox_name);
- name = new_mailbox_name;
+ GLES2Decoder* decoder = helper_->stub()->decoder();
+ TextureManager* texture_manager =
+ decoder->GetContextGroup()->texture_manager();
+ if (!backbuffer_) {
+ mailbox_manager_->GenerateMailboxName(&back_mailbox_name_);
+ GLuint service_id;
glGenTextures(1, &service_id);
+ backbuffer_ = TextureRef::Create(texture_manager, 0, service_id);
+ texture_manager->SetTarget(backbuffer_, GL_TEXTURE_2D);
+ Texture* texture = texture_manager->Produce(backbuffer_);
+ bool success = mailbox_manager_->ProduceTexture(
+ GL_TEXTURE_2D, back_mailbox_name_, texture);
+ DCHECK(success);
}
- backbuffer_.reset(
- CreateTextureDefinition(current_size_, service_id));
-
{
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, service_id);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D,
+ backbuffer_->service_id());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
current_size_.width(), current_size_.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ gpu::gles2::ErrorState* error_state = decoder->GetErrorState();
+ texture_manager->SetParameter("Backbuffer", error_state, backbuffer_,
+ GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ texture_manager->SetParameter("Backbuffer", error_state, backbuffer_,
+ GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ texture_manager->SetParameter("Backbuffer", error_state, backbuffer_,
+ GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ texture_manager->SetParameter("Backbuffer", error_state, backbuffer_,
+ GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ texture_manager->SetLevelInfo(
+ backbuffer_,
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ current_size_.width(),
+ current_size_.height(),
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ DCHECK(texture_manager->CanRender(backbuffer_));
CHECK_GL_ERROR();
}
@@ -431,7 +426,8 @@ void TextureImageTransportSurface::CreateBackTexture() {
}
void TextureImageTransportSurface::AttachBackTextureToFBO() {
- DCHECK(backbuffer_->service_id());
+ DCHECK(helper_->stub()->decoder()->GetGLContext()->IsCurrent(NULL));
+ DCHECK(backbuffer_);
gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
@@ -448,56 +444,4 @@ void TextureImageTransportSurface::AttachBackTextureToFBO() {
#endif
}
-TextureDefinition* TextureImageTransportSurface::CreateTextureDefinition(
- gfx::Size size, int service_id) {
- TextureDefinition::LevelInfo info(
- GL_TEXTURE_2D, GL_RGBA, size.width(), size.height(), 1,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
-
- TextureDefinition::LevelInfos level_infos;
- level_infos.resize(1);
- level_infos[0].resize(1);
- level_infos[0][0] = info;
- return new TextureDefinition(
- GL_TEXTURE_2D,
- service_id,
- GL_LINEAR,
- GL_LINEAR,
- GL_CLAMP_TO_EDGE,
- GL_CLAMP_TO_EDGE,
- GL_NONE,
- true,
- false,
- level_infos);
-}
-
-void TextureImageTransportSurface::ConsumeTexture() {
- DCHECK(!backbuffer_->service_id());
-
- backbuffer_.reset(mailbox_manager_->ConsumeTexture(
- GL_TEXTURE_2D, mailbox_name_));
- if (!backbuffer_) {
- mailbox_name_ = MailboxName();
- backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0));
- }
-}
-
-void TextureImageTransportSurface::ProduceTexture() {
- DCHECK(backbuffer_->service_id());
- DCHECK(!backbuffer_size().IsEmpty());
-
- // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM()
- // when the renderer context group goes away before the RWHV handles a pending
- // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK
- // at which point we consume the correct texture back.
- bool success = mailbox_manager_->ProduceTexture(
- GL_TEXTURE_2D,
- mailbox_name_,
- backbuffer_.release(),
- NULL);
- DCHECK(success);
- mailbox_name_ = MailboxName();
- backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0));
-}
-
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698