PageRenderTime 115ms CodeModel.GetById 16ms RepoModel.GetById 0ms 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
  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_height - srcheight) / 2;
  1625. picasso_offset_x = -xx;
  1626. picasso_offset_y = -yy;
  1627. SetRect (dr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
  1628. mx = my = 1.0;
  1629. } else {
  1630. if (currprefs.win32_rtgscaleaspectratio < 0) {
  1631. // automatic
  1632. srcratio = srcwidth * ASPECTMULT / srcheight;
  1633. dstratio = mon->currentmode.native_width * ASPECTMULT / mon->currentmode.native_height;
  1634. } else if (currprefs.win32_rtgscaleaspectratio == 0) {
  1635. // none
  1636. srcratio = dstratio = 0;
  1637. } else {
  1638. // manual
  1639. dstratio = (currprefs.win32_rtgscaleaspectratio / ASPECTMULT) * ASPECTMULT / (currprefs.win32_rtgscaleaspectratio & (ASPECTMULT - 1));
  1640. srcratio = srcwidth * ASPECTMULT / srcheight;
  1641. }
  1642. if (srcratio == dstratio) {
  1643. SetRect (dr, 0, 0, srcwidth, srcheight);
  1644. } else if (srcratio > dstratio) {
  1645. int yy = srcheight * srcratio / dstratio;
  1646. SetRect (dr, 0, 0, srcwidth, yy);
  1647. picasso_offset_y = (state->Height - yy) / 2;
  1648. } else {
  1649. int xx = srcwidth * dstratio / srcratio;
  1650. SetRect (dr, 0, 0, xx, srcheight);
  1651. picasso_offset_x = (state->Width - xx) / 2;
  1652. }
  1653. }
  1654. OffsetRect (zr, picasso_offset_x, picasso_offset_y);
  1655. picasso_offset_mx = (float)srcwidth * mx / (dr->right - dr->left);
  1656. picasso_offset_my = (float)srcheight * my / (dr->bottom - dr->top);
  1657. }
  1658. static uae_u8 *gfx_lock_picasso2(int monid, bool fullupdate)
  1659. {
  1660. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  1661. if (currprefs.gfx_api) {
  1662. int pitch;
  1663. uae_u8 *p = D3D_locktexture(monid, &pitch, NULL, fullupdate);
  1664. vidinfo->rowbytes = pitch;
  1665. return p;
  1666. } else {
  1667. if (!DirectDraw_SurfaceLock ()) {
  1668. dx_check ();
  1669. return 0;
  1670. }
  1671. vidinfo->rowbytes = DirectDraw_GetSurfacePitch ();
  1672. return DirectDraw_GetSurfacePointer ();
  1673. }
  1674. }
  1675. uae_u8 *gfx_lock_picasso(int monid, bool fullupdate)
  1676. {
  1677. struct AmigaMonitor *mon = &AMonitors[monid];
  1678. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  1679. static uae_u8 *p;
  1680. if (mon->rtg_locked) {
  1681. return p;
  1682. }
  1683. gfx_lock();
  1684. p = gfx_lock_picasso2(monid, fullupdate);
  1685. if (!p) {
  1686. gfx_unlock();
  1687. } else {
  1688. mon->rtg_locked = true;
  1689. }
  1690. return p;
  1691. }
  1692. void gfx_unlock_picasso(int monid, bool dorender)
  1693. {
  1694. struct AmigaMonitor *mon = &AMonitors[monid];
  1695. if (!mon->rtg_locked)
  1696. gfx_lock();
  1697. mon->rtg_locked = false;
  1698. if (currprefs.gfx_api) {
  1699. if (dorender) {
  1700. if (mon->p96_double_buffer_needs_flushing) {
  1701. D3D_flushtexture(monid, mon->p96_double_buffer_first, mon->p96_double_buffer_last);
  1702. mon->p96_double_buffer_needs_flushing = 0;
  1703. }
  1704. }
  1705. D3D_unlocktexture(monid, -1, -1);
  1706. if (dorender) {
  1707. if (D3D_renderframe(monid, true, false)) {
  1708. gfx_unlock();
  1709. mon->render_ok = true;
  1710. show_screen_maybe(monid, true);
  1711. } else {
  1712. gfx_unlock();
  1713. }
  1714. } else {
  1715. gfx_unlock();
  1716. }
  1717. } else {
  1718. DirectDraw_SurfaceUnlock ();
  1719. if (dorender) {
  1720. if (mon->p96_double_buffer_needs_flushing) {
  1721. DX_Blit96(mon, mon->p96_double_buffer_firstx, mon->p96_double_buffer_first,
  1722. mon->p96_double_buffer_lastx - mon->p96_double_buffer_firstx + 1,
  1723. mon->p96_double_buffer_last - mon->p96_double_buffer_first + 1);
  1724. mon->p96_double_buffer_needs_flushing = 0;
  1725. }
  1726. }
  1727. gfx_unlock();
  1728. }
  1729. }
  1730. static HWND blankwindows[MAX_DISPLAYS];
  1731. static void closeblankwindows (void)
  1732. {
  1733. for (int i = 0; i < MAX_DISPLAYS; i++) {
  1734. HWND h = blankwindows[i];
  1735. if (h) {
  1736. ShowWindow (h, SW_HIDE);
  1737. DestroyWindow (h);
  1738. blankwindows[i] = NULL;
  1739. }
  1740. }
  1741. }
  1742. static void createblankwindows (void)
  1743. {
  1744. struct MultiDisplay *mdx = getdisplay(&currprefs, 0);
  1745. int i;
  1746. if (!currprefs.win32_blankmonitors)
  1747. return;
  1748. for (i = 0; Displays[i].monitorname; i++) {
  1749. struct MultiDisplay *md = &Displays[i];
  1750. TCHAR name[100];
  1751. if (mdx == md)
  1752. continue;
  1753. _stprintf (name, _T("WinUAE_Blank_%d"), i);
  1754. blankwindows[i] = CreateWindowEx (
  1755. WS_EX_TOPMOST,
  1756. _T("Blank"), name,
  1757. WS_POPUP | WS_VISIBLE,
  1758. md->rect.left, md->rect.top, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top,
  1759. NULL,
  1760. NULL, hInst, NULL);
  1761. }
  1762. }
  1763. static void close_hwnds(struct AmigaMonitor *mon)
  1764. {
  1765. if (mon->screen_is_initialized)
  1766. releasecapture(mon);
  1767. mon->screen_is_initialized = 0;
  1768. if (!mon->monitor_id) {
  1769. display_vblank_thread_kill();
  1770. #ifdef AVIOUTPUT
  1771. AVIOutput_Restart();
  1772. #endif
  1773. #ifdef RETROPLATFORM
  1774. rp_set_hwnd(NULL);
  1775. #endif
  1776. closeblankwindows();
  1777. rawinput_release();
  1778. }
  1779. if (mon->monitor_id > 0 && mon->hMainWnd)
  1780. setmouseactive(mon->monitor_id, 0);
  1781. deletestatusline(mon->monitor_id);
  1782. if (mon->hStatusWnd) {
  1783. ShowWindow(mon->hStatusWnd, SW_HIDE);
  1784. DestroyWindow(mon->hStatusWnd);
  1785. mon->hStatusWnd = 0;
  1786. if (mon->hStatusBkgB)
  1787. DeleteObject(mon->hStatusBkgB);
  1788. mon->hStatusBkgB = NULL;
  1789. }
  1790. if (mon->hAmigaWnd) {
  1791. addnotifications (mon->hAmigaWnd, TRUE, FALSE);
  1792. #ifdef D3D
  1793. D3D_free(mon->monitor_id, true);
  1794. #endif
  1795. ShowWindow (mon->hAmigaWnd, SW_HIDE);
  1796. DestroyWindow (mon->hAmigaWnd);
  1797. if (mon->hAmigaWnd == mon->hMainWnd)
  1798. mon->hMainWnd = 0;
  1799. mon->hAmigaWnd = 0;
  1800. }
  1801. if (mon->hMainWnd) {
  1802. ShowWindow(mon->hMainWnd, SW_HIDE);
  1803. DestroyWindow(mon->hMainWnd);
  1804. mon->hMainWnd = 0;
  1805. }
  1806. gfx_hdr = false;
  1807. }
  1808. static bool canmatchdepth(void)
  1809. {
  1810. if (!currprefs.win32_rtgmatchdepth)
  1811. return false;
  1812. if (currprefs.gfx_api >= 2)
  1813. return false;
  1814. return true;
  1815. }
  1816. static void updatemodes(struct AmigaMonitor *mon)
  1817. {
  1818. struct uae_filter *usedfilter = mon->usedfilter;
  1819. DWORD flags;
  1820. mon->currentmode.fullfill = 0;
  1821. flags = DM_DDRAW;
  1822. if (isfullscreen () > 0)
  1823. flags |= DM_DX_FULLSCREEN;
  1824. else if (isfullscreen () < 0)
  1825. flags |= DM_W_FULLSCREEN;
  1826. #if defined (GFXFILTER)
  1827. if (usedfilter) {
  1828. flags |= DM_SWSCALE;
  1829. if (mon->currentmode.current_depth < 15)
  1830. mon->currentmode.current_depth = 16;
  1831. }
  1832. #endif
  1833. if (currprefs.gfx_api) {
  1834. flags |= DM_D3D;
  1835. if (flags & DM_DX_FULLSCREEN) {
  1836. flags &= ~DM_DX_FULLSCREEN;
  1837. flags |= DM_D3D_FULLSCREEN;
  1838. }
  1839. flags &= ~DM_DDRAW;
  1840. }
  1841. mon->currentmode.flags = flags;
  1842. if (flags & DM_SWSCALE)
  1843. mon->currentmode.fullfill = 1;
  1844. if (flags & DM_W_FULLSCREEN) {
  1845. RECT rc = getdisplay(&currprefs, mon->monitor_id)->rect;
  1846. mon->currentmode.native_width = rc.right - rc.left;
  1847. mon->currentmode.native_height = rc.bottom - rc.top;
  1848. mon->currentmode.current_width = mon->currentmode.native_width;
  1849. mon->currentmode.current_height = mon->currentmode.native_height;
  1850. } else {
  1851. mon->currentmode.native_width = mon->currentmode.current_width;
  1852. mon->currentmode.native_height = mon->currentmode.current_height;
  1853. }
  1854. }
  1855. static void update_gfxparams(struct AmigaMonitor *mon)
  1856. {
  1857. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  1858. updatewinfsmode(mon->monitor_id, &currprefs);
  1859. #ifdef PICASSO96
  1860. mon->currentmode.vsync = 0;
  1861. if (mon->screen_is_picasso) {
  1862. mon->currentmode.current_width = (int)(state->Width * currprefs.rtg_horiz_zoom_mult);
  1863. mon->currentmode.current_height = (int)(state->Height * currprefs.rtg_vert_zoom_mult);
  1864. currprefs.gfx_apmode[1].gfx_interlaced = false;
  1865. if (currprefs.win32_rtgvblankrate == 0) {
  1866. currprefs.gfx_apmode[1].gfx_refreshrate = currprefs.gfx_apmode[0].gfx_refreshrate;
  1867. if (currprefs.gfx_apmode[0].gfx_interlaced) {
  1868. currprefs.gfx_apmode[1].gfx_refreshrate *= 2;
  1869. }
  1870. } else if (currprefs.win32_rtgvblankrate < 0) {
  1871. currprefs.gfx_apmode[1].gfx_refreshrate = 0;
  1872. } else {
  1873. currprefs.gfx_apmode[1].gfx_refreshrate = currprefs.win32_rtgvblankrate;
  1874. }
  1875. if (currprefs.gfx_apmode[1].gfx_vsync)
  1876. mon->currentmode.vsync = 1 + currprefs.gfx_apmode[1].gfx_vsyncmode;
  1877. } else {
  1878. #endif
  1879. mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
  1880. mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
  1881. if (currprefs.gfx_apmode[0].gfx_vsync)
  1882. mon->currentmode.vsync = 1 + currprefs.gfx_apmode[0].gfx_vsyncmode;
  1883. #ifdef PICASSO96
  1884. }
  1885. #endif
  1886. #if FORCE16BIT
  1887. mon->currentmode.current_depth = 16;
  1888. #else
  1889. mon->currentmode.current_depth = currprefs.color_mode < 5 ? 16 : 32;
  1890. #endif
  1891. if (mon->screen_is_picasso && canmatchdepth() && isfullscreen () > 0) {
  1892. int pbits = state->BytesPerPixel * 8;
  1893. if (pbits <= 8) {
  1894. if (mon->currentmode.current_depth == 32)
  1895. pbits = 32;
  1896. else
  1897. pbits = 16;
  1898. }
  1899. if (pbits == 24)
  1900. pbits = 32;
  1901. mon->currentmode.current_depth = pbits;
  1902. }
  1903. mon->currentmode.amiga_width = mon->currentmode.current_width;
  1904. mon->currentmode.amiga_height = mon->currentmode.current_height;
  1905. mon->scalepicasso = 0;
  1906. if (mon->screen_is_picasso) {
  1907. if (isfullscreen () < 0) {
  1908. if ((currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_CENTER || currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_SCALE || currprefs.win32_rtgallowscaling) && (state->Width != mon->currentmode.native_width || state->Height != mon->currentmode.native_height))
  1909. mon->scalepicasso = 1;
  1910. if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_CENTER)
  1911. mon->scalepicasso = currprefs.gf[1].gfx_filter_autoscale;
  1912. if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio)
  1913. mon->scalepicasso = -1;
  1914. } else if (isfullscreen () > 0) {
  1915. if (!canmatchdepth()) { // can't scale to different color depth
  1916. if (mon->currentmode.native_width > state->Width && mon->currentmode.native_height > state->Height) {
  1917. if (currprefs.gf[1].gfx_filter_autoscale)
  1918. mon->scalepicasso = 1;
  1919. }
  1920. if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_CENTER)
  1921. mon->scalepicasso = currprefs.gf[1].gfx_filter_autoscale;
  1922. if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio)
  1923. mon->scalepicasso = -1;
  1924. }
  1925. } else if (isfullscreen () == 0) {
  1926. if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_INTEGER_SCALE) {
  1927. mon->scalepicasso = RTG_MODE_INTEGER_SCALE;
  1928. mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
  1929. mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
  1930. } else if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_CENTER) {
  1931. if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width < state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height < state->Height) {
  1932. if (!currprefs.win32_rtgallowscaling) {
  1933. ;
  1934. } else if (currprefs.win32_rtgscaleaspectratio) {
  1935. mon->scalepicasso = -1;
  1936. mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
  1937. mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
  1938. }
  1939. } else {
  1940. mon->scalepicasso = 2;
  1941. mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
  1942. mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
  1943. }
  1944. } else if (currprefs.gf[1].gfx_filter_autoscale == RTG_MODE_SCALE) {
  1945. if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width > state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height > state->Height)
  1946. mon->scalepicasso = 1;
  1947. if ((currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height) && currprefs.win32_rtgallowscaling) {
  1948. mon->scalepicasso = 1;
  1949. } else if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width < state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height < state->Height) {
  1950. // no always scaling and smaller? Back to normal size and set new configured max size
  1951. mon->currentmode.current_width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width = state->Width;
  1952. mon->currentmode.current_height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height = state->Height;
  1953. } else if (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width == state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height == state->Height) {
  1954. ;
  1955. } else if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio) {
  1956. mon->scalepicasso = -1;
  1957. }
  1958. } else {
  1959. if ((currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height) && currprefs.win32_rtgallowscaling)
  1960. mon->scalepicasso = 1;
  1961. if (!mon->scalepicasso && currprefs.win32_rtgscaleaspectratio)
  1962. mon->scalepicasso = -1;
  1963. }
  1964. }
  1965. if (mon->scalepicasso > 0 && (currprefs.gfx_monitor[mon->monitor_id].gfx_size.width != state->Width || currprefs.gfx_monitor[mon->monitor_id].gfx_size.height != state->Height)) {
  1966. mon->currentmode.current_width = currprefs.gfx_monitor[mon->monitor_id].gfx_size.width;
  1967. mon->currentmode.current_height = currprefs.gfx_monitor[mon->monitor_id].gfx_size.height;
  1968. }
  1969. }
  1970. }
  1971. static int open_windows(struct AmigaMonitor *mon, bool mousecapture, bool started)
  1972. {
  1973. bool recapture = false;
  1974. int ret;
  1975. mon->screen_is_initialized = 0;
  1976. if (mon->monitor_id && mouseactive)
  1977. recapture = true;
  1978. inputdevice_unacquire();
  1979. reset_sound();
  1980. if (mon->hAmigaWnd == NULL)
  1981. wait_keyrelease();
  1982. mon->in_sizemove = 0;
  1983. updatewinfsmode(mon->monitor_id, &currprefs);
  1984. #ifdef D3D
  1985. gfx_lock();
  1986. D3D_free(mon->monitor_id, false);
  1987. gfx_unlock();
  1988. #endif
  1989. if (!DirectDraw_Start())
  1990. return 0;
  1991. int init_round = 0;
  1992. ret = -2;
  1993. do {
  1994. if (ret < -1) {
  1995. updatemodes(mon);
  1996. update_gfxparams(mon);
  1997. }
  1998. ret = doInit(mon);
  1999. init_round++;
  2000. if (ret < -9) {
  2001. DirectDraw_Release();
  2002. if (!DirectDraw_Start())
  2003. return 0;
  2004. }
  2005. } while (ret < 0);
  2006. if (!ret) {
  2007. DirectDraw_Release();
  2008. return ret;
  2009. }
  2010. bool startactive = (started && mouseactive) || (!started && !currprefs.win32_start_uncaptured && !currprefs.win32_start_minimized);
  2011. bool startpaused = !started && ((currprefs.win32_start_minimized && currprefs.win32_iconified_pause) || (currprefs.win32_start_uncaptured && currprefs.win32_inactive_pause && isfullscreen() <= 0));
  2012. bool startminimized = !started && currprefs.win32_start_minimized && isfullscreen() <= 0;
  2013. int input = 0;
  2014. if ((mousecapture && startactive) || recapture)
  2015. setmouseactive(mon->monitor_id, -1);
  2016. int upd = 0;
  2017. if (startactive) {
  2018. setpriority(&priorities[currprefs.win32_active_capture_priority]);
  2019. upd = 2;
  2020. } else if (startminimized) {
  2021. setpriority(&priorities[currprefs.win32_iconified_priority]);
  2022. setminimized(mon->monitor_id);
  2023. input = currprefs.win32_inactive_input;
  2024. upd = 1;
  2025. } else {
  2026. setpriority(&priorities[currprefs.win32_inactive_priority]);
  2027. input = currprefs.win32_inactive_input;
  2028. upd = 2;
  2029. }
  2030. if (upd > 1) {
  2031. for (int i = 0; i < NUM_LEDS; i++)
  2032. gui_flicker_led(i, -1, -1);
  2033. gui_led(LED_POWER, gui_data.powerled, gui_data.powerled_brightness);
  2034. gui_fps(0, 0, 0);
  2035. if (gui_data.md >= 0)
  2036. gui_led(LED_MD, 0, -1);
  2037. for (int i = 0; i < 4; i++) {
  2038. if (currprefs.floppyslots[i].dfxtype >= 0)
  2039. gui_led(LED_DF0 + i, 0, -1);
  2040. }
  2041. }
  2042. if (upd > 0) {
  2043. inputdevice_acquire(TRUE);
  2044. if (!isfocus())
  2045. inputdevice_unacquire(true, input);
  2046. }
  2047. if (startpaused)
  2048. setpaused(1);
  2049. statusline_updated(mon->monitor_id);
  2050. refreshtitle();
  2051. return ret;
  2052. }
  2053. static void reopen_gfx(struct AmigaMonitor *mon)
  2054. {
  2055. open_windows(mon, false, true);
  2056. if (isfullscreen () <= 0)
  2057. DirectDraw_FillPrimary ();
  2058. render_screen(mon->monitor_id, 1, true);
  2059. }
  2060. static int getstatuswindowheight(int monid, HWND hwnd)
  2061. {
  2062. if (monid > 0)
  2063. return 0;
  2064. int def = GetSystemMetrics (SM_CYMENU) + 3;
  2065. WINDOWINFO wi;
  2066. HWND h = CreateWindowEx (
  2067. 0, STATUSCLASSNAME, (LPCTSTR) NULL, SBARS_TOOLTIPS | WS_CHILD,
  2068. 0, 0, 0, 0, hwnd ? hwnd : hHiddenWnd, (HMENU) 1, hInst, NULL);
  2069. if (!h)
  2070. return def;
  2071. wi.cbSize = sizeof wi;
  2072. if (GetWindowInfo(h, &wi)) {
  2073. def = wi.rcWindow.bottom - wi.rcWindow.top;
  2074. }
  2075. DestroyWindow(h);
  2076. return def;
  2077. }
  2078. void graphics_reset(bool forced)
  2079. {
  2080. if (forced) {
  2081. display_change_requested = 2;
  2082. } else {
  2083. // full reset if display size can't changed.
  2084. if (currprefs.gfx_api) {
  2085. display_change_requested = 3;
  2086. } else {
  2087. display_change_requested = 2;
  2088. }
  2089. }
  2090. }
  2091. void WIN32GFX_DisplayChangeRequested (int mode)
  2092. {
  2093. display_change_requested = mode;
  2094. }
  2095. int check_prefs_changed_gfx (void)
  2096. {
  2097. int c = 0;
  2098. bool monitors[MAX_AMIGAMONITORS];
  2099. if (!config_changed && !display_change_requested)
  2100. return 0;
  2101. c |= currprefs.win32_statusbar != changed_prefs.win32_statusbar ? 512 : 0;
  2102. for (int i = 0; i < MAX_AMIGADISPLAYS; i++) {
  2103. monitors[i] = false;
  2104. int c2 = 0;
  2105. c2 |= currprefs.gfx_monitor[i].gfx_size_fs.width != changed_prefs.gfx_monitor[i].gfx_size_fs.width ? 16 : 0;
  2106. c2 |= currprefs.gfx_monitor[i].gfx_size_fs.height != changed_prefs.gfx_monitor[i].gfx_size_fs.height ? 16 : 0;
  2107. c2 |= ((currprefs.gfx_monitor[i].gfx_size_win.width + 7) & ~7) != ((changed_prefs.gfx_monitor[i].gfx_size_win.width + 7) & ~7) ? 16 : 0;
  2108. c2 |= currprefs.gfx_monitor[i].gfx_size_win.height != changed_prefs.gfx_monitor[i].gfx_size_win.height ? 16 : 0;
  2109. if (c2) {
  2110. c |= c2;
  2111. monitors[i] = true;
  2112. }
  2113. }
  2114. monitors[0] = true;
  2115. #if 0
  2116. c |= currprefs.gfx_size_win.x != changed_prefs.gfx_size_win.x ? 16 : 0;
  2117. c |= currprefs.gfx_size_win.y != changed_prefs.gfx_size_win.y ? 16 : 0;
  2118. #endif
  2119. c |= currprefs.color_mode != changed_prefs.color_mode ? 2 | 16 : 0;
  2120. c |= currprefs.gfx_apmode[0].gfx_fullscreen != changed_prefs.gfx_apmode[0].gfx_fullscreen ? 16 : 0;
  2121. c |= currprefs.gfx_apmode[1].gfx_fullscreen != changed_prefs.gfx_apmode[1].gfx_fullscreen ? 16 : 0;
  2122. c |= currprefs.gfx_apmode[0].gfx_vsync != changed_prefs.gfx_apmode[0].gfx_vsync ? 2 | 16 : 0;
  2123. c |= currprefs.gfx_apmode[1].gfx_vsync != changed_prefs.gfx_apmode[1].gfx_vsync ? 2 | 16 : 0;
  2124. c |= currprefs.gfx_apmode[0].gfx_vsyncmode != changed_prefs.gfx_apmode[0].gfx_vsyncmode ? 2 | 16 : 0;
  2125. c |= currprefs.gfx_apmode[1].gfx_vsyncmode != changed_prefs.gfx_apmode[1].gfx_vsyncmode ? 2 | 16 : 0;
  2126. c |= currprefs.gfx_apmode[0].gfx_refreshrate != changed_prefs.gfx_apmode[0].gfx_refreshrate ? 2 | 16 : 0;
  2127. #if 0
  2128. c |= currprefs.gfx_apmode[1].gfx_refreshrate != changed_prefs.gfx_apmode[1].gfx_refreshrate ? 2 | 16 : 0;
  2129. #endif
  2130. c |= currprefs.gfx_autoresolution != changed_prefs.gfx_autoresolution ? (2|8|16) : 0;
  2131. c |= currprefs.gfx_autoresolution_vga != changed_prefs.gfx_autoresolution_vga ? (2|8|16) : 0;
  2132. c |= currprefs.gfx_api != changed_prefs.gfx_api ? (1 | 8 | 32) : 0;
  2133. c |= currprefs.gfx_api_options != changed_prefs.gfx_api_options ? (1 | 8 | 32) : 0;
  2134. c |= currprefs.lightboost_strobo != changed_prefs.lightboost_strobo ? (2|16) : 0;
  2135. for (int j = 0; j < 2; j++) {
  2136. struct gfx_filterdata *gf = &currprefs.gf[j];
  2137. struct gfx_filterdata *gfc = &changed_prefs.gf[j];
  2138. c |= gf->gfx_filter != gfc->gfx_filter ? (2|8) : 0;
  2139. for (int i = 0; i <= 2 * MAX_FILTERSHADERS; i++) {
  2140. c |= _tcscmp (gf->gfx_filtershader[i], gfc->gfx_filtershader[i]) ? (2|8) : 0;
  2141. c |= _tcscmp (gf->gfx_filtermask[i], gfc->gfx_filtermask[i]) ? (2|8) : 0;
  2142. }
  2143. c |= _tcscmp (gf->gfx_filteroverlay, gfc->gfx_filteroverlay) ? (2|8) : 0;
  2144. c |= gf->gfx_filter_scanlines != gfc->gfx_filter_scanlines ? (1|8) : 0;
  2145. c |= gf->gfx_filter_scanlinelevel != gfc->gfx_filter_scanlinelevel ? (1|8) : 0;
  2146. c |= gf->gfx_filter_scanlineratio != gfc->gfx_filter_scanlineratio ? (1 | 8) : 0;
  2147. c |= gf->gfx_filter_scanlineoffset != gfc->gfx_filter_scanlineoffset ? (1 | 8) : 0;
  2148. c |= gf->gfx_filter_horiz_zoom_mult != gfc->gfx_filter_horiz_zoom_mult ? (1) : 0;
  2149. c |= gf->gfx_filter_vert_zoom_mult != gfc->gfx_filter_vert_zoom_mult ? (1) : 0;
  2150. c |= gf->gfx_filter_filtermodeh != gfc->gfx_filter_filtermodeh ? (2 | 8) : 0;
  2151. c |= gf->gfx_filter_filtermodev != gfc->gfx_filter_filtermodev ? (2 | 8) : 0;
  2152. c |= gf->gfx_filter_bilinear != gfc->gfx_filter_bilinear ? (2|8|16) : 0;
  2153. c |= gf->gfx_filter_noise != gfc->gfx_filter_noise ? (1) : 0;
  2154. c |= gf->gfx_filter_blur != gfc->gfx_filter_blur ? (1) : 0;
  2155. c |= gf->gfx_filter_aspect != gfc->gfx_filter_aspect ? (1) : 0;
  2156. c |= gf->gfx_filter_keep_aspect != gfc->gfx_filter_keep_aspect ? (1) : 0;
  2157. c |= gf->gfx_filter_keep_autoscale_aspect != gfc->gfx_filter_keep_autoscale_aspect ? (1) : 0;
  2158. c |= gf->gfx_filter_luminance != gfc->gfx_filter_luminance ? (1) : 0;
  2159. c |= gf->gfx_filter_contrast != gfc->gfx_filter_contrast ? (1) : 0;
  2160. c |= gf->gfx_filter_saturation != gfc->gfx_filter_saturation ? (1) : 0;
  2161. c |= gf->gfx_filter_gamma != gfc->gfx_filter_gamma ? (1) : 0;
  2162. c |= gf->gfx_filter_integerscalelimit != gfc->gfx_filter_integerscalelimit ? (1) : 0;
  2163. if (j && gf->gfx_filter_autoscale != gfc->gfx_filter_autoscale)
  2164. c |= 8 | 64;
  2165. //c |= gf->gfx_filter_ != gfc->gfx_filter_ ? (1|8) : 0;
  2166. }
  2167. c |= currprefs.rtg_horiz_zoom_mult != changed_prefs.rtg_horiz_zoom_mult ? 16 : 0;
  2168. c |= currprefs.rtg_vert_zoom_mult != changed_prefs.rtg_vert_zoom_mult ? 16 : 0;
  2169. c |= currprefs.gfx_luminance != changed_prefs.gfx_luminance ? (1 | 256) : 0;
  2170. c |= currprefs.gfx_contrast != changed_prefs.gfx_contrast ? (1 | 256) : 0;
  2171. c |= currprefs.gfx_gamma != changed_prefs.gfx_gamma ? (1 | 256) : 0;
  2172. c |= currprefs.gfx_resolution != changed_prefs.gfx_resolution ? (128) : 0;
  2173. c |= currprefs.gfx_vresolution != changed_prefs.gfx_vresolution ? (128) : 0;
  2174. c |= currprefs.gfx_autoresolution_minh != changed_prefs.gfx_autoresolution_minh ? (128) : 0;
  2175. c |= currprefs.gfx_autoresolution_minv != changed_prefs.gfx_autoresolution_minv ? (128) : 0;
  2176. c |= currprefs.gfx_iscanlines != changed_prefs.gfx_iscanlines ? (2 | 8) : 0;
  2177. c |= currprefs.gfx_pscanlines != changed_prefs.gfx_pscanlines ? (2 | 8) : 0;
  2178. c |= currprefs.monitoremu != changed_prefs.monitoremu ? (2 | 8) : 0;
  2179. c |= currprefs.genlock_image != changed_prefs.genlock_image ? (2 | 8) : 0;
  2180. c |= currprefs.genlock != changed_prefs.genlock ? (2 | 8) : 0;
  2181. c |= currprefs.genlock_alpha != changed_prefs.genlock_alpha ? (1 | 8) : 0;
  2182. c |= currprefs.genlock_mix != changed_prefs.genlock_mix ? (1 | 256) : 0;
  2183. c |= currprefs.genlock_aspect != changed_prefs.genlock_aspect ? (1 | 256) : 0;
  2184. c |= currprefs.genlock_scale != changed_prefs.genlock_scale ? (1 | 256) : 0;
  2185. c |= _tcsicmp(currprefs.genlock_image_file, changed_prefs.genlock_image_file) ? (2 | 8) : 0;
  2186. c |= _tcsicmp(currprefs.genlock_video_file, changed_prefs.genlock_video_file) ? (2 | 8) : 0;
  2187. c |= currprefs.gfx_lores_mode != changed_prefs.gfx_lores_mode ? (2 | 8) : 0;
  2188. c |= currprefs.gfx_overscanmode != changed_prefs.gfx_overscanmode ? (2 | 8) : 0;
  2189. c |= currprefs.gfx_scandoubler != changed_prefs.gfx_scandoubler ? (2 | 8) : 0;
  2190. c |= currprefs.gfx_threebitcolors != changed_prefs.gfx_threebitcolors ? (256) : 0;
  2191. c |= currprefs.gfx_grayscale != changed_prefs.gfx_grayscale ? (512) : 0;
  2192. c |= currprefs.gfx_display_sections != changed_prefs.gfx_display_sections ? (512) : 0;
  2193. c |= currprefs.gfx_variable_sync != changed_prefs.gfx_variable_sync ? 1 : 0;
  2194. c |= currprefs.gfx_windowed_resize != changed_prefs.gfx_windowed_resize ? 1 : 0;
  2195. c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_display != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_display ? (2|4|8) : 0;
  2196. c |= currprefs.gfx_apmode[APMODE_RTG].gfx_display != changed_prefs.gfx_apmode[APMODE_RTG].gfx_display ? (2|4|8) : 0;
  2197. c |= currprefs.gfx_blackerthanblack != changed_prefs.gfx_blackerthanblack ? (2 | 8) : 0;
  2198. c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers ? (2 | 16) : 0;
  2199. c |= currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced ? (2 | 8) : 0;
  2200. c |= currprefs.gfx_apmode[APMODE_RTG].gfx_backbuffers != changed_prefs.gfx_apmode[APMODE_RTG].gfx_backbuffers ? (2 | 16) : 0;
  2201. c |= currprefs.win32_main_alwaysontop != changed_prefs.win32_main_alwaysontop ? 32 : 0;
  2202. c |= currprefs.win32_gui_alwaysontop != changed_prefs.win32_gui_alwaysontop ? 2 : 0;
  2203. c |= currprefs.win32_notaskbarbutton != changed_prefs.win32_notaskbarbutton ? 32 : 0;
  2204. c |= currprefs.win32_nonotificationicon != changed_prefs.win32_nonotificationicon ? 32 : 0;
  2205. c |= currprefs.win32_borderless != changed_prefs.win32_borderless ? 32 : 0;
  2206. c |= currprefs.win32_blankmonitors != changed_prefs.win32_blankmonitors ? 32 : 0;
  2207. c |= currprefs.win32_rtgmatchdepth != changed_prefs.win32_rtgmatchdepth ? 2 : 0;
  2208. // c |= currprefs.win32_rtgscalemode != changed_prefs.win32_rtgscalemode ? (2 | 8 | 64) : 0;
  2209. c |= currprefs.win32_rtgallowscaling != changed_prefs.win32_rtgallowscaling ? (2 | 8 | 64) : 0;
  2210. c |= currprefs.win32_rtgscaleaspectratio != changed_prefs.win32_rtgscaleaspectratio ? (8 | 64) : 0;
  2211. c |= currprefs.win32_rtgvblankrate != changed_prefs.win32_rtgvblankrate ? 8 : 0;
  2212. if (display_change_requested || c)
  2213. {
  2214. bool setpause = false;
  2215. bool dontcapture = false;
  2216. int keepfsmode =
  2217. currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
  2218. currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen;
  2219. currprefs.gfx_autoresolution = changed_prefs.gfx_autoresolution;
  2220. currprefs.gfx_autoresolution_vga = changed_prefs.gfx_autoresolution_vga;
  2221. currprefs.color_mode = changed_prefs.color_mode;
  2222. currprefs.lightboost_strobo = changed_prefs.lightboost_strobo;
  2223. if (currprefs.gfx_api != changed_prefs.gfx_api) {
  2224. display_change_requested = 1;
  2225. }
  2226. if (c & 128) {
  2227. // hres/vres change
  2228. rp_screenmode_changed();
  2229. }
  2230. if (display_change_requested) {
  2231. if (display_change_requested == 3) {
  2232. c = 1024;
  2233. } else if (display_change_requested == 2) {
  2234. c = 512;
  2235. } else {
  2236. c = 2;
  2237. keepfsmode = 0;
  2238. if (display_change_requested <= -1) {
  2239. dontcapture = true;
  2240. if (display_change_requested == -2)
  2241. setpause = true;
  2242. if (pause_emulation)
  2243. setpause = true;
  2244. }
  2245. }
  2246. display_change_requested = 0;
  2247. }
  2248. for (int j = 0; j < 2; j++) {
  2249. struct gfx_filterdata *gf = &currprefs.gf[j];
  2250. struct gfx_filterdata *gfc = &changed_prefs.gf[j];
  2251. memcpy(gf, gfc, sizeof(struct gfx_filterdata));
  2252. }
  2253. currprefs.rtg_horiz_zoom_mult = changed_prefs.rtg_horiz_zoom_mult;
  2254. currprefs.rtg_vert_zoom_mult = changed_prefs.rtg_vert_zoom_mult;
  2255. currprefs.gfx_luminance = changed_prefs.gfx_luminance;
  2256. currprefs.gfx_contrast = changed_prefs.gfx_contrast;
  2257. currprefs.gfx_gamma = changed_prefs.gfx_gamma;
  2258. currprefs.gfx_resolution = changed_prefs.gfx_resolution;
  2259. currprefs.gfx_vresolution = changed_prefs.gfx_vresolution;
  2260. currprefs.gfx_autoresolution_minh = changed_prefs.gfx_autoresolution_minh;
  2261. currprefs.gfx_autoresolution_minv = changed_prefs.gfx_autoresolution_minv;
  2262. currprefs.gfx_iscanlines = changed_prefs.gfx_iscanlines;
  2263. currprefs.gfx_pscanlines = changed_prefs.gfx_pscanlines;
  2264. currprefs.monitoremu = changed_prefs.monitoremu;
  2265. currprefs.genlock_image = changed_prefs.genlock_image;
  2266. currprefs.genlock = changed_prefs.genlock;
  2267. currprefs.genlock_mix = changed_prefs.genlock_mix;
  2268. currprefs.genlock_alpha = changed_prefs.genlock_alpha;
  2269. currprefs.genlock_aspect = changed_prefs.genlock_aspect;
  2270. currprefs.genlock_scale = changed_prefs.genlock_scale;
  2271. _tcscpy(currprefs.genlock_image_file, changed_prefs.genlock_image_file);
  2272. _tcscpy(currprefs.genlock_video_file, changed_prefs.genlock_video_file);
  2273. currprefs.gfx_lores_mode = changed_prefs.gfx_lores_mode;
  2274. currprefs.gfx_overscanmode = changed_prefs.gfx_overscanmode;
  2275. currprefs.gfx_scandoubler = changed_prefs.gfx_scandoubler;
  2276. currprefs.gfx_threebitcolors = changed_prefs.gfx_threebitcolors;
  2277. currprefs.gfx_grayscale = changed_prefs.gfx_grayscale;
  2278. currprefs.gfx_display_sections = changed_prefs.gfx_display_sections;
  2279. currprefs.gfx_variable_sync = changed_prefs.gfx_variable_sync;
  2280. currprefs.gfx_windowed_resize = changed_prefs.gfx_windowed_resize;
  2281. currprefs.gfx_apmode[APMODE_NATIVE].gfx_display = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_display;
  2282. currprefs.gfx_apmode[APMODE_RTG].gfx_display = changed_prefs.gfx_apmode[APMODE_RTG].gfx_display;
  2283. currprefs.gfx_blackerthanblack = changed_prefs.gfx_blackerthanblack;
  2284. currprefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_backbuffers;
  2285. currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced;
  2286. currprefs.gfx_apmode[APMODE_RTG].gfx_backbuffers = changed_prefs.gfx_apmode[APMODE_RTG].gfx_backbuffers;
  2287. currprefs.win32_main_alwaysontop = changed_prefs.win32_main_alwaysontop;
  2288. currprefs.win32_gui_alwaysontop = changed_prefs.win32_gui_alwaysontop;
  2289. currprefs.win32_nonotificationicon = changed_prefs.win32_nonotificationicon;
  2290. currprefs.win32_notaskbarbutton = changed_prefs.win32_notaskbarbutton;
  2291. currprefs.win32_borderless = changed_prefs.win32_borderless;
  2292. currprefs.win32_blankmonitors = changed_prefs.win32_blankmonitors;
  2293. currprefs.win32_statusbar = changed_prefs.win32_statusbar;
  2294. currprefs.win32_rtgmatchdepth = changed_prefs.win32_rtgmatchdepth;
  2295. // currprefs.win32_rtgscalemode = changed_prefs.win32_rtgscalemode;
  2296. currprefs.win32_rtgallowscaling = changed_prefs.win32_rtgallowscaling;
  2297. currprefs.win32_rtgscaleaspectratio = changed_prefs.win32_rtgscaleaspectratio;
  2298. currprefs.win32_rtgvblankrate = changed_prefs.win32_rtgvblankrate;
  2299. bool unacquired = false;
  2300. for (int monid = MAX_AMIGAMONITORS - 1; monid >= 0; monid--) {
  2301. if (!monitors[monid])
  2302. continue;
  2303. struct AmigaMonitor *mon = &AMonitors[monid];
  2304. if (c & 64) {
  2305. if (!unacquired) {
  2306. inputdevice_unacquire();
  2307. unacquired = true;
  2308. }
  2309. DirectDraw_Fill(NULL, 0);
  2310. DirectDraw_BlitToPrimary(NULL);
  2311. }
  2312. if (c & 256) {
  2313. init_colors(mon->monitor_id);
  2314. reset_drawing();
  2315. }
  2316. if (c & 128) {
  2317. if (currprefs.gfx_autoresolution) {
  2318. c |= 2 | 8;
  2319. } else {
  2320. c |= 16;
  2321. reset_drawing();
  2322. S2X_reset(mon->monitor_id);
  2323. }
  2324. }
  2325. if (c & 1024) {
  2326. target_graphics_buffer_update(mon->monitor_id);
  2327. }
  2328. if (c & 512) {
  2329. reopen_gfx(mon);
  2330. }
  2331. if ((c & 16) || ((c & 8) && keepfsmode)) {
  2332. if (reopen(mon, c & 2, unacquired == false)) {
  2333. c |= 2;
  2334. } else {
  2335. unacquired = true;
  2336. }
  2337. }
  2338. if ((c & 32) || ((c & 2) && !keepfsmode)) {
  2339. if (!unacquired) {
  2340. inputdevice_unacquire();
  2341. unacquired = true;
  2342. }
  2343. close_windows(mon);
  2344. if (currprefs.gfx_api != changed_prefs.gfx_api || currprefs.gfx_api_options != changed_prefs.gfx_api_options) {
  2345. currprefs.gfx_api = changed_prefs.gfx_api;
  2346. currprefs.gfx_api_options = changed_prefs.gfx_api_options;
  2347. d3d_select(&currprefs);
  2348. }
  2349. graphics_init(dontcapture ? false : true);
  2350. }
  2351. }
  2352. init_custom();
  2353. if (c & 4) {
  2354. pause_sound();
  2355. reset_sound();
  2356. resume_sound();
  2357. }
  2358. if (setpause || dontcapture) {
  2359. if (!unacquired)
  2360. inputdevice_unacquire();
  2361. unacquired = false;
  2362. }
  2363. if (unacquired)
  2364. inputdevice_acquire(TRUE);
  2365. if (setpause)
  2366. setpaused(1);
  2367. return 1;
  2368. }
  2369. bool changed = false;
  2370. for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
  2371. if (currprefs.cr[i].rate != changed_prefs.cr[i].rate ||
  2372. currprefs.cr[i].locked != changed_prefs.cr[i].locked) {
  2373. memcpy (&currprefs.cr[i], &changed_prefs.cr[i], sizeof (struct chipset_refresh));
  2374. changed = true;
  2375. }
  2376. }
  2377. if (changed) {
  2378. init_hz_normal();
  2379. }
  2380. if (currprefs.chipset_refreshrate != changed_prefs.chipset_refreshrate) {
  2381. currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate;
  2382. init_hz_normal();
  2383. return 1;
  2384. }
  2385. if (currprefs.gf[0].gfx_filter_autoscale != changed_prefs.gf[0].gfx_filter_autoscale ||
  2386. currprefs.gfx_xcenter_pos != changed_prefs.gfx_xcenter_pos ||
  2387. currprefs.gfx_ycenter_pos != changed_prefs.gfx_ycenter_pos ||
  2388. currprefs.gfx_xcenter_size != changed_prefs.gfx_xcenter_size ||
  2389. currprefs.gfx_ycenter_size != changed_prefs.gfx_ycenter_size ||
  2390. currprefs.gfx_xcenter != changed_prefs.gfx_xcenter ||
  2391. currprefs.gfx_ycenter != changed_prefs.gfx_ycenter)
  2392. {
  2393. currprefs.gfx_xcenter_pos = changed_prefs.gfx_xcenter_pos;
  2394. currprefs.gfx_ycenter_pos = changed_prefs.gfx_ycenter_pos;
  2395. currprefs.gfx_xcenter_size = changed_prefs.gfx_xcenter_size;
  2396. currprefs.gfx_ycenter_size = changed_prefs.gfx_ycenter_size;
  2397. currprefs.gfx_xcenter = changed_prefs.gfx_xcenter;
  2398. currprefs.gfx_ycenter = changed_prefs.gfx_ycenter;
  2399. currprefs.gf[0].gfx_filter_autoscale = changed_prefs.gf[0].gfx_filter_autoscale;
  2400. get_custom_limits (NULL, NULL, NULL, NULL, NULL);
  2401. fixup_prefs_dimensions (&changed_prefs);
  2402. return 1;
  2403. }
  2404. currprefs.win32_norecyclebin = changed_prefs.win32_norecyclebin;
  2405. currprefs.filesys_limit = changed_prefs.filesys_limit;
  2406. currprefs.harddrive_read_only = changed_prefs.harddrive_read_only;
  2407. if (currprefs.win32_logfile != changed_prefs.win32_logfile) {
  2408. currprefs.win32_logfile = changed_prefs.win32_logfile;
  2409. if (currprefs.win32_logfile)
  2410. logging_open (0, 1);
  2411. else
  2412. logging_cleanup ();
  2413. }
  2414. if (currprefs.leds_on_screen != changed_prefs.leds_on_screen ||
  2415. currprefs.keyboard_leds[0] != changed_prefs.keyboard_leds[0] ||
  2416. currprefs.keyboard_leds[1] != changed_prefs.keyboard_leds[1] ||
  2417. currprefs.keyboard_leds[2] != changed_prefs.keyboard_leds[2] ||
  2418. currprefs.input_mouse_untrap != changed_prefs.input_mouse_untrap ||
  2419. currprefs.win32_minimize_inactive != changed_prefs.win32_minimize_inactive ||
  2420. currprefs.win32_active_capture_priority != changed_prefs.win32_active_capture_priority ||
  2421. currprefs.win32_inactive_priority != changed_prefs.win32_inactive_priority ||
  2422. currprefs.win32_iconified_priority != changed_prefs.win32_iconified_priority ||
  2423. currprefs.win32_active_nocapture_nosound != changed_prefs.win32_active_nocapture_nosound ||
  2424. currprefs.win32_active_nocapture_pause != changed_prefs.win32_active_nocapture_pause ||
  2425. currprefs.win32_inactive_nosound != changed_prefs.win32_inactive_nosound ||
  2426. currprefs.win32_inactive_pause != changed_prefs.win32_inactive_pause ||
  2427. currprefs.win32_inactive_input != changed_prefs.win32_inactive_input ||
  2428. currprefs.win32_iconified_nosound != changed_prefs.win32_iconified_nosound ||
  2429. currprefs.win32_iconified_pause != changed_prefs.win32_iconified_pause ||
  2430. currprefs.win32_iconified_input != changed_prefs.win32_iconified_input ||
  2431. currprefs.win32_ctrl_F11_is_quit != changed_prefs.win32_ctrl_F11_is_quit ||
  2432. currprefs.win32_shutdown_notification != changed_prefs.win32_shutdown_notification ||
  2433. currprefs.win32_warn_exit != changed_prefs.win32_warn_exit ||
  2434. currprefs.right_control_is_right_win_key != changed_prefs.right_control_is_right_win_key)
  2435. {
  2436. currprefs.win32_minimize_inactive = changed_prefs.win32_minimize_inactive;
  2437. currprefs.leds_on_screen = changed_prefs.leds_on_screen;
  2438. currprefs.keyboard_leds[0] = changed_prefs.keyboard_leds[0];
  2439. currprefs.keyboard_leds[1] = changed_prefs.keyboard_leds[1];
  2440. currprefs.keyboard_leds[2] = changed_prefs.keyboard_leds[2];
  2441. currprefs.input_mouse_untrap = changed_prefs.input_mouse_untrap;
  2442. currprefs.win32_active_capture_priority = changed_prefs.win32_active_capture_priority;
  2443. currprefs.win32_inactive_priority = changed_prefs.win32_inactive_priority;
  2444. currprefs.win32_iconified_priority = changed_prefs.win32_iconified_priority;
  2445. currprefs.win32_active_nocapture_nosound = changed_prefs.win32_active_nocapture_nosound;
  2446. currprefs.win32_active_nocapture_pause = changed_prefs.win32_active_nocapture_pause;
  2447. currprefs.win32_inactive_nosound = changed_prefs.win32_inactive_nosound;
  2448. currprefs.win32_inactive_pause = changed_prefs.win32_inactive_pause;
  2449. currprefs.win32_inactive_input = changed_prefs.win32_inactive_input;
  2450. currprefs.win32_iconified_nosound = changed_prefs.win32_iconified_nosound;
  2451. currprefs.win32_iconified_pause = changed_prefs.win32_iconified_pause;
  2452. currprefs.win32_iconified_input = changed_prefs.win32_iconified_input;
  2453. currprefs.win32_ctrl_F11_is_quit = changed_prefs.win32_ctrl_F11_is_quit;
  2454. currprefs.win32_shutdown_notification = changed_prefs.win32_shutdown_notification;
  2455. currprefs.win32_warn_exit = changed_prefs.win32_warn_exit;
  2456. currprefs.right_control_is_right_win_key = changed_prefs.right_control_is_right_win_key;
  2457. inputdevice_unacquire ();
  2458. currprefs.keyboard_leds_in_use = changed_prefs.keyboard_leds_in_use = (currprefs.keyboard_leds[0] | currprefs.keyboard_leds[1] | currprefs.keyboard_leds[2]) != 0;
  2459. pause_sound ();
  2460. resume_sound ();
  2461. refreshtitle();
  2462. inputdevice_acquire (TRUE);
  2463. #ifndef _DEBUG
  2464. setpriority (&priorities[currprefs.win32_active_capture_priority]);
  2465. #endif
  2466. return 1;
  2467. }
  2468. if (currprefs.win32_samplersoundcard != changed_prefs.win32_samplersoundcard ||
  2469. currprefs.sampler_stereo != changed_prefs.sampler_stereo) {
  2470. currprefs.win32_samplersoundcard = changed_prefs.win32_samplersoundcard;
  2471. currprefs.sampler_stereo = changed_prefs.sampler_stereo;
  2472. sampler_free ();
  2473. }
  2474. if (_tcscmp (currprefs.prtname, changed_prefs.prtname) ||
  2475. currprefs.parallel_autoflush_time != changed_prefs.parallel_autoflush_time ||
  2476. currprefs.parallel_matrix_emulation != changed_prefs.parallel_matrix_emulation ||
  2477. currprefs.parallel_postscript_emulation != changed_prefs.parallel_postscript_emulation ||
  2478. currprefs.parallel_postscript_detection != changed_prefs.parallel_postscript_detection ||
  2479. _tcscmp (currprefs.ghostscript_parameters, changed_prefs.ghostscript_parameters)) {
  2480. _tcscpy (currprefs.prtname, changed_prefs.prtname);
  2481. currprefs.parallel_autoflush_time = changed_prefs.parallel_autoflush_time;
  2482. currprefs.parallel_matrix_emulation = changed_prefs.parallel_matrix_emulation;
  2483. currprefs.parallel_postscript_emulation = changed_prefs.parallel_postscript_emulation;
  2484. currprefs.parallel_postscript_detection = changed_prefs.parallel_postscript_detection;
  2485. _tcscpy (currprefs.ghostscript_parameters, changed_prefs.ghostscript_parameters);
  2486. #ifdef PARALLEL_PORT
  2487. closeprinter ();
  2488. #endif
  2489. }
  2490. if (_tcscmp (currprefs.sername, changed_prefs.sername) ||
  2491. currprefs.serial_hwctsrts != changed_prefs.serial_hwctsrts ||
  2492. currprefs.serial_direct != changed_prefs.serial_direct ||
  2493. currprefs.serial_demand != changed_prefs.serial_demand) {
  2494. _tcscpy (currprefs.sername, changed_prefs.sername);
  2495. currprefs.serial_hwctsrts = changed_prefs.serial_hwctsrts;
  2496. currprefs.serial_demand = changed_prefs.serial_demand;
  2497. currprefs.serial_direct = changed_prefs.serial_direct;
  2498. #ifdef SERIAL_PORT
  2499. serial_exit ();
  2500. serial_init ();
  2501. #endif
  2502. }
  2503. if (currprefs.win32_midiindev != changed_prefs.win32_midiindev ||
  2504. currprefs.win32_midioutdev != changed_prefs.win32_midioutdev ||
  2505. currprefs.sound_volume_midi != changed_prefs.sound_volume_midi ||
  2506. currprefs.win32_midirouter != changed_prefs.win32_midirouter)
  2507. {
  2508. currprefs.win32_midiindev = changed_prefs.win32_midiindev;
  2509. currprefs.win32_midioutdev = changed_prefs.win32_midioutdev;
  2510. currprefs.sound_volume_midi = changed_prefs.sound_volume_midi;
  2511. currprefs.win32_midirouter = changed_prefs.win32_midirouter;
  2512. #ifdef SERIAL_PORT
  2513. if (midi_ready) {
  2514. Midi_Close ();
  2515. Midi_Open ();
  2516. }
  2517. #endif
  2518. }
  2519. if (currprefs.win32_powersavedisabled != changed_prefs.win32_powersavedisabled) {
  2520. currprefs.win32_powersavedisabled = changed_prefs.win32_powersavedisabled;
  2521. }
  2522. return 0;
  2523. }
  2524. /* Color management */
  2525. static xcolnr xcol8[4096];
  2526. static int red_bits, green_bits, blue_bits, alpha_bits;
  2527. static int red_shift, green_shift, blue_shift, alpha_shift;
  2528. static int alpha;
  2529. void init_colors(int monid)
  2530. {
  2531. struct AmigaMonitor *mon = &AMonitors[monid];
  2532. /* init colors */
  2533. if (mon->currentmode.flags & DM_D3D) {
  2534. D3D_getpixelformat (mon->currentmode.current_depth,
  2535. &red_bits, &green_bits, &blue_bits, &red_shift, &green_shift, &blue_shift, &alpha_bits, &alpha_shift, &alpha);
  2536. } else {
  2537. red_bits = bits_in_mask (DirectDraw_GetPixelFormatBitMask (red_mask));
  2538. green_bits = bits_in_mask (DirectDraw_GetPixelFormatBitMask (green_mask));
  2539. blue_bits = bits_in_mask (DirectDraw_GetPixelFormatBitMask (blue_mask));
  2540. red_shift = mask_shift (DirectDraw_GetPixelFormatBitMask (red_mask));
  2541. green_shift = mask_shift (DirectDraw_GetPixelFormatBitMask (green_mask));
  2542. blue_shift = mask_shift (DirectDraw_GetPixelFormatBitMask (blue_mask));
  2543. alpha_bits = 0;
  2544. alpha_shift = 0;
  2545. }
  2546. if (!(mon->currentmode.flags & (DM_D3D))) {
  2547. if (mon->currentmode.current_depth != mon->currentmode.native_depth) {
  2548. if (mon->currentmode.current_depth == 16) {
  2549. red_bits = 5; green_bits = 6; blue_bits = 5;
  2550. red_shift = 11; green_shift = 5; blue_shift = 0;
  2551. } else {
  2552. red_bits = green_bits = blue_bits = 8;
  2553. red_shift = 16; green_shift = 8; blue_shift = 0;
  2554. }
  2555. }
  2556. }
  2557. alloc_colors64k(monid, red_bits, green_bits, blue_bits, red_shift,green_shift, blue_shift, alpha_bits, alpha_shift, alpha, 0, mon->usedfilter && mon->usedfilter->yuv);
  2558. notice_new_xcolors ();
  2559. #ifdef GFXFILTER
  2560. S2X_configure(monid, red_bits, green_bits, blue_bits, red_shift,green_shift, blue_shift);
  2561. #endif
  2562. #ifdef AVIOUTPUT
  2563. AVIOutput_RGBinfo (red_bits, green_bits, blue_bits, alpha_bits, red_shift, green_shift, blue_shift, alpha_shift);
  2564. #endif
  2565. Screenshot_RGBinfo (red_bits, green_bits, blue_bits, alpha_bits, red_shift, green_shift, blue_shift, alpha_shift);
  2566. }
  2567. #ifdef PICASSO96
  2568. int picasso_palette(struct MyCLUTEntry *CLUT, uae_u32 *clut)
  2569. {
  2570. int changed = 0;
  2571. for (int i = 0; i < 256 * 2; i++) {
  2572. int r = CLUT[i].Red;
  2573. int g = CLUT[i].Green;
  2574. int b = CLUT[i].Blue;
  2575. uae_u32 v = (doMask256 (r, red_bits, red_shift)
  2576. | doMask256 (g, green_bits, green_shift)
  2577. | doMask256 (b, blue_bits, blue_shift))
  2578. | doMask256 ((1 << alpha_bits) - 1, alpha_bits, alpha_shift);
  2579. if (v != clut[i]) {
  2580. //write_log (_T("%d:%08x\n"), i, v);
  2581. clut[i] = v;
  2582. changed = 1;
  2583. }
  2584. }
  2585. return changed;
  2586. }
  2587. void DX_Invalidate(struct AmigaMonitor *mon, int x, int y, int width, int height)
  2588. {
  2589. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[mon->monitor_id];
  2590. int last, lastx;
  2591. if (width == 0 || height == 0)
  2592. return;
  2593. if (y < 0 || height < 0) {
  2594. y = 0;
  2595. height = vidinfo->height;
  2596. }
  2597. if (x < 0 || width < 0) {
  2598. x = 0;
  2599. width = vidinfo->width;
  2600. }
  2601. last = y + height - 1;
  2602. lastx = x + width - 1;
  2603. mon->p96_double_buffer_first = y;
  2604. mon->p96_double_buffer_last = last;
  2605. mon->p96_double_buffer_firstx = x;
  2606. mon->p96_double_buffer_lastx = lastx;
  2607. mon->p96_double_buffer_needs_flushing = 1;
  2608. }
  2609. #endif
  2610. static void open_screen(struct AmigaMonitor *mon)
  2611. {
  2612. close_windows(mon);
  2613. open_windows(mon, true, true);
  2614. }
  2615. static int ifs(struct AmigaMonitor *mon, struct uae_prefs *p)
  2616. {
  2617. int idx = mon->screen_is_picasso ? 1 : 0;
  2618. return p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLSCREEN ? 1 : (p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLWINDOW ? -1 : 0);
  2619. }
  2620. static int reopen(struct AmigaMonitor *mon, int full, bool unacquire)
  2621. {
  2622. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  2623. int quick = 0;
  2624. int idx = mon->screen_is_picasso ? 1 : 0;
  2625. struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
  2626. updatewinfsmode(mon->monitor_id, &changed_prefs);
  2627. if (changed_prefs.gfx_apmode[0].gfx_fullscreen != currprefs.gfx_apmode[0].gfx_fullscreen && !mon->screen_is_picasso)
  2628. full = 1;
  2629. if (changed_prefs.gfx_apmode[1].gfx_fullscreen != currprefs.gfx_apmode[1].gfx_fullscreen && mon->screen_is_picasso)
  2630. full = 1;
  2631. /* fullscreen to fullscreen? */
  2632. if (isfullscreen () > 0 && currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
  2633. currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen && currprefs.gfx_apmode[0].gfx_fullscreen == GFX_FULLSCREEN) {
  2634. quick = 1;
  2635. }
  2636. /* windowed to windowed */
  2637. if (isfullscreen () <= 0 && currprefs.gfx_apmode[0].gfx_fullscreen == changed_prefs.gfx_apmode[0].gfx_fullscreen &&
  2638. currprefs.gfx_apmode[1].gfx_fullscreen == changed_prefs.gfx_apmode[1].gfx_fullscreen) {
  2639. quick = 1;
  2640. }
  2641. currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.width;
  2642. currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height;
  2643. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.width = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.width;
  2644. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.height = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.height;
  2645. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.x = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.x;
  2646. currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.y = changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_win.y;
  2647. currprefs.gfx_apmode[0].gfx_fullscreen = changed_prefs.gfx_apmode[0].gfx_fullscreen;
  2648. currprefs.gfx_apmode[1].gfx_fullscreen = changed_prefs.gfx_apmode[1].gfx_fullscreen;
  2649. currprefs.gfx_apmode[0].gfx_vsync = changed_prefs.gfx_apmode[0].gfx_vsync;
  2650. currprefs.gfx_apmode[1].gfx_vsync = changed_prefs.gfx_apmode[1].gfx_vsync;
  2651. currprefs.gfx_apmode[0].gfx_vsyncmode = changed_prefs.gfx_apmode[0].gfx_vsyncmode;
  2652. currprefs.gfx_apmode[1].gfx_vsyncmode = changed_prefs.gfx_apmode[1].gfx_vsyncmode;
  2653. currprefs.gfx_apmode[0].gfx_refreshrate = changed_prefs.gfx_apmode[0].gfx_refreshrate;
  2654. currprefs.rtg_horiz_zoom_mult = changed_prefs.rtg_horiz_zoom_mult;
  2655. currprefs.rtg_vert_zoom_mult = changed_prefs.rtg_vert_zoom_mult;
  2656. #if 0
  2657. currprefs.gfx_apmode[1].gfx_refreshrate = changed_prefs.gfx_apmode[1].gfx_refreshrate;
  2658. #endif
  2659. set_config_changed ();
  2660. if (!quick)
  2661. return 1;
  2662. if (unacquire) {
  2663. inputdevice_unacquire ();
  2664. }
  2665. reopen_gfx(mon);
  2666. return 0;
  2667. }
  2668. bool vsync_switchmode(int monid, int hz)
  2669. {
  2670. struct AmigaMonitor *mon = &AMonitors[monid];
  2671. static struct PicassoResolution *oldmode;
  2672. static int oldhz;
  2673. int w = mon->currentmode.native_width;
  2674. int h = mon->currentmode.native_height;
  2675. int d = mon->currentmode.native_depth / 8;
  2676. struct MultiDisplay *md = getdisplay(&currprefs, monid);
  2677. struct PicassoResolution *found;
  2678. int newh, i, cnt;
  2679. bool preferdouble = 0, preferlace = 0;
  2680. bool lace = false;
  2681. if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate > 85) {
  2682. preferdouble = 1;
  2683. } else if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced) {
  2684. preferlace = 1;
  2685. }
  2686. if (hz >= 55)
  2687. hz = 60;
  2688. else
  2689. hz = 50;
  2690. newh = h * (currprefs.ntscmode ? 60 : 50) / hz;
  2691. found = NULL;
  2692. for (cnt = 0; cnt <= abs (newh - h) + 1 && !found; cnt++) {
  2693. for (int dbl = 0; dbl < 2 && !found; dbl++) {
  2694. bool doublecheck = false;
  2695. bool lacecheck = false;
  2696. if (preferdouble && dbl == 0)
  2697. doublecheck = true;
  2698. else if (preferlace && dbl == 0)
  2699. lacecheck = true;
  2700. for (int extra = 1; extra >= -1 && !found; extra--) {
  2701. for (i = 0; md->DisplayModes[i].depth >= 0 && !found; i++) {
  2702. struct PicassoResolution *r = &md->DisplayModes[i];
  2703. if (r->res.width == w && (r->res.height == newh + cnt || r->res.height == newh - cnt) && r->depth == d) {
  2704. int j;
  2705. for (j = 0; r->refresh[j] > 0; j++) {
  2706. if (doublecheck) {
  2707. if (r->refreshtype[j] & REFRESH_RATE_LACE)
  2708. continue;
  2709. if (r->refresh[j] == hz * 2 + extra) {
  2710. found = r;
  2711. hz = r->refresh[j];
  2712. break;
  2713. }
  2714. } else if (lacecheck) {
  2715. if (!(r->refreshtype[j] & REFRESH_RATE_LACE))
  2716. continue;
  2717. if (r->refresh[j] * 2 == hz + extra) {
  2718. found = r;
  2719. lace = true;
  2720. hz = r->refresh[j];
  2721. break;
  2722. }
  2723. } else {
  2724. if (r->refresh[j] == hz + extra) {
  2725. found = r;
  2726. hz = r->refresh[j];
  2727. break;
  2728. }
  2729. }
  2730. }
  2731. }
  2732. }
  2733. }
  2734. }
  2735. }
  2736. if (found == oldmode && hz == oldhz)
  2737. return true;
  2738. oldmode = found;
  2739. oldhz = hz;
  2740. if (!found) {
  2741. changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_vsync = 0;
  2742. if (currprefs.gfx_apmode[APMODE_NATIVE].gfx_vsync != changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_vsync) {
  2743. set_config_changed ();
  2744. }
  2745. write_log (_T("refresh rate changed to %d%s but no matching screenmode found, vsync disabled\n"), hz, lace ? _T("i") : _T("p"));
  2746. return false;
  2747. } else {
  2748. newh = found->res.height;
  2749. changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height = newh;
  2750. changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate = hz;
  2751. changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_interlaced = lace;
  2752. if (changed_prefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height != currprefs.gfx_monitor[mon->monitor_id].gfx_size_fs.height ||
  2753. changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate != currprefs.gfx_apmode[APMODE_NATIVE].gfx_refreshrate) {
  2754. write_log (_T("refresh rate changed to %d%s, new screenmode %dx%d\n"), hz, lace ? _T("i") : _T("p"), w, newh);
  2755. set_config_changed ();
  2756. }
  2757. return true;
  2758. }
  2759. }
  2760. void vsync_clear(void)
  2761. {
  2762. vsync_active = false;
  2763. if (waitvblankevent)
  2764. ResetEvent(waitvblankevent);
  2765. }
  2766. int vsync_isdone(frame_time_t *dt)
  2767. {
  2768. if (isvsync() == 0)
  2769. return -1;
  2770. if (waitvblankthread_mode <= 0)
  2771. return -2;
  2772. if (dt)
  2773. *dt = wait_vblank_timestamp;
  2774. return vsync_active ? 1 : 0;
  2775. }
  2776. #ifdef PICASSO96
  2777. static int modeswitchneeded(struct AmigaMonitor *mon, struct winuae_currentmode *wc)
  2778. {
  2779. struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
  2780. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  2781. if (isfullscreen () > 0) {
  2782. /* fullscreen to fullscreen */
  2783. if (mon->screen_is_picasso) {
  2784. if (state->BytesPerPixel > 1 && state->BytesPerPixel * 8 != wc->current_depth && canmatchdepth())
  2785. return -1;
  2786. if (state->Width < wc->current_width && state->Height < wc->current_height) {
  2787. if ((currprefs.gf[1].gfx_filter_autoscale == 1 || (currprefs.gf[1].gfx_filter_autoscale == 2 && currprefs.win32_rtgallowscaling)) && !canmatchdepth())
  2788. return 0;
  2789. }
  2790. if (state->Width != wc->current_width ||
  2791. state->Height != wc->current_height)
  2792. return 1;
  2793. if (state->Width == wc->current_width &&
  2794. state->Height == wc->current_height) {
  2795. if (state->BytesPerPixel * 8 == wc->current_depth || state->BytesPerPixel == 1)
  2796. return 0;
  2797. if (!canmatchdepth())
  2798. return 0;
  2799. }
  2800. return 1;
  2801. } else {
  2802. if (mon->currentmode.current_width != wc->current_width ||
  2803. mon->currentmode.current_height != wc->current_height ||
  2804. mon->currentmode.current_depth != wc->current_depth)
  2805. return -1;
  2806. if (!avidinfo->outbuffer->bufmem_lockable)
  2807. return -1;
  2808. }
  2809. } else if (isfullscreen () == 0) {
  2810. /* windowed to windowed */
  2811. return -1;
  2812. } else {
  2813. /* fullwindow to fullwindow */
  2814. DirectDraw_Fill (NULL, 0);
  2815. DirectDraw_BlitToPrimary (NULL);
  2816. if (mon->screen_is_picasso) {
  2817. if (currprefs.gf[1].gfx_filter_autoscale && ((wc->native_width > state->Width && wc->native_height >= state->Height) || (wc->native_height > state->Height && wc->native_width >= state->Width)))
  2818. return -1;
  2819. if (currprefs.win32_rtgallowscaling && (state->Width != wc->native_width || state->Height != wc->native_height))
  2820. return -1;
  2821. #if 0
  2822. if (wc->native_width < state->Width || wc->native_height < state->Height)
  2823. return 1;
  2824. #endif
  2825. }
  2826. return -1;
  2827. }
  2828. return 0;
  2829. }
  2830. void gfx_set_picasso_state(int monid, int on)
  2831. {
  2832. struct AmigaMonitor *mon = &AMonitors[monid];
  2833. struct winuae_currentmode wc;
  2834. struct apmode *newmode, *oldmode;
  2835. struct gfx_filterdata *newf, *oldf;
  2836. int mode;
  2837. if (mon->screen_is_picasso == on)
  2838. return;
  2839. mon->screen_is_picasso = on;
  2840. rp_rtg_switch ();
  2841. memcpy (&wc, &mon->currentmode, sizeof (wc));
  2842. newmode = &currprefs.gfx_apmode[on ? 1 : 0];
  2843. oldmode = &currprefs.gfx_apmode[on ? 0 : 1];
  2844. newf = &currprefs.gf[on ? 1 : 0];
  2845. oldf = &currprefs.gf[on ? 0 : 1];
  2846. updatemodes(mon);
  2847. update_gfxparams(mon);
  2848. clearscreen();
  2849. // if filter changes, need to reset
  2850. mode = 0;
  2851. if (newf->gfx_filter != oldf->gfx_filter)
  2852. mode = -1;
  2853. for (int i = 0; i <= 2 * MAX_FILTERSHADERS; i++) {
  2854. if (_tcscmp(newf->gfx_filtershader[i], oldf->gfx_filtershader[i]))
  2855. mode = -1;
  2856. if (_tcscmp(newf->gfx_filtermask[i], oldf->gfx_filtermask[i]))
  2857. mode = -1;
  2858. }
  2859. // if screen parameter changes, need to reopen window
  2860. if (newmode->gfx_fullscreen != oldmode->gfx_fullscreen ||
  2861. (newmode->gfx_fullscreen && (
  2862. newmode->gfx_backbuffers != oldmode->gfx_backbuffers ||
  2863. newmode->gfx_display != oldmode->gfx_display ||
  2864. newmode->gfx_refreshrate != oldmode->gfx_refreshrate ||
  2865. newmode->gfx_strobo != oldmode->gfx_strobo ||
  2866. newmode->gfx_vflip != oldmode->gfx_vflip ||
  2867. newmode->gfx_vsync != oldmode->gfx_vsync))) {
  2868. mode = 1;
  2869. }
  2870. if (mode <= 0) {
  2871. int m = modeswitchneeded(mon, &wc);
  2872. if (m > 0)
  2873. mode = m;
  2874. if (m < 0 && !mode)
  2875. mode = m;
  2876. if (!mode)
  2877. goto end;
  2878. }
  2879. if (mode < 0) {
  2880. open_windows(mon, true, true);
  2881. } else {
  2882. open_screen(mon); // reopen everything
  2883. }
  2884. end:
  2885. #ifdef RETROPLATFORM
  2886. rp_set_hwnd (mon->hAmigaWnd);
  2887. #endif
  2888. }
  2889. static void updatepicasso96(struct AmigaMonitor *mon)
  2890. {
  2891. #ifdef PICASSO96
  2892. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[mon->monitor_id];
  2893. vidinfo->rowbytes = 0;
  2894. vidinfo->pixbytes = mon->currentmode.current_depth / 8;
  2895. vidinfo->rgbformat = 0;
  2896. vidinfo->extra_mem = 1;
  2897. vidinfo->height = mon->currentmode.current_height;
  2898. vidinfo->width = mon->currentmode.current_width;
  2899. vidinfo->depth = mon->currentmode.current_depth;
  2900. vidinfo->offset = 0;
  2901. vidinfo->splitypos = -1;
  2902. #endif
  2903. }
  2904. void gfx_set_picasso_modeinfo(int monid, RGBFTYPE rgbfmt)
  2905. {
  2906. struct AmigaMonitor *mon = &AMonitors[monid];
  2907. int need;
  2908. if (!mon->screen_is_picasso)
  2909. return;
  2910. clearscreen();
  2911. gfx_set_picasso_colors(monid, rgbfmt);
  2912. updatemodes(mon);
  2913. need = modeswitchneeded(mon, &mon->currentmode);
  2914. update_gfxparams(mon);
  2915. if (need > 0) {
  2916. open_screen(mon);
  2917. } else if (need < 0) {
  2918. struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
  2919. struct winuae_currentmode *wc = &mon->currentmode;
  2920. if (state->Width != wc->native_width || state->Width != wc->current_width ||
  2921. state->Height != wc->native_height || state->Height != wc->current_height) {
  2922. open_windows(mon, true, true);
  2923. }
  2924. }
  2925. #ifdef RETROPLATFORM
  2926. rp_set_hwnd(mon->hAmigaWnd);
  2927. #endif
  2928. }
  2929. #endif
  2930. void gfx_set_picasso_colors(int monid, RGBFTYPE rgbfmt)
  2931. {
  2932. alloc_colors_picasso(red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift, rgbfmt, p96_rgbx16);
  2933. }
  2934. static void gfxmode_reset(int monid)
  2935. {
  2936. struct amigadisplay *ad = &adisplays[monid];
  2937. struct uae_filter **usedfilter = &AMonitors[monid].usedfilter;
  2938. #ifdef GFXFILTER
  2939. *usedfilter = NULL;
  2940. if (currprefs.gf[ad->picasso_on].gfx_filter > 0) {
  2941. int i = 0;
  2942. while (uaefilters[i].name) {
  2943. if (uaefilters[i].type == currprefs.gf[ad->picasso_on].gfx_filter) {
  2944. *usedfilter = &uaefilters[i];
  2945. break;
  2946. }
  2947. i++;
  2948. }
  2949. }
  2950. #endif
  2951. }
  2952. int machdep_init(void)
  2953. {
  2954. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  2955. struct AmigaMonitor *mon = &AMonitors[i];
  2956. struct amigadisplay *ad = &adisplays[i];
  2957. mon->monitor_id = i;
  2958. ad->picasso_requested_on = 0;
  2959. ad->picasso_on = 0;
  2960. mon->screen_is_picasso = 0;
  2961. memset(&mon->currentmode, 0, sizeof(*&mon->currentmode));
  2962. }
  2963. #ifdef LOGITECHLCD
  2964. lcd_open ();
  2965. #endif
  2966. systray (hHiddenWnd, FALSE);
  2967. return 1;
  2968. }
  2969. void machdep_free(void)
  2970. {
  2971. #ifdef LOGITECHLCD
  2972. lcd_close ();
  2973. #endif
  2974. }
  2975. int graphics_init(bool mousecapture)
  2976. {
  2977. systray (hHiddenWnd, TRUE);
  2978. systray (hHiddenWnd, FALSE);
  2979. d3d_select(&currprefs);
  2980. gfxmode_reset(0);
  2981. if (open_windows(&AMonitors[0], mousecapture, false)) {
  2982. if (currprefs.monitoremu_mon > 0 && currprefs.monitoremu) {
  2983. gfxmode_reset(currprefs.monitoremu_mon);
  2984. open_windows(&AMonitors[currprefs.monitoremu_mon], mousecapture, false);
  2985. }
  2986. return true;
  2987. }
  2988. return false;
  2989. }
  2990. int graphics_setup(void)
  2991. {
  2992. if (!screen_cs_allocated) {
  2993. InitializeCriticalSection(&screen_cs);
  2994. screen_cs_allocated = true;
  2995. }
  2996. #ifdef PICASSO96
  2997. InitPicasso96(0);
  2998. #endif
  2999. return 1;
  3000. }
  3001. void graphics_leave(void)
  3002. {
  3003. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  3004. close_windows(&AMonitors[i]);
  3005. }
  3006. }
  3007. uae_u32 OSDEP_minimize_uae (void)
  3008. {
  3009. struct AmigaMonitor *mon = &AMonitors[0];
  3010. return ShowWindow(mon->hAmigaWnd, SW_MINIMIZE);
  3011. }
  3012. typedef HRESULT (CALLBACK* DWMENABLEMMCSS)(BOOL);
  3013. static void setDwmEnableMMCSS (bool state)
  3014. {
  3015. if (!os_vista)
  3016. return;
  3017. HMODULE hm = GetModuleHandle(_T("dwmapi.dll"));
  3018. if (hm) {
  3019. DWMENABLEMMCSS pDwmEnableMMCSS;
  3020. pDwmEnableMMCSS = (DWMENABLEMMCSS)GetProcAddress(hm, "DwmEnableMMCSS");
  3021. if (pDwmEnableMMCSS)
  3022. pDwmEnableMMCSS(state);
  3023. }
  3024. }
  3025. void close_windows(struct AmigaMonitor *mon)
  3026. {
  3027. struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
  3028. setDwmEnableMMCSS (FALSE);
  3029. reset_sound ();
  3030. #if defined (GFXFILTER)
  3031. S2X_free(mon->monitor_id);
  3032. #endif
  3033. freevidbuffer(mon->monitor_id, &avidinfo->drawbuffer);
  3034. freevidbuffer(mon->monitor_id, &avidinfo->tempbuffer);
  3035. DirectDraw_Release();
  3036. close_hwnds(mon);
  3037. }
  3038. static void createstatuswindow(struct AmigaMonitor *mon)
  3039. {
  3040. RECT rc;
  3041. HLOCAL hloc;
  3042. LPINT lpParts;
  3043. int drive_width, hd_width, cd_width, power_width;
  3044. int fps_width, idle_width, snd_width, joy_width, net_width;
  3045. int joys = currprefs.win32_statusbar > 1 ? 2 : 0;
  3046. int num_parts = 12 + joys + 1;
  3047. float scale = 1.0;
  3048. WINDOWINFO wi;
  3049. int extra;
  3050. if (mon->hStatusWnd) {
  3051. ShowWindow(mon->hStatusWnd, SW_HIDE);
  3052. DestroyWindow(mon->hStatusWnd);
  3053. }
  3054. if (currprefs.win32_statusbar == 0 || mon->monitor_id > 0)
  3055. return;
  3056. if (isfullscreen () != 0)
  3057. return;
  3058. if (currprefs.win32_borderless)
  3059. return;
  3060. mon->hStatusWnd = CreateWindowEx (
  3061. WS_EX_COMPOSITED, STATUSCLASSNAME, (LPCTSTR) NULL, SBARS_TOOLTIPS | WS_CHILD | WS_VISIBLE,
  3062. 0, 0, 0, 0, mon->hMainWnd, (HMENU) 1, hInst, NULL);
  3063. if (!mon->hStatusWnd)
  3064. return;
  3065. wi.cbSize = sizeof wi;
  3066. GetWindowInfo(mon->hMainWnd, &wi);
  3067. extra = wi.rcClient.top - wi.rcWindow.top;
  3068. scale = getdpiforwindow(mon->hStatusWnd) / 96.0;
  3069. drive_width = (int)(24 * scale);
  3070. hd_width = (int)(24 * scale);
  3071. cd_width = (int)(24 * scale);
  3072. power_width = (int)(42 * scale);
  3073. fps_width = (int)(64 * scale);
  3074. idle_width = (int)(64 * scale);
  3075. net_width = (int)(24 * scale);
  3076. if (is_ppc_cpu(&currprefs))
  3077. idle_width += (int)(68 * scale);
  3078. if (is_x86_cpu(&currprefs))
  3079. idle_width += (int)(68 * scale);
  3080. snd_width = (int)(72 * scale);
  3081. joy_width = (int)(24 * scale);
  3082. GetClientRect(mon->hMainWnd, &rc);
  3083. /* Allocate an array for holding the right edge coordinates. */
  3084. hloc = LocalAlloc (LHND, sizeof (int) * (num_parts + 1));
  3085. if (hloc) {
  3086. lpParts = (LPINT)LocalLock(hloc);
  3087. if (lpParts) {
  3088. int i = 0, i1;
  3089. // left side, msg area
  3090. lpParts[i] = rc.left + 2;
  3091. i++;
  3092. window_led_msg_start = i;
  3093. /* Calculate the right edge coordinate for each part, and copy the coords to the array. */
  3094. int startx = rc.right - (drive_width * 4) - power_width - idle_width - fps_width - cd_width - hd_width - snd_width - net_width - joys * joy_width - extra;
  3095. for (int j = 0; j < joys; j++) {
  3096. lpParts[i] = startx;
  3097. i++;
  3098. startx += joy_width;
  3099. }
  3100. window_led_joy_start = i;
  3101. if (lpParts[0] >= startx)
  3102. lpParts[0] = startx - 1;
  3103. // snd
  3104. lpParts[i] = startx;
  3105. i++;
  3106. // cpu
  3107. lpParts[i] = lpParts[i - 1] + snd_width;
  3108. i++;
  3109. // fps
  3110. lpParts[i] = lpParts[i - 1] + idle_width;
  3111. i++;
  3112. // power
  3113. lpParts[i] = lpParts[i - 1] + fps_width;
  3114. i++;
  3115. i1 = i;
  3116. // hd
  3117. lpParts[i] = lpParts[i - 1] + power_width;
  3118. i++;
  3119. // cd
  3120. lpParts[i] = lpParts[i - 1] + hd_width;
  3121. i++;
  3122. // net
  3123. lpParts[i] = lpParts[i - 1] + cd_width;
  3124. i++;
  3125. // df0
  3126. lpParts[i] = lpParts[i - 1] + net_width;
  3127. i++;
  3128. // df1
  3129. lpParts[i] = lpParts[i - 1] + drive_width;
  3130. i++;
  3131. // df2
  3132. lpParts[i] = lpParts[i - 1] + drive_width;
  3133. i++;
  3134. // df3
  3135. lpParts[i] = lpParts[i - 1] + drive_width;
  3136. i++;
  3137. // edge
  3138. lpParts[i] = lpParts[i - 1] + drive_width;
  3139. window_led_msg = lpParts[window_led_msg_start - 1];
  3140. window_led_msg_end = lpParts[window_led_msg_start - 1 + 1];
  3141. window_led_joys = lpParts[window_led_joy_start - joys];
  3142. window_led_joys_end = lpParts[window_led_joy_start - joys + 1];
  3143. window_led_hd = lpParts[i1];
  3144. window_led_hd_end = lpParts[i1 + 1];
  3145. window_led_drives = lpParts[i1 + 3];
  3146. window_led_drives_end = lpParts[i1 + 3 + 4];
  3147. /* Create the parts */
  3148. SendMessage(mon->hStatusWnd, SB_SETPARTS, (WPARAM)num_parts, (LPARAM)lpParts);
  3149. LocalUnlock(hloc);
  3150. LocalFree(hloc);
  3151. }
  3152. }
  3153. registertouch(mon->hStatusWnd);
  3154. }
  3155. #if 0
  3156. #include <dbt.h>
  3157. static int createnotification (HWND hwnd)
  3158. {
  3159. DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
  3160. HDEVNOTIFY hDevNotify;
  3161. ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
  3162. NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  3163. NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  3164. hDevNotify = RegisterDeviceNotification(hMainWnd,
  3165. &NotificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
  3166. if(!hDevNotify)
  3167. {
  3168. write_log (_T("RegisterDeviceNotification failed: %d\n"), GetLastError());
  3169. return FALSE;
  3170. }
  3171. return TRUE;
  3172. }
  3173. #endif
  3174. static int getbestmode(struct AmigaMonitor *mon, int nextbest)
  3175. {
  3176. int i, startidx;
  3177. struct MultiDisplay *md;
  3178. int ratio;
  3179. int index = -1;
  3180. for(;;) {
  3181. md = getdisplay2(&currprefs, index);
  3182. if (!md)
  3183. return 0;
  3184. ratio = mon->currentmode.native_width > mon->currentmode.native_height ? 1 : 0;
  3185. for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
  3186. struct PicassoResolution *pr = &md->DisplayModes[i];
  3187. if (pr->res.width == mon->currentmode.native_width && pr->res.height == mon->currentmode.native_height)
  3188. break;
  3189. }
  3190. if (md->DisplayModes[i].depth >= 0) {
  3191. if (!nextbest)
  3192. break;
  3193. while (md->DisplayModes[i].res.width == mon->currentmode.native_width && md->DisplayModes[i].res.height == mon->currentmode.native_height)
  3194. i++;
  3195. } else {
  3196. i = 0;
  3197. }
  3198. // first iterate only modes that have similar aspect ratio
  3199. startidx = i;
  3200. for (; md->DisplayModes[i].depth >= 0; i++) {
  3201. struct PicassoResolution *pr = &md->DisplayModes[i];
  3202. int r = pr->res.width > pr->res.height ? 1 : 0;
  3203. if (pr->res.width >= mon->currentmode.native_width && pr->res.height >= mon->currentmode.native_height && r == ratio) {
  3204. write_log (_T("FS: %dx%d -> %dx%d %d %d\n"), mon->currentmode.native_width, mon->currentmode.native_height,
  3205. pr->res.width, pr->res.height, ratio, index);
  3206. mon->currentmode.native_width = pr->res.width;
  3207. mon->currentmode.native_height = pr->res.height;
  3208. mon->currentmode.current_width = mon->currentmode.native_width;
  3209. mon->currentmode.current_height = mon->currentmode.native_height;
  3210. goto end;
  3211. }
  3212. }
  3213. // still not match? check all modes
  3214. i = startidx;
  3215. for (; md->DisplayModes[i].depth >= 0; i++) {
  3216. struct PicassoResolution *pr = &md->DisplayModes[i];
  3217. int r = pr->res.width > pr->res.height ? 1 : 0;
  3218. if (pr->res.width >= mon->currentmode.native_width && pr->res.height >= mon->currentmode.native_height) {
  3219. write_log (_T("FS: %dx%d -> %dx%d\n"), mon->currentmode.native_width, mon->currentmode.native_height,
  3220. pr->res.width, pr->res.height);
  3221. mon->currentmode.native_width = pr->res.width;
  3222. mon->currentmode.native_height = pr->res.height;
  3223. mon->currentmode.current_width = mon->currentmode.native_width;
  3224. mon->currentmode.current_height = mon->currentmode.native_height;
  3225. goto end;
  3226. }
  3227. }
  3228. index++;
  3229. }
  3230. end:
  3231. if (index >= 0) {
  3232. currprefs.gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display =
  3233. changed_prefs.gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display = index;
  3234. write_log (L"Can't find mode %dx%d ->\n", mon->currentmode.native_width, mon->currentmode.native_height);
  3235. write_log (L"Monitor switched to '%s'\n", md->adaptername);
  3236. }
  3237. return 1;
  3238. }
  3239. float target_getcurrentvblankrate(int monid)
  3240. {
  3241. struct AmigaMonitor *mon = &AMonitors[monid];
  3242. float vb;
  3243. if (currprefs.gfx_variable_sync)
  3244. return (float)mon->currentmode.freq;
  3245. if (get_display_vblank_params(-1, NULL, NULL, &vb, NULL)) {
  3246. return vb;
  3247. } else if (currprefs.gfx_api) {
  3248. return D3D_getrefreshrate(0);
  3249. } else {
  3250. return (float)DirectDraw_CurrentRefreshRate();
  3251. }
  3252. }
  3253. static void movecursor (int x, int y)
  3254. {
  3255. write_log (_T("SetCursorPos %dx%d\n"), x, y);
  3256. SetCursorPos (x, y);
  3257. }
  3258. static void getextramonitorpos(struct AmigaMonitor *mon, RECT *r)
  3259. {
  3260. TCHAR buf[100];
  3261. RECT r1, r2;
  3262. int x, y;
  3263. bool got = true;
  3264. _stprintf(buf, _T("MainPosX_%d"), mon->monitor_id);
  3265. if (!regqueryint(NULL, buf, &x)) {
  3266. got = false;
  3267. }
  3268. _stprintf(buf, _T("MainPosY_%d"), mon->monitor_id);
  3269. if (!regqueryint(NULL, buf, &y)) {
  3270. got = false;
  3271. }
  3272. if (got) {
  3273. POINT pt;
  3274. pt.x = x;
  3275. pt.y = y;
  3276. if (!MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
  3277. got = false;
  3278. }
  3279. }
  3280. // find rightmost window edge
  3281. int monid = MAX_AMIGAMONITORS - 1;
  3282. int rightmon = -1;
  3283. int rightedge = 0;
  3284. HWND hwnd = NULL;
  3285. for (;;) {
  3286. if (monid < 1)
  3287. break;
  3288. monid--;
  3289. hwnd = AMonitors[monid].hMainWnd;
  3290. if (!hwnd)
  3291. continue;
  3292. GetWindowRect(hwnd, &r1);
  3293. if (r1.right > rightedge) {
  3294. rightedge = r1.right;
  3295. rightmon = monid;
  3296. }
  3297. }
  3298. if (rightmon < 0 && !got)
  3299. return;
  3300. hwnd = AMonitors[rightmon].hMainWnd;
  3301. GetWindowRect(hwnd, &r1);
  3302. r2 = r1;
  3303. getextendedframebounds(hwnd, &r2);
  3304. int width = r->right - r->left;
  3305. int height = r->bottom - r->top;
  3306. if (got) {
  3307. r->left = x;
  3308. r->top = y;
  3309. } else {
  3310. r->left = r1.right - ((r2.left - r1.left) + (r1.right - r2.right));
  3311. r->top = r1.top;
  3312. }
  3313. r->bottom = r->top + height;
  3314. r->right = r->left + width;
  3315. }
  3316. static int create_windows_2(struct AmigaMonitor *mon)
  3317. {
  3318. static bool firstwindow = true;
  3319. int dxfs = mon->currentmode.flags & (DM_DX_FULLSCREEN);
  3320. int d3dfs = mon->currentmode.flags & (DM_D3D_FULLSCREEN);
  3321. int fsw = mon->currentmode.flags & (DM_W_FULLSCREEN);
  3322. DWORD exstyle = (currprefs.win32_notaskbarbutton ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW) | 0;
  3323. DWORD flags = 0;
  3324. int borderless = currprefs.win32_borderless;
  3325. DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  3326. int cyborder = GetSystemMetrics (SM_CYFRAME);
  3327. int gap = 0;
  3328. int x, y, w, h;
  3329. struct MultiDisplay *md;
  3330. md = getdisplay(&currprefs, mon->monitor_id);
  3331. if (mon->monitor_id && fsw) {
  3332. struct MultiDisplay *md2 = NULL;
  3333. int idx = 0;
  3334. for (;;) {
  3335. md2 = getdisplay2(&currprefs, idx);
  3336. if (md2 == md)
  3337. break;
  3338. if (!md2)
  3339. break;
  3340. idx++;
  3341. }
  3342. for (int i = 0; i <= mon->monitor_id; i++) {
  3343. md2 = getdisplay2(&currprefs, idx);
  3344. if (!md2)
  3345. idx = 0;
  3346. else
  3347. idx++;
  3348. }
  3349. if (md2)
  3350. md = md2;
  3351. }
  3352. mon->md = md;
  3353. if (mon->hAmigaWnd) {
  3354. RECT r;
  3355. int w, h, x, y;
  3356. int nw, nh, nx, ny;
  3357. if (minimized) {
  3358. minimized = -1;
  3359. return 1;
  3360. }
  3361. #if 0
  3362. if (minimized && hMainWnd) {
  3363. unsetminimized ();
  3364. ShowWindow (hMainWnd, SW_SHOW);
  3365. ShowWindow (hMainWnd, SW_RESTORE);
  3366. }
  3367. #endif
  3368. GetWindowRect (mon->hAmigaWnd, &r);
  3369. int sbheight = currprefs.win32_statusbar ? getstatuswindowheight(mon->monitor_id, mon->hAmigaWnd) : 0;
  3370. int dpi = getdpiforwindow(mon->hAmigaWnd);
  3371. x = r.left;
  3372. y = r.top;
  3373. w = r.right - r.left;
  3374. h = r.bottom - r.top;
  3375. nx = x;
  3376. ny = y;
  3377. if (mon->screen_is_picasso) {
  3378. nw = mon->currentmode.current_width;
  3379. nh = mon->currentmode.current_height;
  3380. } else {
  3381. nw = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.width;
  3382. nh = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.height;
  3383. }
  3384. if (fsw || dxfs) {
  3385. RECT rc = md->rect;
  3386. nx = rc.left;
  3387. ny = rc.top;
  3388. nw = rc.right - rc.left;
  3389. nh = rc.bottom - rc.top;
  3390. } else if (d3dfs) {
  3391. RECT rc = md->rect;
  3392. nw = mon->currentmode.native_width;
  3393. nh = mon->currentmode.native_height;
  3394. if (rc.left >= 0)
  3395. nx = rc.left;
  3396. else
  3397. nx = rc.left + (rc.right - rc.left - nw);
  3398. if (rc.top >= 0)
  3399. ny = rc.top;
  3400. else
  3401. ny = rc.top + (rc.bottom - rc.top - nh);
  3402. }
  3403. if (w != nw || h != nh || x != nx || y != ny || sbheight != mon->window_extra_height_bar || dpi != mon->dpi) {
  3404. w = nw;
  3405. h = nh;
  3406. x = nx;
  3407. y = ny;
  3408. mon->in_sizemove++;
  3409. if (mon->hMainWnd && !fsw && !dxfs && !d3dfs && !rp_isactive()) {
  3410. if (dpi != mon->dpi) {
  3411. mon->window_extra_height -= mon->window_extra_height_bar;
  3412. mon->window_extra_height += sbheight;
  3413. } else {
  3414. mon->window_extra_height += (sbheight - mon->window_extra_height_bar);
  3415. }
  3416. GetWindowRect(mon->hMainWnd, &r);
  3417. #if 0
  3418. RECT r2;
  3419. GetClientRect(mon->hMainWnd, &r2);
  3420. if (pAdjustWindowRectExForDpi) {
  3421. HMONITOR mon = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);
  3422. pAdjustWindowRectExForDpi(&r, borderless ? WS_POPUP : style, FALSE, exstyle, getdpiformonitor(mon));
  3423. } else {
  3424. AdjustWindowRectEx(&r, borderless ? WS_POPUP : style, FALSE, exstyle);
  3425. }
  3426. #endif
  3427. x = r.left;
  3428. y = r.top;
  3429. SetWindowPos(mon->hMainWnd, HWND_TOP, x, y, w + mon->window_extra_width, h + mon->window_extra_height,
  3430. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
  3431. x = gap;
  3432. y = gap;
  3433. }
  3434. SetWindowPos(mon->hAmigaWnd, HWND_TOP, x, y, w, h,
  3435. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
  3436. mon->in_sizemove--;
  3437. mon->dpi = dpi;
  3438. } else {
  3439. w = nw;
  3440. h = nh;
  3441. x = nx;
  3442. y = ny;
  3443. }
  3444. createstatuswindow(mon);
  3445. createstatusline(mon->hAmigaWnd, mon->monitor_id);
  3446. updatewinrect(mon, false);
  3447. GetWindowRect (mon->hMainWnd, &mon->mainwin_rect);
  3448. if (d3dfs || dxfs)
  3449. movecursor (x + w / 2, y + h / 2);
  3450. write_log (_T("window already open (%dx%d %dx%d)\n"),
  3451. mon->amigawin_rect.left, mon->amigawin_rect.top, mon->amigawin_rect.right - mon->amigawin_rect.left, mon->amigawin_rect.bottom - mon->amigawin_rect.top);
  3452. updatemouseclip(mon);
  3453. rp_screenmode_changed ();
  3454. mon->window_extra_height_bar = sbheight;
  3455. return 1;
  3456. }
  3457. if (fsw && !borderless)
  3458. borderless = 1;
  3459. window_led_drives = 0;
  3460. window_led_drives_end = 0;
  3461. mon->hMainWnd = NULL;
  3462. x = 0; y = 0;
  3463. int sbheight = currprefs.win32_statusbar ? getstatuswindowheight(mon->monitor_id, NULL) : 0;
  3464. if (borderless)
  3465. sbheight = cyborder = 0;
  3466. if (!dxfs && !d3dfs) {
  3467. RECT rc;
  3468. int stored_x = 1, stored_y = sbheight + cyborder;
  3469. int oldx, oldy;
  3470. int first = 2;
  3471. regqueryint (NULL, _T("MainPosX"), &stored_x);
  3472. regqueryint (NULL, _T("MainPosY"), &stored_y);
  3473. if (borderless) {
  3474. stored_x = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.x;
  3475. stored_y = currprefs.gfx_monitor[mon->monitor_id].gfx_size_win.y;
  3476. }
  3477. while (first) {
  3478. first--;
  3479. if (stored_x < GetSystemMetrics (SM_XVIRTUALSCREEN))
  3480. stored_x = GetSystemMetrics (SM_XVIRTUALSCREEN);
  3481. if (stored_y < GetSystemMetrics (SM_YVIRTUALSCREEN) + sbheight + cyborder)
  3482. stored_y = GetSystemMetrics (SM_YVIRTUALSCREEN) + sbheight + cyborder;
  3483. if (stored_x > GetSystemMetrics (SM_CXVIRTUALSCREEN))
  3484. rc.left = 1;
  3485. else
  3486. rc.left = stored_x;
  3487. if (stored_y > GetSystemMetrics (SM_CYVIRTUALSCREEN))
  3488. rc.top = 1;
  3489. else
  3490. rc.top = stored_y;
  3491. rc.right = rc.left + gap + mon->currentmode.current_width + gap;
  3492. rc.bottom = rc.top + gap + mon->currentmode.current_height + gap + sbheight;
  3493. oldx = rc.left;
  3494. oldy = rc.top;
  3495. if (pAdjustWindowRectExForDpi) {
  3496. HMONITOR mon = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
  3497. pAdjustWindowRectExForDpi(&rc, borderless ? WS_POPUP : style, FALSE, exstyle, getdpiformonitor(mon));
  3498. } else {
  3499. AdjustWindowRectEx(&rc, borderless ? WS_POPUP : style, FALSE, exstyle);
  3500. }
  3501. mon->win_x_diff = rc.left - oldx;
  3502. mon->win_y_diff = rc.top - oldy;
  3503. if (MonitorFromRect (&rc, MONITOR_DEFAULTTONULL) == NULL) {
  3504. write_log (_T("window coordinates are not visible on any monitor, reseting..\n"));
  3505. stored_x = stored_y = 0;
  3506. continue;
  3507. }
  3508. if (mon->monitor_id > 0) {
  3509. getextramonitorpos(mon, &rc);
  3510. }
  3511. break;
  3512. }
  3513. if (fsw) {
  3514. rc = md->rect;
  3515. flags |= WS_EX_TOPMOST;
  3516. style = WS_POPUP;
  3517. mon->currentmode.native_width = rc.right - rc.left;
  3518. mon->currentmode.native_height = rc.bottom - rc.top;
  3519. }
  3520. flags |= currprefs.win32_main_alwaysontop ? WS_EX_TOPMOST : 0;
  3521. if (!borderless) {
  3522. RECT rc2;
  3523. int sbheight2 = -1;
  3524. for (;;) {
  3525. mon->hMainWnd = CreateWindowEx(WS_EX_ACCEPTFILES | exstyle | flags,
  3526. _T("PCsuxRox"), _T("WinUAE"),
  3527. style,
  3528. rc.left, rc.top,
  3529. rc.right - rc.left, rc.bottom - rc.top,
  3530. NULL, NULL, hInst, NULL);
  3531. if (!mon->hMainWnd) {
  3532. write_log(_T("main window creation failed\n"));
  3533. return 0;
  3534. }
  3535. if (sbheight && sbheight2 < 0 && !fsw) {
  3536. // recheck, system could have multiple monitors with different DPI
  3537. sbheight2 = getstatuswindowheight(mon->monitor_id, mon->hMainWnd);
  3538. if (sbheight2 != sbheight) {
  3539. rc.bottom -= sbheight;
  3540. rc.bottom += sbheight2;
  3541. sbheight = sbheight2;
  3542. DestroyWindow(mon->hMainWnd);
  3543. mon->hMainWnd = NULL;
  3544. continue;
  3545. }
  3546. }
  3547. break;
  3548. }
  3549. GetWindowRect(mon->hMainWnd, &rc2);
  3550. mon->window_extra_width = rc2.right - rc2.left - mon->currentmode.current_width;
  3551. mon->window_extra_height = rc2.bottom - rc2.top - mon->currentmode.current_height;
  3552. createstatuswindow(mon);
  3553. createstatusline(mon->hMainWnd, mon->monitor_id);
  3554. } else {
  3555. x = rc.left;
  3556. y = rc.top;
  3557. }
  3558. w = mon->currentmode.native_width;
  3559. h = mon->currentmode.native_height;
  3560. } else {
  3561. RECT rc;
  3562. getbestmode(mon, 0);
  3563. w = mon->currentmode.native_width;
  3564. h = mon->currentmode.native_height;
  3565. rc = md->rect;
  3566. if (rc.left >= 0)
  3567. x = rc.left;
  3568. else
  3569. x = rc.left + (rc.right - rc.left - w);
  3570. if (rc.top >= 0)
  3571. y = rc.top;
  3572. else
  3573. y = rc.top + (rc.bottom - rc.top - h);
  3574. }
  3575. if (rp_isactive () && !dxfs && !d3dfs && !fsw) {
  3576. HWND parent = rp_getparent ();
  3577. mon->hAmigaWnd = CreateWindowEx (dxfs || d3dfs ? WS_EX_ACCEPTFILES | WS_EX_TOPMOST : WS_EX_ACCEPTFILES | WS_EX_TOOLWINDOW | (currprefs.win32_main_alwaysontop ? WS_EX_TOPMOST : 0),
  3578. _T("AmigaPowah"), _T("WinUAE"),
  3579. WS_POPUP,
  3580. 0, 0, w, h,
  3581. parent, NULL, hInst, NULL);
  3582. } else {
  3583. mon->hAmigaWnd = CreateWindowEx (
  3584. ((dxfs || d3dfs || currprefs.win32_main_alwaysontop) ? WS_EX_TOPMOST : WS_EX_ACCEPTFILES) | exstyle,
  3585. _T("AmigaPowah"), _T("WinUAE"),
  3586. ((dxfs || d3dfs || currprefs.headless) ? WS_POPUP : (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | (mon->hMainWnd ? WS_VISIBLE | WS_CHILD : WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX))),
  3587. x, y, w, h,
  3588. borderless ? NULL : (mon->hMainWnd ? mon->hMainWnd : NULL),
  3589. NULL, hInst, NULL);
  3590. }
  3591. if (!mon->hAmigaWnd) {
  3592. write_log (_T("creation of amiga window failed\n"));
  3593. close_hwnds(mon);
  3594. return 0;
  3595. }
  3596. if (mon->hMainWnd == NULL) {
  3597. mon->hMainWnd = mon->hAmigaWnd;
  3598. registertouch(mon->hAmigaWnd);
  3599. } else {
  3600. registertouch(mon->hMainWnd);
  3601. registertouch(mon->hAmigaWnd);
  3602. }
  3603. updatewinrect(mon, true);
  3604. GetWindowRect(mon->hMainWnd, &mon->mainwin_rect);
  3605. if (dxfs || d3dfs)
  3606. movecursor (x + w / 2, y + h / 2);
  3607. addnotifications (mon->hAmigaWnd, FALSE, FALSE);
  3608. mon->window_extra_height_bar = sbheight;
  3609. mon->dpi = getdpiforwindow(mon->hAmigaWnd);
  3610. if (mon->monitor_id) {
  3611. ShowWindow(mon->hMainWnd, SW_SHOWNOACTIVATE);
  3612. UpdateWindow(mon->hMainWnd);
  3613. ShowWindow(mon->hAmigaWnd, SW_SHOWNOACTIVATE);
  3614. UpdateWindow(mon->hAmigaWnd);
  3615. } else {
  3616. createblankwindows();
  3617. if (mon->hMainWnd != mon->hAmigaWnd) {
  3618. if (!currprefs.headless && !rp_isactive())
  3619. ShowWindow(mon->hMainWnd, firstwindow ? (currprefs.win32_start_minimized ? SW_SHOWMINIMIZED : SW_SHOWDEFAULT) : SW_SHOWNORMAL);
  3620. UpdateWindow(mon->hMainWnd);
  3621. }
  3622. if (!currprefs.headless && !rp_isactive())
  3623. ShowWindow(mon->hAmigaWnd, SW_SHOWNORMAL);
  3624. UpdateWindow(mon->hAmigaWnd);
  3625. firstwindow = false;
  3626. setDwmEnableMMCSS(true);
  3627. rawinput_alloc();
  3628. if (currprefs.win32_shutdown_notification && !rp_isactive()) {
  3629. typedef BOOL(WINAPI *SHUTDOWNBLOCKREASONCREATE)(HWND, LPCWSTR);
  3630. SHUTDOWNBLOCKREASONCREATE pShutdownBlockReasonCreate;
  3631. pShutdownBlockReasonCreate = (SHUTDOWNBLOCKREASONCREATE)GetProcAddress(userdll, "ShutdownBlockReasonCreate");
  3632. if (pShutdownBlockReasonCreate) {
  3633. TCHAR tmp[MAX_DPATH];
  3634. WIN32GUI_LoadUIString(IDS_SHUTDOWN_NOTIFICATION, tmp, MAX_DPATH);
  3635. if (!pShutdownBlockReasonCreate(mon->hMainWnd, tmp)) {
  3636. write_log(_T("ShutdownBlockReasonCreate %08x\n"), GetLastError());
  3637. }
  3638. }
  3639. }
  3640. }
  3641. return 1;
  3642. }
  3643. static int set_ddraw(struct AmigaMonitor *mon)
  3644. {
  3645. int cnt, ret;
  3646. cnt = 3;
  3647. for (;;) {
  3648. ret = set_ddraw_2(mon);
  3649. if (cnt-- <= 0)
  3650. return 0;
  3651. if (ret < 0) {
  3652. getbestmode(mon, 1);
  3653. continue;
  3654. }
  3655. if (ret == 0)
  3656. return 0;
  3657. break;
  3658. }
  3659. return 1;
  3660. }
  3661. static void allocsoftbuffer(int monid, const TCHAR *name, struct vidbuffer *buf, int flags, int width, int height, int depth)
  3662. {
  3663. struct vidbuf_description *vidinfo = &adisplays[monid].gfxvidinfo;
  3664. buf->monitor_id = monid;
  3665. buf->pixbytes = (depth + 7) / 8;
  3666. buf->width_allocated = (width + 7) & ~7;
  3667. buf->height_allocated = height;
  3668. if (!(flags & DM_SWSCALE)) {
  3669. if (buf != &vidinfo->drawbuffer)
  3670. return;
  3671. buf->bufmem = NULL;
  3672. buf->bufmemend = NULL;
  3673. buf->realbufmem = NULL;
  3674. buf->bufmem_allocated = NULL;
  3675. buf->bufmem_lockable = true;
  3676. write_log (_T("Mon %d reserved %s temp buffer (%d*%d*%d)\n"), monid, name, width, height, depth);
  3677. } else if (flags & DM_SWSCALE) {
  3678. int w = buf->width_allocated;
  3679. int h = buf->height_allocated;
  3680. int size = (w * 2) * (h * 2) * buf->pixbytes;
  3681. buf->rowbytes = w * 2 * buf->pixbytes;
  3682. buf->realbufmem = xcalloc(uae_u8, size);
  3683. buf->bufmem_allocated = buf->bufmem = buf->realbufmem + (h / 2) * buf->rowbytes + (w / 2) * buf->pixbytes;
  3684. buf->bufmemend = buf->realbufmem + size - buf->rowbytes;
  3685. buf->bufmem_lockable = true;
  3686. write_log (_T("Mon %d allocated %s temp buffer (%d*%d*%d) = %p\n"), monid, name, width, height, depth, buf->realbufmem);
  3687. }
  3688. }
  3689. static int create_windows(struct AmigaMonitor *mon)
  3690. {
  3691. if (!create_windows_2(mon))
  3692. return 0;
  3693. return set_ddraw(mon);
  3694. }
  3695. static int oldtex_w[MAX_AMIGAMONITORS], oldtex_h[MAX_AMIGAMONITORS], oldtex_rtg[MAX_AMIGAMONITORS];
  3696. static BOOL doInit(struct AmigaMonitor *mon)
  3697. {
  3698. int tmp_depth;
  3699. int ret = 0;
  3700. retry:
  3701. struct vidbuf_description *avidinfo = &adisplays[mon->monitor_id].gfxvidinfo;
  3702. struct amigadisplay *ad = &adisplays[mon->monitor_id];
  3703. if (wasfullwindow_a == 0)
  3704. wasfullwindow_a = currprefs.gfx_apmode[0].gfx_fullscreen == GFX_FULLWINDOW ? 1 : -1;
  3705. if (wasfullwindow_p == 0)
  3706. wasfullwindow_p = currprefs.gfx_apmode[1].gfx_fullscreen == GFX_FULLWINDOW ? 1 : -1;
  3707. gfxmode_reset(mon->monitor_id);
  3708. freevidbuffer(mon->monitor_id, &avidinfo->drawbuffer);
  3709. freevidbuffer(mon->monitor_id, &avidinfo->tempbuffer);
  3710. for (;;) {
  3711. updatemodes(mon);
  3712. mon->currentmode.native_depth = 0;
  3713. tmp_depth = mon->currentmode.current_depth;
  3714. if (mon->currentmode.flags & DM_W_FULLSCREEN) {
  3715. RECT rc = getdisplay(&currprefs, mon->monitor_id)->rect;
  3716. mon->currentmode.native_width = rc.right - rc.left;
  3717. mon->currentmode.native_height = rc.bottom - rc.top;
  3718. }
  3719. if (isfullscreen() <= 0 && !(mon->currentmode.flags & (DM_D3D))) {
  3720. mon->currentmode.current_depth = DirectDraw_GetCurrentDepth ();
  3721. updatemodes(mon);
  3722. }
  3723. if (!(mon->currentmode.flags & (DM_D3D)) && DirectDraw_GetCurrentDepth () == mon->currentmode.current_depth) {
  3724. updatemodes(mon);
  3725. }
  3726. #if 0
  3727. TCHAR tmpstr[300];
  3728. int fs_warning = -1;
  3729. if (!rp_isactive () && (mon->currentmode.current_width > GetSystemMetrics(SM_CXVIRTUALSCREEN) ||
  3730. mon->currentmode.current_height > GetSystemMetrics(SM_CYVIRTUALSCREEN))) {
  3731. if (!console_logging)
  3732. fs_warning = IDS_UNSUPPORTEDSCREENMODE_3;
  3733. }
  3734. if (fs_warning >= 0 && isfullscreen () <= 0) {
  3735. TCHAR szMessage[MAX_DPATH], szMessage2[MAX_DPATH];
  3736. WIN32GUI_LoadUIString(IDS_UNSUPPORTEDSCREENMODE, szMessage, MAX_DPATH);
  3737. WIN32GUI_LoadUIString(fs_warning, szMessage2, MAX_DPATH);
  3738. // Temporarily drop the DirectDraw stuff
  3739. DirectDraw_Release ();
  3740. _stprintf (tmpstr, szMessage, szMessage2);
  3741. gui_message (tmpstr);
  3742. DirectDraw_Start ();
  3743. if (mon->screen_is_picasso)
  3744. changed_prefs.gfx_apmode[1].gfx_fullscreen = currprefs.gfx_apmode[1].gfx_fullscreen = GFX_FULLSCREEN;
  3745. else
  3746. changed_prefs.gfx_apmode[0].gfx_fullscreen = currprefs.gfx_apmode[0].gfx_fullscreen = GFX_FULLSCREEN;
  3747. updatewinfsmode(mon->monitor_id, &currprefs);
  3748. updatewinfsmode(mon->monitor_id, &changed_prefs);
  3749. mon->currentmode.current_depth = tmp_depth;
  3750. updatemodes(mon);
  3751. ret = -2;
  3752. goto oops;
  3753. }
  3754. #endif
  3755. if (!create_windows(mon))
  3756. goto oops;
  3757. #ifdef PICASSO96
  3758. if (mon->screen_is_picasso) {
  3759. break;
  3760. } else {
  3761. #endif
  3762. struct uae_filter *usedfilter = mon->usedfilter;
  3763. mon->currentmode.native_depth = mon->currentmode.current_depth;
  3764. if (currprefs.gfx_resolution > avidinfo->gfx_resolution_reserved)
  3765. avidinfo->gfx_resolution_reserved = currprefs.gfx_resolution;
  3766. if (currprefs.gfx_vresolution > avidinfo->gfx_vresolution_reserved)
  3767. avidinfo->gfx_vresolution_reserved = currprefs.gfx_vresolution;
  3768. //gfxvidinfo.drawbuffer.gfx_resolution_reserved = RES_SUPERHIRES;
  3769. #if defined (GFXFILTER)
  3770. if (mon->currentmode.flags & (DM_D3D | DM_SWSCALE)) {
  3771. if (!currprefs.gfx_autoresolution) {
  3772. mon->currentmode.amiga_width = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
  3773. mon->currentmode.amiga_height = AMIGA_HEIGHT_MAX << currprefs.gfx_vresolution;
  3774. } else {
  3775. mon->currentmode.amiga_width = AMIGA_WIDTH_MAX << avidinfo->gfx_resolution_reserved;
  3776. mon->currentmode.amiga_height = AMIGA_HEIGHT_MAX << avidinfo->gfx_vresolution_reserved;
  3777. }
  3778. if (avidinfo->gfx_resolution_reserved == RES_SUPERHIRES)
  3779. mon->currentmode.amiga_height *= 2;
  3780. if (mon->currentmode.amiga_height > 1280)
  3781. mon->currentmode.amiga_height = 1280;
  3782. avidinfo->drawbuffer.inwidth = avidinfo->drawbuffer.outwidth = mon->currentmode.amiga_width;
  3783. avidinfo->drawbuffer.inheight = avidinfo->drawbuffer.outheight = mon->currentmode.amiga_height;
  3784. if (usedfilter) {
  3785. if ((usedfilter->flags & (UAE_FILTER_MODE_16 | UAE_FILTER_MODE_32)) == (UAE_FILTER_MODE_16 | UAE_FILTER_MODE_32)) {
  3786. mon->currentmode.current_depth = mon->currentmode.native_depth;
  3787. } else {
  3788. mon->currentmode.current_depth = (usedfilter->flags & UAE_FILTER_MODE_32) ? 32 : 16;
  3789. }
  3790. }
  3791. mon->currentmode.pitch = mon->currentmode.amiga_width * mon->currentmode.current_depth >> 3;
  3792. }
  3793. else
  3794. #endif
  3795. {
  3796. mon->currentmode.amiga_width = mon->currentmode.current_width;
  3797. mon->currentmode.amiga_height = mon->currentmode.current_height;
  3798. }
  3799. avidinfo->drawbuffer.pixbytes = mon->currentmode.current_depth >> 3;
  3800. avidinfo->drawbuffer.bufmem = NULL;
  3801. avidinfo->drawbuffer.linemem = NULL;
  3802. avidinfo->drawbuffer.rowbytes = mon->currentmode.pitch;
  3803. break;
  3804. #ifdef PICASSO96
  3805. }
  3806. #endif
  3807. }
  3808. updatepicasso96(mon);
  3809. if (!scrlinebuf)
  3810. scrlinebuf = xmalloc (uae_u8, max_uae_width * 4);
  3811. avidinfo->drawbuffer.emergmem = scrlinebuf; // memcpy from system-memory to video-memory
  3812. avidinfo->drawbuffer.realbufmem = NULL;
  3813. avidinfo->drawbuffer.bufmem = NULL;
  3814. avidinfo->drawbuffer.bufmem_allocated = NULL;
  3815. avidinfo->drawbuffer.bufmem_lockable = false;
  3816. avidinfo->outbuffer = &avidinfo->drawbuffer;
  3817. avidinfo->inbuffer = &avidinfo->drawbuffer;
  3818. if (!mon->screen_is_picasso) {
  3819. if (currprefs.gfx_api == 0 && currprefs.gf[0].gfx_filter == 0) {
  3820. allocsoftbuffer(mon->monitor_id, _T("draw"), &avidinfo->drawbuffer, mon->currentmode.flags,
  3821. mon->currentmode.native_width, mon->currentmode.native_height, mon->currentmode.current_depth);
  3822. } else {
  3823. allocsoftbuffer(mon->monitor_id, _T("draw"), &avidinfo->drawbuffer, mon->currentmode.flags,
  3824. 1920, 1280, mon->currentmode.current_depth);
  3825. }
  3826. if (currprefs.monitoremu || currprefs.cs_cd32fmv || (currprefs.genlock && currprefs.genlock_image) || currprefs.cs_color_burst || currprefs.gfx_grayscale) {
  3827. allocsoftbuffer(mon->monitor_id, _T("monemu"), &avidinfo->tempbuffer, mon->currentmode.flags,
  3828. mon->currentmode.amiga_width > 1024 ? mon->currentmode.amiga_width : 1024,
  3829. mon->currentmode.amiga_height > 1024 ? mon->currentmode.amiga_height : 1024,
  3830. mon->currentmode.current_depth);
  3831. }
  3832. init_row_map ();
  3833. }
  3834. S2X_free(mon->monitor_id);
  3835. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  3836. oldtex_w[i] = oldtex_h[i] = -1;
  3837. }
  3838. if (mon->currentmode.flags & DM_D3D) {
  3839. int fmh = mon->screen_is_picasso ? 1 : currprefs.gf[ad->picasso_on].gfx_filter_filtermodeh + 1;
  3840. int fmv = mon->screen_is_picasso ? 1 : currprefs.gf[ad->picasso_on].gfx_filter_filtermodev + 1 - 1;
  3841. if (currprefs.gf[ad->picasso_on].gfx_filter_filtermodev == 0) {
  3842. fmv = fmh;
  3843. }
  3844. const TCHAR *err = D3D_init(mon->hAmigaWnd, mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height,
  3845. mon->currentmode.current_depth, &mon->currentmode.freq, fmh, fmv);
  3846. if (err) {
  3847. gfx_hdr = false;
  3848. if (currprefs.gfx_api >= 2) {
  3849. D3D_free(0, true);
  3850. if (err[0] == 0 && currprefs.color_mode != 5) {
  3851. changed_prefs.color_mode = currprefs.color_mode = 5;
  3852. update_gfxparams(mon);
  3853. goto retry;
  3854. }
  3855. changed_prefs.gfx_api = currprefs.gfx_api = 1;
  3856. d3d_select(&currprefs);
  3857. error_log(_T("Direct3D11 failed to initialize ('%s'), falling back to Direct3D9."), err);
  3858. err = D3D_init(mon->hAmigaWnd, mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height,
  3859. mon->currentmode.current_depth, &mon->currentmode.freq, fmh, fmv);
  3860. }
  3861. if (err) {
  3862. D3D_free(0, true);
  3863. error_log(_T("Direct3D9 failed to initialize ('%s'), falling back to DirectDraw."), err);
  3864. changed_prefs.gfx_api = currprefs.gfx_api = 0;
  3865. changed_prefs.gf[ad->picasso_on].gfx_filter = currprefs.gf[ad->picasso_on].gfx_filter = 1;
  3866. mon->currentmode.current_depth = mon->currentmode.native_depth;
  3867. gfxmode_reset(mon->monitor_id);
  3868. DirectDraw_Start();
  3869. ret = -1;
  3870. goto oops;
  3871. }
  3872. }
  3873. target_graphics_buffer_update(mon->monitor_id);
  3874. updatewinrect(mon, true);
  3875. }
  3876. init_colors(mon->monitor_id);
  3877. mon->screen_is_initialized = 1;
  3878. display_param_init(mon);
  3879. createstatusline(mon->hAmigaWnd, mon->monitor_id);
  3880. picasso_refresh(mon->monitor_id);
  3881. #ifdef RETROPLATFORM
  3882. rp_set_hwnd_delayed ();
  3883. #endif
  3884. if (isfullscreen () != 0)
  3885. setmouseactive(mon->monitor_id, -1);
  3886. return 1;
  3887. oops:
  3888. close_hwnds(mon);
  3889. return ret;
  3890. }
  3891. bool target_graphics_buffer_update(int monid)
  3892. {
  3893. struct AmigaMonitor *mon = &AMonitors[monid];
  3894. struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
  3895. struct vidbuf_description *avidinfo = &adisplays[monid].gfxvidinfo;
  3896. struct picasso96_state_struct *state = &picasso96_state[monid];
  3897. static bool graphicsbuffer_retry;
  3898. int w, h;
  3899. graphicsbuffer_retry = false;
  3900. if (mon->screen_is_picasso) {
  3901. w = state->Width > vidinfo->width ? state->Width : vidinfo->width;
  3902. h = state->Height > vidinfo->height ? state->Height : vidinfo->height;
  3903. } else {
  3904. struct vidbuffer *vb = avidinfo->drawbuffer.tempbufferinuse ? &avidinfo->tempbuffer : &avidinfo->drawbuffer;
  3905. avidinfo->outbuffer = vb;
  3906. w = vb->outwidth;
  3907. h = vb->outheight;
  3908. }
  3909. if (oldtex_w[monid] == w && oldtex_h[monid] == h && oldtex_rtg[monid] == mon->screen_is_picasso)
  3910. return false;
  3911. if (!w || !h) {
  3912. oldtex_w[monid] = w;
  3913. oldtex_h[monid] = h;
  3914. oldtex_rtg[monid] = mon->screen_is_picasso;
  3915. return false;
  3916. }
  3917. S2X_free(mon->monitor_id);
  3918. if (mon->currentmode.flags & DM_D3D) {
  3919. if (!D3D_alloctexture(mon->monitor_id, w, h)) {
  3920. graphicsbuffer_retry = true;
  3921. return false;
  3922. }
  3923. } else {
  3924. DirectDraw_ClearSurface (NULL);
  3925. }
  3926. oldtex_w[monid] = w;
  3927. oldtex_h[monid] = h;
  3928. oldtex_rtg[monid] = mon->screen_is_picasso;
  3929. write_log (_T("Buffer %d size (%d*%d) %s\n"), monid, w, h, mon->screen_is_picasso ? _T("RTG") : _T("Native"));
  3930. if ((mon->currentmode.flags & DM_SWSCALE) && !mon->screen_is_picasso) {
  3931. if (!S2X_init(mon->monitor_id, mon->currentmode.native_width, mon->currentmode.native_height, mon->currentmode.native_depth))
  3932. return false;
  3933. }
  3934. return true;
  3935. }
  3936. static void updatedisplayarea2(int monid)
  3937. {
  3938. struct AmigaMonitor *mon = &AMonitors[monid];
  3939. struct amigadisplay *ad = &adisplays[monid];
  3940. if (!mon->screen_is_initialized)
  3941. return;
  3942. if (dx_islost())
  3943. return;
  3944. #if defined (GFXFILTER)
  3945. if (mon->currentmode.flags & DM_D3D) {
  3946. #if defined (D3D)
  3947. D3D_refresh(monid);
  3948. #endif
  3949. } else
  3950. #endif
  3951. if (mon->currentmode.flags & DM_DDRAW) {
  3952. #if defined (GFXFILTER)
  3953. if (!ad->picasso_on) {
  3954. if (mon->currentmode.flags & DM_SWSCALE)
  3955. S2X_refresh(monid);
  3956. }
  3957. #endif
  3958. DirectDraw_Flip(0);
  3959. }
  3960. }
  3961. void updatedisplayarea(int monid)
  3962. {
  3963. if (monid >= 0) {
  3964. updatedisplayarea2(monid);
  3965. } else {
  3966. for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
  3967. updatedisplayarea2(i);
  3968. }
  3969. }
  3970. }
  3971. void updatewinfsmode(int monid, struct uae_prefs *p)
  3972. {
  3973. struct MultiDisplay *md;
  3974. fixup_prefs_dimensions (p);
  3975. if (isfullscreen_2 (p) != 0) {
  3976. p->gfx_monitor[monid].gfx_size = p->gfx_monitor[monid].gfx_size_fs;
  3977. } else {
  3978. p->gfx_monitor[monid].gfx_size = p->gfx_monitor[monid].gfx_size_win;
  3979. }
  3980. md = getdisplay(p, monid);
  3981. set_config_changed ();
  3982. }
  3983. bool toggle_3d_debug(void)
  3984. {
  3985. if (isvsync_chipset() < 0) {
  3986. beamracer_debug = !beamracer_debug;
  3987. if (D3D_debug) {
  3988. D3D_debug(0, beamracer_debug);
  3989. }
  3990. reset_drawing();
  3991. return true;
  3992. }
  3993. return false;
  3994. }
  3995. int rtg_index = -1;
  3996. // -2 = default
  3997. // -1 = prev
  3998. // 0 = chipset
  3999. // 1..4 = rtg
  4000. // 5 = next
  4001. bool toggle_rtg (int monid, int mode)
  4002. {
  4003. struct amigadisplay *ad = &adisplays[monid];
  4004. int old_index = rtg_index;
  4005. if (monid > 0) {
  4006. return true;
  4007. }
  4008. if (mode < -1 && rtg_index >= 0)
  4009. return true;
  4010. for (;;) {
  4011. if (mode == -1) {
  4012. rtg_index--;
  4013. } else if (mode >= 0 && mode <= MAX_RTG_BOARDS) {
  4014. rtg_index = mode - 1;
  4015. } else {
  4016. rtg_index++;
  4017. }
  4018. if (rtg_index >= MAX_RTG_BOARDS) {
  4019. rtg_index = -1;
  4020. } else if (rtg_index < -1) {
  4021. rtg_index = MAX_RTG_BOARDS - 1;
  4022. }
  4023. if (rtg_index < 0) {
  4024. if (ad->picasso_on) {
  4025. gfxboard_rtg_disable(monid, old_index);
  4026. ad->picasso_requested_on = false;
  4027. statusline_add_message(STATUSTYPE_DISPLAY, _T("Chipset display"));
  4028. set_config_changed();
  4029. return false;
  4030. }
  4031. return false;
  4032. }
  4033. struct rtgboardconfig *r = &currprefs.rtgboards[rtg_index];
  4034. if (r->rtgmem_size > 0 && r->monitor_id == monid) {
  4035. if (r->rtgmem_type >= GFXBOARD_HARDWARE) {
  4036. int idx = gfxboard_toggle(r->monitor_id, rtg_index, mode >= -1);
  4037. if (idx >= 0) {
  4038. rtg_index = idx;
  4039. return true;
  4040. }
  4041. if (idx < -1) {
  4042. rtg_index = -1;
  4043. return false;
  4044. }
  4045. } else {
  4046. gfxboard_toggle(r->monitor_id, -1, -1);
  4047. if (mode < -1)
  4048. return true;
  4049. devices_unsafeperiod();
  4050. gfxboard_rtg_disable(monid, old_index);
  4051. // can always switch from RTG to custom
  4052. if (ad->picasso_requested_on && ad->picasso_on) {
  4053. ad->picasso_requested_on = false;
  4054. rtg_index = -1;
  4055. set_config_changed();
  4056. return true;
  4057. }
  4058. if (ad->picasso_on)
  4059. return false;
  4060. // can only switch from custom to RTG if there is some mode active
  4061. if (picasso_is_active(r->monitor_id)) {
  4062. picasso_enablescreen(r->monitor_id, 1);
  4063. ad->picasso_requested_on = true;
  4064. statusline_add_message(STATUSTYPE_DISPLAY, _T("RTG %d: %s"), rtg_index + 1, _T("UAEGFX"));
  4065. set_config_changed();
  4066. return true;
  4067. }
  4068. }
  4069. }
  4070. if (mode >= 0 && mode <= MAX_RTG_BOARDS) {
  4071. rtg_index = old_index;
  4072. return false;
  4073. }
  4074. }
  4075. return false;
  4076. }
  4077. void close_rtg(int monid, bool reset)
  4078. {
  4079. struct AmigaMonitor *mon = &AMonitors[monid];
  4080. close_windows(mon);
  4081. if (reset) {
  4082. mon->screen_is_picasso = false;
  4083. }
  4084. }
  4085. void toggle_fullscreen(int monid, int mode)
  4086. {
  4087. struct amigadisplay *ad = &adisplays[monid];
  4088. int *p = ad->picasso_on ? &changed_prefs.gfx_apmode[1].gfx_fullscreen : &changed_prefs.gfx_apmode[0].gfx_fullscreen;
  4089. int wfw = ad->picasso_on ? wasfullwindow_p : wasfullwindow_a;
  4090. int v = *p;
  4091. if (mode < 0) {
  4092. // fullscreen <> window (if in fullwindow: fullwindow <> fullscreen)
  4093. if (v == GFX_FULLWINDOW)
  4094. v = GFX_FULLSCREEN;
  4095. else if (v == GFX_WINDOW)
  4096. v = GFX_FULLSCREEN;
  4097. else if (v == GFX_FULLSCREEN)
  4098. if (wfw > 0)
  4099. v = GFX_FULLWINDOW;
  4100. else
  4101. v = GFX_WINDOW;
  4102. } else if (mode == 0) {
  4103. // fullscreen <> window
  4104. if (v == GFX_FULLSCREEN)
  4105. v = GFX_WINDOW;
  4106. else
  4107. v = GFX_FULLSCREEN;
  4108. } else if (mode == 1) {
  4109. // fullscreen <> fullwindow
  4110. if (v == GFX_FULLSCREEN)
  4111. v = GFX_FULLWINDOW;
  4112. else
  4113. v = GFX_FULLSCREEN;
  4114. } else if (mode == 2) {
  4115. // window <> fullwindow
  4116. if (v == GFX_FULLWINDOW)
  4117. v = GFX_WINDOW;
  4118. else
  4119. v = GFX_FULLWINDOW;
  4120. } else if (mode == 10) {
  4121. v = GFX_WINDOW;
  4122. }
  4123. *p = v;
  4124. devices_unsafeperiod();
  4125. updatewinfsmode(monid, &changed_prefs);
  4126. }
  4127. HDC gethdc(int monid)
  4128. {
  4129. HDC hdc = 0;
  4130. #ifdef D3D
  4131. if (D3D_isenabled(0))
  4132. return D3D_getDC(monid, 0);
  4133. #endif
  4134. if(FAILED(DirectDraw_GetDC(&hdc)))
  4135. hdc = 0;
  4136. return hdc;
  4137. }
  4138. void releasehdc(int monid, HDC hdc)
  4139. {
  4140. #ifdef D3D
  4141. if (D3D_isenabled(0)) {
  4142. D3D_getDC(monid, hdc);
  4143. return;
  4144. }
  4145. #endif
  4146. DirectDraw_ReleaseDC(hdc);
  4147. }