1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SurfaceStream.h"
9 #include "SharedSurface.h"
10 #include "SurfaceFactory.h"
11 #include "GeckoProfiler.h"
17 SurfaceStream::ChooseGLStreamType(SurfaceStream::OMTC omtc
,
20 if (omtc
== SurfaceStream::OffMainThread
) {
22 return SurfaceStreamType::TripleBuffer_Copy
;
24 return SurfaceStreamType::TripleBuffer_Async
;
27 return SurfaceStreamType::SingleBuffer
;
29 return SurfaceStreamType::TripleBuffer
;
34 SurfaceStream::CreateForType(SurfaceStreamType type
, mozilla::gl::GLContext
* glContext
, SurfaceStream
* prevStream
)
36 SurfaceStream
* result
= nullptr;
39 case SurfaceStreamType::SingleBuffer
:
40 result
= new SurfaceStream_SingleBuffer(prevStream
);
42 case SurfaceStreamType::TripleBuffer_Copy
:
43 result
= new SurfaceStream_TripleBuffer_Copy(prevStream
);
45 case SurfaceStreamType::TripleBuffer_Async
:
46 result
= new SurfaceStream_TripleBuffer_Async(prevStream
);
48 case SurfaceStreamType::TripleBuffer
:
49 result
= new SurfaceStream_TripleBuffer(prevStream
);
52 MOZ_CRASH("Invalid Type.");
55 result
->mGLContext
= glContext
;
60 SurfaceStream::New(SurfaceFactory
* factory
, const gfxIntSize
& size
,
64 surf
= factory
->NewSharedSurface(size
);
67 mSurfaces
.insert(surf
);
71 SurfaceStream::Recycle(SurfaceFactory
* factory
, SharedSurface
*& surf
)
74 mSurfaces
.erase(surf
);
75 factory
->Recycle(surf
);
81 SurfaceStream::Delete(SharedSurface
*& surf
)
84 mSurfaces
.erase(surf
);
92 SurfaceStream::Surrender(SharedSurface
*& surf
)
94 SharedSurface
* ret
= surf
;
97 mSurfaces
.erase(surf
);
106 SurfaceStream::Absorb(SharedSurface
*& surf
)
108 SharedSurface
* ret
= surf
;
111 mSurfaces
.insert(surf
);
120 SurfaceStream::Scrap(SharedSurface
*& scrap
)
130 SurfaceStream::RecycleScraps(SurfaceFactory
* factory
)
132 while (!mScraps
.empty()) {
133 SharedSurface
* cur
= mScraps
.top();
136 Recycle(factory
, cur
);
142 SurfaceStream::~SurfaceStream()
146 while (!mScraps
.empty()) {
147 SharedSurface
* cur
= mScraps
.top();
153 MOZ_ASSERT(mSurfaces
.empty());
157 SurfaceStream::SwapConsumer()
159 MOZ_ASSERT(mIsAlive
);
161 SharedSurface
* ret
= SwapConsumer_NoWait();
165 if (!ret
->WaitSync()) {
173 SurfaceStream::Resize(SurfaceFactory
* factory
, const gfxIntSize
& size
)
175 MonitorAutoLock
lock(mMonitor
);
181 New(factory
, size
, mProducer
);
185 SurfaceStream_SingleBuffer::SurfaceStream_SingleBuffer(SurfaceStream
* prevStream
)
186 : SurfaceStream(SurfaceStreamType::SingleBuffer
, prevStream
)
192 SharedSurface
* prevProducer
= nullptr;
193 SharedSurface
* prevConsumer
= nullptr;
194 prevStream
->SurrenderSurfaces(prevProducer
, prevConsumer
);
196 if (prevConsumer
== prevProducer
)
197 prevConsumer
= nullptr;
199 mProducer
= Absorb(prevProducer
);
200 mConsumer
= Absorb(prevConsumer
);
203 SurfaceStream_SingleBuffer::~SurfaceStream_SingleBuffer()
209 SurfaceStream_SingleBuffer::SurrenderSurfaces(SharedSurface
*& producer
,
210 SharedSurface
*& consumer
)
214 producer
= Surrender(mProducer
);
215 consumer
= Surrender(mConsumer
);
222 SurfaceStream_SingleBuffer::SwapProducer(SurfaceFactory
* factory
,
223 const gfxIntSize
& size
)
225 MonitorAutoLock
lock(mMonitor
);
227 Recycle(factory
, mConsumer
);
231 // Fence now, before we start (maybe) juggling Prod around.
234 // Size mismatch means we need to squirrel the current Prod
235 // into Cons, and leave Prod empty, so it gets a new surface below.
236 bool needsNewBuffer
= mProducer
->Size() != size
;
238 // Even if we're the right size, if the type has changed, and we don't
239 // need to preserve, we should switch out for (presumedly) better perf.
240 if (mProducer
->Type() != factory
->Type() &&
241 !factory
->Caps().preserve
)
243 needsNewBuffer
= true;
246 if (needsNewBuffer
) {
247 Move(mProducer
, mConsumer
);
251 // The old Prod (if there every was one) was invalid,
252 // so we need a new one.
254 New(factory
, size
, mProducer
);
261 SurfaceStream_SingleBuffer::SwapConsumer_NoWait()
263 MonitorAutoLock
lock(mMonitor
);
265 // Use Cons, if present.
266 // Otherwise, just use Prod directly.
267 SharedSurface
* toConsume
= mConsumer
;
269 toConsume
= mProducer
;
276 SurfaceStream_TripleBuffer_Copy::SurfaceStream_TripleBuffer_Copy(SurfaceStream
* prevStream
)
277 : SurfaceStream(SurfaceStreamType::TripleBuffer_Copy
, prevStream
)
284 SharedSurface
* prevProducer
= nullptr;
285 SharedSurface
* prevConsumer
= nullptr;
286 prevStream
->SurrenderSurfaces(prevProducer
, prevConsumer
);
288 if (prevConsumer
== prevProducer
)
289 prevConsumer
= nullptr;
291 mProducer
= Absorb(prevProducer
);
292 mConsumer
= Absorb(prevConsumer
);
295 SurfaceStream_TripleBuffer_Copy::~SurfaceStream_TripleBuffer_Copy()
302 SurfaceStream_TripleBuffer_Copy::SurrenderSurfaces(SharedSurface
*& producer
,
303 SharedSurface
*& consumer
)
307 producer
= Surrender(mProducer
);
308 consumer
= Surrender(mConsumer
);
311 consumer
= Surrender(mStaging
);
315 SurfaceStream_TripleBuffer_Copy::SwapProducer(SurfaceFactory
* factory
,
316 const gfxIntSize
& size
)
318 MonitorAutoLock
lock(mMonitor
);
320 RecycleScraps(factory
);
323 // We'll re-use this for a new mProducer later on if
324 // the size remains the same
325 Recycle(factory
, mStaging
);
328 Move(mProducer
, mStaging
);
331 New(factory
, size
, mProducer
);
333 if (mProducer
&& mStaging
->Size() == mProducer
->Size())
334 SharedSurface::Copy(mStaging
, mProducer
, factory
);
336 New(factory
, size
, mProducer
);
344 SurfaceStream_TripleBuffer_Copy::SwapConsumer_NoWait()
346 MonitorAutoLock
lock(mMonitor
);
350 Move(mStaging
, mConsumer
);
356 void SurfaceStream_TripleBuffer::Init(SurfaceStream
* prevStream
)
361 SharedSurface
* prevProducer
= nullptr;
362 SharedSurface
* prevConsumer
= nullptr;
363 prevStream
->SurrenderSurfaces(prevProducer
, prevConsumer
);
365 if (prevConsumer
== prevProducer
)
366 prevConsumer
= nullptr;
368 mProducer
= Absorb(prevProducer
);
369 mConsumer
= Absorb(prevConsumer
);
373 SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStreamType type
, SurfaceStream
* prevStream
)
374 : SurfaceStream(type
, prevStream
)
378 SurfaceStream_TripleBuffer::Init(prevStream
);
381 SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStream
* prevStream
)
382 : SurfaceStream(SurfaceStreamType::TripleBuffer
, prevStream
)
386 SurfaceStream_TripleBuffer::Init(prevStream
);
389 SurfaceStream_TripleBuffer::~SurfaceStream_TripleBuffer()
396 SurfaceStream_TripleBuffer::SurrenderSurfaces(SharedSurface
*& producer
,
397 SharedSurface
*& consumer
)
401 producer
= Surrender(mProducer
);
402 consumer
= Surrender(mConsumer
);
405 consumer
= Surrender(mStaging
);
409 SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory
* factory
,
410 const gfxIntSize
& size
)
412 PROFILER_LABEL("SurfaceStream_TripleBuffer", "SwapProducer");
414 MonitorAutoLock
lock(mMonitor
);
416 RecycleScraps(factory
);
418 // If WaitForCompositor succeeds, mStaging has moved to mConsumer.
419 // If it failed, we might have to scrap it.
420 if (mStaging
&& !WaitForCompositor())
423 MOZ_ASSERT(!mStaging
);
424 Move(mProducer
, mStaging
);
428 MOZ_ASSERT(!mProducer
);
429 New(factory
, size
, mProducer
);
435 SurfaceStream_TripleBuffer::SwapConsumer_NoWait()
437 MonitorAutoLock
lock(mMonitor
);
440 Move(mStaging
, mConsumer
);
441 mMonitor
.NotifyAll();
447 SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(SurfaceStream
* prevStream
)
448 : SurfaceStream_TripleBuffer(SurfaceStreamType::TripleBuffer_Async
, prevStream
)
452 SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
457 SurfaceStream_TripleBuffer_Async::WaitForCompositor()
459 PROFILER_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor");
461 // We are assumed to be locked
468 } /* namespace gfx */
469 } /* namespace mozilla */