File: RequestVideo.c

package info (click to toggle)
abuse 2.00-12
  • links: PTS
  • area: main
  • in suites: slink
  • size: 12,708 kB
  • ctags: 15,389
  • sloc: ansic: 115,852; cpp: 6,792; lisp: 2,066; sh: 1,734; makefile: 1,601; asm: 264
file content (700 lines) | stat: -rw-r--r-- 26,304 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
/*------------------------------------------------------------------------------
#
#	MacOS Sample Code
#	
#	Written by: Eric Anderson
#	 AppleLink: ERIC3
#	 AOL: ERICTHREE
#
#	Display Manager sample code
#
#	RequestVideo
#
#	RequestVideo.c	-	C Code
#
#	Copyright  1995 Apple Computer, Inc.
#	All rights reserved.
#
#	5/31/95		ewa		Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
#						to make it easy to revert back to where you came from and to give
#						the user a chance to confirm the new setting if the new mode was
#						valid (ie: the card supports it) but not safe (the monitor may not).
#	5/24/95		ewa		Give the kAllValidModesBit requestFlags option for safe only or all
#						valid resolution timings.
#
#
#
#	Components:	PlayVideo.c			
#				RequestVideo.c		
#				RequestVideo.h		
#				RequestVideo.rsrc		
#
#	RequestVideo demonstrates the usage of the Display Manager introduced
#	with the PowerMacs and integrated into the system under System 7.5. With
#	the RequestVideo sample code library, developers will be able to explore
#	the Display Manager API by changing bit depth and screen resolution on
#	multisync displays on built-in, NuBus, and PCI based video. Display Manager 1.0
#	is built into the Systems included with the first PowerMacs up through System 7.5.
#	Display Manager 2.0 is included with the release of the new PCI based PowerMacs,
#	and will be included in post 7.5 System Software releases. 
#	
#	It is a good idea to reset the screen(s) to the original setting before exit
#	since the call to RVSetVideoAsScreenPrefs() may not do the right thing under
#	Display Manager 1.0 with certain video drivers.
#
#	For information on the use of this sample code, please the documentation in the Read Me file
------------------------------------------------------------------------------*/

#include "RequestVideo.h"

// Internal includes
#include <Dialogs.h>
#include <ROMDefs.h>
#include <Devices.h>
#include <Errors.h>
#include <GestaltEqu.h>
#include <Memory.h>
#include <Palettes.h>
#include <Slots.h>
#include <StdIO.h>
#include <Displays.h>

#include <stdlib.h>

//--------------------------------------------------------------
//
// Internal defines, structs, typedefs, and routine declarations
//
//--------------------------------------------------------------
#define		KMonoDev			0						// false (handy definitions for gdDevType settings)
#define		kColorDev			1						// true
#define		char_Enter			0x03					// for our filter proc
#define		char_Return			0x0D					//
#define		iRevertItem			1						// User buttons
#define		iConfirmItem		2						//
#define		kSecondsToConfirm	8						// seconds before confirm dialog is taken down
#define		rConfirmSwtchAlrt	2735					// ID of alert dialog

struct DepthInfo {
	VDSwitchInfoRec			depthSwitchInfo;			// This is the switch mode to choose this timing/depth
	VPBlock					depthVPBlock;				// VPBlock (including size, depth and format)
};
typedef struct DepthInfo DepthInfo;

struct ListIteratorDataRec {
	VDTimingInfoRec			displayModeTimingInfo;		// Contains timing flags and such
	unsigned long			depthBlockCount;			// How many depths available for a particular timing
	DepthInfo				*depthBlocks;				// Array of DepthInfo
};
typedef struct ListIteratorDataRec ListIteratorDataRec;

void GetRequestTheDM1Way (		VideoRequestRecPtr requestRecPtr,
								GDHandle walkDevice);

void GetRequestTheDM2Way (		VideoRequestRecPtr requestRecPtr,
								GDHandle walkDevice,
								DMDisplayModeListIteratorUPP myModeIteratorProc,
								DMListIndexType theDisplayModeCount,
								DMListType *theDisplayModeList);

pascal void ModeListIterator (	void *userData,
								DMListIndexType itemIndex,
								DMDisplayModeListEntryPtr displaymodeInfo);

Boolean FindBestMatch (			VideoRequestRecPtr requestRecPtr,
								short bitDepth,
								unsigned long horizontal,
								unsigned long vertical);

void GravitateMonitors (void);

pascal Boolean ConfirmAlertFilter (DialogPtr dlg, EventRecord *evt, short *itemHit);

