/src/mozilla-central/gfx/2d/SourceSurfaceSkia.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
8 | | #include "Logging.h" |
9 | | #include "SourceSurfaceSkia.h" |
10 | | #include "HelpersSkia.h" |
11 | | #include "DrawTargetSkia.h" |
12 | | #include "DataSurfaceHelpers.h" |
13 | | #include "skia/include/core/SkData.h" |
14 | | #include "mozilla/CheckedInt.h" |
15 | | |
16 | | using namespace std; |
17 | | |
18 | | namespace mozilla { |
19 | | namespace gfx { |
20 | | |
21 | | SourceSurfaceSkia::SourceSurfaceSkia() |
22 | | : mFormat(SurfaceFormat::UNKNOWN) |
23 | | , mStride(0) |
24 | | , mDrawTarget(nullptr) |
25 | | , mChangeMutex("SourceSurfaceSkia::mChangeMutex") |
26 | 0 | { |
27 | 0 | } |
28 | | |
29 | | SourceSurfaceSkia::~SourceSurfaceSkia() |
30 | 0 | { |
31 | 0 | } |
32 | | |
33 | | IntSize |
34 | | SourceSurfaceSkia::GetSize() const |
35 | 0 | { |
36 | 0 | return mSize; |
37 | 0 | } |
38 | | |
39 | | SurfaceFormat |
40 | | SourceSurfaceSkia::GetFormat() const |
41 | 0 | { |
42 | 0 | return mFormat; |
43 | 0 | } |
44 | | |
45 | | sk_sp<SkImage> |
46 | | SourceSurfaceSkia::GetImage() |
47 | 0 | { |
48 | 0 | MutexAutoLock lock(mChangeMutex); |
49 | 0 | sk_sp<SkImage> image = mImage; |
50 | 0 | return image; |
51 | 0 | } |
52 | | |
53 | | static sk_sp<SkData> |
54 | | MakeSkData(void* aData, int32_t aHeight, size_t aStride) |
55 | 0 | { |
56 | 0 | CheckedInt<size_t> size = aStride; |
57 | 0 | size *= aHeight; |
58 | 0 | if (size.isValid()) { |
59 | 0 | void* mem = sk_malloc_flags(size.value(), 0); |
60 | 0 | if (mem) { |
61 | 0 | if (aData) { |
62 | 0 | memcpy(mem, aData, size.value()); |
63 | 0 | } |
64 | 0 | return SkData::MakeFromMalloc(mem, size.value()); |
65 | 0 | } |
66 | 0 | } |
67 | 0 | return nullptr; |
68 | 0 | } |
69 | | |
70 | | static sk_sp<SkImage> |
71 | | ReadSkImage(const sk_sp<SkImage>& aImage, const SkImageInfo& aInfo, size_t aStride) |
72 | 0 | { |
73 | 0 | if (sk_sp<SkData> data = MakeSkData(nullptr, aInfo.height(), aStride)) { |
74 | 0 | if (aImage->readPixels(aInfo, data->writable_data(), aStride, 0, 0, SkImage::kDisallow_CachingHint)) { |
75 | 0 | return SkImage::MakeRasterData(aInfo, data, aStride); |
76 | 0 | } |
77 | 0 | } |
78 | 0 | return nullptr; |
79 | 0 | } |
80 | | |
81 | | bool |
82 | | SourceSurfaceSkia::InitFromData(unsigned char* aData, |
83 | | const IntSize &aSize, |
84 | | int32_t aStride, |
85 | | SurfaceFormat aFormat) |
86 | 0 | { |
87 | 0 | sk_sp<SkData> data = MakeSkData(aData, aSize.height, aStride); |
88 | 0 | if (!data) { |
89 | 0 | return false; |
90 | 0 | } |
91 | 0 | |
92 | 0 | SkImageInfo info = MakeSkiaImageInfo(aSize, aFormat); |
93 | 0 | mImage = SkImage::MakeRasterData(info, data, aStride); |
94 | 0 | if (!mImage) { |
95 | 0 | return false; |
96 | 0 | } |
97 | 0 | |
98 | 0 | mSize = aSize; |
99 | 0 | mFormat = aFormat; |
100 | 0 | mStride = aStride; |
101 | 0 | return true; |
102 | 0 | } |
103 | | |
104 | | bool |
105 | | SourceSurfaceSkia::InitFromImage(const sk_sp<SkImage>& aImage, |
106 | | SurfaceFormat aFormat, |
107 | | DrawTargetSkia* aOwner) |
108 | 0 | { |
109 | 0 | if (!aImage) { |
110 | 0 | return false; |
111 | 0 | } |
112 | 0 | |
113 | 0 | mSize = IntSize(aImage->width(), aImage->height()); |
114 | 0 |
|
115 | 0 | // For the raster image case, we want to use the format and stride |
116 | 0 | // information that the underlying raster image is using, which is |
117 | 0 | // reliable. |
118 | 0 | // For the GPU case (for which peekPixels is false), we can't easily |
119 | 0 | // figure this information out. It is better to report the originally |
120 | 0 | // intended format and stride that we will convert to if this GPU |
121 | 0 | // image is ever read back into a raster image. |
122 | 0 | SkPixmap pixmap; |
123 | 0 | if (aImage->peekPixels(&pixmap)) { |
124 | 0 | mFormat = |
125 | 0 | aFormat != SurfaceFormat::UNKNOWN ? |
126 | 0 | aFormat : |
127 | 0 | SkiaColorTypeToGfxFormat(pixmap.colorType(), pixmap.alphaType()); |
128 | 0 | mStride = pixmap.rowBytes(); |
129 | 0 | } else if (aFormat != SurfaceFormat::UNKNOWN) { |
130 | 0 | mFormat = aFormat; |
131 | 0 | SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat); |
132 | 0 | mStride = SkAlign4(info.minRowBytes()); |
133 | 0 | } else { |
134 | 0 | return false; |
135 | 0 | } |
136 | 0 | |
137 | 0 | mImage = aImage; |
138 | 0 |
|
139 | 0 | if (aOwner) { |
140 | 0 | mDrawTarget = aOwner; |
141 | 0 | } |
142 | 0 |
|
143 | 0 | return true; |
144 | 0 | } |
145 | | |
146 | | uint8_t* |
147 | | SourceSurfaceSkia::GetData() |
148 | 0 | { |
149 | 0 | if (!mImage) { |
150 | 0 | return nullptr; |
151 | 0 | } |
152 | 0 | #ifdef USE_SKIA_GPU |
153 | 0 | if (mImage->isTextureBacked()) { |
154 | 0 | if (sk_sp<SkImage> raster = ReadSkImage(mImage, MakeSkiaImageInfo(mSize, mFormat), mStride)) { |
155 | 0 | mImage = raster; |
156 | 0 | } else { |
157 | 0 | gfxCriticalError() << "Failed making Skia raster image for GPU surface"; |
158 | 0 | } |
159 | 0 | } |
160 | 0 | #endif |
161 | 0 | SkPixmap pixmap; |
162 | 0 | if (!mImage->peekPixels(&pixmap)) { |
163 | 0 | gfxCriticalError() << "Failed accessing pixels for Skia raster image"; |
164 | 0 | } |
165 | 0 | return reinterpret_cast<uint8_t*>(pixmap.writable_addr()); |
166 | 0 | } |
167 | | |
168 | | bool |
169 | | SourceSurfaceSkia::Map(MapType, MappedSurface *aMappedSurface) |
170 | 0 | { |
171 | 0 | mChangeMutex.Lock(); |
172 | 0 | aMappedSurface->mData = GetData(); |
173 | 0 | aMappedSurface->mStride = Stride(); |
174 | 0 | mIsMapped = !!aMappedSurface->mData; |
175 | 0 | bool isMapped = mIsMapped; |
176 | 0 | if (!mIsMapped) { |
177 | 0 | mChangeMutex.Unlock(); |
178 | 0 | } |
179 | 0 | return isMapped; |
180 | 0 | } |
181 | | |
182 | | void |
183 | | SourceSurfaceSkia::Unmap() |
184 | 0 | { |
185 | 0 | MOZ_ASSERT(mIsMapped); |
186 | 0 | mIsMapped = false; |
187 | 0 | mChangeMutex.Unlock(); |
188 | 0 | } |
189 | | |
190 | | void |
191 | | SourceSurfaceSkia::DrawTargetWillChange() |
192 | 0 | { |
193 | 0 | MutexAutoLock lock(mChangeMutex); |
194 | 0 | if (mDrawTarget) { |
195 | 0 | // Raster snapshots do not use Skia's internal copy-on-write mechanism, |
196 | 0 | // so we need to do an explicit copy here. |
197 | 0 | // GPU snapshots, for which peekPixels is false, will already be dealt |
198 | 0 | // with automatically via the internal copy-on-write mechanism, so we |
199 | 0 | // don't need to do anything for them here. |
200 | 0 | SkPixmap pixmap; |
201 | 0 | if (mImage->peekPixels(&pixmap)) { |
202 | 0 | mImage = ReadSkImage(mImage, pixmap.info(), pixmap.rowBytes()); |
203 | 0 | if (!mImage) { |
204 | 0 | gfxCriticalError() << "Failed copying Skia raster snapshot"; |
205 | 0 | } |
206 | 0 | } |
207 | 0 | mDrawTarget = nullptr; |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | } // namespace gfx |
212 | | } // namespace mozilla |