From c7397523e77578cf8f09ba3258791f68c34e2e5f Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 27 Nov 2015 11:56:50 +0100 Subject: Windows: Improve EVR presenter. Removed hard dependency to Angle; it's now required only when rendering to a texture. If Angle is not used, the buffers are now mappable to system memory. This enables HW-accelerated video decoding in QML for non-ANGLE builds. Note that the frame data have to do a round-trip through system memory, which is not ideal but still faster than SW decoding. Task-number: QTBUG-45593 Change-Id: Icc3503142df4e8dbb53b4e11f409b161fd2f9bde Reviewed-by: Christian Stromme --- src/plugins/common/evr/evrd3dpresentengine.cpp | 741 ++++++++++++------------- 1 file changed, 362 insertions(+), 379 deletions(-) (limited to 'src/plugins/common/evr/evrd3dpresentengine.cpp') diff --git a/src/plugins/common/evr/evrd3dpresentengine.cpp b/src/plugins/common/evr/evrd3dpresentengine.cpp index 61cee88d7..77cd7e0c8 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.cpp +++ b/src/plugins/common/evr/evrd3dpresentengine.cpp @@ -35,48 +35,23 @@ #include "evrhelpers.h" -#include -#include -#include #include #include #include #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include +#include + +#ifdef MAYBE_ANGLE +# include +# include +# include +# include +#endif static const int PRESENTER_BUFFER_COUNT = 3; -class TextureVideoBuffer : public QAbstractVideoBuffer -{ -public: - TextureVideoBuffer(GLuint textureId) - : QAbstractVideoBuffer(GLTextureHandle) - , m_textureId(textureId) - {} - - ~TextureVideoBuffer() {} - - MapMode mapMode() const { return NotMapped; } - uchar *map(MapMode, int*, int*) { return 0; } - void unmap() {} - - QVariant handle() const - { - return QVariant::fromValue(m_textureId); - } - -private: - GLuint m_textureId; -}; +#ifdef MAYBE_ANGLE EGLWrapper::EGLWrapper() { @@ -140,22 +115,160 @@ EGLBoolean EGLWrapper::releaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLin return m_eglReleaseTexImage(dpy, surface, buffer); } + +class OpenGLResources : public QObject +{ +public: + OpenGLResources() + : egl(new EGLWrapper) + , eglDisplay(0) + , eglSurface(0) + , glTexture(0) + {} + + void release() + { + if (thread() == QThread::currentThread()) + delete this; + else + deleteLater(); + } + + EGLWrapper *egl; + EGLDisplay *eglDisplay; + EGLSurface eglSurface; + unsigned int glTexture; + +private: + ~OpenGLResources() + { + Q_ASSERT(QOpenGLContext::currentContext() != NULL); + + if (eglSurface && egl) { + egl->releaseTexImage(eglDisplay, eglSurface, EGL_BACK_BUFFER); + egl->destroySurface(eglDisplay, eglSurface); + } + if (glTexture) + QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &glTexture); + + delete egl; + } +}; + +#endif // MAYBE_ANGLE + + +class IMFSampleVideoBuffer: public QAbstractVideoBuffer +{ +public: + IMFSampleVideoBuffer(D3DPresentEngine *engine, IMFSample *sample, QAbstractVideoBuffer::HandleType handleType) + : QAbstractVideoBuffer(handleType) + , m_engine(engine) + , m_sample(sample) + , m_surface(0) + , m_mapMode(NotMapped) + , m_textureUpdated(false) + { + if (m_sample) { + m_sample->AddRef(); + + IMFMediaBuffer *buffer; + if (SUCCEEDED(m_sample->GetBufferByIndex(0, &buffer))) { + MFGetService(buffer, + mr_BUFFER_SERVICE, + iid_IDirect3DSurface9, + reinterpret_cast(&m_surface)); + buffer->Release(); + } + } + } + + ~IMFSampleVideoBuffer() + { + if (m_surface) { + if (m_mapMode != NotMapped) + m_surface->UnlockRect(); + m_surface->Release(); + } + if (m_sample) + m_sample->Release(); + } + + QVariant handle() const; + + MapMode mapMode() const { return m_mapMode; } + uchar *map(MapMode, int*, int*); + void unmap(); + +private: + mutable D3DPresentEngine *m_engine; + IMFSample *m_sample; + IDirect3DSurface9 *m_surface; + MapMode m_mapMode; + mutable bool m_textureUpdated; +}; + +uchar *IMFSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +{ + if (!m_surface || m_mapMode != NotMapped) + return 0; + + D3DSURFACE_DESC desc; + if (FAILED(m_surface->GetDesc(&desc))) + return 0; + + D3DLOCKED_RECT rect; + if (FAILED(m_surface->LockRect(&rect, NULL, mode == ReadOnly ? D3DLOCK_READONLY : 0))) + return 0; + + m_mapMode = mode; + + if (numBytes) + *numBytes = (int)(rect.Pitch * desc.Height); + + if (bytesPerLine) + *bytesPerLine = (int)rect.Pitch; + + return reinterpret_cast(rect.pBits); +} + +void IMFSampleVideoBuffer::unmap() +{ + if (m_mapMode == NotMapped) + return; + + m_mapMode = NotMapped; + m_surface->UnlockRect(); +} + +QVariant IMFSampleVideoBuffer::handle() const +{ + QVariant handle; + +#ifdef MAYBE_ANGLE + if (handleType() != GLTextureHandle) + return handle; + + if (m_textureUpdated || m_engine->updateTexture(m_surface)) { + m_textureUpdated = true; + handle = QVariant::fromValue(m_engine->m_glResources->glTexture); + } +#endif + + return handle; +} + + D3DPresentEngine::D3DPresentEngine() - : QObject() - , m_mutex(QMutex::Recursive) - , m_deviceResetToken(0) + : m_deviceResetToken(0) , m_D3D9(0) , m_device(0) , m_deviceManager(0) - , m_surface(0) - , m_glContext(0) - , m_offscreenSurface(0) - , m_eglDisplay(0) - , m_eglConfig(0) - , m_eglSurface(0) - , m_glTexture(0) + , m_useTextureRendering(false) +#ifdef MAYBE_ANGLE + , m_glResources(0) , m_texture(0) - , m_egl(0) +#endif { ZeroMemory(&m_displayMode, sizeof(m_displayMode)); @@ -172,47 +285,110 @@ D3DPresentEngine::D3DPresentEngine() D3DPresentEngine::~D3DPresentEngine() { - qt_evr_safe_release(&m_texture); + releaseResources(); + qt_evr_safe_release(&m_device); qt_evr_safe_release(&m_deviceManager); qt_evr_safe_release(&m_D3D9); +} - if (m_eglSurface) { - m_egl->releaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER); - m_egl->destroySurface(m_eglDisplay, m_eglSurface); - m_eglSurface = NULL; - } - if (m_glTexture) { - if (QOpenGLContext *current = QOpenGLContext::currentContext()) - current->functions()->glDeleteTextures(1, &m_glTexture); - else - qWarning() << "D3DPresentEngine: Cannot obtain GL context, unable to delete textures"; - } +HRESULT D3DPresentEngine::initializeD3D() +{ + HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_D3D9); - delete m_glContext; - delete m_offscreenSurface; - delete m_egl; + if (SUCCEEDED(hr)) + hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, &m_deviceManager); + + return hr; } -void D3DPresentEngine::start() +HRESULT D3DPresentEngine::createD3DDevice() { - QMutexLocker locker(&m_mutex); + HRESULT hr = S_OK; + HWND hwnd = NULL; + UINT uAdapterID = D3DADAPTER_DEFAULT; + DWORD vp = 0; - if (!m_surfaceFormat.isValid()) - return; + D3DCAPS9 ddCaps; + ZeroMemory(&ddCaps, sizeof(ddCaps)); + + IDirect3DDevice9Ex* device = NULL; + + if (!m_D3D9 || !m_deviceManager) + return MF_E_NOT_INITIALIZED; + + hwnd = ::GetShellWindow(); + + D3DPRESENT_PARAMETERS pp; + ZeroMemory(&pp, sizeof(pp)); + + pp.BackBufferWidth = 1; + pp.BackBufferHeight = 1; + pp.BackBufferFormat = D3DFMT_UNKNOWN; + pp.BackBufferCount = 1; + pp.Windowed = TRUE; + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.BackBufferFormat = D3DFMT_UNKNOWN; + pp.hDeviceWindow = hwnd; + pp.Flags = D3DPRESENTFLAG_VIDEO; + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - if (!m_texture) - createOffscreenTexture(); + hr = m_D3D9->GetDeviceCaps(uAdapterID, D3DDEVTYPE_HAL, &ddCaps); + if (FAILED(hr)) + goto done; + + if (ddCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) + vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; + else + vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; - if (m_surface && !m_surface->isActive()) - m_surface->start(m_surfaceFormat); + hr = m_D3D9->CreateDeviceEx( + uAdapterID, + D3DDEVTYPE_HAL, + pp.hDeviceWindow, + vp | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, + &pp, + NULL, + &device + ); + if (FAILED(hr)) + goto done; + + hr = m_D3D9->GetAdapterDisplayMode(uAdapterID, &m_displayMode); + if (FAILED(hr)) + goto done; + + hr = m_deviceManager->ResetDevice(device, m_deviceResetToken); + if (FAILED(hr)) + goto done; + + qt_evr_safe_release(&m_device); + + m_device = device; + m_device->AddRef(); + +done: + qt_evr_safe_release(&device); + return hr; } -void D3DPresentEngine::stop() +bool D3DPresentEngine::isValid() const { - QMutexLocker locker(&m_mutex); - if (m_surface && m_surface->isActive()) - m_surface->stop(); + return m_device != NULL; +} + +void D3DPresentEngine::releaseResources() +{ + m_surfaceFormat = QVideoSurfaceFormat(); + +#ifdef MAYBE_ANGLE + qt_evr_safe_release(&m_texture); + + if (m_glResources) { + m_glResources->release(); // deleted in GL thread + m_glResources = NULL; + } +#endif } HRESULT D3DPresentEngine::getService(REFGUID, REFIID riid, void** ppv) @@ -235,33 +411,52 @@ HRESULT D3DPresentEngine::getService(REFGUID, REFIID riid, void** ppv) HRESULT D3DPresentEngine::checkFormat(D3DFORMAT format) { - HRESULT hr = S_OK; + if (!m_D3D9 || !m_device) + return E_FAIL; - UINT uAdapter = D3DADAPTER_DEFAULT; - D3DDEVTYPE type = D3DDEVTYPE_HAL; + HRESULT hr = S_OK; D3DDISPLAYMODE mode; D3DDEVICE_CREATION_PARAMETERS params; - // Our shared D3D/EGL surface only supports RGB32, - // reject all other formats - if (format != D3DFMT_X8R8G8B8) - return MF_E_INVALIDMEDIATYPE; - - if (m_device) { - hr = m_device->GetCreationParameters(¶ms); - if (FAILED(hr)) - return hr; + hr = m_device->GetCreationParameters(¶ms); + if (FAILED(hr)) + return hr; - uAdapter = params.AdapterOrdinal; - type = params.DeviceType; - } + UINT uAdapter = params.AdapterOrdinal; + D3DDEVTYPE type = params.DeviceType; hr = m_D3D9->GetAdapterDisplayMode(uAdapter, &mode); if (FAILED(hr)) return hr; - return m_D3D9->CheckDeviceType(uAdapter, type, mode.Format, format, TRUE); + hr = m_D3D9->CheckDeviceFormat(uAdapter, type, mode.Format, + D3DUSAGE_RENDERTARGET, + D3DRTYPE_SURFACE, + format); + + if (m_useTextureRendering && format != D3DFMT_X8R8G8B8 && format != D3DFMT_A8R8G8B8) { + // The texture is always in RGB32 so the d3d driver must support conversion from the + // requested format to RGB32. + hr = m_D3D9->CheckDeviceFormatConversion(uAdapter, type, format, D3DFMT_X8R8G8B8); + } + + return hr; +} + +bool D3DPresentEngine::supportsTextureRendering() const +{ +#ifdef MAYBE_ANGLE + return QMediaOpenGLHelper::isANGLE(); +#else + return false; +#endif +} + +void D3DPresentEngine::setHint(Hint hint, bool enable) +{ + if (hint == RenderToTexture) + m_useTextureRendering = enable && supportsTextureRendering(); } HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QList &videoSampleQueue) @@ -270,211 +465,148 @@ HRESULT D3DPresentEngine::createVideoSamples(IMFMediaType *format, QListCreateAdditionalSwapChain(&pp, &swapChain); + hr = m_device->CreateRenderTarget(width, height, + (D3DFORMAT)d3dFormat, + D3DMULTISAMPLE_NONE, + 0, + TRUE, + &surface, NULL); if (FAILED(hr)) goto done; - // Create the video sample from the swap chain. - hr = createD3DSample(swapChain, &videoSample); + hr = MFCreateVideoSampleFromSurface(surface, &videoSample); if (FAILED(hr)) goto done; - // Add it to the list. videoSample->AddRef(); videoSampleQueue.append(videoSample); - // Set the swap chain pointer as a custom attribute on the sample. This keeps - // a reference count on the swap chain, so that the swap chain is kept alive - // for the duration of the sample's lifetime. - hr = videoSample->SetUnknown(MFSamplePresenter_SampleSwapChain, swapChain); - if (FAILED(hr)) - goto done; - qt_evr_safe_release(&videoSample); - qt_evr_safe_release(&swapChain); + qt_evr_safe_release(&surface); } done: - if (FAILED(hr)) + if (SUCCEEDED(hr)) { + m_surfaceFormat = QVideoSurfaceFormat(QSize(width, height), + m_useTextureRendering ? QVideoFrame::Format_RGB32 + : qt_evr_pixelFormatFromD3DFormat((D3DFORMAT)d3dFormat), + m_useTextureRendering ? QAbstractVideoBuffer::GLTextureHandle + : QAbstractVideoBuffer::NoHandle); + } else { releaseResources(); + } - qt_evr_safe_release(&swapChain); qt_evr_safe_release(&videoSample); + qt_evr_safe_release(&surface); return hr; } -void D3DPresentEngine::releaseResources() +QVideoFrame D3DPresentEngine::makeVideoFrame(IMFSample *sample) { -} + if (!sample) + return QVideoFrame(); -void D3DPresentEngine::presentSample(void *opaque, qint64) -{ - HRESULT hr = S_OK; + QVideoFrame frame(new IMFSampleVideoBuffer(this, sample, m_surfaceFormat.handleType()), + m_surfaceFormat.frameSize(), + m_surfaceFormat.pixelFormat()); - IMFSample *sample = reinterpret_cast(opaque); - IMFMediaBuffer* buffer = NULL; - IDirect3DSurface9* surface = NULL; - - if (m_surface && m_surface->isActive()) { - if (sample) { - // Get the buffer from the sample. - hr = sample->GetBufferByIndex(0, &buffer); - if (FAILED(hr)) - goto done; - - // Get the surface from the buffer. - hr = MFGetService(buffer, mr_BUFFER_SERVICE, IID_PPV_ARGS(&surface)); - if (FAILED(hr)) - goto done; - } + // WMF uses 100-nanosecond units, Qt uses microseconds + LONGLONG startTime = -1; + if (SUCCEEDED(sample->GetSampleTime(&startTime))) { + frame.setStartTime(startTime * 0.1); - if (surface && updateTexture(surface)) { - QVideoFrame frame = QVideoFrame(new TextureVideoBuffer(m_glTexture), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat()); - - // WMF uses 100-nanosecond units, Qt uses microseconds - LONGLONG startTime = -1; - if (SUCCEEDED(sample->GetSampleTime(&startTime))) { - frame.setStartTime(startTime * 0.1); - - LONGLONG duration = -1; - if (SUCCEEDED(sample->GetSampleDuration(&duration))) - frame.setEndTime((startTime + duration) * 0.1); - } - - m_surface->present(frame); - } + LONGLONG duration = -1; + if (SUCCEEDED(sample->GetSampleDuration(&duration))) + frame.setEndTime((startTime + duration) * 0.1); } -done: - qt_evr_safe_release(&surface); - qt_evr_safe_release(&buffer); - qt_evr_safe_release(&sample); + return frame; } -void D3DPresentEngine::setSurface(QAbstractVideoSurface *surface) -{ - QMutexLocker locker(&m_mutex); - m_surface = surface; -} +#ifdef MAYBE_ANGLE -void D3DPresentEngine::setSurfaceFormat(const QVideoSurfaceFormat &format) +bool D3DPresentEngine::createRenderTexture() { - QMutexLocker locker(&m_mutex); - m_surfaceFormat = format; -} + if (m_texture) + return true; -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(m_surface->property("GLContext").value()); - 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; - } + Q_ASSERT(QOpenGLContext::currentContext() != NULL); - if (m_glContext) - m_glContext->makeCurrent(m_offscreenSurface); + if (!m_glResources) + m_glResources = new OpenGLResources; - if (!m_egl) - m_egl = new EGLWrapper; + QOpenGLContext *currentContext = QOpenGLContext::currentContext(); + if (!currentContext) + return false; QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - m_eglDisplay = static_cast( + m_glResources->eglDisplay = static_cast( nativeInterface->nativeResourceForContext("eglDisplay", currentContext)); - m_eglConfig = static_cast( + EGLConfig *eglConfig = static_cast( nativeInterface->nativeResourceForContext("eglConfig", currentContext)); - currentContext->functions()->glGenTextures(1, &m_glTexture); + currentContext->functions()->glGenTextures(1, &m_glResources->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_WIDTH, m_surfaceFormat.frameWidth(), + EGL_HEIGHT, m_surfaceFormat.frameHeight(), 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); + EGLSurface pbuffer = m_glResources->egl->createPbufferSurface(m_glResources->eglDisplay, eglConfig, attribs); HANDLE share_handle = 0; PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = - reinterpret_cast(m_egl->getProcAddress("eglQuerySurfacePointerANGLE")); + reinterpret_cast(m_glResources->egl->getProcAddress("eglQuerySurfacePointerANGLE")); Q_ASSERT(eglQuerySurfacePointerANGLE); eglQuerySurfacePointerANGLE( - m_eglDisplay, + m_glResources->eglDisplay, pbuffer, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle); - m_device->CreateTexture(w, h, 1, + m_device->CreateTexture(m_surfaceFormat.frameWidth(), m_surfaceFormat.frameHeight(), 1, D3DUSAGE_RENDERTARGET, hasAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_texture, &share_handle); - m_eglSurface = pbuffer; + m_glResources->eglSurface = pbuffer; + + QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, m_glResources->glTexture); + m_glResources->egl->bindTexImage(m_glResources->eglDisplay, m_glResources->eglSurface, EGL_BACK_BUFFER); - if (m_glContext) - m_glContext->doneCurrent(); + return m_texture != NULL; } bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src) { - if (!m_texture) + if (!m_texture && !createRenderTexture()) return false; - if (m_glContext) - m_glContext->makeCurrent(m_offscreenSurface); - - QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, m_glTexture); - IDirect3DSurface9 *dest = NULL; // Copy the sample surface to the shared D3D/EGL surface @@ -483,173 +615,24 @@ bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src) goto done; hr = m_device->StretchRect(src, NULL, dest, NULL, D3DTEXF_NONE); - if (FAILED(hr)) + if (FAILED(hr)) { qWarning("Failed to copy D3D surface"); - - if (hr == S_OK) - m_egl->bindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER); + } else { + // Shared surfaces are not synchronized, there's no guarantee that + // StretchRect is complete when the texture is later rendered by Qt. + // To make sure the next rendered frame is up to date, flush the command pipeline + // using an event query. + IDirect3DQuery9 *eventQuery = NULL; + m_device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery); + eventQuery->Issue(D3DISSUE_END); + while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE); + eventQuery->Release(); + } done: qt_evr_safe_release(&dest); - if (m_glContext) - m_glContext->doneCurrent(); - return SUCCEEDED(hr); } -HRESULT D3DPresentEngine::initializeD3D() -{ - HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_D3D9); - - if (SUCCEEDED(hr)) - hr = DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, &m_deviceManager); - - return hr; -} - -HRESULT D3DPresentEngine::createD3DDevice() -{ - HRESULT hr = S_OK; - HWND hwnd = NULL; - UINT uAdapterID = D3DADAPTER_DEFAULT; - DWORD vp = 0; - - D3DCAPS9 ddCaps; - ZeroMemory(&ddCaps, sizeof(ddCaps)); - - IDirect3DDevice9Ex* device = NULL; - - // Hold the lock because we might be discarding an existing device. - QMutexLocker locker(&m_mutex); - - if (!m_D3D9 || !m_deviceManager) - return MF_E_NOT_INITIALIZED; - - hwnd = ::GetShellWindow(); - - // Note: The presenter creates additional swap chains to present the - // video frames. Therefore, it does not use the device's implicit - // swap chain, so the size of the back buffer here is 1 x 1. - - D3DPRESENT_PARAMETERS pp; - ZeroMemory(&pp, sizeof(pp)); - - pp.BackBufferWidth = 1; - pp.BackBufferHeight = 1; - pp.BackBufferFormat = D3DFMT_UNKNOWN; - pp.BackBufferCount = 1; - pp.Windowed = TRUE; - pp.SwapEffect = D3DSWAPEFFECT_DISCARD; - pp.BackBufferFormat = D3DFMT_UNKNOWN; - pp.hDeviceWindow = hwnd; - pp.Flags = D3DPRESENTFLAG_VIDEO; - pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - - hr = m_D3D9->GetDeviceCaps(uAdapterID, D3DDEVTYPE_HAL, &ddCaps); - if (FAILED(hr)) - goto done; - - if (ddCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) - vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; - else - vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; - - hr = m_D3D9->CreateDeviceEx( - uAdapterID, - D3DDEVTYPE_HAL, - pp.hDeviceWindow, - vp | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, - &pp, - NULL, - &device - ); - if (FAILED(hr)) - goto done; - - hr = m_D3D9->GetAdapterDisplayMode(uAdapterID, &m_displayMode); - if (FAILED(hr)) - goto done; - - hr = m_deviceManager->ResetDevice(device, m_deviceResetToken); - if (FAILED(hr)) - goto done; - - qt_evr_safe_release(&m_device); - - m_device = device; - m_device->AddRef(); - -done: - qt_evr_safe_release(&device); - return hr; -} - -HRESULT D3DPresentEngine::createD3DSample(IDirect3DSwapChain9 *swapChain, IMFSample **videoSample) -{ - D3DCOLOR clrBlack = D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0x00); - - IDirect3DSurface9* surface = NULL; - IMFSample* sample = NULL; - - // Get the back buffer surface. - HRESULT hr = swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface); - if (FAILED(hr)) - goto done; - - // Fill it with black. - hr = m_device->ColorFill(surface, NULL, clrBlack); - if (FAILED(hr)) - goto done; - - hr = MFCreateVideoSampleFromSurface(surface, &sample); - if (FAILED(hr)) - goto done; - - *videoSample = sample; - (*videoSample)->AddRef(); - -done: - qt_evr_safe_release(&surface); - qt_evr_safe_release(&sample); - return hr; -} - -HRESULT D3DPresentEngine::getSwapChainPresentParameters(IMFMediaType *type, D3DPRESENT_PARAMETERS* pp) -{ - ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS)); - - // Get some information about the video format. - - UINT32 width = 0, height = 0; - - HRESULT hr = MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width, &height); - if (FAILED(hr)) - return hr; - - DWORD d3dFormat = 0; - - hr = qt_evr_getFourCC(type, &d3dFormat); - if (FAILED(hr)) - return hr; - - ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS)); - pp->BackBufferWidth = width; - pp->BackBufferHeight = height; - pp->Windowed = TRUE; - pp->SwapEffect = D3DSWAPEFFECT_DISCARD; - pp->BackBufferFormat = (D3DFORMAT)d3dFormat; - pp->hDeviceWindow = ::GetShellWindow(); - pp->Flags = D3DPRESENTFLAG_VIDEO; - pp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - - D3DDEVICE_CREATION_PARAMETERS params; - hr = m_device->GetCreationParameters(¶ms); - if (FAILED(hr)) - return hr; - - if (params.DeviceType != D3DDEVTYPE_HAL) - pp->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; - - return S_OK; -} +#endif // MAYBE_ANGLE -- cgit v1.2.3