/******************************************************************************
* This is called by the system to paint the widgets area.
******************************************************************************/
void FrameBufferWidget::paintEvent(QPaintEvent* event)
{
	if(frameBuffer()) {
		QPainter painter(this);
		painter.drawImage(0, 0, frameBuffer()->image());
	}
}
Пример #2
0
bool UIMachineViewNormal::eventFilter(QObject *pWatched, QEvent *pEvent)
{
    if (pWatched != 0 && pWatched == machineWindow())
    {
        switch (pEvent->type())
        {
            case QEvent::Resize:
            {
                /* We call this on every resize as:
                 *   * Window frame geometry can change on resize.
                 *   * On X11 we set information here which becomes available
                 *     asynchronously at an unknown time after window
                 *     creation.  As long as the information is not available
                 *     we make a best guess.
                 */
                setMaxGuestSize();
                if (pEvent->spontaneous() && m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics())
                    QTimer::singleShot(300, this, SLOT(sltPerformGuestResize()));
                break;
            }
#if defined (Q_WS_WIN32)
# if defined (VBOX_GUI_USE_DDRAW)
            case QEvent::Move:
            {
                /* Notification from our parent that it has moved. We need this in order
                 * to possibly adjust the direct screen blitting: */
                if (frameBuffer())
                    frameBuffer()->moveEvent(static_cast<QMoveEvent*>(pEvent));
                break;
            }
# endif /* defined (VBOX_GUI_USE_DDRAW) */
#endif /* defined (Q_WS_WIN32) */
            default:
                break;
        }
    }

#ifdef Q_WS_WIN
    else if (pWatched != 0 && pWatched == machineWindow()->menuBar())
    {
        /* Due to windows host uses separate 'focus set' to let menubar to
         * operate while popped up (see UIMachineViewNormal::event() for details),
         * it also requires backward processing: */
        switch (pEvent->type())
        {
            /* If menubar gets the focus while not popped up => give it back: */
            case QEvent::FocusIn:
            {
                if (!QApplication::activePopupWidget())
                    setFocus();
            }
            default:
                break;
        }
    }
#endif /* Q_WS_WIN */

    return UIMachineView::eventFilter(pWatched, pEvent);
}
Пример #3
0
void UIMachineViewSeamless::normalizeGeometry(bool /* fAdjustPosition */)
{
    /* Check if we should adjust guest to new size: */
    if ((int)frameBuffer()->width() != workingArea().size().width() ||
        (int)frameBuffer()->height() != workingArea().size().height())
        if (uisession()->isGuestSupportsGraphics())
            sltPerformGuestResize(workingArea().size());
}
Пример #4
0
void UIMachineViewNormal::adjustGuestScreenSize()
{
    /* Should we adjust guest-screen size? Logging paranoia is required here to reveal the truth. */
    LogRel(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Adjust guest-screen size if necessary.\n"));
    bool fAdjust = false;

    /* Step 1: Is the guest-screen of another size than necessary? */
    if (!fAdjust)
    {
        /* Acquire frame-buffer size: */
        QSize frameBufferSize(frameBuffer()->width(), frameBuffer()->height());
        /* Take the scale-factor(s) into account: */
        frameBufferSize = scaledForward(frameBufferSize);

        /* Acquire central-widget size: */
        const QSize centralWidgetSize = machineWindow()->centralWidget()->size();

        if (frameBufferSize != centralWidgetSize)
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen is of another size than necessary, adjustment is required.\n"));
            fAdjust = true;
        }
    }

    /* Step 2: Is guest-additions supports graphics? */
    if (fAdjust)
    {
        if (!uisession()->isGuestSupportsGraphics())
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-additions are not supporting graphics, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 3: Is guest-screen visible? */
    if (fAdjust)
    {
        if (!uisession()->isScreenVisible(screenId()))
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen is not visible, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 4: Is guest-screen auto-resize enabled? */
    if (fAdjust)
    {
        if (!m_bIsGuestAutoresizeEnabled)
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen auto-resize is disabled, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }

    /* Final step: Adjust if requested/allowed. */
    if (fAdjust)
    {
        sltPerformGuestResize(machineWindow()->centralWidget()->size());
    }
}
void UIMachineViewFullscreen::sltAdditionsStateChanged()
{
    /* Check if we should restrict minimum size: */
    maybeRestrictMinimumSize();

    /* Check if we should resize guest to fullscreen, all the
     * required features will be tested in sltPerformGuestResize(...): */
    if ((int)frameBuffer()->width() != workingArea().size().width() ||
        (int)frameBuffer()->height() != workingArea().size().height())
        sltPerformGuestResize(workingArea().size());
}
Пример #6
0
void UIMachineViewFullscreen::sltAdditionsStateChanged()
{
    /* Check if we should restrict minimum size: */
    maybeRestrictMinimumSize();

    /* Check if we should resize guest to fullscreen */
    if ((int)frameBuffer()->width() != workingArea().size().width() ||
            (int)frameBuffer()->height() != workingArea().size().height())
        if (m_bIsGuestAutoresizeEnabled && uisession()->isGuestSupportsGraphics())
            sltPerformGuestResize(workingArea().size());
}
Пример #7
0
void UIMachineView::updateSliders()
{
    QSize p = viewport()->size();
    QSize m = maximumViewportSize();

    QSize v = QSize(frameBuffer()->width(), frameBuffer()->height());
    /* No scroll bars needed: */
    if (m.expandedTo(v) == m)
        p = m;

    horizontalScrollBar()->setRange(0, v.width() - p.width());
    verticalScrollBar()->setRange(0, v.height() - p.height());
    horizontalScrollBar()->setPageStep(p.width());
    verticalScrollBar()->setPageStep(p.height());
}
bool UIMachineViewScale::eventFilter(QObject *pWatched, QEvent *pEvent)
{
    /* Who are we watching? */
    QMainWindow *pMainDialog = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
                               qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow()) : 0;

    if (pWatched != 0 && pWatched == viewport())
    {
        switch (pEvent->type())
        {
            case QEvent::Resize:
            {
                /* Perform the actually resize */
                sltPerformGuestScale();
                break;
            }
            default:
                break;
        }
    }
    else if (pWatched != 0 && pWatched == pMainDialog)
    {
        switch (pEvent->type())
        {
#if defined (Q_WS_WIN32)
# if defined (VBOX_GUI_USE_DDRAW)
            case QEvent::Move:
            {
                /* Notification from our parent that it has moved. We need this in order
                 * to possibly adjust the direct screen blitting: */
                if (frameBuffer())
                    frameBuffer()->moveEvent(static_cast<QMoveEvent*>(pEvent));
                break;
            }
# else
            case 0: /* Fixes compiler warning, fall through. */
# endif /* defined (VBOX_GUI_USE_DDRAW) */

#else
            case 0: /* Fixes compiler warning, fall through. */
#endif /* defined (Q_WS_WIN32) */
            default:
                break;
        }
    }

    return UIMachineView::eventFilter(pWatched, pEvent);
}
Пример #9
0
	void afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
	struct timeval presentationTime, unsigned durationInMicroseconds)
	{
		if (fStreamId != NULL) envir() << "Stream \"" << fStreamId << "\"; ";
		envir() << fSubsession.mediumName() << "/" << fSubsession.codecName() << ":\tReceived " << frameSize << " bytes";

		QByteArray frameBuffer((char*)fReceiveBuffer, frameSize);
		
		
		//插入SPS PPS才能让H264解码器正确解码
		QByteArray sps = sprop_parameter_sets;
		QByteArray extraData;
		QList<QByteArray> recodList = sps.split(',');

		for (int i = 0; i < recodList.size(); ++i)
		{
			extraData.append(char(0x00));
			extraData.append(char(0x00));
			extraData.append(char(0x00));
			extraData.append(char(0x01));

			extraData += QByteArray::fromBase64(recodList.at(i));
		}
		QByteArray endMark = QByteArray(4, 0);
		endMark[3] = 0x01;


		frameBuffer.insert(0, extraData);
		frameBuffer.insert(extraData.size(), endMark);

		m_ffmpeg->decodeFrame((uint8_t*)frameBuffer.data(), frameBuffer.size(), presentationTime.tv_sec, presentationTime.tv_usec);

		// Then continue, to request the next frame of data:
		continuePlaying();
	}
