Example #1
0
void
ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental* aHost)
{
  Compositor* compositor = aHost->GetCompositor();
  MOZ_ASSERT(compositor);

  RefPtr<DataTextureSource> temp =
    compositor->CreateDataTextureSource(mTextureInfo.mTextureFlags);
  MOZ_ASSERT(temp->AsSourceOGL() &&
             temp->AsSourceOGL()->AsTextureImageTextureSource());
  RefPtr<TextureImageTextureSourceOGL> newSource =
    temp->AsSourceOGL()->AsTextureImageTextureSource();

  RefPtr<TextureImageTextureSourceOGL> newSourceOnWhite;
  if (mTextureInfo.mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
    temp =
      compositor->CreateDataTextureSource(mTextureInfo.mTextureFlags);
    MOZ_ASSERT(temp->AsSourceOGL() &&
               temp->AsSourceOGL()->AsTextureImageTextureSource());
    newSourceOnWhite = temp->AsSourceOGL()->AsTextureImageTextureSource();
  }

  if (mTextureInfo.mDeprecatedTextureHostFlags & DeprecatedTextureHostFlags::COPY_PREVIOUS) {
    MOZ_ASSERT(aHost->mSource);
    MOZ_ASSERT(aHost->mSource->IsValid());
    nsIntRect bufferRect = aHost->mBufferRect;
    nsIntPoint bufferRotation = aHost->mBufferRotation;
    nsIntRect overlap;

    // The buffer looks like:
    //  ______
    // |1  |2 |  Where the center point is offset by mBufferRotation from the top-left corner.
    // |___|__|
    // |3  |4 |
    // |___|__|
    //
    // This is drawn to the screen as:
    //  ______
    // |4  |3 |  Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
    // |___|__|  from the top left corner - rotationPoint.
    // |2  |1 |
    // |___|__|
    //

    // The basic idea below is to take all quadrant rectangles from the src and transform them into rectangles
    // in the destination. Unfortunately, it seems it is overly complex and could perhaps be simplified.

    nsIntRect srcBufferSpaceBottomRight(bufferRotation.x, bufferRotation.y, bufferRect.width - bufferRotation.x, bufferRect.height - bufferRotation.y);
    nsIntRect srcBufferSpaceTopRight(bufferRotation.x, 0, bufferRect.width - bufferRotation.x, bufferRotation.y);
    nsIntRect srcBufferSpaceTopLeft(0, 0, bufferRotation.x, bufferRotation.y);
    nsIntRect srcBufferSpaceBottomLeft(0, bufferRotation.y, bufferRotation.x, bufferRect.height - bufferRotation.y);

    overlap.IntersectRect(bufferRect, mBufferRect);

    nsIntRect srcRect(overlap), dstRect(overlap);
    srcRect.MoveBy(- bufferRect.TopLeft() + bufferRotation);

    nsIntRect srcRectDrawTopRight(srcRect);
    nsIntRect srcRectDrawTopLeft(srcRect);
    nsIntRect srcRectDrawBottomLeft(srcRect);
    // transform into the different quadrants
    srcRectDrawTopRight  .MoveBy(-nsIntPoint(0, bufferRect.height));
    srcRectDrawTopLeft   .MoveBy(-nsIntPoint(bufferRect.width, bufferRect.height));
    srcRectDrawBottomLeft.MoveBy(-nsIntPoint(bufferRect.width, 0));

    // Intersect with the quadrant
    srcRect               = srcRect              .Intersect(srcBufferSpaceBottomRight);
    srcRectDrawTopRight   = srcRectDrawTopRight  .Intersect(srcBufferSpaceTopRight);
    srcRectDrawTopLeft    = srcRectDrawTopLeft   .Intersect(srcBufferSpaceTopLeft);
    srcRectDrawBottomLeft = srcRectDrawBottomLeft.Intersect(srcBufferSpaceBottomLeft);

    dstRect = srcRect;
    nsIntRect dstRectDrawTopRight(srcRectDrawTopRight);
    nsIntRect dstRectDrawTopLeft(srcRectDrawTopLeft);
    nsIntRect dstRectDrawBottomLeft(srcRectDrawBottomLeft);

    // transform back to src buffer space
    dstRect              .MoveBy(-bufferRotation);
    dstRectDrawTopRight  .MoveBy(-bufferRotation + nsIntPoint(0, bufferRect.height));
    dstRectDrawTopLeft   .MoveBy(-bufferRotation + nsIntPoint(bufferRect.width, bufferRect.height));
    dstRectDrawBottomLeft.MoveBy(-bufferRotation + nsIntPoint(bufferRect.width, 0));

    // transform back to draw coordinates
    dstRect              .MoveBy(bufferRect.TopLeft());
    dstRectDrawTopRight  .MoveBy(bufferRect.TopLeft());
    dstRectDrawTopLeft   .MoveBy(bufferRect.TopLeft());
    dstRectDrawBottomLeft.MoveBy(bufferRect.TopLeft());

    // transform to destBuffer space
    dstRect              .MoveBy(-mBufferRect.TopLeft());
    dstRectDrawTopRight  .MoveBy(-mBufferRect.TopLeft());
    dstRectDrawTopLeft   .MoveBy(-mBufferRect.TopLeft());
    dstRectDrawBottomLeft.MoveBy(-mBufferRect.TopLeft());

    newSource->EnsureBuffer(mBufferRect.Size(),
                           ContentForFormat(aHost->mSource->GetFormat()));

    aHost->mSource->CopyTo(srcRect, newSource, dstRect);
    if (bufferRotation != nsIntPoint(0, 0)) {
      // Draw the remaining quadrants. We call BlitTextureImage 3 extra
      // times instead of doing a single draw call because supporting that
      // with a tiled source is quite tricky.

      if (!srcRectDrawTopRight.IsEmpty())
        aHost->mSource->CopyTo(srcRectDrawTopRight,
                               newSource, dstRectDrawTopRight);
      if (!srcRectDrawTopLeft.IsEmpty())
        aHost->mSource->CopyTo(srcRectDrawTopLeft,
                               newSource, dstRectDrawTopLeft);
      if (!srcRectDrawBottomLeft.IsEmpty())
        aHost->mSource->CopyTo(srcRectDrawBottomLeft,
                               newSource, dstRectDrawBottomLeft);
    }

    if (newSourceOnWhite) {
      newSourceOnWhite->EnsureBuffer(mBufferRect.Size(),
                                    ContentForFormat(aHost->mSourceOnWhite->GetFormat()));
      aHost->mSourceOnWhite->CopyTo(srcRect, newSourceOnWhite, dstRect);
      if (bufferRotation != nsIntPoint(0, 0)) {
        // draw the remaining quadrants
        if (!srcRectDrawTopRight.IsEmpty())
          aHost->mSourceOnWhite->CopyTo(srcRectDrawTopRight,
                                        newSourceOnWhite, dstRectDrawTopRight);
        if (!srcRectDrawTopLeft.IsEmpty())
          aHost->mSourceOnWhite->CopyTo(srcRectDrawTopLeft,
                                        newSourceOnWhite, dstRectDrawTopLeft);
        if (!srcRectDrawBottomLeft.IsEmpty())
          aHost->mSourceOnWhite->CopyTo(srcRectDrawBottomLeft,
                                        newSourceOnWhite, dstRectDrawBottomLeft);
      }
    }
  }

  aHost->mSource = newSource;
  aHost->mSourceOnWhite = newSourceOnWhite;

  aHost->mBufferRect = mBufferRect;
  aHost->mBufferRotation = nsIntPoint();
}