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