1*a81c3ea0SDavid du Colombier /*
2*a81c3ea0SDavid du Colombier * radeon frame buffer
3*a81c3ea0SDavid du Colombier * currently use all PMON defaults
4*a81c3ea0SDavid du Colombier */
5*a81c3ea0SDavid du Colombier #include "u.h"
6*a81c3ea0SDavid du Colombier #include "../port/lib.h"
7*a81c3ea0SDavid du Colombier #include "mem.h"
8*a81c3ea0SDavid du Colombier #include "dat.h"
9*a81c3ea0SDavid du Colombier #include "fns.h"
10*a81c3ea0SDavid du Colombier #include "io.h"
11*a81c3ea0SDavid du Colombier
12*a81c3ea0SDavid du Colombier #define Image IMAGE
13*a81c3ea0SDavid du Colombier #include <draw.h>
14*a81c3ea0SDavid du Colombier #include <memdraw.h>
15*a81c3ea0SDavid du Colombier #include <cursor.h>
16*a81c3ea0SDavid du Colombier #include "screen.h"
17*a81c3ea0SDavid du Colombier
18*a81c3ea0SDavid du Colombier enum {
19*a81c3ea0SDavid du Colombier Tabstop = 4,
20*a81c3ea0SDavid du Colombier Scroll = 8,
21*a81c3ea0SDavid du Colombier Wid = 640,
22*a81c3ea0SDavid du Colombier Ht = 480,
23*a81c3ea0SDavid du Colombier Depth = 16,
24*a81c3ea0SDavid du Colombier };
25*a81c3ea0SDavid du Colombier
26*a81c3ea0SDavid du Colombier Cursor arrow = {
27*a81c3ea0SDavid du Colombier { -1, -1 },
28*a81c3ea0SDavid du Colombier { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
29*a81c3ea0SDavid du Colombier 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
30*a81c3ea0SDavid du Colombier 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
31*a81c3ea0SDavid du Colombier 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
32*a81c3ea0SDavid du Colombier },
33*a81c3ea0SDavid du Colombier { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
34*a81c3ea0SDavid du Colombier 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
35*a81c3ea0SDavid du Colombier 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
36*a81c3ea0SDavid du Colombier 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
37*a81c3ea0SDavid du Colombier },
38*a81c3ea0SDavid du Colombier };
39*a81c3ea0SDavid du Colombier
40*a81c3ea0SDavid du Colombier Memimage *gscreen;
41*a81c3ea0SDavid du Colombier
42*a81c3ea0SDavid du Colombier static Memdata xgdata;
43*a81c3ea0SDavid du Colombier
44*a81c3ea0SDavid du Colombier static Memimage xgscreen =
45*a81c3ea0SDavid du Colombier {
46*a81c3ea0SDavid du Colombier { 0, 0, Wid, Ht }, /* r */
47*a81c3ea0SDavid du Colombier { 0, 0, Wid, Ht }, /* clipr */
48*a81c3ea0SDavid du Colombier Depth, /* depth */
49*a81c3ea0SDavid du Colombier 3, /* nchan */
50*a81c3ea0SDavid du Colombier RGB16, /* chan */
51*a81c3ea0SDavid du Colombier nil, /* cmap */
52*a81c3ea0SDavid du Colombier &xgdata, /* data */
53*a81c3ea0SDavid du Colombier 0, /* zero */
54*a81c3ea0SDavid du Colombier 0, /* width in words of a single scan line */
55*a81c3ea0SDavid du Colombier 0, /* layer */
56*a81c3ea0SDavid du Colombier 0, /* flags */
57*a81c3ea0SDavid du Colombier };
58*a81c3ea0SDavid du Colombier
59*a81c3ea0SDavid du Colombier static Memimage *conscol;
60*a81c3ea0SDavid du Colombier static Memimage *back;
61*a81c3ea0SDavid du Colombier static Memsubfont *memdefont;
62*a81c3ea0SDavid du Colombier
63*a81c3ea0SDavid du Colombier static Lock screenlock;
64*a81c3ea0SDavid du Colombier
65*a81c3ea0SDavid du Colombier static Point curpos;
66*a81c3ea0SDavid du Colombier static int h, w;
67*a81c3ea0SDavid du Colombier static Rectangle window;
68*a81c3ea0SDavid du Colombier
69*a81c3ea0SDavid du Colombier int screenwid;
70*a81c3ea0SDavid du Colombier int screenht;
71*a81c3ea0SDavid du Colombier int screendepth;
72*a81c3ea0SDavid du Colombier
73*a81c3ea0SDavid du Colombier /*
74*a81c3ea0SDavid du Colombier * Software cursor.
75*a81c3ea0SDavid du Colombier */
76*a81c3ea0SDavid du Colombier static int swvisible; /* is the cursor visible? */
77*a81c3ea0SDavid du Colombier static int swenabled; /* is the cursor supposed to be on the screen? */
78*a81c3ea0SDavid du Colombier static Memimage *swback; /* screen under cursor */
79*a81c3ea0SDavid du Colombier static Memimage *swimg; /* cursor image */
80*a81c3ea0SDavid du Colombier static Memimage *swmask; /* cursor mask */
81*a81c3ea0SDavid du Colombier static Memimage *swimg1;
82*a81c3ea0SDavid du Colombier static Memimage *swmask1;
83*a81c3ea0SDavid du Colombier
84*a81c3ea0SDavid du Colombier static Point swoffset;
85*a81c3ea0SDavid du Colombier static Rectangle swrect; /* screen rectangle in swback */
86*a81c3ea0SDavid du Colombier static Point swpt; /* desired cursor location */
87*a81c3ea0SDavid du Colombier static Point swvispt; /* actual cursor location */
88*a81c3ea0SDavid du Colombier static int swvers; /* incremented each time cursor image changes */
89*a81c3ea0SDavid du Colombier static int swvisvers; /* the version on the screen */
90*a81c3ea0SDavid du Colombier
91*a81c3ea0SDavid du Colombier /*
92*a81c3ea0SDavid du Colombier * called with drawlock locked for us, most of the time.
93*a81c3ea0SDavid du Colombier * kernel prints at inopportune times might mean we don't
94*a81c3ea0SDavid du Colombier * hold the lock, but memimagedraw is now reentrant so
95*a81c3ea0SDavid du Colombier * that should be okay: worst case we get cursor droppings.
96*a81c3ea0SDavid du Colombier */
97*a81c3ea0SDavid du Colombier static void
swcursorhide(void)98*a81c3ea0SDavid du Colombier swcursorhide(void)
99*a81c3ea0SDavid du Colombier {
100*a81c3ea0SDavid du Colombier if(swvisible == 0)
101*a81c3ea0SDavid du Colombier return;
102*a81c3ea0SDavid du Colombier if(swback == nil)
103*a81c3ea0SDavid du Colombier return;
104*a81c3ea0SDavid du Colombier swvisible = 0;
105*a81c3ea0SDavid du Colombier memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
106*a81c3ea0SDavid du Colombier flushmemscreen(swrect);
107*a81c3ea0SDavid du Colombier }
108*a81c3ea0SDavid du Colombier
109*a81c3ea0SDavid du Colombier static void
swcursoravoid(Rectangle r)110*a81c3ea0SDavid du Colombier swcursoravoid(Rectangle r)
111*a81c3ea0SDavid du Colombier {
112*a81c3ea0SDavid du Colombier if(swvisible && rectXrect(r, swrect))
113*a81c3ea0SDavid du Colombier swcursorhide();
114*a81c3ea0SDavid du Colombier }
115*a81c3ea0SDavid du Colombier
116*a81c3ea0SDavid du Colombier static void
swcursordraw(void)117*a81c3ea0SDavid du Colombier swcursordraw(void)
118*a81c3ea0SDavid du Colombier {
119*a81c3ea0SDavid du Colombier int dounlock;
120*a81c3ea0SDavid du Colombier
121*a81c3ea0SDavid du Colombier if(swvisible)
122*a81c3ea0SDavid du Colombier return;
123*a81c3ea0SDavid du Colombier if(swenabled == 0)
124*a81c3ea0SDavid du Colombier return;
125*a81c3ea0SDavid du Colombier if(swback == nil || swimg1 == nil || swmask1 == nil)
126*a81c3ea0SDavid du Colombier return;
127*a81c3ea0SDavid du Colombier dounlock = canqlock(&drawlock);
128*a81c3ea0SDavid du Colombier swvispt = swpt;
129*a81c3ea0SDavid du Colombier swvisvers = swvers;
130*a81c3ea0SDavid du Colombier swrect = rectaddpt(Rect(0,0,16,16), swvispt);
131*a81c3ea0SDavid du Colombier memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
132*a81c3ea0SDavid du Colombier memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
133*a81c3ea0SDavid du Colombier flushmemscreen(swrect);
134*a81c3ea0SDavid du Colombier swvisible = 1;
135*a81c3ea0SDavid du Colombier if(dounlock)
136*a81c3ea0SDavid du Colombier qunlock(&drawlock);
137*a81c3ea0SDavid du Colombier }
138*a81c3ea0SDavid du Colombier
139*a81c3ea0SDavid du Colombier int
cursoron(int dolock)140*a81c3ea0SDavid du Colombier cursoron(int dolock)
141*a81c3ea0SDavid du Colombier {
142*a81c3ea0SDavid du Colombier int retry;
143*a81c3ea0SDavid du Colombier
144*a81c3ea0SDavid du Colombier if (dolock)
145*a81c3ea0SDavid du Colombier lock(&cursor);
146*a81c3ea0SDavid du Colombier if (canqlock(&drawlock)) {
147*a81c3ea0SDavid du Colombier retry = 0;
148*a81c3ea0SDavid du Colombier swcursorhide();
149*a81c3ea0SDavid du Colombier swcursordraw();
150*a81c3ea0SDavid du Colombier qunlock(&drawlock);
151*a81c3ea0SDavid du Colombier } else
152*a81c3ea0SDavid du Colombier retry = 1;
153*a81c3ea0SDavid du Colombier if (dolock)
154*a81c3ea0SDavid du Colombier unlock(&cursor);
155*a81c3ea0SDavid du Colombier return retry;
156*a81c3ea0SDavid du Colombier }
157*a81c3ea0SDavid du Colombier
158*a81c3ea0SDavid du Colombier void
cursoroff(int dolock)159*a81c3ea0SDavid du Colombier cursoroff(int dolock)
160*a81c3ea0SDavid du Colombier {
161*a81c3ea0SDavid du Colombier if (dolock)
162*a81c3ea0SDavid du Colombier lock(&cursor);
163*a81c3ea0SDavid du Colombier swcursorhide();
164*a81c3ea0SDavid du Colombier if (dolock)
165*a81c3ea0SDavid du Colombier unlock(&cursor);
166*a81c3ea0SDavid du Colombier }
167*a81c3ea0SDavid du Colombier
168*a81c3ea0SDavid du Colombier static void
swload(Cursor * curs)169*a81c3ea0SDavid du Colombier swload(Cursor *curs)
170*a81c3ea0SDavid du Colombier {
171*a81c3ea0SDavid du Colombier uchar *ip, *mp;
172*a81c3ea0SDavid du Colombier int i, j, set, clr;
173*a81c3ea0SDavid du Colombier
174*a81c3ea0SDavid du Colombier if(!swimg || !swmask || !swimg1 || !swmask1)
175*a81c3ea0SDavid du Colombier return;
176*a81c3ea0SDavid du Colombier /*
177*a81c3ea0SDavid du Colombier * Build cursor image and mask.
178*a81c3ea0SDavid du Colombier * Image is just the usual cursor image
179*a81c3ea0SDavid du Colombier * but mask is a transparent alpha mask.
180*a81c3ea0SDavid du Colombier *
181*a81c3ea0SDavid du Colombier * The 16x16x8 memimages do not have
182*a81c3ea0SDavid du Colombier * padding at the end of their scan lines.
183*a81c3ea0SDavid du Colombier */
184*a81c3ea0SDavid du Colombier ip = byteaddr(swimg, ZP);
185*a81c3ea0SDavid du Colombier mp = byteaddr(swmask, ZP);
186*a81c3ea0SDavid du Colombier for(i=0; i<32; i++){
187*a81c3ea0SDavid du Colombier set = curs->set[i];
188*a81c3ea0SDavid du Colombier clr = curs->clr[i];
189*a81c3ea0SDavid du Colombier for(j=0x80; j; j>>=1){
190*a81c3ea0SDavid du Colombier *ip++ = set&j ? 0x00 : 0xFF;
191*a81c3ea0SDavid du Colombier *mp++ = (clr|set)&j ? 0xFF : 0x00;
192*a81c3ea0SDavid du Colombier }
193*a81c3ea0SDavid du Colombier }
194*a81c3ea0SDavid du Colombier swoffset = curs->offset;
195*a81c3ea0SDavid du Colombier swvers++;
196*a81c3ea0SDavid du Colombier memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
197*a81c3ea0SDavid du Colombier memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
198*a81c3ea0SDavid du Colombier }
199*a81c3ea0SDavid du Colombier
200*a81c3ea0SDavid du Colombier /* called from devmouse */
201*a81c3ea0SDavid du Colombier void
setcursor(Cursor * curs)202*a81c3ea0SDavid du Colombier setcursor(Cursor* curs)
203*a81c3ea0SDavid du Colombier {
204*a81c3ea0SDavid du Colombier cursoroff(0);
205*a81c3ea0SDavid du Colombier swload(curs);
206*a81c3ea0SDavid du Colombier cursoron(0);
207*a81c3ea0SDavid du Colombier }
208*a81c3ea0SDavid du Colombier
209*a81c3ea0SDavid du Colombier static int
swmove(Point p)210*a81c3ea0SDavid du Colombier swmove(Point p)
211*a81c3ea0SDavid du Colombier {
212*a81c3ea0SDavid du Colombier swpt = addpt(p, swoffset);
213*a81c3ea0SDavid du Colombier return 0;
214*a81c3ea0SDavid du Colombier }
215*a81c3ea0SDavid du Colombier
216*a81c3ea0SDavid du Colombier static void
swcursorclock(void)217*a81c3ea0SDavid du Colombier swcursorclock(void)
218*a81c3ea0SDavid du Colombier {
219*a81c3ea0SDavid du Colombier int x;
220*a81c3ea0SDavid du Colombier
221*a81c3ea0SDavid du Colombier if(!swenabled)
222*a81c3ea0SDavid du Colombier return;
223*a81c3ea0SDavid du Colombier swmove(mousexy());
224*a81c3ea0SDavid du Colombier if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
225*a81c3ea0SDavid du Colombier return;
226*a81c3ea0SDavid du Colombier
227*a81c3ea0SDavid du Colombier x = splhi();
228*a81c3ea0SDavid du Colombier if(swenabled)
229*a81c3ea0SDavid du Colombier if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
230*a81c3ea0SDavid du Colombier if(canqlock(&drawlock)){
231*a81c3ea0SDavid du Colombier swcursorhide();
232*a81c3ea0SDavid du Colombier swcursordraw();
233*a81c3ea0SDavid du Colombier qunlock(&drawlock);
234*a81c3ea0SDavid du Colombier }
235*a81c3ea0SDavid du Colombier splx(x);
236*a81c3ea0SDavid du Colombier }
237*a81c3ea0SDavid du Colombier
238*a81c3ea0SDavid du Colombier void
swcursorinit(void)239*a81c3ea0SDavid du Colombier swcursorinit(void)
240*a81c3ea0SDavid du Colombier {
241*a81c3ea0SDavid du Colombier static int init;
242*a81c3ea0SDavid du Colombier
243*a81c3ea0SDavid du Colombier if(!init){
244*a81c3ea0SDavid du Colombier init = 1;
245*a81c3ea0SDavid du Colombier addclock0link(swcursorclock, 10);
246*a81c3ea0SDavid du Colombier swenabled = 1;
247*a81c3ea0SDavid du Colombier }
248*a81c3ea0SDavid du Colombier if(swback){
249*a81c3ea0SDavid du Colombier freememimage(swback);
250*a81c3ea0SDavid du Colombier freememimage(swmask);
251*a81c3ea0SDavid du Colombier freememimage(swmask1);
252*a81c3ea0SDavid du Colombier freememimage(swimg);
253*a81c3ea0SDavid du Colombier freememimage(swimg1);
254*a81c3ea0SDavid du Colombier }
255*a81c3ea0SDavid du Colombier
256*a81c3ea0SDavid du Colombier swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
257*a81c3ea0SDavid du Colombier swmask = allocmemimage(Rect(0,0,16,16), GREY8);
258*a81c3ea0SDavid du Colombier swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
259*a81c3ea0SDavid du Colombier swimg = allocmemimage(Rect(0,0,16,16), GREY8);
260*a81c3ea0SDavid du Colombier swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
261*a81c3ea0SDavid du Colombier if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
262*a81c3ea0SDavid du Colombier print("software cursor: allocmemimage fails\n");
263*a81c3ea0SDavid du Colombier return;
264*a81c3ea0SDavid du Colombier }
265*a81c3ea0SDavid du Colombier
266*a81c3ea0SDavid du Colombier memfillcolor(swmask, DOpaque);
267*a81c3ea0SDavid du Colombier memfillcolor(swmask1, DOpaque);
268*a81c3ea0SDavid du Colombier memfillcolor(swimg, DBlack);
269*a81c3ea0SDavid du Colombier memfillcolor(swimg1, DBlack);
270*a81c3ea0SDavid du Colombier }
271*a81c3ea0SDavid du Colombier
272*a81c3ea0SDavid du Colombier static int
screensize(void)273*a81c3ea0SDavid du Colombier screensize(void)
274*a81c3ea0SDavid du Colombier {
275*a81c3ea0SDavid du Colombier char *p;
276*a81c3ea0SDavid du Colombier char *f[3];
277*a81c3ea0SDavid du Colombier int width, height, depth;
278*a81c3ea0SDavid du Colombier
279*a81c3ea0SDavid du Colombier p = getconf("vgasize");
280*a81c3ea0SDavid du Colombier if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) ||
281*a81c3ea0SDavid du Colombier (width = atoi(f[0])) < 16 || (height = atoi(f[1])) <= 0 ||
282*a81c3ea0SDavid du Colombier (depth = atoi(f[2])) <= 0) {
283*a81c3ea0SDavid du Colombier width = screenwid? screenwid: Wid;
284*a81c3ea0SDavid du Colombier height = screenht? screenht: Ht;
285*a81c3ea0SDavid du Colombier depth = screendepth? screendepth: Depth;
286*a81c3ea0SDavid du Colombier }
287*a81c3ea0SDavid du Colombier
288*a81c3ea0SDavid du Colombier xgscreen.r.max = Pt(width, height);
289*a81c3ea0SDavid du Colombier xgscreen.depth = depth;
290*a81c3ea0SDavid du Colombier return 0;
291*a81c3ea0SDavid du Colombier }
292*a81c3ea0SDavid du Colombier
293*a81c3ea0SDavid du Colombier void
flushmemscreen(Rectangle)294*a81c3ea0SDavid du Colombier flushmemscreen(Rectangle)
295*a81c3ea0SDavid du Colombier {
296*a81c3ea0SDavid du Colombier }
297*a81c3ea0SDavid du Colombier
298*a81c3ea0SDavid du Colombier static void
screenwin(void)299*a81c3ea0SDavid du Colombier screenwin(void)
300*a81c3ea0SDavid du Colombier {
301*a81c3ea0SDavid du Colombier char *greet;
302*a81c3ea0SDavid du Colombier Memimage *orange;
303*a81c3ea0SDavid du Colombier Point p, q;
304*a81c3ea0SDavid du Colombier Rectangle r;
305*a81c3ea0SDavid du Colombier
306*a81c3ea0SDavid du Colombier back = memwhite;
307*a81c3ea0SDavid du Colombier conscol = memblack;
308*a81c3ea0SDavid du Colombier
309*a81c3ea0SDavid du Colombier orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
310*a81c3ea0SDavid du Colombier orange->flags |= Frepl;
311*a81c3ea0SDavid du Colombier orange->clipr = gscreen->r;
312*a81c3ea0SDavid du Colombier orange->data->bdata[0] = 0x40; /* magic: colour? */
313*a81c3ea0SDavid du Colombier orange->data->bdata[1] = 0xfd; /* magic: colour? */
314*a81c3ea0SDavid du Colombier
315*a81c3ea0SDavid du Colombier w = memdefont->info[' '].width;
316*a81c3ea0SDavid du Colombier h = memdefont->height;
317*a81c3ea0SDavid du Colombier
318*a81c3ea0SDavid du Colombier r = insetrect(gscreen->r, 0);
319*a81c3ea0SDavid du Colombier
320*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
321*a81c3ea0SDavid du Colombier window = insetrect(r, 0);
322*a81c3ea0SDavid du Colombier memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
323*a81c3ea0SDavid du Colombier
324*a81c3ea0SDavid du Colombier memimagedraw(gscreen, Rect(window.min.x, window.min.y,
325*a81c3ea0SDavid du Colombier window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
326*a81c3ea0SDavid du Colombier freememimage(orange);
327*a81c3ea0SDavid du Colombier window = insetrect(window, 5);
328*a81c3ea0SDavid du Colombier
329*a81c3ea0SDavid du Colombier greet = " Plan 9 Console ";
330*a81c3ea0SDavid du Colombier p = addpt(window.min, Pt(10, 0));
331*a81c3ea0SDavid du Colombier q = memsubfontwidth(memdefont, greet);
332*a81c3ea0SDavid du Colombier memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
333*a81c3ea0SDavid du Colombier flushmemscreen(r);
334*a81c3ea0SDavid du Colombier window.min.y += h + 6;
335*a81c3ea0SDavid du Colombier curpos = window.min;
336*a81c3ea0SDavid du Colombier window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
337*a81c3ea0SDavid du Colombier }
338*a81c3ea0SDavid du Colombier
339*a81c3ea0SDavid du Colombier static void
scroll(void)340*a81c3ea0SDavid du Colombier scroll(void)
341*a81c3ea0SDavid du Colombier {
342*a81c3ea0SDavid du Colombier int o;
343*a81c3ea0SDavid du Colombier Point p;
344*a81c3ea0SDavid du Colombier Rectangle r;
345*a81c3ea0SDavid du Colombier
346*a81c3ea0SDavid du Colombier o = Scroll*h;
347*a81c3ea0SDavid du Colombier r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
348*a81c3ea0SDavid du Colombier p = Pt(window.min.x, window.min.y+o);
349*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, gscreen, p, nil, p, S);
350*a81c3ea0SDavid du Colombier flushmemscreen(r);
351*a81c3ea0SDavid du Colombier r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
352*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
353*a81c3ea0SDavid du Colombier flushmemscreen(r);
354*a81c3ea0SDavid du Colombier
355*a81c3ea0SDavid du Colombier curpos.y -= o;
356*a81c3ea0SDavid du Colombier }
357*a81c3ea0SDavid du Colombier
358*a81c3ea0SDavid du Colombier static void
screenputc(char * buf)359*a81c3ea0SDavid du Colombier screenputc(char *buf)
360*a81c3ea0SDavid du Colombier {
361*a81c3ea0SDavid du Colombier int w;
362*a81c3ea0SDavid du Colombier uint pos;
363*a81c3ea0SDavid du Colombier Point p;
364*a81c3ea0SDavid du Colombier Rectangle r;
365*a81c3ea0SDavid du Colombier static int *xp;
366*a81c3ea0SDavid du Colombier static int xbuf[256];
367*a81c3ea0SDavid du Colombier
368*a81c3ea0SDavid du Colombier if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
369*a81c3ea0SDavid du Colombier xp = xbuf;
370*a81c3ea0SDavid du Colombier
371*a81c3ea0SDavid du Colombier switch (buf[0]) {
372*a81c3ea0SDavid du Colombier case '\n':
373*a81c3ea0SDavid du Colombier if (curpos.y + h >= window.max.y)
374*a81c3ea0SDavid du Colombier scroll();
375*a81c3ea0SDavid du Colombier curpos.y += h;
376*a81c3ea0SDavid du Colombier screenputc("\r");
377*a81c3ea0SDavid du Colombier break;
378*a81c3ea0SDavid du Colombier case '\r':
379*a81c3ea0SDavid du Colombier xp = xbuf;
380*a81c3ea0SDavid du Colombier curpos.x = window.min.x;
381*a81c3ea0SDavid du Colombier break;
382*a81c3ea0SDavid du Colombier case '\t':
383*a81c3ea0SDavid du Colombier p = memsubfontwidth(memdefont, " ");
384*a81c3ea0SDavid du Colombier w = p.x;
385*a81c3ea0SDavid du Colombier if (curpos.x >= window.max.x - Tabstop * w)
386*a81c3ea0SDavid du Colombier screenputc("\n");
387*a81c3ea0SDavid du Colombier
388*a81c3ea0SDavid du Colombier pos = (curpos.x - window.min.x) / w;
389*a81c3ea0SDavid du Colombier pos = Tabstop - pos % Tabstop;
390*a81c3ea0SDavid du Colombier *xp++ = curpos.x;
391*a81c3ea0SDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
392*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
393*a81c3ea0SDavid du Colombier flushmemscreen(r);
394*a81c3ea0SDavid du Colombier curpos.x += pos * w;
395*a81c3ea0SDavid du Colombier break;
396*a81c3ea0SDavid du Colombier case '\b':
397*a81c3ea0SDavid du Colombier if (xp <= xbuf)
398*a81c3ea0SDavid du Colombier break;
399*a81c3ea0SDavid du Colombier xp--;
400*a81c3ea0SDavid du Colombier r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
401*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
402*a81c3ea0SDavid du Colombier flushmemscreen(r);
403*a81c3ea0SDavid du Colombier curpos.x = *xp;
404*a81c3ea0SDavid du Colombier break;
405*a81c3ea0SDavid du Colombier case '\0':
406*a81c3ea0SDavid du Colombier break;
407*a81c3ea0SDavid du Colombier default:
408*a81c3ea0SDavid du Colombier p = memsubfontwidth(memdefont, buf);
409*a81c3ea0SDavid du Colombier w = p.x;
410*a81c3ea0SDavid du Colombier
411*a81c3ea0SDavid du Colombier if (curpos.x >= window.max.x - w)
412*a81c3ea0SDavid du Colombier screenputc("\n");
413*a81c3ea0SDavid du Colombier
414*a81c3ea0SDavid du Colombier *xp++ = curpos.x;
415*a81c3ea0SDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
416*a81c3ea0SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
417*a81c3ea0SDavid du Colombier memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
418*a81c3ea0SDavid du Colombier flushmemscreen(r);
419*a81c3ea0SDavid du Colombier curpos.x += w;
420*a81c3ea0SDavid du Colombier break;
421*a81c3ea0SDavid du Colombier }
422*a81c3ea0SDavid du Colombier }
423*a81c3ea0SDavid du Colombier
424*a81c3ea0SDavid du Colombier static void
myscreenputs(char * s,int n)425*a81c3ea0SDavid du Colombier myscreenputs(char *s, int n)
426*a81c3ea0SDavid du Colombier {
427*a81c3ea0SDavid du Colombier int i;
428*a81c3ea0SDavid du Colombier Rune r;
429*a81c3ea0SDavid du Colombier char buf[4];
430*a81c3ea0SDavid du Colombier
431*a81c3ea0SDavid du Colombier if(!islo()) {
432*a81c3ea0SDavid du Colombier /* don't deadlock trying to print in interrupt */
433*a81c3ea0SDavid du Colombier if(!canlock(&screenlock))
434*a81c3ea0SDavid du Colombier return;
435*a81c3ea0SDavid du Colombier }
436*a81c3ea0SDavid du Colombier else
437*a81c3ea0SDavid du Colombier lock(&screenlock);
438*a81c3ea0SDavid du Colombier
439*a81c3ea0SDavid du Colombier while(n > 0){
440*a81c3ea0SDavid du Colombier i = chartorune(&r, s);
441*a81c3ea0SDavid du Colombier if(i == 0){
442*a81c3ea0SDavid du Colombier s++;
443*a81c3ea0SDavid du Colombier --n;
444*a81c3ea0SDavid du Colombier continue;
445*a81c3ea0SDavid du Colombier }
446*a81c3ea0SDavid du Colombier memmove(buf, s, i);
447*a81c3ea0SDavid du Colombier buf[i] = 0;
448*a81c3ea0SDavid du Colombier n -= i;
449*a81c3ea0SDavid du Colombier s += i;
450*a81c3ea0SDavid du Colombier screenputc(buf);
451*a81c3ea0SDavid du Colombier }
452*a81c3ea0SDavid du Colombier unlock(&screenlock);
453*a81c3ea0SDavid du Colombier }
454*a81c3ea0SDavid du Colombier
455*a81c3ea0SDavid du Colombier void
screeninit(void)456*a81c3ea0SDavid du Colombier screeninit(void)
457*a81c3ea0SDavid du Colombier {
458*a81c3ea0SDavid du Colombier ulong chan;
459*a81c3ea0SDavid du Colombier uchar *fb;
460*a81c3ea0SDavid du Colombier
461*a81c3ea0SDavid du Colombier screensize();
462*a81c3ea0SDavid du Colombier fb = (uchar*)fbinit();
463*a81c3ea0SDavid du Colombier if(fb == nil){
464*a81c3ea0SDavid du Colombier print("can't initialise %dx%dx%d framebuffer \n",
465*a81c3ea0SDavid du Colombier xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
466*a81c3ea0SDavid du Colombier return;
467*a81c3ea0SDavid du Colombier }
468*a81c3ea0SDavid du Colombier
469*a81c3ea0SDavid du Colombier xgscreen.clipr = xgscreen.r;
470*a81c3ea0SDavid du Colombier switch(xgscreen.depth){
471*a81c3ea0SDavid du Colombier default:
472*a81c3ea0SDavid du Colombier print("unsupported screen depth %d\n", xgscreen.depth);
473*a81c3ea0SDavid du Colombier xgscreen.depth = 16;
474*a81c3ea0SDavid du Colombier /* fall through */
475*a81c3ea0SDavid du Colombier case 16:
476*a81c3ea0SDavid du Colombier chan = RGB16;
477*a81c3ea0SDavid du Colombier break;
478*a81c3ea0SDavid du Colombier case 24:
479*a81c3ea0SDavid du Colombier chan = BGR24;
480*a81c3ea0SDavid du Colombier break;
481*a81c3ea0SDavid du Colombier case 32:
482*a81c3ea0SDavid du Colombier chan = ARGB32;
483*a81c3ea0SDavid du Colombier break;
484*a81c3ea0SDavid du Colombier }
485*a81c3ea0SDavid du Colombier memsetchan(&xgscreen, chan);
486*a81c3ea0SDavid du Colombier conf.monitor = 1;
487*a81c3ea0SDavid du Colombier xgdata.bdata = fb;
488*a81c3ea0SDavid du Colombier xgdata.ref = 1;
489*a81c3ea0SDavid du Colombier gscreen = &xgscreen;
490*a81c3ea0SDavid du Colombier gscreen->width = wordsperline(gscreen->r, gscreen->depth);
491*a81c3ea0SDavid du Colombier
492*a81c3ea0SDavid du Colombier memimageinit();
493*a81c3ea0SDavid du Colombier memdefont = getmemdefont();
494*a81c3ea0SDavid du Colombier screenwin();
495*a81c3ea0SDavid du Colombier screenputs = myscreenputs;
496*a81c3ea0SDavid du Colombier }
497*a81c3ea0SDavid du Colombier
498*a81c3ea0SDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)499*a81c3ea0SDavid du Colombier attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
500*a81c3ea0SDavid du Colombier {
501*a81c3ea0SDavid du Colombier *r = gscreen->r;
502*a81c3ea0SDavid du Colombier *d = gscreen->depth;
503*a81c3ea0SDavid du Colombier *chan = gscreen->chan;
504*a81c3ea0SDavid du Colombier *width = gscreen->width;
505*a81c3ea0SDavid du Colombier *softscreen = 0;
506*a81c3ea0SDavid du Colombier
507*a81c3ea0SDavid du Colombier return gscreen->data->bdata;
508*a81c3ea0SDavid du Colombier }
509*a81c3ea0SDavid du Colombier
510*a81c3ea0SDavid du Colombier void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)511*a81c3ea0SDavid du Colombier getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
512*a81c3ea0SDavid du Colombier {
513*a81c3ea0SDavid du Colombier USED(p, pr, pg, pb);
514*a81c3ea0SDavid du Colombier }
515*a81c3ea0SDavid du Colombier
516*a81c3ea0SDavid du Colombier int
setcolor(ulong p,ulong r,ulong g,ulong b)517*a81c3ea0SDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b)
518*a81c3ea0SDavid du Colombier {
519*a81c3ea0SDavid du Colombier USED(p, r, g, b);
520*a81c3ea0SDavid du Colombier return 0;
521*a81c3ea0SDavid du Colombier }
522*a81c3ea0SDavid du Colombier
523*a81c3ea0SDavid du Colombier void
blankscreen(int blank)524*a81c3ea0SDavid du Colombier blankscreen(int blank)
525*a81c3ea0SDavid du Colombier {
526*a81c3ea0SDavid du Colombier USED(blank);
527*a81c3ea0SDavid du Colombier }
528*a81c3ea0SDavid du Colombier
529*a81c3ea0SDavid du Colombier int
hwdraw(Memdrawparam * par)530*a81c3ea0SDavid du Colombier hwdraw(Memdrawparam *par)
531*a81c3ea0SDavid du Colombier {
532*a81c3ea0SDavid du Colombier Memimage *dst, *src, *mask;
533*a81c3ea0SDavid du Colombier
534*a81c3ea0SDavid du Colombier if((dst=par->dst) == nil || dst->data == nil)
535*a81c3ea0SDavid du Colombier return 0;
536*a81c3ea0SDavid du Colombier if((src=par->src) == nil || src->data == nil)
537*a81c3ea0SDavid du Colombier return 0;
538*a81c3ea0SDavid du Colombier if((mask=par->mask) == nil || mask->data == nil)
539*a81c3ea0SDavid du Colombier return 0;
540*a81c3ea0SDavid du Colombier
541*a81c3ea0SDavid du Colombier if(dst->data->bdata == xgdata.bdata)
542*a81c3ea0SDavid du Colombier swcursoravoid(par->r);
543*a81c3ea0SDavid du Colombier if(src->data->bdata == xgdata.bdata)
544*a81c3ea0SDavid du Colombier swcursoravoid(par->sr);
545*a81c3ea0SDavid du Colombier if(mask->data->bdata == xgdata.bdata)
546*a81c3ea0SDavid du Colombier swcursoravoid(par->mr);
547*a81c3ea0SDavid du Colombier
548*a81c3ea0SDavid du Colombier return 0;
549*a81c3ea0SDavid du Colombier }
550*a81c3ea0SDavid du Colombier
551*a81c3ea0SDavid du Colombier /* radeon frame buffer control */
552*a81c3ea0SDavid du Colombier typedef struct Ctlr {
553*a81c3ea0SDavid du Colombier Pcidev* pcidev;
554*a81c3ea0SDavid du Colombier int port;
555*a81c3ea0SDavid du Colombier void* mmio;
556*a81c3ea0SDavid du Colombier ulong paddr;
557*a81c3ea0SDavid du Colombier void* vaddr;
558*a81c3ea0SDavid du Colombier } Ctlr;
559*a81c3ea0SDavid du Colombier
560*a81c3ea0SDavid du Colombier static Ctlr *ctlr;
561*a81c3ea0SDavid du Colombier
562*a81c3ea0SDavid du Colombier static Pcidev*
videopci(void)563*a81c3ea0SDavid du Colombier videopci(void)
564*a81c3ea0SDavid du Colombier {
565*a81c3ea0SDavid du Colombier static Pcidev *p = nil;
566*a81c3ea0SDavid du Colombier
567*a81c3ea0SDavid du Colombier while((p = pcimatch(p, 0, 0)) != nil){
568*a81c3ea0SDavid du Colombier if(p->ccrb != Pcibcdisp || p->ccru != 0)
569*a81c3ea0SDavid du Colombier continue;
570*a81c3ea0SDavid du Colombier return p;
571*a81c3ea0SDavid du Colombier }
572*a81c3ea0SDavid du Colombier return nil;
573*a81c3ea0SDavid du Colombier }
574*a81c3ea0SDavid du Colombier
575*a81c3ea0SDavid du Colombier static void
fbenable(void)576*a81c3ea0SDavid du Colombier fbenable(void)
577*a81c3ea0SDavid du Colombier {
578*a81c3ea0SDavid du Colombier Pcidev *p;
579*a81c3ea0SDavid du Colombier
580*a81c3ea0SDavid du Colombier if(ctlr)
581*a81c3ea0SDavid du Colombier return;
582*a81c3ea0SDavid du Colombier p = videopci();
583*a81c3ea0SDavid du Colombier if(p == nil)
584*a81c3ea0SDavid du Colombier return;
585*a81c3ea0SDavid du Colombier ctlr = malloc(sizeof(Ctlr));
586*a81c3ea0SDavid du Colombier ctlr->pcidev = p;
587*a81c3ea0SDavid du Colombier ctlr->paddr = PCIMEMADDR(p->mem[0].bar & ~0x0f);
588*a81c3ea0SDavid du Colombier ctlr->vaddr = KSEG1ADDR(ctlr->paddr);
589*a81c3ea0SDavid du Colombier ctlr->port = p->mem[1].bar & ~0x01;
590*a81c3ea0SDavid du Colombier ctlr->mmio = KSEG1ADDR(PCIMEMADDR(p->mem[2].bar & ~0x0f));
591*a81c3ea0SDavid du Colombier }
592*a81c3ea0SDavid du Colombier
593*a81c3ea0SDavid du Colombier void*
fbinit(void)594*a81c3ea0SDavid du Colombier fbinit(void)
595*a81c3ea0SDavid du Colombier {
596*a81c3ea0SDavid du Colombier if(!ctlr)
597*a81c3ea0SDavid du Colombier fbenable();
598*a81c3ea0SDavid du Colombier
599*a81c3ea0SDavid du Colombier if(!ctlr)
600*a81c3ea0SDavid du Colombier return nil;
601*a81c3ea0SDavid du Colombier else
602*a81c3ea0SDavid du Colombier return ctlr->vaddr;
603*a81c3ea0SDavid du Colombier }
604