blob: 56a197e74589453803dd62e09479774600a152f7 [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18//
19// Image.cxx
20//
21
22
23#include <stdio.h>
24#include <sys/types.h>
25#include <sys/ipc.h>
26#include <sys/shm.h>
27#include <X11/Xlib.h>
28#include <X11/Xutil.h>
29#include <X11/extensions/XShm.h>
30#include "Image.h"
31#include <list>
32
33class ImageCleanup {
34public:
35 std::list<Image*> images;
36
37 ~ImageCleanup()
38 {
39 fprintf(stderr,"~ImageCleanup called\n");
40
41 while (!images.empty()) {
42 delete images.front();
43 }
44 }
45};
46
47ImageCleanup imageCleanup;
48
49static bool caughtShmError = false;
50
51static int ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error)
52{
53 caughtShmError = true;
54 return 0;
55}
56
57Image::Image(Display* d, int width, int height)
58 : xim(0), dpy(d), shminfo(0), usingShm(false)
59{
60 if (createShmImage(width, height)) return;
61
62 xim = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)),
63 DefaultDepth(dpy,DefaultScreen(dpy)), ZPixmap,
64 0, 0, width, height, BitmapPad(dpy), 0);
65
66 xim->data = (char*)malloc(xim->bytes_per_line * xim->height);
67 if (!xim->data) {
68 fprintf(stderr,"malloc failed\n");
69 exit(1);
70 }
71}
72
73Image::~Image()
74{
75 fprintf(stderr,"~Image called - usingShm %d\n",usingShm);
76 if (usingShm) {
77 usingShm = false;
78 shmdt(shminfo->shmaddr);
79 shmctl(shminfo->shmid, IPC_RMID, 0);
80 imageCleanup.images.remove(this);
81 }
82 delete shminfo;
83 if (xim) XDestroyImage(xim);
84}
85
86void Image::get(Window w)
87{
88 if (usingShm) {
89 XShmGetImage(dpy, w, xim, 0, 0, AllPlanes);
90 } else {
91 XGetSubImage(dpy, w, 0, 0, xim->width, xim->height,
92 AllPlanes, ZPixmap, xim, 0, 0);
93 }
94}
95
96bool Image::createShmImage(int width, int height)
97{
98 if (XShmQueryExtension(dpy)) {
99 shminfo = new XShmSegmentInfo;
100
101 xim = XShmCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)),
102 DefaultDepth(dpy,DefaultScreen(dpy)), ZPixmap,
103 0, shminfo, width, height);
104
105 if (xim) {
106 shminfo->shmid = shmget(IPC_PRIVATE,
107 xim->bytes_per_line * xim->height,
108 IPC_CREAT|0777);
109
110 if (shminfo->shmid != -1) {
111 shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0);
112
113 if (shminfo->shmaddr != (char *)-1) {
114
115 shminfo->readOnly = False;
116
117 XErrorHandler oldHdlr = XSetErrorHandler(ShmCreationXErrorHandler);
118 XShmAttach(dpy, shminfo);
119 XSync(dpy, False);
120 XSetErrorHandler(oldHdlr);
121
122 if (!caughtShmError) {
123 fprintf(stderr,"Using shared memory XImage\n");
124 usingShm = true;
125 imageCleanup.images.push_back(this);
126 return true;
127 }
128
129 shmdt(shminfo->shmaddr);
130 } else {
131 fprintf(stderr,"shmat failed\n");
132 perror("shmat");
133 }
134
135 shmctl(shminfo->shmid, IPC_RMID, 0);
136 } else {
137 fprintf(stderr,"shmget failed\n");
138 perror("shmget");
139 }
140
141 XDestroyImage(xim);
142 xim = 0;
143 } else {
144 fprintf(stderr,"XShmCreateImage failed\n");
145 }
146 }
147
148 return false;
149}