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