screen.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "ureg.h"
  8. #include "../port/error.h"
  9. #define Image IMAGE
  10. #include <draw.h>
  11. #include <memdraw.h>
  12. #include <cursor.h>
  13. #include "screen.h"
  14. #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
  15. Point ZP = {0, 0};
  16. Rectangle physgscreenr;
  17. Memdata gscreendata;
  18. Memimage *gscreen;
  19. VGAscr vgascreen[1];
  20. Cursor arrow = {
  21. { -1, -1 },
  22. { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
  23. 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
  24. 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
  25. 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
  26. },
  27. { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
  28. 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
  29. 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
  30. 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
  31. },
  32. };
  33. int
  34. screensize(int x, int y, int z, ulong chan)
  35. {
  36. VGAscr *scr;
  37. memimageinit();
  38. scr = &vgascreen[0];
  39. /*
  40. * BUG: need to check if any xalloc'ed memory needs to
  41. * be given back if aperture is set.
  42. */
  43. if(scr->aperture == 0){
  44. int width = (x*z)/BI2WD;
  45. gscreendata.bdata = xalloc(width*BY2WD*y);
  46. if(gscreendata.bdata == 0)
  47. error("screensize: vga soft memory");
  48. /* memset(gscreendata.bdata, 0x72, width*BY2WD*y); /* not really black */
  49. scr->useflush = 1;
  50. scr->aperture = VGAMEM();
  51. scr->apsize = 1<<16;
  52. }
  53. else
  54. gscreendata.bdata = KADDR(scr->aperture);
  55. if(gscreen)
  56. freememimage(gscreen);
  57. gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata);
  58. vgaimageinit(chan);
  59. if(gscreen == nil)
  60. return -1;
  61. if(scr->dev && scr->dev->flush)
  62. scr->useflush = 1;
  63. scr->palettedepth = 6; /* default */
  64. scr->gscreendata = &gscreendata;
  65. scr->memdefont = getmemdefont();
  66. scr->gscreen = gscreen;
  67. physgscreenr = gscreen->r;
  68. drawcmap();
  69. return 0;
  70. }
  71. int
  72. screenaperture(int size, int align)
  73. {
  74. VGAscr *scr;
  75. ulong aperture;
  76. scr = &vgascreen[0];
  77. if(size == 0){
  78. if(scr->aperture && scr->isupamem)
  79. upafree(scr->aperture, scr->apsize);
  80. scr->aperture = 0;
  81. scr->isupamem = 0;
  82. return 0;
  83. }
  84. if(scr->dev && scr->dev->linear){
  85. aperture = scr->dev->linear(scr, &size, &align);
  86. if(aperture == 0)
  87. return 1;
  88. }else{
  89. aperture = upamalloc(0, size, align);
  90. if(aperture == 0)
  91. return 1;
  92. if(scr->aperture && scr->isupamem)
  93. upafree(scr->aperture, scr->apsize);
  94. scr->isupamem = 1;
  95. }
  96. scr->aperture = aperture;
  97. scr->apsize = size;
  98. return 0;
  99. }
  100. uchar*
  101. attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
  102. {
  103. VGAscr *scr;
  104. scr = &vgascreen[0];
  105. if(scr->gscreen == nil || scr->gscreendata == nil)
  106. return nil;
  107. *r = scr->gscreen->clipr;
  108. *chan = scr->gscreen->chan;
  109. *d = scr->gscreen->depth;
  110. *width = scr->gscreen->width;
  111. *softscreen = scr->useflush;
  112. return scr->gscreendata->bdata;
  113. }
  114. /*
  115. * It would be fair to say that this doesn't work for >8-bit screens.
  116. */
  117. void
  118. flushmemscreen(Rectangle r)
  119. {
  120. VGAscr *scr;
  121. uchar *sp, *disp, *sdisp, *edisp;
  122. int y, len, incs, off, page;
  123. scr = &vgascreen[0];
  124. if(scr->dev && scr->dev->flush){
  125. scr->dev->flush(scr, r);
  126. return;
  127. }
  128. if(scr->gscreen == nil || scr->useflush == 0)
  129. return;
  130. if(scr->dev == nil || scr->dev->page == nil)
  131. return;
  132. if(rectclip(&r, scr->gscreen->r) == 0)
  133. return;
  134. incs = scr->gscreen->width * BY2WD;
  135. switch(scr->gscreen->depth){
  136. default:
  137. len = 0;
  138. panic("flushmemscreen: depth\n");
  139. break;
  140. case 8:
  141. len = Dx(r);
  142. break;
  143. }
  144. if(len < 1)
  145. return;
  146. off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
  147. page = off/scr->apsize;
  148. off %= scr->apsize;
  149. disp = KADDR(scr->aperture);
  150. sdisp = disp+off;
  151. edisp = disp+scr->apsize;
  152. off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
  153. sp = scr->gscreendata->bdata + off;
  154. scr->dev->page(scr, page);
  155. for(y = r.min.y; y < r.max.y; y++) {
  156. if(sdisp + incs < edisp) {
  157. memmove(sdisp, sp, len);
  158. sp += incs;
  159. sdisp += incs;
  160. }
  161. else {
  162. off = edisp - sdisp;
  163. page++;
  164. if(off <= len){
  165. if(off > 0)
  166. memmove(sdisp, sp, off);
  167. scr->dev->page(scr, page);
  168. if(len - off > 0)
  169. memmove(disp, sp+off, len - off);
  170. }
  171. else {
  172. memmove(sdisp, sp, len);
  173. scr->dev->page(scr, page);
  174. }
  175. sp += incs;
  176. sdisp += incs - scr->apsize;
  177. }
  178. }
  179. }
  180. void
  181. getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
  182. {
  183. VGAscr *scr;
  184. ulong x;
  185. scr = &vgascreen[0];
  186. if(scr->gscreen == nil)
  187. return;
  188. switch(scr->gscreen->depth){
  189. default:
  190. x = 0x0F;
  191. break;
  192. case 8:
  193. x = 0xFF;
  194. break;
  195. }
  196. p &= x;
  197. lock(&cursor);
  198. *pr = scr->colormap[p][0];
  199. *pg = scr->colormap[p][1];
  200. *pb = scr->colormap[p][2];
  201. unlock(&cursor);
  202. }
  203. int
  204. setpalette(ulong p, ulong r, ulong g, ulong b)
  205. {
  206. VGAscr *scr;
  207. int d;
  208. scr = &vgascreen[0];
  209. d = scr->palettedepth;
  210. lock(&cursor);
  211. scr->colormap[p][0] = r;
  212. scr->colormap[p][1] = g;
  213. scr->colormap[p][2] = b;
  214. vgao(PaddrW, p);
  215. vgao(Pdata, r>>(32-d));
  216. vgao(Pdata, g>>(32-d));
  217. vgao(Pdata, b>>(32-d));
  218. unlock(&cursor);
  219. return ~0;
  220. }
  221. /*
  222. * On some video cards (e.g. Mach64), the palette is used as the
  223. * DAC registers for >8-bit modes. We don't want to set them when the user
  224. * is trying to set a colormap and the card is in one of these modes.
  225. */
  226. int
  227. setcolor(ulong p, ulong r, ulong g, ulong b)
  228. {
  229. VGAscr *scr;
  230. int x;
  231. scr = &vgascreen[0];
  232. if(scr->gscreen == nil)
  233. return 0;
  234. switch(scr->gscreen->depth){
  235. case 1:
  236. case 2:
  237. case 4:
  238. x = 0x0F;
  239. break;
  240. case 8:
  241. x = 0xFF;
  242. break;
  243. default:
  244. return 0;
  245. }
  246. p &= x;
  247. return setpalette(p, r, g, b);
  248. }
  249. int
  250. cursoron(int dolock)
  251. {
  252. VGAscr *scr;
  253. int v;
  254. scr = &vgascreen[0];
  255. if(scr->cur == nil || scr->cur->move == nil)
  256. return 0;
  257. if(dolock)
  258. lock(&cursor);
  259. v = scr->cur->move(scr, mousexy());
  260. if(dolock)
  261. unlock(&cursor);
  262. return v;
  263. }
  264. void
  265. cursoroff(int)
  266. {
  267. }
  268. void
  269. setcursor(Cursor* curs)
  270. {
  271. VGAscr *scr;
  272. scr = &vgascreen[0];
  273. if(scr->cur == nil || scr->cur->load == nil)
  274. return;
  275. scr->cur->load(scr, curs);
  276. }
  277. int hwaccel = 1;
  278. int hwblank = 0; /* turned on by drivers that are known good */
  279. int panning = 0;
  280. int
  281. hwdraw(Memdrawparam *par)
  282. {
  283. VGAscr *scr;
  284. Memimage *dst, *src;
  285. int m;
  286. if(hwaccel == 0)
  287. return 0;
  288. dst = par->dst;
  289. scr = &vgascreen[0];
  290. if(dst == nil || dst->data == nil)
  291. return 0;
  292. if(dst->data->bdata != gscreendata.bdata)
  293. return 0;
  294. if(scr->fill==nil && scr->scroll==nil)
  295. return 0;
  296. /*
  297. * If we have an opaque mask and source is one opaque
  298. * pixel we can convert to the destination format and just
  299. * replicate with memset.
  300. */
  301. m = Simplesrc|Simplemask|Fullmask;
  302. if(scr->fill
  303. && (par->state&m)==m
  304. && ((par->srgba&0xFF) == 0xFF)
  305. && (par->op&S) == S)
  306. return scr->fill(scr, par->r, par->sdval);
  307. /*
  308. * If no source alpha, an opaque mask, we can just copy the
  309. * source onto the destination. If the channels are the same and
  310. * the source is not replicated, memmove suffices.
  311. */
  312. m = Simplemask|Fullmask;
  313. src = par->src;
  314. if(scr->scroll
  315. && src->data->bdata==dst->data->bdata
  316. && !(src->flags&Falpha)
  317. && (par->state&m)==m
  318. && (par->op&S) == S)
  319. return scr->scroll(scr, par->r, par->sr);
  320. return 0;
  321. }
  322. void
  323. blankscreen(int blank)
  324. {
  325. VGAscr *scr;
  326. scr = &vgascreen[0];
  327. if(hwblank){
  328. if(scr->blank)
  329. scr->blank(scr, blank);
  330. else
  331. vgablank(scr, blank);
  332. }
  333. }