1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/ContentClient.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,476 @@ 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 +#ifndef MOZILLA_GFX_CONTENTCLIENT_H 1.10 +#define MOZILLA_GFX_CONTENTCLIENT_H 1.11 + 1.12 +#include <stdint.h> // for uint32_t 1.13 +#include "RotatedBuffer.h" // for RotatedContentBuffer, etc 1.14 +#include "gfxTypes.h" 1.15 +#include "gfxPlatform.h" // for gfxPlatform 1.16 +#include "mozilla/Assertions.h" // for MOZ_CRASH 1.17 +#include "mozilla/Attributes.h" // for MOZ_OVERRIDE 1.18 +#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef 1.19 +#include "mozilla/gfx/Point.h" // for IntSize 1.20 +#include "mozilla/layers/CompositableClient.h" // for CompositableClient 1.21 +#include "mozilla/layers/CompositableForwarder.h" 1.22 +#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc 1.23 +#include "mozilla/layers/ISurfaceAllocator.h" 1.24 +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor 1.25 +#include "mozilla/layers/TextureClient.h" // for TextureClient 1.26 +#include "mozilla/mozalloc.h" // for operator delete 1.27 +#include "nsCOMPtr.h" // for already_AddRefed 1.28 +#include "nsPoint.h" // for nsIntPoint 1.29 +#include "nsRect.h" // for nsIntRect 1.30 +#include "nsRegion.h" // for nsIntRegion 1.31 +#include "nsTArray.h" // for nsTArray 1.32 + 1.33 +class gfxContext; 1.34 + 1.35 +namespace mozilla { 1.36 +namespace gfx { 1.37 +class DrawTarget; 1.38 +} 1.39 + 1.40 +namespace layers { 1.41 + 1.42 +class BasicLayerManager; 1.43 +class ThebesLayer; 1.44 + 1.45 +/** 1.46 + * A compositable client for Thebes layers. These are different to Image/Canvas 1.47 + * clients due to sending a valid region across IPC and because we do a lot more 1.48 + * optimisation work, encapsualted in RotatedContentBuffers. 1.49 + * 1.50 + * We use content clients for OMTC and non-OMTC, basic rendering so that 1.51 + * BasicThebesLayer has only one interface to deal with. We support single and 1.52 + * double buffered flavours. For tiled layers, we do not use a ContentClient 1.53 + * although we do have a ContentHost, and we do use texture clients and texture 1.54 + * hosts. 1.55 + * 1.56 + * The interface presented by ContentClient is used by the BasicThebesLayer 1.57 + * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer 1.58 + * which is different (the OMTC one does a little more). The 'buffer' in the 1.59 + * names of a lot of these method is actually the TextureClient. But, 'buffer' 1.60 + * for the RotatedContentBuffer (as in SetBuffer) means a gfxSurface. See the 1.61 + * comments for SetBuffer and SetBufferProvider in RotatedContentBuffer. To keep 1.62 + * these mapped buffers alive, we store a pointer in mOldTextures if the 1.63 + * RotatedContentBuffer's surface is not the one from our texture client, once we 1.64 + * are done painting we unmap the surface/texture client and don't need to keep 1.65 + * it alive anymore, so we clear mOldTextures. 1.66 + * 1.67 + * The sequence for painting is: call BeginPaint on the content client; 1.68 + * call BeginPaintBuffer on the content client. That will initialise the buffer 1.69 + * for painting, by calling RotatedContentBuffer::BeginPaint (usually) which 1.70 + * will call back to ContentClient::FinalizeFrame to finalize update of the 1.71 + * buffers before drawing (i.e., it finalizes the previous frame). Then call 1.72 + * BorrowDrawTargetForPainting to get a DrawTarget to paint into. Then paint. 1.73 + * Then return that DrawTarget using ReturnDrawTarget. 1.74 + * Call EndPaint on the content client; 1.75 + * 1.76 + * SwapBuffers is called in response to the transaction reply from the compositor. 1.77 + */ 1.78 +class ContentClient : public CompositableClient 1.79 +{ 1.80 +public: 1.81 + /** 1.82 + * Creates, configures, and returns a new content client. If necessary, a 1.83 + * message will be sent to the compositor to create a corresponding content 1.84 + * host. 1.85 + */ 1.86 + static TemporaryRef<ContentClient> CreateContentClient(CompositableForwarder* aFwd); 1.87 + 1.88 + ContentClient(CompositableForwarder* aForwarder) 1.89 + : CompositableClient(aForwarder) 1.90 + {} 1.91 + virtual ~ContentClient() 1.92 + {} 1.93 + 1.94 + 1.95 + virtual void Clear() = 0; 1.96 + virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer, 1.97 + uint32_t aFlags) = 0; 1.98 + virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const RotatedContentBuffer::PaintState& aPaintState, 1.99 + RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0; 1.100 + virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0; 1.101 + 1.102 + // Called as part of the layers transation reply. Conveys data about our 1.103 + // buffer(s) from the compositor. If appropriate we should swap references 1.104 + // to our buffers. 1.105 + virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {} 1.106 + 1.107 + // call before and after painting into this content client 1.108 + virtual void BeginPaint() {} 1.109 + virtual void EndPaint(); 1.110 +}; 1.111 + 1.112 +/** 1.113 + * A ContentClient for use with OMTC. 1.114 + */ 1.115 +class ContentClientRemote : public ContentClient 1.116 +{ 1.117 +public: 1.118 + ContentClientRemote(CompositableForwarder* aForwarder) 1.119 + : ContentClient(aForwarder) 1.120 + {} 1.121 + 1.122 + virtual void Updated(const nsIntRegion& aRegionToDraw, 1.123 + const nsIntRegion& aVisibleRegion, 1.124 + bool aDidSelfCopy) = 0; 1.125 +}; 1.126 + 1.127 +// thin wrapper around RotatedContentBuffer, for on-mtc 1.128 +class ContentClientBasic : public ContentClient 1.129 + , protected RotatedContentBuffer 1.130 +{ 1.131 +public: 1.132 + ContentClientBasic(); 1.133 + 1.134 + typedef RotatedContentBuffer::PaintState PaintState; 1.135 + typedef RotatedContentBuffer::ContentType ContentType; 1.136 + 1.137 + virtual void Clear() { RotatedContentBuffer::Clear(); } 1.138 + virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, 1.139 + uint32_t aFlags) MOZ_OVERRIDE 1.140 + { 1.141 + return RotatedContentBuffer::BeginPaint(aLayer, aFlags); 1.142 + } 1.143 + virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, 1.144 + RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE 1.145 + { 1.146 + return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter); 1.147 + } 1.148 + virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE 1.149 + { 1.150 + BorrowDrawTarget::ReturnDrawTarget(aReturned); 1.151 + } 1.152 + 1.153 + void DrawTo(ThebesLayer* aLayer, 1.154 + gfx::DrawTarget* aTarget, 1.155 + float aOpacity, 1.156 + gfx::CompositionOp aOp, 1.157 + gfx::SourceSurface* aMask, 1.158 + const gfx::Matrix* aMaskTransform) 1.159 + { 1.160 + RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp, 1.161 + aMask, aMaskTransform); 1.162 + } 1.163 + 1.164 + virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, 1.165 + RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE; 1.166 + 1.167 + virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE 1.168 + { 1.169 + MOZ_CRASH("Should not be called on non-remote ContentClient"); 1.170 + } 1.171 +}; 1.172 + 1.173 +/** 1.174 + * A ContentClientRemote backed by a RotatedContentBuffer. 1.175 + * 1.176 + * When using a ContentClientRemote, SurfaceDescriptors are created on 1.177 + * the rendering side and destroyed on the compositing side. They are only 1.178 + * passed from one side to the other when the TextureClient/Hosts are created. 1.179 + * *Ownership* of the SurfaceDescriptor moves from the rendering side to the 1.180 + * compositing side with the create message (send from CreateBuffer) which 1.181 + * tells the compositor that TextureClients have been created and that the 1.182 + * compositor should assign the corresponding TextureHosts to our corresponding 1.183 + * ContentHost. 1.184 + * 1.185 + * If the size or type of our buffer(s) change(s), then we simply destroy and 1.186 + * create them. 1.187 + */ 1.188 +// Version using new texture clients 1.189 +class ContentClientRemoteBuffer : public ContentClientRemote 1.190 + , protected RotatedContentBuffer 1.191 +{ 1.192 + using RotatedContentBuffer::BufferRect; 1.193 + using RotatedContentBuffer::BufferRotation; 1.194 +public: 1.195 + ContentClientRemoteBuffer(CompositableForwarder* aForwarder) 1.196 + : ContentClientRemote(aForwarder) 1.197 + , RotatedContentBuffer(ContainsVisibleBounds) 1.198 + , mIsNewBuffer(false) 1.199 + , mFrontAndBackBufferDiffer(false) 1.200 + , mSurfaceFormat(gfx::SurfaceFormat::B8G8R8A8) 1.201 + {} 1.202 + 1.203 + typedef RotatedContentBuffer::PaintState PaintState; 1.204 + typedef RotatedContentBuffer::ContentType ContentType; 1.205 + 1.206 + virtual void Clear() 1.207 + { 1.208 + RotatedContentBuffer::Clear(); 1.209 + mTextureClient = nullptr; 1.210 + mTextureClientOnWhite = nullptr; 1.211 + } 1.212 + 1.213 + virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, 1.214 + uint32_t aFlags) MOZ_OVERRIDE 1.215 + { 1.216 + return RotatedContentBuffer::BeginPaint(aLayer, aFlags); 1.217 + } 1.218 + virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, 1.219 + RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE 1.220 + { 1.221 + return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter); 1.222 + } 1.223 + virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE 1.224 + { 1.225 + BorrowDrawTarget::ReturnDrawTarget(aReturned); 1.226 + } 1.227 + 1.228 + /** 1.229 + * Begin/End Paint map a gfxASurface from the texture client 1.230 + * into the buffer of RotatedBuffer. The surface is only 1.231 + * valid when the texture client is locked, so is mapped out 1.232 + * of RotatedContentBuffer when we are done painting. 1.233 + * None of the underlying buffer attributes (rect, rotation) 1.234 + * are affected by mapping/unmapping. 1.235 + */ 1.236 + virtual void BeginPaint() MOZ_OVERRIDE; 1.237 + virtual void EndPaint() MOZ_OVERRIDE; 1.238 + 1.239 + virtual void Updated(const nsIntRegion& aRegionToDraw, 1.240 + const nsIntRegion& aVisibleRegion, 1.241 + bool aDidSelfCopy); 1.242 + 1.243 + virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE; 1.244 + 1.245 + // Expose these protected methods from the superclass. 1.246 + virtual const nsIntRect& BufferRect() const 1.247 + { 1.248 + return RotatedContentBuffer::BufferRect(); 1.249 + } 1.250 + virtual const nsIntPoint& BufferRotation() const 1.251 + { 1.252 + return RotatedContentBuffer::BufferRotation(); 1.253 + } 1.254 + 1.255 + virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, 1.256 + RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE; 1.257 + 1.258 + virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE 1.259 + { 1.260 + return mTextureInfo; 1.261 + } 1.262 + 1.263 +protected: 1.264 + void DestroyBuffers(); 1.265 + 1.266 + virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw, 1.267 + const nsIntRegion& aVisibleRegion, 1.268 + bool aDidSelfCopy); 1.269 + 1.270 + void BuildTextureClients(gfx::SurfaceFormat aFormat, 1.271 + const nsIntRect& aRect, 1.272 + uint32_t aFlags); 1.273 + 1.274 + // Create the front buffer for the ContentClient/Host pair if necessary 1.275 + // and notify the compositor that we have created the buffer(s). 1.276 + virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0; 1.277 + virtual void DestroyFrontBuffer() {} 1.278 + 1.279 + bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient, 1.280 + TextureFlags aFlags = 0); 1.281 + 1.282 + virtual void AbortTextureClientCreation() 1.283 + { 1.284 + mTextureClient = nullptr; 1.285 + mTextureClientOnWhite = nullptr; 1.286 + mIsNewBuffer = false; 1.287 + } 1.288 + 1.289 + RefPtr<TextureClient> mTextureClient; 1.290 + RefPtr<TextureClient> mTextureClientOnWhite; 1.291 + // keep a record of texture clients we have created and need to keep around 1.292 + // (for RotatedBuffer to access), then unlock and remove them when we are done 1.293 + // painting. 1.294 + nsTArray<RefPtr<TextureClient> > mOldTextures; 1.295 + 1.296 + TextureInfo mTextureInfo; 1.297 + bool mIsNewBuffer; 1.298 + bool mFrontAndBackBufferDiffer; 1.299 + gfx::IntSize mSize; 1.300 + gfx::SurfaceFormat mSurfaceFormat; 1.301 +}; 1.302 + 1.303 +/** 1.304 + * A double buffered ContentClient. mTextureClient is the back buffer, which 1.305 + * we draw into. mFrontClient is the front buffer which we may read from, but 1.306 + * not write to, when the compositor does not have the 'soft' lock. We can write 1.307 + * into mTextureClient at any time. 1.308 + * 1.309 + * The ContentHost keeps a reference to both corresponding texture hosts, in 1.310 + * response to our UpdateTextureRegion message, the compositor swaps its 1.311 + * references. In response to the compositor's reply we swap our references 1.312 + * (in SwapBuffers). 1.313 + */ 1.314 +class ContentClientDoubleBuffered : public ContentClientRemoteBuffer 1.315 +{ 1.316 +public: 1.317 + ContentClientDoubleBuffered(CompositableForwarder* aFwd) 1.318 + : ContentClientRemoteBuffer(aFwd) 1.319 + { 1.320 + mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE; 1.321 + } 1.322 + virtual ~ContentClientDoubleBuffered() {} 1.323 + 1.324 + virtual void Clear() MOZ_OVERRIDE 1.325 + { 1.326 + ContentClientRemoteBuffer::Clear(); 1.327 + mFrontClient = nullptr; 1.328 + mFrontClientOnWhite = nullptr; 1.329 + } 1.330 + 1.331 + virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE; 1.332 + 1.333 + virtual void BeginPaint() MOZ_OVERRIDE; 1.334 + 1.335 + virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE; 1.336 + 1.337 +protected: 1.338 + virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE; 1.339 + virtual void DestroyFrontBuffer() MOZ_OVERRIDE; 1.340 + 1.341 +private: 1.342 + void UpdateDestinationFrom(const RotatedBuffer& aSource, 1.343 + const nsIntRegion& aUpdateRegion); 1.344 + 1.345 + virtual void AbortTextureClientCreation() MOZ_OVERRIDE 1.346 + { 1.347 + mTextureClient = nullptr; 1.348 + mTextureClientOnWhite = nullptr; 1.349 + mFrontClient = nullptr; 1.350 + mFrontClientOnWhite = nullptr; 1.351 + } 1.352 + 1.353 + RefPtr<TextureClient> mFrontClient; 1.354 + RefPtr<TextureClient> mFrontClientOnWhite; 1.355 + nsIntRegion mFrontUpdatedRegion; 1.356 + nsIntRect mFrontBufferRect; 1.357 + nsIntPoint mFrontBufferRotation; 1.358 +}; 1.359 + 1.360 +/** 1.361 + * A single buffered ContentClient. We have a single TextureClient/Host 1.362 + * which we update and then send a message to the compositor that we are 1.363 + * done updating. It is not safe for the compositor to use the corresponding 1.364 + * TextureHost's memory directly, it must upload it to video memory of some 1.365 + * kind. We are free to modify the TextureClient once we receive reply from 1.366 + * the compositor. 1.367 + */ 1.368 +class ContentClientSingleBuffered : public ContentClientRemoteBuffer 1.369 +{ 1.370 +public: 1.371 + ContentClientSingleBuffered(CompositableForwarder* aFwd) 1.372 + : ContentClientRemoteBuffer(aFwd) 1.373 + { 1.374 + mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE; 1.375 + } 1.376 + virtual ~ContentClientSingleBuffered() {} 1.377 + 1.378 + virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE; 1.379 + 1.380 +protected: 1.381 + virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {} 1.382 +}; 1.383 + 1.384 +/** 1.385 + * A single buffered ContentClient that creates temporary buffers which are 1.386 + * used to update the host-side texture. The ownership of the buffers is 1.387 + * passed to the host side during the transaction, and we need to create 1.388 + * new ones each frame. 1.389 + */ 1.390 +class ContentClientIncremental : public ContentClientRemote 1.391 + , public BorrowDrawTarget 1.392 +{ 1.393 +public: 1.394 + ContentClientIncremental(CompositableForwarder* aFwd) 1.395 + : ContentClientRemote(aFwd) 1.396 + , mContentType(gfxContentType::COLOR_ALPHA) 1.397 + , mHasBuffer(false) 1.398 + , mHasBufferOnWhite(false) 1.399 + { 1.400 + mTextureInfo.mCompositableType = BUFFER_CONTENT_INC; 1.401 + } 1.402 + 1.403 + typedef RotatedContentBuffer::PaintState PaintState; 1.404 + typedef RotatedContentBuffer::ContentType ContentType; 1.405 + 1.406 + virtual TextureInfo GetTextureInfo() const 1.407 + { 1.408 + return mTextureInfo; 1.409 + } 1.410 + 1.411 + virtual void Clear() 1.412 + { 1.413 + mBufferRect.SetEmpty(); 1.414 + mHasBuffer = false; 1.415 + mHasBufferOnWhite = false; 1.416 + } 1.417 + 1.418 + virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, 1.419 + uint32_t aFlags) MOZ_OVERRIDE; 1.420 + virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, 1.421 + RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE; 1.422 + virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE 1.423 + { 1.424 + BorrowDrawTarget::ReturnDrawTarget(aReturned); 1.425 + } 1.426 + 1.427 + virtual void Updated(const nsIntRegion& aRegionToDraw, 1.428 + const nsIntRegion& aVisibleRegion, 1.429 + bool aDidSelfCopy); 1.430 + 1.431 + virtual void EndPaint() 1.432 + { 1.433 + if (IsSurfaceDescriptorValid(mUpdateDescriptor)) { 1.434 + mForwarder->DestroySharedSurface(&mUpdateDescriptor); 1.435 + } 1.436 + if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) { 1.437 + mForwarder->DestroySharedSurface(&mUpdateDescriptorOnWhite); 1.438 + } 1.439 + ContentClientRemote::EndPaint(); 1.440 + } 1.441 + 1.442 +private: 1.443 + 1.444 + enum BufferType{ 1.445 + BUFFER_BLACK, 1.446 + BUFFER_WHITE 1.447 + }; 1.448 + 1.449 + void NotifyBufferCreated(ContentType aType, uint32_t aFlags) 1.450 + { 1.451 + mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT; 1.452 + mContentType = aType; 1.453 + 1.454 + mForwarder->CreatedIncrementalBuffer(this, 1.455 + mTextureInfo, 1.456 + mBufferRect); 1.457 + 1.458 + } 1.459 + 1.460 + TemporaryRef<gfx::DrawTarget> GetUpdateSurface(BufferType aType, 1.461 + const nsIntRegion& aUpdateRegion); 1.462 + 1.463 + TextureInfo mTextureInfo; 1.464 + nsIntRect mBufferRect; 1.465 + nsIntPoint mBufferRotation; 1.466 + 1.467 + SurfaceDescriptor mUpdateDescriptor; 1.468 + SurfaceDescriptor mUpdateDescriptorOnWhite; 1.469 + 1.470 + ContentType mContentType; 1.471 + 1.472 + bool mHasBuffer; 1.473 + bool mHasBufferOnWhite; 1.474 +}; 1.475 + 1.476 +} 1.477 +} 1.478 + 1.479 +#endif