summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/delegated_frame_node.cpp74
-rw-r--r--src/core/delegated_frame_node.h3
-rw-r--r--src/core/render_widget_host_view_qt_delegate.h2
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.cpp6
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.h1
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp5
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.h1
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp5
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h1
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;