1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "WindowSurfaceXRender.h"
8 
9 #include "mozilla/gfx/2D.h"
10 #include "mozilla/gfx/Types.h"
11 #include "gfxPlatform.h"
12 
13 namespace mozilla {
14 namespace widget {
15 
WindowSurfaceXRender(Display * aDisplay,Window aWindow,Visual * aVisual,unsigned int aDepth)16 WindowSurfaceXRender::WindowSurfaceXRender(Display* aDisplay, Window aWindow,
17                                            Visual* aVisual, unsigned int aDepth)
18     : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth),
19       mXlibSurface(nullptr),
20       mGC(X11None) {}
21 
~WindowSurfaceXRender()22 WindowSurfaceXRender::~WindowSurfaceXRender() {
23   if (mGC != X11None) {
24     XFreeGC(mDisplay, mGC);
25   }
26 }
27 
Lock(const LayoutDeviceIntRegion & aRegion)28 already_AddRefed<gfx::DrawTarget> WindowSurfaceXRender::Lock(
29     const LayoutDeviceIntRegion& aRegion) {
30   gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
31   gfx::IntSize size(bounds.XMost(), bounds.YMost());
32   if (!mXlibSurface || mXlibSurface->CairoStatus() ||
33       !(size <= mXlibSurface->GetSize())) {
34     mXlibSurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(mDisplay),
35                                           mVisual, size, mWindow);
36   }
37   if (!mXlibSurface || mXlibSurface->CairoStatus()) {
38     return nullptr;
39   }
40 
41   return gfxPlatform::CreateDrawTargetForSurface(mXlibSurface, size);
42 }
43 
Commit(const LayoutDeviceIntRegion & aInvalidRegion)44 void WindowSurfaceXRender::Commit(const LayoutDeviceIntRegion& aInvalidRegion) {
45   AutoTArray<XRectangle, 32> xrects;
46   xrects.SetCapacity(aInvalidRegion.GetNumRects());
47 
48   for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
49     const LayoutDeviceIntRect& r = iter.Get();
50     XRectangle xrect = {(short)r.x, (short)r.y, (unsigned short)r.width,
51                         (unsigned short)r.height};
52     xrects.AppendElement(xrect);
53   }
54 
55   if (!mGC) {
56     mGC = XCreateGC(mDisplay, mWindow, 0, nullptr);
57     if (!mGC) {
58       NS_WARNING("Couldn't create X11 graphics context for window!");
59       return;
60     }
61   }
62 
63   XSetClipRectangles(mDisplay, mGC, 0, 0, xrects.Elements(), xrects.Length(),
64                      YXBanded);
65 
66   MOZ_ASSERT(mXlibSurface && mXlibSurface->CairoStatus() == 0,
67              "Attempted to commit invalid surface!");
68   gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
69   gfx::IntSize size(bounds.XMost(), bounds.YMost());
70   XCopyArea(mDisplay, mXlibSurface->XDrawable(), mWindow, mGC, bounds.x,
71             bounds.y, size.width, size.height, bounds.x, bounds.y);
72 }
73 
74 }  // namespace widget
75 }  // namespace mozilla
76