changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: devvga: properly handle physical screen size and panning

changeset 6244: 7cdbac004f34
parent 6243: fb452c44205d
child 6245: 6153167c7bd4
author: cinap_lenrek@felloff.net
date: Sun, 03 Dec 2017 18:54:25 +0100
files: sys/src/9/pc/devvga.c sys/src/9/pc/vga.c
description: devvga: properly handle physical screen size and panning

- remove arbitrary limits on screen size, just check with badrect()
- post resize when physgscreenr is changed (actualsize ctl command)
- preserve physgscreenr across softscreen flag toggle
- honor panning flag on resize
- fix nil dereference in panning ctl command when scr->gscreen == nil
- use clipr when drawing vga plan 9 console (vgascreenwin())
     1.1--- a/sys/src/9/pc/devvga.c
     1.2+++ b/sys/src/9/pc/devvga.c
     1.3@@ -212,11 +212,13 @@ vgaread(Chan* c, void* a, long n, vlong 
     1.4 }
     1.5 
     1.6 static char Ebusy[] = "vga already configured";
     1.7+static char Enoscreen[] = "set the screen size first";
     1.8 
     1.9 static void
    1.10 vgactl(Cmdbuf *cb)
    1.11 {
    1.12 	int align, i, size, x, y, z;
    1.13+	Rectangle r;
    1.14 	char *chanstr, *p;
    1.15 	ulong chan;
    1.16 	Cmdtab *ct;
    1.17@@ -229,8 +231,7 @@ vgactl(Cmdbuf *cb)
    1.18 	switch(ct->index){
    1.19 	case CMhwgc:
    1.20 		if(scr->gscreen == nil)
    1.21-			error("hwgc: no gscreen");
    1.22-
    1.23+			error(Enoscreen);
    1.24 		if(strcmp(cb->f[1], "off") == 0){
    1.25 			lock(&cursor);
    1.26 			if(scr->cur){
    1.27@@ -305,26 +306,19 @@ vgactl(Cmdbuf *cb)
    1.28 
    1.29 	case CMsize:
    1.30 		x = strtoul(cb->f[1], &p, 0);
    1.31-		if(x == 0 || x > 10240)
    1.32-			error(Ebadarg);
    1.33 		if(*p)
    1.34 			p++;
    1.35-
    1.36 		y = strtoul(p, &p, 0);
    1.37-		if(y == 0 || y > 10240)
    1.38-			error(Ebadarg);
    1.39 		if(*p)
    1.40 			p++;
    1.41-
    1.42 		z = strtoul(p, &p, 0);
    1.43-
    1.44+		if(badrect(Rect(0,0,x,y)))
    1.45+			error(Ebadarg);
    1.46 		chanstr = cb->f[2];
    1.47 		if((chan = strtochan(chanstr)) == 0)
    1.48 			error("bad channel");
    1.49-
    1.50 		if(chantodepth(chan) != z)
    1.51 			error("depth, channel do not match");
    1.52-
    1.53 		cursoroff();
    1.54 		deletescreenimage();
    1.55 		if(screensize(x, y, z, chan))
    1.56@@ -334,30 +328,25 @@ vgactl(Cmdbuf *cb)
    1.57 
    1.58 	case CMactualsize:
    1.59 		if(scr->gscreen == nil)
    1.60-			error("set the screen size first");
    1.61-
    1.62+			error(Enoscreen);
    1.63 		x = strtoul(cb->f[1], &p, 0);
    1.64-		if(x == 0 || x > 2048)
    1.65-			error(Ebadarg);
    1.66 		if(*p)
    1.67 			p++;
    1.68-
    1.69 		y = strtoul(p, nil, 0);
    1.70-		if(y == 0 || y > 2048)
    1.71+		r = Rect(0,0,x,y);
    1.72+		if(badrect(r))
    1.73 			error(Ebadarg);
    1.74-
    1.75-		if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
    1.76+		if(!rectinrect(r, scr->gscreen->r))
    1.77 			error("physical screen bigger than virtual");
    1.78-
    1.79-		physgscreenr = Rect(0,0,x,y);
    1.80-		scr->gscreen->clipr = physgscreenr;
    1.81-		return;
    1.82+		cursoroff();
    1.83+		deletescreenimage();
    1.84+		physgscreenr = r;
    1.85+		goto Resized;
    1.86 	
    1.87 	case CMpalettedepth:
    1.88 		x = strtoul(cb->f[1], &p, 0);
    1.89 		if(x != 8 && x != 6)
    1.90 			error(Ebadarg);
    1.91-
    1.92 		scr->palettedepth = x;
    1.93 		return;
    1.94 
    1.95@@ -370,6 +359,7 @@ vgactl(Cmdbuf *cb)
    1.96 			break;
    1.97 		if(scr->gscreen == nil)
    1.98 			return;
    1.99+		r = physgscreenr;
   1.100 		x = scr->gscreen->r.max.x;
   1.101 		y = scr->gscreen->r.max.y;
   1.102 		z = scr->gscreen->depth;
   1.103@@ -378,14 +368,17 @@ vgactl(Cmdbuf *cb)
   1.104 		deletescreenimage();
   1.105 		if(screensize(x, y, z, chan))
   1.106 			error(Egreg);
   1.107+		physgscreenr = r;
   1.108 		/* no break */
   1.109 	case CMdrawinit:
   1.110 		if(scr->gscreen == nil)
   1.111-			error("drawinit: no gscreen");
   1.112+			error(Enoscreen);
   1.113 		if(scr->dev && scr->dev->drawinit)
   1.114 			scr->dev->drawinit(scr);
   1.115 		hwblank = scr->blank != nil;
   1.116 		hwaccel = scr->fill != nil || scr->scroll != nil;
   1.117+	Resized:
   1.118+		scr->gscreen->clipr = panning ? scr->gscreen->r : physgscreenr;
   1.119 		vgascreenwin(scr);
   1.120 		resetscreenimage();
   1.121 		cursoron();
   1.122@@ -405,19 +398,21 @@ vgactl(Cmdbuf *cb)
   1.123 
   1.124 	case CMpanning:
   1.125 		if(strcmp(cb->f[1], "on") == 0){
   1.126-			if(scr == nil || scr->cur == nil)
   1.127-				error("set screen first");
   1.128+			if(scr->cur == nil)
   1.129+				error("set cursor first");
   1.130 			if(!scr->cur->doespanning)
   1.131 				error("panning not supported");
   1.132-			scr->gscreen->clipr = scr->gscreen->r;
   1.133 			panning = 1;
   1.134 		}
   1.135 		else if(strcmp(cb->f[1], "off") == 0){
   1.136-			scr->gscreen->clipr = physgscreenr;
   1.137 			panning = 0;
   1.138 		}else
   1.139 			break;
   1.140-		return;
   1.141+		if(scr->gscreen == nil)
   1.142+			return;
   1.143+		cursoroff();
   1.144+		deletescreenimage();
   1.145+		goto Resized;
   1.146 
   1.147 	case CMhwaccel:
   1.148 		if(strcmp(cb->f[1], "on") == 0)
     2.1--- a/sys/src/9/pc/vga.c
     2.2+++ b/sys/src/9/pc/vga.c
     2.3@@ -193,6 +193,7 @@ vgascreenwin(VGAscr* scr)
     2.4 		freememimage(i);
     2.5 	}
     2.6 
     2.7+	r = scr->gscreen->clipr;
     2.8 	window = insetrect(r, 20);
     2.9 	memimagedraw(scr->gscreen, window, conscol, ZP, memopaque, ZP, S);
    2.10 	window = insetrect(window, 4);