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