//--------------------------------------------------------------
//
// Implementation of sample code
//
//--------------------------------------------------------------
OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
{
	GDHandle		aMonitor;
	Boolean			displayMgrPresent;
	unsigned long	displayMgrVersion;
	OSErr			err;
	Boolean			isColor;
	long			value = 0;

	Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
	Gestalt(gestaltDisplayMgrAttr,&value);
	displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
	if (displayMgrPresent)
	{
		if (requestRecPtr->displayMode && requestRecPtr->depthMode)
		{
			if (requestRecPtr->availBitDepth == 1)	// Based on avail bit depth, 
				isColor = KMonoDev;					// set the device to a mono device, or
			else isColor = kColorDev;				// set the device to a color device
			SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);		
			
			// see how many monitors we have, aMonitor will be nil if we have only one.
			aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);			// get the first guy
			aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );	// get the next guy
			
			if (nil == aMonitor || displayMgrVersion >= 0x00020000)
			{
				// only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
				// since DM1.0 does not automatically gravitate monitors and our gravitate code
				// is not implemented.
				err = DMSetDisplayMode(	requestRecPtr->screenDevice,	// GDevice
						requestRecPtr->displayMode,						// DM1.0 uses this
						&requestRecPtr->depthMode,						// DM1.0 uses this
						(unsigned long) &(requestRecPtr->switchInfo),	// DM2.0 uses this rather than displayMode/depthMode combo
						nil);
				if (noErr == err)
				{
					// Do the monitor gravitate here if we are using a version less than DM2.0
					if (displayMgrVersion < 0x00020000)
						GravitateMonitors ();
				}
				else if (kDMDriverNotDisplayMgrAwareErr == err)
				{
					// DM not supported by driver, so all we can do is set the bit depth
					err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
				}
			}
			else
			{
				// we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
				err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
			}
			
			return (err);	// we did try to set the request
		}
	}
	return (-1);	// return a generic error
}

// This extern should be removed once this function is formally defined in Displays.h
extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
 THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);

OSErr RVSetVideoAsScreenPrefs (void)
{
	Handle		displaystate;
	Boolean		displayMgrPresent;
	long		value = 0;

	Gestalt(gestaltDisplayMgrAttr,&value);
	displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
	if (displayMgrPresent)
	{
		DMBeginConfigureDisplays (&displaystate);	// Tell the world it is about to change
		DMUseScreenPrefs (true, displaystate);		// Make the change
		DMEndConfigureDisplays (displaystate);		// Tell the world the change is over
		
		return (noErr);	// we (maybe) set the world back to a known setting
	}
	return (-1);	// return a generic error
}

OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
{
	unsigned long		displayMgrVersion;
	OSErr				error = paramErr;
	CntrlParam			pBlock;
	VDSwitchInfoRec		switchInfo;
	AuxDCEHandle		theDCE;
	VDSwitchInfoRec		videoMode;		

	requestRecPtr->availBitDepth			= 0;	// init to default - you can do it if it is important to you
	requestRecPtr->availHorizontal			= 0;
	requestRecPtr->availVertical			= 0;
	requestRecPtr->availFlags				= 0;
	requestRecPtr->displayMode				= -1; 
	requestRecPtr->depthMode				= -1;
	requestRecPtr->switchInfo.csMode		= 0;
	requestRecPtr->switchInfo.csData		= 0;
	requestRecPtr->switchInfo.csPage		= 0;
	requestRecPtr->switchInfo.csBaseAddr	= 0;
	requestRecPtr->switchInfo.csReserved	= 0;
	
	Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
	if (requestRecPtr->screenDevice)
	{
		if (displayMgrVersion >= 0x00020000)
		{	// get the info the DM 2.0 way
			error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
			if (noErr == error)
			{
				requestRecPtr->depthMode			= switchInfo.csMode;
				requestRecPtr->displayMode			= switchInfo.csData; 
				requestRecPtr->switchInfo.csMode	= switchInfo.csMode;
				requestRecPtr->switchInfo.csData	= switchInfo.csData;
			}
			return (error);	// we (maybe) set the world back to a known setting
		}
		else
		{	// get the info the DM 1.0 way
			videoMode.csMode = -1;		// init to bogus value
			videoMode.csData = -1;		// init to bogus value			
			pBlock.ioNamePtr = nil;
			pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
			pBlock.csCode = cscGetCurMode;
			*(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
				
			error = PBStatusSync((ParmBlkPtr )&pBlock);	// ask the driver first....since we trust it the most
				
			if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
				error = statusErr;
			
			if (noErr != error)	// if the driver has no clue fill it videoMode by hand as a last resort
			{	
				theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
				
				if( theDCE )
				{
					videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
					videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
					error = noErr;
				}
			}
			if (noErr == error)	// Set our data
			{
				requestRecPtr->displayMode			= videoMode.csData; 
				requestRecPtr->depthMode			= videoMode.csMode;
				requestRecPtr->switchInfo.csMode	= videoMode.csMode;
				requestRecPtr->switchInfo.csData	= videoMode.csData;
			}
			return (error);	// we (maybe) set the world back to a known setting
		}
	}
	return (-1);
}

pascal Boolean ConfirmAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
{
	char charCode;
	Boolean enterORreturn;
	Boolean returnValue = false;

	if (0 == GetWRefCon(theDialog))
		SetWRefCon (theDialog,TickCount());
	else
	{
		if (GetWRefCon(theDialog) + kSecondsToConfirm * 60 < TickCount())
		{
			returnValue = true;
			theEvent->what = nullEvent;
			*itemHit = 1;
		}
		else
		{
			if (theEvent->what == keyDown)
			{
				charCode = (char)theEvent->message & charCodeMask;
				enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
				if (enterORreturn)
				{
					theEvent->what = nullEvent;
					returnValue = true;
					*itemHit = iRevertItem;
					if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
					{
						*itemHit = iConfirmItem;
					}
				}
			}
		}
	}
	return (returnValue);
}

OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
{
	short			alertReturn;		// Alert() return value
	ModalFilterUPP	confirmFilterUPP;	// got to have us one of them new fangled UPP thingies
	
	if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
	{	// new mode is valid but not safe, so ask user to confirm
		SetCursor(&qd.arrow);										// have to show the arrow

		confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);	// create a new modal filter proc UPP
		alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);	// alert the user
		DisposeRoutineDescriptor (confirmFilterUPP);				// of course there is no DisposeModalFilterProc...
		
		if (alertReturn != iConfirmItem)
			return (-1);							// tell the caller to switch back to a known setting
		else return (noErr);						// all is well with the new setting, just leave it
	}
	return (noErr);									// the mode was safe, so do nothing
}


OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
{
	Boolean							displayMgrPresent;
	short							iCount = 0;					// just a counter of GDevices we have seen
	DMDisplayModeListIteratorUPP	myModeIteratorProc = nil;	// for DM2.0 searches
	SpBlock							spBlock;
	Boolean							suppliedGDevice;	
	DisplayIDType					theDisplayID;				// for DM2.0 searches
	DMListIndexType					theDisplayModeCount;		// for DM2.0 searches
	DMListType						theDisplayModeList;			// for DM2.0 searches
	long							value = 0;
	GDHandle						walkDevice = nil;			// for everybody

	Gestalt(gestaltDisplayMgrAttr,&value);
	displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
	displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);	// need slot manager
	if (displayMgrPresent)
	{
		// init the needed data before we start
		if (requestRecPtr->screenDevice)							// user wants a specifc device?
		{
			walkDevice = requestRecPtr->screenDevice;
			suppliedGDevice = true;
		}
		else
		{
			walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);			// for everybody
			suppliedGDevice = false;
		}
		
		myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);	// for DM2.0 searches
	
		// Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
		// ...now do the loop if we can start
		if( walkDevice && myModeIteratorProc) do // start the search
		{
			iCount++;		// GDevice we are looking at (just a counter)
			if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )	// DM1.0 does not need this, but it fits in the loop
			{
				theDisplayModeCount = 0;	// for DM2.0 searches
				if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
				{
					// search NuBus & PCI the new kool way through Display Manager 2.0
					GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
					DMDisposeList(theDisplayModeList);	// now toss the lists for this gdevice and go on to the next one
				}
				else
				{
					// search NuBus only the old disgusting way through the slot manager
					GetRequestTheDM1Way (requestRecPtr, walkDevice);
				}
			}
		} while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );	// go until no more gdevices
		if( myModeIteratorProc )
			DisposeRoutineDescriptor(myModeIteratorProc);
		return (noErr);	// we were able to get the look for a match
	}
	return (-1);		// return a generic error
}

