| 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
|
|
|