PageRenderTime 68ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/gfxlib.cpp

https://github.com/tonioni/WinUAE
C++ | 1680 lines | 1376 code | 186 blank | 118 comment | 364 complexity | 8510256277f125201c3beb1274a5796d MD5 | raw file
  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * graphics.library emulation
  5. *
  6. * Copyright 1996, 1997 Bernd Schmidt
  7. *
  8. * Ideas for this:
  9. * Rewrite layers completely. When there are lots of windows on the screen
  10. * it can take 3 minutes to update everything after resizing or moving one
  11. * (at least with Kick 1.3). Hide the internal structure of the layers as far
  12. * as possible, keep most of the data in emulator space so we save copying/
  13. * conversion time. Programs really shouldn't do anything directly with the
  14. * Layer or ClipRect structures.
  15. * This means that a lot of graphics.library functions will have to be
  16. * rewritten as well.
  17. * Once that's done, add support for non-planar bitmaps. Conveniently, the
  18. * struct Bitmap has an unused pad field which we could abuse as some sort of
  19. * type field. Need to add chunky<->planar conversion routines to get it
  20. * going, plus variants of all the drawing functions for speed reasons.
  21. *
  22. * When it becomes necessary to convert a structure from Amiga memory, make
  23. * a function with a name ending in ..FA, which takes a pointer to the
  24. * native structure and a uaecptr and returns the native pointer.
  25. */
  26. #include "sysconfig.h"
  27. #include "sysdeps.h"
  28. #include <assert.h>
  29. #include "options.h"
  30. #include "threaddep/thread.h"
  31. #include "memory.h"
  32. #include "custom.h"
  33. #include "newcpu.h"
  34. #include "xwin.h"
  35. #include "autoconf.h"
  36. #include "osemu.h"
  37. #ifdef USE_EXECLIB
  38. /* Uniq list management. Should be in a separate file. */
  39. struct uniq_head {
  40. struct uniq_head *next;
  41. uae_u32 uniq;
  42. };
  43. typedef struct {
  44. struct uniq_head *head;
  45. uae_u32 uniq;
  46. } uniq_list;
  47. #define UNIQ_INIT { NULL, 1 }
  48. static void init_uniq(uniq_list *list)
  49. {
  50. list->head = NULL;
  51. list->uniq = 1;
  52. }
  53. static struct uniq_head *find_uniq (uniq_list *a, uae_u32 uniq)
  54. {
  55. struct uniq_head *b = a->head;
  56. while (b && b->uniq != uniq)
  57. b = b->next;
  58. if (!b)
  59. write_log (_T("Couldn't find structure. Bad\n"));
  60. return b;
  61. }
  62. static struct uniq_head *find_and_rem_uniq (uniq_list *a, uae_u32 uniq)
  63. {
  64. struct uniq_head **b = &a->head, *c;
  65. while (*b && (*b)->uniq != uniq)
  66. b = &(*b)->next;
  67. c = *b;
  68. if (!c)
  69. write_log (_T("Couldn't find structure. Bad\n"));
  70. else
  71. *b = c->next;
  72. return c;
  73. }
  74. static void add_uniq (uniq_list *a, struct uniq_head *item, uaecptr amem)
  75. {
  76. item->uniq = a->uniq++;
  77. put_long (amem, item->uniq);
  78. if (a->uniq == 0)
  79. a->uniq++;
  80. item->next = a->head;
  81. a->head = item;
  82. }
  83. /* Graphics stuff begins here */
  84. #define CLIPRECT_SIZE 40
  85. #define LAYER_SIZE 160
  86. #define LINFO_SIZE 102
  87. static uaecptr gfxbase, layersbase;
  88. static void do_LockLayer(uaecptr layer)
  89. {
  90. #if 0 /* Later.. */
  91. uaecptr sigsem = layer + 72;
  92. m68k_areg (regs, 0) = sigsem;
  93. CallLib (get_long (4), -564);
  94. #else
  95. m68k_areg (regs, 1) = layer;
  96. CallLib (layersbase, -96);
  97. #endif
  98. }
  99. static void do_UnlockLayer(uaecptr layer)
  100. {
  101. m68k_areg (regs, 0) = layer;
  102. CallLib (layersbase, -102);
  103. }
  104. static uae_u32 gfxlibname, layerslibname;
  105. struct Rectangle {
  106. int MinX, MinY, MaxX, MaxY;
  107. };
  108. static int GFX_PointInRectangle(uaecptr rect, int x, int y)
  109. {
  110. uae_s16 minx = get_word (rect);
  111. uae_s16 miny = get_word (rect+2);
  112. uae_s16 maxx = get_word (rect+4);
  113. uae_s16 maxy = get_word (rect+6);
  114. if (x < minx || x > maxx || y < miny || y > maxy)
  115. return 0;
  116. return 1;
  117. }
  118. static int GFX_RectContainsRect(struct Rectangle *r1, struct Rectangle *r2)
  119. {
  120. return (r2->MinX >= r1->MinX && r2->MaxX <= r1->MaxX
  121. && r2->MinY >= r1->MinY && r2->MaxY <= r1->MaxY);
  122. }
  123. static struct Rectangle *GFX_RectFA(struct Rectangle *rp, uaecptr rect)
  124. {
  125. rp->MinX = (uae_s16)get_word (rect);
  126. rp->MinY = (uae_s16)get_word (rect+2);
  127. rp->MaxX = (uae_s16)get_word (rect+4);
  128. rp->MaxY = (uae_s16)get_word (rect+6);
  129. return rp;
  130. }
  131. static int GFX_Bitmap_WritePixel(uaecptr bitmap, int x, int y, uaecptr rp)
  132. {
  133. int i, offs;
  134. unsigned int bpr = get_word (bitmap);
  135. unsigned int rows = get_word (bitmap + 2);
  136. uae_u16 mask;
  137. uae_u8 planemask = get_byte (rp + 24);
  138. uae_u8 fgpen = get_byte (rp + 25);
  139. uae_u8 bgpen = get_byte (rp + 26);
  140. uae_u8 drmd = get_byte (rp + 28);
  141. uae_u8 pen = drmd & 4 ? bgpen : fgpen;
  142. if (x < 0 || y < 0 || x >= 8*bpr || y >= rows)
  143. return -1;
  144. offs = y*bpr + (x & ~15)/8;
  145. for (i = 0; i < get_byte (bitmap + 5); i++) {
  146. uaecptr planeptr;
  147. uae_u16 data;
  148. if ((planemask & (1 << i)) == 0)
  149. continue;
  150. planeptr = get_long (bitmap + 8 + i*4);
  151. data = get_word (planeptr + offs);
  152. mask = 0x8000 >> (x & 15);
  153. if (drmd & 2) {
  154. if ((pen & (1 << i)) != 0)
  155. data ^=mask;
  156. } else {
  157. data &= ~mask;
  158. if ((pen & (1 << i)) != 0)
  159. data |= mask;
  160. }
  161. put_word (planeptr + offs, data);
  162. }
  163. return 0;
  164. }
  165. int GFX_WritePixel(uaecptr rp, int x, int y)
  166. {
  167. int v;
  168. uaecptr layer = get_long (rp);
  169. uaecptr bitmap = get_long (rp + 4);
  170. uaecptr cliprect;
  171. int x2, y2;
  172. if (bitmap == 0) {
  173. write_log (_T("bogus RastPort in WritePixel\n"));
  174. return -1;
  175. }
  176. /* Easy case first */
  177. if (layer == 0) {
  178. return GFX_Bitmap_WritePixel(bitmap, x, y, rp);
  179. }
  180. do_LockLayer(layer);
  181. /*
  182. * Now, in theory we ought to obtain the semaphore.
  183. * Since we don't, the programs will happily write into the raster
  184. * even though we are currently moving the window around.
  185. * Not good.
  186. */
  187. x2 = x + (uae_s16)get_word (layer + 16);
  188. y2 = y + (uae_s16)get_word (layer + 18);
  189. if (!GFX_PointInRectangle (layer + 16, x2, y2)) {
  190. do_UnlockLayer(layer);
  191. return -1;
  192. }
  193. /* Find the right ClipRect */
  194. cliprect = get_long (layer + 8);
  195. while (cliprect != 0 && !GFX_PointInRectangle (cliprect + 16, x2, y2))
  196. cliprect = get_long (cliprect);
  197. if (cliprect == 0) {
  198. /* Don't complain: The "Dots" demo does this all the time. I
  199. * suppose if we can't find a ClipRect, we aren't supposed to draw
  200. * the dot.
  201. */
  202. /*write_log (_T("Weirdness in WritePixel\n"));*/
  203. v = -1;
  204. } else if (get_long (cliprect + 8) == 0) {
  205. v = GFX_Bitmap_WritePixel(bitmap, x2, y2, rp);
  206. } else if (get_long (cliprect + 12) == 0) {
  207. /* I don't really know what to do here... */
  208. v = 0;
  209. } else {
  210. /* This appears to be normal for smart refresh layers which are obscured */
  211. v = GFX_Bitmap_WritePixel (get_long (cliprect + 12), x2 - (uae_s16)get_word (cliprect + 16),
  212. y2 - (uae_s16)get_word (cliprect + 18), rp);
  213. }
  214. do_UnlockLayer(layer);
  215. return v;
  216. }
  217. static uae_u32 gfxl_WritePixel(void) { return GFX_WritePixel(m68k_areg (regs, 1), (uae_s16)m68k_dreg (regs, 0), (uae_s16)m68k_dreg (regs, 1)); }
  218. static uae_u32 gfxl_BltClear(void)
  219. {
  220. uaecptr mem=m68k_areg (regs, 1);
  221. uae_u8 *mptr = chipmem_bank.xlateaddr(m68k_areg (regs, 1));
  222. uae_u32 count=m68k_dreg (regs, 0);
  223. uae_u32 flags=m68k_dreg (regs, 1);
  224. unsigned int i;
  225. uae_u32 pattern;
  226. if ((flags & 2) == 2){
  227. /* count is given in Rows / Bytes per row */
  228. count=(count & 0xFFFF) * (count >> 16);
  229. }
  230. if ((mem & 1) != 0 || (count & 1) != 0)
  231. write_log (_T("gfx: BltClear called with odd parameters\n"));
  232. /* Bit 2 set means use pattern (V36+ only, but we might as well emulate
  233. * it always) */
  234. if ((flags & 4) == 0)
  235. pattern = 0;
  236. else
  237. pattern= ((flags >> 16) & 0xFFFF) | (flags & 0xFFFF0000ul);
  238. if ((pattern & 0xFF) == ((pattern >> 8) & 0xFF)) {
  239. memset(mptr, pattern, count);
  240. return 0;
  241. }
  242. for(i = 0; i < count; i += 4)
  243. chipmem_bank.lput(mem+i, pattern);
  244. if ((count & 3) != 0)
  245. chipmem_bank.wput(mem + i - 4, pattern);
  246. return 0;
  247. }
  248. static uae_u32 gfxl_BltBitmap(void)
  249. {
  250. uaecptr srcbitmap = m68k_areg (regs, 0), dstbitmap = m68k_areg (regs, 1);
  251. int srcx = (uae_s16)m68k_dreg (regs, 0), srcy = (uae_s16)m68k_dreg (regs, 1);
  252. int dstx = (uae_s16)m68k_dreg (regs, 2), dsty = (uae_s16)m68k_dreg (regs, 3);
  253. int sizex = (uae_s16)m68k_dreg (regs, 4), sizey = (uae_s16)m68k_dreg (regs, 5);
  254. uae_u8 minterm = (uae_u8)m68k_dreg (regs, 6), mask = m68k_dreg (regs, 7);
  255. return 0; /* sam: a return was missing here ! */
  256. }
  257. static uaecptr amiga_malloc(int len)
  258. {
  259. m68k_dreg (regs, 0) = len;
  260. m68k_dreg (regs, 1) = 1; /* MEMF_PUBLIC */
  261. return CallLib (get_long (4), -198); /* AllocMem */
  262. }
  263. static void amiga_free(uaecptr addr, int len)
  264. {
  265. m68k_areg (regs, 1) = addr;
  266. m68k_dreg (regs, 0) = len;
  267. CallLib (get_long (4), -210); /* FreeMem */
  268. }
  269. /*
  270. * Region handling code
  271. *
  272. * General ideas stolen from xc/verylongpath/miregion.c
  273. *
  274. * The Clear code is untested. And and Or seem to work, Xor is only used
  275. * by the 1.3 Prefs program and seems to work, too.
  276. */
  277. struct RegionRectangle {
  278. struct RegionRectangle *Next,*Prev;
  279. struct Rectangle bounds;
  280. };
  281. struct Region {
  282. struct Rectangle bounds;
  283. struct RegionRectangle *RegionRectangle;
  284. };
  285. struct RectList {
  286. int count;
  287. int space;
  288. struct Rectangle bounds;
  289. struct Rectangle *rects;
  290. };
  291. struct BandList {
  292. int count;
  293. int space;
  294. int *miny, *maxy;
  295. };
  296. static void init_bandlist(struct BandList *bl)
  297. {
  298. bl->count = 0;
  299. bl->space = 20;
  300. bl->miny = (int *)malloc(20*sizeof(int));
  301. bl->maxy = (int *)malloc(20*sizeof(int));
  302. }
  303. static void dup_bandlist(struct BandList *to, struct BandList *from)
  304. {
  305. to->count = from->count;
  306. to->space = to->count+4;
  307. to->miny = (int *)malloc (to->space*sizeof(int));
  308. to->maxy = (int *)malloc (to->space*sizeof(int));
  309. memcpy(to->miny, from->miny, to->count*sizeof(int));
  310. memcpy(to->maxy, from->maxy, to->count*sizeof(int));
  311. }
  312. STATIC_INLINE void add_band(struct BandList *bl, int miny, int maxy, int pos)
  313. {
  314. if (bl->count == bl->space) {
  315. bl->space += 20;
  316. bl->miny = (int *)realloc(bl->miny, bl->space*sizeof(int));
  317. bl->maxy = (int *)realloc(bl->maxy, bl->space*sizeof(int));
  318. }
  319. memmove(bl->miny + pos + 1, bl->miny + pos, (bl->count - pos) * sizeof(int));
  320. memmove(bl->maxy + pos + 1, bl->maxy + pos, (bl->count - pos) * sizeof(int));
  321. bl->count++;
  322. bl->miny[pos] = miny;
  323. bl->maxy[pos] = maxy;
  324. }
  325. static void init_rectlist(struct RectList *rl)
  326. {
  327. rl->count = 0;
  328. rl->space = 100;
  329. rl->bounds.MinX = rl->bounds.MinY = rl->bounds.MaxX = rl->bounds.MaxY = 0;
  330. rl->rects = (struct Rectangle *)malloc(100*sizeof(struct Rectangle));
  331. }
  332. static void dup_rectlist(struct RectList *to, struct RectList *from)
  333. {
  334. to->count = from->count;
  335. to->space = to->count+4;
  336. to->bounds = from->bounds;
  337. to->rects = (struct Rectangle *)malloc (to->space*sizeof(struct Rectangle));
  338. memcpy(to->rects, from->rects, to->count*sizeof(struct Rectangle));
  339. }
  340. STATIC_INLINE void add_rect(struct RectList *rl, struct Rectangle r)
  341. {
  342. if (rl->count == 0)
  343. rl->bounds = r;
  344. else {
  345. if (r.MinX < rl->bounds.MinX)
  346. rl->bounds.MinX = r.MinX;
  347. if (r.MinY < rl->bounds.MinY)
  348. rl->bounds.MinY = r.MinY;
  349. if (r.MaxX > rl->bounds.MaxX)
  350. rl->bounds.MaxX = r.MaxX;
  351. if (r.MaxY > rl->bounds.MaxY)
  352. rl->bounds.MaxY = r.MaxY;
  353. }
  354. if (rl->count == rl->space) {
  355. rl->space += 100;
  356. rl->rects = (struct Rectangle *)realloc(rl->rects, rl->space*sizeof(struct Rectangle));
  357. }
  358. rl->rects[rl->count++] = r;
  359. }
  360. STATIC_INLINE void rem_rect(struct RectList *rl, int num)
  361. {
  362. rl->count--;
  363. if (num == rl->count)
  364. return;
  365. rl->rects[num] = rl->rects[rl->count];
  366. }
  367. static void free_rectlist(struct RectList *rl)
  368. {
  369. free(rl->rects);
  370. }
  371. static void free_bandlist(struct BandList *bl)
  372. {
  373. free(bl->miny);
  374. free(bl->maxy);
  375. }
  376. static int regionrect_cmpfn(const void *a, const void *b)
  377. {
  378. struct Rectangle *ra = (struct Rectangle *)a;
  379. struct Rectangle *rb = (struct Rectangle *)b;
  380. if (ra->MinY < rb->MinY)
  381. return -1;
  382. if (ra->MinY > rb->MinY)
  383. return 1;
  384. if (ra->MinX < rb->MinX)
  385. return -1;
  386. if (ra->MinX > rb->MinX)
  387. return 1;
  388. if (ra->MaxX < rb->MaxX)
  389. return -1;
  390. return 1;
  391. }
  392. STATIC_INLINE int min(int x, int y)
  393. {
  394. return x < y ? x : y;
  395. }
  396. STATIC_INLINE int max(int x, int y)
  397. {
  398. return x > y ? x : y;
  399. }
  400. static void add_rect_to_bands(struct BandList *bl, struct Rectangle *rect)
  401. {
  402. int j;
  403. struct Rectangle tmpr = *rect;
  404. for (j = 0; j < bl->count; j++) {
  405. /* Is the current band before the rectangle? */
  406. if (bl->maxy[j] < tmpr.MinY)
  407. continue;
  408. /* Band already present? */
  409. if (bl->miny[j] == tmpr.MinY && bl->maxy[j] == tmpr.MaxY)
  410. break;
  411. /* Completely new band? Add it */
  412. if (bl->miny[j] > tmpr.MaxY) {
  413. add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  414. break;
  415. }
  416. /* Now we know that the bands are overlapping.
  417. * See whether they match in one point */
  418. if (bl->miny[j] == tmpr.MinY) {
  419. int t;
  420. if (bl->maxy[j] < tmpr.MaxY) {
  421. /* Rectangle exceeds band */
  422. tmpr.MinY = bl->maxy[j]+1;
  423. continue;
  424. }
  425. /* Rectangle splits band */
  426. t = bl->maxy[j];
  427. bl->maxy[j] = tmpr.MaxY;
  428. tmpr.MinY = bl->maxy[j] + 1;
  429. tmpr.MaxY = t;
  430. continue;
  431. } else if (bl->maxy[j] == tmpr.MaxY) {
  432. int t;
  433. if (bl->miny[j] > tmpr.MinY) {
  434. /* Rectangle exceeds band */
  435. t = bl->miny[j];
  436. bl->miny[j] = tmpr.MinY;
  437. bl->maxy[j] = t-1;
  438. tmpr.MinY = t;
  439. continue;
  440. }
  441. /* Rectangle splits band */
  442. bl->maxy[j] = tmpr.MinY - 1;
  443. continue;
  444. }
  445. /* Bands overlap and match in no points. Get a new band and align */
  446. if (bl->miny[j] > tmpr.MinY) {
  447. /* Rectangle begins before band, so make a new band before
  448. * and adjust rectangle */
  449. add_band(bl, tmpr.MinY, bl->miny[j] - 1, j);
  450. tmpr.MinY = bl->miny[j+1];
  451. } else {
  452. /* Rectangle begins in band */
  453. add_band(bl, bl->miny[j], tmpr.MinY - 1, j);
  454. bl->miny[j+1] = tmpr.MinY;
  455. }
  456. continue;
  457. }
  458. if (j == bl->count)
  459. add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  460. }
  461. static void region_addbands(struct RectList *rl, struct BandList *bl)
  462. {
  463. int i,j;
  464. for (i = 0; i < rl->count; i++) {
  465. add_rect_to_bands(bl, rl->rects + i);
  466. }
  467. }
  468. static void merge_bands(struct BandList *dest, struct BandList *src)
  469. {
  470. int i;
  471. for (i = 0; i < src->count; i++) {
  472. struct Rectangle tmp;
  473. tmp.MinY = src->miny[i];
  474. tmp.MaxY = src->maxy[i];
  475. add_rect_to_bands(dest, &tmp);
  476. }
  477. }
  478. static void region_splitrects_band(struct RectList *rl, struct BandList *bl)
  479. {
  480. int i,j;
  481. for (i = 0; i < rl->count; i++) {
  482. for (j = 0; j < bl->count; j++) {
  483. if (bl->miny[j] == rl->rects[i].MinY && bl->maxy[j] == rl->rects[i].MaxY)
  484. break;
  485. if (rl->rects[i].MinY > bl->maxy[j])
  486. continue;
  487. if (bl->miny[j] == rl->rects[i].MinY) {
  488. struct Rectangle tmpr;
  489. tmpr.MinX = rl->rects[i].MinX;
  490. tmpr.MaxX = rl->rects[i].MaxX;
  491. tmpr.MinY = bl->maxy[j] + 1;
  492. tmpr.MaxY = rl->rects[i].MaxY;
  493. add_rect(rl, tmpr); /* will be processed later */
  494. rl->rects[i].MaxY = bl->maxy[j];
  495. break;
  496. }
  497. write_log (_T("Foo..\n"));
  498. }
  499. }
  500. qsort(rl->rects, rl->count, sizeof (struct Rectangle), regionrect_cmpfn);
  501. }
  502. static void region_coalesce_rects(struct RectList *rl, int do_2nd_pass)
  503. {
  504. int i,j;
  505. /* First pass: Coalesce horizontally */
  506. for (i = j = 0; i < rl->count;) {
  507. int offs = 1;
  508. while (i + offs < rl->count) {
  509. if (rl->rects[i].MinY != rl->rects[i+offs].MinY
  510. || rl->rects[i].MaxY != rl->rects[i+offs].MaxY
  511. || rl->rects[i].MaxX+1 < rl->rects[i+offs].MinX)
  512. break;
  513. rl->rects[i].MaxX = rl->rects[i+offs].MaxX;
  514. offs++;
  515. }
  516. rl->rects[j++] = rl->rects[i];
  517. i += offs;
  518. }
  519. rl->count = j;
  520. if (!do_2nd_pass)
  521. return;
  522. /* Second pass: Coalesce bands */
  523. for (i = 0; i < rl->count;) {
  524. int match = 0;
  525. for (j = i + 1; j < rl->count; j++)
  526. if (rl->rects[i].MinY != rl->rects[j].MinY)
  527. break;
  528. if (j < rl->count && rl->rects[i].MaxY + 1 == rl->rects[j].MinY) {
  529. int k;
  530. match = 1;
  531. for (k = 0; i+k < j; k++) {
  532. if (j+k >= rl->count
  533. || rl->rects[j+k].MinY != rl->rects[j].MinY)
  534. {
  535. match = 0; break;
  536. }
  537. if (rl->rects[i+k].MinX != rl->rects[j+k].MinX
  538. || rl->rects[i+k].MaxX != rl->rects[j+k].MaxX)
  539. {
  540. match = 0;
  541. break;
  542. }
  543. }
  544. if (j+k < rl->count && rl->rects[j+k].MinY == rl->rects[j].MinY)
  545. match = 0;
  546. if (match) {
  547. for (k = 0; i+k < j; k++)
  548. rl->rects[i+k].MaxY = rl->rects[j].MaxY;
  549. memmove(rl->rects + j, rl->rects + j + k, (rl->count - j - k)*sizeof(struct Rectangle));
  550. rl->count -= k;
  551. }
  552. }
  553. if (!match)
  554. i = j;
  555. }
  556. }
  557. static int copy_rects (uaecptr region, struct RectList *rl)
  558. {
  559. uaecptr regionrect;
  560. int numrects = 0;
  561. struct Rectangle b;
  562. regionrect = get_long (region+8);
  563. b.MinX = get_word (region);
  564. b.MinY = get_word (region+2);
  565. b.MaxX = get_word (region+4);
  566. b.MaxY = get_word (region+6);
  567. while (regionrect != 0) {
  568. struct Rectangle tmpr;
  569. tmpr.MinX = (uae_s16)get_word (regionrect+8) + b.MinX;
  570. tmpr.MinY = (uae_s16)get_word (regionrect+10) + b.MinY;
  571. tmpr.MaxX = (uae_s16)get_word (regionrect+12) + b.MinX;
  572. tmpr.MaxY = (uae_s16)get_word (regionrect+14) + b.MinY;
  573. add_rect(rl, tmpr);
  574. regionrect = get_long (regionrect);
  575. numrects++;
  576. }
  577. return numrects;
  578. }
  579. static int rect_in_region(struct RectList *rl, struct Rectangle *r)
  580. {
  581. int i;
  582. int miny = r->MinY;
  583. for (i = 0; i < rl->count; i++) {
  584. int j;
  585. if (rl->rects[i].MaxY < miny)
  586. continue;
  587. if (rl->rects[i].MinY > miny)
  588. break;
  589. if (rl->rects[i].MaxX < r->MinX)
  590. continue;
  591. if (rl->rects[i].MinX > r->MaxX)
  592. break;
  593. /* Overlap! */
  594. j = i;
  595. for (;;) {
  596. if (rl->rects[j].MaxX > r->MaxX) {
  597. miny = rl->rects[i].MaxY + 1;
  598. break;
  599. }
  600. j++;
  601. if (j == rl->count)
  602. break;
  603. if (rl->rects[j].MinX != rl->rects[j-1].MaxX+1)
  604. break;
  605. if (rl->rects[i].MinY != rl->rects[j].MinY)
  606. break;
  607. }
  608. if (miny <= rl->rects[i].MaxY)
  609. break;
  610. }
  611. return 0;
  612. }
  613. typedef void (*regionop)(struct RectList *,struct RectList *,struct RectList *);
  614. static void region_do_ClearRegionRegion(struct RectList *rl1,struct RectList *rl2,
  615. struct RectList *rl3)
  616. {
  617. int i,j;
  618. for (i = j = 0; i < rl2->count && j < rl1->count;) {
  619. struct Rectangle tmpr;
  620. while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  621. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  622. && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  623. && j < rl1->count)
  624. j++;
  625. if (j >= rl1->count)
  626. break;
  627. while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  628. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  629. && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  630. && i < rl2->count)
  631. {
  632. add_rect(rl3, rl2->rects[i]);
  633. i++;
  634. }
  635. if (i >= rl2->count)
  636. break;
  637. tmpr = rl2->rects[i];
  638. while (i < rl2->count && j < rl1->count
  639. && rl1->rects[j].MinY == tmpr.MinY
  640. && rl2->rects[i].MinY == tmpr.MinY
  641. && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  642. && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  643. {
  644. int oldmin = tmpr.MinX;
  645. int oldmax = tmpr.MaxX;
  646. if (tmpr.MinX < rl1->rects[j].MinX) {
  647. tmpr.MaxX = rl1->rects[j].MinX - 1;
  648. add_rect(rl3, tmpr);
  649. }
  650. if (oldmax <= rl1->rects[j].MaxX) {
  651. i++;
  652. if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY)
  653. tmpr = rl2->rects[i];
  654. } else {
  655. tmpr.MinX = rl1->rects[j].MaxX + 1;
  656. tmpr.MaxX = oldmax;
  657. j++;
  658. }
  659. }
  660. }
  661. for(; i < rl2->count; i++)
  662. add_rect(rl3, rl2->rects[i]);
  663. }
  664. static void region_do_AndRegionRegion(struct RectList *rl1,struct RectList *rl2,
  665. struct RectList *rl3)
  666. {
  667. int i,j;
  668. for (i = j = 0; i < rl2->count && j < rl1->count;) {
  669. while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  670. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  671. && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  672. && j < rl1->count)
  673. j++;
  674. if (j >= rl1->count)
  675. break;
  676. while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  677. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  678. && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  679. && i < rl2->count)
  680. i++;
  681. if (i >= rl2->count)
  682. break;
  683. if (rl1->rects[j].MinY == rl2->rects[i].MinY
  684. && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  685. && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  686. {
  687. /* We have an intersection! */
  688. struct Rectangle tmpr;
  689. tmpr = rl2->rects[i];
  690. if (tmpr.MinX < rl1->rects[j].MinX)
  691. tmpr.MinX = rl1->rects[j].MinX;
  692. if (tmpr.MaxX > rl1->rects[j].MaxX)
  693. tmpr.MaxX = rl1->rects[j].MaxX;
  694. add_rect(rl3, tmpr);
  695. if (rl1->rects[j].MaxX == rl2->rects[i].MaxX)
  696. i++, j++;
  697. else if (rl1->rects[j].MaxX > rl2->rects[i].MaxX)
  698. i++;
  699. else
  700. j++;
  701. }
  702. }
  703. }
  704. static void region_do_OrRegionRegion(struct RectList *rl1,struct RectList *rl2,
  705. struct RectList *rl3)
  706. {
  707. int i,j;
  708. for (i = j = 0; i < rl2->count && j < rl1->count;) {
  709. while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  710. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  711. && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  712. && j < rl1->count)
  713. {
  714. add_rect(rl3, rl1->rects[j]);
  715. j++;
  716. }
  717. if (j >= rl1->count)
  718. break;
  719. while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  720. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  721. && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  722. && i < rl2->count)
  723. {
  724. add_rect(rl3, rl2->rects[i]);
  725. i++;
  726. }
  727. if (i >= rl2->count)
  728. break;
  729. if (rl1->rects[j].MinY == rl2->rects[i].MinY
  730. && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  731. && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  732. {
  733. /* We have an intersection! */
  734. struct Rectangle tmpr;
  735. tmpr = rl2->rects[i];
  736. if (tmpr.MinX > rl1->rects[j].MinX)
  737. tmpr.MinX = rl1->rects[j].MinX;
  738. if (tmpr.MaxX < rl1->rects[j].MaxX)
  739. tmpr.MaxX = rl1->rects[j].MaxX;
  740. i++; j++;
  741. for (;;) {
  742. int cont = 0;
  743. if (j < rl1->count && rl1->rects[j].MinY == tmpr.MinY
  744. && tmpr.MaxX+1 >= rl1->rects[j].MinX) {
  745. if (tmpr.MaxX < rl1->rects[j].MaxX)
  746. tmpr.MaxX = rl1->rects[j].MaxX;
  747. j++; cont = 1;
  748. }
  749. if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY
  750. && tmpr.MaxX+1 >= rl2->rects[i].MinX) {
  751. if (tmpr.MaxX < rl2->rects[i].MaxX)
  752. tmpr.MaxX = rl2->rects[i].MaxX;
  753. i++; cont = 1;
  754. }
  755. if (!cont)
  756. break;
  757. }
  758. add_rect(rl3, tmpr);
  759. }
  760. }
  761. for(; i < rl2->count; i++)
  762. add_rect(rl3, rl2->rects[i]);
  763. for(; j < rl1->count; j++)
  764. add_rect(rl3, rl1->rects[j]);
  765. }
  766. static void region_do_XorRegionRegion(struct RectList *rl1,struct RectList *rl2,
  767. struct RectList *rl3)
  768. {
  769. int i,j;
  770. for (i = j = 0; i < rl2->count && j < rl1->count;) {
  771. struct Rectangle tmpr1, tmpr2;
  772. while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  773. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  774. && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  775. && j < rl1->count)
  776. {
  777. add_rect(rl3, rl1->rects[j]);
  778. j++;
  779. }
  780. if (j >= rl1->count)
  781. break;
  782. while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  783. || (rl1->rects[j].MinY == rl2->rects[i].MinY
  784. && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  785. && i < rl2->count)
  786. {
  787. add_rect(rl3, rl2->rects[i]);
  788. i++;
  789. }
  790. if (i >= rl2->count)
  791. break;
  792. tmpr2 = rl2->rects[i];
  793. tmpr1 = rl1->rects[j];
  794. while (i < rl2->count && j < rl1->count
  795. && rl1->rects[j].MinY == tmpr1.MinY
  796. && rl2->rects[i].MinY == tmpr1.MinY
  797. && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  798. && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  799. {
  800. int oldmin2 = tmpr2.MinX;
  801. int oldmax2 = tmpr2.MaxX;
  802. int oldmin1 = tmpr1.MinX;
  803. int oldmax1 = tmpr1.MaxX;
  804. int need_1 = 0, need_2 = 0;
  805. if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX)
  806. {
  807. /*
  808. * ###########
  809. * ****
  810. */
  811. tmpr1.MaxX = tmpr2.MinX - 1;
  812. add_rect(rl3, tmpr1);
  813. tmpr1.MaxX = oldmax1;
  814. tmpr1.MinX = tmpr2.MaxX + 1;
  815. add_rect(rl3, tmpr1);
  816. need_2 = 1;
  817. } else if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  818. /*
  819. * ##########
  820. * *********
  821. */
  822. tmpr1.MaxX = tmpr2.MinX - 1;
  823. add_rect(rl3, tmpr1);
  824. tmpr2.MinX = oldmax1 + 1;
  825. add_rect(rl3, tmpr2);
  826. need_1 = 1;
  827. } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  828. /*
  829. * ##########
  830. * *********
  831. */
  832. tmpr2.MaxX = tmpr1.MinX - 1;
  833. add_rect(rl3, tmpr2);
  834. tmpr1.MinX = oldmax2 + 1;
  835. add_rect(rl3, tmpr1);
  836. need_2 = 1;
  837. } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  838. /*
  839. * ###
  840. * *********
  841. */
  842. tmpr2.MaxX = tmpr1.MinX - 1;
  843. add_rect(rl3, tmpr2);
  844. tmpr2.MaxX = oldmax2;
  845. tmpr2.MinX = tmpr1.MaxX + 1;
  846. add_rect(rl3, tmpr2);
  847. need_1 = 1;
  848. } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  849. /*
  850. * #############
  851. * *********
  852. */
  853. tmpr1.MinX = tmpr2.MaxX + 1;
  854. need_2 = 1;
  855. } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  856. /*
  857. * #########
  858. * *************
  859. */
  860. tmpr2.MinX = tmpr1.MaxX + 1;
  861. need_1 = 1;
  862. } else if (tmpr1.MinX < tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  863. /*
  864. * #############
  865. * *********
  866. */
  867. tmpr1.MaxX = tmpr2.MinX - 1;
  868. add_rect(rl3, tmpr1);
  869. need_2 = need_1 = 1;
  870. } else if (tmpr1.MinX > tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  871. /*
  872. * #########
  873. * *************
  874. */
  875. tmpr2.MaxX = tmpr1.MinX - 1;
  876. add_rect(rl3, tmpr2);
  877. need_2 = need_1 = 1;
  878. } else {
  879. assert(tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX);
  880. need_1 = need_2 = 1;
  881. }
  882. if (need_1) {
  883. j++;
  884. if (j < rl1->count && rl1->rects[j].MinY == tmpr1.MinY)
  885. tmpr1 = rl1->rects[j];
  886. }
  887. if (need_2) {
  888. i++;
  889. if (i < rl2->count && rl2->rects[i].MinY == tmpr2.MinY)
  890. tmpr2 = rl2->rects[i];
  891. }
  892. }
  893. }
  894. for(; i < rl2->count; i++)
  895. add_rect(rl3, rl2->rects[i]);
  896. for(; j < rl1->count; j++)
  897. add_rect(rl3, rl1->rects[j]);
  898. }
  899. static uae_u32 gfxl_perform_regionop(regionop op, int with_rect)
  900. {
  901. int i,j,k;
  902. uaecptr reg1;
  903. uaecptr reg2;
  904. uaecptr tmp, rpp;
  905. struct RectList rl1, rl2, rl3;
  906. struct BandList bl;
  907. int retval = 0;
  908. int numrects2;
  909. init_rectlist(&rl1); init_rectlist(&rl2); init_rectlist(&rl3);
  910. if (with_rect) {
  911. struct Rectangle tmpr;
  912. reg2 = m68k_areg (regs, 0);
  913. numrects2 = copy_rects(reg2, &rl2);
  914. tmpr.MinX = get_word (m68k_areg (regs, 1));
  915. tmpr.MinY = get_word (m68k_areg (regs, 1) + 2);
  916. tmpr.MaxX = get_word (m68k_areg (regs, 1) + 4);
  917. tmpr.MaxY = get_word (m68k_areg (regs, 1) + 6);
  918. add_rect(&rl1, tmpr);
  919. } else {
  920. reg1 = m68k_areg (regs, 0);
  921. reg2 = m68k_areg (regs, 1);
  922. copy_rects(reg1, &rl1);
  923. numrects2 = copy_rects(reg2, &rl2);
  924. }
  925. init_bandlist(&bl);
  926. region_addbands(&rl1, &bl);
  927. region_addbands(&rl2, &bl);
  928. region_splitrects_band(&rl1, &bl);
  929. region_splitrects_band(&rl2, &bl);
  930. region_coalesce_rects(&rl1, 0);
  931. region_coalesce_rects(&rl2, 0);
  932. (*op)(&rl1, &rl2, &rl3);
  933. region_coalesce_rects(&rl3, 1);
  934. rpp = reg2 + 8;
  935. if (rl3.count < numrects2) {
  936. while (numrects2-- != rl3.count) {
  937. tmp = get_long (rpp);
  938. put_long (rpp, get_long (tmp));
  939. amiga_free(tmp, 16);
  940. }
  941. if (rl3.count > 0)
  942. put_long (get_long (rpp) + 4, rpp);
  943. } else if (rl3.count > numrects2) {
  944. while(numrects2++ != rl3.count) {
  945. uaecptr prev = get_long (rpp);
  946. tmp = amiga_malloc(16);
  947. if (tmp == 0)
  948. goto done;
  949. put_long (tmp, prev);
  950. put_long (tmp + 4, rpp);
  951. if (prev != 0)
  952. put_long (prev + 4, tmp);
  953. put_long (rpp, tmp);
  954. }
  955. }
  956. if (rl3.count > 0) {
  957. rpp = reg2 + 8;
  958. for (i = 0; i < rl3.count; i++) {
  959. uaecptr rr = get_long (rpp);
  960. put_word (rr+8, rl3.rects[i].MinX - rl3.bounds.MinX);
  961. put_word (rr+10, rl3.rects[i].MinY - rl3.bounds.MinY);
  962. put_word (rr+12, rl3.rects[i].MaxX - rl3.bounds.MinX);
  963. put_word (rr+14, rl3.rects[i].MaxY - rl3.bounds.MinY);
  964. rpp = rr;
  965. }
  966. if (get_long (rpp) != 0)
  967. write_log (_T("BUG\n"));
  968. }
  969. put_word (reg2+0, rl3.bounds.MinX);
  970. put_word (reg2+2, rl3.bounds.MinY);
  971. put_word (reg2+4, rl3.bounds.MaxX);
  972. put_word (reg2+6, rl3.bounds.MaxY);
  973. retval = 1;
  974. done:
  975. free_rectlist(&rl1); free_rectlist(&rl2); free_rectlist(&rl3);
  976. free_bandlist(&bl);
  977. return retval;
  978. }
  979. static uae_u32 gfxl_AndRegionRegion(void)
  980. {
  981. return gfxl_perform_regionop(region_do_AndRegionRegion, 0);
  982. }
  983. static uae_u32 gfxl_XorRegionRegion(void)
  984. {
  985. return gfxl_perform_regionop(region_do_XorRegionRegion, 0);
  986. }
  987. static uae_u32 gfxl_OrRegionRegion(void)
  988. {
  989. return gfxl_perform_regionop(region_do_OrRegionRegion, 0);
  990. }
  991. static uae_u32 gfxl_ClearRectRegion(void)
  992. {
  993. return gfxl_perform_regionop(region_do_ClearRegionRegion, 1);
  994. }
  995. static uae_u32 gfxl_OrRectRegion(void)
  996. {
  997. return gfxl_perform_regionop(region_do_OrRegionRegion, 1);
  998. }
  999. static uae_u32 gfxl_AndRectRegion(void)
  1000. {
  1001. return gfxl_perform_regionop(region_do_AndRegionRegion, 1);
  1002. }
  1003. static uae_u32 gfxl_XorRectRegion(void)
  1004. {
  1005. return gfxl_perform_regionop(region_do_XorRegionRegion, 1);
  1006. }
  1007. /* Layers code */
  1008. static uae_u32 LY_TryLockLayer(uaecptr layer)
  1009. {
  1010. uaecptr sigsem = layer + 72;
  1011. m68k_areg (regs, 0) = sigsem;
  1012. return CallLib (get_long (4), -576);
  1013. }
  1014. static void LY_LockLayer(uaecptr layer)
  1015. {
  1016. uaecptr sigsem = layer + 72;
  1017. m68k_areg (regs, 0) = sigsem;
  1018. CallLib (get_long (4), -564);
  1019. }
  1020. static void LY_UnlockLayer(uaecptr layer)
  1021. {
  1022. uaecptr sigsem = layer + 72;
  1023. m68k_areg (regs, 0) = sigsem;
  1024. CallLib (get_long (4), -570);
  1025. }
  1026. static void LY_LockLayerInfo(uaecptr li)
  1027. {
  1028. uaecptr sigsem = li + 24;
  1029. m68k_areg (regs, 0) = sigsem;
  1030. CallLib (get_long (4), -564);
  1031. put_byte (li+91, get_byte (li+91)+1);
  1032. }
  1033. static void LY_UnlockLayerInfo(uaecptr li)
  1034. {
  1035. uaecptr sigsem = li + 24;
  1036. put_byte (li+91, get_byte (li+91)-1);
  1037. m68k_areg (regs, 0) = sigsem;
  1038. CallLib (get_long (4), -570);
  1039. }
  1040. static void LY_LockLayers(uaecptr li)
  1041. {
  1042. uaecptr l = get_long (li);
  1043. LY_LockLayerInfo(li);
  1044. while (l != 0) {
  1045. LY_LockLayer(l);
  1046. l = get_long (l);
  1047. }
  1048. LY_UnlockLayerInfo(li);
  1049. }
  1050. static void LY_UnlockLayers(uaecptr li)
  1051. {
  1052. uaecptr l = get_long (li);
  1053. LY_LockLayerInfo(li);
  1054. while (l != 0) {
  1055. LY_UnlockLayer(l);
  1056. l = get_long (l);
  1057. }
  1058. LY_UnlockLayerInfo(li);
  1059. }
  1060. #define LAYER_CLUELESS 0x8000 /* Indicates we know nothing about the layer's regions. */
  1061. #define LAYER_CR_CHANGED 0x4000 /* Indicates that the cliprects in Amiga memory need to be re-done */
  1062. #define LAYER_REDO 0x2000 /* Indicates that we have regions, but they are bogus. */
  1063. static uae_u32 layer_uniq = 1;
  1064. struct MyLayerInfo {
  1065. struct uniq_head head;
  1066. uaecptr amigaos_linfo;
  1067. uniq_list layer_list;
  1068. };
  1069. struct MyLayer {
  1070. struct uniq_head head;
  1071. uaecptr amigaos_layer, rastport;
  1072. struct Rectangle bounds;
  1073. struct RectList clipregion;
  1074. struct RectList obscured;
  1075. struct RectList visible;
  1076. struct BandList big_bands; /* created by obscuring layers */
  1077. struct BandList small_bands; /* big_bands + those from clipregion */
  1078. struct RectList damage;
  1079. struct BandList damage_bands;
  1080. struct MyLayerInfo *mli;
  1081. };
  1082. static uniq_list MyLayerInfo_list = UNIQ_INIT;
  1083. static void LY_InitLayers(uaecptr li)
  1084. {
  1085. memset (get_real_address (li), 0, 92);
  1086. put_long (li + 0, 0); /* top layer */
  1087. put_long (li+84, 0); /* uniq: */
  1088. m68k_areg (regs, 0) = li + 24; CallLib (get_long (4), -558); /* InitSemaphore() */
  1089. put_word (li+88, 0); /* flags (???) */
  1090. put_byte (li+89, 0); /* fatten_count */
  1091. /* @@@ How big can I assume the structure? What's all this 1.0/1.1 cruft? */
  1092. }
  1093. static void LY_FattenLayerInfo(uaecptr li)
  1094. {
  1095. struct MyLayerInfo *mli;
  1096. int fatten_count = get_byte (li + 89);
  1097. if (fatten_count == 0) {
  1098. mli = (struct MyLayerInfo *)malloc(sizeof(struct MyLayerInfo));
  1099. add_uniq(&MyLayerInfo_list, &mli->head, li + 84);
  1100. init_uniq(&mli->layer_list);
  1101. mli->amigaos_linfo = li;
  1102. }
  1103. put_byte (li + 89, fatten_count + 1);
  1104. }
  1105. static void LY_ThinLayerInfo(uaecptr li)
  1106. {
  1107. int fatten_count = get_byte (li + 89)-1;
  1108. put_byte (li + 89, fatten_count);
  1109. if (fatten_count == 0) {
  1110. struct MyLayerInfo *mli = (struct MyLayerInfo *)find_and_rem_uniq(&MyLayerInfo_list, get_long (li+84));
  1111. if (mli)
  1112. free(mli);
  1113. }
  1114. }
  1115. static void build_cliprect (struct MyLayer *l, struct Rectangle *bounds,
  1116. int obscured, uaecptr *crp, uaecptr *prev)
  1117. {
  1118. uaecptr cr = get_long (*crp);
  1119. if (cr == 0) {
  1120. put_long (*crp, cr = amiga_malloc(CLIPRECT_SIZE));
  1121. put_long (cr, 0);
  1122. }
  1123. *prev = cr;
  1124. *crp = cr;
  1125. put_word (cr + 16, bounds->MinX);
  1126. put_word (cr + 18, bounds->MinY);
  1127. put_word (cr + 20, bounds->MaxX);
  1128. put_word (cr + 22, bounds->MaxY);
  1129. put_long (cr + 8, obscured ? l->amigaos_layer : 0); /* cheat */
  1130. put_long (cr + 12, 0); /* no smart refresh yet */
  1131. }
  1132. static void build_cliprects (struct MyLayer *l)
  1133. {
  1134. uaecptr layer = l->amigaos_layer;
  1135. uaecptr cr = layer + 8;
  1136. uaecptr prev = 0;
  1137. uae_u16 flags = get_word (layer + 30);
  1138. int i;
  1139. if ((flags & LAYER_CR_CHANGED) == 0)
  1140. return;
  1141. put_word (layer + 30, flags & ~LAYER_CR_CHANGED);
  1142. for (i = 0; i < l->obscured.count; i++) {
  1143. build_cliprect (l, l->obscured.rects + i, 1, &cr, &prev);
  1144. }
  1145. for (i = 0; i < l->visible.count; i++) {
  1146. build_cliprect (l, l->visible.rects + i, 1, &cr, &prev);
  1147. }
  1148. while ((prev = get_long (cr))) {
  1149. put_long (cr, get_long (prev));
  1150. amiga_free (prev, CLIPRECT_SIZE);
  1151. }
  1152. }
  1153. static void propagate_clueless_redo (struct MyLayerInfo *mli)
  1154. {
  1155. /* For all CLUELESS layers, set the REDO bit for all layers below it that overlap it
  1156. * and delete the data associated with them. */
  1157. uaecptr current_l = get_long (mli->amigaos_linfo);
  1158. while (current_l) {
  1159. struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long (current_l + 24));
  1160. if ((get_word (l->amigaos_layer + 32) & LAYER_CLUELESS) != 0) {
  1161. uaecptr next_l = get_long (current_l);
  1162. put_word (l->amigaos_layer + 32, get_word (l->amigaos_layer + 32) | LAYER_REDO);
  1163. while (next_l) {
  1164. struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long (next_l + 24));
  1165. uae_u16 flags = get_word (l2->amigaos_layer + 32);
  1166. if (l2->bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->bounds.MaxX
  1167. && l2->bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->bounds.MaxY)
  1168. put_word (l2->amigaos_layer + 32, flags | LAYER_REDO);
  1169. if ((flags & (LAYER_REDO|LAYER_CLUELESS)) == 0) {
  1170. free_rectlist(&l->obscured);
  1171. free_rectlist(&l->visible);
  1172. free_bandlist(&l->big_bands);
  1173. free_bandlist(&l->small_bands);
  1174. }
  1175. next_l = get_long (next_l);
  1176. }
  1177. }
  1178. current_l = get_long (current_l);
  1179. }
  1180. }
  1181. static void redo_layers(struct MyLayerInfo *mli, uaecptr bm)
  1182. {
  1183. uaecptr current_l;
  1184. struct RectList tmp_rl;
  1185. propagate_clueless_redo(mli);
  1186. current_l = get_long (mli->amigaos_linfo);
  1187. while (current_l) {
  1188. struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long (current_l + 24));
  1189. uae_u16 flags = get_word (l->amigaos_layer + 32);
  1190. if ((flags & LAYER_REDO) != 0) {
  1191. uaecptr next_l = get_long (current_l+4);
  1192. int have_rects = 0;
  1193. init_rectlist(&l->obscured);
  1194. init_bandlist(&l->big_bands);
  1195. add_rect_to_bands(&l->big_bands, &l->bounds);
  1196. while (next_l) {
  1197. struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long (next_l + 24));
  1198. if (l2->visible.bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->visible.bounds.MaxX
  1199. && l2->visible.bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->visible.bounds.MaxY
  1200. && !rect_in_region (&l->obscured, &l2->visible.bounds))
  1201. {
  1202. add_rect_to_bands(&l->big_bands, &l2->visible.bounds);
  1203. add_rect(&l->obscured, l2->visible.bounds);
  1204. have_rects++;
  1205. }
  1206. next_l = get_long (next_l+4);
  1207. }
  1208. init_rectlist(&l->visible);
  1209. init_rectlist(&tmp_rl);
  1210. add_rect (&tmp_rl, l->bounds);
  1211. region_splitrects_band(&l->obscured, &l->big_bands);
  1212. region_splitrects_band(&tmp_rl, &l->big_bands);
  1213. region_do_ClearRegionRegion(&l->obscured, &tmp_rl, &l->visible);
  1214. flags |= LAYER_CR_CHANGED;
  1215. }
  1216. put_word (l->amigaos_layer + 32, flags & ~(LAYER_CLUELESS|LAYER_REDO));
  1217. current_l = get_long (current_l);
  1218. }
  1219. }
  1220. static struct MyLayer *LY_NewLayer(struct MyLayerInfo *mli, int x0, int x1, int y0, int y1,
  1221. uae_u16 flags, uaecptr bm, uaecptr sbm)
  1222. {
  1223. struct MyLayer *l = (struct MyLayer *)malloc(sizeof (struct MyLayer));
  1224. uaecptr layer = amiga_malloc(LAYER_SIZE);
  1225. memset (get_real_address (layer), 0, LAYER_SIZE);
  1226. l->amigaos_layer = layer;
  1227. put_word (layer + 16, x0); /* bounds */
  1228. put_word (layer + 18, y0);
  1229. put_word (layer + 20, x1);
  1230. put_word (layer + 22, y1);
  1231. put_word (layer + 30, flags | LAYER_CLUELESS);
  1232. put_long (layer + 32, flags & 4 ? sbm : 0); /* ClipRect */
  1233. put_long (layer + 68, mli->amigaos_linfo);
  1234. m68k_areg (regs, 0) = layer + 72; CallLib (get_long (4), -558); /* InitSemaphore() */
  1235. add_uniq(&mli->layer_list, &l->head, layer + 24);
  1236. l->mli = mli;
  1237. l->bounds.MinX = x0;
  1238. l->bounds.MaxX = x1;
  1239. l->bounds.MinY = y0;
  1240. l->bounds.MaxY = y1;
  1241. return l;
  1242. }
  1243. static void LY_DeleteLayer(uaecptr layer)
  1244. {
  1245. uaecptr cr;
  1246. struct MyLayer *l = (struct MyLayer *)find_and_rem_uniq(&l->mli->layer_list, get_long (layer + 24));
  1247. /* Free ClipRects */
  1248. while ((cr = get_long (l->amigaos_layer + 8))) {
  1249. put_long (l->amigaos_layer + 8, get_long (cr));
  1250. amiga_free(cr, CLIPRECT_SIZE);
  1251. }
  1252. amiga_free (l->amigaos_layer, LAYER_SIZE);
  1253. free(l);
  1254. }
  1255. static uaecptr find_behindlayer_position(uaecptr li, uae_u16 flags)
  1256. {
  1257. uaecptr where = li;
  1258. for (;;) {
  1259. uaecptr other = get_long (where);
  1260. /* End of list? */
  1261. if (other == 0)
  1262. break;
  1263. /* Backdrop? */
  1264. if ((get_word (other + 30) & 0x40) > (flags & 0x40))
  1265. break;
  1266. where = other;
  1267. }
  1268. return where;
  1269. }
  1270. static uaecptr LY_CreateLayer(uaecptr li, int x0, int x1, int y0, int y1,
  1271. uae_u16 flags, uaecptr bm, uaecptr sbm, uaecptr where)
  1272. {
  1273. struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq(&MyLayerInfo_list, get_long (li + 84));
  1274. struct MyLayer *l;
  1275. LY_LockLayerInfo(li);
  1276. l = LY_NewLayer(mli, x0, x1, y0, y1, flags, bm, sbm);
  1277. /* Chain into list */
  1278. put_long (l->amigaos_layer, get_long (where));
  1279. put_long (l->amigaos_layer + 4, where == li ? 0 : where);
  1280. if (get_long (where) != 0)
  1281. put_long (get_long (where) + 4, l->amigaos_layer);
  1282. put_long (where, l->amigaos_layer);
  1283. redo_layers(mli, bm);
  1284. build_cliprects(l);
  1285. LY_UnlockLayerInfo(li);
  1286. return l->amigaos_layer;
  1287. }
  1288. static void LY_DisposeLayerInfo(uaecptr li)
  1289. {
  1290. LY_ThinLayerInfo(li);
  1291. amiga_free(li, LINFO_SIZE);
  1292. }
  1293. static uae_u32 layers_NewLayerInfo(void)
  1294. {
  1295. uaecptr li = amiga_malloc(LINFO_SIZE);
  1296. LY_InitLayers(li);
  1297. LY_FattenLayerInfo(li);
  1298. return li;
  1299. }
  1300. static uae_u32 layers_InitLayers(void) { LY_InitLayers (m68k_areg (regs, 0)); return 0; }
  1301. static uae_u32 layers_DisposeLayerInfo(void) { LY_DisposeLayerInfo (m68k_areg (regs, 0)); return 0; }
  1302. static uae_u32 layers_FattenLayerInfo(void) { LY_FattenLayerInfo(m68k_areg (regs, 0)); return 0; }
  1303. static uae_u32 layers_ThinLayerInfo(void) { LY_ThinLayerInfo(m68k_areg (regs, 0)); return 0; }
  1304. static uae_u32 layers_CreateUpfrontLayer(void)
  1305. {
  1306. return LY_CreateLayer(m68k_areg (regs, 0), (uae_s32)m68k_dreg (regs, 0),
  1307. (uae_s32)m68k_dreg (regs, 1), (uae_s32)m68k_dreg (regs, 2),
  1308. (uae_s32)m68k_dreg (regs, 3),
  1309. m68k_dreg (regs, 4),
  1310. m68k_areg (regs, 1), m68k_areg (regs, 2), m68k_areg (regs, 0));
  1311. }
  1312. static uae_u32 layers_CreateBehindLayer(void)
  1313. {
  1314. return LY_CreateLayer(m68k_areg (regs, 0), (uae_s32)m68k_dreg (regs, 0),
  1315. (uae_s32)m68k_dreg (regs, 1), (uae_s32)m68k_dreg (regs, 2),
  1316. (uae_s32)m68k_dreg (regs, 3),
  1317. m68k_dreg (regs, 4),
  1318. m68k_areg (regs, 1), m68k_areg (regs, 2),
  1319. find_behindlayer_position (m68k_areg (regs, 0), m68k_dreg (regs, 4)));
  1320. }
  1321. static uae_u32 layers_DeleteLayer(void) { LY_DeleteLayer (m68k_areg (regs, 1)); return 0; }
  1322. static void LY_LockLayer1(uaecptr layer)
  1323. {
  1324. uaecptr li = get_long (layer + 68);
  1325. struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
  1326. struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
  1327. LY_LockLayer(layer);
  1328. build_cliprects (l);
  1329. }
  1330. static uae_u32 LY_TryLockLayer1(uaecptr layer)
  1331. {
  1332. uaecptr li = get_long (layer + 68);
  1333. struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
  1334. struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
  1335. if (!LY_TryLockLayer(layer))
  1336. return 0;
  1337. build_cliprects (l);
  1338. return 1;
  1339. }
  1340. static uae_u32 gfx_TryLockLayer(void) { return LY_TryLockLayer1 (m68k_areg (regs, 5)); }
  1341. static uae_u32 gfx_LockLayer(void) { LY_LockLayer1 (m68k_areg (regs, 5)); return 0; }
  1342. static uae_u32 gfx_UnlockLayer(void) { LY_UnlockLayer(m68k_areg (regs, 5)); return 0; }
  1343. static uae_u32 layers_LockLayer(void) { LY_LockLayer1 (m68k_areg (regs, 1)); return 0; }
  1344. static uae_u32 layers_LockLayers(void) { LY_LockLayers(m68k_areg (regs, 0)); return 0; }
  1345. static uae_u32 layers_LockLayerInfo(void) { LY_LockLayerInfo(m68k_areg (regs, 0)); return 0; }
  1346. static uae_u32 layers_UnlockLayer(void) { LY_UnlockLayer(m68k_areg (regs, 0)); return 0; }
  1347. static uae_u32 layers_UnlockLayers(void) { LY_UnlockLayers(m68k_areg (regs, 0)); return 0; }
  1348. static uae_u32 layers_UnlockLayerInfo(void) { LY_UnlockLayerInfo(m68k_areg (regs, 0)); return 0; }
  1349. static uae_u32 layers_ScrollLayer(void)
  1350. {
  1351. abort();
  1352. }
  1353. static uae_u32 layers_SizeLayer(void)
  1354. {
  1355. abort();
  1356. }
  1357. static uae_u32 layers_MoveLayer(void)
  1358. {
  1359. abort();
  1360. }
  1361. static uae_u32 layers_UpfrontLayer(void)
  1362. {
  1363. abort();
  1364. }
  1365. static uae_u32 layers_BehindLayer(void)
  1366. {
  1367. abort();
  1368. }
  1369. static uae_u32 layers_MoveLayerInFrontOf(void)
  1370. {
  1371. abort();
  1372. }
  1373. static uae_u32 layers_BeginUpdate(void)
  1374. {
  1375. return 1;
  1376. }
  1377. static uae_u32 layers_EndUpdate(void)
  1378. {
  1379. return 0;
  1380. }
  1381. static uae_u32 layers_WhichLayer(void)
  1382. {
  1383. abort();
  1384. }
  1385. static uae_u32 layers_InstallClipRegion(void)
  1386. {
  1387. return 0;
  1388. }
  1389. static uae_u32 layers_SwapBitsRastPortClipRect(void)
  1390. {
  1391. abort();
  1392. }
  1393. /*
  1394. * Initialization
  1395. */
  1396. static uae_u32 gfxlib_init(void)
  1397. {
  1398. uae_u32 old_arr;
  1399. uaecptr sysbase=m68k_areg (regs, 6);
  1400. int i=0;
  1401. /* Install new routines */
  1402. m68k_dreg (regs, 0)=0;
  1403. m68k_areg (regs, 1)=gfxlibname;
  1404. gfxbase=CallLib (sysbase, -408); /* OpenLibrary */
  1405. m68k_dreg (regs, 0)=0;
  1406. m68k_areg (regs, 1)=layerslibname;
  1407. layersbase=CallLib (sysbase, -408); /* OpenLibrary */
  1408. libemu_InstallFunctionFlags(gfxl_WritePixel, gfxbase, -324, TRAPFLAG_EXTRA_STACK, "");
  1409. libemu_InstallFunctionFlags(gfxl_BltClear, gfxbase, -300, 0, "");
  1410. libemu_InstallFunctionFlags(gfxl_AndRegionRegion, gfxbase, -624, TRAPFLAG_EXTRA_STACK, "");
  1411. libemu_InstallFunctionFlags(gfxl_OrRegionRegion, gfxbase, -612, TRAPFLAG_EXTRA_STACK, "");
  1412. libemu_InstallFunctionFlags(gfxl_XorRegionRegion, gfxbase, -618, TRAPFLAG_EXTRA_STACK, "");
  1413. libemu_InstallFunctionFlags(gfxl_AndRectRegion, gfxbase, -504, TRAPFLAG_EXTRA_STACK, "");
  1414. libemu_InstallFunctionFlags(gfxl_OrRectRegion, gfxbase, -510, TRAPFLAG_EXTRA_STACK, "");
  1415. libemu_InstallFunctionFlags(gfxl_XorRectRegion, gfxbase, -558, TRAPFLAG_EXTRA_STACK, "");
  1416. libemu_InstallFunctionFlags(gfxl_ClearRectRegion, gfxbase, -522, TRAPFLAG_EXTRA_STACK, "");
  1417. #if 0
  1418. #define MAYBE_FUNCTION(a) NULL
  1419. #else
  1420. #define MAYBE_FUNCTION(a) (a)
  1421. #endif
  1422. #if 0
  1423. libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_TryLockLayer), gfxbase, -654, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "AttemptLockLayerRom");
  1424. libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_LockLayer), gfxbase, -432, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "LockLayerRom");
  1425. libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_UnlockLayer), gfxbase, -438, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "UnlockLayerRom");
  1426. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InitLayers), layersbase, -30, TRAPFLAG_EXTRA_STACK, "InitLayers");
  1427. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateUpfrontLayer), layersbase, -36, TRAPFLAG_EXTRA_STACK, "CreateUpfrontLayer");
  1428. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateBehindLayer), layersbase, -42, TRAPFLAG_EXTRA_STACK, "CreateBehindLayer");
  1429. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UpfrontLayer), layersbase, -48, TRAPFLAG_EXTRA_STACK, "UpfrontLayer");
  1430. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BehindLayer), layersbase, -54, TRAPFLAG_EXTRA_STACK, "BehindLayer");
  1431. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayer), layersbase, -60, TRAPFLAG_EXTRA_STACK, "MoveLayer");
  1432. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SizeLayer), layersbase, -66, TRAPFLAG_EXTRA_STACK, "SizeLayer");
  1433. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ScrollLayer), layersbase, -72, TRAPFLAG_EXTRA_STACK, "ScrollLayer");
  1434. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BeginUpdate), layersbase, -78, TRAPFLAG_EXTRA_STACK, "BeginUpdate");
  1435. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_EndUpdate), layersbase, -84, TRAPFLAG_EXTRA_STACK, "EndUpdate");
  1436. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DeleteLayer), layersbase, -90, TRAPFLAG_EXTRA_STACK, "DeleteLayer");
  1437. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayer), layersbase, -96, TRAPFLAG_EXTRA_STACK, "LockLayer");
  1438. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayer), layersbase, -102, TRAPFLAG_EXTRA_STACK, "UnlockLayer");
  1439. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayers), layersbase, -108, TRAPFLAG_EXTRA_STACK, "LockLayers");
  1440. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayers), layersbase, -114, TRAPFLAG_EXTRA_STACK, "UnlockLayers");
  1441. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayerInfo), layersbase, -120, TRAPFLAG_EXTRA_STACK, "LockLayerInfo");
  1442. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SwapBitsRastPortClipRect), layersbase, -126, TRAPFLAG_EXTRA_STACK, "SwapBitsRastPortClipRect");
  1443. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_WhichLayer), layersbase, -132, TRAPFLAG_EXTRA_STACK, "WhichLayer");
  1444. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayerInfo), layersbase, -138, TRAPFLAG_EXTRA_STACK, "UnlockLayerInfo");
  1445. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_NewLayerInfo), layersbase, -144, TRAPFLAG_EXTRA_STACK, "NewLayerInfo");
  1446. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DisposeLayerInfo), layersbase, -150, TRAPFLAG_EXTRA_STACK, "DisposeLayerInfo");
  1447. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_FattenLayerInfo), layersbase, -156, TRAPFLAG_EXTRA_STACK, "FattenLayerInfo");
  1448. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ThinLayerInfo), layersbase, -162, TRAPFLAG_EXTRA_STACK, "ThinLayerInfo");
  1449. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayerInFrontOf), layersbase, -168, TRAPFLAG_EXTRA_STACK, "MoveLayerInFrontOf");
  1450. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InstallClipRegion), layersbase, -174, TRAPFLAG_EXTRA_STACK, "InstallClipRegion");
  1451. #if 0
  1452. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -180, TRAPFLAG_EXTRA_STACK, "MoveSizeLayer");
  1453. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -186, TRAPFLAG_EXTRA_STACK, "CreateUpfrontHookLayer");
  1454. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -192, TRAPFLAG_EXTRA_STACK, "CreateBehindHookLayer");
  1455. libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -198, TRAPFLAG_EXTRA_STACK, "InstallLayerHook");
  1456. #endif
  1457. #endif
  1458. return 0;
  1459. }
  1460. /*
  1461. * Install the gfx-library-replacement
  1462. */
  1463. void gfxlib_install(void)
  1464. {
  1465. uae_u32 begin, end, resname, resid;
  1466. int i;
  1467. if (! currprefs.use_gfxlib)
  1468. return;
  1469. write_log (_T("Warning: you enabled the graphics.library replacement with -g\n")
  1470. "This may be buggy right now, and will not speed things up much.\n");
  1471. resname = ds ("UAEgfxlib.resource");
  1472. resid = ds ("UAE gfxlib 0.1");
  1473. gfxlibname = ds ("graphics.library");
  1474. layerslibname = ds ("layers.library");
  1475. begin = here();
  1476. dw(0x4AFC); /* RTC_MATCHuae_s16 */
  1477. dl(begin); /* our start address */
  1478. dl(0); /* Continue scan here */
  1479. dw(0x0101); /* RTF_COLDSTART; Version 1 */
  1480. dw(0x0805); /* NT_RESOURCE; pri 5 */
  1481. dl(resname); /* name */
  1482. dl(resid); /* ID */
  1483. dl(here() + 4); /* Init area: directly after this */
  1484. calltrap(deftrap2(gfxlib_init, TRAPFLAG_EXTRA_STACK, "")); dw(RTS);
  1485. end = here();
  1486. org(begin + 6);
  1487. dl(end);
  1488. org(end);
  1489. }
  1490. #else
  1491. void gfxlib_install (void)
  1492. {
  1493. }
  1494. #endif