void nsShmImage::Put(Display* aDisplay, Drawable aWindow, const LayoutDeviceIntRegion& aRegion) { GC gc = XCreateGC(aDisplay, aWindow, 0, nullptr); LayoutDeviceIntRegion bounded; bounded.And(aRegion, LayoutDeviceIntRect(0, 0, mImage->width, mImage->height)); LayoutDeviceIntRegion::RectIterator iter(bounded); for (const LayoutDeviceIntRect *r = iter.Next(); r; r = iter.Next()) { XShmPutImage(aDisplay, aWindow, gc, mImage, r->x, r->y, r->x, r->y, r->width, r->height, False); } XFreeGC(aDisplay, gc); // FIXME/bug 597336: we need to ensure that the shm image isn't // scribbled over before all its pending XShmPutImage()s complete. // However, XSync() is an unnecessarily heavyweight // synchronization mechanism; other options are possible. If this // XSync is shown to hurt responsiveness, we need to explore the // other options. XSync(aDisplay, False); }
void BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, gfx::Rect *aClipRectOut /* = nullptr */, gfx::Rect *aRenderBoundsOut /* = nullptr */) { LayoutDeviceIntRect intRect(LayoutDeviceIntPoint(), mWidget->GetClientSize()); Rect rect = Rect(0, 0, intRect.width, intRect.height); LayoutDeviceIntRegion invalidRegionSafe; if (mDidExternalComposition) { // We do not know rendered region during external composition, just redraw // whole widget. invalidRegionSafe = intRect; mDidExternalComposition = false; } else { // Sometimes the invalid region is larger than we want to draw. invalidRegionSafe.And( LayoutDeviceIntRegion::FromUnknownRegion(aInvalidRegion), intRect); } mInvalidRegion = invalidRegionSafe; mInvalidRect = mInvalidRegion.GetBounds(); if (aRenderBoundsOut) { *aRenderBoundsOut = Rect(); } BufferMode bufferMode = BufferMode::BUFFERED; if (mTarget) { // If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Use a dummy // placeholder so that CreateRenderTarget() works. mDrawTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(); } else { // StartRemoteDrawingInRegion can mutate mInvalidRegion. mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion, &bufferMode); if (!mDrawTarget) { return; } mInvalidRect = mInvalidRegion.GetBounds(); if (mInvalidRect.IsEmpty()) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); return; } } if (!mDrawTarget || mInvalidRect.IsEmpty()) { return; } // Setup an intermediate render target to buffer all compositing. We will // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame() RefPtr<CompositingRenderTarget> target = CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR, bufferMode); if (!target) { if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); } return; } SetRenderTarget(target); // We only allocate a surface sized to the invalidated region, so we need to // translate future coordinates. mRenderTarget->mDrawTarget->SetTransform(Matrix::Translation(-mRenderTarget->GetOrigin())); gfxUtils::ClipToRegion(mRenderTarget->mDrawTarget, mInvalidRegion.ToUnknownRegion()); if (aRenderBoundsOut) { *aRenderBoundsOut = rect; } if (aClipRectIn) { mRenderTarget->mDrawTarget->PushClipRect(*aClipRectIn); } else { mRenderTarget->mDrawTarget->PushClipRect(rect); if (aClipRectOut) { *aClipRectOut = rect; } } }