+/* $Id$
+
+This file is part of libmspgbase
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef WIN32
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xutil.h>
+#endif
+#include <msp/core/except.h>
+#include "display.h"
+#include "drawcontext.h"
+#include "window.h"
+
+namespace Msp {
+namespace Graphics {
+
+DrawContext::DrawContext(Window &w):
+ display(w.get_display()),
+ window(w),
+ image(0)
+{
+#ifndef WIN32
+ ::Display *dpy=display.get_display();
+
+ use_shm=false; XShmQueryExtension(dpy);
+
+ XWindowAttributes wa;
+ XGetWindowAttributes(dpy, window.get_handle(), &wa);
+
+ if(use_shm)
+ {
+ image=XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &shminfo, wa.width, wa.height);
+ if(!image)
+ throw Exception("Could not create shared memory XImage");
+
+ shminfo.shmid=shmget(IPC_PRIVATE, image->bytes_per_line*image->height, IPC_CREAT|0666);
+ shminfo.shmaddr=image->data=reinterpret_cast<char *>(shmat(shminfo.shmid, 0, 0));
+ shminfo.readOnly=false;
+
+ XShmAttach(dpy, &shminfo);
+
+ XSync(dpy, false);
+ display.check_error();
+ }
+ else
+ {
+ image=XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
+ if(!image)
+ throw Exception("Could not create XImage");
+ image->data=new char[image->bytes_per_line*image->height];
+ }
+#endif
+}
+
+DrawContext::~DrawContext()
+{
+#ifndef WIN32
+ if(use_shm)
+ {
+ XShmDetach(display.get_display(), &shminfo);
+ shmdt(shminfo.shmaddr);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ }
+
+ XDestroyImage(image);
+#endif
+}
+
+void DrawContext::update()
+{
+#ifndef WIN32
+ ::Display *dpy=display.get_display();
+
+ GC gc=XCreateGC(dpy, window.get_handle(), 0, 0);
+
+ if(use_shm)
+ XShmPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height, false);
+ else
+ XPutImage(dpy, window.get_handle(), gc, image, 0, 0, 0, 0, image->width, image->height);
+
+ XFreeGC(dpy, gc);
+#endif
+}
+
+} // namespace Graphics
+} // namespace Msp