PageRenderTime 65ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/od-win32/win32gfx.cpp

https://github.com/tonioni/WinUAE
C++ | 4554 lines | 4059 code | 407 blank | 88 comment | 1416 complexity | cae24ac5828bd04fb235002675342e2d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * Win32 Drawing and DirectX interface
  5. *
  6. * Copyright 1997-1998 Mathias Ortmann
  7. * Copyright 1997-2000 Brian King
  8. */
  9. #define FORCE16BIT 0
  10. #include "sysconfig.h"
  11. #include <stdlib.h>
  12. #include <stdarg.h>
  13. #include <windows.h>
  14. #include <commctrl.h>
  15. #include <ddraw.h>
  16. #include <shellapi.h>
  17. #include <dwmapi.h>
  18. #include <D3dkmthk.h>
  19. #include <process.h>
  20. #include "sysdeps.h"
  21. #include "resource.h"
  22. #include "options.h"
  23. #include "audio.h"
  24. #include "uae.h"
  25. #include "memory.h"
  26. #include "custom.h"
  27. #include "events.h"
  28. #include "newcpu.h"
  29. #include "traps.h"
  30. #include "xwin.h"
  31. #include "keyboard.h"
  32. #include "drawing.h"
  33. #include "dxwrap.h"
  34. #include "picasso96_win.h"
  35. #include "registry.h"
  36. #include "win32.h"
  37. #include "win32gfx.h"
  38. #include "win32gui.h"
  39. #include "sound.h"
  40. #include "inputdevice.h"
  41. #include "direct3d.h"
  42. #include "midi.h"
  43. #include "gui.h"
  44. #include "serial.h"
  45. #include "avioutput.h"
  46. #include "gfxfilter.h"
  47. #include "parser.h"
  48. #include "lcd.h"
  49. #include "sampler.h"
  50. #include "gfxboard.h"
  51. #include "cpuboard.h"
  52. #include "x86.h"
  53. #ifdef RETROPLATFORM
  54. #include "rp.h"
  55. #endif
  56. #include "statusline.h"
  57. #include "devices.h"
  58. #define DM_DX_FULLSCREEN 1
  59. #define DM_W_FULLSCREEN 2
  60. #define DM_D3D_FULLSCREEN 16
  61. #define DM_PICASSO96 32
  62. #define DM_DDRAW 64
  63. #define DM_DC 128
  64. #define DM_D3D 256
  65. #define DM_SWSCALE 1024
  66. #define SM_WINDOW 0
  67. #define SM_FULLSCREEN_DX 2
  68. #define SM_OPENGL_WINDOW 3
  69. #define SM_OPENGL_FULLWINDOW 9
  70. #define SM_OPENGL_FULLSCREEN_DX 4
  71. #define SM_D3D_WINDOW 5
  72. #define SM_D3D_FULLWINDOW 10
  73. #define SM_D3D_FULLSCREEN_DX 6
  74. #define SM_FULLWINDOW 7
  75. #define SM_NONE 11
  76. static int deskhz;
  77. struct MultiDisplay Displays[MAX_DISPLAYS + 1];
  78. struct AmigaMonitor AMonitors[MAX_AMIGAMONITORS];
  79. struct AmigaMonitor *amon = NULL;
  80. static int display_change_requested;
  81. int window_led_drives, window_led_drives_end;
  82. int window_led_hd, window_led_hd_end;
  83. int window_led_joys, window_led_joys_end, window_led_joy_start;
  84. int window_led_msg, window_led_msg_end, window_led_msg_start;
  85. extern int console_logging;
  86. static int wasfullwindow_a, wasfullwindow_p;
  87. int vsync_modechangetimeout = 10;
  88. int vsync_activeheight, vsync_totalheight;
  89. float vsync_vblank, vsync_hblank;
  90. bool beamracer_debug;
  91. bool gfx_hdr;
  92. int reopen(struct AmigaMonitor *, int, bool);
  93. static CRITICAL_SECTION screen_cs;
  94. static bool screen_cs_allocated;
  95. void gfx_lock (void)
  96. {
  97. EnterCriticalSection (&screen_cs);
  98. }
  99. void gfx_unlock (void)
  100. {
  101. LeaveCriticalSection (&screen_cs);
  102. }
  103. int WIN32GFX_IsPicassoScreen(struct AmigaMonitor *mon)
  104. {
  105. return mon->screen_is_picasso ? 1 : 0;
  106. }
  107. static int isscreen(struct AmigaMonitor *mon)
  108. {
  109. return mon->hMainWnd ? 1 : 0;
  110. }
  111. static void clearscreen (void)
  112. {
  113. DirectDraw_FillPrimary ();
  114. }
  115. static int isfullscreen_2(struct uae_prefs *p)
  116. {
  117. struct AmigaMonitor *mon = &AMonitors[0];
  118. int idx = mon->screen_is_picasso ? 1 : 0;
  119. return p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLSCREEN ? 1 : (p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLWINDOW ? -1 : 0);
  120. }
  121. int isfullscreen(void)
  122. {
  123. return isfullscreen_2(&currprefs);
  124. }
  125. int WIN32GFX_GetDepth(struct AmigaMonitor *mon, int real)
  126. {
  127. if (!mon->currentmode.native_depth)
  128. return mon->currentmode.current_depth;
  129. return real ? mon->currentmode.native_depth : mon->currentmode.current_depth;
  130. }
  131. int WIN32GFX_GetWidth(struct AmigaMonitor *mon)
  132. {
  133. return mon->currentmode.current_width;
  134. }
  135. int WIN32GFX_GetHeight(struct AmigaMonitor *mon)
  136. {
  137. return mon->currentmode.current_height;
  138. }
  139. static BOOL doInit (struct AmigaMonitor*);
  140. int default_freq = 60;
  141. static uae_u8 *scrlinebuf;
  142. static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index)
  143. {
  144. struct AmigaMonitor *mon = &AMonitors[0];
  145. static int max;
  146. int display = index < 0 ? p->gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display - 1 : index;
  147. if (!max || (max > 0 && Displays[max].monitorname != NULL)) {
  148. max = 0;
  149. while (Displays[max].monitorname)
  150. max++;
  151. if (max == 0) {
  152. gui_message(_T("no display adapters! Exiting"));
  153. exit(0);
  154. }
  155. }
  156. if (index >= 0 && display >= max)
  157. return NULL;
  158. if (display >= max)
  159. display = 0;
  160. if (display < 0)
  161. display = 0;
  162. return &Displays[display];
  163. }
  164. struct MultiDisplay *getdisplay(struct uae_prefs *p, int monid)
  165. {
  166. struct AmigaMonitor *mon = &AMonitors[monid];
  167. if (monid > 0 && mon->md)
  168. return mon->md;
  169. return getdisplay2(p, -1);
  170. }
  171. void desktop_coords(int monid, int *dw, int *dh, int *ax, int *ay, int *aw, int *ah)
  172. {
  173. struct AmigaMonitor *mon = &AMonitors[monid];
  174. struct MultiDisplay *md = getdisplay(&currprefs, monid);
  175. *dw = md->rect.right - md->rect.left;
  176. *dh = md->rect.bottom - md->rect.top;
  177. *ax = mon->amigawin_rect.left;
  178. *ay = mon->amigawin_rect.top;
  179. *aw = mon->amigawin_rect.right - *ax;
  180. *ah = mon->amigawin_rect.bottom - *ay;
  181. }
  182. static int target_get_display2(const TCHAR *name, int mode)
  183. {
  184. int found, found2;
  185. found = -1;
  186. found2 = -1;
  187. for (int i = 0; Displays[i].monitorname; i++) {
  188. struct MultiDisplay *md = &Displays[i];
  189. if (mode == 1 && md->monitorid[0] == '\\')
  190. continue;
  191. if (mode == 2 && md->monitorid[0] != '\\')
  192. continue;
  193. if (!_tcscmp (md->monitorid, name)) {
  194. if (found < 0) {
  195. found = i + 1;
  196. } else {
  197. found2 = found;
  198. found = -1;
  199. break;
  200. }
  201. }
  202. }
  203. if (found >= 0)
  204. return found;
  205. found = -1;
  206. for (int i = 0; Displays[i].monitorname; i++) {
  207. struct MultiDisplay *md = &Displays[i];
  208. if (mode == 1 && md->adapterid[0] == '\\')
  209. continue;
  210. if (mode == 2 && md->adapterid[0] != '\\')
  211. continue;
  212. if (!_tcscmp (md->adapterid, name)) {
  213. if (found < 0) {
  214. found = i + 1;
  215. } else {
  216. if (found2 < 0)
  217. found2 = found;
  218. found = -1;
  219. break;
  220. }
  221. }
  222. }
  223. if (found >= 0)
  224. return found;
  225. for (int i = 0; Displays[i].monitorname; i++) {
  226. struct MultiDisplay *md = &Displays[i];
  227. if (mode == 1 && md->adaptername[0] == '\\')
  228. continue;
  229. if (mode == 2 && md->adaptername[0] != '\\')
  230. continue;
  231. if (!_tcscmp (md->adaptername, name)) {
  232. if (found < 0) {
  233. found = i + 1;
  234. } else {
  235. if (found2 < 0)
  236. found2 = found;
  237. found = -1;
  238. break;
  239. }
  240. }
  241. }
  242. if (found >= 0)
  243. return found;
  244. for (int i = 0; Displays[i].monitorname; i++) {
  245. struct MultiDisplay *md = &Displays[i];
  246. if (mode == 1 && md->monitorname[0] == '\\')
  247. continue;
  248. if (mode == 2 && md->monitorname[0] != '\\')
  249. continue;
  250. if (!_tcscmp (md->monitorname, name)) {
  251. if (found < 0) {
  252. found = i + 1;
  253. } else {
  254. if (found2 < 0)
  255. found2 = found;
  256. found = -1;
  257. break;
  258. }
  259. }
  260. }
  261. if (found >= 0)
  262. return found;
  263. if (mode == 3) {
  264. if (found2 >= 0)
  265. return found2;
  266. }
  267. return -1;
  268. }
  269. int target_get_display(const TCHAR *name)
  270. {
  271. int disp;
  272. //write_log(_T("target_get_display '%s'\n"), name);
  273. disp = target_get_display2(name, 0);
  274. //write_log(_T("Scan 0: %d\n"), disp);
  275. if (disp >= 0)
  276. return disp;
  277. disp = target_get_display2(name, 1);
  278. //write_log(_T("Scan 1: %d\n"), disp);
  279. if (disp >= 0)
  280. return disp;
  281. disp = target_get_display2(name, 2);
  282. //write_log(_T("Scan 2: %d\n"), disp);
  283. if (disp >= 0)
  284. return disp;
  285. disp = target_get_display2(name, 3);
  286. //write_log(_T("Scan 3: %d\n"), disp);
  287. if (disp >= 0)
  288. return disp;
  289. return -1;
  290. }
  291. static volatile int waitvblankthread_mode;
  292. HANDLE waitvblankevent;
  293. static frame_time_t wait_vblank_timestamp;
  294. static MultiDisplay *wait_vblank_display;
  295. static volatile bool vsync_active;
  296. static bool scanlinecalibrating;
  297. typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
  298. static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
  299. typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
  300. static D3DKMTGETSCANLINE pD3DKMTGetScanLine;
  301. typedef NTSTATUS(CALLBACK* D3DKMTWAITFORVERTICALBLANKEVENT)(const D3DKMT_WAITFORVERTICALBLANKEVENT*);
  302. static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent;
  303. #define STATUS_SUCCESS ((NTSTATUS)0)
  304. static int target_get_display_scanline2(int displayindex)
  305. {
  306. if (pD3DKMTGetScanLine) {
  307. D3DKMT_GETSCANLINE sl = { 0 };
  308. struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
  309. if (!md->HasAdapterData)
  310. return -11;
  311. sl.VidPnSourceId = md->VidPnSourceId;
  312. sl.hAdapter = md->AdapterHandle;
  313. NTSTATUS status = pD3DKMTGetScanLine(&sl);
  314. if (status == STATUS_SUCCESS) {
  315. if (sl.InVerticalBlank)
  316. return -1;
  317. return sl.ScanLine;
  318. } else {
  319. if ((int)status > 0)
  320. return -(int)status;
  321. return status;
  322. }
  323. return -12;
  324. } else if (D3D_getscanline) {
  325. int scanline;
  326. bool invblank;
  327. if (D3D_getscanline(&scanline, &invblank)) {
  328. if (invblank)
  329. return -1;
  330. return scanline;
  331. }
  332. return -14;
  333. }
  334. return -13;
  335. }
  336. extern uae_u64 spincount;
  337. bool calculated_scanline = 1;
  338. int target_get_display_scanline(int displayindex)
  339. {
  340. if (!scanlinecalibrating && calculated_scanline) {
  341. static int lastline;
  342. float diff = read_processor_time() - wait_vblank_timestamp;
  343. if (diff < 0)
  344. return -1;
  345. int sl = (int)(diff * (vsync_activeheight + (vsync_totalheight - vsync_activeheight) / 10) * vsync_vblank / syncbase);
  346. if (sl < 0)
  347. sl = -1;
  348. return sl;
  349. } else {
  350. static uae_u64 lastrdtsc;
  351. static int lastvpos;
  352. if (spincount == 0 || currprefs.m68k_speed >= 0) {
  353. lastrdtsc = 0;
  354. lastvpos = target_get_display_scanline2(displayindex);
  355. return lastvpos;
  356. }
  357. uae_u64 v = __rdtsc();
  358. if (lastrdtsc > v)
  359. return lastvpos;
  360. lastvpos = target_get_display_scanline2(displayindex);
  361. lastrdtsc = __rdtsc() + spincount * 4;
  362. return lastvpos;
  363. }
  364. }
  365. typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
  366. typedef LONG(CALLBACK* GETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*);
  367. typedef LONG(CALLBACK* DISPLAYCONFIGGETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
  368. static bool get_display_vblank_params(int displayindex, int *activeheightp, int *totalheightp, float *vblankp, float *hblankp)
  369. {
  370. static QUERYDISPLAYCONFIG pQueryDisplayConfig;
  371. static GETDISPLAYCONFIGBUFFERSIZES pGetDisplayConfigBufferSizes;
  372. static DISPLAYCONFIGGETDEVICEINFO pDisplayConfigGetDeviceInfo;
  373. if (!pQueryDisplayConfig)
  374. pQueryDisplayConfig = (QUERYDISPLAYCONFIG)GetProcAddress(userdll, "QueryDisplayConfig");
  375. if (!pGetDisplayConfigBufferSizes)
  376. pGetDisplayConfigBufferSizes = (GETDISPLAYCONFIGBUFFERSIZES)GetProcAddress(userdll, "GetDisplayConfigBufferSizes");
  377. if (!pDisplayConfigGetDeviceInfo)
  378. pDisplayConfigGetDeviceInfo = (DISPLAYCONFIGGETDEVICEINFO)GetProcAddress(userdll, "DisplayConfigGetDeviceInfo");
  379. if (!pQueryDisplayConfig || !pGetDisplayConfigBufferSizes || !pDisplayConfigGetDeviceInfo)
  380. return false;
  381. struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
  382. UINT32 pathCount, modeCount;
  383. bool ret = false;
  384. if (pGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) == ERROR_SUCCESS) {
  385. DISPLAYCONFIG_PATH_INFO *displayPaths;
  386. DISPLAYCONFIG_MODE_INFO *displayModes;
  387. displayPaths = xmalloc(DISPLAYCONFIG_PATH_INFO, pathCount);
  388. displayModes = xmalloc(DISPLAYCONFIG_MODE_INFO, modeCount);
  389. if (pQueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, displayPaths, &modeCount, displayModes, NULL) == ERROR_SUCCESS) {
  390. for (int i = 0; i < pathCount; i++) {
  391. DISPLAYCONFIG_PATH_INFO *path = &displayPaths[i];
  392. DISPLAYCONFIG_MODE_INFO *target = &displayModes[path->targetInfo.modeInfoIdx];
  393. DISPLAYCONFIG_MODE_INFO *source = &displayModes[path->sourceInfo.modeInfoIdx];
  394. DISPLAYCONFIG_SOURCE_DEVICE_NAME dcsdn;
  395. DISPLAYCONFIG_DEVICE_INFO_HEADER *dcdih = &dcsdn.header;
  396. dcdih->size = sizeof dcsdn;
  397. dcdih->adapterId = source->adapterId;
  398. dcdih->id = source->id;
  399. dcdih->type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
  400. if (pDisplayConfigGetDeviceInfo(dcdih) == ERROR_SUCCESS) {
  401. if (!_tcscmp(md->adapterid, dcsdn.viewGdiDeviceName)) {
  402. DISPLAYCONFIG_VIDEO_SIGNAL_INFO *si = &target->targetMode.targetVideoSignalInfo;
  403. if (activeheightp)
  404. *activeheightp = si->activeSize.cy;
  405. if (totalheightp)
  406. *totalheightp = si->totalSize.cy;
  407. float vblank = (float)si->vSyncFreq.Numerator / si->vSyncFreq.Denominator;
  408. float hblank = (float)si->hSyncFreq.Numerator / si->hSyncFreq.Denominator;
  409. if (vblankp)
  410. *vblankp = vblank;
  411. if (hblankp)
  412. *hblankp = hblank;
  413. write_log(_T("ActiveHeight: %d TotalHeight: %d VFreq=%d/%d=%.2fHz HFreq=%d/%d=%.3fKHz\n"),
  414. target->targetMode.targetVideoSignalInfo.activeSize.cy,
  415. target->targetMode.targetVideoSignalInfo.totalSize.cy,
  416. target->targetMode.targetVideoSignalInfo.vSyncFreq.Numerator,
  417. target->targetMode.targetVideoSignalInfo.vSyncFreq.Denominator,
  418. vblank,
  419. target->targetMode.targetVideoSignalInfo.hSyncFreq.Numerator,
  420. target->targetMode.targetVideoSignalInfo.hSyncFreq.Denominator,
  421. hblank / 1000.0);
  422. ret = true;
  423. break;
  424. }
  425. }
  426. }
  427. }
  428. xfree(displayModes);
  429. xfree(displayPaths);
  430. }
  431. return ret;
  432. }
  433. static unsigned int __stdcall waitvblankthread(void *dummy)
  434. {
  435. waitvblankthread_mode = 2;
  436. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  437. while (waitvblankthread_mode) {
  438. D3DKMT_WAITFORVERTICALBLANKEVENT e = { 0 };
  439. e.hAdapter = wait_vblank_display->AdapterHandle;
  440. e.VidPnSourceId = wait_vblank_display->VidPnSourceId;
  441. pD3DKMTWaitForVerticalBlankEvent(&e);
  442. wait_vblank_timestamp = read_processor_time();
  443. vsync_active = true;
  444. SetEvent(waitvblankevent);
  445. }
  446. waitvblankthread_mode = -1;
  447. return 0;
  448. }
  449. static void display_vblank_thread_kill(void)
  450. {
  451. if (waitvblankthread_mode == 2) {
  452. waitvblankthread_mode = 0;
  453. while (waitvblankthread_mode != -1) {
  454. Sleep(10);
  455. }
  456. waitvblankthread_mode = 0;
  457. CloseHandle(waitvblankevent);
  458. waitvblankevent = NULL;
  459. }
  460. }
  461. static void display_vblank_thread(struct AmigaMonitor *mon)
  462. {
  463. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  464. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  465. if (waitvblankthread_mode > 0)
  466. return;
  467. // It seems some Windows 7 drivers stall if D3DKMTWaitForVerticalBlankEvent()
  468. // and D3DKMTGetScanLine() is used simultaneously.
  469. if ((calculated_scanline || os_win8) && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
  470. waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
  471. waitvblankthread_mode = 1;
  472. unsigned int th;
  473. _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
  474. } else {
  475. calculated_scanline = 0;
  476. }
  477. }
  478. void target_cpu_speed(void)
  479. {
  480. display_vblank_thread(&AMonitors[0]);
  481. }
  482. extern void target_calibrate_spin(void);
  483. static void display_param_init(struct AmigaMonitor *mon)
  484. {
  485. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  486. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  487. vsync_activeheight = mon->currentmode.current_height;
  488. vsync_totalheight = vsync_activeheight * 1125 / 1080;
  489. vsync_vblank = 0;
  490. vsync_hblank = 0;
  491. get_display_vblank_params(-1, &vsync_activeheight, &vsync_totalheight, &vsync_vblank, &vsync_hblank);
  492. if (vsync_vblank <= 0)
  493. vsync_vblank = mon->currentmode.freq;
  494. // GPU scaled mode?
  495. if (vsync_activeheight > mon->currentmode.current_height) {
  496. float m = (float)vsync_activeheight / mon->currentmode.current_height;
  497. vsync_hblank = (int)(vsync_hblank / m + 0.5);
  498. vsync_activeheight = mon->currentmode.current_height;
  499. }
  500. wait_vblank_display = getdisplay(&currprefs, mon->monitor_id);
  501. if (!wait_vblank_display || !wait_vblank_display->HasAdapterData) {
  502. write_log(_T("Selected display mode does not have adapter data!\n"));
  503. }
  504. Sleep(10);
  505. scanlinecalibrating = true;
  506. target_calibrate_spin();
  507. scanlinecalibrating = false;
  508. display_vblank_thread(mon);
  509. }
  510. const TCHAR *target_get_display_name (int num, bool friendlyname)
  511. {
  512. if (num <= 0)
  513. return NULL;
  514. struct MultiDisplay *md = getdisplay2(NULL, num - 1);
  515. if (!md)
  516. return NULL;
  517. if (friendlyname)
  518. return md->monitorname;
  519. return md->monitorid;
  520. }
  521. void centerdstrect(struct AmigaMonitor *mon, RECT *dr)
  522. {
  523. struct uae_filter *usedfilter = mon->usedfilter;
  524. if(!(mon->currentmode.flags & (DM_DX_FULLSCREEN | DM_D3D_FULLSCREEN | DM_W_FULLSCREEN)))
  525. OffsetRect (dr, mon->amigawin_rect.left, mon->amigawin_rect.top);
  526. if (mon->currentmode.flags & DM_W_FULLSCREEN) {
  527. if (mon->scalepicasso && mon->screen_is_picasso)
  528. return;
  529. if (usedfilter && !mon->screen_is_picasso)
  530. return;
  531. if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
  532. return;
  533. OffsetRect (dr, (mon->currentmode.native_width - mon->currentmode.current_width) / 2,
  534. (mon->currentmode.native_height - mon->currentmode.current_height) / 2);
  535. }
  536. }
  537. static int picasso_offset_x, picasso_offset_y;
  538. static float picasso_offset_mx, picasso_offset_my;
  539. void getgfxoffset(int monid, float *dxp, float *dyp, float *mxp, float *myp)
  540. {
  541. struct AmigaMonitor *mon = &AMonitors[monid];
  542. struct amigadisplay *ad = &adisplays[monid];
  543. struct uae_filter *usedfilter = mon->usedfilter;
  544. float dx, dy, mx, my;
  545. getfilteroffset(monid, &dx, &dy, &mx, &my);
  546. if (ad->picasso_on) {
  547. dx = picasso_offset_x * picasso_offset_mx;
  548. dy = picasso_offset_y * picasso_offset_my;
  549. mx = picasso_offset_mx;
  550. my = picasso_offset_my;
  551. }
  552. //write_log(_T("%.2fx%.2f %.2fx%.2f\n"), dx, dy, mx, my);
  553. if (mon->currentmode.flags & DM_W_FULLSCREEN) {
  554. for (;;) {
  555. if (mon->scalepicasso && mon->screen_is_picasso)
  556. break;
  557. if (usedfilter && !mon->screen_is_picasso)
  558. break;
  559. if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
  560. break;
  561. dx += (mon->currentmode.native_width - mon->currentmode.current_width) / 2;
  562. dy += (mon->currentmode.native_height - mon->currentmode.current_height) / 2;
  563. break;
  564. }
  565. }
  566. *dxp = dx;
  567. *dyp = dy;
  568. *mxp = 1.0 / mx;
  569. *myp = 1.0 / my;
  570. }
  571. void DX_Fill(struct AmigaMonitor *mon, int dstx, int dsty, int width, int height, uae_u32 color)
  572. {
  573. RECT dstrect;
  574. if (width < 0)
  575. width = mon->currentmode.current_width;
  576. if (height < 0)
  577. height = mon->currentmode.current_height;
  578. SetRect (&dstrect, dstx, dsty, dstx + width, dsty + height);
  579. DirectDraw_Fill (&dstrect, color);
  580. }
  581. static int rgbformat_bits (RGBFTYPE t)
  582. {
  583. unsigned long f = 1 << t;
  584. return ((f & RGBMASK_8BIT) != 0 ? 8
  585. : (f & RGBMASK_15BIT) != 0 ? 15
  586. : (f & RGBMASK_16BIT) != 0 ? 16
  587. : (f & RGBMASK_24BIT) != 0 ? 24
  588. : (f & RGBMASK_32BIT) != 0 ? 32
  589. : 0);
  590. }
  591. int getrefreshrate(int monid, int width, int height)
  592. {
  593. struct amigadisplay *ad = &adisplays[monid];
  594. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
  595. int freq = 0;
  596. if (ap->gfx_refreshrate <= 0)
  597. return 0;
  598. struct MultiDisplay *md = getdisplay(&currprefs, monid);
  599. for (int i = 0; md->DisplayModes[i].depth >= 0; i++) {
  600. struct PicassoResolution *pr = &md->DisplayModes[i];
  601. if (pr->res.width == width && pr->res.height == height) {
  602. for (int j = 0; pr->refresh[j] > 0; j++) {
  603. if (pr->refresh[j] == ap->gfx_refreshrate)
  604. return ap->gfx_refreshrate;
  605. if (pr->refresh[j] > freq && pr->refresh[j] < ap->gfx_refreshrate)
  606. freq = pr->refresh[j];
  607. }
  608. }
  609. }
  610. write_log (_T("Refresh rate %d not supported, using %d\n"), ap->gfx_refreshrate, freq);
  611. return freq;
  612. }
  613. static int set_ddraw_2(struct AmigaMonitor *mon)
  614. {
  615. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  616. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  617. HRESULT ddrval;
  618. int bits = (mon->currentmode.current_depth + 7) & ~7;
  619. int width = mon->currentmode.native_width;
  620. int height = mon->currentmode.native_height;
  621. int dxfullscreen, wfullscreen, dd;
  622. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
  623. int freq = ap->gfx_refreshrate;
  624. dxfullscreen = (mon->currentmode.flags & DM_DX_FULLSCREEN) ? TRUE : FALSE;
  625. wfullscreen = (mon->currentmode.flags & DM_W_FULLSCREEN) ? TRUE : FALSE;
  626. dd = (mon->currentmode.flags & DM_DDRAW) ? TRUE : FALSE;
  627. if (WIN32GFX_IsPicassoScreen(mon) && (state->Width > width || state->Height > height)) {
  628. width = state->Width;
  629. height = state->Height;
  630. }
  631. DirectDraw_FreeMainSurface ();
  632. if (!dd && !dxfullscreen)
  633. return 1;
  634. ddrval = DirectDraw_SetCooperativeLevel (mon->hAmigaWnd, dxfullscreen, TRUE);
  635. if (FAILED (ddrval))
  636. goto oops;
  637. if (dxfullscreen) {
  638. for (;;) {
  639. HRESULT olderr;
  640. freq = getrefreshrate(mon->monitor_id, width, height);
  641. write_log (_T("set_ddraw: trying %dx%d, bits=%d, refreshrate=%d\n"), width, height, bits, freq);
  642. ddrval = DirectDraw_SetDisplayMode (width, height, bits, freq);
  643. if (SUCCEEDED (ddrval))
  644. break;
  645. olderr = ddrval;
  646. if (freq) {
  647. write_log (_T("set_ddraw: failed, trying without forced refresh rate\n"));
  648. freq = 0;
  649. DirectDraw_SetCooperativeLevel (mon->hAmigaWnd, dxfullscreen, TRUE);
  650. ddrval = DirectDraw_SetDisplayMode (width, height, bits, freq);
  651. if (SUCCEEDED (ddrval))
  652. break;
  653. }
  654. if (olderr != DDERR_INVALIDMODE && olderr != 0x80004001 && olderr != DDERR_UNSUPPORTEDMODE)
  655. goto oops;
  656. return -1;
  657. }
  658. mon->currentmode.freq = freq;
  659. updatewinrect(mon, true);
  660. }
  661. if (dd) {
  662. ddrval = DirectDraw_CreateClipper ();
  663. if (FAILED (ddrval))
  664. goto oops;
  665. ddrval = DirectDraw_CreateMainSurface (width, height);
  666. if (FAILED(ddrval)) {
  667. write_log (_T("set_ddraw: couldn't CreateSurface() for primary because %s.\n"), DXError (ddrval));
  668. goto oops;
  669. }
  670. ddrval = DirectDraw_SetClipper(mon->hAmigaWnd);
  671. if (FAILED (ddrval))
  672. goto oops;
  673. if (DirectDraw_SurfaceLock ()) {
  674. mon->currentmode.pitch = DirectDraw_GetSurfacePitch ();
  675. DirectDraw_SurfaceUnlock ();
  676. }
  677. }
  678. write_log (_T("set_ddraw: %dx%d@%d-bytes\n"), width, height, bits);
  679. return 1;
  680. oops:
  681. return 0;
  682. }
  683. static void addmode (struct MultiDisplay *md, DEVMODE *dm, int rawmode)
  684. {
  685. int ct;
  686. int i, j;
  687. int w = dm->dmPelsWidth;
  688. int h = dm->dmPelsHeight;
  689. int d = dm->dmBitsPerPel;
  690. bool lace = false;
  691. int freq = 0;
  692. if (w > max_uae_width || h > max_uae_height) {
  693. write_log (_T("Ignored mode %d*%d\n"), w, h);
  694. return;
  695. }
  696. if (dm->dmFields & DM_DISPLAYFREQUENCY) {
  697. freq = dm->dmDisplayFrequency;
  698. if (freq < 10)
  699. freq = 0;
  700. }
  701. if (dm->dmFields & DM_DISPLAYFLAGS) {
  702. lace = (dm->dmDisplayFlags & DM_INTERLACED) != 0;
  703. }
  704. ct = 0;
  705. if (d == 8)
  706. ct = RGBMASK_8BIT;
  707. if (d == 15)
  708. ct = RGBMASK_15BIT;
  709. if (d == 16)
  710. ct = RGBMASK_16BIT;
  711. if (d == 24)
  712. ct = RGBMASK_24BIT;
  713. if (d == 32)
  714. ct = RGBMASK_32BIT;
  715. if (ct == 0)
  716. return;
  717. d /= 8;
  718. i = 0;
  719. while (md->DisplayModes[i].depth >= 0) {
  720. if (md->DisplayModes[i].depth == d && md->DisplayModes[i].res.width == w && md->DisplayModes[i].res.height == h) {
  721. for (j = 0; j < MAX_REFRESH_RATES; j++) {
  722. if (md->DisplayModes[i].refresh[j] == 0 || md->DisplayModes[i].refresh[j] == freq)
  723. break;
  724. }
  725. if (j < MAX_REFRESH_RATES) {
  726. md->DisplayModes[i].refresh[j] = freq;
  727. md->DisplayModes[i].refreshtype[j] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
  728. md->DisplayModes[i].refresh[j + 1] = 0;
  729. if (!lace)
  730. md->DisplayModes[i].lace = false;
  731. return;
  732. }
  733. }
  734. i++;
  735. }
  736. i = 0;
  737. while (md->DisplayModes[i].depth >= 0)
  738. i++;
  739. if (i >= MAX_PICASSO_MODES - 1)
  740. return;
  741. md->DisplayModes[i].rawmode = rawmode;
  742. md->DisplayModes[i].lace = lace;
  743. md->DisplayModes[i].res.width = w;
  744. md->DisplayModes[i].res.height = h;
  745. md->DisplayModes[i].depth = d;
  746. md->DisplayModes[i].refresh[0] = freq;
  747. md->DisplayModes[i].refreshtype[0] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
  748. md->DisplayModes[i].refresh[1] = 0;
  749. md->DisplayModes[i].colormodes = ct;
  750. md->DisplayModes[i + 1].depth = -1;
  751. _stprintf (md->DisplayModes[i].name, _T("%dx%d%s, %d-bit"),
  752. md->DisplayModes[i].res.width, md->DisplayModes[i].res.height,
  753. lace ? _T("i") : _T(""),
  754. md->DisplayModes[i].depth * 8);
  755. }
  756. static int _cdecl resolution_compare (const void *a, const void *b)
  757. {
  758. struct PicassoResolution *ma = (struct PicassoResolution *)a;
  759. struct PicassoResolution *mb = (struct PicassoResolution *)b;
  760. if (ma->res.width < mb->res.width)
  761. return -1;
  762. if (ma->res.width > mb->res.width)
  763. return 1;
  764. if (ma->res.height < mb->res.height)
  765. return -1;
  766. if (ma->res.height > mb->res.height)
  767. return 1;
  768. return ma->depth - mb->depth;
  769. }
  770. static void sortmodes (struct MultiDisplay *md)
  771. {
  772. int i, idx = -1;
  773. int pw = -1, ph = -1;
  774. i = 0;
  775. while (md->DisplayModes[i].depth >= 0)
  776. i++;
  777. qsort (md->DisplayModes, i, sizeof (struct PicassoResolution), resolution_compare);
  778. for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
  779. int j, k;
  780. for (j = 0; md->DisplayModes[i].refresh[j]; j++) {
  781. for (k = j + 1; md->DisplayModes[i].refresh[k]; k++) {
  782. if (md->DisplayModes[i].refresh[j] > md->DisplayModes[i].refresh[k]) {
  783. int t = md->DisplayModes[i].refresh[j];
  784. md->DisplayModes[i].refresh[j] = md->DisplayModes[i].refresh[k];
  785. md->DisplayModes[i].refresh[k] = t;
  786. t = md->DisplayModes[i].refreshtype[j];
  787. md->DisplayModes[i].refreshtype[j] = md->DisplayModes[i].refreshtype[k];
  788. md->DisplayModes[i].refreshtype[k] = t;
  789. }
  790. }
  791. }
  792. if (md->DisplayModes[i].res.height != ph || md->DisplayModes[i].res.width != pw) {
  793. ph = md->DisplayModes[i].res.height;
  794. pw = md->DisplayModes[i].res.width;
  795. idx++;
  796. }
  797. md->DisplayModes[i].residx = idx;
  798. }
  799. }
  800. #if 0
  801. static void sortmonitors (void)
  802. {
  803. for (int i = 0; Displays[i].monitorid; i++) {
  804. for (int j = i + 1; Displays[j].monitorid; j++) {
  805. int comp = (Displays[j].primary ? 1 : 0) - (Displays[i].primary ? 1 : 0);
  806. if (!comp)
  807. comp = _tcsicmp (Displays[i].adapterid, Displays[j].adapterid);
  808. if (comp > 0) {
  809. struct MultiDisplay md;
  810. memcpy (&md, &Displays[i], sizeof MultiDisplay);
  811. memcpy (&Displays[i], &Displays[j], sizeof MultiDisplay);
  812. memcpy (&Displays[j], &md, sizeof MultiDisplay);
  813. }
  814. }
  815. }
  816. }
  817. #endif
  818. static void modesList (struct MultiDisplay *md)
  819. {
  820. int i, j;
  821. i = 0;
  822. while (md->DisplayModes[i].depth >= 0) {
  823. write_log (_T("%d: %s%s ("), i, md->DisplayModes[i].rawmode ? _T("!") : _T(""), md->DisplayModes[i].name);
  824. j = 0;
  825. while (md->DisplayModes[i].refresh[j] > 0) {
  826. if (j > 0)
  827. write_log (_T(","));
  828. if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_RAW)
  829. write_log (_T("!"));
  830. write_log (_T("%d"), md->DisplayModes[i].refresh[j]);
  831. if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_LACE)
  832. write_log (_T("i"));
  833. j++;
  834. }
  835. write_log (_T(")\n"));
  836. i++;
  837. }
  838. }
  839. static void adjustappbar(RECT *monitor, RECT *workrect)
  840. {
  841. if (!os_vista)
  842. return;
  843. APPBARDATA abd;
  844. // Isn't this ugly API?
  845. for (int i = 0; i < 4; i++) {
  846. abd.cbSize = sizeof abd;
  847. abd.rc = *monitor;
  848. abd.uEdge = i; // ABE_LEFT, TOP, RIGHT, BOTTOM
  849. HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &abd);
  850. if (hwndAutoHide == NULL)
  851. continue;
  852. WINDOWINFO wi;
  853. wi.cbSize = sizeof wi;
  854. if (!GetWindowInfo(hwndAutoHide, &wi))
  855. continue;
  856. int edge;
  857. switch (i)
  858. {
  859. case ABE_LEFT:
  860. edge = monitor->left + (wi.rcWindow.right - wi.rcWindow.left);
  861. if (edge > workrect->left && edge < workrect->right)
  862. workrect->left = edge;
  863. break;
  864. case ABE_RIGHT:
  865. edge = monitor->right - (wi.rcWindow.right - wi.rcWindow.left);
  866. if (edge < workrect->right && edge > workrect->left)
  867. workrect->right = edge;
  868. break;
  869. case ABE_TOP:
  870. edge = monitor->top + (wi.rcWindow.bottom - wi.rcWindow.top);
  871. if (edge > workrect->top && edge < workrect->bottom)
  872. workrect->top = edge;
  873. break;
  874. case ABE_BOTTOM:
  875. edge = monitor->bottom - (wi.rcWindow.bottom - wi.rcWindow.top);
  876. if (edge < workrect->bottom && edge > workrect->top)
  877. workrect->bottom = edge;
  878. break;
  879. }
  880. }
  881. }
  882. static BOOL CALLBACK monitorEnumProc (HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
  883. {
  884. struct MultiDisplay *md = Displays;
  885. MONITORINFOEX lpmi;
  886. lpmi.cbSize = sizeof lpmi;
  887. GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
  888. while (md - Displays < MAX_DISPLAYS && md->monitorid) {
  889. if (!_tcscmp (md->adapterid, lpmi.szDevice)) {
  890. TCHAR tmp[1000];
  891. md->monitor = h;
  892. md->rect = lpmi.rcMonitor;
  893. md->workrect = lpmi.rcWork;
  894. adjustappbar(&md->rect, &md->workrect);
  895. if (md->rect.left == 0 && md->rect.top == 0)
  896. _stprintf (tmp, _T("%s (%d*%d)"), md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top);
  897. else
  898. _stprintf (tmp, _T("%s (%d*%d) [%d*%d]"), md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top, md->rect.left, md->rect.top);
  899. if (md->primary)
  900. _tcscat (tmp, _T(" *"));
  901. xfree (md->fullname);
  902. md->fullname = my_strdup (tmp);
  903. return TRUE;
  904. }
  905. md++;
  906. }
  907. return TRUE;
  908. }
  909. static BOOL CALLBACK monitorEnumProc2(HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
  910. {
  911. MONITORINFOEX lpmi;
  912. lpmi.cbSize = sizeof lpmi;
  913. GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
  914. for (int i = 0; i < MAX_DISPLAYS && Displays[i].monitorid; i++) {
  915. struct MultiDisplay *md = &Displays[i];
  916. if (!_tcscmp (md->adapterid, lpmi.szDevice) && !memcmp(&md->rect, &lpmi.rcMonitor, sizeof RECT)) {
  917. md->workrect = lpmi.rcWork;
  918. md->monitor = h;
  919. adjustappbar(&md->rect, &md->workrect);
  920. return TRUE;
  921. }
  922. }
  923. return TRUE;
  924. }
  925. void reenumeratemonitors(void)
  926. {
  927. for (int i = 0; i < MAX_DISPLAYS; i++) {
  928. struct MultiDisplay *md = &Displays[i];
  929. memcpy(&md->workrect, &md->rect, sizeof RECT);
  930. }
  931. EnumDisplayMonitors (NULL, NULL, monitorEnumProc2, NULL);
  932. }
  933. static void getd3dmonitornames (void)
  934. {
  935. struct MultiDisplay *md = Displays;
  936. IDirect3D9 *d3d;
  937. int max;
  938. // XP does not support hybrid displays, don't load Direct3D
  939. if (!os_vista)
  940. return;
  941. d3d = Direct3DCreate9 (D3D_SDK_VERSION);
  942. if (!d3d)
  943. return;
  944. max = d3d->GetAdapterCount ();
  945. while (md - Displays < MAX_DISPLAYS && md->monitorid) {
  946. POINT pt;
  947. HMONITOR winmon;
  948. pt.x = (md->rect.right - md->rect.left) / 2 + md->rect.left;
  949. pt.y = (md->rect.bottom - md->rect.top) / 2 + md->rect.top;
  950. winmon = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
  951. for (int i = 0; i < max; i++) {
  952. D3DADAPTER_IDENTIFIER9 did;
  953. HMONITOR d3dmon = d3d->GetAdapterMonitor (i);
  954. if (d3dmon != winmon)
  955. continue;
  956. if (SUCCEEDED (d3d->GetAdapterIdentifier (i, 0, &did))) {
  957. TCHAR *name = au (did.Description);
  958. my_trim (name);
  959. if (_tcsicmp (name, md->adaptername)) {
  960. write_log (_T("%d: '%s' -> '%s'\n"), i, md->adaptername, name);
  961. xfree (md->adaptername);
  962. md->adaptername = name;
  963. name = NULL;
  964. }
  965. xfree (name);
  966. }
  967. break;
  968. }
  969. md++;
  970. }
  971. d3d->Release ();
  972. }
  973. static bool enumeratedisplays2 (bool selectall)
  974. {
  975. struct MultiDisplay *md = Displays;
  976. int adapterindex = 0;
  977. DISPLAY_DEVICE add;
  978. add.cb = sizeof add;
  979. while (EnumDisplayDevices (NULL, adapterindex, &add, 0)) {
  980. adapterindex++;
  981. if (!selectall) {
  982. if (!(add.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
  983. continue;
  984. if (add.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  985. continue;
  986. }
  987. if (md - Displays >= MAX_DISPLAYS)
  988. break;
  989. int monitorindex = 0;
  990. DISPLAY_DEVICE mdd;
  991. mdd.cb = sizeof mdd;
  992. while (EnumDisplayDevices (add.DeviceName, monitorindex, &mdd, 0)) {
  993. monitorindex++;
  994. if (md - Displays >= MAX_DISPLAYS)
  995. break;
  996. if (!selectall) {
  997. if (!(mdd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
  998. continue;
  999. if (mdd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  1000. continue;
  1001. }
  1002. md->adaptername = my_strdup_trim (add.DeviceString);
  1003. md->adapterid = my_strdup (add.DeviceName);
  1004. md->adapterkey = my_strdup (add.DeviceID);
  1005. md->monitorname = my_strdup_trim (mdd.DeviceString);
  1006. md->monitorid = my_strdup (mdd.DeviceKey);
  1007. if (add.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  1008. md->primary = true;
  1009. if (pD3DKMTOpenAdapterFromHdc) {
  1010. HDC hdc = CreateDC(NULL, add.DeviceName, NULL, NULL);
  1011. if (hdc != NULL) {
  1012. D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = { 0 };
  1013. OpenAdapterData.hDc = hdc;
  1014. NTSTATUS status = pD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
  1015. if (status == STATUS_SUCCESS) {
  1016. md->AdapterLuid = OpenAdapterData.AdapterLuid;
  1017. md->VidPnSourceId = OpenAdapterData.VidPnSourceId;
  1018. md->AdapterHandle = OpenAdapterData.hAdapter;
  1019. md->HasAdapterData = true;
  1020. }
  1021. DeleteDC(hdc);
  1022. }
  1023. }
  1024. md++;
  1025. }
  1026. if (md - Displays >= MAX_DISPLAYS)
  1027. return true;
  1028. if (monitorindex == 0) {
  1029. md->adaptername = my_strdup_trim (add.DeviceString);
  1030. md->adapterid = my_strdup (add.DeviceName);
  1031. md->adapterkey = my_strdup (add.DeviceID);
  1032. md->monitorname = my_strdup_trim (add.DeviceString);
  1033. md->monitorid = my_strdup (add.DeviceKey);
  1034. md->primary = true;
  1035. md++;
  1036. }
  1037. }
  1038. if (md == Displays)
  1039. return false;
  1040. EnumDisplayMonitors (NULL, NULL, monitorEnumProc, NULL);
  1041. md = Displays;
  1042. while (md->monitorname) {
  1043. if (!md->fullname)
  1044. md->fullname = my_strdup (md->adapterid);
  1045. md++;
  1046. }
  1047. getd3dmonitornames ();
  1048. //sortmonitors ();
  1049. return true;
  1050. }
  1051. void enumeratedisplays (void)
  1052. {
  1053. if (!pD3DKMTWaitForVerticalBlankEvent) {
  1054. pD3DKMTOpenAdapterFromHdc = (D3DKMTOPENADAPTERFROMHDC)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTOpenAdapterFromHdc");
  1055. pD3DKMTGetScanLine = (D3DKMTGETSCANLINE)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTGetScanLine");
  1056. pD3DKMTWaitForVerticalBlankEvent = (D3DKMTWAITFORVERTICALBLANKEVENT)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTWaitForVerticalBlankEvent");
  1057. }
  1058. if (!enumeratedisplays2 (false))
  1059. enumeratedisplays2(true);
  1060. }
  1061. void sortdisplays (void)
  1062. {
  1063. struct MultiDisplay *md;
  1064. int i, idx;
  1065. int w = GetSystemMetrics (SM_CXSCREEN);
  1066. int h = GetSystemMetrics (SM_CYSCREEN);
  1067. int wv = GetSystemMetrics(SM_CXVIRTUALSCREEN);
  1068. int hv = GetSystemMetrics(SM_CYVIRTUALSCREEN);
  1069. int b = 0;
  1070. deskhz = 0;
  1071. HDC hdc = GetDC (NULL);
  1072. if (hdc) {
  1073. b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  1074. ReleaseDC (NULL, hdc);
  1075. }
  1076. md = Displays;
  1077. while (md->monitorname) {
  1078. md->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
  1079. md->DisplayModes[0].depth = -1;
  1080. write_log (_T("%s '%s' [%s]\n"), md->adaptername, md->adapterid, md->adapterkey);
  1081. write_log (_T("-: %s [%s]\n"), md->fullname, md->monitorid);
  1082. for (int mode = 0; mode < 2; mode++) {
  1083. DEVMODE dm;
  1084. dm.dmSize = sizeof dm;
  1085. dm.dmDriverExtra = 0;
  1086. idx = 0;
  1087. while (EnumDisplaySettingsEx (md->adapterid, idx, &dm, mode ? EDS_RAWMODE : 0)) {
  1088. int found = 0;
  1089. int idx2 = 0;
  1090. while (md->DisplayModes[idx2].depth >= 0 && !found) {
  1091. struct PicassoResolution *pr = &md->DisplayModes[idx2];
  1092. if (dm.dmPelsWidth == w && dm.dmPelsHeight == h && dm.dmBitsPerPel == b) {
  1093. if (dm.dmDisplayFrequency > deskhz)
  1094. deskhz = dm.dmDisplayFrequency;
  1095. }
  1096. if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) {
  1097. for (i = 0; pr->refresh[i]; i++) {
  1098. if (pr->refresh[i] == dm.dmDisplayFrequency) {
  1099. found = 1;
  1100. break;
  1101. }
  1102. }
  1103. }
  1104. idx2++;
  1105. }
  1106. if (!found && dm.dmBitsPerPel > 8) {
  1107. int freq = 0;
  1108. #if 0
  1109. write_log (_T("EnumDisplaySettings(%dx%dx%d %dHz %08x)\n"),
  1110. dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency, dm.dmFields);
  1111. #endif
  1112. if ((dm.dmFields & DM_PELSWIDTH) && (dm.dmFields & DM_PELSHEIGHT) && (dm.dmFields & DM_BITSPERPEL)) {
  1113. addmode (md, &dm, mode);
  1114. }
  1115. }
  1116. idx++;
  1117. }
  1118. }
  1119. //dhack();
  1120. sortmodes (md);
  1121. modesList (md);
  1122. i = 0;
  1123. while (md->DisplayModes[i].depth > 0)
  1124. i++;
  1125. write_log (_T("%d display modes.\n"), i);
  1126. md++;
  1127. }
  1128. write_log(_T("Desktop: W=%d H=%d B=%d HZ=%d. CXVS=%d CYVS=%d\n"), w, h, b, deskhz, wv, hv);
  1129. }
  1130. /* DirectX will fail with "Mode not supported" if we try to switch to a full
  1131. * screen mode that doesn't match one of the dimensions we got during enumeration.
  1132. * So try to find a best match for the given resolution in our list. */
  1133. int WIN32GFX_AdjustScreenmode (struct MultiDisplay *md, int *pwidth, int *pheight, int *ppixbits)
  1134. {
  1135. struct PicassoResolution *best;
  1136. uae_u32 selected_mask = (*ppixbits == 8 ? RGBMASK_8BIT
  1137. : *ppixbits == 15 ? RGBMASK_15BIT
  1138. : *ppixbits == 16 ? RGBMASK_16BIT
  1139. : *ppixbits == 24 ? RGBMASK_24BIT
  1140. : RGBMASK_32BIT);
  1141. int pass, i = 0, index = 0;
  1142. for (pass = 0; pass < 2; pass++) {
  1143. struct PicassoResolution *dm;
  1144. uae_u32 mask = (pass == 0
  1145. ? selected_mask
  1146. : RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT); /* %%% - BERND, were you missing 15-bit here??? */
  1147. i = 0;
  1148. index = 0;
  1149. best = &md->DisplayModes[0];
  1150. dm = &md->DisplayModes[1];
  1151. while (dm->depth >= 0) {
  1152. /* do we already have supported resolution? */
  1153. if (dm->res.width == *pwidth && dm->res.height == *pheight && dm->depth == (*ppixbits / 8))
  1154. return i;
  1155. if ((dm->colormodes & mask) != 0) {
  1156. if (dm->res.width <= best->res.width && dm->res.height <= best->res.height
  1157. && dm->res.width >= *pwidth && dm->res.height >= *pheight)
  1158. {
  1159. best = dm;
  1160. index = i;
  1161. }
  1162. if (dm->res.width >= best->res.width && dm->res.height >= best->res.height
  1163. && dm->res.width <= *pwidth && dm->res.height <= *pheight)
  1164. {
  1165. best = dm;
  1166. index = i;
  1167. }
  1168. }
  1169. dm++;
  1170. i++;
  1171. }
  1172. if (best->res.width == *pwidth && best->res.height == *pheight) {
  1173. selected_mask = mask; /* %%% - BERND, I added this - does it make sense? Otherwise, I'd specify a 16-bit display-mode for my
  1174. Workbench (using -H 2, but SHOULD have been -H 1), and end up with an 8-bit mode instead*/
  1175. break;
  1176. }
  1177. }
  1178. *pwidth = best->res.width;
  1179. *pheight = best->res.height;
  1180. if (best->colormodes & selected_mask)
  1181. return index;
  1182. /* Ordering here is done such that 16-bit is preferred, followed by 15-bit, 8-bit, 32-bit and 24-bit */
  1183. if (best->colormodes & RGBMASK_16BIT)
  1184. *ppixbits = 16;
  1185. else if (best->colormodes & RGBMASK_15BIT) /* %%% - BERND, this possibility was missing? */
  1186. *ppixbits = 15;
  1187. else if (best->colormodes & RGBMASK_8BIT)
  1188. *ppixbits = 8;
  1189. else if (best->colormodes & RGBMASK_32BIT)
  1190. *ppixbits = 32;
  1191. else if (best->colormodes & RGBMASK_24BIT)
  1192. *ppixbits = 24;
  1193. else
  1194. index = -1;
  1195. return index;
  1196. }
  1197. #if 0
  1198. static int flushymin, flushymax;
  1199. #define FLUSH_DIFF 50
  1200. static void flushit (struct vidbuffer *vb, int lineno)
  1201. {
  1202. if (!currprefs.gfx_api)
  1203. return;
  1204. if (mon->currentmode.flags & DM_SWSCALE)
  1205. return;
  1206. if (flushymin > lineno) {
  1207. if (flushymin - lineno > FLUSH_DIFF && flushymax != 0) {
  1208. D3D_flushtexture (flushymin, flushymax);
  1209. flushymin = mon->currentmode.amiga_height;
  1210. flushymax = 0;
  1211. } else {
  1212. flushymin = lineno;
  1213. }
  1214. }
  1215. if (flushymax < lineno) {
  1216. if (lineno - flushymax > FLUSH_DIFF && flushymax != 0) {
  1217. D3D_flushtexture (flushymin, flushymax);
  1218. flushymin = mon->currentmode.amiga_height;
  1219. flushymax = 0;
  1220. } else {
  1221. flushymax = lineno;
  1222. }
  1223. }
  1224. }
  1225. void flush_line (struct vidbuffer *vb, int lineno)
  1226. {
  1227. flushit (vb, lineno);
  1228. }
  1229. void flush_block (struct vidbuffer *vb, int first, int last)
  1230. {
  1231. flushit (vb, first);
  1232. flushit (vb, last);
  1233. }
  1234. void flush_screen (struct vidbuffer *vb, int a, int b)
  1235. {
  1236. }
  1237. #endif
  1238. bool render_screen(int monid, int mode, bool immediate)
  1239. {
  1240. struct AmigaMonitor *mon = &AMonitors[monid];
  1241. struct amigadisplay *ad = &adisplays[monid];
  1242. bool v = false;
  1243. int cnt;
  1244. mon->render_ok = false;
  1245. if (minimized || ad->picasso_on || monitor_off || dx_islost ()) {
  1246. return mon->render_ok;
  1247. }
  1248. cnt = 0;
  1249. while (mon->wait_render) {
  1250. sleep_millis (1);
  1251. cnt++;
  1252. if (cnt > 500) {
  1253. return mon->render_ok;
  1254. }
  1255. }
  1256. // flushymin = 0;
  1257. // flushymax = mon->currentmode.amiga_height;
  1258. gfx_lock();
  1259. if (mon->currentmode.flags & DM_D3D) {
  1260. v = D3D_renderframe(monid, mode, immediate);
  1261. } else if (mon->currentmode.flags & DM_SWSCALE) {
  1262. S2X_render(monid, -1, -1);
  1263. v = true;
  1264. } else if (mon->currentmode.flags & DM_DDRAW) {
  1265. v = true;
  1266. }
  1267. mon->render_ok = v;
  1268. gfx_unlock();
  1269. return mon->render_ok;
  1270. }
  1271. bool show_screen_maybe(int monid, bool show)
  1272. {
  1273. struct AmigaMonitor *mon = &AMonitors[monid];
  1274. struct amigadisplay *ad = &adisplays[monid];
  1275. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  1276. if (!ap->gfx_vflip || ap->gfx_vsyncmode == 0 || ap->gfx_vsync <= 0) {
  1277. if (show)
  1278. show_screen(monid, 0);
  1279. return false;
  1280. }
  1281. #if 0
  1282. if (ap->gfx_vflip < 0) {
  1283. doflipevent ();
  1284. return true;
  1285. }
  1286. #endif
  1287. return false;
  1288. }
  1289. void show_screen_special (void)
  1290. {
  1291. struct AmigaMonitor *mon = &AMonitors[0];
  1292. if (!mon->screen_is_initialized)
  1293. return;
  1294. if (!D3D_showframe_special)
  1295. return;
  1296. if (mon->currentmode.flags & DM_D3D) {
  1297. gfx_lock();
  1298. D3D_showframe_special(0, 1);
  1299. gfx_unlock();
  1300. }
  1301. }
  1302. static frame_time_t strobo_time;
  1303. static volatile int strobo_active;
  1304. static volatile bool strobo_active2;
  1305. static void CALLBACK blackinsertion_cb(
  1306. UINT uTimerID,
  1307. UINT uMsg,
  1308. DWORD_PTR dwUser,
  1309. DWORD_PTR dw1,
  1310. DWORD_PTR dw2
  1311. )
  1312. {
  1313. struct AmigaMonitor *mon = &AMonitors[0];
  1314. if (mon->screen_is_initialized) {
  1315. if (strobo_active) {
  1316. }
  1317. while (strobo_active) {
  1318. frame_time_t ct = read_processor_time();
  1319. int diff = (int)strobo_time - (int)ct;
  1320. if (diff < -vsynctimebase / 2) {
  1321. break;
  1322. }
  1323. if (diff <= 0) {
  1324. if (strobo_active) {
  1325. gfx_lock();
  1326. D3D_showframe_special(0, 1);
  1327. gfx_unlock();
  1328. }
  1329. break;
  1330. }
  1331. if (diff > vsynctimebase / 4) {
  1332. break;
  1333. }
  1334. }
  1335. }
  1336. strobo_active = 0;
  1337. }
  1338. float target_adjust_vblank_hz(int monid, float hz)
  1339. {
  1340. struct AmigaMonitor *mon = &AMonitors[monid];
  1341. int maxrate;
  1342. if (!currprefs.lightboost_strobo)
  1343. return hz;
  1344. if (isfullscreen() > 0) {
  1345. maxrate = mon->currentmode.freq;
  1346. } else {
  1347. maxrate = deskhz;
  1348. }
  1349. double nhz = hz * 2.0;
  1350. if (nhz >= maxrate - 1 && nhz < maxrate + 1)
  1351. hz -= 0.5;
  1352. return hz;
  1353. }
  1354. void show_screen(int monid, int mode)
  1355. {
  1356. struct AmigaMonitor *mon = &AMonitors[monid];
  1357. struct amigadisplay *ad = &adisplays[monid];
  1358. strobo_active = false;
  1359. strobo_active2 = false;
  1360. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  1361. gfx_lock();
  1362. if (mode == 2 || mode == 3 || mode == 4) {
  1363. if ((mon->currentmode.flags & DM_D3D) && D3D_showframe_special && ap->gfx_strobo) {
  1364. if (mode == 4) {
  1365. // erase + render
  1366. D3D_showframe_special(0, 2);
  1367. D3D_showframe_special(0, 1);
  1368. } else {
  1369. // erase or render
  1370. D3D_showframe_special(0, mode == 3 ? 2 : 1);
  1371. }
  1372. }
  1373. gfx_unlock();
  1374. return;
  1375. }
  1376. if (mode >= 0 && !mon->render_ok) {
  1377. gfx_unlock();
  1378. return;
  1379. }
  1380. if (mon->currentmode.flags & DM_D3D) {
  1381. if (ap->gfx_strobo && currprefs.gfx_variable_sync) {
  1382. float vblank = vblank_hz;
  1383. int ratio = currprefs.lightboost_strobo_ratio;
  1384. int ms = (int)(1000 / vblank);
  1385. int waitms = ms * ratio / 100 - 1;
  1386. strobo_active = -1;
  1387. strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
  1388. timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
  1389. }
  1390. #if 0
  1391. if (ap->gfx_vsync < 0 && ap->gfx_strobo && currprefs.gfx_api < 2) {
  1392. float vblank = vblank_hz;
  1393. if (WIN32GFX_IsPicassoScreen(mon)) {
  1394. if (currprefs.win32_rtgvblankrate > 0)
  1395. vblank = currprefs.win32_rtgvblankrate;
  1396. }
  1397. bool ok = true;
  1398. int ratio = currprefs.lightboost_strobo_ratio;
  1399. int ms = (int)(1000 / vblank);
  1400. int waitms = ms * ratio / 100 - 1;
  1401. int maxrate;
  1402. if (isfullscreen() > 0) {
  1403. maxrate = mon->currentmode.freq;
  1404. } else {
  1405. maxrate = deskhz;
  1406. }
  1407. if (maxrate > 0) {
  1408. double rate = vblank * 2.0;
  1409. rate *= ratio > 50 ? ratio / 50.0 : 50.0 / ratio;
  1410. if (rate > maxrate + 1.0)
  1411. ok = false;
  1412. }
  1413. if (ok) {
  1414. strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
  1415. strobo_active = true;
  1416. timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
  1417. }
  1418. }
  1419. #endif
  1420. D3D_showframe(monid);
  1421. if (monid == 0) {
  1422. strobo_active2 = true;
  1423. if (strobo_active < 0) {
  1424. D3D_showframe_special(0, 2);
  1425. }
  1426. }
  1427. #ifdef GFXFILTER
  1428. } else if (mon->currentmode.flags & DM_SWSCALE) {
  1429. if (!dx_islost () && !ad->picasso_on)
  1430. DirectDraw_Flip(1);
  1431. #endif
  1432. } else if (mon->currentmode.flags & DM_DDRAW) {
  1433. if (!dx_islost () && !ad->picasso_on)
  1434. DirectDraw_Flip(1);
  1435. }
  1436. gfx_unlock();
  1437. mon->render_ok = false;
  1438. }
  1439. static uae_u8 *ddraw_dolock (void)
  1440. {
  1441. struct vidbuf_description *avidinfo = &adisplays[0].gfxvidinfo;
  1442. if (!DirectDraw_SurfaceLock ()) {
  1443. dx_check ();
  1444. return 0;
  1445. }
  1446. avidinfo->outbuffer->bufmem = DirectDraw_GetSurfacePointer ();
  1447. avidinfo->outbuffer->rowbytes = DirectDraw_GetSurfacePitch ();
  1448. init_row_map ();
  1449. clear_inhibit_frame(0, IHF_WINDOWHIDDEN);
  1450. return avidinfo->outbuffer->bufmem;
  1451. }
  1452. bool lockscr3d(struct vidbuffer *vb)
  1453. {
  1454. struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
  1455. if (mon->currentmode.flags & DM_D3D) {
  1456. if (!(mon->currentmode.flags & DM_SWSCALE)) {
  1457. vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, false);
  1458. if (vb->bufmem)
  1459. return true;
  1460. }
  1461. }
  1462. return false;
  1463. }
  1464. void unlockscr3d(struct vidbuffer *vb)
  1465. {
  1466. struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
  1467. if (mon->currentmode.flags & DM_D3D) {
  1468. if (!(mon->currentmode.flags & DM_SWSCALE)) {
  1469. D3D_unlocktexture(vb->monitor_id, -1, -1);
  1470. }
  1471. }
  1472. }
  1473. int lockscr(struct vidbuffer *vb, bool fullupdate, bool first, bool skip)
  1474. {
  1475. struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
  1476. int ret = 0;
  1477. if (!isscreen(mon))
  1478. return ret;
  1479. #if 0
  1480. flushymin = mon->currentmode.amiga_height;
  1481. flushymax = 0;
  1482. #endif
  1483. gfx_lock();
  1484. ret = 1;
  1485. if (mon->currentmode.flags & DM_D3D) {
  1486. #ifdef D3D
  1487. if (mon->currentmode.flags & DM_SWSCALE) {
  1488. ret = 1;
  1489. } else {
  1490. ret = 0;
  1491. vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, skip ? -1 : (fullupdate ? 1 : 0));
  1492. if (vb->bufmem) {
  1493. if (first)
  1494. init_row_map();
  1495. ret = 1;
  1496. }
  1497. }
  1498. #endif
  1499. } else if (mon->currentmode.flags & DM_SWSCALE) {
  1500. ret = 1;
  1501. } else if (mon->currentmode.flags & DM_DDRAW) {
  1502. ret = ddraw_dolock() != 0;
  1503. }
  1504. gfx_unlock();
  1505. return ret;
  1506. }
  1507. void unlockscr(struct vidbuffer *vb, int y_start, int y_end)
  1508. {
  1509. struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
  1510. gfx_lock();
  1511. if (mon->currentmode.flags & DM_D3D) {
  1512. if (mon->currentmode.flags & DM_SWSCALE) {
  1513. S2X_render(vb->monitor_id, y_start, y_end);
  1514. } else {
  1515. vb->bufmem = NULL;
  1516. }
  1517. D3D_unlocktexture(vb->monitor_id, y_start, y_end);
  1518. } else if (mon->currentmode.flags & DM_SWSCALE) {
  1519. return;
  1520. } else if (mon->currentmode.flags & DM_DDRAW) {
  1521. DirectDraw_SurfaceUnlock();
  1522. vb->bufmem = NULL;
  1523. }
  1524. gfx_unlock();
  1525. }
  1526. void flush_clear_screen (struct vidbuffer *vb)
  1527. {
  1528. if (!vb)
  1529. return;
  1530. if (lockscr(vb, true, true, false)) {
  1531. int y;
  1532. for (y = 0; y < vb->height_allocated; y++) {
  1533. memset(vb->bufmem + y * vb->rowbytes, 0, vb->width_allocated * vb->pixbytes);
  1534. }
  1535. unlockscr(vb, -1, -1);
  1536. }
  1537. }
  1538. static void DX_Blit96(struct AmigaMonitor *mon, int x, int y, int w, int h)
  1539. {
  1540. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  1541. RECT dr, sr;
  1542. picasso_offset_x = 0;
  1543. picasso_offset_y = 0;
  1544. picasso_offset_mx = 1.0;
  1545. picasso_offset_my = 1.0;
  1546. if (mon->scalepicasso) {
  1547. int srcratio, dstratio;
  1548. int srcwidth, srcheight;
  1549. if (mon->scalepicasso < 0 || mon->scalepicasso > 1) {
  1550. srcwidth = state->Width;
  1551. srcheight = state->Height;
  1552. } else {
  1553. srcwidth = mon->currentmode.native_width;
  1554. srcheight = mon->currentmode.native_height;
  1555. }
  1556. SetRect (&sr, 0, 0, state->Width, state->Height);
  1557. if (currprefs.win32_rtgscaleaspectratio < 0) {
  1558. // automatic
  1559. srcratio = state->Width * ASPECTMULT / state->Height;
  1560. dstratio = srcwidth * ASPECTMULT / srcheight;
  1561. } else if (currprefs.win32_rtgscaleaspectratio == 0) {
  1562. // none
  1563. srcratio = dstratio = 0;
  1564. } else {
  1565. // manual
  1566. srcratio = currprefs.win32_rtgscaleaspectratio;
  1567. dstratio = srcwidth * ASPECTMULT / srcheight;
  1568. }
  1569. if (srcratio == dstratio) {
  1570. SetRect (&dr, 0, 0, srcwidth, srcheight);
  1571. } else if (srcratio > dstratio) {
  1572. int yy = srcheight - srcheight * dstratio / srcratio;
  1573. SetRect (&dr, 0, yy / 2, srcwidth, srcheight - yy / 2);
  1574. picasso_offset_y = yy / 2;
  1575. } else {
  1576. int xx = srcwidth - srcwidth * srcratio / dstratio;
  1577. SetRect (&dr, xx / 2, 0,srcwidth - xx / 2, srcheight);
  1578. picasso_offset_x = xx / 2;
  1579. }
  1580. picasso_offset_mx = (float)state->Width / (dr.right - dr.left);
  1581. picasso_offset_my = (float)state->Height / (dr.bottom - dr.top);
  1582. DirectDraw_BlitToPrimaryScale (&dr, &sr);
  1583. } else {
  1584. SetRect (&sr, x, y, x + w, y + h);
  1585. DirectDraw_BlitToPrimary (&sr);
  1586. }
  1587. }
  1588. void getrtgfilterrect2(int monid, RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height)
  1589. {
  1590. struct AmigaMonitor *mon = &AMonitors[monid];
  1591. struct amigadisplay *ad = &adisplays[monid];
  1592. struct picasso96_state_struct *state = &picasso96_state[monid];
  1593. SetRect (sr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
  1594. SetRect (dr, 0, 0, state->Width, state->Height);
  1595. SetRect (zr, 0, 0, 0, 0);
  1596. picasso_offset_x = 0;
  1597. picasso_offset_y = 0;
  1598. picasso_offset_mx = 1.0;
  1599. picasso_offset_my = 1.0;
  1600. if (!ad->picasso_on)
  1601. return;
  1602. if (!mon->scalepicasso)
  1603. return;
  1604. int srcratio, dstratio;
  1605. int srcwidth, srcheight;
  1606. srcwidth = state->Width;
  1607. srcheight = state->Height;
  1608. if (!srcwidth || !srcheight)
  1609. return;
  1610. float mx = (float)mon->currentmode.native_width / srcwidth;
  1611. float my = (float)mon->currentmode.native_height / srcheight;
  1612. if (mon->scalepicasso == RTG_MODE_INTEGER_SCALE) {
  1613. int divx = mon->currentmode.native_width / srcwidth;
  1614. int divy = mon->currentmode.native_height / srcheight;
  1615. int mul = divx > divy ? divy : divx;
  1616. int xx = srcwidth * mul;
  1617. int yy = srcheight * mul;
  1618. SetRect (dr, 0, 0, mon->currentmode.native_width / mul, mon->currentmode.native_height / mul);
  1619. //picasso_offset_x = -(state->Width - xx) / 2;
  1620. //picasso_offset_y = -(mon->currentmode.native_height - srcheight) / 2;
  1621. mx = my = 1.0;
  1622. } else if (mon->scalepicasso == RTG_MODE_CENTER) {
  1623. int xx = (mon->currentmode.native_width - srcwidth) / 2;
  1624. int yy = (mon->currentmode.native_heigh

Large files files are truncated, but you can click here to view the full file