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(); }
static void DrawVelGraph(const nsIntRect& aClipRect, LayerManagerComposite* aManager, Layer* aLayer) { Compositor* compositor = aManager->GetCompositor(); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); TimeStamp now = TimeStamp::Now(); LayerVelocityUserData* velocityData = GetVelocityData(aLayer); if (velocityData->mData.size() >= 1 && now > velocityData->mData[velocityData->mData.size() - 1].mFrameTime + TimeDuration::FromMilliseconds(200)) { // clear stale data velocityData->mData.clear(); } const gfx::Point layerTransform = GetScrollData(aLayer); velocityData->mData.push_back( LayerVelocityUserData::VelocityData(now, static_cast<int>(layerTransform.x), static_cast<int>(layerTransform.y))); // TODO: dump to file // XXX: Uncomment these lines to enable ScrollGraph logging. This is // useful for HVGA phones or to output the data to accurate // graphing software. // printf_stderr("ScrollGraph (%p): %f, %f\n", // aLayer, layerTransform.x, layerTransform.y); // Keep a circular buffer of 100. size_t circularBufferSize = 100; if (velocityData->mData.size() > circularBufferSize) { velocityData->mData.erase(velocityData->mData.begin()); } if (velocityData->mData.size() == 1) { return; } // Clear and disable the graph when it's flat for (size_t i = 1; i < velocityData->mData.size(); i++) { if (velocityData->mData[i - 1].mPoint != velocityData->mData[i].mPoint) { break; } if (i == velocityData->mData.size() - 1) { velocityData->mData.clear(); return; } } if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 || aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) { // Don't want a graph for smaller layers return; } aManager->SetDebugOverlayWantsNextFrame(true); const Matrix4x4& transform = aLayer->GetEffectiveTransform(); nsIntRect bounds = aLayer->GetEffectiveVisibleRegion().GetBounds(); IntSize graphSize = IntSize(200, 100); Rect graphRect = Rect(bounds.x, bounds.y, graphSize.width, graphSize.height); RefPtr<DrawTarget> dt = aManager->CreateDrawTarget(graphSize, SurfaceFormat::B8G8R8A8); dt->FillRect(Rect(0, 0, graphSize.width, graphSize.height), ColorPattern(Color(0.2f,0,0,1))); int yScaleFactor = 3; Point prev = Point(0,0); bool first = true; for (int32_t i = (int32_t)velocityData->mData.size() - 2; i >= 0; i--) { const gfx::Point& p1 = velocityData->mData[i+1].mPoint; const gfx::Point& p2 = velocityData->mData[i].mPoint; int vel = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); Point next = Point(graphRect.width / circularBufferSize * i, graphRect.height - vel/yScaleFactor); if (first) { first = false; } else { dt->StrokeLine(prev, next, ColorPattern(Color(0,1,0,1))); } prev = next; } RefPtr<DataTextureSource> textureSource = compositor->CreateDataTextureSource(); RefPtr<SourceSurface> snapshot = dt->Snapshot(); RefPtr<DataSourceSurface> data = snapshot->GetDataSurface(); textureSource->Update(data); EffectChain effectChain; effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, textureSource, Filter::POINT, true); compositor->DrawQuad(graphRect, clipRect, effectChain, 1.0f, transform); }