/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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_RecordedCanvasEventImpl_h #define mozilla_layers_RecordedCanvasEventImpl_h #include "mozilla/gfx/RecordedEvent.h" #include "mozilla/gfx/RecordingTypes.h" #include "mozilla/layers/CanvasTranslator.h" #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/TextureClient.h" namespace mozilla { namespace layers { using gfx::DrawTarget; using gfx::IntSize; using gfx::RecordedEvent; using gfx::RecordedEventDerived; using EventType = gfx::RecordedEvent::EventType; using gfx::ReadElement; using gfx::ReferencePtr; using gfx::SurfaceFormat; using gfx::WriteElement; using ipc::SharedMemoryBasic; const EventType CANVAS_BEGIN_TRANSACTION = EventType::LAST; const EventType CANVAS_END_TRANSACTION = EventType(EventType::LAST + 1); const EventType CANVAS_FLUSH = EventType(EventType::LAST + 2); const EventType TEXTURE_LOCK = EventType(EventType::LAST + 3); const EventType TEXTURE_UNLOCK = EventType(EventType::LAST + 4); const EventType CACHE_DATA_SURFACE = EventType(EventType::LAST + 5); const EventType PREPARE_DATA_FOR_SURFACE = EventType(EventType::LAST + 6); const EventType GET_DATA_FOR_SURFACE = EventType(EventType::LAST + 7); const EventType ADD_SURFACE_ALIAS = EventType(EventType::LAST + 8); const EventType REMOVE_SURFACE_ALIAS = EventType(EventType::LAST + 9); class RecordedCanvasBeginTransaction final : public RecordedEventDerived { public: RecordedCanvasBeginTransaction() : RecordedEventDerived(CANVAS_BEGIN_TRANSACTION) {} template MOZ_IMPLICIT RecordedCanvasBeginTransaction(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedCanvasBeginTransaction"; } }; inline bool RecordedCanvasBeginTransaction::PlayCanvasEvent( CanvasTranslator* aTranslator) const { aTranslator->BeginTransaction(); return true; } template void RecordedCanvasBeginTransaction::Record(S& aStream) const {} template RecordedCanvasBeginTransaction::RecordedCanvasBeginTransaction(S& aStream) : RecordedEventDerived(CANVAS_BEGIN_TRANSACTION) {} class RecordedCanvasEndTransaction final : public RecordedEventDerived { public: RecordedCanvasEndTransaction() : RecordedEventDerived(CANVAS_END_TRANSACTION) {} template MOZ_IMPLICIT RecordedCanvasEndTransaction(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedCanvasEndTransaction"; } }; inline bool RecordedCanvasEndTransaction::PlayCanvasEvent( CanvasTranslator* aTranslator) const { aTranslator->EndTransaction(); return true; } template void RecordedCanvasEndTransaction::Record(S& aStream) const {} template RecordedCanvasEndTransaction::RecordedCanvasEndTransaction(S& aStream) : RecordedEventDerived(CANVAS_END_TRANSACTION) {} class RecordedCanvasFlush final : public RecordedEventDerived { public: RecordedCanvasFlush() : RecordedEventDerived(CANVAS_FLUSH) {} template MOZ_IMPLICIT RecordedCanvasFlush(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedCanvasFlush"; } }; inline bool RecordedCanvasFlush::PlayCanvasEvent( CanvasTranslator* aTranslator) const { aTranslator->Flush(); return true; } template void RecordedCanvasFlush::Record(S& aStream) const {} template RecordedCanvasFlush::RecordedCanvasFlush(S& aStream) : RecordedEventDerived(CANVAS_FLUSH) {} class RecordedTextureLock final : public RecordedEventDerived { public: RecordedTextureLock(DrawTarget* aDT, const OpenMode aMode) : RecordedEventDerived(TEXTURE_LOCK), mDT(aDT), mMode(aMode) {} template MOZ_IMPLICIT RecordedTextureLock(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "TextureLock"; } private: ReferencePtr mDT; OpenMode mMode; }; inline bool RecordedTextureLock::PlayCanvasEvent( CanvasTranslator* aTranslator) const { TextureData* textureData = aTranslator->LookupTextureData(mDT); if (!textureData) { return false; } gfx::AutoSerializeWithMoz2D serializeWithMoz2D( aTranslator->GetReferenceDrawTarget()->GetBackendType()); textureData->Lock(mMode); return true; } template void RecordedTextureLock::Record(S& aStream) const { WriteElement(aStream, mDT); WriteElement(aStream, mMode); } template RecordedTextureLock::RecordedTextureLock(S& aStream) : RecordedEventDerived(TEXTURE_LOCK) { ReadElement(aStream, mDT); ReadElementConstrained(aStream, mMode, OpenMode::OPEN_NONE, OpenMode::OPEN_READ_WRITE_ASYNC); } class RecordedTextureUnlock final : public RecordedEventDerived { public: explicit RecordedTextureUnlock(DrawTarget* aDT) : RecordedEventDerived(TEXTURE_UNLOCK), mDT(aDT) {} template MOZ_IMPLICIT RecordedTextureUnlock(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "TextureUnlock"; } private: ReferencePtr mDT; }; inline bool RecordedTextureUnlock::PlayCanvasEvent( CanvasTranslator* aTranslator) const { TextureData* textureData = aTranslator->LookupTextureData(mDT); if (!textureData) { return false; } gfx::AutoSerializeWithMoz2D serializeWithMoz2D( aTranslator->GetReferenceDrawTarget()->GetBackendType()); textureData->Unlock(); return true; } template void RecordedTextureUnlock::Record(S& aStream) const { WriteElement(aStream, mDT); } template RecordedTextureUnlock::RecordedTextureUnlock(S& aStream) : RecordedEventDerived(TEXTURE_UNLOCK) { ReadElement(aStream, mDT); } class RecordedCacheDataSurface final : public RecordedEventDerived { public: explicit RecordedCacheDataSurface(gfx::SourceSurface* aSurface) : RecordedEventDerived(CACHE_DATA_SURFACE), mSurface(aSurface) {} template MOZ_IMPLICIT RecordedCacheDataSurface(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedCacheDataSurface"; } private: ReferencePtr mSurface; }; inline bool RecordedCacheDataSurface::PlayCanvasEvent( CanvasTranslator* aTranslator) const { RefPtr surface = aTranslator->LookupSourceSurface(mSurface); RefPtr dataSurface = surface->GetDataSurface(); aTranslator->AddDataSurface(mSurface, std::move(dataSurface)); return true; } template void RecordedCacheDataSurface::Record(S& aStream) const { WriteElement(aStream, mSurface); } template RecordedCacheDataSurface::RecordedCacheDataSurface(S& aStream) : RecordedEventDerived(CACHE_DATA_SURFACE) { ReadElement(aStream, mSurface); } class RecordedPrepareDataForSurface final : public RecordedEventDerived { public: explicit RecordedPrepareDataForSurface(const gfx::SourceSurface* aSurface) : RecordedEventDerived(PREPARE_DATA_FOR_SURFACE), mSurface(aSurface) {} template MOZ_IMPLICIT RecordedPrepareDataForSurface(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedPrepareDataForSurface"; } private: ReferencePtr mSurface; }; inline bool RecordedPrepareDataForSurface::PlayCanvasEvent( CanvasTranslator* aTranslator) const { RefPtr dataSurface = aTranslator->LookupDataSurface(mSurface); if (!dataSurface) { RefPtr surface = aTranslator->LookupSourceSurface(mSurface); if (!surface) { return false; } dataSurface = surface->GetDataSurface(); if (!dataSurface) { return false; } } auto preparedMap = MakeUnique( dataSurface, gfx::DataSourceSurface::READ); aTranslator->SetPreparedMap(mSurface, std::move(preparedMap)); return true; } template void RecordedPrepareDataForSurface::Record(S& aStream) const { WriteElement(aStream, mSurface); } template RecordedPrepareDataForSurface::RecordedPrepareDataForSurface(S& aStream) : RecordedEventDerived(PREPARE_DATA_FOR_SURFACE) { ReadElement(aStream, mSurface); } class RecordedGetDataForSurface final : public RecordedEventDerived { public: explicit RecordedGetDataForSurface(const gfx::SourceSurface* aSurface) : RecordedEventDerived(GET_DATA_FOR_SURFACE), mSurface(aSurface) {} template MOZ_IMPLICIT RecordedGetDataForSurface(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedGetDataForSurface"; } private: ReferencePtr mSurface; }; inline bool RecordedGetDataForSurface::PlayCanvasEvent( CanvasTranslator* aTranslator) const { RefPtr surface = aTranslator->LookupSourceSurface(mSurface); if (!surface) { return false; } UniquePtr map = aTranslator->GetPreparedMap(mSurface); gfx::IntSize ssSize = surface->GetSize(); size_t dataFormatWidth = ssSize.width * BytesPerPixel(surface->GetFormat()); int32_t srcStride = map->GetStride(); char* src = reinterpret_cast(map->GetData()); char* endSrc = src + (ssSize.height * srcStride); while (src < endSrc) { aTranslator->ReturnWrite(src, dataFormatWidth); src += srcStride; } return true; } template void RecordedGetDataForSurface::Record(S& aStream) const { WriteElement(aStream, mSurface); } template RecordedGetDataForSurface::RecordedGetDataForSurface(S& aStream) : RecordedEventDerived(GET_DATA_FOR_SURFACE) { ReadElement(aStream, mSurface); } class RecordedAddSurfaceAlias final : public RecordedEventDerived { public: RecordedAddSurfaceAlias(ReferencePtr aSurfaceAlias, const RefPtr& aActualSurface) : RecordedEventDerived(ADD_SURFACE_ALIAS), mSurfaceAlias(aSurfaceAlias), mActualSurface(aActualSurface) {} template MOZ_IMPLICIT RecordedAddSurfaceAlias(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedAddSurfaceAlias"; } private: ReferencePtr mSurfaceAlias; ReferencePtr mActualSurface; }; inline bool RecordedAddSurfaceAlias::PlayCanvasEvent( CanvasTranslator* aTranslator) const { RefPtr surface = aTranslator->LookupSourceSurface(mActualSurface); if (!surface) { return false; } aTranslator->AddSourceSurface(mSurfaceAlias, surface); return true; } template void RecordedAddSurfaceAlias::Record(S& aStream) const { WriteElement(aStream, mSurfaceAlias); WriteElement(aStream, mActualSurface); } template RecordedAddSurfaceAlias::RecordedAddSurfaceAlias(S& aStream) : RecordedEventDerived(ADD_SURFACE_ALIAS) { ReadElement(aStream, mSurfaceAlias); ReadElement(aStream, mActualSurface); } class RecordedRemoveSurfaceAlias final : public RecordedEventDerived { public: explicit RecordedRemoveSurfaceAlias(ReferencePtr aSurfaceAlias) : RecordedEventDerived(REMOVE_SURFACE_ALIAS), mSurfaceAlias(aSurfaceAlias) {} template MOZ_IMPLICIT RecordedRemoveSurfaceAlias(S& aStream); bool PlayCanvasEvent(CanvasTranslator* aTranslator) const; template void Record(S& aStream) const; std::string GetName() const final { return "RecordedRemoveSurfaceAlias"; } private: ReferencePtr mSurfaceAlias; }; inline bool RecordedRemoveSurfaceAlias::PlayCanvasEvent( CanvasTranslator* aTranslator) const { aTranslator->RemoveSourceSurface(mSurfaceAlias); return true; } template void RecordedRemoveSurfaceAlias::Record(S& aStream) const { WriteElement(aStream, mSurfaceAlias); } template RecordedRemoveSurfaceAlias::RecordedRemoveSurfaceAlias(S& aStream) : RecordedEventDerived(REMOVE_SURFACE_ALIAS) { ReadElement(aStream, mSurfaceAlias); } #define FOR_EACH_CANVAS_EVENT(f) \ f(CANVAS_BEGIN_TRANSACTION, RecordedCanvasBeginTransaction); \ f(CANVAS_END_TRANSACTION, RecordedCanvasEndTransaction); \ f(CANVAS_FLUSH, RecordedCanvasFlush); \ f(TEXTURE_LOCK, RecordedTextureLock); \ f(TEXTURE_UNLOCK, RecordedTextureUnlock); \ f(CACHE_DATA_SURFACE, RecordedCacheDataSurface); \ f(PREPARE_DATA_FOR_SURFACE, RecordedPrepareDataForSurface); \ f(GET_DATA_FOR_SURFACE, RecordedGetDataForSurface); \ f(ADD_SURFACE_ALIAS, RecordedAddSurfaceAlias); \ f(REMOVE_SURFACE_ALIAS, RecordedRemoveSurfaceAlias); } // namespace layers } // namespace mozilla #endif // mozilla_layers_RecordedCanvasEventImpl_h