summaryrefslogtreecommitdiff
path: root/sys/src/cmd/unix/drawterm/gui-x11/alloc.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/unix/drawterm/gui-x11/alloc.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/unix/drawterm/gui-x11/alloc.c')
-rwxr-xr-xsys/src/cmd/unix/drawterm/gui-x11/alloc.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/sys/src/cmd/unix/drawterm/gui-x11/alloc.c b/sys/src/cmd/unix/drawterm/gui-x11/alloc.c
new file mode 100755
index 000000000..8053c4488
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/gui-x11/alloc.c
@@ -0,0 +1,204 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include "xmem.h"
+
+/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
+#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
+
+Memimage*
+xallocmemimage(Rectangle r, ulong chan, int pmid)
+{
+ Memimage *m;
+ Xmem *xm;
+ XImage *xi;
+ int offset;
+ int d;
+
+ m = _allocmemimage(r, chan);
+ if(chan != GREY1 && chan != xscreenchan)
+ return m;
+
+ d = m->depth;
+ xm = mallocz(sizeof(Xmem), 1);
+ if(pmid != PMundef)
+ xm->pmid = pmid;
+ else
+ xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
+
+ if(m->depth == 24)
+ offset = r.min.x&(4-1);
+ else
+ offset = r.min.x&(31/m->depth);
+ r.min.x -= offset;
+
+ assert(wordsperline(r, m->depth) <= m->width);
+
+ xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
+ (char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
+
+ if(xi == nil){
+ _freememimage(m);
+ return nil;
+ }
+
+ xm->xi = xi;
+ xm->pc = getcallerpc(&r);
+ xm->r = r;
+
+ /*
+ * Set the parameters of the XImage so its memory looks exactly like a
+ * Memimage, so we can call _memimagedraw on the same data. All frame
+ * buffers we've seen, and Plan 9's graphics code, require big-endian
+ * bits within bytes, but little endian byte order within pixels.
+ */
+ xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
+ xi->byte_order = LSBFirst;
+ xi->bitmap_bit_order = MSBFirst;
+ xi->bitmap_pad = 32;
+ xm->r = Rect(0,0,0,0);
+ XInitImage(xi);
+ XFlush(xdisplay);
+
+ m->X = xm;
+ return m;
+}
+
+Memimage*
+allocmemimage(Rectangle r, ulong chan)
+{
+ return xallocmemimage(r, chan, PMundef);
+}
+
+void
+freememimage(Memimage *m)
+{
+ Xmem *xm;
+
+ if(m == nil)
+ return;
+
+ if(m->data->ref == 1){
+ if((xm = m->X) != nil){
+ if(xm->xi){
+ xm->xi->data = nil;
+ XFree(xm->xi);
+ }
+ XFreePixmap(xdisplay, xm->pmid);
+ free(xm);
+ m->X = nil;
+ }
+ }
+ _freememimage(m);
+}
+
+void
+memfillcolor(Memimage *m, ulong val)
+{
+ _memfillcolor(m, val);
+ if(m->X){
+ if((val & 0xFF) == 0xFF)
+ xfillcolor(m, m->r, _rgbatoimg(m, val));
+ else
+ putXdata(m, m->r);
+ }
+}
+
+static void
+addrect(Rectangle *rp, Rectangle r)
+{
+ if(rp->min.x >= rp->max.x)
+ *rp = r;
+ else
+ combinerect(rp, r);
+}
+
+XImage*
+getXdata(Memimage *m, Rectangle r)
+{
+ uchar *p;
+ int x, y;
+ Xmem *xm;
+ Point xdelta, delta;
+ Point tp;
+
+ xm = m->X;
+ if(xm == nil)
+ return nil;
+
+ assert(xm != nil && xm->xi != nil);
+
+ if(xm->dirty == 0)
+ return xm->xi;
+
+ r = xm->dirtyr;
+ if(Dx(r)==0 || Dy(r)==0)
+ return xm->xi;
+
+ delta = subpt(r.min, m->r.min);
+ tp = xm->r.min; /* avoid unaligned access on digital unix */
+ xdelta = subpt(r.min, tp);
+
+ XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
+ AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
+
+ if(xtblbit && m->chan == CMAP8)
+ for(y=r.min.y; y<r.max.y; y++)
+ for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+ *p = x11toplan9[*p];
+
+ xm->dirty = 0;
+ xm->dirtyr = Rect(0,0,0,0);
+ return xm->xi;
+}
+
+void
+putXdata(Memimage *m, Rectangle r)
+{
+ Xmem *xm;
+ XImage *xi;
+ GC g;
+ Point xdelta, delta;
+ Point tp;
+ int x, y;
+ uchar *p;
+
+ xm = m->X;
+ if(xm == nil)
+ return;
+
+ assert(xm != nil);
+ assert(xm->xi != nil);
+
+ xi = xm->xi;
+
+ g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
+
+ delta = subpt(r.min, m->r.min);
+ tp = xm->r.min; /* avoid unaligned access on digital unix */
+ xdelta = subpt(r.min, tp);
+
+ if(xtblbit && m->chan == CMAP8)
+ for(y=r.min.y; y<r.max.y; y++)
+ for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+ *p = plan9tox11[*p];
+
+ XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
+
+ if(xtblbit && m->chan == CMAP8)
+ for(y=r.min.y; y<r.max.y; y++)
+ for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
+ *p = x11toplan9[*p];
+}
+
+void
+dirtyXdata(Memimage *m, Rectangle r)
+{
+ Xmem *xm;
+
+ if((xm = m->X) != nil){
+ xm->dirty = 1;
+ addrect(&xm->dirtyr, r);
+ }
+}