gfx/layers/client/ImageClient.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:d304165e05c3
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "ImageClient.h"
7 #include <stdint.h> // for uint32_t
8 #include "ImageContainer.h" // for Image, PlanarYCbCrImage, etc
9 #include "ImageTypes.h" // for ImageFormat::PLANAR_YCBCR, etc
10 #include "SharedTextureImage.h" // for SharedTextureImage::Data, etc
11 #include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat
12 #include "gfxPlatform.h" // for gfxPlatform
13 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
14 #include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef
15 #include "mozilla/gfx/BaseSize.h" // for BaseSize
16 #include "mozilla/gfx/Point.h" // for IntSize
17 #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc
18 #include "mozilla/layers/CompositableClient.h" // for CompositableClient
19 #include "mozilla/layers/CompositableForwarder.h"
20 #include "mozilla/layers/CompositorTypes.h" // for CompositableType, etc
21 #include "mozilla/layers/ISurfaceAllocator.h"
22 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
23 #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
24 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
25 #include "mozilla/layers/SharedRGBImage.h"
26 #include "mozilla/layers/TextureClient.h" // for TextureClient, etc
27 #include "mozilla/layers/TextureClientOGL.h" // for SharedTextureClientOGL
28 #include "mozilla/mozalloc.h" // for operator delete, etc
29 #include "nsAutoPtr.h" // for nsRefPtr
30 #include "nsCOMPtr.h" // for already_AddRefed
31 #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
32 #include "nsISupportsImpl.h" // for Image::Release, etc
33 #include "nsRect.h" // for nsIntRect
34 #include "mozilla/gfx/2D.h"
35 #ifdef MOZ_WIDGET_GONK
36 #include "GrallocImages.h"
37 #endif
38
39 using namespace mozilla::gfx;
40
41 namespace mozilla {
42 namespace layers {
43
44 /* static */ TemporaryRef<ImageClient>
45 ImageClient::CreateImageClient(CompositableType aCompositableHostType,
46 CompositableForwarder* aForwarder,
47 TextureFlags aFlags)
48 {
49 RefPtr<ImageClient> result = nullptr;
50 switch (aCompositableHostType) {
51 case COMPOSITABLE_IMAGE:
52 case BUFFER_IMAGE_SINGLE:
53 result = new ImageClientSingle(aForwarder, aFlags, COMPOSITABLE_IMAGE);
54 break;
55 case BUFFER_IMAGE_BUFFERED:
56 result = new ImageClientBuffered(aForwarder, aFlags, COMPOSITABLE_IMAGE);
57 break;
58 case BUFFER_BRIDGE:
59 result = new ImageClientBridge(aForwarder, aFlags);
60 break;
61 case BUFFER_UNKNOWN:
62 result = nullptr;
63 break;
64 default:
65 MOZ_CRASH("unhandled program type");
66 }
67
68 NS_ASSERTION(result, "Failed to create ImageClient");
69
70 return result.forget();
71 }
72
73 ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
74 TextureFlags aFlags,
75 CompositableType aType)
76 : ImageClient(aFwd, aFlags, aType)
77 {
78 }
79
80 ImageClientBuffered::ImageClientBuffered(CompositableForwarder* aFwd,
81 TextureFlags aFlags,
82 CompositableType aType)
83 : ImageClientSingle(aFwd, aFlags, aType)
84 {
85 }
86
87 TextureInfo ImageClientSingle::GetTextureInfo() const
88 {
89 return TextureInfo(COMPOSITABLE_IMAGE);
90 }
91
92 void
93 ImageClientSingle::FlushAllImages(bool aExceptFront)
94 {
95 if (!aExceptFront && mFrontBuffer) {
96 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
97 mFrontBuffer = nullptr;
98 }
99 }
100
101 void
102 ImageClientBuffered::FlushAllImages(bool aExceptFront)
103 {
104 if (!aExceptFront && mFrontBuffer) {
105 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
106 mFrontBuffer = nullptr;
107 }
108 if (mBackBuffer) {
109 GetForwarder()->RemoveTextureFromCompositable(this, mBackBuffer);
110 mBackBuffer = nullptr;
111 }
112 }
113
114 bool
115 ImageClientSingle::UpdateImage(ImageContainer* aContainer,
116 uint32_t aContentFlags)
117 {
118 bool isSwapped = false;
119 return UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
120 }
121
122 bool
123 ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
124 uint32_t aContentFlags, bool* aIsSwapped)
125 {
126 AutoLockImage autoLock(aContainer);
127 *aIsSwapped = false;
128
129 Image *image = autoLock.GetImage();
130 if (!image) {
131 return false;
132 }
133
134 if (mLastPaintedImageSerial == image->GetSerial()) {
135 return true;
136 }
137
138 if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient(this)) {
139 // fast path: no need to allocate and/or copy image data
140 RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient(this);
141
142
143 if (mFrontBuffer) {
144 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
145 }
146 mFrontBuffer = texture;
147 if (!AddTextureClient(texture)) {
148 mFrontBuffer = nullptr;
149 return false;
150 }
151 GetForwarder()->UpdatedTexture(this, texture, nullptr);
152 GetForwarder()->UseTexture(this, texture);
153 } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
154 PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
155 const PlanarYCbCrData* data = ycbcr->GetData();
156 if (!data) {
157 return false;
158 }
159
160 if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
161 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
162 mFrontBuffer = nullptr;
163 }
164
165 bool bufferCreated = false;
166 if (!mFrontBuffer) {
167 mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TEXTURE_FLAGS_DEFAULT);
168 gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
169 gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
170 if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) {
171 mFrontBuffer = nullptr;
172 return false;
173 }
174 bufferCreated = true;
175 }
176
177 if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
178 mFrontBuffer = nullptr;
179 return false;
180 }
181 bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data);
182 mFrontBuffer->Unlock();
183
184 if (bufferCreated) {
185 if (!AddTextureClient(mFrontBuffer)) {
186 mFrontBuffer = nullptr;
187 return false;
188 }
189 }
190
191 if (status) {
192 GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
193 GetForwarder()->UseTexture(this, mFrontBuffer);
194 } else {
195 MOZ_ASSERT(false);
196 return false;
197 }
198
199 } else if (image->GetFormat() == ImageFormat::SHARED_TEXTURE) {
200 SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image);
201 const SharedTextureImage::Data *data = sharedImage->GetData();
202 gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
203
204 if (mFrontBuffer) {
205 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
206 mFrontBuffer = nullptr;
207 }
208
209 RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags);
210 buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted);
211 mFrontBuffer = buffer;
212 if (!AddTextureClient(mFrontBuffer)) {
213 mFrontBuffer = nullptr;
214 return false;
215 }
216
217 GetForwarder()->UseTexture(this, mFrontBuffer);
218 } else {
219 RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
220 MOZ_ASSERT(surface);
221
222 gfx::IntSize size = image->GetSize();
223
224 if (mFrontBuffer &&
225 (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
226 GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
227 mFrontBuffer = nullptr;
228 }
229
230 bool bufferCreated = false;
231 if (!mFrontBuffer) {
232 gfxImageFormat format
233 = gfxPlatform::GetPlatform()->OptimalFormatForContent(gfx::ContentForFormat(surface->GetFormat()));
234 mFrontBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
235 mTextureFlags, gfx::BackendType::NONE, size);
236 MOZ_ASSERT(mFrontBuffer->CanExposeDrawTarget());
237 if (!mFrontBuffer->AllocateForSurface(size)) {
238 mFrontBuffer = nullptr;
239 return false;
240 }
241
242 bufferCreated = true;
243 }
244
245 if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
246 mFrontBuffer = nullptr;
247 return false;
248 }
249
250 {
251 // We must not keep a reference to the DrawTarget after it has been unlocked.
252 RefPtr<DrawTarget> dt = mFrontBuffer->GetAsDrawTarget();
253 MOZ_ASSERT(surface.get());
254 dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
255 }
256
257 mFrontBuffer->Unlock();
258
259 if (bufferCreated) {
260 if (!AddTextureClient(mFrontBuffer)) {
261 mFrontBuffer = nullptr;
262 return false;
263 }
264 }
265
266 GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
267 GetForwarder()->UseTexture(this, mFrontBuffer);
268 }
269
270 UpdatePictureRect(image->GetPictureRect());
271
272 mLastPaintedImageSerial = image->GetSerial();
273 aContainer->NotifyPaintedImage(image);
274 *aIsSwapped = true;
275 return true;
276 }
277
278 bool
279 ImageClientBuffered::UpdateImage(ImageContainer* aContainer,
280 uint32_t aContentFlags)
281 {
282 RefPtr<TextureClient> temp = mFrontBuffer;
283 mFrontBuffer = mBackBuffer;
284 mBackBuffer = temp;
285
286 bool isSwapped = false;
287 bool ret = ImageClientSingle::UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
288
289 if (!isSwapped) {
290 // If buffer swap did not happen at Host side, swap back the buffers.
291 RefPtr<TextureClient> temp = mFrontBuffer;
292 mFrontBuffer = mBackBuffer;
293 mBackBuffer = temp;
294 }
295 return ret;
296 }
297
298 bool
299 ImageClientSingle::AddTextureClient(TextureClient* aTexture)
300 {
301 MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
302 return CompositableClient::AddTextureClient(aTexture);
303 }
304
305 void
306 ImageClientSingle::OnDetach()
307 {
308 mFrontBuffer = nullptr;
309 }
310
311 void
312 ImageClientBuffered::OnDetach()
313 {
314 mFrontBuffer = nullptr;
315 mBackBuffer = nullptr;
316 }
317
318 ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
319 CompositableType aType)
320 : CompositableClient(aFwd, aFlags)
321 , mType(aType)
322 , mLastPaintedImageSerial(0)
323 {}
324
325 void
326 ImageClient::UpdatePictureRect(nsIntRect aRect)
327 {
328 if (mPictureRect == aRect) {
329 return;
330 }
331 mPictureRect = aRect;
332 MOZ_ASSERT(mForwarder);
333 GetForwarder()->UpdatePictureRect(this, aRect);
334 }
335
336 ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
337 TextureFlags aFlags)
338 : ImageClient(aFwd, aFlags, BUFFER_BRIDGE)
339 , mAsyncContainerID(0)
340 , mLayer(nullptr)
341 {
342 }
343
344 bool
345 ImageClientBridge::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
346 {
347 if (!GetForwarder() || !mLayer) {
348 return false;
349 }
350 if (mAsyncContainerID == aContainer->GetAsyncContainerID()) {
351 return true;
352 }
353 mAsyncContainerID = aContainer->GetAsyncContainerID();
354 static_cast<ShadowLayerForwarder*>(GetForwarder())->AttachAsyncCompositable(mAsyncContainerID, mLayer);
355 AutoLockImage autoLock(aContainer);
356 aContainer->NotifyPaintedImage(autoLock.GetImage());
357 Updated();
358 return true;
359 }
360
361 already_AddRefed<Image>
362 ImageClientSingle::CreateImage(ImageFormat aFormat)
363 {
364 nsRefPtr<Image> img;
365 switch (aFormat) {
366 case ImageFormat::PLANAR_YCBCR:
367 img = new SharedPlanarYCbCrImage(this);
368 return img.forget();
369 case ImageFormat::SHARED_RGB:
370 img = new SharedRGBImage(this);
371 return img.forget();
372 #ifdef MOZ_WIDGET_GONK
373 case ImageFormat::GRALLOC_PLANAR_YCBCR:
374 img = new GrallocImage();
375 return img.forget();
376 #endif
377 default:
378 return nullptr;
379 }
380 }
381
382 }
383 }

mercurial