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 +}