void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
{
	AuxDCEHandle myAuxDCEHandle;
	unsigned long	depthMode;
	unsigned long	displayMode;
	OSErr			error;
	OSErr			errorEndOfTimings;
	short			height;
	short			jCount = 0;
	Boolean			modeOk;
	SpBlock			spAuxBlock;
	SpBlock			spBlock;
	unsigned long	switchFlags;
	VPBlock			*vpData;
	short			width;

	myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);	
	spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
	spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
	spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
	spBlock.spHwDev = 0;								// we are going to get this pup
	spBlock.spParamData = 1<<foneslot;					// this slot, enabled, and it better be here.
	spBlock.spTBMask = 3;								// don't have constants for this yet
	errorEndOfTimings = SGetSRsrc(&spBlock);			// get the spDrvrHW so we know the ID of this puppy. This is important
														// since some video cards support more than one display, and the spDrvrHW
														// ID can, and will, be used to differentiate them.
	
	if ( noErr == errorEndOfTimings )
	{
		// reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
		spBlock.spID = 0;								// start at zero, 
		spBlock.spTBMask = 2;							// 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
		spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);	// 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
		spBlock.spCategory=catDisplay;
		spBlock.spCType=typeVideo;
		errorEndOfTimings = SGetTypeSRsrc(&spBlock);	// but only on 7.0 systems, not a problem since we require DM1.0
		
		// now, loop through all the timings for this GDevice
		if ( noErr == errorEndOfTimings ) do
		{
			// now, loop through all possible depth modes for this timing mode
			displayMode = (unsigned char)spBlock.spID;	// "timing mode, ie:resource ref number"
			for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
			{
				depthMode = jCount;		// vid mode
				error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
	
				// only if the mode is safe or we override it with the kAllValidModesBit request flag
				if (	noErr == error &&
						modeOk &&
						(	switchFlags & 1<<kNoSwitchConfirmBit ||
							requestRecPtr->requestFlags & 1<<kAllValidModesBit
						)
					)
				{
					// have a good displayMode/depthMode combo - now lets look inside
					spAuxBlock = spBlock;				// don't ruin the iteration spBlock!!
					spAuxBlock.spID = depthMode;		// vid mode
					error=SFindStruct(&spAuxBlock);		// get back a new spsPointer
					if (noErr == error)					// keep going if no error
					{
						spAuxBlock.spID = 0x01;			// mVidParams request
						error=SGetBlock (&spAuxBlock);	// use the new spPointer and get back...a NewPtr'ed spResult
						if (noErr == error)				// keep going if no error
						{								// We have data! lets have a look
							vpData = (VPBlock*)spAuxBlock.spResult;
							height = vpData->vpBounds.bottom;	// left and top are usually zero
							width = vpData->vpBounds.right;
							
							if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
							{
								requestRecPtr->screenDevice = walkDevice;
								requestRecPtr->availBitDepth = vpData->vpPixelSize;
								requestRecPtr->availHorizontal = vpData->vpBounds.right;
								requestRecPtr->availVertical = vpData->vpBounds.bottom;
								requestRecPtr->displayMode = displayMode;
								requestRecPtr->depthMode = depthMode;
								requestRecPtr->switchInfo.csMode = depthMode;				// fill in for completeness
								requestRecPtr->switchInfo.csData = displayMode;
								requestRecPtr->switchInfo.csPage = 0;
								requestRecPtr->switchInfo.csBaseAddr = 0;
								requestRecPtr->switchInfo.csReserved = 0;
								if (switchFlags & 1<<kNoSwitchConfirmBit)
									requestRecPtr->availFlags = 0;							// mode safe
								else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;	// mode valid but not safe, requires user validation of mode switch
							}

							if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);	// toss this puppy when done
						}
					}
				}
			}
			// go around again, looking for timing modes for this GDevice
			spBlock.spTBMask = 2;		// ignore DrvrSW
			spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);	// next resource, this slot, whether enabled or disabled
			errorEndOfTimings = SGetTypeSRsrc(&spBlock);	// and get the next timing mode
		} while ( noErr == errorEndOfTimings );	// until the end of this GDevice
	}

}

pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
{
	unsigned long			depthCount;
	short					iCount;
	ListIteratorDataRec		*myIterateData		= (ListIteratorDataRec*) userData;
	DepthInfo				*myDepthInfo;
	
	// set user data in a round about way
	myIterateData->displayModeTimingInfo		= *displaymodeInfo->displayModeTimingInfo;
	
	// now get the DMDepthInfo info into memory we own
	depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
	myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));

	// set the info for the caller
	myIterateData->depthBlockCount = depthCount;
	myIterateData->depthBlocks = myDepthInfo;

	// and fill out all the entries
	if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
	{
		myDepthInfo[iCount].depthSwitchInfo = 
			*displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
		myDepthInfo[iCount].depthVPBlock = 
			*displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
	}
}

