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