From 5e5a99fa374d4b83e548ada8c76fa191a27e4b51 Mon Sep 17 00:00:00 2001 From: Mansoor Chishtie Date: Tue, 27 May 2014 19:35:12 -0500 Subject: 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 --- src/core/chromium_gpu_helper.cpp | 18 ++++++++++++++++++ src/core/chromium_gpu_helper.h | 16 ++++++++++++++++ src/core/delegated_frame_node.cpp | 26 +++++++++++++++++++++++++- src/core/stream_video_node.cpp | 26 +++++++++++++++----------- src/core/stream_video_node.h | 3 ++- 5 files changed, 76 insertions(+), 13 deletions(-) (limited to 'src/core') 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 // 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(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 // 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 findRenderPassTexture(const cc::RenderPass::Id &id, const QList > &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(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(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; -- cgit v1.2.3