gfx/gl/SurfaceStream.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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"
     8 #include "gfxPoint.h"
     9 #include "SharedSurface.h"
    10 #include "SharedSurfaceGL.h"
    11 #include "SurfaceFactory.h"
    12 #include "GeckoProfiler.h"
    14 namespace mozilla {
    15 namespace gfx {
    17 SurfaceStreamType
    18 SurfaceStream::ChooseGLStreamType(SurfaceStream::OMTC omtc,
    19                                   bool preserveBuffer)
    20 {
    21     if (omtc == SurfaceStream::OffMainThread) {
    22         if (preserveBuffer)
    23             return SurfaceStreamType::TripleBuffer_Copy;
    24         else
    25             return SurfaceStreamType::TripleBuffer_Async;
    26     } else {
    27         if (preserveBuffer)
    28             return SurfaceStreamType::SingleBuffer;
    29         else
    30             return SurfaceStreamType::TripleBuffer;
    31     }
    32 }
    34 SurfaceStream*
    35 SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glContext, SurfaceStream* prevStream)
    36 {
    37     SurfaceStream* result = nullptr;
    39     switch (type) {
    40         case SurfaceStreamType::SingleBuffer:
    41             result = new SurfaceStream_SingleBuffer(prevStream);
    42             break;
    43         case SurfaceStreamType::TripleBuffer_Copy:
    44             result = new SurfaceStream_TripleBuffer_Copy(prevStream);
    45             break;
    46         case SurfaceStreamType::TripleBuffer_Async:
    47             result = new SurfaceStream_TripleBuffer_Async(prevStream);
    48             break;
    49         case SurfaceStreamType::TripleBuffer:
    50             result = new SurfaceStream_TripleBuffer(prevStream);
    51             break;
    52         default:
    53             MOZ_CRASH("Invalid Type.");
    54     }
    56     result->mGLContext = glContext;
    57     return result;
    58 }
    60 bool
    61 SurfaceStream_TripleBuffer::CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory)
    62 {
    63     if (!mProducer) {
    64         New(factory, src->Size(), mProducer);
    65         if (!mProducer) {
    66             return false;
    67         }
    68     }
    70     MOZ_ASSERT(src->Size() == mProducer->Size(), "Size mismatch");
    72     SharedSurface::Copy(src, mProducer, factory);
    73     return true;
    74 }
    76 void
    77 SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size,
    78                    SharedSurface*& surf)
    79 {
    80     MOZ_ASSERT(!surf);
    81     surf = factory->NewSharedSurface(size);
    83     if (surf)
    84         mSurfaces.insert(surf);
    85 }
    87 void
    88 SurfaceStream::Recycle(SurfaceFactory* factory, SharedSurface*& surf)
    89 {
    90     if (surf) {
    91         mSurfaces.erase(surf);
    92         factory->Recycle(surf);
    93     }
    94     MOZ_ASSERT(!surf);
    95 }
    97 void
    98 SurfaceStream::Delete(SharedSurface*& surf)
    99 {
   100     if (surf) {
   101         mSurfaces.erase(surf);
   102         delete surf;
   103         surf = nullptr;
   104     }
   105     MOZ_ASSERT(!surf);
   106 }
   108 SharedSurface*
   109 SurfaceStream::Surrender(SharedSurface*& surf)
   110 {
   111     SharedSurface* ret = surf;
   113     if (surf) {
   114         mSurfaces.erase(surf);
   115         surf = nullptr;
   116     }
   117     MOZ_ASSERT(!surf);
   119     return ret;
   120 }
   122 SharedSurface*
   123 SurfaceStream::Absorb(SharedSurface*& surf)
   124 {
   125     SharedSurface* ret = surf;
   127     if (surf) {
   128         mSurfaces.insert(surf);
   129         surf = nullptr;
   130     }
   131     MOZ_ASSERT(!surf);
   133     return ret;
   134 }
   136 void
   137 SurfaceStream::Scrap(SharedSurface*& scrap)
   138 {
   139     if (scrap) {
   140         mScraps.push(scrap);
   141         scrap = nullptr;
   142     }
   143     MOZ_ASSERT(!scrap);
   144 }
   146 void
   147 SurfaceStream::RecycleScraps(SurfaceFactory* factory)
   148 {
   149     while (!mScraps.empty()) {
   150         SharedSurface* cur = mScraps.top();
   151         mScraps.pop();
   153         Recycle(factory, cur);
   154     }
   155 }
   159 SurfaceStream::~SurfaceStream()
   160 {
   161     Delete(mProducer);
   163     while (!mScraps.empty()) {
   164         SharedSurface* cur = mScraps.top();
   165         mScraps.pop();
   167         Delete(cur);
   168     }
   170     MOZ_ASSERT(mSurfaces.empty());
   171 }
   173 SharedSurface*
   174 SurfaceStream::SwapConsumer()
   175 {
   176     MOZ_ASSERT(mIsAlive);
   178     SharedSurface* ret = SwapConsumer_NoWait();
   179     if (!ret)
   180         return nullptr;
   182     if (!ret->WaitSync()) {
   183         return nullptr;
   184     }
   186     return ret;
   187 }
   189 SharedSurface*
   190 SurfaceStream::Resize(SurfaceFactory* factory, const gfx::IntSize& size)
   191 {
   192     MonitorAutoLock lock(mMonitor);
   194     if (mProducer) {
   195         Scrap(mProducer);
   196     }
   198     New(factory, size, mProducer);
   199     return mProducer;
   200 }
   202 SurfaceStream_SingleBuffer::SurfaceStream_SingleBuffer(SurfaceStream* prevStream)
   203     : SurfaceStream(SurfaceStreamType::SingleBuffer, prevStream)
   204     , mConsumer(nullptr)
   205 {
   206     if (!prevStream)
   207         return;
   209     SharedSurface* prevProducer = nullptr;
   210     SharedSurface* prevConsumer = nullptr;
   211     prevStream->SurrenderSurfaces(prevProducer, prevConsumer);
   213     if (prevConsumer == prevProducer)
   214         prevConsumer = nullptr;
   216     mProducer = Absorb(prevProducer);
   217     mConsumer = Absorb(prevConsumer);
   218 }
   220 SurfaceStream_SingleBuffer::~SurfaceStream_SingleBuffer()
   221 {
   222     Delete(mConsumer);
   223 }
   225 void
   226 SurfaceStream_SingleBuffer::SurrenderSurfaces(SharedSurface*& producer,
   227                                               SharedSurface*& consumer)
   228 {
   229     mIsAlive = false;
   231     producer = Surrender(mProducer);
   232     consumer = Surrender(mConsumer);
   234     if (!consumer)
   235         consumer = producer;
   236 }
   238 SharedSurface*
   239 SurfaceStream_SingleBuffer::SwapProducer(SurfaceFactory* factory,
   240                                          const gfx::IntSize& size)
   241 {
   242     MonitorAutoLock lock(mMonitor);
   243     if (mConsumer) {
   244         Recycle(factory, mConsumer);
   245     }
   247     if (mProducer) {
   248         // Fence now, before we start (maybe) juggling Prod around.
   249         mProducer->Fence();
   251         // Size mismatch means we need to squirrel the current Prod
   252         // into Cons, and leave Prod empty, so it gets a new surface below.
   253         bool needsNewBuffer = mProducer->Size() != size;
   255         // Even if we're the right size, if the type has changed, and we don't
   256         // need to preserve, we should switch out for (presumedly) better perf.
   257         if (mProducer->Type() != factory->Type() &&
   258             !factory->Caps().preserve)
   259         {
   260             needsNewBuffer = true;
   261         }
   263         if (needsNewBuffer) {
   264             Move(mProducer, mConsumer);
   265         }
   266     }
   268     // The old Prod (if there every was one) was invalid,
   269     // so we need a new one.
   270     if (!mProducer) {
   271         New(factory, size, mProducer);
   272     }
   274     return mProducer;
   275 }
   277 SharedSurface*
   278 SurfaceStream_SingleBuffer::SwapConsumer_NoWait()
   279 {
   280     MonitorAutoLock lock(mMonitor);
   282     // Use Cons, if present.
   283     // Otherwise, just use Prod directly.
   284     SharedSurface* toConsume = mConsumer;
   285     if (!toConsume)
   286         toConsume = mProducer;
   288     return toConsume;
   289 }
   293 SurfaceStream_TripleBuffer_Copy::SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream)
   294     : SurfaceStream(SurfaceStreamType::TripleBuffer_Copy, prevStream)
   295     , mStaging(nullptr)
   296     , mConsumer(nullptr)
   297 {
   298     if (!prevStream)
   299         return;
   301     SharedSurface* prevProducer = nullptr;
   302     SharedSurface* prevConsumer = nullptr;
   303     prevStream->SurrenderSurfaces(prevProducer, prevConsumer);
   305     if (prevConsumer == prevProducer)
   306       prevConsumer = nullptr;
   308     mProducer = Absorb(prevProducer);
   309     mConsumer = Absorb(prevConsumer);
   310 }
   312 SurfaceStream_TripleBuffer_Copy::~SurfaceStream_TripleBuffer_Copy()
   313 {
   314     Delete(mStaging);
   315     Delete(mConsumer);
   316 }
   318 void
   319 SurfaceStream_TripleBuffer_Copy::SurrenderSurfaces(SharedSurface*& producer,
   320                                                    SharedSurface*& consumer)
   321 {
   322     mIsAlive = false;
   324     producer = Surrender(mProducer);
   325     consumer = Surrender(mConsumer);
   327     if (!consumer)
   328         consumer = Surrender(mStaging);
   329 }
   331 SharedSurface*
   332 SurfaceStream_TripleBuffer_Copy::SwapProducer(SurfaceFactory* factory,
   333                                               const gfx::IntSize& size)
   334 {
   335     MonitorAutoLock lock(mMonitor);
   337     RecycleScraps(factory);
   338     if (mProducer) {
   339         if (mStaging) {
   340             // We'll re-use this for a new mProducer later on if
   341             // the size remains the same
   342             Recycle(factory, mStaging);
   343         }
   345         Move(mProducer, mStaging);
   346         mStaging->Fence();
   348         New(factory, size, mProducer);
   350         if (mProducer && mStaging->Size() == mProducer->Size())
   351             SharedSurface::Copy(mStaging, mProducer, factory);
   352     } else {
   353         New(factory, size, mProducer);
   354     }
   356     return mProducer;
   357 }
   360 SharedSurface*
   361 SurfaceStream_TripleBuffer_Copy::SwapConsumer_NoWait()
   362 {
   363     MonitorAutoLock lock(mMonitor);
   365     if (mStaging) {
   366         Scrap(mConsumer);
   367         Move(mStaging, mConsumer);
   368     }
   370     return mConsumer;
   371 }
   373 void SurfaceStream_TripleBuffer::Init(SurfaceStream* prevStream)
   374 {
   375     if (!prevStream)
   376         return;
   378     SharedSurface* prevProducer = nullptr;
   379     SharedSurface* prevConsumer = nullptr;
   380     prevStream->SurrenderSurfaces(prevProducer, prevConsumer);
   382     if (prevConsumer == prevProducer)
   383         prevConsumer = nullptr;
   385     mProducer = Absorb(prevProducer);
   386     mConsumer = Absorb(prevConsumer);
   387 }
   390 SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream)
   391     : SurfaceStream(type, prevStream)
   392     , mStaging(nullptr)
   393     , mConsumer(nullptr)
   394 {
   395     SurfaceStream_TripleBuffer::Init(prevStream);
   396 }
   398 SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStream* prevStream)
   399     : SurfaceStream(SurfaceStreamType::TripleBuffer, prevStream)
   400     , mStaging(nullptr)
   401     , mConsumer(nullptr)
   402 {
   403     SurfaceStream_TripleBuffer::Init(prevStream);
   404 }
   406 SurfaceStream_TripleBuffer::~SurfaceStream_TripleBuffer()
   407 {
   408     Delete(mStaging);
   409     Delete(mConsumer);
   410 }
   412 void
   413 SurfaceStream_TripleBuffer::SurrenderSurfaces(SharedSurface*& producer,
   414                                               SharedSurface*& consumer)
   415 {
   416     mIsAlive = false;
   418     producer = Surrender(mProducer);
   419     consumer = Surrender(mConsumer);
   421     if (!consumer)
   422         consumer = Surrender(mStaging);
   423 }
   425 SharedSurface*
   426 SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory,
   427                                          const gfx::IntSize& size)
   428 {
   429     PROFILER_LABEL("SurfaceStream_TripleBuffer", "SwapProducer");
   431     MonitorAutoLock lock(mMonitor);
   432     if (mProducer) {
   433         RecycleScraps(factory);
   435         // If WaitForCompositor succeeds, mStaging has moved to mConsumer.
   436         // If it failed, we might have to scrap it.
   437         if (mStaging && !WaitForCompositor())
   438             Scrap(mStaging);
   440         MOZ_ASSERT(!mStaging);
   441         Move(mProducer, mStaging);
   442         mStaging->Fence();
   443     }
   445     MOZ_ASSERT(!mProducer);
   446     New(factory, size, mProducer);
   448     return mProducer;
   449 }
   451 SharedSurface*
   452 SurfaceStream_TripleBuffer::SwapConsumer_NoWait()
   453 {
   454     MonitorAutoLock lock(mMonitor);
   455     if (mStaging) {
   456         Scrap(mConsumer);
   457         Move(mStaging, mConsumer);
   458         mMonitor.NotifyAll();
   459     }
   461     return mConsumer;
   462 }
   464 SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream)
   465     : SurfaceStream_TripleBuffer(SurfaceStreamType::TripleBuffer_Async, prevStream)
   466 {
   467 }
   469 SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
   470 {
   471 }
   473 bool
   474 SurfaceStream_TripleBuffer_Async::WaitForCompositor()
   475 {
   476     PROFILER_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor");
   478     // We are assumed to be locked
   479     while (mStaging) {
   480         if (!NS_SUCCEEDED(mMonitor.Wait(PR_MillisecondsToInterval(100)))) {
   481             return false;
   482         }
   483     }
   485     return true;
   486 }
   488 } /* namespace gfx */
   489 } /* namespace mozilla */

mercurial