diff options
9 files changed, 74 insertions, 24 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 5a0ba1111..7c89b5e44 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -104,15 +104,15 @@ private: class ResourceHolder { public: ResourceHolder(const cc::TransferableResource &resource); - ~ResourceHolder() { delete m_texture; } - MailboxTexture *texture() const { return m_texture; } + QSharedPointer<QSGTexture> initTexture(bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); + QSGTexture *texture() const { return m_texture.data(); } cc::TransferableResource &transferableResource() { return m_resource; } cc::ReturnedResource returnResource(); void incImportCount() { ++m_importCount; } - bool needsToFetch() const { return !m_texture->textureId(); } + bool needsToFetch() const { return !m_resource.is_software && m_texture && !m_texture.data()->textureId(); } private: - MailboxTexture *m_texture; + QWeakPointer<QSGTexture> m_texture; cc::TransferableResource m_resource; int m_importCount; }; @@ -321,12 +321,38 @@ void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager) } ResourceHolder::ResourceHolder(const cc::TransferableResource &resource) - : m_texture(new MailboxTexture(resource.mailbox_holder, toQt(resource.size))) - , m_resource(resource) + : m_resource(resource) , m_importCount(1) { } +QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, RenderWidgetHostViewQtDelegate *apiDelegate) +{ + QSharedPointer<QSGTexture> texture = m_texture.toStrongRef(); + if (!texture) { + if (m_resource.is_software) { + Q_ASSERT(apiDelegate); + scoped_ptr<cc::SharedBitmap> sharedBitmap = content::HostSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox); + // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending + // to draw it but Chromium keeps this information in the quads. + // The input format is currently always Format_ARGB32_Premultiplied, so assume that all + // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion + // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to + // return false. + QImage::Format format = quadNeedsBlending ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; + QImage image(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format); + texture.reset(apiDelegate->createTextureFromImage(image.copy())); + } else { + texture.reset(new MailboxTexture(m_resource.mailbox_holder, toQt(m_resource.size))); + static_cast<MailboxTexture *>(texture.data())->setHasAlphaChannel(quadNeedsBlending); + } + m_texture = texture; + } + // All quads using a resource should request the same blending state. + Q_ASSERT(texture->hasAlphaChannel() || !quadNeedsBlending); + return texture; +} + cc::ReturnedResource ResourceHolder::returnResource() { cc::ReturnedResource returned; @@ -527,22 +553,12 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } case cc::DrawQuad::TEXTURE_CONTENT: { const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad); ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); - MailboxTexture *texture = resource->texture(); - - // 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(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); - textureNode->setTexture(texture); + textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); currentLayerChain->appendChildNode(textureNode); break; } case cc::DrawQuad::SOLID_COLOR: { @@ -585,16 +601,12 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } case cc::DrawQuad::TILED_CONTENT: { const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad); ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); - MailboxTexture *texture = resource->texture(); - - 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->setSourceRect(toQt(tquad->tex_coord_rect)); textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); - textureNode->setTexture(texture); + textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); currentLayerChain->appendChildNode(textureNode); break; } case cc::DrawQuad::YUV_VIDEO_CONTENT: { @@ -607,7 +619,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, if (vquad->a_plane_resource_id) aResource = findAndHoldResource(vquad->a_plane_resource_id, resourceCandidates); - YUVVideoNode *videoNode = new YUVVideoNode(yResource->texture(), uResource->texture(), vResource->texture(), aResource ? aResource->texture() : 0, toQt(vquad->tex_coord_rect)); + YUVVideoNode *videoNode = new YUVVideoNode( + initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()), + aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0, toQt(vquad->tex_coord_rect)); videoNode->setRect(toQt(quad->rect)); currentLayerChain->appendChildNode(videoNode); break; @@ -615,7 +631,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } case cc::DrawQuad::STREAM_VIDEO_CONTENT: { const cc::StreamVideoDrawQuad *squad = cc::StreamVideoDrawQuad::MaterialCast(quad); ResourceHolder *resource = findAndHoldResource(squad->resource_id, resourceCandidates); - MailboxTexture *texture = resource->texture(); + MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending())); texture->setTarget(GL_TEXTURE_EXTERNAL_OES); // since this is not default TEXTURE_2D type StreamVideoNode *svideoNode = new StreamVideoNode(texture); @@ -645,6 +661,16 @@ ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHa return resource.data(); } +QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate) +{ + // QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree, + // so we can't store them with the ResourceHolder in m_chromiumCompositorData. + // Hold them through a QSharedPointer solely on the root DelegatedFrameNode of the web view + // and access them through a QWeakPointer from the resource holder to find them later. + m_sgObjects.textureStrongRefs.append(resource->initTexture(quadIsAllOpaque, apiDelegate)); + return m_sgObjects.textureStrongRefs.last().data(); +} + void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch) { // Fetch texture IDs from the mailboxes while we're on the GPU thread, where the MailboxManager lives. diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index 8fad76cb3..b866c94b4 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -84,10 +84,13 @@ private: static void syncPointRetired(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch); ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); + QSGTexture *initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); + QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; struct SGObjects { QList<QPair<cc::RenderPass::Id, QSharedPointer<QSGLayer> > > renderPassLayers; QList<QSharedPointer<QSGRootNode> > renderPassRootNodes; + QList<QSharedPointer<QSGTexture> > textureStrongRefs; } m_sgObjects; int m_numPendingSyncPoints; QMap<uint32, gfx::TransferableFence> m_mailboxGLFences; diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index 7b9a3e16c..0fb3d1d5f 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -49,6 +49,7 @@ class QPainter; class QSGImageNode; class QSGLayer; class QSGNode; +class QSGTexture; class QVariant; class QWindow; class QInputMethodEvent; @@ -80,6 +81,7 @@ public: virtual void hide() = 0; virtual bool isVisible() const = 0; virtual QWindow* window() const = 0; + virtual QSGTexture *createTextureFromImage(const QImage &) = 0; virtual QSGLayer *createLayer() = 0; virtual QSGImageNode *createImageNode() = 0; virtual void update() = 0; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index b09de3fcb..209b5fbea 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -44,6 +44,7 @@ #include <QVariant> #include <QWindow> #include <private/qquickwindow_p.h> +#include <private/qsgcontext_p.h> RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) : m_client(client) @@ -124,6 +125,11 @@ QWindow* RenderWidgetHostViewQtDelegateQuick::window() const return QQuickItem::window(); } +QSGTexture *RenderWidgetHostViewQtDelegateQuick::createTextureFromImage(const QImage &image) +{ + return QQuickItem::window()->createTextureFromImage(image, QQuickWindow::TextureCanUseAtlas); +} + QSGLayer *RenderWidgetHostViewQtDelegateQuick::createLayer() { QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h index 1d2d8a92e..112d97377 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h @@ -57,6 +57,7 @@ public: virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp index 46db28768..6a0e416e0 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -95,6 +95,11 @@ QWindow *RenderWidgetHostViewQtDelegateQuickWindow::window() const return const_cast<RenderWidgetHostViewQtDelegateQuickWindow*>(this); } +QSGTexture *RenderWidgetHostViewQtDelegateQuickWindow::createTextureFromImage(const QImage &image) +{ + return m_realDelegate->createTextureFromImage(image); +} + QSGLayer *RenderWidgetHostViewQtDelegateQuickWindow::createLayer() { return m_realDelegate->createLayer(); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h index 95e636c4c..e6c793143 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h @@ -60,6 +60,7 @@ public: virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index 811cce90f..e49259a59 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -145,6 +145,11 @@ QWindow* RenderWidgetHostViewQtDelegateWidget::window() const return root ? root->windowHandle() : 0; } +QSGTexture *RenderWidgetHostViewQtDelegateWidget::createTextureFromImage(const QImage &image) +{ + return m_sgEngine->createTextureFromImage(image, QSGEngine::TextureCanUseAtlas); +} + QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer() { QSGEnginePrivate *enginePrivate = QSGEnginePrivate::get(m_sgEngine.data()); diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h index 4f4e7bff1..670e22f31 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -65,6 +65,7 @@ public: virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; |