gfx/layers/d3d9/ThebesLayerD3D9.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 */

mercurial