Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/client/ImageClient.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
#include "ImageClient.h"
8
9
#include <stdint.h>                     // for uint32_t
10
11
#include "ClientLayerManager.h"         // for ClientLayer
12
#include "ImageContainer.h"             // for Image, PlanarYCbCrImage, etc
13
#include "ImageTypes.h"                 // for ImageFormat::PLANAR_YCBCR, etc
14
#include "GLImages.h"                   // for SurfaceTextureImage::Data, etc
15
#include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
16
#include "gfxPlatform.h"                // for gfxPlatform
17
#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
18
#include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
19
#include "mozilla/gfx/2D.h"
20
#include "mozilla/gfx/BaseSize.h"       // for BaseSize
21
#include "mozilla/gfx/Point.h"          // for IntSize
22
#include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
23
#include "mozilla/layers/CompositableClient.h"  // for CompositableClient
24
#include "mozilla/layers/CompositableForwarder.h"
25
#include "mozilla/layers/CompositorTypes.h"  // for CompositableType, etc
26
#include "mozilla/layers/ISurfaceAllocator.h"
27
#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
28
#include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
29
#include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
30
#include "mozilla/layers/TextureClientOGL.h"  // for SurfaceTextureClient
31
#include "mozilla/mozalloc.h"           // for operator delete, etc
32
#include "nsCOMPtr.h"                   // for already_AddRefed
33
#include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
34
#include "nsISupportsImpl.h"            // for Image::Release, etc
35
#include "nsRect.h"                     // for mozilla::gfx::IntRect
36
37
namespace mozilla {
38
namespace layers {
39
40
using namespace mozilla::gfx;
41
42
/* static */ already_AddRefed<ImageClient>
43
ImageClient::CreateImageClient(CompositableType aCompositableHostType,
44
                               CompositableForwarder* aForwarder,
45
                               TextureFlags aFlags)
46
0
{
47
0
  RefPtr<ImageClient> result = nullptr;
48
0
  switch (aCompositableHostType) {
49
0
  case CompositableType::IMAGE:
50
0
    result = new ImageClientSingle(aForwarder, aFlags, CompositableType::IMAGE);
51
0
    break;
52
0
  case CompositableType::IMAGE_BRIDGE:
53
0
    result = new ImageClientBridge(aForwarder, aFlags);
54
0
    break;
55
0
  case CompositableType::UNKNOWN:
56
0
    result = nullptr;
57
0
    break;
58
0
  default:
59
0
    MOZ_CRASH("GFX: unhandled program type image");
60
0
  }
61
0
62
0
  NS_ASSERTION(result, "Failed to create ImageClient");
63
0
64
0
  return result.forget();
65
0
}
66
67
void
68
ImageClient::RemoveTexture(TextureClient* aTexture)
69
0
{
70
0
  GetForwarder()->RemoveTextureFromCompositable(this, aTexture);
71
0
}
72
73
ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
74
                                     TextureFlags aFlags,
75
                                     CompositableType aType)
76
  : ImageClient(aFwd, aFlags, aType)
77
0
{
78
0
}
79
80
TextureInfo ImageClientSingle::GetTextureInfo() const
81
0
{
82
0
  return TextureInfo(CompositableType::IMAGE);
83
0
}
84
85
void
86
ImageClientSingle::FlushAllImages()
87
0
{
88
0
  for (auto& b : mBuffers) {
89
0
    RemoveTexture(b.mTextureClient);
90
0
  }
91
0
  mBuffers.Clear();
92
0
}
93
94
/* static */ already_AddRefed<TextureClient>
95
ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwarder)
96
0
{
97
0
  RefPtr<TextureClient> texture;
98
0
  if (aImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
99
0
    PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(aImage);
100
0
    const PlanarYCbCrData* data = ycbcr->GetData();
101
0
    if (!data) {
102
0
      return nullptr;
103
0
    }
104
0
    texture = TextureClient::CreateForYCbCr(aForwarder,
105
0
                                            data->mYSize, data->mYStride,
106
0
                                            data->mCbCrSize, data->mCbCrStride,
107
0
                                            data->mStereoMode,
108
0
                                            data->mYUVColorSpace,
109
0
                                            data->mBitDepth,
110
0
                                            TextureFlags::DEFAULT);
111
0
    if (!texture) {
112
0
      return nullptr;
113
0
    }
114
0
115
0
    TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
116
0
    if (!autoLock.Succeeded()) {
117
0
      return nullptr;
118
0
    }
119
0
120
0
    bool status = UpdateYCbCrTextureClient(texture, *data);
121
0
    MOZ_ASSERT(status);
122
0
    if (!status) {
123
0
      return nullptr;
124
0
    }
125
#ifdef MOZ_WIDGET_ANDROID
126
  } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
127
    gfx::IntSize size = aImage->GetSize();
128
    SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
129
    texture = AndroidSurfaceTextureData::CreateTextureClient(
130
      typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
131
      aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
132
#endif
133
0
  } else {
134
0
    RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
135
0
    MOZ_ASSERT(surface);
136
0
    texture = TextureClient::CreateForDrawing(aForwarder, surface->GetFormat(), aImage->GetSize(),
137
0
                                              BackendSelector::Content, TextureFlags::DEFAULT);
138
0
    if (!texture) {
139
0
      return nullptr;
140
0
    }
141
0
142
0
    MOZ_ASSERT(texture->CanExposeDrawTarget());
143
0
144
0
    if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
145
0
      return nullptr;
146
0
    }
147
0
148
0
    {
149
0
      // We must not keep a reference to the DrawTarget after it has been unlocked.
150
0
      DrawTarget* dt = texture->BorrowDrawTarget();
151
0
      if (!dt) {
152
0
        gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
153
0
        return nullptr;
154
0
      }
155
0
      MOZ_ASSERT(surface.get());
156
0
      dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
157
0
    }
158
0
159
0
    texture->Unlock();
160
0
  }
