gfx/layers/ReadbackLayer.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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 #ifndef GFX_READBACKLAYER_H
michael@0 7 #define GFX_READBACKLAYER_H
michael@0 8
michael@0 9 #include <stdint.h> // for uint64_t
michael@0 10 #include "Layers.h" // for Layer, etc
michael@0 11 #include "gfxColor.h" // for gfxRGBA
michael@0 12 #include "gfxRect.h" // for gfxRect
michael@0 13 #include "mozilla/mozalloc.h" // for operator delete
michael@0 14 #include "nsAutoPtr.h" // for nsAutoPtr
michael@0 15 #include "nsCOMPtr.h" // for already_AddRefed
michael@0 16 #include "nsDebug.h" // for NS_ASSERTION
michael@0 17 #include "nsPoint.h" // for nsIntPoint
michael@0 18 #include "nsRect.h" // for nsIntRect
michael@0 19 #include "nsSize.h" // for nsIntSize
michael@0 20 #include "nscore.h" // for nsACString
michael@0 21
michael@0 22 class gfxContext;
michael@0 23
michael@0 24 namespace mozilla {
michael@0 25 namespace layers {
michael@0 26
michael@0 27 class ReadbackProcessor;
michael@0 28
michael@0 29 /**
michael@0 30 * A ReadbackSink receives a stream of updates to a rectangle of pixels.
michael@0 31 * These update callbacks are always called on the main thread, either during
michael@0 32 * EndTransaction or from the event loop.
michael@0 33 */
michael@0 34 class ReadbackSink {
michael@0 35 public:
michael@0 36 ReadbackSink() {}
michael@0 37 virtual ~ReadbackSink() {}
michael@0 38
michael@0 39 /**
michael@0 40 * Sends an update to indicate that the background is currently unknown.
michael@0 41 */
michael@0 42 virtual void SetUnknown(uint64_t aSequenceNumber) = 0;
michael@0 43 /**
michael@0 44 * Called by the layer system to indicate that the contents of part of
michael@0 45 * the readback area are changing.
michael@0 46 * @param aRect is the rectangle of content that is being updated,
michael@0 47 * in the coordinate system of the ReadbackLayer.
michael@0 48 * @param aSequenceNumber updates issued out of order should be ignored.
michael@0 49 * Only use updates whose sequence counter is greater than all other updates
michael@0 50 * seen so far. Return null when a non-fresh sequence value is given.
michael@0 51 * @return a context into which the update should be drawn. This should be
michael@0 52 * set up to clip to aRect. Zero should never be passed as a sequence number.
michael@0 53 * If this returns null, EndUpdate should NOT be called. If it returns
michael@0 54 * non-null, EndUpdate must be called.
michael@0 55 *
michael@0 56 * We don't support partially unknown backgrounds. Therefore, the
michael@0 57 * first BeginUpdate after a SetUnknown will have the complete background.
michael@0 58 */
michael@0 59 virtual already_AddRefed<gfxContext>
michael@0 60 BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber) = 0;
michael@0 61 /**
michael@0 62 * EndUpdate must be called immediately after BeginUpdate, without returning
michael@0 63 * to the event loop.
michael@0 64 * @param aContext the context returned by BeginUpdate
michael@0 65 * Implicitly Restore()s the state of aContext.
michael@0 66 */
michael@0 67 virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect) = 0;
michael@0 68 };
michael@0 69
michael@0 70 /**
michael@0 71 * A ReadbackLayer never renders anything. It enables clients to extract
michael@0 72 * the rendered contents of the layer tree below the ReadbackLayer.
michael@0 73 * The rendered contents are delivered asynchronously via calls to a
michael@0 74 * ReadbackSink object supplied by the client.
michael@0 75 *
michael@0 76 * This is a "best effort" API; it is possible for the layer system to tell
michael@0 77 * the ReadbackSink that the contents of the readback area are unknown.
michael@0 78 *
michael@0 79 * This API exists to work around the limitations of transparent windowless
michael@0 80 * plugin rendering APIs. It should not be used for anything else.
michael@0 81 */
michael@0 82 class ReadbackLayer : public Layer {
michael@0 83 public:
michael@0 84 MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
michael@0 85
michael@0 86 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
michael@0 87 {
michael@0 88 // Snap our local transform first, and snap the inherited transform as well.
michael@0 89 // This makes our snapping equivalent to what would happen if our content
michael@0 90 // was drawn into a ThebesLayer (gfxContext would snap using the local
michael@0 91 // transform, then we'd snap again when compositing the ThebesLayer).
michael@0 92 mEffectiveTransform =
michael@0 93 SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
michael@0 94 nullptr)*
michael@0 95 SnapTransformTranslation(aTransformToSurface, nullptr);
michael@0 96 }
michael@0 97
michael@0 98 /**
michael@0 99 * CONSTRUCTION PHASE ONLY
michael@0 100 * Set the callback object to which readback updates will be delivered.
michael@0 101 * This also resets the "needed rectangle" so that on the next layer tree
michael@0 102 * transaction we will try to deliver the full contents of the readback
michael@0 103 * area to the sink.
michael@0 104 * This layer takes ownership of the sink. It will be deleted when the
michael@0 105 * layer is destroyed or when a new sink is set.
michael@0 106 * Initially the contents of the readback area are completely unknown.
michael@0 107 */
michael@0 108 void SetSink(ReadbackSink* aSink)
michael@0 109 {
michael@0 110 SetUnknown();
michael@0 111 mSink = aSink;
michael@0 112 }
michael@0 113 ReadbackSink* GetSink() { return mSink; }
michael@0 114
michael@0 115 /**
michael@0 116 * CONSTRUCTION PHASE ONLY
michael@0 117 * Set the size of content that should be read back. The readback area
michael@0 118 * has its top-left at 0,0 and has size aSize.
michael@0 119 * Can only be called while the sink is null!
michael@0 120 */
michael@0 121 void SetSize(const nsIntSize& aSize)
michael@0 122 {
michael@0 123 NS_ASSERTION(!mSink, "Should have no sink while changing size!");
michael@0 124 mSize = aSize;
michael@0 125 }
michael@0 126 const nsIntSize& GetSize() { return mSize; }
michael@0 127 nsIntRect GetRect() { return nsIntRect(nsIntPoint(0, 0), mSize); }
michael@0 128
michael@0 129 bool IsBackgroundKnown()
michael@0 130 {
michael@0 131 return mBackgroundLayer || mBackgroundColor.a == 1.0;
michael@0 132 }
michael@0 133
michael@0 134 void NotifyRemoved() {
michael@0 135 SetUnknown();
michael@0 136 mSink = nullptr;
michael@0 137 }
michael@0 138
michael@0 139 void NotifyThebesLayerRemoved(ThebesLayer* aLayer)
michael@0 140 {
michael@0 141 if (mBackgroundLayer == aLayer) {
michael@0 142 mBackgroundLayer = nullptr;
michael@0 143 }
michael@0 144 }
michael@0 145
michael@0 146 const nsIntPoint& GetBackgroundLayerOffset() { return mBackgroundLayerOffset; }
michael@0 147
michael@0 148 uint64_t AllocateSequenceNumber() { return ++mSequenceCounter; }
michael@0 149
michael@0 150 void SetUnknown()
michael@0 151 {
michael@0 152 if (IsBackgroundKnown()) {
michael@0 153 if (mSink) {
michael@0 154 mSink->SetUnknown(AllocateSequenceNumber());
michael@0 155 }
michael@0 156 mBackgroundLayer = nullptr;
michael@0 157 mBackgroundColor = gfxRGBA(0,0,0,0);
michael@0 158 }
michael@0 159 }
michael@0 160
michael@0 161 protected:
michael@0 162 friend class ReadbackProcessor;
michael@0 163
michael@0 164 ReadbackLayer(LayerManager* aManager, void* aImplData) :
michael@0 165 Layer(aManager, aImplData),
michael@0 166 mSequenceCounter(0),
michael@0 167 mSize(0,0),
michael@0 168 mBackgroundLayer(nullptr),
michael@0 169 mBackgroundLayerOffset(0, 0),
michael@0 170 mBackgroundColor(gfxRGBA(0,0,0,0))
michael@0 171 {}
michael@0 172
michael@0 173 // Print interesting information about this into aTo. Internally
michael@0 174 // used to implement Dump*() and Log*().
michael@0 175 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 176
michael@0 177 uint64_t mSequenceCounter;
michael@0 178 nsAutoPtr<ReadbackSink> mSink;
michael@0 179 nsIntSize mSize;
michael@0 180
michael@0 181 // This can refer to any (earlier) sibling ThebesLayer. That ThebesLayer
michael@0 182 // must have mUsedForReadback set on it. If the ThebesLayer is removed
michael@0 183 // for the container, this will be set to null by NotifyThebesLayerRemoved.
michael@0 184 // This ThebesLayer contains the contents which have previously been reported
michael@0 185 // to mSink. The ThebesLayer had only an integer translation transform,
michael@0 186 // and it covered the entire readback area. This layer also had only an
michael@0 187 // integer translation transform.
michael@0 188 ThebesLayer* mBackgroundLayer;
michael@0 189 // When mBackgroundLayer is non-null, this is the offset to add to
michael@0 190 // convert from the coordinates of mBackgroundLayer to the coordinates
michael@0 191 // of this layer.
michael@0 192 nsIntPoint mBackgroundLayerOffset;
michael@0 193 // When mBackgroundColor is opaque, this is the color of the ColorLayer
michael@0 194 // that contained the contents we reported to mSink, which covered the
michael@0 195 // entire readback area.
michael@0 196 gfxRGBA mBackgroundColor;
michael@0 197 };
michael@0 198
michael@0 199 }
michael@0 200 }
michael@0 201 #endif /* GFX_READBACKLAYER_H */

mercurial