gfx/2d/SourceSurfaceD2D.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:feb8a52fa3eb
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/. */
5
6 #include "SourceSurfaceD2D.h"
7 #include "DrawTargetD2D.h"
8 #include "Logging.h"
9 #include "Tools.h"
10
11 namespace mozilla {
12 namespace gfx {
13
14 SourceSurfaceD2D::SourceSurfaceD2D()
15 {
16 }
17
18 SourceSurfaceD2D::~SourceSurfaceD2D()
19 {
20 if (mBitmap) {
21 DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
22 }
23 }
24
25 IntSize
26 SourceSurfaceD2D::GetSize() const
27 {
28 return mSize;
29 }
30
31 SurfaceFormat
32 SourceSurfaceD2D::GetFormat() const
33 {
34 return mFormat;
35 }
36
37 bool
38 SourceSurfaceD2D::IsValid() const
39 {
40 return mDevice == Factory::GetDirect3D10Device();
41 }
42
43 TemporaryRef<DataSourceSurface>
44 SourceSurfaceD2D::GetDataSurface()
45 {
46 RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
47 if (result->IsValid()) {
48 return result;
49 }
50 return nullptr;
51 }
52
53 bool
54 SourceSurfaceD2D::InitFromData(unsigned char *aData,
55 const IntSize &aSize,
56 int32_t aStride,
57 SurfaceFormat aFormat,
58 ID2D1RenderTarget *aRT)
59 {
60 HRESULT hr;
61
62 mFormat = aFormat;
63 mSize = aSize;
64
65 if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
66 (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
67 gfxDebug() << "Bitmap does not fit in texture.";
68 return false;
69 }
70
71 D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
72 hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));
73
74 if (FAILED(hr)) {
75 gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
76 return false;
77 }
78
79 DrawTargetD2D::mVRAMUsageSS += GetByteSize();
80 mDevice = Factory::GetDirect3D10Device();
81
82 return true;
83 }
84
85 bool
86 SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
87 SurfaceFormat aFormat,
88 ID2D1RenderTarget *aRT)
89 {
90 HRESULT hr;
91
92 RefPtr<IDXGISurface> surf;
93
94 hr = aTexture->QueryInterface((IDXGISurface**)&surf);
95
96 if (FAILED(hr)) {
97 gfxWarning() << "Failed to QI texture to surface. Code: " << hr;
98 return false;
99 }
100
101 D3D10_TEXTURE2D_DESC desc;
102 aTexture->GetDesc(&desc);
103
104 mSize = IntSize(desc.Width, desc.Height);
105 mFormat = aFormat;
106
107 D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
108 hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
109
110 if (FAILED(hr)) {
111 gfxWarning() << "Failed to create SharedBitmap. Code: " << hr;
112 return false;
113 }
114
115 aTexture->GetDevice(byRef(mDevice));
116 DrawTargetD2D::mVRAMUsageSS += GetByteSize();
117
118 return true;
119 }
120
121 uint32_t
122 SourceSurfaceD2D::GetByteSize() const
123 {
124 return mSize.width * mSize.height * BytesPerPixel(mFormat);
125 }
126
127 DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
128 : mTexture(nullptr)
129 , mFormat(aSourceSurface->mFormat)
130 , mSize(aSourceSurface->mSize)
131 , mMapped(false)
132 {
133 // We allocate ourselves a regular D3D surface (sourceTexture) and paint the
134 // D2D bitmap into it via a DXGI render target. Then we need to copy
135 // sourceTexture into a staging texture (mTexture), which we will lazily map
136 // to get the data.
137
138 CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
139 desc.MipLevels = 1;
140 desc.Usage = D3D10_USAGE_DEFAULT;
141 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
142 RefPtr<ID3D10Texture2D> sourceTexture;
143 HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
144 byRef(sourceTexture));
145 if (FAILED(hr)) {
146 gfxWarning() << "Failed to create texture. Code: " << hr;
147 return;
148 }
149
150 RefPtr<IDXGISurface> dxgiSurface;
151 hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
152 if (FAILED(hr)) {
153 gfxWarning() << "Failed to create DXGI surface. Code: " << hr;
154 return;
155 }
156
157 D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
158 D2D1_RENDER_TARGET_TYPE_DEFAULT,
159 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
160
161 RefPtr<ID2D1RenderTarget> renderTarget;
162 hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
163 &rtProps,
164 byRef(renderTarget));
165 if (FAILED(hr)) {
166 gfxWarning() << "Failed to create render target. Code: " << hr;
167 return;
168 }
169
170 renderTarget->BeginDraw();
171 renderTarget->Clear(D2D1::ColorF(0, 0.0f));
172 renderTarget->DrawBitmap(aSourceSurface->mBitmap,
173 D2D1::RectF(0, 0,
174 Float(mSize.width),
175 Float(mSize.height)));
176 hr = renderTarget->EndDraw();
177 if (FAILED(hr)) {
178 gfxWarning() << "Failed to draw bitmap. Code: " << hr;
179 return;
180 }
181
182 desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
183 desc.Usage = D3D10_USAGE_STAGING;
184 desc.BindFlags = 0;
185 hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
186 if (FAILED(hr)) {
187 gfxWarning() << "Failed to create staging texture. Code: " << hr;
188 mTexture = nullptr;
189 return;
190 }
191
192 aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
193 }
194
195 DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
196 {
197 if (mMapped) {
198 mTexture->Unmap(0);
199 }
200 }
201
202 unsigned char*
203 DataSourceSurfaceD2D::GetData()
204 {
205 EnsureMappedTexture();
206 if (!mMapped) {
207 return nullptr;
208 }
209
210 return reinterpret_cast<unsigned char*>(mData.pData);
211 }
212
213 int32_t
214 DataSourceSurfaceD2D::Stride()
215 {
216 EnsureMappedTexture();
217 if (!mMapped) {
218 return 0;
219 }
220
221 return mData.RowPitch;
222 }
223
224 IntSize
225 DataSourceSurfaceD2D::GetSize() const
226 {
227 return mSize;
228 }
229
230 SurfaceFormat
231 DataSourceSurfaceD2D::GetFormat() const
232 {
233 return mFormat;
234 }
235
236 bool
237 DataSourceSurfaceD2D::Map(MapType aMapType, MappedSurface *aMappedSurface)
238 {
239 // DataSourceSurfaces used with the new Map API should not be used with GetData!!
240 MOZ_ASSERT(!mMapped);
241 MOZ_ASSERT(!mIsMapped);
242
243 if (!mTexture) {
244 return false;
245 }
246
247 D3D10_MAP mapType;
248
249 if (aMapType == MapType::READ) {
250 mapType = D3D10_MAP_READ;
251 } else if (aMapType == MapType::WRITE) {
252 mapType = D3D10_MAP_WRITE;
253 } else {
254 mapType = D3D10_MAP_READ_WRITE;
255 }
256
257 D3D10_MAPPED_TEXTURE2D map;
258
259 HRESULT hr = mTexture->Map(0, mapType, 0, &map);
260
261 if (FAILED(hr)) {
262 gfxWarning() << "Texture map failed with code: " << hr;
263 return false;
264 }
265
266 aMappedSurface->mData = (uint8_t*)map.pData;
267 aMappedSurface->mStride = map.RowPitch;
268 mIsMapped = true;
269
270 return true;
271 }
272
273 void
274 DataSourceSurfaceD2D::Unmap()
275 {
276 MOZ_ASSERT(mIsMapped);
277
278 mIsMapped = false;
279 mTexture->Unmap(0);
280 }
281
282 void
283 DataSourceSurfaceD2D::EnsureMappedTexture()
284 {
285 // Do not use GetData() after having used Map!
286 MOZ_ASSERT(!mIsMapped);
287
288 if (mMapped ||
289 !mTexture) {
290 return;
291 }
292
293 HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
294 if (FAILED(hr)) {
295 gfxWarning() << "Failed to map texture. Code: " << hr;
296 mTexture = nullptr;
297 } else {
298 mMapped = true;
299 }
300 }
301
302 }
303 }

mercurial