cbscreen.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "ureg.h"
  16. #include "../port/error.h"
  17. #define Image IMAGE
  18. #include <draw.h>
  19. #include <memdraw.h>
  20. #include <cursor.h>
  21. #include "screen.h"
  22. #define RGB2K(r, g, b) ((156763 * (r) + 307758 * (g) + 59769 * (b)) >> 19)
  23. Point ZP = {0, 0};
  24. Rectangle physgscreenr;
  25. Memdata gscreendata;
  26. Memimage *gscreen;
  27. VGAscr vgascreen[1];
  28. Cursor arrow = {
  29. {-1, -1},
  30. {
  31. 0xFF,
  32. 0xFF,
  33. 0x80,
  34. 0x01,
  35. 0x80,
  36. 0x02,
  37. 0x80,
  38. 0x0C,
  39. 0x80,
  40. 0x10,
  41. 0x80,
  42. 0x10,
  43. 0x80,
  44. 0x08,
  45. 0x80,
  46. 0x04,
  47. 0x80,
  48. 0x02,
  49. 0x80,
  50. 0x01,
  51. 0x80,
  52. 0x02,
  53. 0x8C,
  54. 0x04,
  55. 0x92,
  56. 0x08,
  57. 0x91,
  58. 0x10,
  59. 0xA0,
  60. 0xA0,
  61. 0xC0,
  62. 0x40,
  63. },
  64. {
  65. 0x00,
  66. 0x00,
  67. 0x7F,
  68. 0xFE,
  69. 0x7F,
  70. 0xFC,
  71. 0x7F,
  72. 0xF0,
  73. 0x7F,
  74. 0xE0,
  75. 0x7F,
  76. 0xE0,
  77. 0x7F,
  78. 0xF0,
  79. 0x7F,
  80. 0xF8,
  81. 0x7F,
  82. 0xFC,
  83. 0x7F,
  84. 0xFE,
  85. 0x7F,
  86. 0xFC,
  87. 0x73,
  88. 0xF8,
  89. 0x61,
  90. 0xF0,
  91. 0x60,
  92. 0xE0,
  93. 0x40,
  94. 0x40,
  95. 0x00,
  96. 0x00,
  97. },
  98. };
  99. int didswcursorinit;
  100. static void *softscreen;
  101. int
  102. screensize(int x, int y, int z, uint32_t chan)
  103. {
  104. Proc *up = externup();
  105. VGAscr *scr;
  106. void *oldsoft;
  107. lock(&vgascreenlock);
  108. if(waserror()){
  109. unlock(&vgascreenlock);
  110. nexterror();
  111. }
  112. memimageinit();
  113. scr = &vgascreen[0];
  114. oldsoft = softscreen;
  115. if(scr->paddr == 0){
  116. int width = (x * z) / BI2WD;
  117. void *p;
  118. error("Can't do this");
  119. p = malloc(width * BY2WD * y);
  120. if(p == nil)
  121. error("no memory for vga soft screen");
  122. gscreendata.bdata = softscreen = p;
  123. if(scr->dev && scr->dev->page){
  124. scr->vaddr = KADDR(VGAMEM());
  125. scr->apsize = 1 << 16;
  126. }
  127. scr->useflush = 1;
  128. } else {
  129. gscreendata.bdata = scr->vaddr;
  130. scr->useflush = scr->dev && scr->dev->flush;
  131. }
  132. scr->gscreen = nil;
  133. if(gscreen)
  134. freememimage(gscreen);
  135. gscreen = allocmemimaged(Rect(0, 0, x, y), chan, &gscreendata);
  136. if(gscreen == nil)
  137. error("no memory for vga memimage");
  138. vgaimageinit(chan);
  139. scr->palettedepth = 6; /* default */
  140. scr->gscreendata = &gscreendata;
  141. scr->memdefont = getmemdefont();
  142. scr->gscreen = gscreen;
  143. physgscreenr = gscreen->r;
  144. unlock(&vgascreenlock);
  145. poperror();
  146. if(oldsoft)
  147. free(oldsoft);
  148. memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S);
  149. flushmemscreen(gscreen->r);
  150. if(didswcursorinit)
  151. swcursorinit();
  152. drawcmap();
  153. return 0;
  154. }
  155. int
  156. screenaperture(int size, int align)
  157. {
  158. VGAscr *scr;
  159. scr = &vgascreen[0];
  160. if(scr->paddr) /* set up during enable */
  161. return 0;
  162. error("can't do this");
  163. if(size == 0)
  164. return 0;
  165. if(scr->dev && scr->dev->linear){
  166. scr->dev->linear(scr, size, align);
  167. return 0;
  168. }
  169. /*
  170. * Need to allocate some physical address space.
  171. * The driver will tell the card to use it.
  172. */
  173. size = ROUNDUP(sizeof(size), 4 * KiB);
  174. scr->paddr = (uint64_t)malloc(size);
  175. if(scr->paddr == 0)
  176. return -1;
  177. scr->vaddr = vmap(scr->paddr, size);
  178. if(scr->vaddr == nil)
  179. return -1;
  180. scr->apsize = size;
  181. return 0;
  182. }
  183. unsigned char *
  184. attachscreen(Rectangle *r, uint32_t *chan, int *d, int *width, int *softscreen)
  185. {
  186. VGAscr *scr;
  187. scr = &vgascreen[0];
  188. if(scr->gscreen == nil || scr->gscreendata == nil)
  189. return nil;
  190. *r = scr->gscreen->clipr;
  191. *chan = scr->gscreen->chan;
  192. *d = scr->gscreen->depth;
  193. *width = scr->gscreen->width;
  194. *softscreen = scr->useflush;
  195. return scr->gscreendata->bdata;
  196. }
  197. /*
  198. * It would be fair to say that this doesn't work for >8-bit screens.
  199. */
  200. void
  201. flushmemscreen(Rectangle r)
  202. {
  203. VGAscr *scr;
  204. unsigned char *sp, *disp, *sdisp, *edisp;
  205. int y, len, incs, off, page;
  206. scr = &vgascreen[0];
  207. if(scr->dev && scr->dev->flush){
  208. scr->dev->flush(scr, r);
  209. return;
  210. }
  211. if(scr->gscreen == nil || scr->useflush == 0)
  212. return;
  213. if(scr->dev == nil || scr->dev->page == nil)
  214. return;
  215. if(rectclip(&r, scr->gscreen->r) == 0)
  216. return;
  217. incs = scr->gscreen->width * BY2WD;
  218. switch(scr->gscreen->depth){
  219. default:
  220. len = 0;
  221. panic("flushmemscreen: depth\n");
  222. break;
  223. case 8:
  224. len = Dx(r);
  225. break;
  226. }
  227. if(len < 1)
  228. return;
  229. off = r.min.y * scr->gscreen->width * BY2WD + (r.min.x * scr->gscreen->depth) / 8;
  230. page = off / scr->apsize;
  231. off %= scr->apsize;
  232. disp = scr->vaddr;
  233. sdisp = disp + off;
  234. edisp = disp + scr->apsize;
  235. off = r.min.y * scr->gscreen->width * BY2WD + (r.min.x * scr->gscreen->depth) / 8;
  236. sp = scr->gscreendata->bdata + off;
  237. scr->dev->page(scr, page);
  238. for(y = r.min.y; y < r.max.y; y++){
  239. if(sdisp + incs < edisp){
  240. memmove(sdisp, sp, len);
  241. sp += incs;
  242. sdisp += incs;
  243. } else {
  244. off = edisp - sdisp;
  245. page++;
  246. if(off <= len){
  247. if(off > 0)
  248. memmove(sdisp, sp, off);
  249. scr->dev->page(scr, page);
  250. if(len - off > 0)
  251. memmove(disp, sp + off, len - off);
  252. } else {
  253. memmove(sdisp, sp, len);
  254. scr->dev->page(scr, page);
  255. }
  256. sp += incs;
  257. sdisp += incs - scr->apsize;
  258. }
  259. }
  260. }
  261. void
  262. getcolor(uint32_t p, uint32_t *pr, uint32_t *pg, uint32_t *pb)
  263. {
  264. VGAscr *scr;
  265. uint32_t x;
  266. scr = &vgascreen[0];
  267. if(scr->gscreen == nil)
  268. return;
  269. switch(scr->gscreen->depth){
  270. default:
  271. x = 0x0F;
  272. break;
  273. case 8:
  274. x = 0xFF;
  275. break;
  276. }
  277. p &= x;
  278. lock(&cursor.l);
  279. *pr = scr->colormap[p][0];
  280. *pg = scr->colormap[p][1];
  281. *pb = scr->colormap[p][2];
  282. unlock(&cursor.l);
  283. }
  284. int
  285. setpalette(uint32_t p, uint32_t r, uint32_t g, uint32_t b)
  286. {
  287. VGAscr *scr;
  288. error("can't do this");
  289. scr = &vgascreen[0];
  290. lock(&cursor.l);
  291. scr->colormap[p][0] = r;
  292. scr->colormap[p][1] = g;
  293. scr->colormap[p][2] = b;
  294. unlock(&cursor.l);
  295. return ~0;
  296. }
  297. /*
  298. * On some video cards (e.g. Mach64), the palette is used as the
  299. * DAC registers for >8-bit modes. We don't want to set them when the user
  300. * is trying to set a colormap and the card is in one of these modes.
  301. */
  302. int
  303. setcolor(uint32_t p, uint32_t r, uint32_t g, uint32_t b)
  304. {
  305. VGAscr *scr;
  306. int x;
  307. scr = &vgascreen[0];
  308. if(scr->gscreen == nil)
  309. return 0;
  310. switch(scr->gscreen->depth){
  311. case 1:
  312. case 2:
  313. case 4:
  314. x = 0x0F;
  315. break;
  316. case 8:
  317. x = 0xFF;
  318. break;
  319. default:
  320. return 0;
  321. }
  322. p &= x;
  323. return setpalette(p, r, g, b);
  324. }
  325. int
  326. cursoron(int dolock)
  327. {
  328. VGAscr *scr;
  329. int v;
  330. scr = &vgascreen[0];
  331. if(scr->cur == nil || scr->cur->move == nil)
  332. return 0;
  333. if(dolock)
  334. lock(&cursor.l);
  335. v = scr->cur->move(scr, mousexy());
  336. if(dolock)
  337. unlock(&cursor.l);
  338. return v;
  339. }
  340. void
  341. cursoroff(int i)
  342. {
  343. }
  344. void
  345. setcursor(Cursor *curs)
  346. {
  347. VGAscr *scr;
  348. scr = &vgascreen[0];
  349. if(scr->cur == nil || scr->cur->load == nil)
  350. return;
  351. scr->cur->load(scr, curs);
  352. }
  353. int hwaccel = 0;
  354. int hwblank = 0; /* turned on by drivers that are known good */
  355. int panning = 0;
  356. int
  357. hwdraw(Memdrawparam *par)
  358. {
  359. VGAscr *scr;
  360. Memimage *dst, *src, *mask;
  361. int m;
  362. if(hwaccel == 0)
  363. return 0;
  364. scr = &vgascreen[0];
  365. if((dst = par->dst) == nil || dst->data == nil)
  366. return 0;
  367. if((src = par->src) == nil || src->data == nil)
  368. return 0;
  369. if((mask = par->mask) == nil || mask->data == nil)
  370. return 0;
  371. if(scr->cur == &swcursor){
  372. /*
  373. * always calling swcursorhide here doesn't cure
  374. * leaving cursor tracks nor failing to refresh menus
  375. * with the latest libmemdraw/draw.c.
  376. */
  377. if(dst->data->bdata == gscreendata.bdata)
  378. swcursoravoid(par->r);
  379. if(src->data->bdata == gscreendata.bdata)
  380. swcursoravoid(par->sr);
  381. if(mask->data->bdata == gscreendata.bdata)
  382. swcursoravoid(par->mr);
  383. }
  384. if(dst->data->bdata != gscreendata.bdata)
  385. return 0;
  386. if(scr->fill == nil && scr->scroll == nil)
  387. return 0;
  388. /*
  389. * If we have an opaque mask and source is one opaque
  390. * pixel we can convert to the destination format and just
  391. * replicate with memset.
  392. */
  393. m = Simplesrc | Simplemask | Fullmask;
  394. if(scr->fill && (par->state & m) == m && ((par->srgba & 0xFF) == 0xFF) && (par->op & S) == S)
  395. return scr->fill(scr, par->r, par->sdval);
  396. /*
  397. * If no source alpha, an opaque mask, we can just copy the
  398. * source onto the destination. If the channels are the same and
  399. * the source is not replicated, memmove suffices.
  400. */
  401. m = Simplemask | Fullmask;
  402. if(scr->scroll && src->data->bdata == dst->data->bdata && !(src->flags & Falpha) && (par->state & m) == m && (par->op & S) == S)
  403. return scr->scroll(scr, par->r, par->sr);
  404. return 0;
  405. }
  406. void
  407. blankscreen(int blank)
  408. {
  409. VGAscr *scr;
  410. scr = &vgascreen[0];
  411. if(hwblank){
  412. if(scr->blank)
  413. scr->blank(scr, blank);
  414. else
  415. vgablank(scr, blank);
  416. }
  417. }
  418. void
  419. vgalinearaddr(VGAscr *scr, uint32_t paddr, int size)
  420. {
  421. int x, nsize;
  422. uint32_t npaddr;
  423. /*
  424. * new approach. instead of trying to resize this
  425. * later, let's assume that we can just allocate the
  426. * entire window to start with.
  427. */
  428. if(scr->paddr == paddr && size <= scr->apsize)
  429. return;
  430. error("Can't do vgalinearaddr");
  431. if(scr->paddr){
  432. /*
  433. * could call vunmap and vmap,
  434. * but worried about dangling pointers in devdraw
  435. */
  436. error("cannot grow vga frame buffer");
  437. }
  438. /* round to page boundary, just in case */
  439. x = paddr & (4 * KiB - 1);
  440. npaddr = paddr - x;
  441. nsize = ROUNDUP(size + x, 4 * KiB);
  442. /*
  443. * Don't bother trying to map more than 4000x4000x32 = 64MB.
  444. * We only have a 256MB window.
  445. */
  446. if(nsize > 64 * MB)
  447. nsize = 64 * MB;
  448. scr->vaddr = vmap(npaddr, nsize);
  449. if(scr->vaddr == 0)
  450. error("cannot allocate vga frame buffer");
  451. scr->vaddr = (char *)scr->vaddr + x;
  452. scr->paddr = paddr;
  453. scr->apsize = nsize;
  454. }
  455. /*
  456. * Software cursor.
  457. */
  458. int swvisible; /* is the cursor visible? */
  459. int swenabled; /* is the cursor supposed to be on the screen? */
  460. Memimage *swback; /* screen under cursor */
  461. Memimage *swimg; /* cursor image */
  462. Memimage *swmask; /* cursor mask */
  463. Memimage *swimg1;
  464. Memimage *swmask1;
  465. Point swoffset;
  466. Rectangle swrect; /* screen rectangle in swback */
  467. Point swpt; /* desired cursor location */
  468. Point swvispt; /* actual cursor location */
  469. int swvers; /* incremented each time cursor image changes */
  470. int swvisvers; /* the version on the screen */
  471. /*
  472. * called with drawlock locked for us, most of the time.
  473. * kernel prints at inopportune times might mean we don't
  474. * hold the lock, but memimagedraw is now reentrant so
  475. * that should be okay: worst case we get cursor droppings.
  476. */
  477. void
  478. swcursorhide(void)
  479. {
  480. if(swvisible == 0)
  481. return;
  482. if(swback == nil)
  483. return;
  484. swvisible = 0;
  485. memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
  486. flushmemscreen(swrect);
  487. }
  488. void
  489. swcursoravoid(Rectangle r)
  490. {
  491. if(swvisible && rectXrect(r, swrect))
  492. swcursorhide();
  493. }
  494. void
  495. swcursordraw(void)
  496. {
  497. if(swvisible)
  498. return;
  499. if(swenabled == 0)
  500. return;
  501. if(swback == nil || swimg1 == nil || swmask1 == nil)
  502. return;
  503. assert(!canqlock(&drawlock));
  504. swvispt = swpt;
  505. swvisvers = swvers;
  506. swrect = rectaddpt(Rect(0, 0, 16, 16), swvispt);
  507. memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
  508. memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
  509. flushmemscreen(swrect);
  510. swvisible = 1;
  511. }
  512. /*
  513. * Need to lock drawlock for ourselves.
  514. */
  515. void
  516. swenable(VGAscr *v)
  517. {
  518. swenabled = 1;
  519. if(canqlock(&drawlock)){
  520. swcursordraw();
  521. qunlock(&drawlock);
  522. }
  523. }
  524. void
  525. swdisable(VGAscr *v)
  526. {
  527. swenabled = 0;
  528. if(canqlock(&drawlock)){
  529. swcursorhide();
  530. qunlock(&drawlock);
  531. }
  532. }
  533. void
  534. swload(VGAscr *v, Cursor *curs)
  535. {
  536. unsigned char *ip, *mp;
  537. int i, j, set, clr;
  538. if(!swimg || !swmask || !swimg1 || !swmask1)
  539. return;
  540. /*
  541. * Build cursor image and mask.
  542. * Image is just the usual cursor image
  543. * but mask is a transparent alpha mask.
  544. *
  545. * The 16x16x8 memimages do not have
  546. * padding at the end of their scan lines.
  547. */
  548. ip = byteaddr(swimg, ZP);
  549. mp = byteaddr(swmask, ZP);
  550. for(i = 0; i < 32; i++){
  551. set = curs->set[i];
  552. clr = curs->clr[i];
  553. for(j = 0x80; j; j >>= 1){
  554. *ip++ = set & j ? 0x00 : 0xFF;
  555. *mp++ = (clr | set) & j ? 0xFF : 0x00;
  556. }
  557. }
  558. swoffset = curs->offset;
  559. swvers++;
  560. memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
  561. memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
  562. }
  563. int
  564. swmove(VGAscr *v, Point p)
  565. {
  566. swpt = addpt(p, swoffset);
  567. return 0;
  568. }
  569. void
  570. swcursorclock(void)
  571. {
  572. int x;
  573. if(!swenabled)
  574. return;
  575. if(swvisible && eqpt(swpt, swvispt) && swvers == swvisvers)
  576. return;
  577. x = splhi();
  578. if(swenabled)
  579. if(!swvisible || !eqpt(swpt, swvispt) || swvers != swvisvers)
  580. if(canqlock(&drawlock)){
  581. swcursorhide();
  582. swcursordraw();
  583. qunlock(&drawlock);
  584. }
  585. splx(x);
  586. }
  587. void
  588. swcursorinit(void)
  589. {
  590. static int init, warned;
  591. VGAscr *scr;
  592. didswcursorinit = 1;
  593. if(!init){
  594. init = 1;
  595. addclock0link(swcursorclock, 10);
  596. }
  597. scr = &vgascreen[0];
  598. if(scr == nil || scr->gscreen == nil)
  599. return;
  600. if(scr->dev == nil || scr->dev->linear == nil){
  601. if(!warned){
  602. print("cannot use software cursor on non-linear vga screen\n");
  603. warned = 1;
  604. }
  605. return;
  606. }
  607. if(swback){
  608. freememimage(swback);
  609. freememimage(swmask);
  610. freememimage(swmask1);
  611. freememimage(swimg);
  612. freememimage(swimg1);
  613. }
  614. swback = allocmemimage(Rect(0, 0, 32, 32), gscreen->chan);
  615. swmask = allocmemimage(Rect(0, 0, 16, 16), GREY8);
  616. swmask1 = allocmemimage(Rect(0, 0, 16, 16), GREY1);
  617. swimg = allocmemimage(Rect(0, 0, 16, 16), GREY8);
  618. swimg1 = allocmemimage(Rect(0, 0, 16, 16), GREY1);
  619. if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){
  620. print("software cursor: allocmemimage fails");
  621. return;
  622. }
  623. memfillcolor(swmask, DOpaque);
  624. memfillcolor(swmask1, DOpaque);
  625. memfillcolor(swimg, DBlack);
  626. memfillcolor(swimg1, DBlack);
  627. }
  628. VGAcur swcursor =
  629. {
  630. "soft",
  631. swenable,
  632. swdisable,
  633. swload,
  634. swmove,
  635. };