]> git.tdb.fi Git - libs/gui.git/blob - source/gbase/drawcontext.cpp
03965671306f5f7224f920e9a414abb4a06f126a
[libs/gui.git] / source / gbase / drawcontext.cpp
1 #include <stdexcept>
2 #ifndef WIN32
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <X11/Xlib.h>
6 #include <X11/extensions/XShm.h>
7 #include <X11/Xutil.h>
8 #endif
9 #include "display.h"
10 #include "drawcontext.h"
11 #include "window.h"
12 #include "display_priv.h"
13
14 using namespace std;
15
16 namespace Msp {
17 namespace Graphics {
18
19 struct DrawContext::Private
20 {
21 #ifndef WIN32
22         XImage *image;
23         bool use_shm;
24         XShmSegmentInfo shminfo;
25 #endif
26 };
27
28 DrawContext::DrawContext(Window &w):
29         display(w.get_display()),
30         window(w)
31 {
32 #ifdef WIN32
33         throw runtime_error("no DrawContext support on windows");
34 #else
35         priv = new Private;
36
37         ::Display *dpy = display.get_private().display;
38
39         priv->use_shm = XShmQueryExtension(dpy);
40
41         XWindowAttributes wa;
42         XGetWindowAttributes(dpy, window.get_private().window, &wa);
43
44         if(priv->use_shm)
45         {
46                 priv->image = XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &priv->shminfo, wa.width, wa.height);
47                 if(!priv->image)
48                         throw runtime_error("XShmCreateImage");
49
50                 priv->shminfo.shmid = shmget(IPC_PRIVATE, priv->image->bytes_per_line*priv->image->height, IPC_CREAT|0666);
51                 priv->shminfo.shmaddr=priv->image->data = reinterpret_cast<char *>(shmat(priv->shminfo.shmid, 0, 0));
52                 priv->shminfo.readOnly = false;
53
54                 XShmAttach(dpy, &priv->shminfo);
55
56                 XSync(dpy, false);
57                 display.check_error();
58         }
59         else
60         {
61                 priv->image = XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
62                 if(!priv->image)
63                         throw runtime_error("XCreateImage");
64                 priv->image->data = new char[priv->image->bytes_per_line*priv->image->height];
65         }
66 #endif
67 }
68
69 DrawContext::~DrawContext()
70 {
71 #ifndef WIN32
72         if(priv->use_shm)
73         {
74                 XShmDetach(display.get_private().display, &priv->shminfo);
75                 shmdt(priv->shminfo.shmaddr);
76                 shmctl(priv->shminfo.shmid, IPC_RMID, 0);
77         }
78
79         XDestroyImage(priv->image);
80 #endif
81
82         delete priv;
83 }
84
85 unsigned DrawContext::get_depth() const
86 {
87 #ifdef WIN32
88         return 0;
89 #else
90         return priv->image->bits_per_pixel;
91 #endif
92 }
93
94 unsigned char *DrawContext::get_data()
95 {
96 #ifdef WIN32
97         return 0;
98 #else
99         return reinterpret_cast<unsigned char *>(priv->image->data);
100 #endif
101 }
102
103 void DrawContext::update()
104 {
105 #ifndef WIN32
106         ::Display *dpy = display.get_private().display;
107         WindowHandle wnd = window.get_private().window;
108
109         GC gc = XCreateGC(dpy, wnd, 0, 0);
110
111         if(priv->use_shm)
112                 XShmPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height, false);
113         else
114                 XPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height);
115
116         XFreeGC(dpy, gc);
117 #endif
118 }
119
120 } // namespace Graphics
121 } // namespace Msp