CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / src / shared / nsShmImage.cpp
blobd3ad64f196f0284d01a944c56faa7fa03dd0094d
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is the Mozilla browser.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Chris Jones <jones.chris.g@gmail.com>
25 * Oleg Romashin <romaxa@gmail.com>
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.
39 * ***** END LICENSE BLOCK ***** */
41 #if defined(MOZ_WIDGET_GTK2)
42 #include <gtk/gtk.h>
43 #include <gdk/gdkx.h>
44 #elif defined(MOZ_WIDGET_QT)
45 #include <QWidget>
46 #endif
48 #include "nsShmImage.h"
49 #include "gfxPlatform.h"
50 #include "gfxImageSurface.h"
52 #ifdef MOZ_HAVE_SHMIMAGE
54 using namespace mozilla::ipc;
56 // If XShm isn't available to our client, we'll try XShm once, fail,
57 // set this to false and then never try again.
58 static PRBool gShmAvailable = PR_TRUE;
59 PRBool nsShmImage::UseShm()
61 return gfxPlatform::GetPlatform()->
62 ScreenReferenceSurface()->GetType() == gfxASurface::SurfaceTypeImage
63 && gShmAvailable;
66 already_AddRefed<nsShmImage>
67 nsShmImage::Create(const gfxIntSize& aSize,
68 Visual* aVisual, unsigned int aDepth)
70 Display* dpy = DISPLAY();
72 nsRefPtr<nsShmImage> shm = new nsShmImage();
73 shm->mImage = XShmCreateImage(dpy, aVisual, aDepth,
74 ZPixmap, nsnull,
75 &(shm->mInfo),
76 aSize.width, aSize.height);
77 if (!shm->mImage) {
78 return nsnull;
81 size_t size = SharedMemory::PageAlignedSize(
82 shm->mImage->bytes_per_line * shm->mImage->height);
83 shm->mSegment = new SharedMemorySysV();
84 if (!shm->mSegment->Create(size) || !shm->mSegment->Map(size)) {
85 return nsnull;
88 shm->mInfo.shmid = shm->mSegment->GetHandle();
89 shm->mInfo.shmaddr =
90 shm->mImage->data = static_cast<char*>(shm->mSegment->memory());
91 shm->mInfo.readOnly = False;
93 int xerror = 0;
94 #if defined(MOZ_WIDGET_GTK2)
95 gdk_error_trap_push();
96 Status attachOk = XShmAttach(dpy, &shm->mInfo);
97 xerror = gdk_error_trap_pop();
98 #elif defined(MOZ_WIDGET_QT)
99 Status attachOk = XShmAttach(dpy, &shm->mInfo);
100 #endif
102 if (!attachOk || xerror) {
103 // Assume XShm isn't available, and don't attempt to use it
104 // again.
105 gShmAvailable = PR_FALSE;
106 return nsnull;
109 shm->mXAttached = PR_TRUE;
110 shm->mSize = aSize;
111 switch (shm->mImage->depth) {
112 case 24:
113 // Only xRGB is supported.
114 if ((shm->mImage->red_mask == 0xff0000) &&
115 (shm->mImage->green_mask == 0xff00) &&
116 (shm->mImage->blue_mask == 0xff)) {
117 shm->mFormat = gfxASurface::ImageFormatRGB24;
118 break;
120 goto unsupported;
121 case 16:
122 shm->mFormat = gfxASurface::ImageFormatRGB16_565; break;
123 unsupported:
124 default:
125 NS_WARNING("Unsupported XShm Image format!");
126 gShmAvailable = PR_FALSE;
127 return nsnull;
129 return shm.forget();
132 already_AddRefed<gfxASurface>
133 nsShmImage::AsSurface()
135 return nsRefPtr<gfxASurface>(
136 new gfxImageSurface(static_cast<unsigned char*>(mSegment->memory()),
137 mSize,
138 mImage->bytes_per_line,
139 mFormat)
140 ).forget();
143 #if defined(MOZ_WIDGET_GTK2)
144 void
145 nsShmImage::Put(GdkWindow* aWindow, GdkRectangle* aRects, GdkRectangle* aEnd)
147 GdkDrawable* gd;
148 gint dx, dy;
149 gdk_window_get_internal_paint_info(aWindow, &gd, &dx, &dy);
151 Display* dpy = gdk_x11_get_default_xdisplay();
152 Drawable d = GDK_DRAWABLE_XID(gd);
154 GC gc = XCreateGC(dpy, d, 0, nsnull);
155 for (GdkRectangle* r = aRects; r < aEnd; r++) {
156 XShmPutImage(dpy, d, gc, mImage,
157 r->x, r->y,
158 r->x - dx, r->y - dy,
159 r->width, r->height,
160 False);
162 XFreeGC(dpy, gc);
164 #ifdef MOZ_WIDGET_GTK2
165 // FIXME/bug 597336: we need to ensure that the shm image isn't
166 // scribbled over before all its pending XShmPutImage()s complete.
167 // However, XSync() is an unnecessarily heavyweight
168 // synchronization mechanism; other options are possible. If this
169 // XSync is shown to hurt responsiveness, we need to explore the
170 // other options.
171 XSync(dpy, False);
172 #endif
174 #elif defined(MOZ_WIDGET_QT)
175 void
176 nsShmImage::Put(QWidget* aWindow, QRect& aRect)
178 Display* dpy = aWindow->x11Info().display();
179 Drawable d = aWindow->handle();
181 GC gc = XCreateGC(dpy, d, 0, nsnull);
182 // Avoid out of bounds painting
183 QRect inter = aRect.intersected(aWindow->rect());
184 XShmPutImage(dpy, d, gc, mImage,
185 inter.x(), inter.y(),
186 inter.x(), inter.y(),
187 inter.width(), inter.height(),
188 False);
189 XFreeGC(dpy, gc);
191 #endif
193 already_AddRefed<gfxASurface>
194 nsShmImage::EnsureShmImage(const gfxIntSize& aSize, Visual* aVisual, unsigned int aDepth,
195 nsRefPtr<nsShmImage>& aImage)
197 if (!aImage || aImage->Size() != aSize) {
198 // Because we XSync() after XShmAttach() to trap errors, we
199 // know that the X server has the old image's memory mapped
200 // into its address space, so it's OK to destroy the old image
201 // here even if there are outstanding Puts. The Detach is
202 // ordered after the Puts.
203 aImage = nsShmImage::Create(aSize, aVisual, aDepth);
205 return !aImage ? nsnull : aImage->AsSurface();
208 #endif // defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)