Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/ipc/SharedRGBImage.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 "SharedRGBImage.h"
8
#include "ImageTypes.h"                 // for ImageFormat::SHARED_RGB, etc
9
#include "Shmem.h"                      // for Shmem
10
#include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat, etc
11
#include "gfxPlatform.h"                // for gfxPlatform, gfxImageFormat
12
#include "mozilla/gfx/Point.h"          // for IntSIze
13
#include "mozilla/layers/BufferTexture.h"
14
#include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator, etc
15
#include "mozilla/layers/ImageClient.h"  // for ImageClient
16
#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
17
#include "mozilla/layers/TextureClient.h"  // for BufferTextureClient, etc
18
#include "mozilla/layers/ImageBridgeChild.h"  // for ImageBridgeChild
19
#include "mozilla/mozalloc.h"           // for operator delete, etc
20
#include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
21
#include "nsISupportsImpl.h"            // for Image::AddRef, etc
22
#include "nsRect.h"                     // for mozilla::gfx::IntRect
23
24
// Just big enough for a 1080p RGBA32 frame
25
#define MAX_FRAME_SIZE (16 * 1024 * 1024)
26
27
namespace mozilla {
28
namespace layers {
29
30
already_AddRefed<Image>
31
CreateSharedRGBImage(ImageContainer *aImageContainer,
32
                     gfx::IntSize aSize,
33
                     gfxImageFormat aImageFormat)
34
0
{
35
0
  NS_ASSERTION(aImageFormat == gfx::SurfaceFormat::A8R8G8B8_UINT32 ||
36
0
               aImageFormat == gfx::SurfaceFormat::X8R8G8B8_UINT32 ||
37
0
               aImageFormat == gfx::SurfaceFormat::R5G6B5_UINT16,
38
0
               "RGB formats supported only");
39
0
40
0
  if (!aImageContainer) {
41
0
    NS_WARNING("No ImageContainer to allocate SharedRGBImage");
42
0
    return nullptr;
43
0
  }
44
0
45
0
  RefPtr<SharedRGBImage> rgbImage = aImageContainer->CreateSharedRGBImage();
46
0
  if (!rgbImage) {
47
0
    NS_WARNING("Failed to create SharedRGBImage");
48
0
    return nullptr;
49
0
  }
50
0
  if (!rgbImage->Allocate(aSize, gfx::ImageFormatToSurfaceFormat(aImageFormat))) {
51
0
    NS_WARNING("Failed to allocate a shared image");
52
0
    return nullptr;
53
0
  }
54
0
  return rgbImage.forget();
55
0
}
56
57
SharedRGBImage::SharedRGBImage(ImageClient* aCompositable)
58
: Image(nullptr, ImageFormat::SHARED_RGB)
59
, mCompositable(aCompositable)
60
0
{
61
0
  MOZ_COUNT_CTOR(SharedRGBImage);
62
0
}
63
64
SharedRGBImage::~SharedRGBImage()
65
0
{
66
0
  MOZ_COUNT_DTOR(SharedRGBImage);
67
0
}
68
69
bool
70
SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat)
71
0
{
72
0
  mSize = aSize;
73
0
  mTextureClient = mCompositable->CreateBufferTextureClient(aFormat, aSize,
74
0
                                                            gfx::BackendType::NONE,
75
0
                                                            TextureFlags::DEFAULT);
76
0
  return !!mTextureClient;
77
0
}
78
79
uint8_t*
80
SharedRGBImage::GetBuffer() const
81
0
{
82
0
  MappedTextureData mapped;
83
0
  if (mTextureClient && mTextureClient->BorrowMappedData(mapped)) {
84
0
    return mapped.data;
85
0
  }
86
0
  return 0;
87
0
}
88
89
gfx::IntSize
90
SharedRGBImage::GetSize() const
91
0
{
92
0
  return mSize;
93
0
}
94
95
TextureClient*
96
SharedRGBImage::GetTextureClient(KnowsCompositor* aForwarder)
97
0
{
98
0
  return mTextureClient.get();
99
0
}
100
101
static void
102
ReleaseTextureClient(void* aData)
103
0
{
104
0
  RELEASE_MANUALLY(static_cast<TextureClient*>(aData));
105
0
}
106
107
static gfx::UserDataKey sTextureClientKey;
108
109
already_AddRefed<gfx::SourceSurface>
110
SharedRGBImage::GetAsSourceSurface()
111
0
{
112
0
  NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
113
0
114
0
  if (mSourceSurface) {
115
0
    RefPtr<gfx::SourceSurface> surface(mSourceSurface);
116
0
    return surface.forget();
117
0
  }
118
0
119
0
  RefPtr<gfx::SourceSurface> surface;
120
0
  {
121
0
    // We are 'borrowing' the DrawTarget and retaining a permanent reference to
122
0
    // the underlying data (via the surface). It is in this instance since we
123
0
    // know that the TextureClient is always wrapping a BufferTextureData and
124
0
    // therefore it won't go away underneath us.
125
0
    BufferTextureData* decoded_buffer =
126
0
      mTextureClient->GetInternalData()->AsBufferTextureData();
127
0
    RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget();
128
0
129
0
    if (!drawTarget) {
130
0
      return nullptr;
131
0
    }
132
0
133
0
    surface = drawTarget->Snapshot();
134
0
    if (!surface) {
135
0
      return nullptr;
136
0
    }
137
0
138
0
    // The surface may outlive the owning TextureClient. So, we need to ensure
139
0
    // that the surface keeps the TextureClient alive via a reference held in
140
0
    // user data. The TextureClient's DrawTarget only has a weak reference to the
141
0
    // surface, so we won't create any cycles by just referencing the TextureClient.
142
0
    if (!surface->GetUserData(&sTextureClientKey)) {
143
0
      surface->AddUserData(&sTextureClientKey, mTextureClient, ReleaseTextureClient);
144
0
      ADDREF_MANUALLY(mTextureClient);
145
0
    }
146
0
  }
147
0
148
0
  mSourceSurface = surface;
149
0
  return surface.forget();
150
0
}
151
152
} // namespace layers
153
} // namespace mozilla