Tue, 06 Jan 2015 21:39:09 +0100
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.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SourceSurfaceD2D1.h"
7 #include "DrawTargetD2D1.h"
8 #include "Tools.h"
10 namespace mozilla {
11 namespace gfx {
13 SourceSurfaceD2D1::SourceSurfaceD2D1(ID2D1Image *aImage, ID2D1DeviceContext *aDC,
14 SurfaceFormat aFormat, const IntSize &aSize,
15 DrawTargetD2D1 *aDT)
16 : mImage(aImage)
17 , mDC(aDC)
18 , mDrawTarget(aDT)
19 {
20 aImage->QueryInterface((ID2D1Bitmap1**)byRef(mRealizedBitmap));
22 mFormat = aFormat;
23 mSize = aSize;
24 }
26 SourceSurfaceD2D1::~SourceSurfaceD2D1()
27 {
28 }
30 TemporaryRef<DataSourceSurface>
31 SourceSurfaceD2D1::GetDataSurface()
32 {
33 EnsureRealizedBitmap();
35 RefPtr<ID2D1Bitmap1> softwareBitmap;
36 D2D1_BITMAP_PROPERTIES1 props;
37 props.dpiX = 96;
38 props.dpiY = 96;
39 props.pixelFormat = D2DPixelFormat(mFormat);
40 props.colorContext = nullptr;
41 props.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW |
42 D2D1_BITMAP_OPTIONS_CPU_READ;
43 mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(softwareBitmap));
45 D2D1_POINT_2U point = D2D1::Point2U(0, 0);
46 D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height);
47 softwareBitmap->CopyFromBitmap(&point, mRealizedBitmap, &rect);
48 return new DataSourceSurfaceD2D1(softwareBitmap, mFormat);
49 }
51 void
52 SourceSurfaceD2D1::EnsureRealizedBitmap()
53 {
54 if (mRealizedBitmap) {
55 return;
56 }
58 RefPtr<ID2D1DeviceContext> dc;
59 Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, byRef(dc));
61 D2D1_BITMAP_PROPERTIES1 props;
62 props.dpiX = 96;
63 props.dpiY = 96;
64 props.pixelFormat = D2DPixelFormat(mFormat);
65 props.colorContext = nullptr;
66 props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
67 dc->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap));
69 dc->SetTarget(mRealizedBitmap);
71 dc->BeginDraw();
72 dc->DrawImage(mImage);
73 dc->EndDraw();
74 }
76 void
77 SourceSurfaceD2D1::DrawTargetWillChange()
78 {
79 // At this point in time this should always be true here.
80 MOZ_ASSERT(mRealizedBitmap);
82 RefPtr<ID2D1Bitmap1> oldBitmap = mRealizedBitmap;
84 D2D1_BITMAP_PROPERTIES1 props;
85 props.dpiX = 96;
86 props.dpiY = 96;
87 props.pixelFormat = D2DPixelFormat(mFormat);
88 props.colorContext = nullptr;
89 props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
90 mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap));
92 D2D1_POINT_2U point = D2D1::Point2U(0, 0);
93 D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height);
94 mRealizedBitmap->CopyFromBitmap(&point, oldBitmap, &rect);
95 mImage = mRealizedBitmap;
97 DrawTargetD2D1::mVRAMUsageSS += mSize.width * mSize.height * BytesPerPixel(mFormat);
98 mDrawTarget = nullptr;
100 // We now no longer depend on the source surface content remaining the same.
101 MarkIndependent();
102 }
104 void
105 SourceSurfaceD2D1::MarkIndependent()
106 {
107 if (mDrawTarget) {
108 MOZ_ASSERT(mDrawTarget->mSnapshot == this);
109 mDrawTarget->mSnapshot = nullptr;
110 mDrawTarget = nullptr;
111 }
112 }
114 DataSourceSurfaceD2D1::DataSourceSurfaceD2D1(ID2D1Bitmap1 *aMappableBitmap, SurfaceFormat aFormat)
115 : mBitmap(aMappableBitmap)
116 , mFormat(aFormat)
117 , mMapped(false)
118 {
119 }
121 DataSourceSurfaceD2D1::~DataSourceSurfaceD2D1()
122 {
123 if (mMapped) {
124 mBitmap->Unmap();
125 }
126 }
128 IntSize
129 DataSourceSurfaceD2D1::GetSize() const
130 {
131 D2D1_SIZE_F size = mBitmap->GetSize();
133 return IntSize(int32_t(size.width), int32_t(size.height));
134 }
136 uint8_t*
137 DataSourceSurfaceD2D1::GetData()
138 {
139 EnsureMapped();
141 return mMap.bits;
142 }
144 bool
145 DataSourceSurfaceD2D1::Map(MapType aMapType, MappedSurface *aMappedSurface)
146 {
147 // DataSourceSurfaces used with the new Map API should not be used with GetData!!
148 MOZ_ASSERT(!mMapped);
149 MOZ_ASSERT(!mIsMapped);
151 D2D1_MAP_OPTIONS options;
152 if (aMapType == MapType::READ) {
153 options = D2D1_MAP_OPTIONS_READ;
154 } else {
155 MOZ_CRASH("No support for Write maps on D2D1 DataSourceSurfaces yet!");
156 }
158 D2D1_MAPPED_RECT map;
159 mBitmap->Map(D2D1_MAP_OPTIONS_READ, &map);
160 aMappedSurface->mData = map.bits;
161 aMappedSurface->mStride = map.pitch;
163 mIsMapped = true;
164 return true;
165 }
167 void
168 DataSourceSurfaceD2D1::Unmap()
169 {
170 MOZ_ASSERT(mIsMapped);
172 mIsMapped = false;
173 mBitmap->Unmap();
174 }
176 int32_t
177 DataSourceSurfaceD2D1::Stride()
178 {
179 EnsureMapped();
181 return mMap.pitch;
182 }
184 void
185 DataSourceSurfaceD2D1::EnsureMapped()
186 {
187 // Do not use GetData() after having used Map!
188 MOZ_ASSERT(!mIsMapped);
189 if (mMapped) {
190 return;
191 }
192 mBitmap->Map(D2D1_MAP_OPTIONS_READ, &mMap);
193 mMapped = true;
194 }
196 }
197 }