gfx/layers/client/ImageClient.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/client/ImageClient.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,383 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "ImageClient.h"
    1.10 +#include <stdint.h>                     // for uint32_t
    1.11 +#include "ImageContainer.h"             // for Image, PlanarYCbCrImage, etc
    1.12 +#include "ImageTypes.h"                 // for ImageFormat::PLANAR_YCBCR, etc
    1.13 +#include "SharedTextureImage.h"         // for SharedTextureImage::Data, etc
    1.14 +#include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
    1.15 +#include "gfxPlatform.h"                // for gfxPlatform
    1.16 +#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    1.17 +#include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
    1.18 +#include "mozilla/gfx/BaseSize.h"       // for BaseSize
    1.19 +#include "mozilla/gfx/Point.h"          // for IntSize
    1.20 +#include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
    1.21 +#include "mozilla/layers/CompositableClient.h"  // for CompositableClient
    1.22 +#include "mozilla/layers/CompositableForwarder.h"
    1.23 +#include "mozilla/layers/CompositorTypes.h"  // for CompositableType, etc
    1.24 +#include "mozilla/layers/ISurfaceAllocator.h"
    1.25 +#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
    1.26 +#include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
    1.27 +#include "mozilla/layers/SharedPlanarYCbCrImage.h"
    1.28 +#include "mozilla/layers/SharedRGBImage.h"
    1.29 +#include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
    1.30 +#include "mozilla/layers/TextureClientOGL.h"  // for SharedTextureClientOGL
    1.31 +#include "mozilla/mozalloc.h"           // for operator delete, etc
    1.32 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.33 +#include "nsCOMPtr.h"                   // for already_AddRefed
    1.34 +#include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
    1.35 +#include "nsISupportsImpl.h"            // for Image::Release, etc
    1.36 +#include "nsRect.h"                     // for nsIntRect
    1.37 +#include "mozilla/gfx/2D.h"
    1.38 +#ifdef MOZ_WIDGET_GONK
    1.39 +#include "GrallocImages.h"
    1.40 +#endif
    1.41 +
    1.42 +using namespace mozilla::gfx;
    1.43 +
    1.44 +namespace mozilla {
    1.45 +namespace layers {
    1.46 +
    1.47 +/* static */ TemporaryRef<ImageClient>
    1.48 +ImageClient::CreateImageClient(CompositableType aCompositableHostType,
    1.49 +                               CompositableForwarder* aForwarder,
    1.50 +                               TextureFlags aFlags)
    1.51 +{
    1.52 +  RefPtr<ImageClient> result = nullptr;
    1.53 +  switch (aCompositableHostType) {
    1.54 +  case COMPOSITABLE_IMAGE:
    1.55 +  case BUFFER_IMAGE_SINGLE:
    1.56 +    result = new ImageClientSingle(aForwarder, aFlags, COMPOSITABLE_IMAGE);
    1.57 +    break;
    1.58 +  case BUFFER_IMAGE_BUFFERED:
    1.59 +    result = new ImageClientBuffered(aForwarder, aFlags, COMPOSITABLE_IMAGE);
    1.60 +    break;
    1.61 +  case BUFFER_BRIDGE:
    1.62 +    result = new ImageClientBridge(aForwarder, aFlags);
    1.63 +    break;
    1.64 +  case BUFFER_UNKNOWN:
    1.65 +    result = nullptr;
    1.66 +    break;
    1.67 +  default:
    1.68 +    MOZ_CRASH("unhandled program type");
    1.69 +  }
    1.70 +
    1.71 +  NS_ASSERTION(result, "Failed to create ImageClient");
    1.72 +
    1.73 +  return result.forget();
    1.74 +}
    1.75 +
    1.76 +ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
    1.77 +                                     TextureFlags aFlags,
    1.78 +                                     CompositableType aType)
    1.79 +  : ImageClient(aFwd, aFlags, aType)
    1.80 +{
    1.81 +}
    1.82 +
    1.83 +ImageClientBuffered::ImageClientBuffered(CompositableForwarder* aFwd,
    1.84 +                                         TextureFlags aFlags,
    1.85 +                                         CompositableType aType)
    1.86 +  : ImageClientSingle(aFwd, aFlags, aType)
    1.87 +{
    1.88 +}
    1.89 +
    1.90 +TextureInfo ImageClientSingle::GetTextureInfo() const
    1.91 +{
    1.92 +  return TextureInfo(COMPOSITABLE_IMAGE);
    1.93 +}
    1.94 +
    1.95 +void
    1.96 +ImageClientSingle::FlushAllImages(bool aExceptFront)
    1.97 +{
    1.98 +  if (!aExceptFront && mFrontBuffer) {
    1.99 +    GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.100 +    mFrontBuffer = nullptr;
   1.101 +  }
   1.102 +}
   1.103 +
   1.104 +void
   1.105 +ImageClientBuffered::FlushAllImages(bool aExceptFront)
   1.106 +{
   1.107 +  if (!aExceptFront && mFrontBuffer) {
   1.108 +    GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.109 +    mFrontBuffer = nullptr;
   1.110 +  }
   1.111 +  if (mBackBuffer) {
   1.112 +    GetForwarder()->RemoveTextureFromCompositable(this, mBackBuffer);
   1.113 +    mBackBuffer = nullptr;
   1.114 +  }
   1.115 +}
   1.116 +
   1.117 +bool
   1.118 +ImageClientSingle::UpdateImage(ImageContainer* aContainer,
   1.119 +                               uint32_t aContentFlags)
   1.120 +{
   1.121 +  bool isSwapped = false;
   1.122 +  return UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
   1.123 +}
   1.124 +
   1.125 +bool
   1.126 +ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
   1.127 +                                       uint32_t aContentFlags, bool* aIsSwapped)
   1.128 +{
   1.129 +  AutoLockImage autoLock(aContainer);
   1.130 +  *aIsSwapped = false;
   1.131 +
   1.132 +  Image *image = autoLock.GetImage();
   1.133 +  if (!image) {
   1.134 +    return false;
   1.135 +  }
   1.136 +
   1.137 +  if (mLastPaintedImageSerial == image->GetSerial()) {
   1.138 +    return true;
   1.139 +  }
   1.140 +
   1.141 +  if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient(this)) {
   1.142 +    // fast path: no need to allocate and/or copy image data
   1.143 +    RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient(this);
   1.144 +
   1.145 +
   1.146 +    if (mFrontBuffer) {
   1.147 +      GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.148 +    }
   1.149 +    mFrontBuffer = texture;
   1.150 +    if (!AddTextureClient(texture)) {
   1.151 +      mFrontBuffer = nullptr;
   1.152 +      return false;
   1.153 +    }
   1.154 +    GetForwarder()->UpdatedTexture(this, texture, nullptr);
   1.155 +    GetForwarder()->UseTexture(this, texture);
   1.156 +  } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
   1.157 +    PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
   1.158 +    const PlanarYCbCrData* data = ycbcr->GetData();
   1.159 +    if (!data) {
   1.160 +      return false;
   1.161 +    }
   1.162 +
   1.163 +    if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
   1.164 +      GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.165 +      mFrontBuffer = nullptr;
   1.166 +    }
   1.167 +
   1.168 +    bool bufferCreated = false;
   1.169 +    if (!mFrontBuffer) {
   1.170 +      mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TEXTURE_FLAGS_DEFAULT);
   1.171 +      gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
   1.172 +      gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
   1.173 +      if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) {
   1.174 +        mFrontBuffer = nullptr;
   1.175 +        return false;
   1.176 +      }
   1.177 +      bufferCreated = true;
   1.178 +    }
   1.179 +
   1.180 +    if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
   1.181 +      mFrontBuffer = nullptr;
   1.182 +      return false;
   1.183 +    }
   1.184 +    bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data);
   1.185 +    mFrontBuffer->Unlock();
   1.186 +
   1.187 +    if (bufferCreated) {
   1.188 +      if (!AddTextureClient(mFrontBuffer)) {
   1.189 +        mFrontBuffer = nullptr;
   1.190 +        return false;
   1.191 +      }
   1.192 +    }
   1.193 +
   1.194 +    if (status) {
   1.195 +      GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
   1.196 +      GetForwarder()->UseTexture(this, mFrontBuffer);
   1.197 +    } else {
   1.198 +      MOZ_ASSERT(false);
   1.199 +      return false;
   1.200 +    }
   1.201 +
   1.202 +  } else if (image->GetFormat() == ImageFormat::SHARED_TEXTURE) {
   1.203 +    SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image);
   1.204 +    const SharedTextureImage::Data *data = sharedImage->GetData();
   1.205 +    gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
   1.206 +
   1.207 +    if (mFrontBuffer) {
   1.208 +      GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.209 +      mFrontBuffer = nullptr;
   1.210 +    }
   1.211 +
   1.212 +    RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags);
   1.213 +    buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted);
   1.214 +    mFrontBuffer = buffer;
   1.215 +    if (!AddTextureClient(mFrontBuffer)) {
   1.216 +      mFrontBuffer = nullptr;
   1.217 +      return false;
   1.218 +    }
   1.219 +
   1.220 +    GetForwarder()->UseTexture(this, mFrontBuffer);
   1.221 +  } else {
   1.222 +    RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
   1.223 +    MOZ_ASSERT(surface);
   1.224 +
   1.225 +    gfx::IntSize size = image->GetSize();
   1.226 +
   1.227 +    if (mFrontBuffer &&
   1.228 +        (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
   1.229 +      GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
   1.230 +      mFrontBuffer = nullptr;
   1.231 +    }
   1.232 +
   1.233 +    bool bufferCreated = false;
   1.234 +    if (!mFrontBuffer) {
   1.235 +      gfxImageFormat format
   1.236 +        = gfxPlatform::GetPlatform()->OptimalFormatForContent(gfx::ContentForFormat(surface->GetFormat()));
   1.237 +      mFrontBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
   1.238 +                                                   mTextureFlags, gfx::BackendType::NONE, size);
   1.239 +      MOZ_ASSERT(mFrontBuffer->CanExposeDrawTarget());
   1.240 +      if (!mFrontBuffer->AllocateForSurface(size)) {
   1.241 +        mFrontBuffer = nullptr;
   1.242 +        return false;
   1.243 +      }
   1.244 +
   1.245 +      bufferCreated = true;
   1.246 +    }
   1.247 +
   1.248 +    if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
   1.249 +      mFrontBuffer = nullptr;
   1.250 +      return false;
   1.251 +    }
   1.252 +
   1.253 +    {
   1.254 +      // We must not keep a reference to the DrawTarget after it has been unlocked.
   1.255 +      RefPtr<DrawTarget> dt = mFrontBuffer->GetAsDrawTarget();
   1.256 +      MOZ_ASSERT(surface.get());
   1.257 +      dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
   1.258 +    }
   1.259 +
   1.260 +    mFrontBuffer->Unlock();
   1.261 +
   1.262 +    if (bufferCreated) {
   1.263 +      if (!AddTextureClient(mFrontBuffer)) {
   1.264 +        mFrontBuffer = nullptr;
   1.265 +        return false;
   1.266 +      }
   1.267 +    }
   1.268 +
   1.269 +    GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
   1.270 +    GetForwarder()->UseTexture(this, mFrontBuffer);
   1.271 +  }
   1.272 +
   1.273 +  UpdatePictureRect(image->GetPictureRect());
   1.274 +
   1.275 +  mLastPaintedImageSerial = image->GetSerial();
   1.276 +  aContainer->NotifyPaintedImage(image);
   1.277 +  *aIsSwapped = true;
   1.278 +  return true;
   1.279 +}
   1.280 +
   1.281 +bool
   1.282 +ImageClientBuffered::UpdateImage(ImageContainer* aContainer,
   1.283 +                                 uint32_t aContentFlags)
   1.284 +{
   1.285 +  RefPtr<TextureClient> temp = mFrontBuffer;
   1.286 +  mFrontBuffer = mBackBuffer;
   1.287 +  mBackBuffer = temp;
   1.288 +
   1.289 +  bool isSwapped = false;
   1.290 +  bool ret = ImageClientSingle::UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
   1.291 +
   1.292 +  if (!isSwapped) {
   1.293 +    // If buffer swap did not happen at Host side, swap back the buffers.
   1.294 +    RefPtr<TextureClient> temp = mFrontBuffer;
   1.295 +    mFrontBuffer = mBackBuffer;
   1.296 +    mBackBuffer = temp;
   1.297 +  }
   1.298 +  return ret;
   1.299 +}
   1.300 +
   1.301 +bool
   1.302 +ImageClientSingle::AddTextureClient(TextureClient* aTexture)
   1.303 +{
   1.304 +  MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
   1.305 +  return CompositableClient::AddTextureClient(aTexture);
   1.306 +}
   1.307 +
   1.308 +void
   1.309 +ImageClientSingle::OnDetach()
   1.310 +{
   1.311 +  mFrontBuffer = nullptr;
   1.312 +}
   1.313 +
   1.314 +void
   1.315 +ImageClientBuffered::OnDetach()
   1.316 +{
   1.317 +  mFrontBuffer = nullptr;
   1.318 +  mBackBuffer = nullptr;
   1.319 +}
   1.320 +
   1.321 +ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
   1.322 +                         CompositableType aType)
   1.323 +: CompositableClient(aFwd, aFlags)
   1.324 +, mType(aType)
   1.325 +, mLastPaintedImageSerial(0)
   1.326 +{}
   1.327 +
   1.328 +void
   1.329 +ImageClient::UpdatePictureRect(nsIntRect aRect)
   1.330 +{
   1.331 +  if (mPictureRect == aRect) {
   1.332 +    return;
   1.333 +  }
   1.334 +  mPictureRect = aRect;
   1.335 +  MOZ_ASSERT(mForwarder);
   1.336 +  GetForwarder()->UpdatePictureRect(this, aRect);
   1.337 +}
   1.338 +
   1.339 +ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
   1.340 +                                     TextureFlags aFlags)
   1.341 +: ImageClient(aFwd, aFlags, BUFFER_BRIDGE)
   1.342 +, mAsyncContainerID(0)
   1.343 +, mLayer(nullptr)
   1.344 +{
   1.345 +}
   1.346 +
   1.347 +bool
   1.348 +ImageClientBridge::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
   1.349 +{
   1.350 +  if (!GetForwarder() || !mLayer) {
   1.351 +    return false;
   1.352 +  }
   1.353 +  if (mAsyncContainerID == aContainer->GetAsyncContainerID()) {
   1.354 +    return true;
   1.355 +  }
   1.356 +  mAsyncContainerID = aContainer->GetAsyncContainerID();
   1.357 +  static_cast<ShadowLayerForwarder*>(GetForwarder())->AttachAsyncCompositable(mAsyncContainerID, mLayer);
   1.358 +  AutoLockImage autoLock(aContainer);
   1.359 +  aContainer->NotifyPaintedImage(autoLock.GetImage());
   1.360 +  Updated();
   1.361 +  return true;
   1.362 +}
   1.363 +
   1.364 +already_AddRefed<Image>
   1.365 +ImageClientSingle::CreateImage(ImageFormat aFormat)
   1.366 +{
   1.367 +  nsRefPtr<Image> img;
   1.368 +  switch (aFormat) {
   1.369 +    case ImageFormat::PLANAR_YCBCR:
   1.370 +      img = new SharedPlanarYCbCrImage(this);
   1.371 +      return img.forget();
   1.372 +    case ImageFormat::SHARED_RGB:
   1.373 +      img = new SharedRGBImage(this);
   1.374 +      return img.forget();
   1.375 +#ifdef MOZ_WIDGET_GONK
   1.376 +    case ImageFormat::GRALLOC_PLANAR_YCBCR:
   1.377 +      img = new GrallocImage();
   1.378 +      return img.forget();
   1.379 +#endif
   1.380 +    default:
   1.381 +      return nullptr;
   1.382 +  }
   1.383 +}
   1.384 +
   1.385 +}
   1.386 +}

mercurial