161
0
  return texture.forget();
162
0
}
163
164
bool
165
ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
166
0
{
167
0
  AutoTArray<ImageContainer::OwningImage,4> images;
168
0
  uint32_t generationCounter;
169
0
  aContainer->GetCurrentImages(&images, &generationCounter);
170
0
171
0
  if (mLastUpdateGenerationCounter == generationCounter) {
172
0
    return true;
173
0
  }
174
0
  mLastUpdateGenerationCounter = generationCounter;
175
0
176
0
  for (int32_t i = images.Length() - 1; i >= 0; --i) {
177
0
    if (!images[i].mImage->IsValid()) {
178
0
      // Don't try to update to an invalid image.
179
0
      images.RemoveElementAt(i);
180
0
    }
181
0
  }
182
0
  if (images.IsEmpty()) {
183
0
    // This can happen if a ClearAllImages raced with SetCurrentImages from
184
0
    // another thread and ClearImagesFromImageBridge ran after the
185
0
    // SetCurrentImages call but before UpdateImageClientNow.
186
0
    // This can also happen if all images in the list are invalid.
187
0
    // We return true because the caller would attempt to recreate the
188
0
    // ImageClient otherwise, and that isn't going to help.
189
0
    for (auto& b : mBuffers) {
190
0
      RemoveTexture(b.mTextureClient);
191
0
    }
192
0
    mBuffers.Clear();
193
0
    return true;
194
0
  }
195
0
196
0
  nsTArray<Buffer> newBuffers;
197
0
  AutoTArray<CompositableForwarder::TimedTextureClient,4> textures;
198
0
199
0
  for (auto& img : images) {
200
0
    Image* image = img.mImage;
201
0
202
0
    RefPtr<TextureClient> texture = image->GetTextureClient(GetForwarder());
203
0
    const bool hasTextureClient = !!texture;
204
0
205
0
    for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
206
0
      if (mBuffers[i].mImageSerial == image->GetSerial()) {
207
0
        if (hasTextureClient) {
208
0
          MOZ_ASSERT(image->GetTextureClient(GetForwarder()) == mBuffers[i].mTextureClient);
209
0
        } else {
210
0
          texture = mBuffers[i].mTextureClient;
211
0
        }
212
0
        // Remove this element from mBuffers so mBuffers only contains
213
0
        // images that aren't present in 'images'
214
0
        mBuffers.RemoveElementAt(i);
215
0
      }
216
0
    }
217
0
218
0
    if (!texture) {
219
0
      // Slow path, we should not be hitting it very often and if we do it means
220
0
      // we are using an Image class that is not backed by textureClient and we
221
0
      // should fix it.
222
0
      texture = CreateTextureClientForImage(image, GetForwarder());
223
0
    }
224
0
225
0
    if (!texture) {
226
0
      return false;
227
0
    }
228
0
229
0
    // We check if the texture's allocator is still open, since in between media
230
0
    // decoding a frame and adding it to the compositable, we could have
231
0
    // restarted the GPU process.
232
0
    if (!texture->GetAllocator()->IPCOpen()) {
233
0
      continue;
234
0
    }
235
0
    if (!AddTextureClient(texture)) {
236
0
      return false;
237
0
    }
238
0
239
0
    CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
240
0
    t->mTextureClient = texture;
241
0
    t->mTimeStamp = img.mTimeStamp;
242
0
    t->mPictureRect = image->GetPictureRect();
243
0
    t->mFrameID = img.mFrameID;
244
0
    t->mProducerID = img.mProducerID;
245
0
246
0
    Buffer* newBuf = newBuffers.AppendElement();
247
0
    newBuf->mImageSerial = image->GetSerial();
248
0
    newBuf->mTextureClient = texture;
249
0
250
0
    texture->SyncWithObject(GetForwarder()->GetSyncObject());
251
0
  }
252
0
253
0
  GetForwarder()->UseTextures(this, textures);
254
0
255
0
  for (auto& b : mBuffers) {
256
0
    RemoveTexture(b.mTextureClient);
257
0
  }
258
0
  mBuffers.SwapElements(newBuffers);
259
0
260
0
  return true;
261
0
}
262
263
RefPtr<TextureClient>
264
ImageClientSingle::GetForwardedTexture()
265
0
{
266
0
  if (mBuffers.Length() == 0) {
267
0
    return nullptr;
268
0
  }
269
0
  return mBuffers[0].mTextureClient;
270
0
}
271
272
bool
273
ImageClientSingle::AddTextureClient(TextureClient* aTexture)
274
0
{
275
0
  MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
276
0
  return CompositableClient::AddTextureClient(aTexture);
277
0
}
278
279
void
280
ImageClientSingle::OnDetach()
281
0
{
282
0
  mBuffers.Clear();
283
0
}
284
285
ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
286
                         CompositableType aType)
287
: CompositableClient(aFwd, aFlags)
288
, mLayer(nullptr)
289
, mType(aType)
290
, mLastUpdateGenerationCounter(0)
291
0
{}
292
293
ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
294
                                     TextureFlags aFlags)
295
: ImageClient(aFwd, aFlags, CompositableType::IMAGE_BRIDGE)
296
0
{
297
0
}
298
299
bool
300
ImageClientBridge::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
301
0
{
302
0
  if (!GetForwarder() || !mLayer) {
303
0
    return false;
304
0
  }
305
0
  if (mAsyncContainerHandle == aContainer->GetAsyncContainerHandle()) {
306
0
    return true;
307
0
  }
308
0
309
0
  mAsyncContainerHandle = aContainer->GetAsyncContainerHandle();
310
0
  if (!mAsyncContainerHandle) {
311
0
    // If we couldn't contact a working ImageBridgeParent, just return.
312
0
    return true;
313
0
  }
314
0
315
0
  static_cast<ShadowLayerForwarder*>(GetForwarder())->AttachAsyncCompositable(mAsyncContainerHandle, mLayer);
316
0
  return true;
317
0
}
318
319
} // namespace layers
320
} // namespace mozilla