r_blit.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. // alphachannel safe 11/21/99
  25. // highly optimized on 10/10/00 JF. MMX.
  26. #include <windows.h>
  27. #include <commctrl.h>
  28. #include "r_defs.h"
  29. #include "resource.h"
  30. #include "timing.h"
  31. #include "../Agave/Language/api_language.h"
  32. #ifndef LASER
  33. #define C_THISCLASS C_BlitClass
  34. #define MOD_NAME "Trans / Blitter Feedback"
  35. static const unsigned int revn[2]={0xff00ff,0xff00ff};//{0x1000100,0x1000100}; <<- this is actually more correct, but we're going for consistency vs. the non-mmx ver-jf
  36. static const int zero=0;
  37. class C_THISCLASS : public C_RBASE {
  38. protected:
  39. public:
  40. C_THISCLASS();
  41. virtual ~C_THISCLASS();
  42. virtual int render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h);
  43. virtual char *get_desc() { static char desc[128]; return (!desc[0]?WASABI_API_LNGSTRING_BUF(IDS_TRANS_BLITTER_FEEDBACK,desc,128):desc); }
  44. virtual HWND conf(HINSTANCE hInstance, HWND hwndParent);
  45. virtual void load_config(unsigned char *data, int len);
  46. virtual int save_config(unsigned char *data);
  47. int scale, scale2, blend,beatch;
  48. int fpos;
  49. int subpixel;
  50. int blitter_normal(int *framebuffer, int *fbout, int w, int h, int f_val);
  51. int blitter_out(int *framebuffer, int *fbout, int w, int h, int f_val);
  52. };
  53. #define PUT_INT(y) data[pos]=(y)&255; data[pos+1]=(y>>8)&255; data[pos+2]=(y>>16)&255; data[pos+3]=(y>>24)&255
  54. #define GET_INT() (data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24))
  55. void C_THISCLASS::load_config(unsigned char *data, int len)
  56. {
  57. int pos=0;
  58. if (len-pos >= 4) { scale=GET_INT(); pos+=4; }
  59. if (len-pos >= 4) { scale2=GET_INT(); pos+=4; }
  60. if (len-pos >= 4) { blend=GET_INT(); pos+=4; }
  61. if (len-pos >= 4) { beatch=GET_INT(); pos+=4; }
  62. if (len-pos >= 4) { subpixel=GET_INT(); pos+=4; }
  63. else subpixel=0;
  64. fpos=scale;
  65. }
  66. int C_THISCLASS::save_config(unsigned char *data)
  67. {
  68. int pos=0;
  69. PUT_INT(scale); pos+=4;
  70. PUT_INT(scale2); pos+=4;
  71. PUT_INT(blend); pos+=4;
  72. PUT_INT(beatch); pos+=4;
  73. PUT_INT(subpixel); pos+=4;
  74. return pos;
  75. }
  76. C_THISCLASS::C_THISCLASS()
  77. {
  78. scale=30;
  79. scale2=30;
  80. blend=0;
  81. fpos=scale;
  82. beatch=0;
  83. subpixel=1;
  84. }
  85. C_THISCLASS::~C_THISCLASS()
  86. {
  87. }
  88. int C_THISCLASS::blitter_out(int *framebuffer, int *fbout, int w, int h, int f_val)
  89. {
  90. const int adj=7;
  91. int ds_x = ((f_val+(1<<adj)-32)<<(16-adj));
  92. int x_len=((w<<16)/ds_x)&~3;
  93. int y_len=(h<<16)/ds_x;
  94. if (x_len >= w || y_len >= h) return 0;
  95. int start_x=(w-x_len)/2;
  96. int start_y=(h-y_len)/2;
  97. int s_y=32768;
  98. int *dest=(int *)framebuffer+start_y*w + start_x;
  99. int *src=(int *)fbout+start_y*w + start_x;
  100. int y;
  101. fbout += start_y*w;
  102. for (y = 0; y < y_len; y ++)
  103. {
  104. int s_x=32768;
  105. unsigned int *src = ((unsigned int *) framebuffer)+(s_y>>16)*w;
  106. unsigned int *old_dest=((unsigned int *)fbout) + start_x;
  107. s_y+=ds_x;
  108. if (!blend)
  109. {
  110. int x=x_len/4;
  111. while (x--)
  112. {
  113. old_dest[0]=src[s_x>>16];
  114. s_x += ds_x;
  115. old_dest[1]=src[s_x>>16];
  116. s_x += ds_x;
  117. old_dest[2]=src[s_x>>16];
  118. s_x += ds_x;
  119. old_dest[3]=src[s_x>>16];
  120. s_x += ds_x;
  121. old_dest+=4;
  122. }
  123. }
  124. else
  125. {
  126. unsigned int *s2=(unsigned int *)framebuffer+((y+start_y)*w)+start_x;
  127. int x=x_len/4;
  128. while (x--)
  129. {
  130. old_dest[0]=BLEND_AVG(s2[0],src[s_x>>16]);
  131. s_x += ds_x;
  132. old_dest[1]=BLEND_AVG(s2[1],src[s_x>>16]);
  133. s_x += ds_x;
  134. old_dest[2]=BLEND_AVG(s2[2],src[s_x>>16]);
  135. s_x += ds_x;
  136. old_dest[3]=BLEND_AVG(s2[3],src[s_x>>16]);
  137. s2+=4;
  138. old_dest+=4;
  139. s_x += ds_x;
  140. }
  141. }
  142. fbout += w;
  143. }
  144. for (y = 0; y < y_len; y ++)
  145. {
  146. memcpy(dest,src,x_len*sizeof(int));
  147. dest+=w;
  148. src+=w;
  149. }
  150. return 0;
  151. }
  152. int C_THISCLASS::blitter_normal(int *framebuffer, int *fbout, int w, int h, int f_val)
  153. {
  154. int ds_x = ((f_val+32)<<16)/64;
  155. int isx=(((w<<16)-((ds_x*w)))/2);
  156. int s_y=(((h<<16)-((ds_x*h)))/2);
  157. if (subpixel)
  158. {
  159. int y;
  160. for (y = 0; y < h; y ++)
  161. {
  162. int s_x=isx;
  163. unsigned int *src = ((unsigned int *) framebuffer)+(s_y>>16)*w;
  164. int ypart=(s_y>>8)&0xff;
  165. s_y+=ds_x;
  166. #ifdef NO_MMX
  167. {
  168. ypart=(ypart*255)>>8;
  169. int x=w/4;
  170. while (x--)
  171. {
  172. fbout[0]=BLEND4(src+(s_x>>16),w,(s_x>>8)&0xff,ypart);
  173. s_x += ds_x;
  174. fbout[1]=BLEND4(src+(s_x>>16),w,(s_x>>8)&0xff,ypart);
  175. s_x += ds_x;
  176. fbout[2]=BLEND4(src+(s_x>>16),w,(s_x>>8)&0xff,ypart);
  177. s_x += ds_x;
  178. fbout[3]=BLEND4(src+(s_x>>16),w,(s_x>>8)&0xff,ypart);
  179. s_x += ds_x;
  180. fbout+=4;
  181. }
  182. }
  183. #else
  184. {
  185. __int64 mem5,mem7;
  186. __asm
  187. {
  188. mov edi, fbout
  189. mov esi, w
  190. movd mm7, ypart
  191. punpcklwd mm7,mm7
  192. movq mm5, revn
  193. punpckldq mm7,mm7
  194. psubw mm5, mm7
  195. mov ecx, esi
  196. movq mem5,mm5
  197. movq mem7,mm7
  198. shr ecx, 1
  199. mov edx, s_x
  200. align 16
  201. mmx_scale_loop1:
  202. mov ebx, edx
  203. mov eax, edx
  204. shr eax, 14
  205. add edx, ds_x
  206. shr ebx, 8
  207. and eax, ~3
  208. add eax, src
  209. and ebx, 0xff
  210. movd mm6, ebx
  211. //
  212. movq mm4, revn
  213. punpcklwd mm6,mm6
  214. movd mm0, [eax]
  215. punpckldq mm6,mm6
  216. movd mm1, [eax+4]
  217. psubw mm4, mm6
  218. movd mm2, [eax+esi*4]
  219. punpcklbw mm0, [zero]
  220. movd mm3, [eax+esi*4+4]
  221. pmullw mm0, mm4 // mm0 used in divide for 3 cycles
  222. punpcklbw mm1, [zero]
  223. mov eax, edx
  224. pmullw mm1, mm6 // mm1 used in divide for 3 cycles
  225. punpcklbw mm2, [zero]
  226. pmullw mm2, mm4 // mm2 used in divide for 3 cycles
  227. punpcklbw mm3, [zero]
  228. pmullw mm3, mm6 // mm3 used in divide for 3 cycles
  229. shr eax, 14
  230. mov ebx, edx
  231. and eax, ~3
  232. paddw mm0, mm1
  233. shr ebx, 8
  234. psrlw mm0, 8
  235. add eax, src
  236. paddw mm2, mm3
  237. and ebx, 0xff
  238. pmullw mm0, mem5
  239. psrlw mm2, 8
  240. pmullw mm2, mem7
  241. add edx, ds_x
  242. movd mm6, ebx
  243. //
  244. movq mm4, revn
  245. punpcklwd mm6,mm6
  246. movd mm1, [eax+4]
  247. //
  248. movd mm7, [eax+esi*4]
  249. paddw mm0, mm2
  250. movd mm5, [eax]
  251. psrlw mm0, 8
  252. movd mm3, [eax+esi*4+4]
  253. packuswb mm0, mm0
  254. movd [edi], mm0
  255. punpckldq mm6,mm6
  256. //poop
  257. punpcklbw mm5, [zero]
  258. psubw mm4, mm6
  259. punpcklbw mm1, [zero]
  260. pmullw mm5, mm4
  261. punpcklbw mm7, [zero]
  262. pmullw mm1, mm6
  263. punpcklbw mm3, [zero]
  264. pmullw mm7, mm4
  265. //cycle
  266. //cycle
  267. paddw mm5, mm1
  268. //
  269. pmullw mm3, mm6
  270. psrlw mm5, 8
  271. pmullw mm5, mem5
  272. add edi, 8
  273. // cycle
  274. // cycle
  275. paddw mm7, mm3
  276. //
  277. psrlw mm7, 8
  278. //
  279. pmullw mm7, mem7
  280. dec ecx
  281. // cycle
  282. // cycle
  283. // cycle
  284. paddw mm5, mm7
  285. psrlw mm5, 8
  286. packuswb mm5, mm5
  287. movd [edi-4], mm5
  288. jnz mmx_scale_loop1
  289. mov fbout, edi
  290. }
  291. } // end mmx
  292. __asm emms;
  293. #endif
  294. if (blend) // reblend this scanline with the original
  295. {
  296. fbout-=w;
  297. int x=w/4;
  298. unsigned int *s2=(unsigned int *)framebuffer+y*w;
  299. while (x--)
  300. {
  301. fbout[0]=BLEND_AVG(fbout[0],s2[0]);
  302. fbout[1]=BLEND_AVG(fbout[1],s2[1]);
  303. fbout[2]=BLEND_AVG(fbout[2],s2[2]);
  304. fbout[3]=BLEND_AVG(fbout[3],s2[3]);
  305. fbout+=4;
  306. s2+=4;
  307. }
  308. }
  309. } // end subpixel y loop
  310. }
  311. else // !subpixel
  312. {
  313. int y;
  314. for (y = 0; y < h; y ++)
  315. {
  316. int s_x=isx;
  317. unsigned int *src = ((unsigned int *) framebuffer)+(s_y>>16)*w;
  318. int ypart=(s_y>>8)&0xff;
  319. s_y+=ds_x;
  320. if (!blend)
  321. {
  322. int x=w/4;
  323. while (x--)
  324. {
  325. fbout[0]=src[s_x>>16];
  326. s_x += ds_x;
  327. fbout[1]=src[s_x>>16];
  328. s_x += ds_x;
  329. fbout[2]=src[s_x>>16];
  330. s_x += ds_x;
  331. fbout[3]=src[s_x>>16];
  332. s_x += ds_x;
  333. fbout+=4;
  334. }
  335. }
  336. else
  337. {
  338. unsigned int *s2=(unsigned int *)framebuffer+(y*w);
  339. int x=w/4;
  340. while (x--)
  341. {
  342. fbout[0]=BLEND_AVG(s2[0],src[s_x>>16]);
  343. s_x += ds_x;
  344. fbout[1]=BLEND_AVG(s2[1],src[s_x>>16]);
  345. s_x += ds_x;
  346. fbout[2]=BLEND_AVG(s2[2],src[s_x>>16]);
  347. s_x += ds_x;
  348. fbout[3]=BLEND_AVG(s2[3],src[s_x>>16]);
  349. s2+=4;
  350. fbout+=4;
  351. s_x += ds_x;
  352. }
  353. }
  354. }
  355. }
  356. return 1;
  357. }
  358. int C_THISCLASS::render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)
  359. {
  360. if (isBeat&0x80000000) return 0;
  361. int f_val;
  362. unsigned int *dest=(unsigned int *) fbout;
  363. if (isBeat && beatch)
  364. {
  365. fpos=scale2;
  366. }
  367. if (scale < scale2)
  368. {
  369. f_val=(fpos > scale? fpos:scale);
  370. fpos -= 3;
  371. }
  372. else
  373. {
  374. f_val=(fpos < scale? fpos :scale);
  375. fpos+=3;
  376. }
  377. if (f_val<0) f_val=0;
  378. if (f_val < 32) return blitter_normal(framebuffer,fbout,w,h,f_val);
  379. if (f_val > 32) return blitter_out(framebuffer,fbout,w,h,f_val);
  380. return 0;
  381. }
  382. C_RBASE *R_BlitterFB(char *desc)
  383. {
  384. if (desc) { strcpy(desc,MOD_NAME); return NULL; }
  385. return (C_RBASE *) new C_THISCLASS();
  386. }
  387. static C_THISCLASS *g_this;
  388. static BOOL CALLBACK g_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  389. {
  390. int *a=NULL;
  391. switch (uMsg)
  392. {
  393. case WM_INITDIALOG:
  394. SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_SETRANGEMIN,0,0);
  395. SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_SETRANGEMAX,0,256);
  396. SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_SETPOS,1,g_this->scale);
  397. SendDlgItemMessage(hwndDlg,IDC_SLIDER2,TBM_SETRANGEMIN,0,0);
  398. SendDlgItemMessage(hwndDlg,IDC_SLIDER2,TBM_SETRANGEMAX,0,256);
  399. SendDlgItemMessage(hwndDlg,IDC_SLIDER2,TBM_SETPOS,1,g_this->scale2);
  400. if (g_this->blend==1) CheckDlgButton(hwndDlg,IDC_BLEND,BST_CHECKED);
  401. if (g_this->subpixel) CheckDlgButton(hwndDlg,IDC_CHECK2,BST_CHECKED);
  402. if (g_this->beatch==1) CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED);
  403. return 1;
  404. case WM_COMMAND:
  405. switch (LOWORD(wParam))
  406. {
  407. case IDC_BLEND:
  408. if (IsDlgButtonChecked(hwndDlg,IDC_BLEND))
  409. {
  410. g_this->blend=1;
  411. }
  412. else g_this->blend=0;
  413. break;
  414. case IDC_CHECK1:
  415. if (IsDlgButtonChecked(hwndDlg,IDC_CHECK1))
  416. g_this->beatch=1;
  417. else g_this->beatch=0;
  418. break;
  419. case IDC_CHECK2:
  420. if (IsDlgButtonChecked(hwndDlg,IDC_CHECK2))
  421. {
  422. g_this->subpixel=1;
  423. }
  424. else g_this->subpixel=0;
  425. break;
  426. }
  427. return 0;
  428. case WM_HSCROLL:
  429. {
  430. HWND swnd = (HWND) lParam;
  431. int t = (int) SendMessage(swnd,TBM_GETPOS,0,0);
  432. if (swnd == GetDlgItem(hwndDlg,IDC_SLIDER1))
  433. {
  434. g_this->scale=t;
  435. g_this->fpos=t;
  436. }
  437. if (swnd == GetDlgItem(hwndDlg,IDC_SLIDER2))
  438. {
  439. g_this->scale2=t;
  440. g_this->fpos=t;
  441. }
  442. }
  443. }
  444. return 0;
  445. }
  446. HWND C_THISCLASS::conf(HINSTANCE hInstance, HWND hwndParent)
  447. {
  448. g_this = this;
  449. return WASABI_API_CREATEDIALOG(IDD_CFG_BLT,hwndParent,g_DlgProc);
  450. }
  451. #else
  452. C_RBASE *R_BlitterFB(char *desc) { return NULL; }
  453. #endif