summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMansoor Chishtie <mchishtie@blackberry.com>2014-05-27 19:35:12 -0500
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-06-02 20:49:50 +0200
commit5e5a99fa374d4b83e548ada8c76fa191a27e4b51 (patch)
tree9ed2144ddc001fbbb7ca1964772b78bae015a61e
parent65bf1a1334acce38983896241d3b211e1fa4659a (diff)
Support EGLStream video streaming on QNX platform
On QNX platform, we implement video streaming via OpenGL EGLStream streams. Changes were added to StreamVideo class to support EGLStream objects. For non-QNX platforms, we kept the StreamVideoNode class unchanged - assuming other platforms will continue to support streaming via EGLImage objects. On QNX, cc::StreamVideoDrawQuad contains an external OES texture that is associated with an EGLStream. Before we draw with that texture, an 'acquire' is performed to grab latest video frame. See EGL_KHR_stream specs from Khronos. Change-Id: Ia3fe25e9047f475594a55591e3e11caa0eab1e6a Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
-rw-r--r--src/core/chromium_gpu_helper.cpp18
-rw-r--r--src/core/chromium_gpu_helper.h16
-rw-r--r--src/core/delegated_frame_node.cpp26
-rw-r--r--src/core/stream_video_node.cpp26
-rw-r--r--src/core/stream_video_node.h3
5 files changed, 76 insertions, 13 deletions
diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp
index 8782f5d98..663b1ec17 100644
--- a/src/core/chromium_gpu_helper.cpp
+++ b/src/core/chromium_gpu_helper.cpp
@@ -51,6 +51,12 @@
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
+#include <QtGlobal> // We need this for the Q_OS_QNX define.
+
+#ifdef Q_OS_QNX
+#include "content/common/gpu/stream_texture_qnx.h"
+#endif
+
static void addSyncPointCallbackDelegate(content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback)
{
syncPointManager->AddSyncPointCallback(sync_point, callback);
@@ -112,3 +118,15 @@ unsigned int service_id(gpu::gles2::Texture *tex)
{
return tex->service_id();
}
+
+#ifdef Q_OS_QNX
+EGLStreamData eglstream_connect_consumer(gpu::gles2::Texture *tex)
+{
+ EGLStreamData egl_stream;
+ content::StreamTexture* image = static_cast<content::StreamTexture *>(tex->GetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0));
+ if (image) {
+ image->ConnectConsumerIfNeeded(&egl_stream.egl_display, &egl_stream.egl_str_handle);
+ }
+ return egl_stream;
+}
+#endif
diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h
index 285554cc9..00ed5f295 100644
--- a/src/core/chromium_gpu_helper.h
+++ b/src/core/chromium_gpu_helper.h
@@ -42,6 +42,8 @@
#ifndef CHROMIUM_GPU_HELPER_H
#define CHROMIUM_GPU_HELPER_H
+#include <QtGlobal> // We need this for the Q_OS_QNX define.
+
#include "base/callback.h"
namespace base {
@@ -100,4 +102,18 @@ void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content:
gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::gles2::MailboxName& name);
unsigned int service_id(gpu::gles2::Texture *tex);
+#ifdef Q_OS_QNX
+typedef void* EGLDisplay;
+typedef void* EGLStreamKHR;
+
+struct EGLStreamData {
+ EGLDisplay egl_display;
+ EGLStreamKHR egl_str_handle;
+
+ EGLStreamData(): egl_display(NULL), egl_str_handle(NULL) {}
+};
+
+EGLStreamData eglstream_connect_consumer(gpu::gles2::Texture *tex);
+#endif
+
#endif // CHROMIUM_GPU_HELPER_H
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index fd073ad3a..09cc540b7 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -138,6 +138,9 @@ private:
bool m_hasAlpha;
GLenum m_target;
int m_importCount;
+#ifdef Q_OS_QNX
+ EGLStreamData m_eglStreamData;
+#endif
};
static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
@@ -343,6 +346,20 @@ MailboxTexture::MailboxTexture(const cc::TransferableResource &resource)
void MailboxTexture::bind()
{
glBindTexture(m_target, m_textureId);
+#ifdef Q_OS_QNX
+ if (m_target == GL_TEXTURE_EXTERNAL_OES) {
+ static bool resolved = false;
+ static PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquire = 0;
+
+ if (!resolved) {
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ eglStreamConsumerAcquire = (PFNEGLSTREAMCONSUMERACQUIREKHRPROC)context->getProcAddress("eglStreamConsumerAcquireKHR");
+ resolved = true;
+ }
+ if (eglStreamConsumerAcquire)
+ eglStreamConsumerAcquire(m_eglStreamData.egl_display, m_eglStreamData.egl_str_handle);
+ }
+#endif
}
void MailboxTexture::setTarget(GLenum target)
@@ -371,8 +388,14 @@ void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager)
gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, m_target, *reinterpret_cast<const gpu::gles2::MailboxName*>(m_resource.mailbox.name));
// The texture might already have been deleted (e.g. when navigating away from a page).
- if (tex)
+ if (tex) {
m_textureId = service_id(tex);
+#ifdef Q_OS_QNX
+ if (m_target == GL_TEXTURE_EXTERNAL_OES) {
+ m_eglStreamData = eglstream_connect_consumer(tex);
+ }
+#endif
+ }
}
DelegatedFrameNode::DelegatedFrameNode(QSGRenderContext *sgRenderContext)
@@ -595,6 +618,7 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour
StreamVideoNode *svideoNode = new StreamVideoNode(texture.data());
svideoNode->setRect(toQt(squad->rect));
+ svideoNode->setTextureMatrix(toQt(squad->matrix.matrix()));
currentLayerChain->appendChildNode(svideoNode);
break;
#endif
diff --git a/src/core/stream_video_node.cpp b/src/core/stream_video_node.cpp
index c46b14f1c..a8d1f6fbe 100644
--- a/src/core/stream_video_node.cpp
+++ b/src/core/stream_video_node.cpp
@@ -47,7 +47,7 @@ class StreamVideoMaterialShader : public QSGMaterialShader
public:
virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
- virtual char const *const *attributeNames() const {
+ virtual char const *const *attributeNames() const Q_DECL_OVERRIDE {
static const char *names[] = {
"a_position",
"a_texCoord",
@@ -57,21 +57,22 @@ public:
}
protected:
- virtual const char *vertexShader() const {
+ virtual const char *vertexShader() const Q_DECL_OVERRIDE {
// Keep in sync with cc::VertexShaderVideoTransform
const char *shader =
"attribute highp vec4 a_position;\n"
"attribute mediump vec2 a_texCoord;\n"
"uniform highp mat4 matrix;\n"
+ "uniform highp mat4 texMatrix;\n"
"varying mediump vec2 v_texCoord;\n"
"void main() {\n"
" gl_Position = matrix * a_position;\n"
- " v_texCoord = a_texCoord;\n"
+ " v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;\n"
"}";
return shader;
}
- virtual const char *fragmentShader() const {
+ virtual const char *fragmentShader() const Q_DECL_OVERRIDE {
// Keep in sync with cc::FragmentShaderRGBATexAlpha
static const char *shader =
"#extension GL_OES_EGL_image_external : require\n"
@@ -79,7 +80,7 @@ protected:
"uniform samplerExternalOES s_texture;\n"
"uniform lowp float alpha;\n"
"void main() {\n"
- " vec4 texColor = texture2D(s_texture, v_texCoord);\n"
+ " lowp vec4 texColor = texture2D(s_texture, v_texCoord);\n"
" gl_FragColor = texColor * alpha;\n"
"}";
return shader;
@@ -88,10 +89,12 @@ protected:
virtual void initialize() {
m_id_matrix = program()->uniformLocation("matrix");
m_id_sTexture = program()->uniformLocation("s_texture");
+ m_id_texMatrix = program()->uniformLocation("texMatrix");
m_id_opacity = program()->uniformLocation("alpha");
}
int m_id_matrix;
+ int m_id_texMatrix;
int m_id_sTexture;
int m_id_opacity;
};
@@ -110,6 +113,8 @@ void StreamVideoMaterialShader::updateState(const RenderState &state, QSGMateria
if (state.isMatrixDirty())
program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+
+ program()->setUniformValue(m_id_texMatrix, mat->m_texMatrix);
}
StreamVideoMaterial::StreamVideoMaterial(QSGTexture *texture)
@@ -122,12 +127,6 @@ QSGMaterialShader *StreamVideoMaterial::createShader() const
return new StreamVideoMaterialShader;
}
-int StreamVideoMaterial::compare(const QSGMaterial *other) const
-{
- const StreamVideoMaterial *m = static_cast<const StreamVideoMaterial *>(other);
- return (m_texture->textureId() - m->m_texture->textureId());
-}
-
StreamVideoNode::StreamVideoNode(QSGTexture *texture)
: m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
{
@@ -141,3 +140,8 @@ void StreamVideoNode::setRect(const QRectF &rect)
{
QSGGeometry::updateTexturedRectGeometry(geometry(), rect, QRectF(0, 0, 1, 1));
}
+
+void StreamVideoNode::setTextureMatrix(const QMatrix4x4 &matrix)
+{
+ m_material->m_texMatrix = matrix;
+}
diff --git a/src/core/stream_video_node.h b/src/core/stream_video_node.h
index cf16f10d4..fdfa72938 100644
--- a/src/core/stream_video_node.h
+++ b/src/core/stream_video_node.h
@@ -63,9 +63,9 @@ public:
}
virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
QSGTexture *m_texture;
+ QMatrix4x4 m_texMatrix;
};
class StreamVideoNode : public QSGGeometryNode
@@ -73,6 +73,7 @@ class StreamVideoNode : public QSGGeometryNode
public:
StreamVideoNode(QSGTexture *texture);
void setRect(const QRectF &rect);
+ void setTextureMatrix(const QMatrix4x4 &matrix);
private:
QSGGeometry m_geometry;