GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext = 0) : m_display(0) , m_xPixmap(0) , m_glxPixmap(0) , m_glContext(0) , m_detachedContext(0) , m_detachedSurface(0) , m_textureIsYInverted(false) , m_hasAlpha(false) { GLXContext shareContextObject = 0; m_display = XOpenDisplay(0); #if PLATFORM(QT) if (shareContext) { #if 0 // This code path requires QXcbNativeInterface::nativeResourceForContext() which is not availble in Qt5 on the build bots yet. QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); shareContextObject = static_cast<GLXContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("glxcontext"), shareContext)); if (!shareContextObject) return; #else // This code path should be removed as soon as QXcbNativeInterface::nativeResourceForContext() can provide the GLXContext. QOpenGLContext* previousContext = QOpenGLContext::currentContext(); QSurface* previousSurface = previousContext->surface(); QSurface* currentSurface = shareContext->surface(); shareContext->makeCurrent(currentSurface); shareContextObject = glXGetCurrentContext(); previousContext->makeCurrent(previousSurface); #endif } #endif m_display = m_offScreenWindow.display(); int attributes[] = { GLX_LEVEL, 0, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, True, None }; int numReturned; m_fbConfigs = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &numReturned); // Create a GLX context for OpenGL rendering m_glContext = glXCreateNewContext(m_display, m_fbConfigs[0], GLX_RGBA_TYPE, shareContextObject, true); }
void GLWidget::makeObject() { static const int coords[6][4][3] = { { { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } }, { { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } }, { { +1, -1, +1 }, { +1, -1, -1 }, { +1, +1, -1 }, { +1, +1, +1 } }, { { -1, -1, -1 }, { -1, -1, +1 }, { -1, +1, +1 }, { -1, +1, -1 } }, { { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } }, { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } } }; QElapsedTimer timer; timer.start(); #ifndef DISABLED_OPENMAX //loadWithOmx(); QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay"); EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext()); #if 0 eglImageVideo = getEGLImage(1920, 1080, eglDisplay, eglContext, textures[0]); #endif for (int i = 0; i < 5; i++) textures[i] = 0; //QtConcurrent::run(video_decode_test, videoPath, eglImageVideo, eglDisplay); m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider); connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint))); m_videoProc->setVideoPath("/home/pi/out.h264"); m_videoProc->play(); #else for (int i = 0; i < 6; i++) { QPixmap pixmap(QString("%1%2.jpg").arg(prefix).arg(i)); if (pixmap.isNull()) LOG_ERROR(LOG_TAG, "Failed to load image!"); textures[i] = bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA); } #endif LOG_INFORMATION(LOG_TAG, "Elapsed: %lld.", timer.elapsed()); for (int i = 0; i < 6; ++i) { for (int j = 0; j < 4; ++j) { texCoords.append (QVector2D(j == 0 || j == 3, j == 0 || j == 1)); vertices.append (QVector3D(0.2 * coords[i][j][0], 0.2 * coords[i][j][1], 0.2 * coords[i][j][2])); } } }
OMX_TextureData* OMX_TextureProviderQGLWidget::instantiateTexture(QSize size) { // TODO: Reimplement. #if 0 m_parent->makeCurrent(); QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay"); EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext()); GLuint texture; eglImageVideo = getEGLImage(size.width(), size.height(), eglDisplay, eglContext, texture); return texture; #endif return 0; }
/*------------------------------------------------------------------------------ | get_egl_context +-----------------------------------------------------------------------------*/ EGLContext get_global_egl_context() { QOpenGLContext* c = QOpenGLContext::globalShareContext(); if (!c) return (void*)log_warn("Cannot get an OpenGL context."); QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLContext eglc = nativeInterface->nativeResourceForContext("eglcontext", c); if (!eglc) log_warn("Couldn't get EGL context from currrent OpenGL context."); return eglc; }
void GLWidget::loadWithOmx() { LOG_VERBOSE(LOG_TAG, "Loading with OMX."); QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay"); EGLContext eglContext = nativeInterface->nativeResourceForContext("eglcontext", QOpenGLContext::currentContext()); for (int i = 5; i < 6; i++) { QString fileAbsPath = QString("%1%2.jpg").arg(prefix).arg(i); OpenMAXILTextureLoader* omTextureLoader = OpenMAXILTextureLoader::intance(); if (!omTextureLoader->loadTextureFromImage(fileAbsPath, eglDisplay, eglContext, textures[i])) { LOG_ERROR(LOG_TAG, "Failed to load image."); } else { LOG_INFORMATION(LOG_TAG, "Image %s successfully decoded and loaded.", qPrintable(fileAbsPath)); } } }
GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext = 0) : m_display(m_offScreenWindow.display()) , m_xPixmap(0) , m_glxPixmap(0) , m_surface(0) , m_glxSurface(0) , m_glContext(0) , m_detachedContext(0) , m_detachedSurface(0) , m_fbConfig(0) , m_textureIsYInverted(false) , m_hasAlpha(false) , m_isReceiver(false) { GLXContext shareContextObject = 0; #if PLATFORM(QT) if (shareContext) { QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); shareContextObject = static_cast<GLXContext>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("glxcontext"), shareContext)); if (!shareContextObject) return; } #else UNUSED_PARAM(shareContext); #endif int numReturned; GLXFBConfig* fbConfigs = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &numReturned); // Make sure that we choose a configuration that supports an alpha mask. m_fbConfig = findFBConfigWithAlpha(fbConfigs, numReturned); XFree(fbConfigs); // Create a GLX context for OpenGL rendering m_glContext = glXCreateNewContext(m_display, m_fbConfig, GLX_RGBA_TYPE, shareContextObject, true); }
QSGNode* OMX_MediaProcessorElement::updatePaintNode(QSGNode*, UpdatePaintNodeData*) { if (!m_texProvider) { m_texProvider = new OMX_TextureProviderQQuickItem(this); m_mediaProc = new OMX_MediaProcessor(m_texProvider); connect(m_mediaProc, SIGNAL(playbackCompleted()), this, SIGNAL(playbackCompleted())); connect(m_mediaProc, SIGNAL(playbackStarted()), this, SIGNAL(playbackStarted())); // Open if filepath is set. // TODO: Handle errors. if (!m_source.isNull()) { //if (QFile(m_source).exists()) { if (openMedia(m_source)) m_mediaProc->play(); //} //else { LOG_WARNING(LOG_TAG, "File does not exist."); //} } } return NULL; #if 0 QSGGeometryNode* node = 0; QSGGeometry* geometry = 0; if (!oldNode) { // Create the node. node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); geometry->setDrawingMode(GL_TRIANGLE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); // TODO: Who is freeing this? // TODO: I cannot know the texture size here. QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial; m_sgtexture = new OMX_SGTexture(m_texture, QSize(1920, 1080)); material->setTexture(m_sgtexture); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); #ifdef ENABLE_VIDEO_PROCESSOR QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay"); EGLContext eglContext = nativeInterface->nativeResourceForContext( "eglcontext", QOpenGLContext::currentContext() ); #endif // Provider MUST be built in this thread. m_provider = new OMX_TextureProviderQQuickItem(this); #ifdef ENABLE_VIDEO_PROCESSOR m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider); connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint))); if (!m_source.isNull()) m_videoProc->setVideoPath(m_source); if (m_playScheduled) { m_timer->start(30); m_videoProc->play(); } #elif ENABLE_MEDIA_PROCESSOR LOG_VERBOSE(LOG_TAG, "Starting video using media processor..."); m_mediaProc = new OMX_MediaProcessor(m_provider); m_mediaProc->setFilename("/home/pi/usb/Cars2.mkv", m_texture); //if (m_playScheduled) { m_timer->start(40); m_mediaProc->play(); //} #else LOG_VERBOSE(LOG_TAG, "Starting video..."); QtConcurrent::run(&startVideo, m_provider, this); m_timer->start(30); #endif } else { node = static_cast<QSGGeometryNode*>(oldNode); geometry = node->geometry(); geometry->allocate(4); // Update texture in the node if needed. QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material(); if (m_texture != (GLuint)material->texture()->textureId()) { // TODO: Does setTextureId frees the prev texture? // TODO: I should the given the texture size. LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture); material = new QSGOpaqueTextureMaterial; m_sgtexture->setTexture(m_texture, QSize(1920, 1080)); } } // Create the vertices and map to texture. QRectF bounds = boundingRect(); QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D(); vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f); vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f); vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f); vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f); return node; #endif }
void D3DPresentEngine::createOffscreenTexture() { // First, check if we have a context on this thread QOpenGLContext *currentContext = QOpenGLContext::currentContext(); if (!currentContext) { //Create OpenGL context and set share context from surface QOpenGLContext *shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>()); if (!shareContext) return; m_offscreenSurface = new QWindow; m_offscreenSurface->setSurfaceType(QWindow::OpenGLSurface); //Needs geometry to be a valid surface, but size is not important m_offscreenSurface->setGeometry(-1, -1, 1, 1); m_offscreenSurface->create(); m_glContext = new QOpenGLContext; m_glContext->setFormat(m_offscreenSurface->requestedFormat()); m_glContext->setShareContext(shareContext); if (!m_glContext->create()) { delete m_glContext; delete m_offscreenSurface; m_glContext = 0; m_offscreenSurface = 0; return; } currentContext = m_glContext; } if (m_glContext) m_glContext->makeCurrent(m_offscreenSurface); if (!m_egl) m_egl = new EGLWrapper; QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); m_eglDisplay = static_cast<EGLDisplay*>( nativeInterface->nativeResourceForContext("eglDisplay", currentContext)); m_eglConfig = static_cast<EGLConfig*>( nativeInterface->nativeResourceForContext("eglConfig", currentContext)); currentContext->functions()->glGenTextures(1, &m_glTexture); int w = m_surfaceFormat.frameWidth(); int h = m_surfaceFormat.frameHeight(); bool hasAlpha = currentContext->format().hasAlpha(); EGLint attribs[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; EGLSurface pbuffer = m_egl->createPbufferSurface(m_eglDisplay, m_eglConfig, attribs); HANDLE share_handle = 0; PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(m_egl->getProcAddress("eglQuerySurfacePointerANGLE")); Q_ASSERT(eglQuerySurfacePointerANGLE); eglQuerySurfacePointerANGLE( m_eglDisplay, pbuffer, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle); m_device->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, hasAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_texture, &share_handle); m_eglSurface = pbuffer; if (m_glContext) m_glContext->doneCurrent(); }
GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext, const IntSize& size, GraphicsSurface::Flags flags) : m_context(0) , m_size(size) , m_frontBufferTexture(0) , m_frontBufferReadTexture(0) , m_backBufferTexture(0) , m_backBufferReadTexture(0) , m_readFbo(0) , m_drawFbo(0) { #if PLATFORM(QT) QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface(); CGLContextObj shareContextObject = static_cast<CGLContextObj>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("cglContextObj"), shareContext)); if (!shareContextObject) return; CGLPixelFormatObj pixelFormatObject = CGLGetPixelFormat(shareContextObject); if (kCGLNoError != CGLCreateContext(pixelFormatObject, shareContextObject, &m_context)) return; CGLRetainContext(m_context); #endif unsigned pixelFormat = 'BGRA'; unsigned bytesPerElement = 4; int width = m_size.width(); int height = m_size.height(); unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, width * bytesPerElement); if (!bytesPerRow) return; unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, height * bytesPerRow); if (!allocSize) return; const void *keys[6]; const void *values[6]; keys[0] = kIOSurfaceWidth; values[0] = CFNumberCreate(0, kCFNumberIntType, &width); keys[1] = kIOSurfaceHeight; values[1] = CFNumberCreate(0, kCFNumberIntType, &height); keys[2] = kIOSurfacePixelFormat; values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat); keys[3] = kIOSurfaceBytesPerElement; values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement); keys[4] = kIOSurfaceBytesPerRow; values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow); keys[5] = kIOSurfaceAllocSize; values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize); CFDictionaryRef dict = CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for (unsigned i = 0; i < 6; i++) CFRelease(values[i]); m_frontBuffer = IOSurfaceCreate(dict); m_backBuffer = IOSurfaceCreate(dict); if (!(flags & GraphicsSurface::SupportsSharing)) return; m_token = GraphicsSurfaceToken(IOSurfaceCreateMachPort(m_frontBuffer), IOSurfaceCreateMachPort(m_backBuffer)); }
bool EGLInteropResource::ensureD3D9EGL(int w, int h) { if (surface9 && res[0].w == w && res[0].h == h) return true; #if QTAV_HAVE(GUI_PRIVATE) QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); egl->dpy = static_cast<EGLDisplay>(nativeInterface->nativeResourceForContext("eglDisplay", QOpenGLContext::currentContext())); EGLConfig egl_cfg = static_cast<EGLConfig>(nativeInterface->nativeResourceForContext("eglConfig", QOpenGLContext::currentContext())); #else #ifdef Q_OS_WIN #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) #ifdef _MSC_VER #pragma message("ANGLE version in Qt<5.5 does not support eglQueryContext. You must upgrade your runtime ANGLE libraries") #else #warning "ANGLE version in Qt<5.5 does not support eglQueryContext. You must upgrade your runtime ANGLE libraries" #endif //_MSC_VER #endif #endif //Q_OS_WIN // eglQueryContext() added (Feb 2015): https://github.com/google/angle/commit/8310797003c44005da4143774293ea69671b0e2a egl->dpy = eglGetCurrentDisplay(); qDebug("EGL version: %s, client api: %s", eglQueryString(egl->dpy, EGL_VERSION), eglQueryString(egl->dpy, EGL_CLIENT_APIS)); // TODO: check runtime egl>=1.4 for eglGetCurrentContext() EGLint cfg_id = 0; EGL_ENSURE(eglQueryContext(egl->dpy, eglGetCurrentContext(), EGL_CONFIG_ID , &cfg_id) == EGL_TRUE, false); qDebug("egl config id: %d", cfg_id); EGLint nb_cfg = 0; EGL_ENSURE(eglGetConfigs(egl->dpy, NULL, 0, &nb_cfg) == EGL_TRUE, false); qDebug("eglGetConfigs number: %d", nb_cfg); QVector<EGLConfig> cfgs(nb_cfg); //check > 0 EGL_ENSURE(eglGetConfigs(egl->dpy, cfgs.data(), cfgs.size(), &nb_cfg) == EGL_TRUE, false); EGLConfig egl_cfg = NULL; for (int i = 0; i < nb_cfg; ++i) { EGLint id = 0; eglGetConfigAttrib(egl->dpy, cfgs[i], EGL_CONFIG_ID, &id); if (id == cfg_id) { egl_cfg = cfgs[i]; break; } } #endif qDebug("egl display:%p config: %p", egl->dpy, egl_cfg); // check extensions QList<QByteArray> extensions = QByteArray(eglQueryString(egl->dpy, EGL_EXTENSIONS)).split(' '); // ANGLE_d3d_share_handle_client_buffer will be used if possible const bool kEGL_ANGLE_d3d_share_handle_client_buffer = extensions.contains("EGL_ANGLE_d3d_share_handle_client_buffer"); const bool kEGL_ANGLE_query_surface_pointer = extensions.contains("EGL_ANGLE_query_surface_pointer"); if (!kEGL_ANGLE_d3d_share_handle_client_buffer && !kEGL_ANGLE_query_surface_pointer) { qWarning("EGL extension 'kEGL_ANGLE_query_surface_pointer' or 'ANGLE_d3d_share_handle_client_buffer' is required!"); return false; } GLint has_alpha = 1; //QOpenGLContext::currentContext()->format().hasAlpha() eglGetConfigAttrib(egl->dpy, egl_cfg, EGL_BIND_TO_TEXTURE_RGBA, &has_alpha); //EGL_ALPHA_SIZE EGLint attribs[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_TEXTURE_FORMAT, has_alpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; HANDLE share_handle = NULL; if (!kEGL_ANGLE_d3d_share_handle_client_buffer && kEGL_ANGLE_query_surface_pointer) { EGL_ENSURE((egl->surface = eglCreatePbufferSurface(egl->dpy, egl_cfg, attribs)) != EGL_NO_SURFACE, false); qDebug("pbuffer surface: %p", egl->surface); PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(eglGetProcAddress("eglQuerySurfacePointerANGLE")); if (!eglQuerySurfacePointerANGLE) { qWarning("EGL_ANGLE_query_surface_pointer is not supported"); return false; } EGL_ENSURE(eglQuerySurfacePointerANGLE(egl->dpy, egl->surface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle), false); } SafeRelease(&surface9); SafeRelease(&texture9); // _A8 for a yuv plane /* * d3d resource share requires windows >= vista: https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800(v=vs.85).aspx * from extension files: * d3d9: level must be 1, dimensions must match EGL surface's * d3d9ex or d3d10: */ DX_ENSURE(device9->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, has_alpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture9, &share_handle) , false); DX_ENSURE(texture9->GetSurfaceLevel(0, &surface9), false); if (kEGL_ANGLE_d3d_share_handle_client_buffer) { // requires extension EGL_ANGLE_d3d_share_handle_client_buffer // egl surface size must match d3d texture's // d3d9ex or d3d10 is required EGL_ENSURE((egl->surface = eglCreatePbufferFromClientBuffer(egl->dpy, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, share_handle, egl_cfg, attribs)), false); qDebug("pbuffer surface from client buffer: %p", egl->surface); } return true; }