Пример #10
0
bool
PostEffect::composite (const Ctr::GpuTechnique* technique,
                       const Ctr::ISurface* surface,
                       std::vector<const Ctr::IGpuBuffer*> & uavs,
                       std::vector<const Ctr::ITexture*>  & inputs,
                       const Ctr::Camera* camera)
{
    _postEffectBounds = Ctr::Region2i(Ctr::Vector2i(0,0), Ctr::Vector2i(surface->width(), surface->height()));
    Ctr::FrameBuffer frameBuffer(surface, nullptr);

    for (size_t i = 0; i < uavs.size(); i++)
    {
        frameBuffer.setUnorderedSurface(i, uavs[i]);
    }

    _device->setupViewport(frameBuffer);
    _device->bindFrameBuffer(frameBuffer);
    _inputs = inputs;

    _shader->renderMesh (Ctr::RenderRequest(technique, nullptr, camera, this));

    inputs.clear();
    uavs.clear();

    // Needless stall. Needs optimize

    Ctr::FrameBuffer frameBuffer0(_device->backbuffer(), nullptr);
    _device->bindFrameBuffer(frameBuffer0);
    return true;
}
void UIMachineViewSeamless::adjustGuestScreenSize()
{
    /* Acquire working-area size: */
    const QSize workingAreaSize = workingArea().size();
    /* Acquire frame-buffer size: */
    QSize frameBufferSize(frameBuffer()->width(), frameBuffer()->height());
    /* Take the scale-factor(s) into account: */
    frameBufferSize = scaledForward(frameBufferSize);
    /* Check if we should adjust guest-screen to new size: */
    if (frameBuffer()->isAutoEnabled() ||
        frameBufferSize != workingAreaSize)
        if (uisession()->isGuestSupportsGraphics() &&
            uisession()->isScreenVisible(screenId()))
        {
            frameBuffer()->setAutoEnabled(false);
            sltPerformGuestResize(workingArea().size());
        }
}
Пример #12
0
void UIMachineViewScale::sltHandleNotifyUpdate(int iX, int iY, int iW, int iH)
{
    /* Initialize variables for scale mode: */
    QSize scaledSize = frameBuffer()->scaledSize();
    double xRatio = (double)scaledSize.width() / frameBuffer()->width();
    double yRatio = (double)scaledSize.height() / frameBuffer()->height();
    AssertMsg(contentsX() == 0, ("This can't be, else notify Dsen!\n"));
    AssertMsg(contentsY() == 0, ("This can't be, else notify Dsen!\n"));

    /* Update corresponding viewport part,
     * But make sure we update always a bigger rectangle than requested to
     * catch all rounding errors. (use 1 time the ratio factor and
     * round down on top/left, but round up for the width/height) */
    viewport()->update((int)(iX * xRatio) - ((int)xRatio) - 1,
                       (int)(iY * yRatio) - ((int)yRatio) - 1,
                       (int)(iW * xRatio) + ((int)xRatio + 2) * 2,
                       (int)(iH * yRatio) + ((int)yRatio + 2) * 2);
}
Пример #13
0
/******************************************************************************
* Sets the FrameBuffer that is currently shown in the widget.
******************************************************************************/
void FrameBufferWidget::setFrameBuffer(const QSharedPointer<FrameBuffer>& newFrameBuffer)
{
	if(newFrameBuffer == frameBuffer()) {
		onFrameBufferContentReset();
		return;
	}

	if(frameBuffer()) {
		disconnect(_frameBuffer.data(), &FrameBuffer::contentChanged, this, &FrameBufferWidget::onFrameBufferContentChanged);
		disconnect(_frameBuffer.data(), &FrameBuffer::contentReset, this, &FrameBufferWidget::onFrameBufferContentReset);
	}
	
	_frameBuffer = newFrameBuffer;

	onFrameBufferContentReset();

	connect(_frameBuffer.data(), &FrameBuffer::contentChanged, this, &FrameBufferWidget::onFrameBufferContentChanged);
	connect(_frameBuffer.data(), &FrameBuffer::contentReset, this, &FrameBufferWidget::onFrameBufferContentReset);
}
Пример #14
0
UIMachineViewScale::~UIMachineViewScale()
{
    /* Save machine view settings: */
    saveMachineViewSettings();

    /* Disable scaling: */
    frameBuffer()->setScaledSize(QSize());

    /* Cleanup frame buffer: */
    cleanupFrameBuffer();
}
Пример #15
0
void UIMachineViewScale::scalePauseShot()
{
    if (m_pPauseImage)
    {
        QSize scaledSize = frameBuffer()->scaledSize();
        if (scaledSize.isValid())
        {
            QImage tmpImg = m_pPauseImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            dimImage(tmpImg);
            m_pauseShot = QPixmap::fromImage(tmpImg);
        }
    }
}
Пример #16
0
void UIMachineViewScale::sltPerformGuestScale()
{
    /* Check if scale is requested: */
    /* Set new frame-buffer scale-factor: */
    frameBuffer()->setScaledSize(viewport()->size());

    /* Scale the pause image if necessary */
    scalePauseShot();

    /* Update viewport: */
    viewport()->repaint();

    /* Update machine-view sliders: */
    updateSliders();
}
Пример #17
0
bool 
PostEffect::render (const Ctr::ITexture* textureIn, const Ctr::Camera* camera)
{
    _postEffectBounds = Ctr::Region2i(Ctr::Vector2i(0,0), Ctr::Vector2i(_device->backbuffer()->width(), _device->backbuffer()->height()));

    Ctr::FrameBuffer frameBuffer(_postEffectTexture->surface(), nullptr);
    _device->setupViewport(frameBuffer);
    _device->bindFrameBuffer(frameBuffer);

    _textureIn = textureIn;
    _shader->renderMesh (Ctr::RenderRequest(_technique, nullptr, camera, this));

    // Needless stall. Needs optimize
    return _device->backbuffer()->bind (0);
}
Пример #18
0
bool
PostEffect::composite (const Ctr::ISurface* surface,
                       std::vector<const Ctr::ITexture*> &  inputs,
                       const Ctr::Camera*   camera)
{
    _postEffectBounds = Ctr::Region2i(Ctr::Vector2i(0,0), Ctr::Vector2i(surface->width(), surface->height()));
    _inputs = inputs;
    Ctr::FrameBuffer frameBuffer(surface, nullptr);
    _device->setupViewport(frameBuffer);
    _device->bindFrameBuffer(frameBuffer);

    _shader->renderMesh (Ctr::RenderRequest(_technique, nullptr, camera, this));

    inputs.clear();

    // Needless stall. Needs optimize
    return _device->backbuffer()->bind (0);
}
Пример #19
0
QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
{
    //qDebug();

    // See if there is still an existing framebuffer to this WId.
    if (m_frameBuffers.contains(id)) {
        QWeakPointer<FrameBuffer> weakFrameBuffer = m_frameBuffers.value(id);

        if (weakFrameBuffer) {
            //qDebug() << "Found cached frame buffer.";
            return weakFrameBuffer.toStrongRef();
        } else {
            //qDebug() << "Found deleted cached frame buffer. Don't use.";
            m_frameBuffers.remove(id);
        }
    }

    // We don't already have that frame buffer.
    QMap<QString, FrameBufferPlugin *>::const_iterator iter = m_plugins.constBegin();

    while (iter != m_plugins.constEnd()) {

        if (iter.key() == KrfbConfig::preferredFrameBufferPlugin()) {
            qDebug() << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();

            QSharedPointer<FrameBuffer> frameBuffer(iter.value()->frameBuffer(id));

            if (frameBuffer) {
                m_frameBuffers.insert(id, frameBuffer.toWeakRef());

                return frameBuffer;
            }
        }

        ++iter;
    }

    // No valid framebuffer plugin found.
    qDebug() << "No valid framebuffer found. returning null.";
    return QSharedPointer<FrameBuffer>();
}
bool UIMachineViewFullscreen::event(QEvent *pEvent)
{
    switch (pEvent->type())
    {
        case VBoxDefs::ResizeEventType:
        {
            /* Some situations require framebuffer resize events to be ignored at all,
             * leaving machine-window, machine-view and framebuffer sizes preserved: */
            if (uisession()->isGuestResizeIgnored())
                return true;

            /* We are starting to perform machine-view resize,
             * we should temporary ignore other if they are trying to be: */
            bool fWasMachineWindowResizeIgnored = isMachineWindowResizeIgnored();
            setMachineWindowResizeIgnored(true);

            /* Get guest resize-event: */
            UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);

            /* Perform framebuffer resize: */
            frameBuffer()->resizeEvent(pResizeEvent);

            /* Reapply maximum size restriction for machine-view: */
            setMaximumSize(sizeHint());

            /* Store the new size to prevent unwanted resize hints being sent back: */
            storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());

            /* Perform machine-view resize: */
            resize(pResizeEvent->width(), pResizeEvent->height());

            /* May be we have to restrict minimum size? */
            maybeRestrictMinimumSize();

            /* Let our toplevel widget calculate its sizeHint properly: */
            QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);

