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 "InlineTranslator.h"
8 #include "RecordedEventImpl.h"
9 #include "DrawEventRecorder.h"
10
11 #include "gfxContext.h"
12 #include "nsDeviceContext.h"
13 #include "mozilla/gfx/RecordingTypes.h"
14 #include "mozilla/UniquePtr.h"
15
16 using namespace mozilla::gfx;
17
18 namespace mozilla::gfx {
19
InlineTranslator()20 InlineTranslator::InlineTranslator() : mFontContext(nullptr) {}
21
InlineTranslator(DrawTarget * aDT,void * aFontContext)22 InlineTranslator::InlineTranslator(DrawTarget* aDT, void* aFontContext)
23 : mBaseDT(aDT), mFontContext(aFontContext) {}
24
TranslateRecording(char * aData,size_t aLen)25 bool InlineTranslator::TranslateRecording(char* aData, size_t aLen) {
26 // an istream like class for reading from memory
27 struct MemReader {
28 MemReader(char* aData, size_t aLen) : mData(aData), mEnd(aData + aLen) {}
29 void read(char* s, std::streamsize n) {
30 if (n <= (mEnd - mData)) {
31 memcpy(s, mData, n);
32 mData += n;
33 } else {
34 // We've requested more data than is available
35 // set the Reader into an eof state
36 SetIsBad();
37 }
38 }
39 bool eof() { return mData > mEnd; }
40 bool good() { return !eof(); }
41 void SetIsBad() { mData = mEnd + 1; }
42
43 char* mData;
44 char* mEnd;
45 };
46 MemReader reader(aData, aLen);
47
48 uint32_t magicInt;
49 ReadElement(reader, magicInt);
50 if (magicInt != mozilla::gfx::kMagicInt) {
51 mError = "Magic";
52 return false;
53 }
54
55 uint16_t majorRevision;
56 ReadElement(reader, majorRevision);
57 if (majorRevision != kMajorRevision) {
58 mError = "Major";
59 return false;
60 }
61
62 uint16_t minorRevision;
63 ReadElement(reader, minorRevision);
64 if (minorRevision > kMinorRevision) {
65 mError = "Minor";
66 return false;
67 }
68
69 int32_t eventType;
70 ReadElement(reader, eventType);
71 while (reader.good()) {
72 bool success = RecordedEvent::DoWithEvent(
73 reader, static_cast<RecordedEvent::EventType>(eventType),
74 [&](RecordedEvent* recordedEvent) -> bool {
75 // Make sure that the whole event was read from the stream
76 // successfully.
77 if (!reader.good()) {
78 mError = " READ";
79 return false;
80 }
81
82 if (!recordedEvent->PlayEvent(this)) {
83 mError = " PLAY";
84 return false;
85 }
86
87 return true;
88 });
89 if (!success) {
90 mError = RecordedEvent::GetEventName(
91 static_cast<RecordedEvent::EventType>(eventType)) +
92 mError;
93 return false;
94 }
95
96 ReadElement(reader, eventType);
97 }
98
99 return true;
100 }
101
CreateDrawTarget(ReferencePtr aRefPtr,const gfx::IntSize & aSize,gfx::SurfaceFormat aFormat)102 already_AddRefed<DrawTarget> InlineTranslator::CreateDrawTarget(
103 ReferencePtr aRefPtr, const gfx::IntSize& aSize,
104 gfx::SurfaceFormat aFormat) {
105 MOZ_ASSERT(mBaseDT, "mBaseDT has not been initialized.");
106
107 RefPtr<DrawTarget> drawTarget = mBaseDT;
108 AddDrawTarget(aRefPtr, drawTarget);
109 return drawTarget.forget();
110 }
111
LookupExternalSurface(uint64_t aKey)112 already_AddRefed<SourceSurface> InlineTranslator::LookupExternalSurface(
113 uint64_t aKey) {
114 if (mExternalSurfaces) {
115 RefPtr<SourceSurface> surface = mExternalSurfaces->Get(aKey);
116 if (surface) {
117 return surface.forget();
118 }
119 }
120
121 if (!mDependentSurfaces) {
122 return nullptr;
123 }
124
125 RefPtr<RecordedDependentSurface> recordedSurface =
126 mDependentSurfaces->Get(aKey);
127 if (!recordedSurface) {
128 return nullptr;
129 }
130
131 RefPtr<DrawTarget> newDT = GetReferenceDrawTarget()->CreateSimilarDrawTarget(
132 recordedSurface->mSize, SurfaceFormat::B8G8R8A8);
133
134 InlineTranslator translator(newDT, nullptr);
135 translator.SetDependentSurfaces(mDependentSurfaces);
136 if (!translator.TranslateRecording((char*)recordedSurface->mRecording.mData,
137 recordedSurface->mRecording.mLen)) {
138 return nullptr;
139 }
140
141 RefPtr<SourceSurface> snapshot = newDT->Snapshot();
142 return snapshot.forget();
143 }
144
145 } // namespace mozilla::gfx
146