Bug 1133007 - Send the content of a texture only if its was altered since previous transmission. r=kamidphish, r=boris

This commit is contained in:
CJKu 2015-06-02 06:21:00 -04:00
parent 2f0b75b8a7
commit d001f250e3
9 changed files with 220 additions and 140 deletions

View File

@ -178,37 +178,141 @@ private:
nsCOMPtr<nsIServerSocket> mServerSocket;
};
// Static class to create and destory LayerScopeWebSocketManager object
class WebSocketHelper
class DrawSession {
public:
DrawSession()
: mOffsetX(0.0)
, mOffsetY(0.0)
, mRects(0)
{ }
float mOffsetX;
float mOffsetY;
gfx::Matrix4x4 mMVMatrix;
size_t mRects;
gfx::Rect mLayerRects[4];
};
class ContentMonitor {
public:
using THArray = nsTArray<const TextureHost *>;
// Notify the content of a TextureHost was changed.
void SetChangedHost(const TextureHost* host) {
if (THArray::NoIndex == mChangedHosts.IndexOf(host)) {
mChangedHosts.AppendElement(host);
}
}
// Clear changed flag of a host.
void ClearChangedHost(const TextureHost* host) {
if (THArray::NoIndex != mChangedHosts.IndexOf(host)) {
mChangedHosts.RemoveElement(host);
}
}
// Return true iff host is a new one or the content of it had been changed.
bool IsChangedOrNew(const TextureHost* host) {
if (THArray::NoIndex == mSeenHosts.IndexOf(host)) {
mSeenHosts.AppendElement(host);
return true;
}
if (decltype(mChangedHosts)::NoIndex != mChangedHosts.IndexOf(host)) {
return true;
}
return false;
}
void Empty() {
mSeenHosts.SetLength(0);
mChangedHosts.SetLength(0);
}
private:
THArray mSeenHosts;
THArray mChangedHosts;
};
// Hold all singleton objects used by LayerScope
class LayerScopeManager
{
public:
static void CreateServerSocket()
void CreateServerSocket()
{
// Create Web Server Socket (which has to be on the main thread)
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
if (!sWebSocketManager) {
sWebSocketManager = new LayerScopeWebSocketManager();
// WebSocketManager must be created on the main thread.
if (NS_IsMainThread()) {
mWebSocketManager = mozilla::MakeUnique<LayerScopeWebSocketManager>();
} else {
// Dispatch creation to main thread, and make sure we
// dispatch this only once after booting
static bool dispatched = false;
if (dispatched) {
return;
}
DebugOnly<nsresult> rv =
NS_DispatchToMainThread(new CreateServerSocketRunnable(this));
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Failed to dispatch WebSocket Creation to main thread");
dispatched = true;
}
}
static void DestroyServerSocket()
void DestroyServerSocket()
{
// Destroy Web Server Socket
if (sWebSocketManager) {
sWebSocketManager->RemoveAllConnections();
if (mWebSocketManager) {
mWebSocketManager->RemoveAllConnections();
}
}
static LayerScopeWebSocketManager* GetSocketManager()
LayerScopeWebSocketManager* GetSocketManager()
{
return sWebSocketManager;
return mWebSocketManager.get();
}
ContentMonitor* GetContentMonitor()
{
if (!mContentMonitor.get()) {
mContentMonitor = mozilla::MakeUnique<ContentMonitor>();
}
return mContentMonitor.get();
}
void NewDrawSession() {
mSession = mozilla::MakeUnique<DrawSession>();
}
DrawSession& CurrentSession() {
return *mSession;
}
private:
static StaticAutoPtr<LayerScopeWebSocketManager> sWebSocketManager;
friend class CreateServerSocketRunnable;
class CreateServerSocketRunnable : public nsRunnable
{
public:
CreateServerSocketRunnable(LayerScopeManager *aLayerScopeManager)
: mLayerScopeManager(aLayerScopeManager)
{
}
NS_IMETHOD Run() {
mLayerScopeManager->mWebSocketManager =
mozilla::MakeUnique<LayerScopeWebSocketManager>();
return NS_OK;
}
private:
LayerScopeManager* mLayerScopeManager;
};
mozilla::UniquePtr<LayerScopeWebSocketManager> mWebSocketManager;
mozilla::UniquePtr<DrawSession> mSession;
mozilla::UniquePtr<ContentMonitor> mContentMonitor;
};
StaticAutoPtr<LayerScopeWebSocketManager> WebSocketHelper::sWebSocketManager;
LayerScopeManager gLayerScopeManager;
/*
* DebugGLData is the base class of
@ -230,13 +334,13 @@ public:
protected:
static bool WriteToStream(Packet& aPacket) {
if (!WebSocketHelper::GetSocketManager())
if (!gLayerScopeManager.GetSocketManager())
return true;
uint32_t size = aPacket.ByteSize();
auto data = MakeUnique<uint8_t[]>(size);
aPacket.SerializeToArray(data.get(), size);
return WebSocketHelper::GetSocketManager()->WriteAll(data.get(), size);
return gLayerScopeManager.GetSocketManager()->WriteAll(data.get(), size);
}
Packet::DataType mDataType;
@ -290,7 +394,7 @@ public:
return WriteToStream(mPacket);
}
bool TryPack() {
bool TryPack(bool packData) {
android::sp<android::GraphicBuffer> buffer = mState.mSurface;
MOZ_ASSERT(buffer.get());
@ -300,16 +404,9 @@ public:
tp->set_name(mName);
tp->set_target(mTarget);
int format = buffer->getPixelFormat();
if (HAL_PIXEL_FORMAT_RGBA_8888 != format &&
HAL_PIXEL_FORMAT_RGBX_8888 != format) {
return false;
}
uint8_t* grallocData;
if (BAD_VALUE == buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_NEVER,
reinterpret_cast<void**>(&grallocData))) {
int pFormat = buffer->getPixelFormat();
if (HAL_PIXEL_FORMAT_RGBA_8888 != pFormat &&
HAL_PIXEL_FORMAT_RGBX_8888 != pFormat) {
return false;
}
@ -317,29 +414,44 @@ public:
int32_t height = buffer->getHeight();
int32_t width = buffer->getWidth();
int32_t sourceSize = stride * height;
bool ret = false;
if (sourceSize <= 0) {
return false;
}
if (sourceSize > 0) {
auto compressedData = MakeUnique<char[]>(LZ4::maxCompressedSize(sourceSize));
uint32_t dFormat = mState.FormatRBSwapped() ?
LOCAL_GL_BGRA : LOCAL_GL_RGBA;
tp->set_dataformat(dFormat);
tp->set_dataformat((1 << 16 | tp->dataformat()));
tp->set_width(width);
tp->set_height(height);
tp->set_stride(stride);
if (packData) {
uint8_t* grallocData = nullptr;
if (BAD_VALUE == buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_NEVER,
reinterpret_cast<void**>(&grallocData)))
{
return false;
}
// Do not return before buffer->unlock();
auto compressedData =
MakeUnique<char[]>(LZ4::maxCompressedSize(sourceSize));
int compressedSize = LZ4::compress((char*)grallocData,
sourceSize,
compressedData.get());
if (compressedSize > 0) {
uint32_t format = mState.FormatRBSwapped() ?
LOCAL_GL_BGRA : LOCAL_GL_RGBA;
tp->set_dataformat(format);
tp->set_dataformat((1 << 16 | tp->dataformat()));
tp->set_width(width);
tp->set_height(height);
tp->set_stride(stride);
tp->set_data(compressedData.get(), compressedSize);
ret = true;
}
} else {
buffer->unlock();
return false;
}
buffer->unlock();
}
buffer->unlock();
return ret;
return true;
}
private:
@ -576,11 +688,12 @@ public:
NS_IMETHODIMP OnSocketAccepted(nsIServerSocket *aServ,
nsISocketTransport *aTransport) override
{
if (!WebSocketHelper::GetSocketManager())
if (!gLayerScopeManager.GetSocketManager())
return NS_OK;
printf_stderr("*** LayerScope: Accepted connection\n");
WebSocketHelper::GetSocketManager()->AddConnection(aTransport);
gLayerScopeManager.GetSocketManager()->AddConnection(aTransport);
gLayerScopeManager.GetContentMonitor()->Empty();
return NS_OK;
}
@ -619,8 +732,6 @@ public:
delete d;
}
/* nsIRunnable impl; send the data */
NS_IMETHODIMP Run() override {
DebugGLData *d;
nsresult rv = NS_OK;
@ -636,7 +747,7 @@ public:
Cleanup();
if (NS_FAILED(rv)) {
WebSocketHelper::DestroyServerSocket();
gLayerScopeManager.DestroyServerSocket();
}
return NS_OK;
@ -649,15 +760,6 @@ protected:
NS_IMPL_ISUPPORTS(DebugDataSender, nsIRunnable);
class CreateServerSocketRunnable : public nsRunnable
{
public:
NS_IMETHOD Run() {
WebSocketHelper::CreateServerSocket();
return NS_OK;
}
};
/*
* LayerScope SendXXX Structure
* 1. SendLayer
@ -799,7 +901,7 @@ SenderHelper::SendColor(void* aLayerRef,
int aWidth,
int aHeight)
{
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
}
@ -848,7 +950,7 @@ SenderHelper::SendTextureSource(GLContext* aGLContext,
aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
size,
shaderConfig, aFlipY);
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
aTexID, img));
@ -869,13 +971,19 @@ SenderHelper::SendGraphicBuffer(void* aLayerRef,
mozilla::UniquePtr<DebugGLGraphicBuffer> package =
MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, aTexID, aEffect->mState);
if (!package->TryPack()) {
// The texure content in this TexureHost is not altered,
// we don't need to send it again.
bool changed = gLayerScopeManager.GetContentMonitor()->IsChangedOrNew(
aEffect->mState.mTexture);
if (!package->TryPack(changed)) {
return false;
}
// Transfer ownership to SocketManager.
WebSocketHelper::GetSocketManager()->AppendDebugData(package.release());
gLayerScopeManager.GetSocketManager()->AppendDebugData(package.release());
sTextureIdList.push_back(aTexID);
gLayerScopeManager.GetContentMonitor()->ClearChangedHost(aEffect->mState.mTexture);
return true;
}
#endif
@ -897,9 +1005,10 @@ SenderHelper::SendTexturedEffect(GLContext* aGLContext,
#ifdef MOZ_WIDGET_GONK
if (SendGraphicBuffer(aLayerRef, source, texID, aEffect)) {
return;
return;
}
#endif
// Fallback texture sending path.
// Render to texture and read pixels back.
SendTextureSource(aGLContext, aLayerRef, source, texID, false);
}
@ -976,6 +1085,16 @@ SenderHelper::SendEffectChain(GLContext* aGLContext,
// TODO:
}
void
LayerScope::ContentChanged(TextureHost *host)
{
if (!CheckSendable()) {
return;
}
gLayerScopeManager.GetContentMonitor()->SetChangedHost(host);
}
// ----------------------------------------------
// LayerScopeWebSocketHandler implementation
// ----------------------------------------------
@ -1383,7 +1502,7 @@ LayerScopeWebSocketHandler::HandleDataFrame(uint8_t *aData,
void
LayerScopeWebSocketHandler::CloseConnection()
{
WebSocketHelper::GetSocketManager()->CleanDebugData();
gLayerScopeManager.GetSocketManager()->CleanDebugData();
if (mInputStream) {
mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
mInputStream = nullptr;
@ -1453,56 +1572,9 @@ LayerScope::Init()
return;
}
if (NS_IsMainThread()) {
WebSocketHelper::CreateServerSocket();
} else {
// Dispatch creation to main thread, and make sure we
// dispatch this only once after booting
static bool dispatched = false;
if (dispatched) {
return;
}
DebugOnly<nsresult> rv = NS_DispatchToMainThread(new CreateServerSocketRunnable());
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch WebSocket Creation to main thread");
dispatched = true;
}
gLayerScopeManager.CreateServerSocket();
}
class DrawSession {
public:
NS_INLINE_DECL_REFCOUNTING(DrawSession)
DrawSession()
: mOffsetX(0.0),
mOffsetY(0.0),
mRects(0)
{ }
float mOffsetX;
float mOffsetY;
gfx::Matrix4x4 mMVMatrix;
size_t mRects;
gfx::Rect mLayerRects[4];
private:
~DrawSession() {}
};
class DrawSessionHolder {
public:
static void setSession(DrawSession *aSession) {
mSession = aSession;
}
static DrawSession& current() {
return *mSession;
}
private:
static nsRefPtr<DrawSession> mSession;
};
nsRefPtr<DrawSession> DrawSessionHolder::mSession;
void
LayerScope::DrawBegin()
{
@ -1510,7 +1582,7 @@ LayerScope::DrawBegin()
return;
}
DrawSessionHolder::setSession(new DrawSession());
gLayerScopeManager.NewDrawSession();
}
void LayerScope::SetRenderOffset(float aX, float aY)
@ -1519,8 +1591,8 @@ void LayerScope::SetRenderOffset(float aX, float aY)
return;
}
DrawSessionHolder::current().mOffsetX = aX;
DrawSessionHolder::current().mOffsetY = aY;
gLayerScopeManager.CurrentSession().mOffsetX = aX;
gLayerScopeManager.CurrentSession().mOffsetY = aY;
}
void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
@ -1529,7 +1601,7 @@ void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix)
return;
}
DrawSessionHolder::current().mMVMatrix = aMatrix;
gLayerScopeManager.CurrentSession().mMVMatrix = aMatrix;
}
void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
@ -1541,10 +1613,10 @@ void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects)
MOZ_ASSERT(aRects > 0 && aRects <= 4);
MOZ_ASSERT(aLayerRects);
DrawSessionHolder::current().mRects = aRects;
gLayerScopeManager.CurrentSession().mRects = aRects;
for (size_t i = 0; i < aRects; i++){
DrawSessionHolder::current().mLayerRects[i] = aLayerRects[i];
gLayerScopeManager.CurrentSession().mLayerRects[i] = aLayerRects[i];
}
}
@ -1561,8 +1633,8 @@ LayerScope::DrawEnd(gl::GLContext* aGLContext,
// 1. Send parameters of draw call, such as uniforms and attributes of
// vertex adnd fragment shader.
DrawSession& draws = DrawSessionHolder::current();
WebSocketHelper::GetSocketManager()->AppendDebugData(
DrawSession& draws = gLayerScopeManager.CurrentSession();
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY,
draws.mMVMatrix, draws.mRects,
draws.mLayerRects,
@ -1591,7 +1663,7 @@ LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
return;
}
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLLayersData(Move(aPacket)));
}
@ -1604,11 +1676,11 @@ LayerScope::CheckSendable()
if (!gfxPrefs::LayerScopeEnabled()) {
return false;
}
if (!WebSocketHelper::GetSocketManager()) {
if (!gLayerScopeManager.GetSocketManager()) {
Init();
return false;
}
if (!WebSocketHelper::GetSocketManager()->IsConnected()) {
if (!gLayerScopeManager.GetSocketManager()->IsConnected()) {
return false;
}
return true;
@ -1618,7 +1690,7 @@ void
LayerScope::CleanLayer()
{
if (CheckSendable()) {
WebSocketHelper::GetSocketManager()->CleanDebugData();
gLayerScopeManager.GetSocketManager()->CleanDebugData();
}
}
@ -1626,7 +1698,7 @@ void
LayerScope::SetHWComposed()
{
if (CheckSendable()) {
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLMetaData(Packet::META, true));
}
}
@ -1655,7 +1727,7 @@ LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
return;
}
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));
}
@ -1666,9 +1738,9 @@ LayerScopeAutoFrame::EndFrame()
return;
}
WebSocketHelper::GetSocketManager()->AppendDebugData(
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLFrameStatusData(Packet::FRAMEEND));
WebSocketHelper::GetSocketManager()->DispatchDebugData();
gLayerScopeManager.GetSocketManager()->DispatchDebugData();
}
} /* layers */

View File

@ -40,6 +40,7 @@ public:
static void CleanLayer();
static void SetHWComposed();
static void ContentChanged(TextureHost *host);
private:
static void Init();
};

View File

@ -297,7 +297,7 @@ DIBTextureHost::DIBTextureHost(TextureFlags aFlags,
}
void
DIBTextureHost::Updated(const nsIntRegion* aRegion)
DIBTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
{
if (!mCompositor) {
// This can happen if we send textures to a compositable that isn't yet
@ -331,7 +331,7 @@ TextureHostFileMapping::~TextureHostFileMapping()
}
void
TextureHostFileMapping::Updated(const nsIntRegion* aRegion)
TextureHostFileMapping::UpdatedInternal(const nsIntRegion* aRegion)
{
if (!mCompositor) {
// This can happen if we send textures to a compositable that isn't yet

View File

@ -155,14 +155,14 @@ public:
DIBTextureHost(TextureFlags aFlags,
const SurfaceDescriptorDIB& aDescriptor);
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
{
return nullptr; // TODO: cf bug 872568
}
protected:
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
nsRefPtr<gfxWindowsSurface> mSurface;
};
@ -173,8 +173,6 @@ public:
const SurfaceDescriptorFileMapping& aDescriptor);
~TextureHostFileMapping();
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
{
MOZ_CRASH(); // Not implemented! It would be tricky to keep track of the
@ -183,6 +181,8 @@ public:
}
protected:
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
HANDLE mFileMapping;
};

View File

@ -353,6 +353,13 @@ TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
#endif
}
void
TextureHost::Updated(const nsIntRegion* aRegion)
{
LayerScope::ContentChanged(this);
UpdatedInternal(aRegion);
}
TextureSource::TextureSource()
: mCompositableCount(0)
{
@ -401,7 +408,7 @@ BufferTextureHost::~BufferTextureHost()
{}
void
BufferTextureHost::Updated(const nsIntRegion* aRegion)
BufferTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
{
++mUpdateSerial;
// If the last frame wasn't uploaded yet, and we -don't- have a partial update,

View File

@ -388,7 +388,7 @@ public:
* @param aRegion The region that has been changed, if nil, it means that the
* entire surface should be updated.
*/
virtual void Updated(const nsIntRegion* aRegion = nullptr) {}
void Updated(const nsIntRegion* aRegion = nullptr);
/**
* Sets this TextureHost's compositor.
@ -538,6 +538,8 @@ protected:
void RecycleTexture(TextureFlags aFlags);
virtual void UpdatedInternal(const nsIntRegion *Region) {}
PTextureParent* mActor;
TextureFlags mFlags;
int mCompositableCount;
@ -570,8 +572,6 @@ public:
virtual size_t GetBufferSize() = 0;
virtual void Updated(const nsIntRegion* aRegion = nullptr) override;
virtual bool Lock() override;
virtual void Unlock() override;
@ -603,6 +603,8 @@ protected:
void InitSize();
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
RefPtr<Compositor> mCompositor;
RefPtr<DataTextureSource> mFirstSource;
nsIntRegion mMaybeUpdatedRegion;

View File

@ -914,7 +914,7 @@ DataTextureSourceD3D9::UpdateFromTexture(IDirect3DTexture9* aTexture,
}
void
TextureHostD3D9::Updated(const nsIntRegion* aRegion)
TextureHostD3D9::UpdatedInternal(const nsIntRegion* aRegion)
{
MOZ_ASSERT(mTexture);
if (!mTexture) {

View File

@ -308,8 +308,6 @@ public:
virtual void Unlock() override;
virtual void Updated(const nsIntRegion* aRegion) override;
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override
@ -323,6 +321,8 @@ protected:
TextureHostD3D9(TextureFlags aFlags);
IDirect3DDevice9* GetDevice();
virtual void UpdatedInternal(const nsIntRegion* aRegion) override;
RefPtr<DataTextureSourceD3D9> mTextureSource;
RefPtr<IDirect3DTexture9> mTexture;
RefPtr<CompositorD3D9> mCompositor;

View File

@ -24,8 +24,6 @@ public:
virtual ~GrallocTextureHostOGL();
virtual void Updated(const nsIntRegion* aRegion) override {}
virtual bool Lock() override;
virtual void Unlock() override;