2017-06-09 20:30:00 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2017-10-27 23:10:06 +00:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2017-06-09 20:30:00 +00:00
|
|
|
/* 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 MOZILLA_LAYERS_PAINTTHREAD_H
|
|
|
|
#define MOZILLA_LAYERS_PAINTTHREAD_H
|
|
|
|
|
2017-06-20 20:35:39 +00:00
|
|
|
#include "base/platform_thread.h"
|
2017-08-03 15:50:32 +00:00
|
|
|
#include "mozilla/RefPtr.h"
|
2017-06-09 20:30:00 +00:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2017-07-05 22:19:47 +00:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2017-08-05 18:54:11 +00:00
|
|
|
#include "mozilla/layers/TextureClient.h"
|
2017-10-25 14:20:49 +00:00
|
|
|
#include "RotatedBuffer.h"
|
2017-06-09 20:30:00 +00:00
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
|
Create a PaintWorker thread pool and dispatch tiles to it (bug 1425056, r=bas)
This commit adds a paint worker thread pool to PaintThread, and dispatches
tiled paints to it. The thread pool is only created if tiling is enabled,
and its size is set by 'layers.omtp.paint-workers' and defaults to 1. If
-1 is specified, it will be sized to 'max((cpu_cores * 3) / 4, 1)'.
The one tricky part of dispatching tiled paints to a thread pool is the
AsyncEndLayerTransaction message that must execute once all paints are
finished. Previously, this runnable would be queued after all the paints
had been queued, ensuring it would be run after they had all completed.
With a thread pool, there is no guarantee. Instead this commit, uses
a flag on CompositorBridgeChild to signify whether all of the paints
have been queued ('mOutstandingAsyncEndLayerTransaction'), and after
every tiled paint it is examined to see if that paint was the last
paint, and if it is to run AsyncEndLayerTransaction. In addition,
if the async paints complete before we even mark the end of the
layer transaction, we queue it like normal.
The profiler markers are also complicated by using a thread pool.
I don't know of a great way to keep them working as they are per
thread, so for now I've removed them. I may have been the only
one using them anyway.
MozReview-Commit-ID: 5LIJ9GWSfCn
--HG--
extra : rebase_source : 0c26806f337a1b4b1511945f9c72e787b426c5ba
2017-12-08 07:18:05 +00:00
|
|
|
class nsIThreadPool;
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
namespace mozilla {
|
2017-06-20 20:35:39 +00:00
|
|
|
namespace gfx {
|
|
|
|
class DrawTarget;
|
2017-06-22 15:36:14 +00:00
|
|
|
class DrawTargetCapture;
|
2017-06-20 20:35:39 +00:00
|
|
|
};
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
namespace layers {
|
|
|
|
|
2017-11-22 00:12:14 +00:00
|
|
|
// Holds the key operations needed to update a tiled content client on the
|
|
|
|
// paint thread.
|
2018-07-24 20:39:35 +00:00
|
|
|
class PaintTask {
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaintTask)
|
2017-11-22 00:12:14 +00:00
|
|
|
public:
|
2018-07-24 20:39:35 +00:00
|
|
|
PaintTask() {}
|
2017-11-22 00:12:14 +00:00
|
|
|
|
2017-12-05 02:23:50 +00:00
|
|
|
template<typename F>
|
|
|
|
void ForEachTextureClient(F aClosure) const
|
|
|
|
{
|
|
|
|
for (auto client : mClients) {
|
|
|
|
aClosure(client);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DropTextureClients()
|
|
|
|
{
|
|
|
|
mClients.clear();
|
|
|
|
}
|
|
|
|
|
2017-12-08 05:45:47 +00:00
|
|
|
RefPtr<gfx::DrawTarget> mTarget;
|
2017-11-22 00:12:14 +00:00
|
|
|
RefPtr<gfx::DrawTargetCapture> mCapture;
|
|
|
|
std::vector<RefPtr<TextureClient>> mClients;
|
|
|
|
|
|
|
|
protected:
|
2018-07-24 20:39:35 +00:00
|
|
|
virtual ~PaintTask() {}
|
2017-11-22 00:12:14 +00:00
|
|
|
};
|
|
|
|
|
2017-07-05 22:19:52 +00:00
|
|
|
class CompositorBridgeChild;
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
class PaintThread final
|
|
|
|
{
|
2017-07-05 22:19:47 +00:00
|
|
|
friend void DestroyPaintThread(UniquePtr<PaintThread>&& aPaintThread);
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
public:
|
|
|
|
static void Start();
|
|
|
|
static void Shutdown();
|
|
|
|
static PaintThread* Get();
|
2017-08-16 21:53:15 +00:00
|
|
|
|
|
|
|
// Helper for asserts.
|
|
|
|
static bool IsOnPaintThread();
|
Create a PaintWorker thread pool and dispatch tiles to it (bug 1425056, r=bas)
This commit adds a paint worker thread pool to PaintThread, and dispatches
tiled paints to it. The thread pool is only created if tiling is enabled,
and its size is set by 'layers.omtp.paint-workers' and defaults to 1. If
-1 is specified, it will be sized to 'max((cpu_cores * 3) / 4, 1)'.
The one tricky part of dispatching tiled paints to a thread pool is the
AsyncEndLayerTransaction message that must execute once all paints are
finished. Previously, this runnable would be queued after all the paints
had been queued, ensuring it would be run after they had all completed.
With a thread pool, there is no guarantee. Instead this commit, uses
a flag on CompositorBridgeChild to signify whether all of the paints
have been queued ('mOutstandingAsyncEndLayerTransaction'), and after
every tiled paint it is examined to see if that paint was the last
paint, and if it is to run AsyncEndLayerTransaction. In addition,
if the async paints complete before we even mark the end of the
layer transaction, we queue it like normal.
The profiler markers are also complicated by using a thread pool.
I don't know of a great way to keep them working as they are per
thread, so for now I've removed them. I may have been the only
one using them anyway.
MozReview-Commit-ID: 5LIJ9GWSfCn
--HG--
extra : rebase_source : 0c26806f337a1b4b1511945f9c72e787b426c5ba
2017-12-08 07:18:05 +00:00
|
|
|
bool IsOnPaintWorkerThread();
|
2017-10-30 18:49:58 +00:00
|
|
|
|
2018-05-15 18:36:11 +00:00
|
|
|
void UpdateRenderMode();
|
|
|
|
|
2018-07-24 20:39:35 +00:00
|
|
|
void QueuePaintTask(PaintTask* aTask);
|
2018-08-07 17:57:27 +00:00
|
|
|
|
2017-12-01 16:04:46 +00:00
|
|
|
// This allows external users to run code on the paint thread.
|
|
|
|
void Dispatch(RefPtr<Runnable>& aRunnable);
|
|
|
|
|
2017-08-16 06:04:41 +00:00
|
|
|
// Must be called on the main thread. Signifies that the current
|
|
|
|
// layer tree transaction has been finished and any async paints
|
|
|
|
// for it have been queued on the paint thread. This MUST be called
|
|
|
|
// at the end of a layer transaction as it will be used to do an optional
|
|
|
|
// texture sync and then unblock the main thread if it is waiting to paint
|
|
|
|
// a new frame.
|
2017-08-16 21:02:13 +00:00
|
|
|
void EndLayerTransaction(SyncObjectClient* aSyncObject);
|
2017-08-11 04:41:31 +00:00
|
|
|
|
2017-06-20 20:35:39 +00:00
|
|
|
// Sync Runnables need threads to be ref counted,
|
|
|
|
// But this thread lives through the whole process.
|
|
|
|
// We're only temporarily using sync runnables so
|
|
|
|
// Override release/addref but don't do anything.
|
|
|
|
void Release();
|
|
|
|
void AddRef();
|
2017-06-09 20:30:00 +00:00
|
|
|
|
2018-01-23 21:52:13 +00:00
|
|
|
static int32_t CalculatePaintWorkerCount();
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
private:
|
2017-10-30 18:49:58 +00:00
|
|
|
PaintThread();
|
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
bool Init();
|
2017-07-05 22:19:47 +00:00
|
|
|
void ShutdownOnPaintThread();
|
2017-06-20 20:35:39 +00:00
|
|
|
void InitOnPaintThread();
|
2018-05-15 18:36:11 +00:00
|
|
|
void InitPaintWorkers();
|
2017-08-16 21:53:15 +00:00
|
|
|
|
2018-07-24 20:39:35 +00:00
|
|
|
void AsyncPaintTask(CompositorBridgeChild* aBridge,
|
|
|
|
PaintTask* aTask);
|
|
|
|
void AsyncPaintTaskFinished(CompositorBridgeChild* aBridge,
|
|
|
|
PaintTask* aTask);
|
|
|
|
|
Create a PaintWorker thread pool and dispatch tiles to it (bug 1425056, r=bas)
This commit adds a paint worker thread pool to PaintThread, and dispatches
tiled paints to it. The thread pool is only created if tiling is enabled,
and its size is set by 'layers.omtp.paint-workers' and defaults to 1. If
-1 is specified, it will be sized to 'max((cpu_cores * 3) / 4, 1)'.
The one tricky part of dispatching tiled paints to a thread pool is the
AsyncEndLayerTransaction message that must execute once all paints are
finished. Previously, this runnable would be queued after all the paints
had been queued, ensuring it would be run after they had all completed.
With a thread pool, there is no guarantee. Instead this commit, uses
a flag on CompositorBridgeChild to signify whether all of the paints
have been queued ('mOutstandingAsyncEndLayerTransaction'), and after
every tiled paint it is examined to see if that paint was the last
paint, and if it is to run AsyncEndLayerTransaction. In addition,
if the async paints complete before we even mark the end of the
layer transaction, we queue it like normal.
The profiler markers are also complicated by using a thread pool.
I don't know of a great way to keep them working as they are per
thread, so for now I've removed them. I may have been the only
one using them anyway.
MozReview-Commit-ID: 5LIJ9GWSfCn
--HG--
extra : rebase_source : 0c26806f337a1b4b1511945f9c72e787b426c5ba
2017-12-08 07:18:05 +00:00
|
|
|
void AsyncEndLayerTransaction(CompositorBridgeChild* aBridge);
|
|
|
|
|
|
|
|
void DispatchEndLayerTransaction(CompositorBridgeChild* aBridge);
|
2017-06-20 20:35:39 +00:00
|
|
|
|
2017-06-09 20:30:00 +00:00
|
|
|
static StaticAutoPtr<PaintThread> sSingleton;
|
2017-07-05 22:19:47 +00:00
|
|
|
static StaticRefPtr<nsIThread> sThread;
|
|
|
|
static PlatformThreadId sThreadId;
|
2017-08-09 15:24:15 +00:00
|
|
|
|
Create a PaintWorker thread pool and dispatch tiles to it (bug 1425056, r=bas)
This commit adds a paint worker thread pool to PaintThread, and dispatches
tiled paints to it. The thread pool is only created if tiling is enabled,
and its size is set by 'layers.omtp.paint-workers' and defaults to 1. If
-1 is specified, it will be sized to 'max((cpu_cores * 3) / 4, 1)'.
The one tricky part of dispatching tiled paints to a thread pool is the
AsyncEndLayerTransaction message that must execute once all paints are
finished. Previously, this runnable would be queued after all the paints
had been queued, ensuring it would be run after they had all completed.
With a thread pool, there is no guarantee. Instead this commit, uses
a flag on CompositorBridgeChild to signify whether all of the paints
have been queued ('mOutstandingAsyncEndLayerTransaction'), and after
every tiled paint it is examined to see if that paint was the last
paint, and if it is to run AsyncEndLayerTransaction. In addition,
if the async paints complete before we even mark the end of the
layer transaction, we queue it like normal.
The profiler markers are also complicated by using a thread pool.
I don't know of a great way to keep them working as they are per
thread, so for now I've removed them. I may have been the only
one using them anyway.
MozReview-Commit-ID: 5LIJ9GWSfCn
--HG--
extra : rebase_source : 0c26806f337a1b4b1511945f9c72e787b426c5ba
2017-12-08 07:18:05 +00:00
|
|
|
RefPtr<nsIThreadPool> mPaintWorkers;
|
2017-06-09 20:30:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|
|
|
|
|
2017-07-05 22:19:47 +00:00
|
|
|
#endif
|