void GetRequestTheDM2Way (	VideoRequestRecPtr requestRecPtr,
							GDHandle walkDevice,
							DMDisplayModeListIteratorUPP myModeIteratorProc,
							DMListIndexType theDisplayModeCount,
							DMListType *theDisplayModeList)
{
	short					jCount;
	short					kCount;
	ListIteratorDataRec		searchData;

	searchData.depthBlocks = nil;
	// get the mode lists for this GDevice
	for (jCount=0; jCount<theDisplayModeCount; jCount++)		// get info on all the resolution timings
	{
		DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
		
		// for all the depths for this resolution timing (mode)...
		if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
		{
			// only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
			if	(	searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
					(	searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
						requestRecPtr->requestFlags & 1<<kAllValidModesBit
					)
				)
			{
				if (FindBestMatch (	requestRecPtr,
									searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
									searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
									searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
				{
					requestRecPtr->screenDevice = walkDevice;
					requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
					requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
					requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
					
					// now set the important info for DM to set the display
					requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
					requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
					requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
					if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
						requestRecPtr->availFlags = 0;							// mode safe
					else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;	// mode valid but not safe, requires user validation of mode switch
	
				}
			}

		}
	
		if (searchData.depthBlocks)
		{
			DisposePtr ((Ptr)searchData.depthBlocks);	// toss for this timing mode of this gdevice
			searchData.depthBlocks = nil;				// init it just so we know
		}
	}
}

Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
{
	//  do the big comparison 
	// first time only if	(no mode yet) and
	//						(bounds are greater/equal or kMaximizeRes not set) and
	//						(depth is less/equal or kShallowDepth not set) and
	//						(request match or kAbsoluteRequest not set)
	if	(	nil == requestRecPtr->displayMode
			&&
			(	(horizontal >= requestRecPtr->reqHorizontal &&
				vertical >= requestRecPtr->reqVertical)
				||														
				!(requestRecPtr->requestFlags & 1<<kMaximizeResBit)	
			)
			&&
			(	bitDepth <= requestRecPtr->reqBitDepth ||	
				!(requestRecPtr->requestFlags & 1<<kShallowDepthBit)		
			)
			&&
			(	(horizontal == requestRecPtr->reqHorizontal &&	
				vertical == requestRecPtr->reqVertical &&
				bitDepth == requestRecPtr->reqBitDepth)
				||
				!(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)	
			)
		)
		{
			// go ahead and set the new values
			return (true);
		}
	else	// can we do better than last time?
	{
		// if	(kBitDepthPriority set and avail not equal req) and
		//		((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
		//		(avail depth less reqested and new greater avail)
		//		(request match or kAbsoluteRequest not set)
		if	(	(	requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
					requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
				)
				&&
				(	(	bitDepth > requestRecPtr->availBitDepth &&
						bitDepth <= requestRecPtr->reqBitDepth
					)
					||
					!(requestRecPtr->requestFlags & 1<<kShallowDepthBit)	
				)
				&&
				(	requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
					bitDepth > requestRecPtr->availBitDepth	
				)
				&&
				(	(horizontal == requestRecPtr->reqHorizontal &&	
					vertical == requestRecPtr->reqVertical &&
					bitDepth == requestRecPtr->reqBitDepth)
					||
					!(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)	
				)
			)
		{
			// go ahead and set the new values
			return (true);
		}
		else
		{
			// match resolution: minimize h & v
			if	(	abs((requestRecPtr->reqHorizontal - horizontal)) <=
					abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
					abs((requestRecPtr->reqVertical - vertical)) <=
					abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
				)
			{
				// now we have a smaller or equal delta
				//	if (h or v greater/equal to request or kMaximizeRes not set) 
				if (	(horizontal >= requestRecPtr->reqHorizontal &&
						vertical >= requestRecPtr->reqVertical)
						||
						!(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
					)
				{
					// if	(depth is equal or kBitDepthPriority not set) and
					//		(depth is less/equal or kShallowDepth not set) and
					//		([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
					//		(request match or kAbsoluteRequest not set)
					if	(	(	requestRecPtr->availBitDepth == bitDepth ||			
								!(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
							)
							&&
							(	bitDepth <= requestRecPtr->reqBitDepth ||	
								!(requestRecPtr->requestFlags & 1<<kShallowDepthBit)		
							)
							&&
							(	(requestRecPtr->availHorizontal != horizontal ||
								requestRecPtr->availVertical != vertical)
								||
								(requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
								bitDepth > requestRecPtr->availBitDepth)
								||
								(bitDepth == requestRecPtr->reqBitDepth)
							)
							&&
							(	(horizontal == requestRecPtr->reqHorizontal &&	
								vertical == requestRecPtr->reqVertical &&
								bitDepth == requestRecPtr->reqBitDepth)
								||
								!(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)	
							)
						)
					{
						// go ahead and set the new values
						return (true);
					}
				}
			}
		}
	}
	return (false);
}

void GravitateMonitors (void)
{
	// do the magic gravitation here
}