]> git.tdb.fi Git - libs/gui.git/blob - source/graphics/x11/drawcontext.cpp
Split platform-specific parts into separate directories
[libs/gui.git] / source / graphics / x11 / drawcontext.cpp
1 #include <stdexcept>
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 #include "display_private.h"
8 #include "drawcontext.h"
9 #include "window_private.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace Graphics {
15
16 struct DrawContext::Private
17 {
18         XImage *image;
19         bool use_shm;
20         XShmSegmentInfo shminfo;
21 };
22
23 DrawContext::DrawContext(Window &w):
24         display(w.get_display()),
25         window(w),
26         priv(new Private)
27 {
28         DisplayHandle dpy = display.get_private().display;
29
30         priv->use_shm = XShmQueryExtension(dpy);
31
32         XWindowAttributes wa;
33         XGetWindowAttributes(dpy, window.get_private().window, &wa);
34
35         if(priv->use_shm)
36         {
37                 priv->image = XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &priv->shminfo, wa.width, wa.height);
38                 if(!priv->image)
39                         throw runtime_error("XShmCreateImage");
40
41                 priv->shminfo.shmid = shmget(IPC_PRIVATE, priv->image->bytes_per_line*priv->image->height, IPC_CREAT|0666);
42                 priv->shminfo.shmaddr=priv->image->data = reinterpret_cast<char *>(shmat(priv->shminfo.shmid, 0, 0));
43                 priv->shminfo.readOnly = false;
44
45                 XShmAttach(dpy, &priv->shminfo);
46
47                 XSync(dpy, false);
48                 display.check_error();
49         }
50         else
51         {
52                 priv->image = XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
53                 if(!priv->image)
54                         throw runtime_error("XCreateImage");
55                 priv->image->data = new char[priv->image->bytes_per_line*priv->image->height];
56         }
57 }
58
59 DrawContext::~DrawContext()
60 {
61         if(priv->use_shm)
62         {
63                 XShmDetach(display.get_private().display, &priv->shminfo);
64                 shmdt(priv->shminfo.shmaddr);
65                 shmctl(priv->shminfo.shmid, IPC_RMID, 0);
66         }
67
68         XDestroyImage(priv->image);
69
70         delete priv;
71 }
72
73 unsigned DrawContext::get_depth() const
74 {
75         return priv->image->bits_per_pixel;
76 }
77
78 unsigned char *DrawContext::get_data()
79 {
80         return reinterpret_cast<unsigned char *>(priv->image->data);
81 }
82
83 void DrawContext::update()
84 {
85         DisplayHandle dpy = display.get_private().display;
86         WindowHandle wnd = window.get_private().window;
87
88         GC gc = XCreateGC(dpy, wnd, 0, 0);
89
90         if(priv->use_shm)
91                 XShmPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height, false);
92         else
93                 XPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height);
94
95         XFreeGC(dpy, gc);
96 }
97
98 } // namespace Graphics
99 } // namespace Msp