Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 "mozilla/layers/PLayerTransaction.h"
8 // This must occur *after* layers/PLayerTransaction.h to avoid
9 // typedefs conflicts.
10 #include "mozilla/ArrayUtils.h"
12 #include "ThebesLayerD3D9.h"
13 #include "gfxPlatform.h"
15 #include "gfxWindowsPlatform.h"
16 #include "gfxTeeSurface.h"
17 #include "gfxUtils.h"
18 #include "ReadbackProcessor.h"
19 #include "ReadbackLayer.h"
20 #include "mozilla/gfx/2D.h"
22 namespace mozilla {
23 namespace layers {
25 using namespace gfx;
27 ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
28 : ThebesLayer(aManager, nullptr)
29 , LayerD3D9(aManager)
30 {
31 mImplData = static_cast<LayerD3D9*>(this);
32 aManager->deviceManager()->mLayersWithResources.AppendElement(this);
33 }
35 ThebesLayerD3D9::~ThebesLayerD3D9()
36 {
37 if (mD3DManager) {
38 mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
39 }
40 }
42 /**
43 * Retention threshold - amount of pixels intersection required to enable
44 * layer content retention. This is a guesstimate. Profiling could be done to
45 * figure out the optimal threshold.
46 */
47 #define RETENTION_THRESHOLD 16384
49 void
50 ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
51 {
52 mInvalidRegion.Or(mInvalidRegion, aRegion);
53 mInvalidRegion.SimplifyOutward(20);
54 mValidRegion.Sub(mValidRegion, mInvalidRegion);
55 }
57 void
58 ThebesLayerD3D9::CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
59 IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
60 const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion)
61 {
62 nsRefPtr<IDirect3DSurface9> srcSurface, dstSurface;
63 aSrc->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
64 aDest->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
66 nsIntRegion retainedRegion;
67 nsIntRegionRectIterator iter(aCopyRegion);
68 const nsIntRect *r;
69 while ((r = iter.Next())) {
70 if (r->width * r->height > RETENTION_THRESHOLD) {
71 RECT oldRect, newRect;
73 // Calculate the retained rectangle's position on the old and the new
74 // surface.
75 oldRect.left = r->x - aSrcOffset.x;
76 oldRect.top = r->y - aSrcOffset.y;
77 oldRect.right = oldRect.left + r->width;
78 oldRect.bottom = oldRect.top + r->height;
80 newRect.left = r->x - aDestOffset.x;
81 newRect.top = r->y - aDestOffset.y;
82 newRect.right = newRect.left + r->width;
83 newRect.bottom = newRect.top + r->height;
85 // Copy data from our old texture to the new one
86 HRESULT hr = device()->
87 StretchRect(srcSurface, &oldRect, dstSurface, &newRect, D3DTEXF_NONE);
89 if (SUCCEEDED(hr)) {
90 retainedRegion.Or(retainedRegion, *r);
91 }
92 }
93 }
95 // Areas which were valid and were retained are still valid
96 aValidRegion->And(*aValidRegion, retainedRegion);
97 }
99 static uint64_t RectArea(const nsIntRect& aRect)
100 {
101 return aRect.width*uint64_t(aRect.height);
102 }
104 void
105 ThebesLayerD3D9::UpdateTextures(SurfaceMode aMode)
106 {
107 nsIntRect visibleRect = mVisibleRegion.GetBounds();
109 if (HaveTextures(aMode)) {
110 if (!mTextureRect.IsEqualInterior(visibleRect)) {
111 nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
112 nsRefPtr<IDirect3DTexture9> oldTextureOnWhite = mTextureOnWhite;
114 NS_ASSERTION(mTextureRect.Contains(mValidRegion.GetBounds()),
115 "How can we have valid data outside the texture?");
116 nsIntRegion retainRegion;
117 // The region we want to retain is the valid data that is inside
118 // the new visible region
119 retainRegion.And(mValidRegion, mVisibleRegion);
121 CreateNewTextures(gfx::IntSize(visibleRect.width, visibleRect.height), aMode);
123 // If our texture creation failed this can mean a device reset is pending and we
124 // should silently ignore the failure. In the future when device failures
125 // are properly handled we should test for the type of failure and gracefully
126 // handle different failures. See bug 569081.
127 if (!HaveTextures(aMode)) {
128 mValidRegion.SetEmpty();
129 } else {
130 CopyRegion(oldTexture, mTextureRect.TopLeft(), mTexture, visibleRect.TopLeft(),
131 retainRegion, &mValidRegion);
132 if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
133 CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(), mTextureOnWhite, visibleRect.TopLeft(),
134 retainRegion, &mValidRegion);
135 }
136 }
138 mTextureRect = visibleRect;
139 }
140 } else {
141 CreateNewTextures(gfx::IntSize(visibleRect.width, visibleRect.height), aMode);
142 mTextureRect = visibleRect;
144 NS_ASSERTION(mValidRegion.IsEmpty(), "Someone forgot to empty the region");
145 }
146 }
148 void
149 ThebesLayerD3D9::RenderRegion(const nsIntRegion& aRegion)
150 {
151 nsIntRegionRectIterator iter(aRegion);
153 const nsIntRect *iterRect;
154 while ((iterRect = iter.Next())) {
155 device()->SetVertexShaderConstantF(CBvLayerQuad,
156 ShaderConstantRect(iterRect->x,
157 iterRect->y,
158 iterRect->width,
159 iterRect->height),
160 1);
162 device()->SetVertexShaderConstantF(CBvTextureCoords,
163 ShaderConstantRect(
164 (float)(iterRect->x - mTextureRect.x) / (float)mTextureRect.width,
165 (float)(iterRect->y - mTextureRect.y) / (float)mTextureRect.height,
166 (float)iterRect->width / (float)mTextureRect.width,
167 (float)iterRect->height / (float)mTextureRect.height), 1);
169 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
170 }
171 }
173 void
174 ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
175 {
176 if (mVisibleRegion.IsEmpty()) {
177 return;
178 }
180 nsIntRect newTextureRect = mVisibleRegion.GetBounds();
182 SurfaceMode mode = GetSurfaceMode();
183 if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA &&
184 (!mParent || !mParent->SupportsComponentAlphaChildren())) {
185 mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
186 }
187 // If we have a transform that requires resampling of our texture, then
188 // we need to make sure we don't sample pixels that haven't been drawn.
189 // We clamp sample coordinates to the texture rect, but when the visible region
190 // doesn't fill the entire texture rect we need to make sure we draw all the
191 // pixels in the texture rect anyway in case they get sampled.
192 nsIntRegion neededRegion = mVisibleRegion;
193 if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
194 neededRegion.GetNumRects() > 1) {
195 if (MayResample()) {
196 neededRegion = newTextureRect;
197 if (mode == SurfaceMode::SURFACE_OPAQUE) {
198 // We're going to paint outside the visible region, but layout hasn't
199 // promised that it will paint opaquely there, so we'll have to
200 // treat this layer as transparent.
201 mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
202 }
203 }
204 }
206 VerifyContentType(mode);
207 UpdateTextures(mode);
208 if (!HaveTextures(mode)) {
209 NS_WARNING("Texture creation failed");
210 return;
211 }
213 nsTArray<ReadbackProcessor::Update> readbackUpdates;
214 nsIntRegion readbackRegion;
215 if (aReadback && UsedForReadback()) {
216 aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
217 }
219 // Because updates to D3D9 ThebesLayers are rendered with the CPU, we don't
220 // have to do readback from D3D9 surfaces. Instead we make sure that any area
221 // needed for readback is included in the drawRegion we ask layout to render.
222 // Then the readback areas we need can be copied out of the temporary
223 // destinationSurface in DrawRegion.
224 nsIntRegion drawRegion;
225 drawRegion.Sub(neededRegion, mValidRegion);
226 drawRegion.Or(drawRegion, readbackRegion);
227 // NS_ASSERTION(mVisibleRegion.Contains(region), "Bad readback region!");
229 if (!drawRegion.IsEmpty()) {
230 LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
231 if (!cbInfo.Callback) {
232 NS_ERROR("D3D9 should never need to update ThebesLayers in an empty transaction");
233 return;
234 }
236 DrawRegion(drawRegion, mode, readbackUpdates);
238 mValidRegion = neededRegion;
239 }
241 if (mD3DManager->CompositingDisabled()) {
242 return;
243 }
245 SetShaderTransformAndOpacity();
247 if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
248 mD3DManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1,
249 GetMaskLayer());
250 device()->SetTexture(0, mTexture);
251 device()->SetTexture(1, mTextureOnWhite);
252 device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
253 device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
254 RenderRegion(neededRegion);
256 mD3DManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2,
257 GetMaskLayer());
258 device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
259 device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
260 RenderRegion(neededRegion);
262 // Restore defaults
263 device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
264 device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
265 device()->SetTexture(1, nullptr);
266 } else {
267 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER,
268 GetMaskLayer());
269 device()->SetTexture(0, mTexture);
270 RenderRegion(neededRegion);
271 }
273 // Set back to default.
274 device()->SetVertexShaderConstantF(CBvTextureCoords,
275 ShaderConstantRect(0, 0, 1.0f, 1.0f),
276 1);
277 }
279 void
280 ThebesLayerD3D9::CleanResources()
281 {
282 mTexture = nullptr;
283 mTextureOnWhite = nullptr;
284 mValidRegion.SetEmpty();
285 }
287 void
288 ThebesLayerD3D9::LayerManagerDestroyed()
289 {
290 mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
291 mD3DManager = nullptr;
292 }
294 Layer*
295 ThebesLayerD3D9::GetLayer()
296 {
297 return this;
298 }
300 bool
301 ThebesLayerD3D9::IsEmpty()
302 {
303 return !mTexture;
304 }
306 void
307 ThebesLayerD3D9::VerifyContentType(SurfaceMode aMode)
308 {
309 if (!mTexture)
310 return;
312 D3DSURFACE_DESC desc;
313 mTexture->GetLevelDesc(0, &desc);
315 switch (aMode) {
316 case SurfaceMode::SURFACE_OPAQUE:
317 if (desc.Format == D3DFMT_X8R8G8B8 && !mTextureOnWhite)
318 return;
319 break;
321 case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA:
322 if (desc.Format == D3DFMT_A8R8G8B8 && !mTextureOnWhite)
323 return;
324 break;
326 case SurfaceMode::SURFACE_COMPONENT_ALPHA:
327 if (mTextureOnWhite) {
328 NS_ASSERTION(desc.Format == D3DFMT_X8R8G8B8, "Wrong format for component alpha texture");
329 return;
330 }
331 break;
332 }
334 // The new format isn't compatible with the old texture(s), toss out the old
335 // texture(s).
336 mTexture = nullptr;
337 mTextureOnWhite = nullptr;
338 mValidRegion.SetEmpty();
339 }
341 class OpaqueRenderer {
342 public:
343 OpaqueRenderer(const nsIntRegion& aUpdateRegion) :
344 mUpdateRegion(aUpdateRegion) {}
345 ~OpaqueRenderer() { End(); }
346 already_AddRefed<gfxWindowsSurface> Begin(LayerD3D9* aLayer);
347 void End();
348 IDirect3DTexture9* GetTexture() { return mTmpTexture; }
350 private:
351 const nsIntRegion& mUpdateRegion;
352 nsRefPtr<IDirect3DTexture9> mTmpTexture;
353 nsRefPtr<IDirect3DSurface9> mSurface;
354 nsRefPtr<gfxWindowsSurface> mD3D9ThebesSurface;
355 };
357 already_AddRefed<gfxWindowsSurface>
358 OpaqueRenderer::Begin(LayerD3D9* aLayer)
359 {
360 nsIntRect bounds = mUpdateRegion.GetBounds();
362 HRESULT hr = aLayer->device()->
363 CreateTexture(bounds.width, bounds.height, 1, 0, D3DFMT_X8R8G8B8,
364 D3DPOOL_SYSTEMMEM, getter_AddRefs(mTmpTexture), nullptr);
366 if (FAILED(hr)) {
367 aLayer->ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
368 return nullptr;
369 }
371 hr = mTmpTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface));
373 if (FAILED(hr)) {
374 // Uh-oh, bail.
375 NS_WARNING("Failed to get texture surface level.");
376 return nullptr;
377 }
379 nsRefPtr<gfxWindowsSurface> result = new gfxWindowsSurface(mSurface);
380 if (!result || result->CairoStatus()) {
381 NS_WARNING("Failed to d3d9 cairo surface.");
382 return nullptr;
383 }
384 mD3D9ThebesSurface = result;
386 return result.forget();
387 }
389 void
390 OpaqueRenderer::End()
391 {
392 mSurface = nullptr;
393 // gfxWindowsSurface returned from ::Begin() should be released before the
394 // texture is used. This will assert that this is the case
395 #if 1
396 if (mD3D9ThebesSurface) {
397 mD3D9ThebesSurface->AddRef();
398 nsrefcnt c = mD3D9ThebesSurface->Release();
399 if (c != 1)
400 NS_RUNTIMEABORT("Reference mD3D9ThebesSurface must be released by caller of Begin() before calling End()");
401 }
402 #endif
403 mD3D9ThebesSurface = nullptr;
405 }
407 static void
408 FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
409 const nsIntPoint& aOffset, const gfxRGBA& aColor)
410 {
411 nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
412 ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
413 gfxUtils::ClipToRegion(ctx, aRegion);
414 ctx->SetColor(aColor);
415 ctx->Paint();
416 }
418 void
419 ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
420 const nsTArray<ReadbackProcessor::Update>& aReadbackUpdates)
421 {
422 HRESULT hr;
423 nsIntRect visibleRect = mVisibleRegion.GetBounds();
425 nsRefPtr<gfxASurface> destinationSurface;
426 nsIntRect bounds = aRegion.GetBounds();
427 nsRefPtr<IDirect3DTexture9> tmpTexture;
428 OpaqueRenderer opaqueRenderer(aRegion);
429 OpaqueRenderer opaqueRendererOnWhite(aRegion);
431 switch (aMode)
432 {
433 case SurfaceMode::SURFACE_OPAQUE:
434 destinationSurface = opaqueRenderer.Begin(this);
435 break;
437 case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
438 hr = device()->CreateTexture(bounds.width, bounds.height, 1,
439 0, D3DFMT_A8R8G8B8,
440 D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), nullptr);
442 if (FAILED(hr)) {
443 ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
444 return;
445 }
447 // XXX - We may consider retaining a SYSTEMMEM texture texture the size
448 // of our DEFAULT texture and then use UpdateTexture and add dirty rects
449 // to update in a single call.
450 nsRefPtr<gfxWindowsSurface> dest = new gfxWindowsSurface(
451 gfxIntSize(bounds.width, bounds.height), gfxImageFormat::ARGB32);
452 // If the contents of this layer don't require component alpha in the
453 // end of rendering, it's safe to enable Cleartype since all the Cleartype
454 // glyphs must be over (or under) opaque pixels.
455 dest->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
456 destinationSurface = dest.forget();
457 break;
458 }
460 case SurfaceMode::SURFACE_COMPONENT_ALPHA: {
461 nsRefPtr<gfxWindowsSurface> onBlack = opaqueRenderer.Begin(this);
462 nsRefPtr<gfxWindowsSurface> onWhite = opaqueRendererOnWhite.Begin(this);
463 if (onBlack && onWhite) {
464 FillSurface(onBlack, aRegion, bounds.TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0));
465 FillSurface(onWhite, aRegion, bounds.TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0));
466 gfxASurface* surfaces[2] = { onBlack.get(), onWhite.get() };
467 destinationSurface = new gfxTeeSurface(surfaces, ArrayLength(surfaces));
468 // Using this surface as a source will likely go horribly wrong, since
469 // only the onBlack surface will really be used, so alpha information will
470 // be incorrect.
471 destinationSurface->SetAllowUseAsSource(false);
472 }
473 break;
474 }
475 }
477 if (!destinationSurface)
478 return;
480 nsRefPtr<gfxContext> context;
481 if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO)) {
482 RefPtr<DrawTarget> dt =
483 gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(destinationSurface,
484 IntSize(destinationSurface->GetSize().width,
485 destinationSurface->GetSize().height));
487 context = new gfxContext(dt);
488 } else {
489 context = new gfxContext(destinationSurface);
490 }
492 context->Translate(gfxPoint(-bounds.x, -bounds.y));
493 LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
494 cbInfo.Callback(this, context, aRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), cbInfo.CallbackData);
496 for (uint32_t i = 0; i < aReadbackUpdates.Length(); ++i) {
497 NS_ASSERTION(aMode == SurfaceMode::SURFACE_OPAQUE,
498 "Transparent surfaces should not be used for readback");
499 const ReadbackProcessor::Update& update = aReadbackUpdates[i];
500 nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
501 nsRefPtr<gfxContext> ctx =
502 update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
503 update.mSequenceCounter);
504 if (ctx) {
505 ctx->Translate(gfxPoint(offset.x, offset.y));
506 ctx->SetSource(destinationSurface, gfxPoint(bounds.x, bounds.y));
507 ctx->Paint();
508 update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
509 }
510 }
512 // Release the cairo d3d9 surface before we try to composite it
513 context = nullptr;
515 nsAutoTArray<IDirect3DTexture9*,2> srcTextures;
516 nsAutoTArray<IDirect3DTexture9*,2> destTextures;
517 switch (aMode)
518 {
519 case SurfaceMode::SURFACE_OPAQUE:
520 // Must release reference to dest surface before ending drawing
521 destinationSurface = nullptr;
522 opaqueRenderer.End();
523 srcTextures.AppendElement(opaqueRenderer.GetTexture());
524 destTextures.AppendElement(mTexture);
525 break;
527 case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
528 LockTextureRectD3D9 textureLock(tmpTexture);
529 if (!textureLock.HasLock()) {
530 NS_WARNING("Failed to lock ThebesLayer tmpTexture texture.");
531 return;
532 }
534 D3DLOCKED_RECT r = textureLock.GetLockRect();
536 nsRefPtr<gfxImageSurface> imgSurface =
537 new gfxImageSurface((unsigned char *)r.pBits,
538 bounds.Size(),
539 r.Pitch,
540 gfxImageFormat::ARGB32);
542 if (destinationSurface) {
543 nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
544 context->SetSource(destinationSurface);
545 context->SetOperator(gfxContext::OPERATOR_SOURCE);
546 context->Paint();
547 }
549 // Must release reference to dest surface before ending drawing
550 destinationSurface = nullptr;
551 imgSurface = nullptr;
553 srcTextures.AppendElement(tmpTexture);
554 destTextures.AppendElement(mTexture);
555 break;
556 }
558 case SurfaceMode::SURFACE_COMPONENT_ALPHA: {
559 // Must release reference to dest surface before ending drawing
560 destinationSurface = nullptr;
561 opaqueRenderer.End();
562 opaqueRendererOnWhite.End();
563 srcTextures.AppendElement(opaqueRenderer.GetTexture());
564 destTextures.AppendElement(mTexture);
565 srcTextures.AppendElement(opaqueRendererOnWhite.GetTexture());
566 destTextures.AppendElement(mTextureOnWhite);
567 break;
568 }
569 }
570 NS_ASSERTION(srcTextures.Length() == destTextures.Length(), "Mismatched lengths");
573 // Copy to the texture.
574 for (uint32_t i = 0; i < srcTextures.Length(); ++i) {
575 nsRefPtr<IDirect3DSurface9> srcSurface;
576 nsRefPtr<IDirect3DSurface9> dstSurface;
578 destTextures[i]->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
579 srcTextures[i]->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
581 nsIntRegionRectIterator iter(aRegion);
582 const nsIntRect *iterRect;
583 while ((iterRect = iter.Next())) {
584 RECT rect;
585 rect.left = iterRect->x - bounds.x;
586 rect.top = iterRect->y - bounds.y;
587 rect.right = iterRect->XMost() - bounds.x;
588 rect.bottom = iterRect->YMost() - bounds.y;
590 POINT point;
591 point.x = iterRect->x - visibleRect.x;
592 point.y = iterRect->y - visibleRect.y;
593 device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
594 }
595 }
596 }
598 void
599 ThebesLayerD3D9::CreateNewTextures(const gfx::IntSize &aSize,
600 SurfaceMode aMode)
601 {
602 if (aSize.width == 0 || aSize.height == 0) {
603 // Nothing to do.
604 return;
605 }
607 mTexture = nullptr;
608 mTextureOnWhite = nullptr;
609 HRESULT hr = device()->CreateTexture(aSize.width, aSize.height, 1,
610 D3DUSAGE_RENDERTARGET,
611 aMode != SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
612 D3DPOOL_DEFAULT, getter_AddRefs(mTexture), nullptr);
613 if (FAILED(hr)) {
614 ReportFailure(NS_LITERAL_CSTRING("ThebesLayerD3D9::CreateNewTextures(): Failed to create texture"),
615 hr);
616 return;
617 }
619 if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
620 hr = device()->CreateTexture(aSize.width, aSize.height, 1,
621 D3DUSAGE_RENDERTARGET,
622 D3DFMT_X8R8G8B8,
623 D3DPOOL_DEFAULT, getter_AddRefs(mTextureOnWhite), nullptr);
624 if (FAILED(hr)) {
625 ReportFailure(NS_LITERAL_CSTRING("ThebesLayerD3D9::CreateNewTextures(): Failed to create texture (2)"),
626 hr);
627 return;
628 }
629 }
630 }
632 } /* namespace layers */
633 } /* namespace mozilla */