mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Backed out changeset c4ecea1452e9 (bug 947781)
This commit is contained in:
parent
f6dad403d3
commit
46d9238c0a
@ -54,12 +54,6 @@ DIBTextureClient::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
|
||||
if (mDrawTarget) {
|
||||
if (mReadbackSink) {
|
||||
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
|
||||
mReadbackSink->ProcessReadback(dataSurf);
|
||||
}
|
||||
|
||||
mDrawTarget->Flush();
|
||||
mDrawTarget = nullptr;
|
||||
}
|
||||
|
@ -731,12 +731,6 @@ BufferTextureClient::Unlock()
|
||||
// reference remains by the time Unlock() is called.
|
||||
MOZ_ASSERT(mDrawTarget->refCount() == 1);
|
||||
|
||||
if (mReadbackSink) {
|
||||
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
|
||||
mReadbackSink->ProcessReadback(dataSurf);
|
||||
}
|
||||
|
||||
mDrawTarget->Flush();
|
||||
mDrawTarget = nullptr;
|
||||
}
|
||||
|
@ -89,24 +89,6 @@ public:
|
||||
StereoMode aStereoMode) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class may be used to asynchronously receive an update when the content
|
||||
* drawn to this texture client is available for reading in CPU memory. This
|
||||
* can only be used on texture clients that support draw target creation.
|
||||
*/
|
||||
class TextureReadbackSink
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadbackSink)
|
||||
public:
|
||||
/**
|
||||
* Callback function to implement in order to receive a DataSourceSurface
|
||||
* containing the data read back from the texture client. This will always
|
||||
* be called on the main thread, and this may not hold on to the
|
||||
* DataSourceSurface beyond the execution of this function.
|
||||
*/
|
||||
virtual void ProcessReadback(gfx::DataSourceSurface *aSourceSurface) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient is a thin abstraction over texture data that need to be shared
|
||||
* between the content process and the compositor process. It is the
|
||||
@ -391,15 +373,6 @@ public:
|
||||
mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
|
||||
}
|
||||
|
||||
/**
|
||||
* This sets the readback sink that this texture is to use. This will
|
||||
* receive the data for this texture as soon as it becomes available after
|
||||
* texture unlock.
|
||||
*/
|
||||
virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
|
||||
mReadbackSink = aReadbackSink;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called once, just before the destructor.
|
||||
@ -448,8 +421,6 @@ protected:
|
||||
bool mShared;
|
||||
bool mValid;
|
||||
|
||||
RefPtr<TextureReadbackSink> mReadbackSink;
|
||||
|
||||
friend class TextureChild;
|
||||
friend class RemoveTextureFromCompositableTracker;
|
||||
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
|
||||
|
@ -1,159 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ReadbackManagerD3D11.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
#include "ReadbackLayer.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
namespace layers {
|
||||
|
||||
// Structure that contains the information required to execute a readback task,
|
||||
// the only member accessed off the main thread here is mReadbackTexture. Since
|
||||
// mSink may be released only on the main thread this object should always be
|
||||
// destroyed on the main thread!
|
||||
struct ReadbackTask {
|
||||
// The texture that we copied the contents of the thebeslayer to.
|
||||
nsRefPtr<ID3D10Texture2D> mReadbackTexture;
|
||||
// The sink that we're trying to read back to.
|
||||
RefPtr<TextureReadbackSink> mSink;
|
||||
};
|
||||
|
||||
// This class is created and dispatched from the Readback thread but it must be
|
||||
// destroyed by the main thread.
|
||||
class ReadbackResultWriterD3D11 MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
~ReadbackResultWriterD3D11() {}
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
public:
|
||||
ReadbackResultWriterD3D11(ReadbackTask *aTask) : mTask(aTask) {}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTask->mReadbackTexture->GetDesc(&desc);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
// We know this map will immediately succeed, as we've already mapped this
|
||||
// copied data on our task thread.
|
||||
HRESULT hr = mTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
mTask->mSink->ProcessReadback(nullptr);
|
||||
}
|
||||
|
||||
{
|
||||
RefPtr<DataSourceSurface> surf =
|
||||
Factory::CreateWrappingDataSourceSurface((uint8_t*)mappedTex.pData, mappedTex.RowPitch,
|
||||
IntSize(desc.Width, desc.Height),
|
||||
SurfaceFormat::B8G8R8X8);
|
||||
|
||||
mTask->mSink->ProcessReadback(surf);
|
||||
|
||||
MOZ_ASSERT(surf->hasOneRef());
|
||||
}
|
||||
|
||||
mTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<ReadbackTask> mTask;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ReadbackResultWriterD3D11, nsIRunnable)
|
||||
|
||||
static DWORD WINAPI StartTaskThread(void *aManager)
|
||||
{
|
||||
static_cast<ReadbackManagerD3D11*>(aManager)->ProcessTasks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReadbackManagerD3D11::ReadbackManagerD3D11()
|
||||
: mRefCnt(0)
|
||||
{
|
||||
::InitializeCriticalSection(&mTaskMutex);
|
||||
mShutdownEvent = ::CreateEventA(nullptr, FALSE, FALSE, nullptr);
|
||||
mTaskSemaphore = ::CreateSemaphoreA(nullptr, 0, 1000000, nullptr);
|
||||
mTaskThread = ::CreateThread(nullptr, 0, StartTaskThread, this, 0, 0);
|
||||
}
|
||||
|
||||
ReadbackManagerD3D11::~ReadbackManagerD3D11()
|
||||
{
|
||||
::SetEvent(mShutdownEvent);
|
||||
|
||||
// This shouldn't take longer than 5 seconds, if it does we're going to choose
|
||||
// to leak the thread and its synchronisation in favor of crashing or freezing
|
||||
DWORD result = ::WaitForSingleObject(mTaskThread, 5000);
|
||||
if (result != WAIT_TIMEOUT) {
|
||||
::DeleteCriticalSection(&mTaskMutex);
|
||||
::CloseHandle(mShutdownEvent);
|
||||
::CloseHandle(mTaskSemaphore);
|
||||
::CloseHandle(mTaskThread);
|
||||
} else {
|
||||
NS_RUNTIMEABORT("ReadbackManager: Task thread did not shutdown in 5 seconds.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D11::PostTask(ID3D10Texture2D *aTexture, TextureReadbackSink* aSink)
|
||||
{
|
||||
ReadbackTask *task = new ReadbackTask;
|
||||
task->mReadbackTexture = aTexture;
|
||||
task->mSink = aSink;
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
mPendingReadbackTasks.AppendElement(task);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
::ReleaseSemaphore(mTaskSemaphore, 1, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D11::ProcessTasks()
|
||||
{
|
||||
HANDLE handles[] = { mTaskSemaphore, mShutdownEvent };
|
||||
|
||||
while (true) {
|
||||
DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (result != WAIT_OBJECT_0) {
|
||||
return;
|
||||
}
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
if (mPendingReadbackTasks.Length() == 0) {
|
||||
NS_RUNTIMEABORT("Trying to read from an empty array, bad bad bad");
|
||||
}
|
||||
ReadbackTask *nextReadbackTask = mPendingReadbackTasks[0].forget();
|
||||
mPendingReadbackTasks.RemoveElementAt(0);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
// We want to block here until the texture contents are available, the
|
||||
// easiest thing is to simply map and unmap.
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
nextReadbackTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
nextReadbackTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
// We can only send the update to the sink on the main thread, so post an
|
||||
// event there to do so. Ownership of the task is passed from
|
||||
// mPendingReadbackTasks to ReadbackResultWriter here.
|
||||
nsCOMPtr<nsIThread> thread = do_GetMainThread();
|
||||
thread->Dispatch(new ReadbackResultWriterD3D11(nextReadbackTask),
|
||||
nsIEventTarget::DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_READBACKMANAGERD3D11_H
|
||||
#define GFX_READBACKMANAGERD3D11_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d10_1.h>
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class TextureReadbackSink;
|
||||
struct ReadbackTask;
|
||||
|
||||
class ReadbackManagerD3D11 MOZ_FINAL
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(ReadbackManagerD3D11)
|
||||
public:
|
||||
ReadbackManagerD3D11();
|
||||
~ReadbackManagerD3D11();
|
||||
|
||||
/**
|
||||
* Tell the readback manager to post a readback task.
|
||||
*
|
||||
* @param aTexture D3D10_USAGE_STAGING texture that will contain the data that
|
||||
* was readback.
|
||||
* @param aSink TextureReadbackSink that the resulting DataSourceSurface
|
||||
* should be dispatched to.
|
||||
*/
|
||||
void PostTask(ID3D10Texture2D* aTexture, TextureReadbackSink* aSink);
|
||||
|
||||
private:
|
||||
friend DWORD WINAPI StartTaskThread(void *aManager);
|
||||
|
||||
void ProcessTasks();
|
||||
|
||||
// The invariant maintained by |mTaskSemaphore| is that the readback thread
|
||||
// will awaken from WaitForMultipleObjects() at least once per readback
|
||||
// task enqueued by the main thread. Since the readback thread processes
|
||||
// exactly one task per wakeup (with one exception), no tasks are lost. The
|
||||
// exception is when the readback thread is shut down, which orphans the
|
||||
// remaining tasks, on purpose.
|
||||
HANDLE mTaskSemaphore;
|
||||
// Event signaled when the task thread should shutdown
|
||||
HANDLE mShutdownEvent;
|
||||
// Handle to the task thread
|
||||
HANDLE mTaskThread;
|
||||
|
||||
// FiFo list of readback tasks that are to be executed. Access is synchronized
|
||||
// by mTaskMutex.
|
||||
CRITICAL_SECTION mTaskMutex;
|
||||
nsTArray<nsAutoPtr<ReadbackTask>> mPendingReadbackTasks;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GFX_READBACKMANAGERD3D11_H */
|
@ -11,7 +11,6 @@
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "ReadbackManagerD3D11.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -250,28 +249,6 @@ TextureClientD3D11::Unlock()
|
||||
mDrawTarget->Flush();
|
||||
}
|
||||
|
||||
if (mReadbackSink) {
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTexture->GetDesc(&desc);
|
||||
desc.BindFlags = 0;
|
||||
desc.Usage = D3D10_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
RefPtr<ID3D10Texture2D> tex;
|
||||
HRESULT hr = device->CreateTexture2D(&desc, nullptr, byRef(tex));
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
device->CopyResource(tex, mTexture);
|
||||
|
||||
gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, mReadbackSink);
|
||||
} else {
|
||||
mReadbackSink->ProcessReadback(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// The DrawTarget is created only once, and is only usable between calls
|
||||
// to Lock and Unlock.
|
||||
UnlockD3DTexture(mTexture.get());
|
||||
|
@ -80,7 +80,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
]
|
||||
EXPORTS.mozilla.layers += [
|
||||
'd3d11/CompositorD3D11.h',
|
||||
'd3d11/ReadbackManagerD3D11.h',
|
||||
'd3d11/TextureD3D11.h',
|
||||
'ipc/ShadowLayerUtilsD3D10.h',
|
||||
]
|
||||
@ -97,7 +96,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
]
|
||||
SOURCES += [
|
||||
'd3d11/CompositorD3D11.cpp',
|
||||
'd3d11/ReadbackManagerD3D11.cpp',
|
||||
]
|
||||
|
||||
EXPORTS.gfxipc += [
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include "mozilla/layers/CompositorParent.h" // for CompositorParent::IsInCompositorThread
|
||||
#include "DeviceManagerD3D9.h"
|
||||
#include "mozilla/layers/ReadbackManagerD3D11.h"
|
||||
|
||||
#include "WinUtils.h"
|
||||
|
||||
@ -1392,16 +1391,6 @@ gfxWindowsPlatform::GetD3D11Device()
|
||||
return mD3D11Device;
|
||||
}
|
||||
|
||||
ReadbackManagerD3D11*
|
||||
gfxWindowsPlatform::GetReadbackManager()
|
||||
{
|
||||
if (!mD3D11ReadbackManager) {
|
||||
mD3D11ReadbackManager = new ReadbackManagerD3D11();
|
||||
}
|
||||
|
||||
return mD3D11ReadbackManager;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::IsOptimus()
|
||||
{
|
||||
|
@ -46,7 +46,6 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class DeviceManagerD3D9;
|
||||
class ReadbackManagerD3D11;
|
||||
}
|
||||
}
|
||||
struct IDirect3DDevice9;
|
||||
@ -257,8 +256,6 @@ public:
|
||||
#endif
|
||||
ID3D11Device *GetD3D11Device();
|
||||
|
||||
mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
|
||||
|
||||
static bool IsOptimus();
|
||||
|
||||
protected:
|
||||
@ -287,7 +284,6 @@ private:
|
||||
nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
|
||||
mozilla::RefPtr<ID3D11Device> mD3D11Device;
|
||||
bool mD3D11DeviceInitialized;
|
||||
mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
|
||||
|
||||
virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user