gfx/layers/client/ImageClient.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial