1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at:
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * The Mozilla Foundation
21 : * Portions created by the Initial Developer are Copyright (C) 2010
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Chris Jones <jones.chris.g@gmail.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "mozilla/layers/PLayers.h"
42 : #include "mozilla/layers/ShadowLayers.h"
43 :
44 : #include "gfxPlatform.h"
45 :
46 : #include "gfxXlibSurface.h"
47 : #include "mozilla/X11Util.h"
48 : #include "cairo-xlib.h"
49 :
50 : namespace mozilla {
51 : namespace layers {
52 :
53 : // Return true if we're likely compositing using X and so should use
54 : // Xlib surfaces in shadow layers.
55 : static bool
56 0 : UsingXCompositing()
57 : {
58 : return (gfxASurface::SurfaceTypeXlib ==
59 0 : gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType());
60 : }
61 :
62 : // LookReturn a pointer to |aFormat| that lives in the Xrender library.
63 : // All code using render formats assumes it doesn't need to copy.
64 : static XRenderPictFormat*
65 0 : GetXRenderPictFormatFromId(Display* aDisplay, PictFormat aFormatId)
66 : {
67 : XRenderPictFormat tmplate;
68 0 : tmplate.id = aFormatId;
69 0 : return XRenderFindFormat(aDisplay, PictFormatID, &tmplate, 0);
70 : }
71 :
72 : static bool
73 0 : TakeAndDestroyXlibSurface(SurfaceDescriptor* aSurface)
74 : {
75 : nsRefPtr<gfxXlibSurface> surf =
76 0 : aSurface->get_SurfaceDescriptorX11().OpenForeign();
77 0 : surf->TakePixmap();
78 0 : *aSurface = SurfaceDescriptor();
79 : // the Pixmap is destroyed when |surf| goes out of scope
80 0 : return true;
81 : }
82 :
83 0 : SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
84 0 : : mId(aSurf->XDrawable())
85 0 : , mSize(aSurf->GetSize())
86 : {
87 0 : const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
88 0 : if (pictFormat) {
89 0 : mFormat = pictFormat->id;
90 : } else {
91 0 : mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid;
92 : }
93 0 : }
94 :
95 0 : SurfaceDescriptorX11::SurfaceDescriptorX11(Drawable aDrawable, XID aFormatID,
96 : const gfxIntSize& aSize)
97 : : mId(aDrawable)
98 : , mFormat(aFormatID)
99 0 : , mSize(aSize)
100 0 : { }
101 :
102 : already_AddRefed<gfxXlibSurface>
103 0 : SurfaceDescriptorX11::OpenForeign() const
104 : {
105 0 : Display* display = DefaultXDisplay();
106 0 : Screen* screen = DefaultScreenOfDisplay(display);
107 :
108 0 : nsRefPtr<gfxXlibSurface> surf;
109 0 : XRenderPictFormat* pictFormat = GetXRenderPictFormatFromId(display, mFormat);
110 0 : if (pictFormat) {
111 0 : surf = new gfxXlibSurface(screen, mId, pictFormat, mSize);
112 : } else {
113 0 : Visual* visual = NULL;
114 : unsigned int depth;
115 0 : XVisualIDToInfo(display, mFormat, &visual, &depth);
116 0 : if (!visual)
117 0 : return nsnull;
118 :
119 0 : surf = new gfxXlibSurface(display, mId, visual, mSize);
120 : }
121 0 : return surf->CairoStatus() ? nsnull : surf.forget();
122 : }
123 :
124 : bool
125 0 : ShadowLayerForwarder::PlatformAllocDoubleBuffer(const gfxIntSize& aSize,
126 : gfxASurface::gfxContentType aContent,
127 : SurfaceDescriptor* aFrontBuffer,
128 : SurfaceDescriptor* aBackBuffer)
129 : {
130 0 : return (PlatformAllocBuffer(aSize, aContent, aFrontBuffer) &&
131 0 : PlatformAllocBuffer(aSize, aContent, aBackBuffer));
132 : }
133 :
134 : bool
135 0 : ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize& aSize,
136 : gfxASurface::gfxContentType aContent,
137 : SurfaceDescriptor* aBuffer)
138 : {
139 0 : if (!UsingXCompositing()) {
140 : // If we're not using X compositing, we're probably compositing on
141 : // the client side, in which case X surfaces would just slow
142 : // things down. Use Shmem instead.
143 0 : return false;
144 : }
145 :
146 0 : gfxPlatform* platform = gfxPlatform::GetPlatform();
147 0 : nsRefPtr<gfxASurface> buffer = platform->CreateOffscreenSurface(aSize, aContent);
148 0 : if (!buffer ||
149 0 : buffer->GetType() != gfxASurface::SurfaceTypeXlib) {
150 0 : NS_ERROR("creating Xlib front/back surfaces failed!");
151 0 : return false;
152 : }
153 :
154 0 : gfxXlibSurface* bufferX = static_cast<gfxXlibSurface*>(buffer.get());
155 : // Release Pixmap ownership to the layers model
156 0 : bufferX->ReleasePixmap();
157 :
158 0 : *aBuffer = SurfaceDescriptorX11(bufferX);
159 0 : return true;
160 : }
161 :
162 : /*static*/ already_AddRefed<gfxASurface>
163 0 : ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor& aSurface)
164 : {
165 0 : if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface.type()) {
166 0 : return nsnull;
167 : }
168 0 : return aSurface.get_SurfaceDescriptorX11().OpenForeign();
169 : }
170 :
171 : bool
172 0 : ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
173 : {
174 0 : if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
175 0 : return false;
176 : }
177 0 : return TakeAndDestroyXlibSurface(aSurface);
178 : }
179 :
180 : /*static*/ void
181 0 : ShadowLayerForwarder::PlatformSyncBeforeUpdate()
182 : {
183 0 : if (UsingXCompositing()) {
184 : // If we're using X surfaces, then we need to finish all pending
185 : // operations on the back buffers before handing them to the
186 : // parent, otherwise the surface might be used by the parent's
187 : // Display in between two operations queued by our Display.
188 0 : XSync(DefaultXDisplay(), False);
189 : }
190 0 : }
191 :
192 : /*static*/ void
193 0 : ShadowLayerManager::PlatformSyncBeforeReplyUpdate()
194 : {
195 0 : if (UsingXCompositing()) {
196 : // If we're using X surfaces, we need to finish all pending
197 : // operations on the *front buffers* before handing them back to
198 : // the child, even though they will be read operations.
199 : // Otherwise, the child might start scribbling on new back buffers
200 : // that are still participating in requests as old front buffers.
201 0 : XSync(DefaultXDisplay(), False);
202 : }
203 0 : }
204 :
205 : bool
206 0 : ShadowLayerManager::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
207 : {
208 0 : if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
209 0 : return false;
210 : }
211 0 : return TakeAndDestroyXlibSurface(aSurface);
212 : }
213 :
214 : } // namespace layers
215 : } // namespace mozilla
|