/od-win32/win32gfx.cpp
C++ | 4554 lines | 4059 code | 407 blank | 88 comment | 1416 complexity | cae24ac5828bd04fb235002675342e2d MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Win32 Drawing and DirectX interface
- *
- * Copyright 1997-1998 Mathias Ortmann
- * Copyright 1997-2000 Brian King
- */
- #define FORCE16BIT 0
- #include "sysconfig.h"
- #include <stdlib.h>
- #include <stdarg.h>
- #include <windows.h>
- #include <commctrl.h>
- #include <ddraw.h>
- #include <shellapi.h>
- #include <dwmapi.h>
- #include <D3dkmthk.h>
- #include <process.h>
- #include "sysdeps.h"
- #include "resource.h"
- #include "options.h"
- #include "audio.h"
- #include "uae.h"
- #include "memory.h"
- #include "custom.h"
- #include "events.h"
- #include "newcpu.h"
- #include "traps.h"
- #include "xwin.h"
- #include "keyboard.h"
- #include "drawing.h"
- #include "dxwrap.h"
- #include "picasso96_win.h"
- #include "registry.h"
- #include "win32.h"
- #include "win32gfx.h"
- #include "win32gui.h"
- #include "sound.h"
- #include "inputdevice.h"
- #include "direct3d.h"
- #include "midi.h"
- #include "gui.h"
- #include "serial.h"
- #include "avioutput.h"
- #include "gfxfilter.h"
- #include "parser.h"
- #include "lcd.h"
- #include "sampler.h"
- #include "gfxboard.h"
- #include "cpuboard.h"
- #include "x86.h"
- #ifdef RETROPLATFORM
- #include "rp.h"
- #endif
- #include "statusline.h"
- #include "devices.h"
- #define DM_DX_FULLSCREEN 1
- #define DM_W_FULLSCREEN 2
- #define DM_D3D_FULLSCREEN 16
- #define DM_PICASSO96 32
- #define DM_DDRAW 64
- #define DM_DC 128
- #define DM_D3D 256
- #define DM_SWSCALE 1024
- #define SM_WINDOW 0
- #define SM_FULLSCREEN_DX 2
- #define SM_OPENGL_WINDOW 3
- #define SM_OPENGL_FULLWINDOW 9
- #define SM_OPENGL_FULLSCREEN_DX 4
- #define SM_D3D_WINDOW 5
- #define SM_D3D_FULLWINDOW 10
- #define SM_D3D_FULLSCREEN_DX 6
- #define SM_FULLWINDOW 7
- #define SM_NONE 11
- static int deskhz;
- struct MultiDisplay Displays[MAX_DISPLAYS + 1];
- struct AmigaMonitor AMonitors[MAX_AMIGAMONITORS];
- struct AmigaMonitor *amon = NULL;
- static int display_change_requested;
- int window_led_drives, window_led_drives_end;
- int window_led_hd, window_led_hd_end;
- int window_led_joys, window_led_joys_end, window_led_joy_start;
- int window_led_msg, window_led_msg_end, window_led_msg_start;
- extern int console_logging;
- static int wasfullwindow_a, wasfullwindow_p;
- int vsync_modechangetimeout = 10;
- int vsync_activeheight, vsync_totalheight;
- float vsync_vblank, vsync_hblank;
- bool beamracer_debug;
- bool gfx_hdr;
- int reopen(struct AmigaMonitor *, int, bool);
- static CRITICAL_SECTION screen_cs;
- static bool screen_cs_allocated;
- void gfx_lock (void)
- {
- EnterCriticalSection (&screen_cs);
- }
- void gfx_unlock (void)
- {
- LeaveCriticalSection (&screen_cs);
- }
- int WIN32GFX_IsPicassoScreen(struct AmigaMonitor *mon)
- {
- return mon->screen_is_picasso ? 1 : 0;
- }
- static int isscreen(struct AmigaMonitor *mon)
- {
- return mon->hMainWnd ? 1 : 0;
- }
- static void clearscreen (void)
- {
- DirectDraw_FillPrimary ();
- }
- static int isfullscreen_2(struct uae_prefs *p)
- {
- struct AmigaMonitor *mon = &AMonitors[0];
- int idx = mon->screen_is_picasso ? 1 : 0;
- return p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLSCREEN ? 1 : (p->gfx_apmode[idx].gfx_fullscreen == GFX_FULLWINDOW ? -1 : 0);
- }
- int isfullscreen(void)
- {
- return isfullscreen_2(&currprefs);
- }
- int WIN32GFX_GetDepth(struct AmigaMonitor *mon, int real)
- {
- if (!mon->currentmode.native_depth)
- return mon->currentmode.current_depth;
- return real ? mon->currentmode.native_depth : mon->currentmode.current_depth;
- }
- int WIN32GFX_GetWidth(struct AmigaMonitor *mon)
- {
- return mon->currentmode.current_width;
- }
- int WIN32GFX_GetHeight(struct AmigaMonitor *mon)
- {
- return mon->currentmode.current_height;
- }
- static BOOL doInit (struct AmigaMonitor*);
- int default_freq = 60;
- static uae_u8 *scrlinebuf;
- static struct MultiDisplay *getdisplay2(struct uae_prefs *p, int index)
- {
- struct AmigaMonitor *mon = &AMonitors[0];
- static int max;
- int display = index < 0 ? p->gfx_apmode[mon->screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_display - 1 : index;
- if (!max || (max > 0 && Displays[max].monitorname != NULL)) {
- max = 0;
- while (Displays[max].monitorname)
- max++;
- if (max == 0) {
- gui_message(_T("no display adapters! Exiting"));
- exit(0);
- }
- }
- if (index >= 0 && display >= max)
- return NULL;
- if (display >= max)
- display = 0;
- if (display < 0)
- display = 0;
- return &Displays[display];
- }
- struct MultiDisplay *getdisplay(struct uae_prefs *p, int monid)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- if (monid > 0 && mon->md)
- return mon->md;
- return getdisplay2(p, -1);
- }
- void desktop_coords(int monid, int *dw, int *dh, int *ax, int *ay, int *aw, int *ah)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct MultiDisplay *md = getdisplay(&currprefs, monid);
- *dw = md->rect.right - md->rect.left;
- *dh = md->rect.bottom - md->rect.top;
- *ax = mon->amigawin_rect.left;
- *ay = mon->amigawin_rect.top;
- *aw = mon->amigawin_rect.right - *ax;
- *ah = mon->amigawin_rect.bottom - *ay;
- }
- static int target_get_display2(const TCHAR *name, int mode)
- {
- int found, found2;
- found = -1;
- found2 = -1;
- for (int i = 0; Displays[i].monitorname; i++) {
- struct MultiDisplay *md = &Displays[i];
- if (mode == 1 && md->monitorid[0] == '\\')
- continue;
- if (mode == 2 && md->monitorid[0] != '\\')
- continue;
- if (!_tcscmp (md->monitorid, name)) {
- if (found < 0) {
- found = i + 1;
- } else {
- found2 = found;
- found = -1;
- break;
- }
- }
- }
- if (found >= 0)
- return found;
- found = -1;
- for (int i = 0; Displays[i].monitorname; i++) {
- struct MultiDisplay *md = &Displays[i];
- if (mode == 1 && md->adapterid[0] == '\\')
- continue;
- if (mode == 2 && md->adapterid[0] != '\\')
- continue;
- if (!_tcscmp (md->adapterid, name)) {
- if (found < 0) {
- found = i + 1;
- } else {
- if (found2 < 0)
- found2 = found;
- found = -1;
- break;
- }
- }
- }
- if (found >= 0)
- return found;
- for (int i = 0; Displays[i].monitorname; i++) {
- struct MultiDisplay *md = &Displays[i];
- if (mode == 1 && md->adaptername[0] == '\\')
- continue;
- if (mode == 2 && md->adaptername[0] != '\\')
- continue;
- if (!_tcscmp (md->adaptername, name)) {
- if (found < 0) {
- found = i + 1;
- } else {
- if (found2 < 0)
- found2 = found;
- found = -1;
- break;
- }
- }
- }
- if (found >= 0)
- return found;
- for (int i = 0; Displays[i].monitorname; i++) {
- struct MultiDisplay *md = &Displays[i];
- if (mode == 1 && md->monitorname[0] == '\\')
- continue;
- if (mode == 2 && md->monitorname[0] != '\\')
- continue;
- if (!_tcscmp (md->monitorname, name)) {
- if (found < 0) {
- found = i + 1;
- } else {
- if (found2 < 0)
- found2 = found;
- found = -1;
- break;
- }
- }
- }
- if (found >= 0)
- return found;
- if (mode == 3) {
- if (found2 >= 0)
- return found2;
- }
- return -1;
- }
- int target_get_display(const TCHAR *name)
- {
- int disp;
- //write_log(_T("target_get_display '%s'\n"), name);
- disp = target_get_display2(name, 0);
- //write_log(_T("Scan 0: %d\n"), disp);
- if (disp >= 0)
- return disp;
- disp = target_get_display2(name, 1);
- //write_log(_T("Scan 1: %d\n"), disp);
- if (disp >= 0)
- return disp;
- disp = target_get_display2(name, 2);
- //write_log(_T("Scan 2: %d\n"), disp);
- if (disp >= 0)
- return disp;
- disp = target_get_display2(name, 3);
- //write_log(_T("Scan 3: %d\n"), disp);
- if (disp >= 0)
- return disp;
- return -1;
- }
- static volatile int waitvblankthread_mode;
- HANDLE waitvblankevent;
- static frame_time_t wait_vblank_timestamp;
- static MultiDisplay *wait_vblank_display;
- static volatile bool vsync_active;
- static bool scanlinecalibrating;
- typedef NTSTATUS(CALLBACK* D3DKMTOPENADAPTERFROMHDC)(D3DKMT_OPENADAPTERFROMHDC*);
- static D3DKMTOPENADAPTERFROMHDC pD3DKMTOpenAdapterFromHdc;
- typedef NTSTATUS(CALLBACK* D3DKMTGETSCANLINE)(D3DKMT_GETSCANLINE*);
- static D3DKMTGETSCANLINE pD3DKMTGetScanLine;
- typedef NTSTATUS(CALLBACK* D3DKMTWAITFORVERTICALBLANKEVENT)(const D3DKMT_WAITFORVERTICALBLANKEVENT*);
- static D3DKMTWAITFORVERTICALBLANKEVENT pD3DKMTWaitForVerticalBlankEvent;
- #define STATUS_SUCCESS ((NTSTATUS)0)
- static int target_get_display_scanline2(int displayindex)
- {
- if (pD3DKMTGetScanLine) {
- D3DKMT_GETSCANLINE sl = { 0 };
- struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
- if (!md->HasAdapterData)
- return -11;
- sl.VidPnSourceId = md->VidPnSourceId;
- sl.hAdapter = md->AdapterHandle;
- NTSTATUS status = pD3DKMTGetScanLine(&sl);
- if (status == STATUS_SUCCESS) {
- if (sl.InVerticalBlank)
- return -1;
- return sl.ScanLine;
- } else {
- if ((int)status > 0)
- return -(int)status;
- return status;
- }
- return -12;
- } else if (D3D_getscanline) {
- int scanline;
- bool invblank;
- if (D3D_getscanline(&scanline, &invblank)) {
- if (invblank)
- return -1;
- return scanline;
- }
- return -14;
- }
- return -13;
- }
- extern uae_u64 spincount;
- bool calculated_scanline = 1;
- int target_get_display_scanline(int displayindex)
- {
- if (!scanlinecalibrating && calculated_scanline) {
- static int lastline;
- float diff = read_processor_time() - wait_vblank_timestamp;
- if (diff < 0)
- return -1;
- int sl = (int)(diff * (vsync_activeheight + (vsync_totalheight - vsync_activeheight) / 10) * vsync_vblank / syncbase);
- if (sl < 0)
- sl = -1;
- return sl;
- } else {
- static uae_u64 lastrdtsc;
- static int lastvpos;
- if (spincount == 0 || currprefs.m68k_speed >= 0) {
- lastrdtsc = 0;
- lastvpos = target_get_display_scanline2(displayindex);
- return lastvpos;
- }
- uae_u64 v = __rdtsc();
- if (lastrdtsc > v)
- return lastvpos;
- lastvpos = target_get_display_scanline2(displayindex);
- lastrdtsc = __rdtsc() + spincount * 4;
- return lastvpos;
- }
- }
- typedef LONG(CALLBACK* QUERYDISPLAYCONFIG)(UINT32, UINT32*, DISPLAYCONFIG_PATH_INFO*, UINT32*, DISPLAYCONFIG_MODE_INFO*, DISPLAYCONFIG_TOPOLOGY_ID*);
- typedef LONG(CALLBACK* GETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*);
- typedef LONG(CALLBACK* DISPLAYCONFIGGETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
- static bool get_display_vblank_params(int displayindex, int *activeheightp, int *totalheightp, float *vblankp, float *hblankp)
- {
- static QUERYDISPLAYCONFIG pQueryDisplayConfig;
- static GETDISPLAYCONFIGBUFFERSIZES pGetDisplayConfigBufferSizes;
- static DISPLAYCONFIGGETDEVICEINFO pDisplayConfigGetDeviceInfo;
- if (!pQueryDisplayConfig)
- pQueryDisplayConfig = (QUERYDISPLAYCONFIG)GetProcAddress(userdll, "QueryDisplayConfig");
- if (!pGetDisplayConfigBufferSizes)
- pGetDisplayConfigBufferSizes = (GETDISPLAYCONFIGBUFFERSIZES)GetProcAddress(userdll, "GetDisplayConfigBufferSizes");
- if (!pDisplayConfigGetDeviceInfo)
- pDisplayConfigGetDeviceInfo = (DISPLAYCONFIGGETDEVICEINFO)GetProcAddress(userdll, "DisplayConfigGetDeviceInfo");
- if (!pQueryDisplayConfig || !pGetDisplayConfigBufferSizes || !pDisplayConfigGetDeviceInfo)
- return false;
- struct MultiDisplay *md = displayindex < 0 ? getdisplay(&currprefs, 0) : &Displays[displayindex];
- UINT32 pathCount, modeCount;
- bool ret = false;
- if (pGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) == ERROR_SUCCESS) {
- DISPLAYCONFIG_PATH_INFO *displayPaths;
- DISPLAYCONFIG_MODE_INFO *displayModes;
- displayPaths = xmalloc(DISPLAYCONFIG_PATH_INFO, pathCount);
- displayModes = xmalloc(DISPLAYCONFIG_MODE_INFO, modeCount);
- if (pQueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, displayPaths, &modeCount, displayModes, NULL) == ERROR_SUCCESS) {
- for (int i = 0; i < pathCount; i++) {
- DISPLAYCONFIG_PATH_INFO *path = &displayPaths[i];
- DISPLAYCONFIG_MODE_INFO *target = &displayModes[path->targetInfo.modeInfoIdx];
- DISPLAYCONFIG_MODE_INFO *source = &displayModes[path->sourceInfo.modeInfoIdx];
- DISPLAYCONFIG_SOURCE_DEVICE_NAME dcsdn;
- DISPLAYCONFIG_DEVICE_INFO_HEADER *dcdih = &dcsdn.header;
- dcdih->size = sizeof dcsdn;
- dcdih->adapterId = source->adapterId;
- dcdih->id = source->id;
- dcdih->type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
- if (pDisplayConfigGetDeviceInfo(dcdih) == ERROR_SUCCESS) {
- if (!_tcscmp(md->adapterid, dcsdn.viewGdiDeviceName)) {
- DISPLAYCONFIG_VIDEO_SIGNAL_INFO *si = &target->targetMode.targetVideoSignalInfo;
- if (activeheightp)
- *activeheightp = si->activeSize.cy;
- if (totalheightp)
- *totalheightp = si->totalSize.cy;
- float vblank = (float)si->vSyncFreq.Numerator / si->vSyncFreq.Denominator;
- float hblank = (float)si->hSyncFreq.Numerator / si->hSyncFreq.Denominator;
- if (vblankp)
- *vblankp = vblank;
- if (hblankp)
- *hblankp = hblank;
- write_log(_T("ActiveHeight: %d TotalHeight: %d VFreq=%d/%d=%.2fHz HFreq=%d/%d=%.3fKHz\n"),
- target->targetMode.targetVideoSignalInfo.activeSize.cy,
- target->targetMode.targetVideoSignalInfo.totalSize.cy,
- target->targetMode.targetVideoSignalInfo.vSyncFreq.Numerator,
- target->targetMode.targetVideoSignalInfo.vSyncFreq.Denominator,
- vblank,
- target->targetMode.targetVideoSignalInfo.hSyncFreq.Numerator,
- target->targetMode.targetVideoSignalInfo.hSyncFreq.Denominator,
- hblank / 1000.0);
- ret = true;
- break;
- }
- }
- }
- }
- xfree(displayModes);
- xfree(displayPaths);
- }
- return ret;
- }
- static unsigned int __stdcall waitvblankthread(void *dummy)
- {
- waitvblankthread_mode = 2;
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
- while (waitvblankthread_mode) {
- D3DKMT_WAITFORVERTICALBLANKEVENT e = { 0 };
- e.hAdapter = wait_vblank_display->AdapterHandle;
- e.VidPnSourceId = wait_vblank_display->VidPnSourceId;
- pD3DKMTWaitForVerticalBlankEvent(&e);
- wait_vblank_timestamp = read_processor_time();
- vsync_active = true;
- SetEvent(waitvblankevent);
- }
- waitvblankthread_mode = -1;
- return 0;
- }
- static void display_vblank_thread_kill(void)
- {
- if (waitvblankthread_mode == 2) {
- waitvblankthread_mode = 0;
- while (waitvblankthread_mode != -1) {
- Sleep(10);
- }
- waitvblankthread_mode = 0;
- CloseHandle(waitvblankevent);
- waitvblankevent = NULL;
- }
- }
- static void display_vblank_thread(struct AmigaMonitor *mon)
- {
- struct amigadisplay *ad = &adisplays[mon->monitor_id];
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
- if (waitvblankthread_mode > 0)
- return;
- // It seems some Windows 7 drivers stall if D3DKMTWaitForVerticalBlankEvent()
- // and D3DKMTGetScanLine() is used simultaneously.
- if ((calculated_scanline || os_win8) && ap->gfx_vsyncmode && pD3DKMTWaitForVerticalBlankEvent && wait_vblank_display && wait_vblank_display->HasAdapterData) {
- waitvblankevent = CreateEvent(NULL, FALSE, FALSE, NULL);
- waitvblankthread_mode = 1;
- unsigned int th;
- _beginthreadex(NULL, 0, waitvblankthread, 0, 0, &th);
- } else {
- calculated_scanline = 0;
- }
- }
- void target_cpu_speed(void)
- {
- display_vblank_thread(&AMonitors[0]);
- }
- extern void target_calibrate_spin(void);
- static void display_param_init(struct AmigaMonitor *mon)
- {
- struct amigadisplay *ad = &adisplays[mon->monitor_id];
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
- vsync_activeheight = mon->currentmode.current_height;
- vsync_totalheight = vsync_activeheight * 1125 / 1080;
- vsync_vblank = 0;
- vsync_hblank = 0;
- get_display_vblank_params(-1, &vsync_activeheight, &vsync_totalheight, &vsync_vblank, &vsync_hblank);
- if (vsync_vblank <= 0)
- vsync_vblank = mon->currentmode.freq;
- // GPU scaled mode?
- if (vsync_activeheight > mon->currentmode.current_height) {
- float m = (float)vsync_activeheight / mon->currentmode.current_height;
- vsync_hblank = (int)(vsync_hblank / m + 0.5);
- vsync_activeheight = mon->currentmode.current_height;
- }
- wait_vblank_display = getdisplay(&currprefs, mon->monitor_id);
- if (!wait_vblank_display || !wait_vblank_display->HasAdapterData) {
- write_log(_T("Selected display mode does not have adapter data!\n"));
- }
- Sleep(10);
- scanlinecalibrating = true;
- target_calibrate_spin();
- scanlinecalibrating = false;
- display_vblank_thread(mon);
- }
- const TCHAR *target_get_display_name (int num, bool friendlyname)
- {
- if (num <= 0)
- return NULL;
- struct MultiDisplay *md = getdisplay2(NULL, num - 1);
- if (!md)
- return NULL;
- if (friendlyname)
- return md->monitorname;
- return md->monitorid;
- }
- void centerdstrect(struct AmigaMonitor *mon, RECT *dr)
- {
- struct uae_filter *usedfilter = mon->usedfilter;
- if(!(mon->currentmode.flags & (DM_DX_FULLSCREEN | DM_D3D_FULLSCREEN | DM_W_FULLSCREEN)))
- OffsetRect (dr, mon->amigawin_rect.left, mon->amigawin_rect.top);
- if (mon->currentmode.flags & DM_W_FULLSCREEN) {
- if (mon->scalepicasso && mon->screen_is_picasso)
- return;
- if (usedfilter && !mon->screen_is_picasso)
- return;
- if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
- return;
- OffsetRect (dr, (mon->currentmode.native_width - mon->currentmode.current_width) / 2,
- (mon->currentmode.native_height - mon->currentmode.current_height) / 2);
- }
- }
- static int picasso_offset_x, picasso_offset_y;
- static float picasso_offset_mx, picasso_offset_my;
- void getgfxoffset(int monid, float *dxp, float *dyp, float *mxp, float *myp)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct amigadisplay *ad = &adisplays[monid];
- struct uae_filter *usedfilter = mon->usedfilter;
- float dx, dy, mx, my;
- getfilteroffset(monid, &dx, &dy, &mx, &my);
- if (ad->picasso_on) {
- dx = picasso_offset_x * picasso_offset_mx;
- dy = picasso_offset_y * picasso_offset_my;
- mx = picasso_offset_mx;
- my = picasso_offset_my;
- }
- //write_log(_T("%.2fx%.2f %.2fx%.2f\n"), dx, dy, mx, my);
- if (mon->currentmode.flags & DM_W_FULLSCREEN) {
- for (;;) {
- if (mon->scalepicasso && mon->screen_is_picasso)
- break;
- if (usedfilter && !mon->screen_is_picasso)
- break;
- if (mon->currentmode.fullfill && (mon->currentmode.current_width > mon->currentmode.native_width || mon->currentmode.current_height > mon->currentmode.native_height))
- break;
- dx += (mon->currentmode.native_width - mon->currentmode.current_width) / 2;
- dy += (mon->currentmode.native_height - mon->currentmode.current_height) / 2;
- break;
- }
- }
- *dxp = dx;
- *dyp = dy;
- *mxp = 1.0 / mx;
- *myp = 1.0 / my;
- }
- void DX_Fill(struct AmigaMonitor *mon, int dstx, int dsty, int width, int height, uae_u32 color)
- {
- RECT dstrect;
- if (width < 0)
- width = mon->currentmode.current_width;
- if (height < 0)
- height = mon->currentmode.current_height;
- SetRect (&dstrect, dstx, dsty, dstx + width, dsty + height);
- DirectDraw_Fill (&dstrect, color);
- }
- static int rgbformat_bits (RGBFTYPE t)
- {
- unsigned long f = 1 << t;
- return ((f & RGBMASK_8BIT) != 0 ? 8
- : (f & RGBMASK_15BIT) != 0 ? 15
- : (f & RGBMASK_16BIT) != 0 ? 16
- : (f & RGBMASK_24BIT) != 0 ? 24
- : (f & RGBMASK_32BIT) != 0 ? 32
- : 0);
- }
- int getrefreshrate(int monid, int width, int height)
- {
- struct amigadisplay *ad = &adisplays[monid];
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
- int freq = 0;
-
- if (ap->gfx_refreshrate <= 0)
- return 0;
-
- struct MultiDisplay *md = getdisplay(&currprefs, monid);
- for (int i = 0; md->DisplayModes[i].depth >= 0; i++) {
- struct PicassoResolution *pr = &md->DisplayModes[i];
- if (pr->res.width == width && pr->res.height == height) {
- for (int j = 0; pr->refresh[j] > 0; j++) {
- if (pr->refresh[j] == ap->gfx_refreshrate)
- return ap->gfx_refreshrate;
- if (pr->refresh[j] > freq && pr->refresh[j] < ap->gfx_refreshrate)
- freq = pr->refresh[j];
- }
- }
- }
- write_log (_T("Refresh rate %d not supported, using %d\n"), ap->gfx_refreshrate, freq);
- return freq;
- }
- static int set_ddraw_2(struct AmigaMonitor *mon)
- {
- struct amigadisplay *ad = &adisplays[mon->monitor_id];
- struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
- HRESULT ddrval;
- int bits = (mon->currentmode.current_depth + 7) & ~7;
- int width = mon->currentmode.native_width;
- int height = mon->currentmode.native_height;
- int dxfullscreen, wfullscreen, dd;
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[APMODE_RTG] : &currprefs.gfx_apmode[APMODE_NATIVE];
- int freq = ap->gfx_refreshrate;
- dxfullscreen = (mon->currentmode.flags & DM_DX_FULLSCREEN) ? TRUE : FALSE;
- wfullscreen = (mon->currentmode.flags & DM_W_FULLSCREEN) ? TRUE : FALSE;
- dd = (mon->currentmode.flags & DM_DDRAW) ? TRUE : FALSE;
- if (WIN32GFX_IsPicassoScreen(mon) && (state->Width > width || state->Height > height)) {
- width = state->Width;
- height = state->Height;
- }
- DirectDraw_FreeMainSurface ();
- if (!dd && !dxfullscreen)
- return 1;
- ddrval = DirectDraw_SetCooperativeLevel (mon->hAmigaWnd, dxfullscreen, TRUE);
- if (FAILED (ddrval))
- goto oops;
- if (dxfullscreen) {
- for (;;) {
- HRESULT olderr;
- freq = getrefreshrate(mon->monitor_id, width, height);
- write_log (_T("set_ddraw: trying %dx%d, bits=%d, refreshrate=%d\n"), width, height, bits, freq);
- ddrval = DirectDraw_SetDisplayMode (width, height, bits, freq);
- if (SUCCEEDED (ddrval))
- break;
- olderr = ddrval;
- if (freq) {
- write_log (_T("set_ddraw: failed, trying without forced refresh rate\n"));
- freq = 0;
- DirectDraw_SetCooperativeLevel (mon->hAmigaWnd, dxfullscreen, TRUE);
- ddrval = DirectDraw_SetDisplayMode (width, height, bits, freq);
- if (SUCCEEDED (ddrval))
- break;
- }
- if (olderr != DDERR_INVALIDMODE && olderr != 0x80004001 && olderr != DDERR_UNSUPPORTEDMODE)
- goto oops;
- return -1;
- }
- mon->currentmode.freq = freq;
- updatewinrect(mon, true);
- }
- if (dd) {
- ddrval = DirectDraw_CreateClipper ();
- if (FAILED (ddrval))
- goto oops;
- ddrval = DirectDraw_CreateMainSurface (width, height);
- if (FAILED(ddrval)) {
- write_log (_T("set_ddraw: couldn't CreateSurface() for primary because %s.\n"), DXError (ddrval));
- goto oops;
- }
- ddrval = DirectDraw_SetClipper(mon->hAmigaWnd);
- if (FAILED (ddrval))
- goto oops;
- if (DirectDraw_SurfaceLock ()) {
- mon->currentmode.pitch = DirectDraw_GetSurfacePitch ();
- DirectDraw_SurfaceUnlock ();
- }
- }
- write_log (_T("set_ddraw: %dx%d@%d-bytes\n"), width, height, bits);
- return 1;
- oops:
- return 0;
- }
- static void addmode (struct MultiDisplay *md, DEVMODE *dm, int rawmode)
- {
- int ct;
- int i, j;
- int w = dm->dmPelsWidth;
- int h = dm->dmPelsHeight;
- int d = dm->dmBitsPerPel;
- bool lace = false;
- int freq = 0;
- if (w > max_uae_width || h > max_uae_height) {
- write_log (_T("Ignored mode %d*%d\n"), w, h);
- return;
- }
- if (dm->dmFields & DM_DISPLAYFREQUENCY) {
- freq = dm->dmDisplayFrequency;
- if (freq < 10)
- freq = 0;
- }
- if (dm->dmFields & DM_DISPLAYFLAGS) {
- lace = (dm->dmDisplayFlags & DM_INTERLACED) != 0;
- }
- ct = 0;
- if (d == 8)
- ct = RGBMASK_8BIT;
- if (d == 15)
- ct = RGBMASK_15BIT;
- if (d == 16)
- ct = RGBMASK_16BIT;
- if (d == 24)
- ct = RGBMASK_24BIT;
- if (d == 32)
- ct = RGBMASK_32BIT;
- if (ct == 0)
- return;
- d /= 8;
- i = 0;
- while (md->DisplayModes[i].depth >= 0) {
- if (md->DisplayModes[i].depth == d && md->DisplayModes[i].res.width == w && md->DisplayModes[i].res.height == h) {
- for (j = 0; j < MAX_REFRESH_RATES; j++) {
- if (md->DisplayModes[i].refresh[j] == 0 || md->DisplayModes[i].refresh[j] == freq)
- break;
- }
- if (j < MAX_REFRESH_RATES) {
- md->DisplayModes[i].refresh[j] = freq;
- md->DisplayModes[i].refreshtype[j] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
- md->DisplayModes[i].refresh[j + 1] = 0;
- if (!lace)
- md->DisplayModes[i].lace = false;
- return;
- }
- }
- i++;
- }
- i = 0;
- while (md->DisplayModes[i].depth >= 0)
- i++;
- if (i >= MAX_PICASSO_MODES - 1)
- return;
- md->DisplayModes[i].rawmode = rawmode;
- md->DisplayModes[i].lace = lace;
- md->DisplayModes[i].res.width = w;
- md->DisplayModes[i].res.height = h;
- md->DisplayModes[i].depth = d;
- md->DisplayModes[i].refresh[0] = freq;
- md->DisplayModes[i].refreshtype[0] = (lace ? REFRESH_RATE_LACE : 0) | (rawmode ? REFRESH_RATE_RAW : 0);
- md->DisplayModes[i].refresh[1] = 0;
- md->DisplayModes[i].colormodes = ct;
- md->DisplayModes[i + 1].depth = -1;
- _stprintf (md->DisplayModes[i].name, _T("%dx%d%s, %d-bit"),
- md->DisplayModes[i].res.width, md->DisplayModes[i].res.height,
- lace ? _T("i") : _T(""),
- md->DisplayModes[i].depth * 8);
- }
- static int _cdecl resolution_compare (const void *a, const void *b)
- {
- struct PicassoResolution *ma = (struct PicassoResolution *)a;
- struct PicassoResolution *mb = (struct PicassoResolution *)b;
- if (ma->res.width < mb->res.width)
- return -1;
- if (ma->res.width > mb->res.width)
- return 1;
- if (ma->res.height < mb->res.height)
- return -1;
- if (ma->res.height > mb->res.height)
- return 1;
- return ma->depth - mb->depth;
- }
- static void sortmodes (struct MultiDisplay *md)
- {
- int i, idx = -1;
- int pw = -1, ph = -1;
- i = 0;
- while (md->DisplayModes[i].depth >= 0)
- i++;
- qsort (md->DisplayModes, i, sizeof (struct PicassoResolution), resolution_compare);
- for (i = 0; md->DisplayModes[i].depth >= 0; i++) {
- int j, k;
- for (j = 0; md->DisplayModes[i].refresh[j]; j++) {
- for (k = j + 1; md->DisplayModes[i].refresh[k]; k++) {
- if (md->DisplayModes[i].refresh[j] > md->DisplayModes[i].refresh[k]) {
- int t = md->DisplayModes[i].refresh[j];
- md->DisplayModes[i].refresh[j] = md->DisplayModes[i].refresh[k];
- md->DisplayModes[i].refresh[k] = t;
- t = md->DisplayModes[i].refreshtype[j];
- md->DisplayModes[i].refreshtype[j] = md->DisplayModes[i].refreshtype[k];
- md->DisplayModes[i].refreshtype[k] = t;
- }
- }
- }
- if (md->DisplayModes[i].res.height != ph || md->DisplayModes[i].res.width != pw) {
- ph = md->DisplayModes[i].res.height;
- pw = md->DisplayModes[i].res.width;
- idx++;
- }
- md->DisplayModes[i].residx = idx;
- }
- }
- #if 0
- static void sortmonitors (void)
- {
- for (int i = 0; Displays[i].monitorid; i++) {
- for (int j = i + 1; Displays[j].monitorid; j++) {
- int comp = (Displays[j].primary ? 1 : 0) - (Displays[i].primary ? 1 : 0);
- if (!comp)
- comp = _tcsicmp (Displays[i].adapterid, Displays[j].adapterid);
- if (comp > 0) {
- struct MultiDisplay md;
- memcpy (&md, &Displays[i], sizeof MultiDisplay);
- memcpy (&Displays[i], &Displays[j], sizeof MultiDisplay);
- memcpy (&Displays[j], &md, sizeof MultiDisplay);
- }
- }
- }
- }
- #endif
- static void modesList (struct MultiDisplay *md)
- {
- int i, j;
- i = 0;
- while (md->DisplayModes[i].depth >= 0) {
- write_log (_T("%d: %s%s ("), i, md->DisplayModes[i].rawmode ? _T("!") : _T(""), md->DisplayModes[i].name);
- j = 0;
- while (md->DisplayModes[i].refresh[j] > 0) {
- if (j > 0)
- write_log (_T(","));
- if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_RAW)
- write_log (_T("!"));
- write_log (_T("%d"), md->DisplayModes[i].refresh[j]);
- if (md->DisplayModes[i].refreshtype[j] & REFRESH_RATE_LACE)
- write_log (_T("i"));
- j++;
- }
- write_log (_T(")\n"));
- i++;
- }
- }
- static void adjustappbar(RECT *monitor, RECT *workrect)
- {
- if (!os_vista)
- return;
- APPBARDATA abd;
- // Isn't this ugly API?
- for (int i = 0; i < 4; i++) {
- abd.cbSize = sizeof abd;
- abd.rc = *monitor;
- abd.uEdge = i; // ABE_LEFT, TOP, RIGHT, BOTTOM
- HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &abd);
- if (hwndAutoHide == NULL)
- continue;
- WINDOWINFO wi;
- wi.cbSize = sizeof wi;
- if (!GetWindowInfo(hwndAutoHide, &wi))
- continue;
- int edge;
- switch (i)
- {
- case ABE_LEFT:
- edge = monitor->left + (wi.rcWindow.right - wi.rcWindow.left);
- if (edge > workrect->left && edge < workrect->right)
- workrect->left = edge;
- break;
- case ABE_RIGHT:
- edge = monitor->right - (wi.rcWindow.right - wi.rcWindow.left);
- if (edge < workrect->right && edge > workrect->left)
- workrect->right = edge;
- break;
- case ABE_TOP:
- edge = monitor->top + (wi.rcWindow.bottom - wi.rcWindow.top);
- if (edge > workrect->top && edge < workrect->bottom)
- workrect->top = edge;
- break;
- case ABE_BOTTOM:
- edge = monitor->bottom - (wi.rcWindow.bottom - wi.rcWindow.top);
- if (edge < workrect->bottom && edge > workrect->top)
- workrect->bottom = edge;
- break;
- }
- }
- }
- static BOOL CALLBACK monitorEnumProc (HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
- {
- struct MultiDisplay *md = Displays;
- MONITORINFOEX lpmi;
- lpmi.cbSize = sizeof lpmi;
- GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
- while (md - Displays < MAX_DISPLAYS && md->monitorid) {
- if (!_tcscmp (md->adapterid, lpmi.szDevice)) {
- TCHAR tmp[1000];
- md->monitor = h;
- md->rect = lpmi.rcMonitor;
- md->workrect = lpmi.rcWork;
- adjustappbar(&md->rect, &md->workrect);
- if (md->rect.left == 0 && md->rect.top == 0)
- _stprintf (tmp, _T("%s (%d*%d)"), md->monitorname, md->rect.right - md->rect.left, md->rect.bottom - md->rect.top);
- else
- _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);
- if (md->primary)
- _tcscat (tmp, _T(" *"));
- xfree (md->fullname);
- md->fullname = my_strdup (tmp);
- return TRUE;
- }
- md++;
- }
- return TRUE;
- }
- static BOOL CALLBACK monitorEnumProc2(HMONITOR h, HDC hdc, LPRECT rect, LPARAM data)
- {
- MONITORINFOEX lpmi;
- lpmi.cbSize = sizeof lpmi;
- GetMonitorInfo(h, (LPMONITORINFO)&lpmi);
- for (int i = 0; i < MAX_DISPLAYS && Displays[i].monitorid; i++) {
- struct MultiDisplay *md = &Displays[i];
- if (!_tcscmp (md->adapterid, lpmi.szDevice) && !memcmp(&md->rect, &lpmi.rcMonitor, sizeof RECT)) {
- md->workrect = lpmi.rcWork;
- md->monitor = h;
- adjustappbar(&md->rect, &md->workrect);
- return TRUE;
- }
- }
- return TRUE;
- }
- void reenumeratemonitors(void)
- {
- for (int i = 0; i < MAX_DISPLAYS; i++) {
- struct MultiDisplay *md = &Displays[i];
- memcpy(&md->workrect, &md->rect, sizeof RECT);
- }
- EnumDisplayMonitors (NULL, NULL, monitorEnumProc2, NULL);
- }
- static void getd3dmonitornames (void)
- {
- struct MultiDisplay *md = Displays;
- IDirect3D9 *d3d;
- int max;
- // XP does not support hybrid displays, don't load Direct3D
- if (!os_vista)
- return;
- d3d = Direct3DCreate9 (D3D_SDK_VERSION);
- if (!d3d)
- return;
- max = d3d->GetAdapterCount ();
- while (md - Displays < MAX_DISPLAYS && md->monitorid) {
- POINT pt;
- HMONITOR winmon;
- pt.x = (md->rect.right - md->rect.left) / 2 + md->rect.left;
- pt.y = (md->rect.bottom - md->rect.top) / 2 + md->rect.top;
- winmon = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
- for (int i = 0; i < max; i++) {
- D3DADAPTER_IDENTIFIER9 did;
- HMONITOR d3dmon = d3d->GetAdapterMonitor (i);
- if (d3dmon != winmon)
- continue;
- if (SUCCEEDED (d3d->GetAdapterIdentifier (i, 0, &did))) {
- TCHAR *name = au (did.Description);
- my_trim (name);
- if (_tcsicmp (name, md->adaptername)) {
- write_log (_T("%d: '%s' -> '%s'\n"), i, md->adaptername, name);
- xfree (md->adaptername);
- md->adaptername = name;
- name = NULL;
- }
- xfree (name);
- }
- break;
- }
- md++;
- }
- d3d->Release ();
- }
- static bool enumeratedisplays2 (bool selectall)
- {
- struct MultiDisplay *md = Displays;
- int adapterindex = 0;
- DISPLAY_DEVICE add;
- add.cb = sizeof add;
- while (EnumDisplayDevices (NULL, adapterindex, &add, 0)) {
- adapterindex++;
- if (!selectall) {
- if (!(add.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
- continue;
- if (add.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
- continue;
- }
- if (md - Displays >= MAX_DISPLAYS)
- break;
- int monitorindex = 0;
- DISPLAY_DEVICE mdd;
- mdd.cb = sizeof mdd;
- while (EnumDisplayDevices (add.DeviceName, monitorindex, &mdd, 0)) {
- monitorindex++;
- if (md - Displays >= MAX_DISPLAYS)
- break;
- if (!selectall) {
- if (!(mdd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
- continue;
- if (mdd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
- continue;
- }
- md->adaptername = my_strdup_trim (add.DeviceString);
- md->adapterid = my_strdup (add.DeviceName);
- md->adapterkey = my_strdup (add.DeviceID);
- md->monitorname = my_strdup_trim (mdd.DeviceString);
- md->monitorid = my_strdup (mdd.DeviceKey);
- if (add.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- md->primary = true;
- if (pD3DKMTOpenAdapterFromHdc) {
- HDC hdc = CreateDC(NULL, add.DeviceName, NULL, NULL);
- if (hdc != NULL) {
- D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = { 0 };
- OpenAdapterData.hDc = hdc;
- NTSTATUS status = pD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
- if (status == STATUS_SUCCESS) {
- md->AdapterLuid = OpenAdapterData.AdapterLuid;
- md->VidPnSourceId = OpenAdapterData.VidPnSourceId;
- md->AdapterHandle = OpenAdapterData.hAdapter;
- md->HasAdapterData = true;
- }
- DeleteDC(hdc);
- }
- }
- md++;
- }
- if (md - Displays >= MAX_DISPLAYS)
- return true;
- if (monitorindex == 0) {
- md->adaptername = my_strdup_trim (add.DeviceString);
- md->adapterid = my_strdup (add.DeviceName);
- md->adapterkey = my_strdup (add.DeviceID);
- md->monitorname = my_strdup_trim (add.DeviceString);
- md->monitorid = my_strdup (add.DeviceKey);
- md->primary = true;
- md++;
- }
- }
- if (md == Displays)
- return false;
- EnumDisplayMonitors (NULL, NULL, monitorEnumProc, NULL);
- md = Displays;
- while (md->monitorname) {
- if (!md->fullname)
- md->fullname = my_strdup (md->adapterid);
- md++;
- }
- getd3dmonitornames ();
- //sortmonitors ();
- return true;
- }
- void enumeratedisplays (void)
- {
- if (!pD3DKMTWaitForVerticalBlankEvent) {
- pD3DKMTOpenAdapterFromHdc = (D3DKMTOPENADAPTERFROMHDC)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTOpenAdapterFromHdc");
- pD3DKMTGetScanLine = (D3DKMTGETSCANLINE)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTGetScanLine");
- pD3DKMTWaitForVerticalBlankEvent = (D3DKMTWAITFORVERTICALBLANKEVENT)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")), "D3DKMTWaitForVerticalBlankEvent");
- }
- if (!enumeratedisplays2 (false))
- enumeratedisplays2(true);
- }
- void sortdisplays (void)
- {
- struct MultiDisplay *md;
- int i, idx;
- int w = GetSystemMetrics (SM_CXSCREEN);
- int h = GetSystemMetrics (SM_CYSCREEN);
- int wv = GetSystemMetrics(SM_CXVIRTUALSCREEN);
- int hv = GetSystemMetrics(SM_CYVIRTUALSCREEN);
- int b = 0;
-
- deskhz = 0;
- HDC hdc = GetDC (NULL);
- if (hdc) {
- b = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
- ReleaseDC (NULL, hdc);
- }
- md = Displays;
- while (md->monitorname) {
- md->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
- md->DisplayModes[0].depth = -1;
- write_log (_T("%s '%s' [%s]\n"), md->adaptername, md->adapterid, md->adapterkey);
- write_log (_T("-: %s [%s]\n"), md->fullname, md->monitorid);
- for (int mode = 0; mode < 2; mode++) {
- DEVMODE dm;
- dm.dmSize = sizeof dm;
- dm.dmDriverExtra = 0;
- idx = 0;
- while (EnumDisplaySettingsEx (md->adapterid, idx, &dm, mode ? EDS_RAWMODE : 0)) {
- int found = 0;
- int idx2 = 0;
- while (md->DisplayModes[idx2].depth >= 0 && !found) {
- struct PicassoResolution *pr = &md->DisplayModes[idx2];
- if (dm.dmPelsWidth == w && dm.dmPelsHeight == h && dm.dmBitsPerPel == b) {
- if (dm.dmDisplayFrequency > deskhz)
- deskhz = dm.dmDisplayFrequency;
- }
- if (pr->res.width == dm.dmPelsWidth && pr->res.height == dm.dmPelsHeight && pr->depth == dm.dmBitsPerPel / 8) {
- for (i = 0; pr->refresh[i]; i++) {
- if (pr->refresh[i] == dm.dmDisplayFrequency) {
- found = 1;
- break;
- }
- }
- }
- idx2++;
- }
- if (!found && dm.dmBitsPerPel > 8) {
- int freq = 0;
- #if 0
- write_log (_T("EnumDisplaySettings(%dx%dx%d %dHz %08x)\n"),
- dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency, dm.dmFields);
- #endif
- if ((dm.dmFields & DM_PELSWIDTH) && (dm.dmFields & DM_PELSHEIGHT) && (dm.dmFields & DM_BITSPERPEL)) {
- addmode (md, &dm, mode);
- }
- }
- idx++;
- }
- }
- //dhack();
- sortmodes (md);
- modesList (md);
- i = 0;
- while (md->DisplayModes[i].depth > 0)
- i++;
- write_log (_T("%d display modes.\n"), i);
- md++;
- }
- write_log(_T("Desktop: W=%d H=%d B=%d HZ=%d. CXVS=%d CYVS=%d\n"), w, h, b, deskhz, wv, hv);
- }
- /* DirectX will fail with "Mode not supported" if we try to switch to a full
- * screen mode that doesn't match one of the dimensions we got during enumeration.
- * So try to find a best match for the given resolution in our list. */
- int WIN32GFX_AdjustScreenmode (struct MultiDisplay *md, int *pwidth, int *pheight, int *ppixbits)
- {
- struct PicassoResolution *best;
- uae_u32 selected_mask = (*ppixbits == 8 ? RGBMASK_8BIT
- : *ppixbits == 15 ? RGBMASK_15BIT
- : *ppixbits == 16 ? RGBMASK_16BIT
- : *ppixbits == 24 ? RGBMASK_24BIT
- : RGBMASK_32BIT);
- int pass, i = 0, index = 0;
- for (pass = 0; pass < 2; pass++) {
- struct PicassoResolution *dm;
- uae_u32 mask = (pass == 0
- ? selected_mask
- : RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT); /* %%% - BERND, were you missing 15-bit here??? */
- i = 0;
- index = 0;
- best = &md->DisplayModes[0];
- dm = &md->DisplayModes[1];
- while (dm->depth >= 0) {
- /* do we already have supported resolution? */
- if (dm->res.width == *pwidth && dm->res.height == *pheight && dm->depth == (*ppixbits / 8))
- return i;
- if ((dm->colormodes & mask) != 0) {
- if (dm->res.width <= best->res.width && dm->res.height <= best->res.height
- && dm->res.width >= *pwidth && dm->res.height >= *pheight)
- {
- best = dm;
- index = i;
- }
- if (dm->res.width >= best->res.width && dm->res.height >= best->res.height
- && dm->res.width <= *pwidth && dm->res.height <= *pheight)
- {
- best = dm;
- index = i;
- }
- }
- dm++;
- i++;
- }
- if (best->res.width == *pwidth && best->res.height == *pheight) {
- selected_mask = mask; /* %%% - BERND, I added this - does it make sense? Otherwise, I'd specify a 16-bit display-mode for my
- Workbench (using -H 2, but SHOULD have been -H 1), and end up with an 8-bit mode instead*/
- break;
- }
- }
- *pwidth = best->res.width;
- *pheight = best->res.height;
- if (best->colormodes & selected_mask)
- return index;
- /* Ordering here is done such that 16-bit is preferred, followed by 15-bit, 8-bit, 32-bit and 24-bit */
- if (best->colormodes & RGBMASK_16BIT)
- *ppixbits = 16;
- else if (best->colormodes & RGBMASK_15BIT) /* %%% - BERND, this possibility was missing? */
- *ppixbits = 15;
- else if (best->colormodes & RGBMASK_8BIT)
- *ppixbits = 8;
- else if (best->colormodes & RGBMASK_32BIT)
- *ppixbits = 32;
- else if (best->colormodes & RGBMASK_24BIT)
- *ppixbits = 24;
- else
- index = -1;
- return index;
- }
- #if 0
- static int flushymin, flushymax;
- #define FLUSH_DIFF 50
- static void flushit (struct vidbuffer *vb, int lineno)
- {
- if (!currprefs.gfx_api)
- return;
- if (mon->currentmode.flags & DM_SWSCALE)
- return;
- if (flushymin > lineno) {
- if (flushymin - lineno > FLUSH_DIFF && flushymax != 0) {
- D3D_flushtexture (flushymin, flushymax);
- flushymin = mon->currentmode.amiga_height;
- flushymax = 0;
- } else {
- flushymin = lineno;
- }
- }
- if (flushymax < lineno) {
- if (lineno - flushymax > FLUSH_DIFF && flushymax != 0) {
- D3D_flushtexture (flushymin, flushymax);
- flushymin = mon->currentmode.amiga_height;
- flushymax = 0;
- } else {
- flushymax = lineno;
- }
- }
- }
- void flush_line (struct vidbuffer *vb, int lineno)
- {
- flushit (vb, lineno);
- }
- void flush_block (struct vidbuffer *vb, int first, int last)
- {
- flushit (vb, first);
- flushit (vb, last);
- }
- void flush_screen (struct vidbuffer *vb, int a, int b)
- {
- }
- #endif
- bool render_screen(int monid, int mode, bool immediate)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct amigadisplay *ad = &adisplays[monid];
- bool v = false;
- int cnt;
- mon->render_ok = false;
- if (minimized || ad->picasso_on || monitor_off || dx_islost ()) {
- return mon->render_ok;
- }
- cnt = 0;
- while (mon->wait_render) {
- sleep_millis (1);
- cnt++;
- if (cnt > 500) {
- return mon->render_ok;
- }
- }
- // flushymin = 0;
- // flushymax = mon->currentmode.amiga_height;
- gfx_lock();
- if (mon->currentmode.flags & DM_D3D) {
- v = D3D_renderframe(monid, mode, immediate);
- } else if (mon->currentmode.flags & DM_SWSCALE) {
- S2X_render(monid, -1, -1);
- v = true;
- } else if (mon->currentmode.flags & DM_DDRAW) {
- v = true;
- }
- mon->render_ok = v;
- gfx_unlock();
- return mon->render_ok;
- }
- bool show_screen_maybe(int monid, bool show)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct amigadisplay *ad = &adisplays[monid];
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
- if (!ap->gfx_vflip || ap->gfx_vsyncmode == 0 || ap->gfx_vsync <= 0) {
- if (show)
- show_screen(monid, 0);
- return false;
- }
- #if 0
- if (ap->gfx_vflip < 0) {
- doflipevent ();
- return true;
- }
- #endif
- return false;
- }
- void show_screen_special (void)
- {
- struct AmigaMonitor *mon = &AMonitors[0];
- if (!mon->screen_is_initialized)
- return;
- if (!D3D_showframe_special)
- return;
- if (mon->currentmode.flags & DM_D3D) {
- gfx_lock();
- D3D_showframe_special(0, 1);
- gfx_unlock();
- }
- }
- static frame_time_t strobo_time;
- static volatile int strobo_active;
- static volatile bool strobo_active2;
- static void CALLBACK blackinsertion_cb(
- UINT uTimerID,
- UINT uMsg,
- DWORD_PTR dwUser,
- DWORD_PTR dw1,
- DWORD_PTR dw2
- )
- {
- struct AmigaMonitor *mon = &AMonitors[0];
- if (mon->screen_is_initialized) {
- if (strobo_active) {
- }
- while (strobo_active) {
- frame_time_t ct = read_processor_time();
- int diff = (int)strobo_time - (int)ct;
- if (diff < -vsynctimebase / 2) {
- break;
- }
- if (diff <= 0) {
- if (strobo_active) {
- gfx_lock();
- D3D_showframe_special(0, 1);
- gfx_unlock();
- }
- break;
- }
- if (diff > vsynctimebase / 4) {
- break;
- }
- }
- }
- strobo_active = 0;
- }
- float target_adjust_vblank_hz(int monid, float hz)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- int maxrate;
- if (!currprefs.lightboost_strobo)
- return hz;
- if (isfullscreen() > 0) {
- maxrate = mon->currentmode.freq;
- } else {
- maxrate = deskhz;
- }
- double nhz = hz * 2.0;
- if (nhz >= maxrate - 1 && nhz < maxrate + 1)
- hz -= 0.5;
- return hz;
- }
- void show_screen(int monid, int mode)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct amigadisplay *ad = &adisplays[monid];
- strobo_active = false;
- strobo_active2 = false;
- struct apmode *ap = ad->picasso_on ? &currprefs.gfx_apmode[1] : &currprefs.gfx_apmode[0];
- gfx_lock();
- if (mode == 2 || mode == 3 || mode == 4) {
- if ((mon->currentmode.flags & DM_D3D) && D3D_showframe_special && ap->gfx_strobo) {
- if (mode == 4) {
- // erase + render
- D3D_showframe_special(0, 2);
- D3D_showframe_special(0, 1);
- } else {
- // erase or render
- D3D_showframe_special(0, mode == 3 ? 2 : 1);
- }
- }
- gfx_unlock();
- return;
- }
- if (mode >= 0 && !mon->render_ok) {
- gfx_unlock();
- return;
- }
- if (mon->currentmode.flags & DM_D3D) {
- if (ap->gfx_strobo && currprefs.gfx_variable_sync) {
- float vblank = vblank_hz;
- int ratio = currprefs.lightboost_strobo_ratio;
- int ms = (int)(1000 / vblank);
- int waitms = ms * ratio / 100 - 1;
- strobo_active = -1;
- strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
- timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
- }
- #if 0
- if (ap->gfx_vsync < 0 && ap->gfx_strobo && currprefs.gfx_api < 2) {
- float vblank = vblank_hz;
- if (WIN32GFX_IsPicassoScreen(mon)) {
- if (currprefs.win32_rtgvblankrate > 0)
- vblank = currprefs.win32_rtgvblankrate;
- }
- bool ok = true;
- int ratio = currprefs.lightboost_strobo_ratio;
- int ms = (int)(1000 / vblank);
- int waitms = ms * ratio / 100 - 1;
- int maxrate;
- if (isfullscreen() > 0) {
- maxrate = mon->currentmode.freq;
- } else {
- maxrate = deskhz;
- }
- if (maxrate > 0) {
- double rate = vblank * 2.0;
- rate *= ratio > 50 ? ratio / 50.0 : 50.0 / ratio;
- if (rate > maxrate + 1.0)
- ok = false;
- }
- if (ok) {
- strobo_time = read_processor_time() + vsynctimebase * ratio / 100;
- strobo_active = true;
- timeSetEvent(waitms, 0, blackinsertion_cb, NULL, TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
- }
- }
- #endif
- D3D_showframe(monid);
- if (monid == 0) {
- strobo_active2 = true;
- if (strobo_active < 0) {
- D3D_showframe_special(0, 2);
- }
- }
- #ifdef GFXFILTER
- } else if (mon->currentmode.flags & DM_SWSCALE) {
- if (!dx_islost () && !ad->picasso_on)
- DirectDraw_Flip(1);
- #endif
- } else if (mon->currentmode.flags & DM_DDRAW) {
- if (!dx_islost () && !ad->picasso_on)
- DirectDraw_Flip(1);
- }
- gfx_unlock();
- mon->render_ok = false;
- }
- static uae_u8 *ddraw_dolock (void)
- {
- struct vidbuf_description *avidinfo = &adisplays[0].gfxvidinfo;
- if (!DirectDraw_SurfaceLock ()) {
- dx_check ();
- return 0;
- }
- avidinfo->outbuffer->bufmem = DirectDraw_GetSurfacePointer ();
- avidinfo->outbuffer->rowbytes = DirectDraw_GetSurfacePitch ();
- init_row_map ();
- clear_inhibit_frame(0, IHF_WINDOWHIDDEN);
- return avidinfo->outbuffer->bufmem;
- }
- bool lockscr3d(struct vidbuffer *vb)
- {
- struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
- if (mon->currentmode.flags & DM_D3D) {
- if (!(mon->currentmode.flags & DM_SWSCALE)) {
- vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, false);
- if (vb->bufmem)
- return true;
- }
- }
- return false;
- }
- void unlockscr3d(struct vidbuffer *vb)
- {
- struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
- if (mon->currentmode.flags & DM_D3D) {
- if (!(mon->currentmode.flags & DM_SWSCALE)) {
- D3D_unlocktexture(vb->monitor_id, -1, -1);
- }
- }
- }
- int lockscr(struct vidbuffer *vb, bool fullupdate, bool first, bool skip)
- {
- struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
- int ret = 0;
- if (!isscreen(mon))
- return ret;
- #if 0
- flushymin = mon->currentmode.amiga_height;
- flushymax = 0;
- #endif
- gfx_lock();
- ret = 1;
- if (mon->currentmode.flags & DM_D3D) {
- #ifdef D3D
- if (mon->currentmode.flags & DM_SWSCALE) {
- ret = 1;
- } else {
- ret = 0;
- vb->bufmem = D3D_locktexture(vb->monitor_id, &vb->rowbytes, NULL, skip ? -1 : (fullupdate ? 1 : 0));
- if (vb->bufmem) {
- if (first)
- init_row_map();
- ret = 1;
- }
- }
- #endif
- } else if (mon->currentmode.flags & DM_SWSCALE) {
- ret = 1;
- } else if (mon->currentmode.flags & DM_DDRAW) {
- ret = ddraw_dolock() != 0;
- }
- gfx_unlock();
- return ret;
- }
- void unlockscr(struct vidbuffer *vb, int y_start, int y_end)
- {
- struct AmigaMonitor *mon = &AMonitors[vb->monitor_id];
- gfx_lock();
- if (mon->currentmode.flags & DM_D3D) {
- if (mon->currentmode.flags & DM_SWSCALE) {
- S2X_render(vb->monitor_id, y_start, y_end);
- } else {
- vb->bufmem = NULL;
- }
- D3D_unlocktexture(vb->monitor_id, y_start, y_end);
- } else if (mon->currentmode.flags & DM_SWSCALE) {
- return;
- } else if (mon->currentmode.flags & DM_DDRAW) {
- DirectDraw_SurfaceUnlock();
- vb->bufmem = NULL;
- }
- gfx_unlock();
- }
- void flush_clear_screen (struct vidbuffer *vb)
- {
- if (!vb)
- return;
- if (lockscr(vb, true, true, false)) {
- int y;
- for (y = 0; y < vb->height_allocated; y++) {
- memset(vb->bufmem + y * vb->rowbytes, 0, vb->width_allocated * vb->pixbytes);
- }
- unlockscr(vb, -1, -1);
- }
- }
- static void DX_Blit96(struct AmigaMonitor *mon, int x, int y, int w, int h)
- {
- struct picasso96_state_struct *state = &picasso96_state[mon->monitor_id];
- RECT dr, sr;
- picasso_offset_x = 0;
- picasso_offset_y = 0;
- picasso_offset_mx = 1.0;
- picasso_offset_my = 1.0;
- if (mon->scalepicasso) {
- int srcratio, dstratio;
- int srcwidth, srcheight;
- if (mon->scalepicasso < 0 || mon->scalepicasso > 1) {
- srcwidth = state->Width;
- srcheight = state->Height;
- } else {
- srcwidth = mon->currentmode.native_width;
- srcheight = mon->currentmode.native_height;
- }
- SetRect (&sr, 0, 0, state->Width, state->Height);
- if (currprefs.win32_rtgscaleaspectratio < 0) {
- // automatic
- srcratio = state->Width * ASPECTMULT / state->Height;
- dstratio = srcwidth * ASPECTMULT / srcheight;
- } else if (currprefs.win32_rtgscaleaspectratio == 0) {
- // none
- srcratio = dstratio = 0;
- } else {
- // manual
- srcratio = currprefs.win32_rtgscaleaspectratio;
- dstratio = srcwidth * ASPECTMULT / srcheight;
- }
- if (srcratio == dstratio) {
- SetRect (&dr, 0, 0, srcwidth, srcheight);
- } else if (srcratio > dstratio) {
- int yy = srcheight - srcheight * dstratio / srcratio;
- SetRect (&dr, 0, yy / 2, srcwidth, srcheight - yy / 2);
- picasso_offset_y = yy / 2;
- } else {
- int xx = srcwidth - srcwidth * srcratio / dstratio;
- SetRect (&dr, xx / 2, 0,srcwidth - xx / 2, srcheight);
- picasso_offset_x = xx / 2;
- }
- picasso_offset_mx = (float)state->Width / (dr.right - dr.left);
- picasso_offset_my = (float)state->Height / (dr.bottom - dr.top);
- DirectDraw_BlitToPrimaryScale (&dr, &sr);
- } else {
- SetRect (&sr, x, y, x + w, y + h);
- DirectDraw_BlitToPrimary (&sr);
- }
- }
- void getrtgfilterrect2(int monid, RECT *sr, RECT *dr, RECT *zr, int dst_width, int dst_height)
- {
- struct AmigaMonitor *mon = &AMonitors[monid];
- struct amigadisplay *ad = &adisplays[monid];
- struct picasso96_state_struct *state = &picasso96_state[monid];
- SetRect (sr, 0, 0, mon->currentmode.native_width, mon->currentmode.native_height);
- SetRect (dr, 0, 0, state->Width, state->Height);
- SetRect (zr, 0, 0, 0, 0);
-
- picasso_offset_x = 0;
- picasso_offset_y = 0;
- picasso_offset_mx = 1.0;
- picasso_offset_my = 1.0;
- if (!ad->picasso_on)
- return;
- if (!mon->scalepicasso)
- return;
- int srcratio, dstratio;
- int srcwidth, srcheight;
- srcwidth = state->Width;
- srcheight = state->Height;
- if (!srcwidth || !srcheight)
- return;
- float mx = (float)mon->currentmode.native_width / srcwidth;
- float my = (float)mon->currentmode.native_height / srcheight;
- if (mon->scalepicasso == RTG_MODE_INTEGER_SCALE) {
- int divx = mon->currentmode.native_width / srcwidth;
- int divy = mon->currentmode.native_height / srcheight;
- int mul = divx > divy ? divy : divx;
- int xx = srcwidth * mul;
- int yy = srcheight * mul;
- SetRect (dr, 0, 0, mon->currentmode.native_width / mul, mon->currentmode.native_height / mul);
- //picasso_offset_x = -(state->Width - xx) / 2;
- //picasso_offset_y = -(mon->currentmode.native_height - srcheight) / 2;
- mx = my = 1.0;
- } else if (mon->scalepicasso == RTG_MODE_CENTER) {
- int xx = (mon->currentmode.native_width - srcwidth) / 2;
- int yy = (mon->currentmode.native_heigh…
Large files files are truncated, but you can click here to view the full file