Memimage* allocmemimage(Rectangle r, ulong chan) { int d; uchar *p; ulong l, nw; Memdata *md; Memimage *i; if((d = chantodepth(chan)) == 0) { werrstr("bad channel descriptor %.8lux", chan); return nil; } l = wordsperline(r, d); nw = l*Dy(r); md = malloc(sizeof(Memdata)); if(md == nil) return nil; md->ref = 1; md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong)); if(md->base == nil){ free(md); return nil; } p = (uchar*)md->base; *(Memdata**)p = md; p += sizeof(Memdata*); *(ulong*)p = getcallerpc(&r); p += sizeof(ulong); /* if this changes, memimagemove must change too */ md->bdata = p; md->allocd = 1; i = allocmemimaged(r, chan, md); if(i == nil){ poolfree(imagmem, md->base); free(md); return nil; } md->imref = i; return i; }
Memsubfont* getmemdefont(void) { char *hdr, *p; int n; Fontchar *fc; Memsubfont *f; int ld; Rectangle r; Memdata *md; Memimage *i; /* * make sure data is word-aligned. this is true with Plan 9 compilers * but not in general. the byte order is right because the data is * declared as char*, not u32int*. */ p = (char*)defontdata; n = (uintptr)p & 3; if(n != 0){ memmove(p+(4-n), p, sizeofdefont-n); p += 4-n; } ld = atoi(p+0*12); r.min.x = atoi(p+1*12); r.min.y = atoi(p+2*12); r.max.x = atoi(p+3*12); r.max.y = atoi(p+4*12); md = mallocz(sizeof(Memdata), 1); if(md == nil) return nil; p += 5*12; md->base = nil; /* so freememimage doesn't free p */ md->bdata = (uchar*)p; /* ick */ md->ref = 1; md->allocd = 1; /* so freememimage does free md */ i = allocmemimaged(r, drawld2chan[ld], md, nil); if(i == nil){ free(md); return nil; } hdr = p+Dy(r)*i->width*sizeof(u32int); n = atoi(hdr); p = hdr+3*12; fc = malloc(sizeof(Fontchar)*(n+1)); if(fc == 0){ freememimage(i); return 0; } _unpackinfo(fc, (uchar*)p, n); f = allocmemsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i); if(f == 0){ freememimage(i); free(fc); return 0; } return f; }
Memimage* memlalloc(Memscreen *s, Rectangle screenr, Refreshfn refreshfn, void *refreshptr, ulong val) { Memlayer *l; Memimage *n; static Memimage *paint; if(paint == nil){ paint = allocmemimage(Rect(0,0,1,1), RGBA32); if(paint == nil) return nil; paint->flags |= Frepl; paint->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); } n = allocmemimaged(screenr, s->image->chan, s->image->data); if(n == nil) return nil; l = malloc(sizeof(Memlayer)); if(l == nil){ free(n); return nil; } l->screen = s; if(refreshfn) l->save = nil; else{ l->save = allocmemimage(screenr, s->image->chan); if(l->save == nil){ free(l); free(n); return nil; } /* allocmemimage doesn't initialize memory; this paints save area */ if(val != DNofill) memfillcolor(l->save, val); } l->refreshfn = refreshfn; l->refreshptr = nil; /* don't set it until we're done */ l->screenr = screenr; l->delta = Pt(0,0); n->data->ref++; n->zero = s->image->zero; n->width = s->image->width; n->layer = l; /* start with new window behind all existing ones */ l->front = s->rearmost; l->rear = nil; if(s->rearmost) s->rearmost->layer->rear = n; s->rearmost = n; if(s->frontmost == nil) s->frontmost = n; l->clear = 0; /* now pull new window to front */ _memltofrontfill(n, val != DNofill); l->refreshptr = refreshptr; /* * paint with requested color; previously exposed areas are already right * if this window has backing store, but just painting the whole thing is simplest. */ if(val != DNofill){ memsetchan(paint, n->chan); memfillcolor(paint, val); memdraw(n, n->r, paint, n->r.min, nil, n->r.min, S); } return n; }
int screensize(int x, int y, int z, uint32_t chan) { Proc *up = externup(); VGAscr *scr; void *oldsoft; lock(&vgascreenlock); if(waserror()){ unlock(&vgascreenlock); nexterror(); } memimageinit(); scr = &vgascreen[0]; oldsoft = softscreen; if(scr->paddr == 0){ int width = (x*z)/BI2WD; void *p; p = malloc(width*BY2WD*y); if(p == nil) error("no memory for vga soft screen"); gscreendata.bdata = softscreen = p; if(scr->dev && scr->dev->page){ scr->vaddr = KADDR(VGAMEM()); scr->apsize = 1<<16; } scr->useflush = 1; } else{ gscreendata.bdata = scr->vaddr; scr->useflush = scr->dev && scr->dev->flush; } scr->gscreen = nil; if(gscreen) freememimage(gscreen); gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata); if(gscreen == nil) error("no memory for vga memimage"); vgaimageinit(chan); scr->palettedepth = 6; /* default */ scr->gscreendata = &gscreendata; scr->memdefont = getmemdefont(); scr->gscreen = gscreen; physgscreenr = gscreen->r; unlock(&vgascreenlock); poperror(); if(oldsoft) free(oldsoft); memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S); flushmemscreen(gscreen->r); if(didswcursorinit) swcursorinit(); drawcmap(); return 0; }