1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "TextureRecorded.h"
8 
9 #include "mozilla/gfx/gfxVars.h"
10 #include "RecordedCanvasEventImpl.h"
11 
12 namespace mozilla {
13 namespace layers {
14 
15 // The texture ID is used in the GPU process both to lookup the real texture in
16 // the canvas threads and to lookup the SurfaceDescriptor for that texture in
17 // the compositor thread. It is therefore important that the ID is unique (per
18 // recording process), otherwise an old descriptor can be picked up. This means
19 // we can't use the pointer in the recording process as an ID like we do for
20 // other objects.
21 static int64_t sNextRecordedTextureId = 0;
22 
RecordedTextureData(already_AddRefed<CanvasChild> aCanvasChild,gfx::IntSize aSize,gfx::SurfaceFormat aFormat,TextureType aTextureType)23 RecordedTextureData::RecordedTextureData(
24     already_AddRefed<CanvasChild> aCanvasChild, gfx::IntSize aSize,
25     gfx::SurfaceFormat aFormat, TextureType aTextureType)
26     : mCanvasChild(aCanvasChild), mSize(aSize), mFormat(aFormat) {
27   mCanvasChild->EnsureRecorder(aTextureType);
28 }
29 
~RecordedTextureData()30 RecordedTextureData::~RecordedTextureData() {
31   // We need the translator to drop its reference for the DrawTarget first,
32   // because the TextureData might need to destroy its DrawTarget within a lock.
33   mDT = nullptr;
34   mCanvasChild->RecordEvent(RecordedTextureDestruction(mTextureId));
35 }
36 
FillInfo(TextureData::Info & aInfo) const37 void RecordedTextureData::FillInfo(TextureData::Info& aInfo) const {
38   aInfo.size = mSize;
39   aInfo.format = mFormat;
40   aInfo.supportsMoz2D = true;
41   aInfo.hasIntermediateBuffer = false;
42   aInfo.hasSynchronization = true;
43 }
44 
Lock(OpenMode aMode)45 bool RecordedTextureData::Lock(OpenMode aMode) {
46   mCanvasChild->EnsureBeginTransaction();
47   if (!mDT) {
48     mTextureId = sNextRecordedTextureId++;
49     mCanvasChild->RecordEvent(RecordedNextTextureId(mTextureId));
50     mDT = mCanvasChild->CreateDrawTarget(mSize, mFormat);
51     if (!mDT) {
52       return false;
53     }
54 
55     // We lock the TextureData when we create it to get the remote DrawTarget.
56     mCanvasChild->OnTextureWriteLock();
57     mLockedMode = aMode;
58     return true;
59   }
60 
61   mCanvasChild->RecordEvent(RecordedTextureLock(mTextureId, aMode));
62   if (aMode & OpenMode::OPEN_WRITE) {
63     mCanvasChild->OnTextureWriteLock();
64     mSnapshot = nullptr;
65   }
66   mLockedMode = aMode;
67   return true;
68 }
69 
Unlock()70 void RecordedTextureData::Unlock() {
71   if ((mLockedMode & OpenMode::OPEN_WRITE) &&
72       mCanvasChild->ShouldCacheDataSurface()) {
73     mSnapshot = mDT->Snapshot();
74     mDT->DetachAllSnapshots();
75   }
76 
77   mCanvasChild->RecordEvent(RecordedTextureUnlock(mTextureId));
78   mLockedMode = OpenMode::OPEN_NONE;
79 }
80 
BorrowDrawTarget()81 already_AddRefed<gfx::DrawTarget> RecordedTextureData::BorrowDrawTarget() {
82   return do_AddRef(mDT);
83 }
84 
BorrowSnapshot()85 already_AddRefed<gfx::SourceSurface> RecordedTextureData::BorrowSnapshot() {
86   MOZ_ASSERT(mDT);
87 
88   if (mSnapshot) {
89     return mCanvasChild->WrapSurface(mSnapshot);
90   }
91 
92   return mCanvasChild->WrapSurface(mDT->Snapshot());
93 }
94 
Deallocate(LayersIPCChannel * aAllocator)95 void RecordedTextureData::Deallocate(LayersIPCChannel* aAllocator) {}
96 
Serialize(SurfaceDescriptor & aDescriptor)97 bool RecordedTextureData::Serialize(SurfaceDescriptor& aDescriptor) {
98   aDescriptor = SurfaceDescriptorRecorded(mTextureId);
99   return true;
100 }
101 
OnForwardedToHost()102 void RecordedTextureData::OnForwardedToHost() {
103   mCanvasChild->OnTextureForwarded();
104   if (mSnapshot && mCanvasChild->ShouldCacheDataSurface()) {
105     mCanvasChild->RecordEvent(RecordedCacheDataSurface(mSnapshot.get()));
106   }
107 }
108 
GetTextureFlags() const109 TextureFlags RecordedTextureData::GetTextureFlags() const {
110   TextureFlags flags = TextureFlags::NO_FLAGS;
111   // With WebRender, resource open happens asynchronously on RenderThread.
112   // Use WAIT_HOST_USAGE_END to keep TextureClient alive during host side usage.
113   if (gfx::gfxVars::UseWebRender()) {
114     flags |= TextureFlags::WAIT_HOST_USAGE_END;
115   }
116   return flags;
117 }
118 
119 }  // namespace layers
120 }  // namespace mozilla
121