michael@0: /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef SURFACESTREAM_H_ michael@0: #define SURFACESTREAM_H_ michael@0: michael@0: #include michael@0: #include michael@0: #include "mozilla/Monitor.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/gfx/Point.h" michael@0: #include "mozilla/GenericRefCounted.h" michael@0: #include "SurfaceTypes.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace gl { michael@0: class GLContext; michael@0: } michael@0: michael@0: namespace gfx { michael@0: class SharedSurface; michael@0: class SurfaceFactory; michael@0: michael@0: // Owned by: ScreenBuffer michael@0: class SurfaceStream : public GenericAtomicRefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream) michael@0: typedef enum { michael@0: MainThread, michael@0: OffMainThread michael@0: } OMTC; michael@0: michael@0: static SurfaceStreamType ChooseGLStreamType(OMTC omtc, michael@0: bool preserveBuffer); michael@0: michael@0: static SurfaceStream* CreateForType(SurfaceStreamType type, michael@0: mozilla::gl::GLContext* glContext, michael@0: SurfaceStream* prevStream = nullptr); michael@0: michael@0: SurfaceStreamHandle GetShareHandle() { michael@0: return reinterpret_cast(this); michael@0: } michael@0: michael@0: static SurfaceStream* FromHandle(SurfaceStreamHandle handle) { michael@0: return (SurfaceStream*)handle; michael@0: } michael@0: michael@0: const SurfaceStreamType mType; michael@0: michael@0: mozilla::gl::GLContext* GLContext() const { return mGLContext; } michael@0: michael@0: michael@0: protected: michael@0: // |mProd| is owned by us, but can be ripped away when michael@0: // creating a new GLStream from this one. michael@0: SharedSurface* mProducer; michael@0: std::set mSurfaces; michael@0: std::stack mScraps; michael@0: mutable Monitor mMonitor; michael@0: bool mIsAlive; michael@0: michael@0: // Do not use this. It exists solely so we can ref it in CanvasClientWebGL::Update() michael@0: // before sent up to the compositor. You have been warned (Bug 894405) michael@0: mozilla::gl::GLContext* mGLContext; michael@0: michael@0: // |previous| can be null, indicating this is the first one. michael@0: // Otherwise, we pull in |mProd| from |previous| an our initial surface. michael@0: SurfaceStream(SurfaceStreamType type, SurfaceStream* prevStream) michael@0: : mType(type) michael@0: , mProducer(nullptr) michael@0: , mMonitor("SurfaceStream monitor") michael@0: , mIsAlive(true) michael@0: { michael@0: MOZ_ASSERT(!prevStream || mType != prevStream->mType, michael@0: "We should not need to create a SurfaceStream from another " michael@0: "of the same type."); michael@0: } michael@0: michael@0: public: michael@0: virtual ~SurfaceStream(); michael@0: michael@0: protected: michael@0: // These functions below are helpers to make trading buffers around easier. michael@0: // For instance, using Move(a,b) instead of normal assignment assures that michael@0: // we are never leaving anything hanging around, keeping things very safe. michael@0: static void Move(SharedSurface*& from, SharedSurface*& to) { michael@0: MOZ_ASSERT(!to); michael@0: to = from; michael@0: from = nullptr; michael@0: } michael@0: michael@0: void New(SurfaceFactory* factory, const gfx::IntSize& size, michael@0: SharedSurface*& surf); michael@0: void Delete(SharedSurface*& surf); michael@0: void Recycle(SurfaceFactory* factory, SharedSurface*& surf); michael@0: michael@0: // Surrender control of a surface, and return it for use elsewhere. michael@0: SharedSurface* Surrender(SharedSurface*& surf); michael@0: // Absorb control of a surface from elsewhere, clears its old location. michael@0: SharedSurface* Absorb(SharedSurface*& surf); michael@0: michael@0: // For holding on to surfaces we don't need until we can return them to the michael@0: // Producer's factory via SurfaceFactory::Recycle. michael@0: // Not thread-safe. michael@0: void Scrap(SharedSurface*& scrap); michael@0: michael@0: // Not thread-safe. michael@0: void RecycleScraps(SurfaceFactory* factory); michael@0: michael@0: public: michael@0: /* Note that ownership of the returned surfaces below michael@0: * transfers to the caller. michael@0: * SwapProd returns null on failure. Returning null doesn't mean nothing michael@0: * happened, but rather that a surface allocation failed. After returning michael@0: * null, we must be able to call SwapProducer again with better args michael@0: * and have everything work again. michael@0: * One common failure is asking for a too-large |size|. michael@0: */ michael@0: virtual SharedSurface* SwapProducer(SurfaceFactory* factory, michael@0: const gfx::IntSize& size) = 0; michael@0: michael@0: virtual SharedSurface* Resize(SurfaceFactory* factory, const gfx::IntSize& size); michael@0: michael@0: virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) { MOZ_ASSERT(0); return false; } michael@0: michael@0: protected: michael@0: // SwapCons will return the same surface more than once, michael@0: // if nothing new has been published. michael@0: virtual SharedSurface* SwapConsumer_NoWait() = 0; michael@0: michael@0: public: michael@0: virtual SharedSurface* SwapConsumer(); michael@0: michael@0: virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer) = 0; michael@0: }; michael@0: michael@0: // Not thread-safe. Don't use cross-threads. michael@0: class SurfaceStream_SingleBuffer michael@0: : public SurfaceStream michael@0: { michael@0: protected: michael@0: SharedSurface* mConsumer; // Only present after resize-swap. michael@0: michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_SingleBuffer) michael@0: SurfaceStream_SingleBuffer(SurfaceStream* prevStream); michael@0: virtual ~SurfaceStream_SingleBuffer(); michael@0: michael@0: /* Since we're non-OMTC, we know the order of execution here: michael@0: * SwapProd gets called in UpdateSurface, followed by michael@0: * SwapCons being called in Render. michael@0: */ michael@0: virtual SharedSurface* SwapProducer(SurfaceFactory* factory, michael@0: const gfx::IntSize& size); michael@0: michael@0: virtual SharedSurface* SwapConsumer_NoWait(); michael@0: michael@0: virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer); michael@0: }; michael@0: michael@0: // Our hero for preserveDrawingBuffer=true. michael@0: class SurfaceStream_TripleBuffer_Copy michael@0: : public SurfaceStream michael@0: { michael@0: protected: michael@0: SharedSurface* mStaging; michael@0: SharedSurface* mConsumer; michael@0: michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer_Copy) michael@0: SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream); michael@0: virtual ~SurfaceStream_TripleBuffer_Copy(); michael@0: michael@0: virtual SharedSurface* SwapProducer(SurfaceFactory* factory, michael@0: const gfx::IntSize& size); michael@0: michael@0: virtual SharedSurface* SwapConsumer_NoWait(); michael@0: michael@0: virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer); michael@0: }; michael@0: michael@0: michael@0: class SurfaceStream_TripleBuffer michael@0: : public SurfaceStream michael@0: { michael@0: protected: michael@0: SharedSurface* mStaging; michael@0: SharedSurface* mConsumer; michael@0: michael@0: // Returns true if we were able to wait, false if not michael@0: virtual bool WaitForCompositor() { return false; } michael@0: michael@0: // To support subclasses initializing the mType. michael@0: SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream); michael@0: michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer) michael@0: SurfaceStream_TripleBuffer(SurfaceStream* prevStream); michael@0: virtual ~SurfaceStream_TripleBuffer(); michael@0: virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory); michael@0: michael@0: private: michael@0: // Common constructor code. michael@0: void Init(SurfaceStream* prevStream); michael@0: michael@0: public: michael@0: // Done writing to prod, swap prod and staging michael@0: virtual SharedSurface* SwapProducer(SurfaceFactory* factory, michael@0: const gfx::IntSize& size); michael@0: michael@0: virtual SharedSurface* SwapConsumer_NoWait(); michael@0: michael@0: virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer); michael@0: }; michael@0: michael@0: class SurfaceStream_TripleBuffer_Async michael@0: : public SurfaceStream_TripleBuffer michael@0: { michael@0: protected: michael@0: virtual bool WaitForCompositor() MOZ_OVERRIDE; michael@0: michael@0: public: michael@0: SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream); michael@0: virtual ~SurfaceStream_TripleBuffer_Async(); michael@0: }; michael@0: michael@0: michael@0: } /* namespace gfx */ michael@0: } /* namespace mozilla */ michael@0: michael@0: #endif /* SURFACESTREAM_H_ */