summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2013-11-11 13:03:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-15 13:49:20 +0100
commitf5be472e0ba4aa19d0c0f91a848dfa5be9ebaa3b (patch)
tree5149f8bebca3b5ec1a610def1f991fff7f3453a4
parent388b272d32bca3c9e46d571a7a4a94bbbc2b11dc (diff)
Delegated renderer: Fix remaining synchronization issues.
This fixes two issues: - The onFrameSwapped slot was connected with a QueuedConnection, this means that any previous frame triggered by Qt could be queued right before updatePaintNode is called, and be handled right after, thus picking our m_pendingAckFrameData and sending the Ack before this frame was actually swapped. - For cases where Qt triggers a new frame (e.g. typing text in a QtQuick text area) it would be possible that it starts rendering before m_pendingUpdateFrameData had been set, which would render the old frame while Chromium might be in the middle of rendering the new one on the same resources, or destroying them. The solution is grossly to do proper used resource reporting to the child compositors via cc::CompositorFrameAck::resources. We previously released all resources on every frame, and Chromium would resend back to us the ones that could be reused without change. We now instead only return unused resources, but this also means that we have to keep track of used resources ourselves. cc::DelegatedFrameData::resource_list only contain new resources to be added to the scene and we keep a deep copy of the cc::TransferableResource into our MailboxTextures. A few other changes that come with this: - A few null-checks can now be removed since we can better rely on the integrity of the information passed through DelegatedFrameData. - Since we can now prevent used resources from being destroyed while we use them, trigger a frame Ack immediately after updatePaintNode instead of waiting until the buffer is swapped, like ui::Compositor does. - MailboxTexture is now more autonomous, but still require some information from quads. Mark them as not containing alpha by default and fetch this information from quads when encountered. Change-Id: Ice235f3a98a179c87eec7fbcb9880e34b0ed1e73 Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
-rw-r--r--lib/delegated_frame_node.cpp161
-rw-r--r--lib/delegated_frame_node.h3
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.cpp20
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.h6
-rw-r--r--lib/render_widget_host_view_qt.cpp42
-rw-r--r--lib/render_widget_host_view_qt.h7
-rw-r--r--lib/render_widget_host_view_qt_delegate.h1
7 files changed, 103 insertions, 137 deletions
diff --git a/lib/delegated_frame_node.cpp b/lib/delegated_frame_node.cpp
index ad4bb7016..0c50776e0 100644
--- a/lib/delegated_frame_node.cpp
+++ b/lib/delegated_frame_node.cpp
@@ -39,10 +39,6 @@
**
****************************************************************************/
-#include "delegated_frame_node.h"
-
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
-
// On Mac we need to reset this define in order to prevent definition
// of "check" macros etc. The "check" macro collides with a member function name in QtQuick.
// See AssertMacros.h in the Mac SDK.
@@ -52,6 +48,9 @@
#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
#endif
+#include "delegated_frame_node.h"
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
#include "chromium_gpu_helper.h"
#include "type_conversion.h"
#include "yuv_video_node.h"
@@ -108,40 +107,26 @@ private:
class MailboxTexture : public QSGTexture {
public:
- MailboxTexture(const cc::TransferableResource *resource, bool hasAlpha);
+ MailboxTexture(const cc::TransferableResource &resource);
virtual int textureId() const Q_DECL_OVERRIDE { return m_textureId; }
void setTextureSize(const QSize& size) { m_textureSize = size; }
virtual QSize textureSize() const Q_DECL_OVERRIDE { return m_textureSize; }
virtual bool hasAlphaChannel() const Q_DECL_OVERRIDE { return m_hasAlpha; }
+ void setHasAlphaChannel(bool hasAlpha) { m_hasAlpha = hasAlpha; }
virtual bool hasMipmaps() const Q_DECL_OVERRIDE { return false; }
virtual void bind() Q_DECL_OVERRIDE;
- bool needsToFetch() const { return m_resource; }
- const cc::TransferableResource *resource() const { return m_resource; }
+ bool needsToFetch() const { return !m_textureId; }
+ cc::TransferableResource &resource() { return m_resource; }
void fetchTexture(gpu::gles2::MailboxManager *mailboxManager);
private:
- // This is just a pointer to the cc::DelegatedFrameData. It has to be held until DelegatedFrameNode::preprocess is done.
- const cc::TransferableResource *m_resource;
+ cc::TransferableResource m_resource;
int m_textureId;
QSize m_textureSize;
bool m_hasAlpha;
};
-static const cc::TransferableResource *findResource(const cc::TransferableResourceArray &array, unsigned id)
-{
- // A 0 ID means that there is no resource.
- if (!id)
- return 0;
-
- for (unsigned i = 0; i < array.size(); ++i) {
- const cc::TransferableResource &res = array.at(i);
- if (res.id == id)
- return &res;
- }
- return 0;
-}
-
static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
{
Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, list)
@@ -267,11 +252,11 @@ void RenderPassTexture::grab()
m_context->renderNextFrame(m_renderer.data(), m_fbo->handle());
}
-MailboxTexture::MailboxTexture(const cc::TransferableResource *resource, bool hasAlpha)
+MailboxTexture::MailboxTexture(const cc::TransferableResource &resource)
: m_resource(resource)
, m_textureId(0)
- , m_textureSize(toQt(resource->size))
- , m_hasAlpha(hasAlpha)
+ , m_textureSize(toQt(resource.size))
+ , m_hasAlpha(false)
{
}
@@ -282,16 +267,11 @@ void MailboxTexture::bind()
void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager)
{
- Q_ASSERT(m_resource);
- gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, GL_TEXTURE_2D, *reinterpret_cast<const gpu::gles2::MailboxName*>(m_resource->mailbox.name));
+ gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, GL_TEXTURE_2D, *reinterpret_cast<const gpu::gles2::MailboxName*>(m_resource.mailbox.name));
- // The texture might already have been deleted.
- // FIXME: We might be able to avoid this check with better synchronization.
+ // The texture might already have been deleted (e.g. when navigating away from a page).
if (tex)
m_textureId = service_id(tex);
-
- // We do not need to fetch this texture again.
- m_resource = 0;
}
DelegatedFrameNode::DelegatedFrameNode(QQuickWindow *window)
@@ -322,7 +302,7 @@ void DelegatedFrameNode::preprocess()
Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) {
m_numPendingSyncPoints++;
- AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource()->sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch));
+ AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource().sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch));
}
m_mailboxesFetchedWaitCond.wait(&m_mutex);
@@ -333,13 +313,22 @@ void DelegatedFrameNode::preprocess()
renderPass->grab();
}
-void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
+void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData, cc::TransferableResourceArray *resourcesToRelease)
{
// Keep the old texture lists around to find the ones we can re-use.
QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures;
m_renderPassTextures.swap(oldRenderPassTextures);
- QMap<int, QSharedPointer<MailboxTexture> > oldMailboxTextures;
- m_mailboxTextures.swap(oldMailboxTextures);
+ QMap<int, QSharedPointer<MailboxTexture> > mailboxTextureCandidates;
+ m_mailboxTextures.swap(mailboxTextureCandidates);
+
+ // A frame's resource_list only contains the new resources to be added to the scene. Quads can
+ // still reference resources that were added in previous frames. Add them to the list of
+ // candidates to be picked up by quads, it's then our responsibility to return unused resources
+ // to the producing child compositor.
+ for (unsigned i = 0; i < frameData->resource_list.size(); ++i) {
+ const cc::TransferableResource &res = frameData->resource_list.at(i);
+ mailboxTextureCandidates[res.id] = QSharedPointer<MailboxTexture>(new MailboxTexture(res));
+ }
// The RenderPasses list is actually a tree where a parent RenderPass is connected
// to its dependencies through a RenderPass::Id reference in one or more RenderPassQuads.
@@ -390,48 +379,50 @@ void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
case cc::DrawQuad::RENDER_PASS: {
const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad);
QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, m_renderPassTextures).data();
- if (texture) {
- QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
- textureNode->setRect(toQt(quad->rect));
- textureNode->setTexture(texture);
- currentLayerChain->appendChildNode(textureNode);
- } else {
- qWarning("Unknown RenderPass layer: Id %d", renderPassQuad->render_pass_id.layer_id);
+ // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes.
+ if (!texture)
continue;
- }
+
+ QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
+ textureNode->setRect(toQt(quad->rect));
+ textureNode->setTexture(texture);
+ currentLayerChain->appendChildNode(textureNode);
break;
} case cc::DrawQuad::TEXTURE_CONTENT: {
const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad);
- const cc::TransferableResource *res = findResource(frameData->resource_list, tquad->resource_id);
-
- // See if we already have a texture for this resource ID. The ID changes when the contents is updated,
- // even if the GL texture ID is the same as a previous resource.
- // Reusing a texture only saves us the sync point waiting and mailbox fetching.
- QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[res->id] = oldMailboxTextures.value(res->id);
- if (!texture) {
- texture = QSharedPointer<MailboxTexture>(new MailboxTexture(res, quad->ShouldDrawWithBlending()));
- // TransferableResource::size isn't always set properly for TextureDrawQuads, use the size of its DrawQuad::rect instead.
- texture->setTextureSize(toQt(quad->rect.size()));
- }
+ QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[tquad->resource_id] = mailboxTextureCandidates.take(tquad->resource_id);
+ Q_ASSERT(texture);
+
+ // FIXME: TransferableResource::size isn't always set properly for TextureDrawQuads, use the size of its DrawQuad::rect instead.
+ texture->setTextureSize(toQt(quad->rect.size()));
+
+ // TransferableResource::format seems to always be GL_BGRA even though it might not
+ // contain any pixel with alpha < 1.0. The information about if they need blending
+ // for the contents itself is actually stored in quads.
+ // Tell the scene graph to enable blending for a texture only when at least one quad asks for it.
+ // Do not rely on DrawQuad::ShouldDrawWithBlending() since the shared_quad_state->opacity
+ // case will be handled by QtQuick by fetching this information from QSGOpacityNodes.
+ if (!quad->visible_rect.IsEmpty() && !quad->opaque_rect.Contains(quad->visible_rect))
+ texture->setHasAlphaChannel(true);
QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
textureNode->setTextureCoordinatesTransform(tquad->flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
textureNode->setRect(toQt(quad->rect));
- textureNode->setFiltering(res->filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
+ textureNode->setFiltering(texture->resource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
textureNode->setTexture(texture.data());
currentLayerChain->appendChildNode(textureNode);
break;
} case cc::DrawQuad::TILED_CONTENT: {
const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad);
- const cc::TransferableResource *res = findResource(frameData->resource_list, tquad->resource_id);
+ QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[tquad->resource_id] = mailboxTextureCandidates.take(tquad->resource_id);
+ Q_ASSERT(texture);
- QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[res->id] = oldMailboxTextures.value(res->id);
- if (!texture)
- texture = QSharedPointer<MailboxTexture>(new MailboxTexture(res, quad->ShouldDrawWithBlending()));
+ if (!quad->visible_rect.IsEmpty() && !quad->opaque_rect.Contains(quad->visible_rect))
+ texture->setHasAlphaChannel(true);
QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
textureNode->setRect(toQt(quad->rect));
- textureNode->setFiltering(res->filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
+ textureNode->setFiltering(texture->resource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
textureNode->setTexture(texture.data());
// FIXME: Find out if we can implement a QSGSimpleTextureNode::setSourceRect instead of this hack.
@@ -441,29 +432,16 @@ void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
break;
} case cc::DrawQuad::YUV_VIDEO_CONTENT: {
const cc::YUVVideoDrawQuad *vquad = cc::YUVVideoDrawQuad::MaterialCast(quad);
- const cc::TransferableResource *yRes = findResource(frameData->resource_list, vquad->y_plane_resource_id);
- const cc::TransferableResource *uRes = findResource(frameData->resource_list, vquad->u_plane_resource_id);
- const cc::TransferableResource *vRes = findResource(frameData->resource_list, vquad->v_plane_resource_id);
- const cc::TransferableResource *aRes = findResource(frameData->resource_list, vquad->a_plane_resource_id);
-
- QSharedPointer<MailboxTexture> &yTexture = m_mailboxTextures[yRes->id] = oldMailboxTextures.value(yRes->id);
- QSharedPointer<MailboxTexture> &uTexture = m_mailboxTextures[uRes->id] = oldMailboxTextures.value(uRes->id);
- QSharedPointer<MailboxTexture> &vTexture = m_mailboxTextures[vRes->id] = oldMailboxTextures.value(vRes->id);
- if (!yTexture) {
- yTexture = QSharedPointer<MailboxTexture>(new MailboxTexture(yRes, /* hasAlpha */ false));
- uTexture = QSharedPointer<MailboxTexture>(new MailboxTexture(uRes, /* hasAlpha */ false));
- vTexture = QSharedPointer<MailboxTexture>(new MailboxTexture(vRes, /* hasAlpha */ false));
- }
-
- // Do not use a reference for aTexture since we don't necessarily want an entry for it in m_mailboxTextures.
+ QSharedPointer<MailboxTexture> &yTexture = m_mailboxTextures[vquad->y_plane_resource_id] = mailboxTextureCandidates.take(vquad->y_plane_resource_id);
+ QSharedPointer<MailboxTexture> &uTexture = m_mailboxTextures[vquad->u_plane_resource_id] = mailboxTextureCandidates.take(vquad->u_plane_resource_id);
+ QSharedPointer<MailboxTexture> &vTexture = m_mailboxTextures[vquad->v_plane_resource_id] = mailboxTextureCandidates.take(vquad->v_plane_resource_id);
+ Q_ASSERT(yTexture && uTexture && vTexture);
+
+ // Do not use a reference for this one, it might be null.
QSharedPointer<MailboxTexture> aTexture;
- // This currently requires --enable-vp8-alpha-playback to apply.
- if (aRes) {
- aTexture = oldMailboxTextures.value(aRes->id);
- if (!aTexture)
- aTexture = QSharedPointer<MailboxTexture>(new MailboxTexture(aRes, /* hasAlpha */ false));
- m_mailboxTextures[aRes->id] = aTexture;
- }
+ // This currently requires --enable-vp8-alpha-playback and needs a video with alpha data to be triggered.
+ if (vquad->a_plane_resource_id)
+ aTexture = m_mailboxTextures[vquad->a_plane_resource_id] = mailboxTextureCandidates.take(vquad->a_plane_resource_id);
YUVVideoNode *videoNode = new YUVVideoNode(yTexture.data(), uTexture.data(), vTexture.data(), aTexture.data(), toQt(vquad->tex_scale));
videoNode->setRect(toQt(quad->rect));
@@ -471,10 +449,23 @@ void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
break;
} default:
qWarning("Unimplemented quad material: %d", quad->material);
- continue;
}
}
}
+
+ // Send resources of remaining candidates back to the child compositors so that they can be freed or reused.
+ Q_FOREACH (const QSharedPointer<MailboxTexture> &mailboxTexture, mailboxTextureCandidates.values()) {
+ // The ResourceProvider ensures that the resource isn't used by the parent compositor's GL
+ // context in the GPU process by inserting a sync point to be waited for by the child
+ // compositor's GL context. We don't need this since we are triggering the delegated frame
+ // ack directly from our rendering thread. At this point (in updatePaintNode) we know that
+ // a frame that was compositing any of those resources has already been swapped.
+ // Save a bit of overhead by resetting the sync point that has initially been put there
+ // for us (mainly to clean the output of --enable-gpu-service-logging).
+ mailboxTexture->resource().sync_point = 0;
+
+ resourcesToRelease->push_back(mailboxTexture->resource());
+ }
}
void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch)
diff --git a/lib/delegated_frame_node.h b/lib/delegated_frame_node.h
index 0b6657e98..b73370874 100644
--- a/lib/delegated_frame_node.h
+++ b/lib/delegated_frame_node.h
@@ -42,6 +42,7 @@
#ifndef DELEGATED_FRAME_NODE_H
#define DELEGATED_FRAME_NODE_H
+#include "cc/resources/transferable_resource.h"
#include <QMutex>
#include <QSGNode>
#include <QSharedPointer>
@@ -65,7 +66,7 @@ public:
DelegatedFrameNode(QQuickWindow *window);
~DelegatedFrameNode();
void preprocess();
- void commit(cc::DelegatedFrameData *frameData);
+ void commit(cc::DelegatedFrameData *frameData, cc::TransferableResourceArray *resourcesToRelease);
private:
QQuickWindow *m_window;
diff --git a/lib/quick/render_widget_host_view_qt_delegate_quick.cpp b/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
index 2d90e772b..dbd1ea911 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
@@ -58,32 +58,12 @@ void RenderWidgetHostViewQtDelegateQuick::update(const QRect&)
QQuickItem::update();
}
-void RenderWidgetHostViewQtDelegateQuick::itemChange(ItemChange change, const ItemChangeData &value)
-{
- QQuickItem::itemChange(change, value);
- if (change == QQuickItem::ItemSceneChange && value.window)
- connect(value.window, SIGNAL(frameSwapped()), SLOT(onFrameSwapped()));
-}
-
QSGNode *RenderWidgetHostViewQtDelegateQuick::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
return m_client->updatePaintNode(oldNode, QQuickItem::window());
}
-
-void RenderWidgetHostViewQtDelegateQuick::releaseResources()
-{
- // This is the only callback we get before being removed from a window while we still know it.
- QQuickItem::window()->disconnect(this);
-}
-
-void RenderWidgetHostViewQtDelegateQuick::onFrameSwapped()
-{
- m_client->sendDelegatedFrameAck();
-}
-
#endif // QT_VERSION
-
RenderWidgetHostViewQtDelegateQuickPainted::RenderWidgetHostViewQtDelegateQuickPainted(RenderWidgetHostViewQtDelegateClient *client, QQuickItem *parent)
: RenderWidgetHostViewQtDelegateQuickBase<QQuickPaintedItem>(client, parent)
{
diff --git a/lib/quick/render_widget_host_view_qt_delegate_quick.h b/lib/quick/render_widget_host_view_qt_delegate_quick.h
index 5c96f4832..64e84cd44 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.h
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.h
@@ -215,13 +215,7 @@ public:
virtual WId nativeWindowIdForCompositor() const Q_DECL_OVERRIDE;
virtual void update(const QRect& rect = QRect()) Q_DECL_OVERRIDE;
-
- virtual void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE;
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
- virtual void releaseResources() Q_DECL_OVERRIDE;
-
-public Q_SLOTS:
- void onFrameSwapped();
};
#endif // QT_VERSION
diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp
index 16adb5ec2..82d8e14bb 100644
--- a/lib/render_widget_host_view_qt.cpp
+++ b/lib/render_widget_host_view_qt.cpp
@@ -168,20 +168,6 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC
InitAsChild(0);
}
-void RenderWidgetHostViewQt::sendDelegatedFrameAck()
-{
- if (!m_pendingAckFrameData)
- return;
-
- cc::CompositorFrameAck ack;
- ack.resources = m_pendingAckFrameData->resource_list;
- content::RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- m_host->GetRoutingID(), m_pendingOutputSurfaceId,
- m_host->GetProcess()->GetID(), ack);
-
- m_pendingAckFrameData.reset();
-}
-
BackingStoreQt* RenderWidgetHostViewQt::GetBackingStore()
{
bool force_create = !m_host->empty();
@@ -593,9 +579,10 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&)
void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame)
{
+ Q_ASSERT(!m_pendingFrameData);
Q_ASSERT(frame->delegated_frame_data);
m_pendingOutputSurfaceId = output_surface_id;
- m_pendingUpdateFrameData = frame->delegated_frame_data.Pass();
+ m_pendingFrameData = frame->delegated_frame_data.Pass();
m_delegate->update();
}
@@ -651,19 +638,21 @@ void RenderWidgetHostViewQt::paint(QPainter *painter, const QRectF& boundingRect
QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode, QQuickWindow *window)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
- if (!m_pendingUpdateFrameData)
+ if (!m_pendingFrameData)
return oldNode;
DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode);
if (!frameNode)
frameNode = new DelegatedFrameNode(window);
- // Switch the frame from one pointer to the other to keep track of its state
- // to be able to update and then ack each frame only once.
- Q_ASSERT(!m_pendingAckFrameData);
- m_pendingAckFrameData.reset(m_pendingUpdateFrameData.release());
+ frameNode->commit(m_pendingFrameData.get(), &m_resourcesToRelease);
+ m_pendingFrameData.reset();
+
+ // This is possibly called from the Qt render thread, post the ack back to the UI
+ // to tell the child compositors to release resources and trigger a new frame.
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&RenderWidgetHostViewQt::sendDelegatedFrameAck, AsWeakPtr()));
- frameNode->commit(m_pendingAckFrameData.get());
return frameNode;
#else
return 0;
@@ -758,6 +747,17 @@ void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWit
}
}
+void RenderWidgetHostViewQt::sendDelegatedFrameAck()
+{
+ cc::CompositorFrameAck ack;
+ ack.resources = m_resourcesToRelease;
+ content::RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ m_host->GetRoutingID(), m_pendingOutputSurfaceId,
+ m_host->GetProcess()->GetID(), ack);
+
+ m_resourcesToRelease.clear();
+}
+
void RenderWidgetHostViewQt::Paint(const gfx::Rect& damage_rect)
{
QRect r(damage_rect.x(), damage_rect.y(), damage_rect.width(), damage_rect.height());
diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h
index eec96a12a..f9666f5bf 100644
--- a/lib/render_widget_host_view_qt.h
+++ b/lib/render_widget_host_view_qt.h
@@ -47,6 +47,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "cc/resources/transferable_resource.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/gestures/gesture_types.h"
@@ -167,7 +168,6 @@ public:
// Overridden from RenderWidgetHostViewQtDelegateClient.
virtual void paint(QPainter *, const QRectF& boundingRect) Q_DECL_OVERRIDE;
virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) Q_DECL_OVERRIDE;
- virtual void sendDelegatedFrameAck() Q_DECL_OVERRIDE;
virtual void fetchBackingStore() Q_DECL_OVERRIDE;
virtual void notifyResize() Q_DECL_OVERRIDE;
virtual bool forwardEvent(QEvent *) Q_DECL_OVERRIDE;
@@ -195,6 +195,7 @@ public:
#endif // defined(OS_MACOSX)
private:
+ void sendDelegatedFrameAck();
void Paint(const gfx::Rect& damage_rect);
void ProcessGestures(ui::GestureRecognizer::Gestures *gestures);
int GetMappedTouch(int qtTouchId);
@@ -209,9 +210,9 @@ private:
scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate;
BackingStoreQt *m_backingStore;
+ scoped_ptr<cc::DelegatedFrameData> m_pendingFrameData;
+ cc::TransferableResourceArray m_resourcesToRelease;
uint32 m_pendingOutputSurfaceId;
- scoped_ptr<cc::DelegatedFrameData> m_pendingUpdateFrameData;
- scoped_ptr<cc::DelegatedFrameData> m_pendingAckFrameData;
WebContentsAdapterClient *m_adapterClient;
MultipleMouseClickHelper m_clickHelper;
diff --git a/lib/render_widget_host_view_qt_delegate.h b/lib/render_widget_host_view_qt_delegate.h
index c541e36e7..2f1401b6d 100644
--- a/lib/render_widget_host_view_qt_delegate.h
+++ b/lib/render_widget_host_view_qt_delegate.h
@@ -64,7 +64,6 @@ public:
virtual ~RenderWidgetHostViewQtDelegateClient() { }
virtual void paint(QPainter *, const QRectF& boundingRect) = 0;
virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) = 0;
- virtual void sendDelegatedFrameAck() = 0;
virtual void fetchBackingStore() = 0;
virtual void notifyResize() = 0;
virtual bool forwardEvent(QEvent *) = 0;