#ifdef Q_WS_MAC
            machineLogic()->updateDockIconSize(screenId(), pResizeEvent->width(), pResizeEvent->height());
#endif /* Q_WS_MAC */

            /* Update machine-view sliders: */
            updateSliders();

            /* Report to the VM thread that we finished resizing: */
            session().GetConsole().GetDisplay().ResizeCompleted(screenId());

            /* We are finishing to perform machine-view resize: */
            setMachineWindowResizeIgnored(fWasMachineWindowResizeIgnored);

            /* We also recalculate the desktop geometry if this is determined
             * automatically.  In fact, we only need this on the first resize,
             * but it is done every time to keep the code simpler. */
            calculateDesktopGeometry();

            /* Emit a signal about guest was resized: */
            emit resizeHintDone();

            /* Unlock after processing guest resize event: */
            if (m_pSyncBlocker && m_pSyncBlocker->isRunning())
                m_pSyncBlocker->quit();

            pEvent->accept();
            return true;
        }

        default:
            break;
    }
    return UIMachineView::event(pEvent);
}
Пример #21
0
void UIMachineViewScale::saveMachineViewSettings()
{
    /* Store guest size in case we are switching to fullscreen: */
    storeGuestSizeHint(QSize(frameBuffer()->width(), frameBuffer()->height()));
}
Пример #22
0
void UIMachineView::prepareFrameBuffer()
{
    /* Prepare frame-buffer depending on render-mode: */
    switch (vboxGlobal().vmRenderMode())
    {
#ifdef VBOX_GUI_USE_QIMAGE
        case VBoxDefs::QImageMode:
# ifdef VBOX_WITH_VIDEOHWACCEL
            if (m_fAccelerate2DVideo)
            {
                UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
                if (pFramebuffer)
                    pFramebuffer->setView(this);
                else
                {
                    /* these two additional template args is a workaround to this [VBox|UI] duplication
                     * @todo: they are to be removed once VBox stuff is gone */
                    pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferQImage, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
                    uisession()->setFrameBuffer(screenId(), pFramebuffer);
                }
                m_pFrameBuffer = pFramebuffer;
            }
            else
                m_pFrameBuffer = new UIFrameBufferQImage(this);
# else /* VBOX_WITH_VIDEOHWACCEL */
            m_pFrameBuffer = new UIFrameBufferQImage(this);
# endif /* !VBOX_WITH_VIDEOHWACCEL */
            break;
#endif /* VBOX_GUI_USE_QIMAGE */
#ifdef VBOX_GUI_USE_QGLFB
        case VBoxDefs::QGLMode:
            m_pFrameBuffer = new UIFrameBufferQGL(this);
            break;
//        case VBoxDefs::QGLOverlayMode:
//            m_pFrameBuffer = new UIQGLOverlayFrameBuffer(this);
//            break;
#endif /* VBOX_GUI_USE_QGLFB */
#ifdef VBOX_GUI_USE_SDL
        case VBoxDefs::SDLMode:
            /* Indicate that we are doing all drawing stuff ourself: */
            // TODO_NEW_CORE
            viewport()->setAttribute(Qt::WA_PaintOnScreen);
# ifdef Q_WS_X11
            /* This is somehow necessary to prevent strange X11 warnings on i386 and segfaults on x86_64: */
            XFlush(QX11Info::display());
# endif /* Q_WS_X11 */
# if defined(VBOX_WITH_VIDEOHWACCEL) && defined(DEBUG_misha) /* not tested yet */
            if (m_fAccelerate2DVideo)
            {
                class UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
                if (pFramebuffer)
                    pFramebuffer->setView(this);
                else
                {
                    /* these two additional template args is a workaround to this [VBox|UI] duplication
                     * @todo: they are to be removed once VBox stuff is gone */
                    pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferSDL, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
                    uisession()->setFrameBuffer(screenId(), pFramebuffer);
                }
                m_pFrameBuffer = pFramebuffer;
            }
            else
                m_pFrameBuffer = new UIFrameBufferSDL(this);
# else
            m_pFrameBuffer = new UIFrameBufferSDL(this);
# endif
            /* Disable scrollbars because we cannot correctly draw in a scrolled window using SDL: */
            horizontalScrollBar()->setEnabled(false);
            verticalScrollBar()->setEnabled(false);
            break;
#endif /* VBOX_GUI_USE_SDL */
#if 0 // TODO: Enable DDraw frame buffer!
#ifdef VBOX_GUI_USE_DDRAW
        case VBoxDefs::DDRAWMode:
            m_pFrameBuffer = new UIDDRAWFrameBuffer(this);
            if (!m_pFrameBuffer || m_pFrameBuffer->address() == NULL)
            {
                if (m_pFrameBuffer)
                    delete m_pFrameBuffer;
                m_mode = VBoxDefs::QImageMode;
                m_pFrameBuffer = new UIFrameBufferQImage(this);
            }
            break;
#endif /* VBOX_GUI_USE_DDRAW */
#endif
#ifdef VBOX_GUI_USE_QUARTZ2D
        case VBoxDefs::Quartz2DMode:
            /* Indicate that we are doing all drawing stuff ourself: */
            viewport()->setAttribute(Qt::WA_PaintOnScreen);
# ifdef VBOX_WITH_VIDEOHWACCEL
            if (m_fAccelerate2DVideo)
            {
                UIFrameBuffer* pFramebuffer = uisession()->frameBuffer(screenId());
                if (pFramebuffer)
                    pFramebuffer->setView(this);
                else
                {
                    /* these two additional template args is a workaround to this [VBox|UI] duplication
                     * @todo: they are to be removed once VBox stuff is gone */
                    pFramebuffer = new VBoxOverlayFrameBuffer<UIFrameBufferQuartz2D, UIMachineView, UIResizeEvent>(this, &machineWindowWrapper()->session(), (uint32_t)screenId());
                    uisession()->setFrameBuffer(screenId(), pFramebuffer);
                }
                m_pFrameBuffer = pFramebuffer;
            }
            else
                m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
# else /* VBOX_WITH_VIDEOHWACCEL */
            m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
# endif /* !VBOX_WITH_VIDEOHWACCEL */
            break;
#endif /* VBOX_GUI_USE_QUARTZ2D */
        default:
            AssertReleaseMsgFailed(("Render mode must be valid: %d\n", vboxGlobal().vmRenderMode()));
            LogRel(("Invalid render mode: %d\n", vboxGlobal().vmRenderMode()));
            qApp->exit(1);
            break;
    }

    /* If frame-buffer was prepared: */
    if (m_pFrameBuffer)
    {
        /* Prepare display: */
        CDisplay display = session().GetConsole().GetDisplay();
        Assert(!display.isNull());
#ifdef VBOX_WITH_VIDEOHWACCEL
        CFramebuffer fb(NULL);
        if (m_fAccelerate2DVideo)
        {
            LONG XOrigin, YOrigin;
            /* Check if the framebuffer is already assigned;
             * in this case we do not need to re-assign it neither do we need to AddRef. */
            display.GetFramebuffer(m_uScreenId, fb, XOrigin, YOrigin);
        }
        if (fb.raw() != m_pFrameBuffer) /* <-this will evaluate to true iff m_fAccelerate2DVideo is disabled or iff no framebuffer is yet assigned */
#endif /* VBOX_WITH_VIDEOHWACCEL */
        {
            m_pFrameBuffer->AddRef();
        }
        /* Always perform SetFramebuffer to ensure 3D gets notified: */
        display.SetFramebuffer(m_uScreenId, CFramebuffer(m_pFrameBuffer));
    }

    QSize size;
#ifdef Q_WS_X11
    /* Processing pseudo resize-event to synchronize frame-buffer with stored
     * framebuffer size. On X11 this will be additional done when the machine
     * state was 'saved'. */
    if (session().GetMachine().GetState() == KMachineState_Saved)
        size = guestSizeHint();
#endif /* Q_WS_X11 */
    /* If there is a preview image saved, we will resize the framebuffer to the
     * size of that image. */
    ULONG buffer = 0, width = 0, height = 0;
    CMachine machine = session().GetMachine();
    machine.QuerySavedScreenshotPNGSize(0, buffer, width, height);
    if (buffer > 0)
    {
        /* Init with the screenshot size */
        size = QSize(width, height);
        /* Try to get the real guest dimensions from the save state */
        ULONG guestWidth = 0, guestHeight = 0;
        machine.QuerySavedGuestSize(0, guestWidth, guestHeight);
        if (   guestWidth  > 0
            && guestHeight > 0)
            size = QSize(guestWidth, guestHeight);
    }
    /* If we have a valid size, resize the framebuffer. */
    if (   size.width() > 0
        && size.height() > 0)
    {
        UIResizeEvent event(FramebufferPixelFormat_Opaque, NULL, 0, 0, size.width(), size.height());
        frameBuffer()->resizeEvent(&event);
    }
}
Пример #23
0
void UIMachineViewFullscreen::adjustGuestScreenSize()
{
    /* Should we adjust guest-screen size? Logging paranoia is required here to reveal the truth. */
    LogRel(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Adjust guest-screen size if necessary.\n"));
    bool fAdjust = false;

    /* Step 1: Was the guest-screen enabled automatically? */
    if (!fAdjust)
    {
        if (frameBuffer()->isAutoEnabled())
        {
            LogRel2(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Guest-screen was enabled automatically, adjustment is required.\n"));
            fAdjust = true;
        }
    }
    /* Step 2: Is the guest-screen of another size than necessary? */
    if (!fAdjust)
    {
        /* Acquire frame-buffer size: */
        QSize frameBufferSize(frameBuffer()->width(), frameBuffer()->height());
        /* Take the scale-factor(s) into account: */
        frameBufferSize = scaledForward(frameBufferSize);

        /* Acquire working-area size: */
        const QSize workingAreaSize = workingArea().size();

        if (frameBufferSize != workingAreaSize)
        {
            LogRel2(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Guest-screen is of another size than necessary, adjustment is required.\n"));
            fAdjust = true;
        }
    }

    /* Step 3: Is guest-additions supports graphics? */
    if (fAdjust)
    {
        if (!uisession()->isGuestSupportsGraphics())
        {
            LogRel2(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Guest-additions are not supporting graphics, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 4: Is guest-screen visible? */
    if (fAdjust)
    {
        if (!uisession()->isScreenVisible(screenId()))
        {
            LogRel2(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Guest-screen is not visible, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 5: Is guest-screen auto-resize enabled? */
    if (fAdjust)
    {
        if (!m_bIsGuestAutoresizeEnabled)
        {
            LogRel2(("GUI: UIMachineViewFullscreen::adjustGuestScreenSize: Guest-screen auto-resize is disabled, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }

    /* Final step: Adjust if requested/allowed. */
    if (fAdjust)
    {
        frameBuffer()->setAutoEnabled(false);
        sltPerformGuestResize(workingArea().size());
        /* And remember the size to know what we are resizing out of when we exit: */
        uisession()->setLastFullScreenSize(screenId(), scaledForward(scaledBackward(workingArea().size())));
    }
}
Пример #24
0
/**
* @brief 
*
* @return 
*/
int LocalVideoInput::run()
{
    AVInputFormat *inputFormat = av_find_input_format( "video4linux2" );
    if ( inputFormat == NULL)
        Fatal( "Can't load input format" );

#if 0
    AVProbeData probeData;
    probeData.filename = mSource.c_str();
    probeData.buf = new unsigned char[1024];
    probeData.buf_size = 1024;
    inputFormat = av_probe_input_format( &probeData, 0 );
    if ( inputFormat == NULL)
        Fatal( "Can't probe input format" );

    AVFormatParameters formatParameters ;
    memset( &formatParameters, 0, sizeof(formatParameters) );
    formatParameters.channels = 1;
    formatParameters.channel = 0;
    formatParameters.standard = "PAL";
    formatParameters.pix_fmt = PIX_FMT_RGB24;
    //formatParameters.time_base.num = 1;
    //formatParameters.time_base.den = 10;
    formatParameters.width = 352;
    formatParameters.height = 288;
    //formatParameters.prealloced_context = 1;
#endif

    /* New API */
    AVDictionary *opts = NULL;
    av_dict_set( &opts, "standard", "PAL", 0 );
    av_dict_set( &opts, "video_size", "320x240", 0 );
    av_dict_set( &opts, "channel", "0", 0 );
    av_dict_set( &opts, "pixel_format", "rgb24", 0 );
    //av_dict_set( &opts, "framerate", "10", 0 );
    avDumpDict( opts );

    int avError = 0;
    AVFormatContext *formatContext = NULL;
    //if ( av_open_input_file( &formatContext, mSource.c_str(), inputFormat, 0, &formatParameters ) !=0 )
    if ( (avError = avformat_open_input( &formatContext, mSource.c_str(), inputFormat, &opts )) < 0 )
        Fatal( "Unable to open input %s due to: %s", mSource.c_str(), avStrError(avError) );

    avDumpDict( opts );
#if 0
    if ( av_open_input_stream( &formatContext, 0, mSource.c_str(), inputFormat, &formatParameters ) !=0 )
        Fatal( "Unable to open input %s due to: %s", mSource.c_str(), strerror(errno) );
#endif

    // Locate stream info from input
    if ( (avError = avformat_find_stream_info( formatContext, &opts )) < 0 )
        Fatal( "Unable to find stream info from %s due to: %s", mSource.c_str(), avStrError(avError) );
    
    if ( dbgLevel > DBG_INF )
        av_dump_format( formatContext, 0, mSource.c_str(), 0 );

    // Find first video stream present
    int videoStreamId = -1;
    for ( int i=0; i < formatContext->nb_streams; i++ )
    {
        if ( formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
        {
            videoStreamId = i;
            //set_context_opts( formatContext->streams[i]->codec, avcodec_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
            break;
        }
    }
    if ( videoStreamId == -1 )
        Fatal( "Unable to locate video stream in %s", mSource.c_str() );
    mStream = formatContext->streams[videoStreamId];
    mCodecContext = mStream->codec;

    // Try and get the codec from the codec context
    AVCodec *codec = NULL;
    if ( (codec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL )
        Fatal( "Can't find codec for video stream from %s", mSource.c_str() );

    // Open the codec
    if ( avcodec_open2( mCodecContext, codec, &opts ) < 0 )
        Fatal( "Unable to open codec for video stream from %s", mSource.c_str() );

    //AVFrame *savedFrame = avcodec_alloc_frame();

    // Allocate space for the native video frame
    AVFrame *frame = avcodec_alloc_frame();

    // Determine required buffer size and allocate buffer
    int pictureSize = avpicture_get_size( mCodecContext->pix_fmt, mCodecContext->width, mCodecContext->height );
    
    ByteBuffer frameBuffer( pictureSize );
    
    //avpicture_fill( (AVPicture *)savedFrame, mLastFrame.mBuffer.data(), mCodecContext->pix_fmt, mCodecContext->width, mCodecContext->height);

    AVPacket packet;
    while( !mStop )
    {
        int frameComplete = false;
        while ( !frameComplete && (av_read_frame( formatContext, &packet ) >= 0) )
        {
            Debug( 5, "Got packet from stream %d", packet.stream_index );
            if ( packet.stream_index == videoStreamId )
            {
                frameComplete = false;
                if ( avcodec_decode_video2( mCodecContext, frame, &frameComplete, &packet ) < 0 )
                    Fatal( "Unable to decode frame at frame %ju", mFrameCount );

                Debug( 3, "Decoded video packet at frame %ju, pts %jd", mFrameCount, packet.pts );

                if ( frameComplete )
                {
                    Debug( 3, "Got frame %d, pts %jd (%.3f)", mCodecContext->frame_number, frame->pkt_pts, (((double)(packet.pts-mStream->start_time)*mStream->time_base.num)/mStream->time_base.den) );

                    avpicture_layout( (AVPicture *)frame, mCodecContext->pix_fmt, mCodecContext->width, mCodecContext->height, frameBuffer.data(), frameBuffer.capacity() );

                    uint64_t timestamp = packet.pts;
                    //Debug( 3, "%d: TS: %lld, TS1: %lld, TS2: %lld, TS3: %.3f", time( 0 ), timestamp, packet.pts, ((1000000LL*packet.pts*mStream->time_base.num)/mStream->time_base.den), (((double)packet.pts*mStream->time_base.num)/mStream->time_base.den) );
                    //Info( "%ld:TS: %lld, TS1: %lld, TS2: %lld, TS3: %.3f", time( 0 ), timestamp, packet.pts, ((1000000LL*packet.pts*mStream->time_base.num)/mStream->time_base.den), (((double)packet.pts*mStream->time_base.num)/mStream->time_base.den) );

                    VideoFrame *videoFrame = new VideoFrame( this, mCodecContext->frame_number, timestamp, frameBuffer );
                    distributeFrame( FramePtr( videoFrame ) );
                }
            }
            av_free_packet( &packet );
        }
        usleep( INTERFRAME_TIMEOUT );
    }
    cleanup();

    av_freep( &frame );
    if ( mCodecContext )
    {
       avcodec_close( mCodecContext );
       mCodecContext = NULL; // Freed by avformat_close_input
    }
    if ( formatContext )
    {
        avformat_close_input( &formatContext );
        formatContext = NULL;
        //av_free( formatContext );
    }
    return( !ended() );
}
bool UIMachineViewScale::event(QEvent *pEvent)
{
    switch (pEvent->type())
    {
        case VBoxDefs::ResizeEventType:
        {
            /* Some situations require framebuffer resize events to be ignored at all,
             * leaving machine-window, machine-view and framebuffer sizes preserved: */
            if (uisession()->isGuestResizeIgnored())
                return true;

            /* We are starting to perform machine-view resize,
             * we should temporary ignore other if they are trying to be: */
            bool fWasMachineWindowResizeIgnored = isMachineWindowResizeIgnored();
            setMachineWindowResizeIgnored(true);

            /* Get guest resize-event: */
            UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);

            /* Perform framebuffer resize: */
            frameBuffer()->setScaledSize(size());
            frameBuffer()->resizeEvent(pResizeEvent);

            /* Store the new size to prevent unwanted resize hints being sent back: */
            storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());

            /* Let our toplevel widget calculate its sizeHint properly: */
            QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);

#ifdef Q_WS_MAC
            machineLogic()->updateDockIconSize(screenId(), pResizeEvent->width(), pResizeEvent->height());
#endif /* Q_WS_MAC */

            /* Report to the VM thread that we finished resizing: */
            session().GetConsole().GetDisplay().ResizeCompleted(screenId());

            /* We are finishing to perform machine-view resize: */
            setMachineWindowResizeIgnored(fWasMachineWindowResizeIgnored);

            /* We also recalculate the desktop geometry if this is determined
             * automatically.  In fact, we only need this on the first resize,
             * but it is done every time to keep the code simpler. */
            calculateDesktopGeometry();

            /* Emit a signal about guest was resized: */
            emit resizeHintDone();

            pEvent->accept();
            return true;
        }

        case VBoxDefs::RepaintEventType:
        {
            UIRepaintEvent *pPaintEvent = static_cast<UIRepaintEvent*>(pEvent);
            QSize scaledSize = frameBuffer()->scaledSize();
            double xRatio = (double)scaledSize.width() / frameBuffer()->width();
            double yRatio = (double)scaledSize.height() / frameBuffer()->height();
            AssertMsg(contentsX() == 0, ("This can't be, else notify Dsen!\n"));
            AssertMsg(contentsY() == 0, ("This can't be, else notify Dsen!\n"));

            /* Make sure we update always a bigger rectangle than requested to
             * catch all rounding errors. (use 1 time the ratio factor and
             * round down on top/left, but round up for the width/height) */
            viewport()->update((int)(pPaintEvent->x() * xRatio) - ((int)xRatio) - 1,
                               (int)(pPaintEvent->y() * yRatio) - ((int)yRatio) - 1,
                               (int)(pPaintEvent->width() * xRatio) + ((int)xRatio + 2) * 2,
                               (int)(pPaintEvent->height() * yRatio) + ((int)yRatio + 2) * 2);
            pEvent->accept();
            return true;
        }

        default:
            break;
    }
    return UIMachineView::event(pEvent);
}
void UIMachineViewScale::prepareFrameBuffer()
{
    /* That method is partial copy-paste of UIMachineView::prepareFrameBuffer()
     * and its temporary here just because not all of our frame-buffers are currently supports scale-mode;
     * When all of our frame-buffers will be supporting scale-mode, method will be removed!
     * Here we are processing only these frame-buffer types, which knows scale-mode! */

    /* Prepare frame-buffer depending on render-mode: */
    switch (vboxGlobal().vmRenderMode())
    {
#ifdef VBOX_GUI_USE_QUARTZ2D
        case VBoxDefs::Quartz2DMode:
            /* Indicate that we are doing all drawing stuff ourself: */
            viewport()->setAttribute(Qt::WA_PaintOnScreen);
            m_pFrameBuffer = new UIFrameBufferQuartz2D(this);
            break;
#endif /* VBOX_GUI_USE_QUARTZ2D */
        default:
#ifdef VBOX_GUI_USE_QIMAGE
        case VBoxDefs::QImageMode:
            m_pFrameBuffer = new UIFrameBufferQImage(this);
            break;
#endif /* VBOX_GUI_USE_QIMAGE */
            AssertReleaseMsgFailed(("Scale-mode is currently NOT supporting that render-mode: %d\n", vboxGlobal().vmRenderMode()));
            LogRel(("Scale-mode is currently NOT supporting that render-mode: %d\n", vboxGlobal().vmRenderMode()));
            qApp->exit(1);
            break;
    }

    /* If frame-buffer was prepared: */
    if (m_pFrameBuffer)
    {
        /* Prepare display: */
        CDisplay display = session().GetConsole().GetDisplay();
        Assert(!display.isNull());
        m_pFrameBuffer->AddRef();
        display.SetFramebuffer(m_uScreenId, CFramebuffer(m_pFrameBuffer));
    }

    QSize size;
#ifdef Q_WS_X11
    /* Processing pseudo resize-event to synchronize frame-buffer with stored
     * framebuffer size. On X11 this will be additional done when the machine
     * state was 'saved'. */
    if (session().GetMachine().GetState() == KMachineState_Saved)
        size = guestSizeHint();
#endif /* Q_WS_X11 */
    /* If there is a preview image saved, we will resize the framebuffer to the
     * size of that image. */
    ULONG buffer = 0, width = 0, height = 0;
    CMachine machine = session().GetMachine();
    machine.QuerySavedScreenshotPNGSize(0, buffer, width, height);
    if (buffer > 0)
    {
        /* Init with the screenshot size */
        size = QSize(width, height);
        /* Try to get the real guest dimensions from the save state */
        ULONG guestWidth = 0, guestHeight = 0;
        machine.QuerySavedGuestSize(0, guestWidth, guestHeight);
        if (   guestWidth  > 0
            && guestHeight > 0)
            size = QSize(guestWidth, guestHeight);
    }
    /* If we have a valid size, resize the framebuffer. */
    if (   size.width() > 0
        && size.height() > 0)
    {
        UIResizeEvent event(FramebufferPixelFormat_Opaque, NULL, 0, 0, size.width(), size.height());
        frameBuffer()->resizeEvent(&event);
    }
}
Пример #27
0
int main()
{
	Engine engine(screenWidth, screenHeight);
	if(!engine.init())
	{
		GLFWwindow* window = engine.getWindow();

		// Set the required callback functions
		glfwSetKeyCallback(window, key_callback);
		glfwSetCursorPosCallback(window, mouse_callback);
		glfwSetScrollCallback(window, scroll_callback);

		Model crytekSponza("../obj/crytek-sponza/sponza.obj", camera, engine);
		//Model teapot("../obj/teapot/teapot.obj", camera, engine);
		//Model dabrovicSponza("../obj/dabrovic-sponza/sponza.obj", camera, engine);
		//Model sibenikCathedral("../obj/sibenik-cathedral/sibenik.obj", camera, engine);
		//Model nanosuit("../obj/nanosuit/nanosuit.obj", camera, engine);
		//Shader shader("shaders/vertex.glsl", "shaders/fragment.glsl");

		if(glfwJoystickPresent(0))
		{
			cout << glfwGetJoystickName(0) << " : detected" << endl;
			cout << "Left stick : movement control" << endl;
			cout << "Right stick : camera control" << endl;
		}

		double ellapsed_time = glfwGetTime();

		Framebuffer::vertexQuad();
		Framebuffer frameBuffer(true, screenWidth, screenHeight);

		while(!glfwWindowShouldClose(window))
		{
			// Set frame time
			GLdouble currentFrame = glfwGetTime();
			deltaTime = currentFrame - lastFrame;
			lastFrame = currentFrame;

			// Check and call events
			glfwPollEvents();
			Do_Movement();

			glClearDepth(1.0);
			glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			//frameBuffer.enable();
			//glViewport(0, 0, 1280, 720);
			crytekSponza.Draw();
			//frameBuffer.disable();

			/*
			//glViewport(0, 0, 1280, 720);

			glClearDepth(1.0);
			glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			shader.Use();

			glEnable(GL_TEXTURE_2D);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, frameBuffer.getRenderedTexture());

			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, frameBuffer.getDepthTexture());
			
			Framebuffer::drawQuad();

			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
			*/

			/*
			glEnable(GL_SCISSOR_TEST);
			glScissor(0, 0, 1280, 720);
			glClear(GL_DEPTH_BUFFER_BIT);
			glViewport(0, 0, 300, 168);

			glEnable(GL_TEXTURE_2D);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, frameBuffer.getRenderedTexture());
			glUniform1i(glGetUniformLocation(shader.Program, "texBuffer"), 0);
			
			Framebuffer::drawQuad();

			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
			*/
			
			engine.swapBuffer();

			/*
			if((glfwGetTime() - ellapsed_time) / 1000.0 < 16.67)
				Sleep(static_cast<DWORD>(16.67 - ((glfwGetTime() - ellapsed_time) / 1000.0)));
			ellapsed_time = glfwGetTime();
			*/
		}
	}

	return 0;
}
void UIMachineViewScale::saveMachineViewSettings()
{
    /* Store guest size hint: */
    storeGuestSizeHint(QSize(frameBuffer()->width(), frameBuffer()->height()));
}
Пример #29
0
double UIMachineView::aspectRatio() const
{
    return frameBuffer() ? (double)(frameBuffer()->width()) / frameBuffer()->height() : 0;
}
Пример #30
0
List<BoundingBox> SWTHelperGPU::StrokeWidthTransform(const cv::Mat &input)
{
    glFinish();
    auto startTime = now();
    
    DisableIrrelvantState();
    glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
    
    int width  = input.size().width;
    int height = input.size().height;
    // Create a Texture from the input
    Ptr<Texture> texture = textureFromImage<cv::Vec3f>(input);
    
    List< Ptr<Texture> > textures;
    
    /*for(int i = 0; i < 14; ++i)
        textures.push_back( New<Texture>(width, height, GL_RGBA, GL_FLOAT) );
    
    for(int i = 0; i < 14; ++i)
        textures[i].reset();
    */
    
    // Create the framebuffer attachments
    auto colorf       = New<Texture>(GL_RGBA,          width, height, GL_RGBA,          GL_FLOAT);
    auto depthStencil = New<Texture>(GL_DEPTH_STENCIL, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
    //Ptr<RenderBuffer> depthStencil = New<RenderBuffer>(width, height, RenderBufferType::DepthStencil);
    
    // Create and setup framebuffer
    FrameBuffer frameBuffer(colorf);
    //frameBuffer.SetDepthStencil(depthStencil);
    
    // Create a full-screen rect
    DrawableRect rect(-1, -1, 1, 1);
    GraphicsDevice::SetDefaultBuffers(rect.VertexBuffer, rect.IndexBuffer);
    GraphicsDevice::UseDefaultBuffers();
    
    frameBuffer.Bind();

    auto textRegionsFilter = New<TextRegionsFilter>(texture);
    textRegionsFilter->DoLoadShaderPrograms();
    
    glFinish();
    auto setupTime = now() - startTime;
    
    ApplyPass(textRegionsFilter);
    
    //FrameBuffer::GetCurrentlyBound()->Print(RenderBufferType::Stencil);
    
    glFinish();
    auto totalTime = now() - startTime;
    
    auto misc = totalTime - renderTime - setupTime;
    
    printf("\n");
    printf("Total time: %.1fms\n",           GetTimeMsec(totalTime));
    printf("Setup time: %.1fms (%.1f%%)\n",  GetTimeMsec(setupTime),  setupTime  * 100.0f / totalTime);
    printf("Render time: %.1fms (%.1f%%)\n", GetTimeMsec(renderTime), renderTime * 100.0f / totalTime);
    printf("Misc time: %.1fms (%.1f%%)\n",   GetTimeMsec(misc),       misc       * 100.0f / totalTime);
    printf("Textures: Active %i Peak %i\n",  Texture::ActiveTextureCount, Texture::PeakTextureCount);
    
    return textRegionsFilter->ExtractedBoundingBoxes;
}