IBITBLT.C 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. #pragma off (unreferenced)
  14. static char rcsid[] = "$Id: ibitblt.c 1.16 1996/12/19 16:51:38 matt Exp $";
  15. #pragma on (unreferenced)
  16. #ifndef MACINTOSH
  17. #include <conio.h>
  18. #include <dos.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "pa_enabl.h" //$$POLY_ACC
  23. #include "types.h"
  24. #include "gr.h"
  25. #include "mem.h"
  26. #include "error.h"
  27. #include "ibitblt.h"
  28. #include "grdef.h"
  29. #if defined(POLY_ACC)
  30. #include "poly_acc.h"
  31. #endif
  32. #define MODE_NONE 0
  33. #define MODE_SKIP 1
  34. #define MODE_DRAW 2
  35. #define OPCODE_ADD 0x81
  36. #define OPCODE_ESI 0xC6 // Followed by a dword (add esi, ????)
  37. #define OPCODE_EDI 0xC7 // Followed by a dword (add edi, ????)
  38. #define OPCODE_MOV_ECX 0xB9 // Followed by a dword (mov ecx,????)
  39. #define OPCODE_MOVSB 0xA4 // movsb
  40. #define OPCODE_16BIT 0x66 // movsw
  41. #define OPCODE_MOVSD 0xA5 // movsd
  42. #define OPCODE_REP 0xF3 // rep
  43. #define OPCODE_RET 0xC3 // ret
  44. #define OPCODE_MOV_EAX 0xB8 // mov eax, im dword
  45. #define OPCODE_MOV_EBX 0xBB // mov ebx, im dword
  46. #define OPCODE_CALL_EBX1 0xFF // call
  47. #define OPCODE_CALL_EBX2 0xD3 // ebx
  48. #define OPCODE_MOV_EDI 0xBF // mov edi, im dword
  49. ubyte *Code_pointer = NULL;
  50. int Code_counter = 0;
  51. int ibitblt_svga_page = 0;
  52. int is_svga = 0;
  53. uint linear_address;
  54. void count_block( int ecx )
  55. {
  56. int blocks;
  57. while ( ecx > 0 ) {
  58. switch(ecx) {
  59. case 1: Code_counter++; ecx = 0; break; // MOVSB
  60. case 2: Code_counter+=2; ecx = 0; break; // MOVSW
  61. case 3: Code_counter+=3; ecx = 0; break; // MOVSW, MOVSB
  62. case 4: Code_counter++; ecx = 0; break; // MOVSD
  63. default:
  64. blocks = ecx / 4;
  65. if ( blocks == 1 )
  66. Code_counter++; // MOVSD
  67. else
  68. Code_counter+=7;
  69. ecx -= blocks*4;
  70. }
  71. }
  72. }
  73. void move_and_count( int dsource, int ddest, int ecx )
  74. {
  75. if ( ecx <= 0 )
  76. return;
  77. if ( dsource > 0 ) {
  78. // ADD ESI, dsource
  79. Code_counter += 6;
  80. }
  81. if ( !is_svga ) {
  82. if ( ddest > 0 ) {
  83. // ADD EDI, ddest
  84. Code_counter += 6;
  85. }
  86. count_block( ecx );
  87. } else {
  88. int p1, p2, o1;
  89. linear_address += ddest; // Skip to next block
  90. p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
  91. p2 = (linear_address+ecx) >> 16;
  92. if ( p1 != ibitblt_svga_page ) {
  93. // Set page
  94. // MOV EAX, ?, CALL EBX
  95. Code_counter += 7;
  96. ibitblt_svga_page = p1;
  97. }
  98. Code_counter += 5; // mov edi, ????
  99. if ( p1 == p2 ) {
  100. count_block( ecx );
  101. } else {
  102. int nbytes;
  103. nbytes = 0xFFFF-o1+1;
  104. count_block( nbytes );
  105. // set page
  106. // MOV EAX, 0
  107. Code_counter += 7; // mov eax,???? call ebx
  108. ibitblt_svga_page = p2;
  109. Code_counter += 5; // mov edi, ????
  110. nbytes = ecx - nbytes;
  111. if (nbytes > 0 )
  112. count_block( nbytes );
  113. }
  114. linear_address += ecx;
  115. }
  116. }
  117. void draw_block( int ecx )
  118. {
  119. int blocks;
  120. int * iptr;
  121. while ( ecx > 0 ) {
  122. switch( ecx ) {
  123. case 1:
  124. // MOVSB
  125. *Code_pointer++ = OPCODE_MOVSB;
  126. ecx = 0;
  127. break;
  128. case 2:
  129. // MOVSW
  130. *Code_pointer++ = OPCODE_16BIT;
  131. *Code_pointer++ = OPCODE_MOVSD;
  132. ecx = 0;
  133. break;
  134. case 3:
  135. // MOVSW, MOVSB
  136. *Code_pointer++ = OPCODE_16BIT;
  137. *Code_pointer++ = OPCODE_MOVSD;
  138. *Code_pointer++ = OPCODE_MOVSB;
  139. ecx = 0;
  140. break;
  141. case 4:
  142. // MOVSD
  143. *Code_pointer++ = OPCODE_MOVSD;
  144. ecx = 0;
  145. break;
  146. default:
  147. blocks = ecx / 4;
  148. if ( blocks == 1 ) {
  149. // MOVSD
  150. *Code_pointer++ = OPCODE_MOVSD;
  151. } else {
  152. // MOV ECX, blocks
  153. *Code_pointer++ = OPCODE_MOV_ECX;
  154. iptr = (int *)Code_pointer;
  155. *iptr++ = blocks;
  156. Code_pointer = (ubyte *)iptr;
  157. // REP MOVSD
  158. *Code_pointer++ = OPCODE_REP;
  159. *Code_pointer++ = OPCODE_MOVSD;
  160. }
  161. ecx -= blocks*4;
  162. }
  163. }
  164. }
  165. void move_and_draw( int dsource, int ddest, int ecx )
  166. {
  167. int * iptr;
  168. if ( ecx <= 0 )
  169. return;
  170. if ( dsource > 0 ) {
  171. // ADD ESI, dsource
  172. *Code_pointer++ = OPCODE_ADD;
  173. *Code_pointer++ = OPCODE_ESI;
  174. iptr = (int *)Code_pointer;
  175. *iptr++ = dsource;
  176. Code_pointer = (ubyte *)iptr;
  177. }
  178. if ( !is_svga ) {
  179. if ( ddest > 0 ) {
  180. // ADD EDI, ddest
  181. *Code_pointer++ = OPCODE_ADD;
  182. *Code_pointer++ = OPCODE_EDI;
  183. iptr = (int *)Code_pointer;
  184. *iptr++ = ddest;
  185. Code_pointer = (ubyte *)iptr;
  186. }
  187. draw_block( ecx );
  188. } else {
  189. unsigned int temp;
  190. int temp_offset;
  191. int p1, p2, o1;
  192. linear_address += ddest; // Skip to next block
  193. p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
  194. p2 = (linear_address+ecx) >> 16;
  195. if ( p1 != ibitblt_svga_page ) {
  196. // Set page
  197. // MOV EAX, 0
  198. *Code_pointer++ = OPCODE_MOV_EAX;
  199. temp = p1;
  200. memcpy( Code_pointer, &temp, sizeof(int) );
  201. Code_pointer += sizeof(int);
  202. // CALL EBX
  203. *Code_pointer++ = OPCODE_CALL_EBX1;
  204. *Code_pointer++ = OPCODE_CALL_EBX2;
  205. ibitblt_svga_page = p1;
  206. }
  207. temp_offset = 0xA0000 + o1;
  208. *Code_pointer++ = OPCODE_MOV_EDI;
  209. iptr = (int *)Code_pointer;
  210. *iptr++ = temp_offset;
  211. Code_pointer = (ubyte *)iptr;
  212. if ( p1 == p2 ) {
  213. draw_block( ecx );
  214. } else {
  215. int nbytes;
  216. nbytes = 0xFFFF-o1+1;
  217. draw_block( nbytes );
  218. // set page
  219. // MOV EAX, 0
  220. *Code_pointer++ = OPCODE_MOV_EAX;
  221. temp = p2;
  222. memcpy( Code_pointer, &temp, sizeof(int) );
  223. Code_pointer += sizeof(int);
  224. // CALL EBX
  225. *Code_pointer++ = OPCODE_CALL_EBX1;
  226. *Code_pointer++ = OPCODE_CALL_EBX2;
  227. ibitblt_svga_page = p2;
  228. temp_offset = 0xA0000;
  229. *Code_pointer++ = OPCODE_MOV_EDI;
  230. iptr = (int *)Code_pointer;
  231. *iptr++ = temp_offset;
  232. Code_pointer = (ubyte *)iptr;
  233. nbytes = ecx - nbytes;
  234. if (nbytes > 0 )
  235. draw_block( nbytes );
  236. }
  237. linear_address += ecx;
  238. }
  239. }
  240. //-----------------------------------------------------------------------------------------
  241. // Given bitmap, bmp, finds the size of the code
  242. int gr_ibitblt_find_code_size_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
  243. {
  244. int x,y;
  245. ubyte pixel;
  246. int draw_mode = MODE_NONE;
  247. int source_offset = 0;
  248. int dest_offset = 0;
  249. int num_to_draw, draw_start_source, draw_start_dest;
  250. int esi, edi;
  251. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  252. Code_counter = 0;
  253. if ( dest_type == BM_SVGA ) {
  254. Code_counter += 1+4; // move ebx, gr_vesa_set_page
  255. Code_counter += 1+4; // move eax, 0
  256. Code_counter += 2; // call ebx
  257. ibitblt_svga_page = 0;
  258. linear_address = 0;
  259. is_svga = 1;
  260. } else {
  261. is_svga = 0;
  262. }
  263. esi = source_offset = 0;
  264. edi = dest_offset = 0;
  265. draw_start_source = draw_start_dest = 0;
  266. for ( y=sy; y<sy+sh; y++ ) {
  267. for ( x=sx; x<sx+sw; x++ ) {
  268. dest_offset = y*mask_bmp->bm_rowsize+x;
  269. pixel = mask_bmp->bm_data[dest_offset];
  270. if ( pixel!=255 ) {
  271. switch ( draw_mode) {
  272. case MODE_DRAW:
  273. move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
  274. esi = draw_start_source + num_to_draw;
  275. edi = draw_start_dest + num_to_draw;
  276. // fall through!!!
  277. case MODE_NONE:
  278. case MODE_SKIP:
  279. break;
  280. }
  281. draw_mode = MODE_SKIP;
  282. } else {
  283. switch ( draw_mode) {
  284. case MODE_SKIP:
  285. case MODE_NONE:
  286. draw_start_source = source_offset;
  287. draw_start_dest = dest_offset;
  288. num_to_draw = 0;
  289. // fall through
  290. case MODE_DRAW:
  291. num_to_draw++;
  292. break;
  293. }
  294. draw_mode = MODE_DRAW;
  295. }
  296. source_offset++;
  297. }
  298. if ( draw_mode == MODE_DRAW ) {
  299. move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
  300. esi = draw_start_source + num_to_draw;
  301. edi = draw_start_dest + num_to_draw;
  302. }
  303. draw_mode = MODE_NONE;
  304. source_offset += (srowsize - sw);
  305. }
  306. Code_counter++; // for return
  307. //printf( "Code will be %d bytes\n", Code_counter );
  308. Code_counter += 16; // for safety was 16
  309. return Code_counter;
  310. }
  311. int gr_ibitblt_find_code_size( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  312. {
  313. return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
  314. }
  315. int gr_ibitblt_find_code_size_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  316. {
  317. return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
  318. }
  319. //-----------------------------------------------------------------------------------------
  320. // Given bitmap, bmp, create code that transfers a bitmap of size sw*sh to position
  321. // (sx,sy) on top of bmp, only overwritting transparent pixels of the bitmap.
  322. ubyte *gr_ibitblt_create_mask_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
  323. {
  324. int x,y;
  325. ubyte pixel;
  326. int draw_mode = MODE_NONE;
  327. int source_offset = 0;
  328. int dest_offset = 0;
  329. int num_to_draw, draw_start_source, draw_start_dest;
  330. int esi, edi;
  331. int code_size;
  332. ubyte *code;
  333. uint temp;
  334. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  335. if ( dest_type == BM_SVGA )
  336. code_size = gr_ibitblt_find_code_size_svga( mask_bmp, sx, sy, sw, sh, srowsize );
  337. else
  338. code_size = gr_ibitblt_find_code_size( mask_bmp, sx, sy, sw, sh, srowsize );
  339. code = malloc( code_size );
  340. if ( code == NULL )
  341. return NULL;
  342. Code_pointer = code;
  343. if ( dest_type == BM_SVGA ) {
  344. // MOV EBX, gr_vesa_setpage
  345. *Code_pointer++ = OPCODE_MOV_EBX;
  346. temp = (uint)gr_vesa_setpage;
  347. memcpy( Code_pointer, &temp, sizeof(int) );
  348. Code_pointer += sizeof(int);
  349. // MOV EAX, 0
  350. *Code_pointer++ = OPCODE_MOV_EAX;
  351. temp = 0;
  352. memcpy( Code_pointer, &temp, sizeof(int) );
  353. Code_pointer += sizeof(int);
  354. // CALL EBX
  355. *Code_pointer++ = OPCODE_CALL_EBX1;
  356. *Code_pointer++ = OPCODE_CALL_EBX2;
  357. ibitblt_svga_page = 0;
  358. is_svga = 1;
  359. linear_address = 0;
  360. } else {
  361. is_svga = 0;
  362. }
  363. esi = source_offset = 0;
  364. edi = dest_offset = 0;
  365. draw_start_source = draw_start_dest = 0;
  366. for ( y=sy; y<sy+sh; y++ ) {
  367. for ( x=sx; x<sx+sw; x++ ) {
  368. dest_offset = y*mask_bmp->bm_rowsize+x;
  369. pixel = mask_bmp->bm_data[dest_offset];
  370. if ( pixel!=255 ) {
  371. switch ( draw_mode) {
  372. case MODE_DRAW:
  373. move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
  374. esi = draw_start_source + num_to_draw;
  375. edi = draw_start_dest + num_to_draw;
  376. // fall through!!!
  377. case MODE_NONE:
  378. case MODE_SKIP:
  379. break;
  380. }
  381. draw_mode = MODE_SKIP;
  382. } else {
  383. switch ( draw_mode) {
  384. case MODE_SKIP:
  385. case MODE_NONE:
  386. draw_start_source = source_offset;
  387. draw_start_dest = dest_offset;
  388. num_to_draw = 0;
  389. // fall through
  390. case MODE_DRAW:
  391. num_to_draw++;
  392. break;
  393. }
  394. draw_mode = MODE_DRAW;
  395. }
  396. source_offset++;
  397. }
  398. if ( draw_mode == MODE_DRAW ) {
  399. move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
  400. esi = draw_start_source + num_to_draw;
  401. edi = draw_start_dest + num_to_draw;
  402. }
  403. draw_mode = MODE_NONE;
  404. source_offset += (srowsize - sw);
  405. }
  406. *Code_pointer++ = OPCODE_RET;
  407. if ( Code_pointer >= &code[code_size-1] )
  408. Error( "ibitblt overwrote allocated code block\n" );
  409. //printf( "Code is %d bytes\n", Code_pointer - code );
  410. return code;
  411. }
  412. ubyte *gr_ibitblt_create_mask( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  413. {
  414. return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
  415. }
  416. #if defined(POLY_ACC)
  417. ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy)
  418. {
  419. if(w == 0 || h == 0)
  420. return buf;
  421. if(gencode)
  422. {
  423. buf[0] = (w << 16) | h;
  424. buf[1] = (sx << 16) | sy;
  425. buf[2] = (dx << 16) | dy;
  426. }
  427. return buf + 3;
  428. }
  429. ubyte *gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  430. {
  431. ulong *ret, *code = 0;
  432. int pass, x, y, n;
  433. ushort *s;
  434. Assert(mask_bmp->bm_type == BM_LINEAR15);
  435. srowsize /= PA_BPP;
  436. pa_flush();
  437. // make two passes, first pass gets size of output block, second actually creates data.
  438. for(pass = 0; pass != 2; ++pass)
  439. {
  440. for (y = sy; y < sy + sh; y++ )
  441. {
  442. // first byte of interest in mask
  443. s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP);
  444. for ( x=0; x < sw; )
  445. {
  446. for(; x != sw && (s[x] & 0x8000); ++x) // while opaque...
  447. ;
  448. for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent...
  449. ;
  450. code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y);
  451. }
  452. }
  453. if(pass == 0)
  454. {
  455. ret = malloc((int)code + sizeof(ulong));
  456. ret[0] = (int)code / sizeof(ulong); // store num ulongs in list.
  457. code = ret + 1;
  458. }
  459. }
  460. return (ubyte *)ret;
  461. }
  462. #else
  463. ubyte *gr_ibitblt_create_mask_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  464. {
  465. return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
  466. }
  467. #endif
  468. void gr_ibitblt_do_asm(char *start_si, char *start_di, ubyte * code);
  469. #pragma aux gr_ibitblt_do_asm parm [esi] [edi] [eax] modify [ecx edi esi eax] = \
  470. "pusha" \
  471. "cld" \
  472. "call eax" \
  473. "popa"
  474. void gr_ibitblt(grs_bitmap * source_bmp, grs_bitmap * dest_bmp, ubyte * mask )
  475. {
  476. #if defined(POLY_ACC)
  477. Assert(source_bmp->bm_type == BM_LINEAR15);
  478. pa_ibitblt(source_bmp->bm_data, dest_bmp->bm_data, mask);
  479. #else
  480. if (mask != NULL )
  481. gr_ibitblt_do_asm( source_bmp->bm_data, dest_bmp->bm_data, mask );
  482. #endif
  483. }
  484. void gr_ibitblt_find_hole_size( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy )
  485. {
  486. int x, y, count=0;
  487. #if defined(POLY_ACC)
  488. short c;
  489. #else
  490. ubyte c;
  491. #endif
  492. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  493. #if defined(POLY_ACC)
  494. Assert(mask_bmp->bm_type == BM_LINEAR15);
  495. pa_flush();
  496. #endif
  497. *minx = mask_bmp->bm_w-1;
  498. *maxx = 0;
  499. *miny = mask_bmp->bm_h-1;
  500. *maxy = 0;
  501. for ( y=0; y<mask_bmp->bm_h; y++ )
  502. for ( x=0; x<mask_bmp->bm_w; x++ ) {
  503. #if defined(POLY_ACC)
  504. c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP);
  505. if (c >= 0) { // hi true means opaque.
  506. #else
  507. c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
  508. if (c == 255 ) {
  509. #endif
  510. if ( x < *minx ) *minx = x;
  511. if ( y < *miny ) *miny = y;
  512. if ( x > *maxx ) *maxx = x;
  513. if ( y > *maxy ) *maxy = y;
  514. count++;
  515. }
  516. }
  517. if ( count == 0 ) {
  518. Error( "Bitmap for ibitblt doesn't have transparency!\n" );
  519. }
  520. }
  521. #else // ifdef MACINTOSH
  522. #include "pa_enabl.h"
  523. #include "pstypes.h"
  524. #include "gr.h"
  525. #include "ibitblt.h"
  526. #include "error.h"
  527. #include "mem.h"
  528. #if defined(POLY_ACC)
  529. #include "poly_acc.h"
  530. #endif
  531. #define FIND_START 1
  532. #define FIND_STOP 2
  533. #define MAX_WIDTH 640
  534. #define MAX_SCANLINES 480
  535. #define MAX_HOLES 5
  536. static short start_points[MAX_SCANLINES][MAX_HOLES];
  537. static short hole_length[MAX_SCANLINES][MAX_HOLES];
  538. static double *scanline = NULL;
  539. void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double)
  540. {
  541. int x, y, sw, sh, srowsize, drowsize, dstart, sy, dy;
  542. ubyte *src, *dest;
  543. short *current_hole, *current_hole_length;
  544. // variable setup
  545. if ( PAEnabled )
  546. return;
  547. sw = src_bmp->bm_w;
  548. sh = src_bmp->bm_h;
  549. srowsize = src_bmp->bm_rowsize;
  550. drowsize = dest_bmp->bm_rowsize;
  551. src = src_bmp->bm_data;
  552. dest = dest_bmp->bm_data;
  553. sy = 0;
  554. while (start_points[sy][0] == -1) {
  555. sy++;
  556. dest += drowsize;
  557. }
  558. if (pixel_double) {
  559. ubyte *scan = (ubyte *)scanline; // set up for byte processing of scanline
  560. dy = sy;
  561. for (y = sy; y < sy + sh; y++) {
  562. int i, j;
  563. gr_linear_movsd_double(src, scan, sw*2);
  564. current_hole = start_points[dy];
  565. current_hole_length = hole_length[dy];
  566. for (x = 0; x < MAX_HOLES; x++) {
  567. if (*current_hole == -1)
  568. break;
  569. dstart = *current_hole;
  570. gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
  571. current_hole++;
  572. current_hole_length++;
  573. }
  574. dy++;
  575. dest += drowsize;
  576. current_hole = start_points[dy];
  577. current_hole_length = hole_length[dy];
  578. for (x = 0;x < MAX_HOLES; x++) {
  579. if (*current_hole == -1)
  580. break;
  581. dstart = *current_hole;
  582. gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
  583. current_hole++;
  584. current_hole_length++;
  585. }
  586. dy++;
  587. dest += drowsize;
  588. src += srowsize;
  589. }
  590. } else {
  591. Assert(sw <= MAX_WIDTH);
  592. Assert(sh <= MAX_SCANLINES);
  593. for (y = sy; y < sy + sh; y++) {
  594. for (x = 0; x < MAX_HOLES; x++) {
  595. if (start_points[y][x] == -1)
  596. break;
  597. dstart = start_points[y][x];
  598. gr_linear_movsd(&(src[dstart]), &(dest[dstart]), hole_length[y][x]);
  599. }
  600. dest += drowsize;
  601. src += srowsize;
  602. }
  603. }
  604. }
  605. #if defined(POLY_ACC)
  606. ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy)
  607. {
  608. if(w == 0 || h == 0)
  609. return buf;
  610. if(gencode)
  611. {
  612. buf[0] = (w << 16) | h;
  613. buf[1] = (sx << 16) | sy;
  614. buf[2] = (dx << 16) | dy;
  615. }
  616. return buf + 3;
  617. }
  618. void gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
  619. {
  620. ulong *ret, *code = 0;
  621. int pass, x, y, n;
  622. ushort *s;
  623. Assert(mask_bmp->bm_type == BM_LINEAR15);
  624. srowsize /= PA_BPP;
  625. pa_flush();
  626. // make two passes, first pass gets size of output block, second actually creates data.
  627. for(pass = 0; pass != 2; ++pass)
  628. {
  629. for (y = sy; y < sy + sh; y++ )
  630. {
  631. // first byte of interest in mask
  632. s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP);
  633. for ( x=0; x < sw; )
  634. {
  635. for(; x != sw && (s[x] & 0x8000); ++x) // while opaque...
  636. ;
  637. for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent...
  638. ;
  639. code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y);
  640. }
  641. }
  642. if(pass == 0) {
  643. ret = malloc((int)code + sizeof(ulong));
  644. ret[0] = (int)code / sizeof(ulong); // store num ulongs in list.
  645. code = ret + 1;
  646. }
  647. }
  648. // return (ubyte *)ret;
  649. }
  650. #endif
  651. void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize)
  652. {
  653. int x, y, dest_offset;
  654. ubyte pixel, mode;
  655. int count = 0;
  656. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  657. for (y = 0; y < MAX_SCANLINES; y++) {
  658. for (x = 0; x < MAX_HOLES; x++) {
  659. start_points[y][x] = -1;
  660. hole_length[y][x] = -1;
  661. }
  662. }
  663. for (y = sy; y < sy+sh; y++) {
  664. count = 0;
  665. mode = FIND_START;
  666. for (x = sx; x < sx + sw; x++) {
  667. if ((mode == FIND_START) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] == TRANSPARENCY_COLOR)) {
  668. start_points[y][count] = x;
  669. mode = FIND_STOP;
  670. } else if ((mode == FIND_STOP) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] != TRANSPARENCY_COLOR)) {
  671. hole_length[y][count] = x - start_points[y][count];
  672. count++;
  673. mode = FIND_START;
  674. }
  675. }
  676. if (mode == FIND_STOP) {
  677. hole_length[y][count] = x - start_points[y][count];
  678. count++;
  679. }
  680. Assert(count <= MAX_HOLES);
  681. }
  682. }
  683. #if defined(POLY_ACC)
  684. void gr_ibitblt_find_hole_size_pa( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy )
  685. {
  686. int x, y, count=0;
  687. short c;
  688. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  689. Assert(mask_bmp->bm_type == BM_LINEAR15);
  690. while(!pa_idle());
  691. *minx = mask_bmp->bm_w-1;
  692. *maxx = 0;
  693. *miny = mask_bmp->bm_h-1;
  694. *maxy = 0;
  695. for ( y=0; y<mask_bmp->bm_h; y++ )
  696. for ( x=0; x<mask_bmp->bm_w; x++ ) {
  697. c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP);
  698. if (c >= 0) { // hi true means opaque.
  699. if ( x < *minx ) *minx = x;
  700. if ( y < *miny ) *miny = y;
  701. if ( x > *maxx ) *maxx = x;
  702. if ( y > *maxy ) *maxy = y;
  703. count++;
  704. }
  705. }
  706. if ( count == 0 ) {
  707. Error( "Bitmap for ibitblt doesn't have transparency!\n" );
  708. }
  709. }
  710. #endif
  711. void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy)
  712. {
  713. ubyte c;
  714. int x, y, count = 0;
  715. #if defined(POLY_ACC)
  716. if ( PAEnabled ) {
  717. gr_ibitblt_find_hole_size_pa( mask_bmp, minx, miny, maxx, maxy );
  718. return;
  719. }
  720. #endif
  721. Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
  722. Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT );
  723. *minx = mask_bmp->bm_w - 1;
  724. *maxx = 0;
  725. *miny = mask_bmp->bm_h - 1;
  726. *maxy = 0;
  727. if (scanline == NULL)
  728. scanline = (double *)malloc(sizeof(double) * (MAX_WIDTH / sizeof(double)));
  729. for (y = 0; y < mask_bmp->bm_h; y++) {
  730. for (x = 0; x < mask_bmp->bm_w; x++) {
  731. c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
  732. if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here.
  733. count++;
  734. if (x < *minx) *minx = x;
  735. if (y < *miny) *miny = y;
  736. if (x > *maxx) *maxx = x;
  737. if (y > *maxy) *maxy = y;
  738. }
  739. }
  740. }
  741. Assert (count);
  742. }
  743. #endif // ifdef MACINTOSH