1 
2 #include "ScreenDevice.h"
3 
4 
5 #if EG_MAC
6 #include <Displays.h>
7 #endif
8 
9 
10 long		ScreenDevice::sOSDepth				= 16;
11 long		ScreenDevice::sMinDepth 			= 16;
12 
13 
14 
15 
16 
17 
ScreenDevice()18 ScreenDevice::ScreenDevice() {
19 	mContextRef = 0;
20 
21 	#if USE_DIRECTX
22 	HDC hdc = ::GetDC( 0 );
23 	sOSDepth = ::GetDeviceCaps( hdc, BITSPIXEL );
24 	::ReleaseDC( 0, hdc );
25 	if ( sOSDepth == 24 )
26 		sOSDepth = 32;
27 	#endif
28 
29 	#if EG_WIN
30 	mDDObj		= 0;
31 	mFS_DC		= 0;
32 	#endif
33 
34 
35 	/*
36 	GDHandle gDevice = ::GetMainDevice();
37 	if ( gDevice ) {
38 		PixMapHandle pixMap = (**gDevice).gdPMap;
39 		sOSDepth = (**pixMap).pixelSize;
40 		if ( sOSDepth == 8 ) {
41 			::BlockMove( (**(**pixMap).pmTable).ctTable, sOSPalette, 256 * sizeof( ColorSpec ) );
42 		} }
43 	else
44 		sOSDepth = 16;
45 	*/
46 
47 }
48 
49 
~ScreenDevice()50 ScreenDevice::~ScreenDevice() {
51 
52 
53 	//EndFrame();
54 
55 	ExitFullscreen();
56 }
57 
58 
59 
60 
EnterFullscreen(long inDispID,Point & ioSize,int inBitDepth,WindowPtr inWin)61 bool ScreenDevice::EnterFullscreen( long inDispID, Point& ioSize, int inBitDepth, WindowPtr inWin ) {
62 	bool ok = false;
63 
64 
65 	// Check inBitDepth
66 	if ( inBitDepth != 8 && inBitDepth != 16 && inBitDepth != 32 )
67 		inBitDepth = sOSDepth;
68 	if ( inBitDepth < sMinDepth )
69 		inBitDepth = sMinDepth;
70 
71 
72 	ExitFullscreen();
73 	mDispID		= inDispID;
74 	mBitDepth	= inBitDepth;
75 
76 
77 	#if USE_DISP_MGR
78 	Rect		r;
79 	GDHandle	theGDevice;
80 
81 	::HideCursor();
82 	::HideWindow( inWin );
83 
84 
85 	// Hide that pesky menubar...
86 	RgnHandle grayRgn;
87 	grayRgn = ::LMGetGrayRgn();
88 	mMenuBarHeight	= ::LMGetMBarHeight();
89 	::LMSetMBarHeight( 0 );
90 	r = qd.screenBits.bounds;
91 	r.bottom = r.top + mMenuBarHeight;
92 	mMenuBarRgn	= ::NewRgn();
93 	::RectRgn( mMenuBarRgn, &r );
94 	::UnionRgn( grayRgn, mMenuBarRgn, grayRgn );
95 
96 	// Fetch a ptr to the device given by inDispNum
97 	if ( ::DMGetGDeviceByDisplayID( inDispNum, &theGDevice, false ) != noErr )
98 		theGDevice = 0;
99 	if ( ! theGDevice )
100 		theGDevice = ::GetMainDevice();
101 
102 	// Use RequestVideo.c to get the Disp Mgr to do what we want
103 	VideoRequestRec requestRec;
104 	requestRec.screenDevice		=	theGDevice;
105 	requestRec.reqBitDepth		=	inBitDepth;
106 	requestRec.reqHorizontal	=	ioSize.h;
107 	requestRec.reqVertical		=	ioSize.v;
108 	requestRec.displayMode		=	nil;					// must init to nil
109 	requestRec.depthMode		=	nil;					// must init to nil
110 	requestRec.requestFlags		=	0;
111 	if ( RVRequestVideoSetting( &requestRec ) == noErr ) {
112 		if ( RVSetVideoRequest( &requestRec ) == noErr ) {
113 			outSize.h = requestRec.availHorizontal;
114 			outSize.v = requestRec.availVertical;
115 			ok = true;
116 		}
117 	}
118 
119 	if ( ok ) {
120 
121 		// Make the window cover the device
122 		::MoveWindow( inWin, 0, 0, true );
123 		::SizeWindow( inWin, outSize.h, outSize.v, true );
124 		::ShowWindow( inWin );
125 
126 		// Setup the window as the main grafport
127 		mContextRef = inWin;
128 		mX			= outSize.h;
129 		mY			= outSize.v;
130 		::SetRect( &r, 0, 0, mX, mY+2 );
131 		::NewGWorld( &mWorld, inBitDepth, &r, 0, 0, useTempMem );
132 		mBM = ::GetGWorldPixMap( mWorld );
133 		mBytesPerRow	= (**mBM).rowBytes & 0xFFF;
134 		mBytesPerPix	= (**mBM).pixelSize / 8;
135 	}
136 
137 
138 
139 	#elif USE_DRAW_SPROCKETS
140 	DSpContextReference		ref;
141 	OSStatus				err;
142 	DSpContextAttributes	context;
143 	long					bestWidth = 0x7FFFFFFF;
144 	bool 					isInitted = false;
145 
146 	err = ::DSpStartup();
147 	if ( ! err ) {
148 		err = ::DSpGetFirstContext( inDispID, &ref );
149 
150 		// Look for smallest size w/ for given depth
151 		while ( ! err && ref ) {
152 			err = DSpContext_GetAttributes( ref, &context );
153 			if ( ! err && ref ) {
154 				if ( context.displayBestDepth == inBitDepth ) {
155 					if ( context.displayWidth == ioSize.h && context.displayHeight == ioSize.v ) {
156 						mContextRef = ref;
157 						isInitted = true;
158 						break; }
159 					else if ( context.displayWidth <= bestWidth && context.displayWidth >= 640 ) {
160 						mContextRef = ref;
161 						isInitted = true;
162 						bestWidth = context.displayWidth;
163 					}
164 				}
165 
166 				// Try the next context for this display
167 				err = ::DSpGetNextContext( ref, &ref );
168 			}
169 		}
170 
171 		if ( ! isInitted ) {
172 			mContextRef = 0;
173 			::DSpShutdown();
174 			return false;
175 		}
176 
177 		::DSpContext_GetAttributes( mContextRef, &mContext );
178 		ioSize.h = mContext.displayWidth;
179 		ioSize.v = mContext.displayHeight;
180 
181 		mContext.contextOptions 			= kDSpContextOption_DontSyncVBL;
182 		mContext.frequency					= 0;
183 		mContext.reserved1					= 0;
184 		mContext.reserved2					= 0;
185 		mContext.gameMustConfirmSwitch		= false;
186 		mContext.reserved3[0]	= 0;
187 		mContext.reserved3[1]	= 0;
188 		mContext.reserved3[2]	= 0;
189 		mContext.reserved3[3]	= 0;
190 		mContext.colorTable		= 0;
191 		mContext.pageCount		= 1;
192 		mContext.colorNeeds		= kDSpColorNeeds_Require;
193 
194 		RGBColor back = { 0, 0, 0 };
195 		::DSpSetBlankingColor( &back );
196 
197 		// Try to reserve the device
198 		err = ::DSpContext_Reserve( mContextRef, &mContext );
199 		if ( ! err ) {
200 
201 			// If no errors, 'activate' the device into fullscreen
202 			::DSpContext_FadeGammaOut( mContextRef, 0 );
203 			::HideCursor();
204 
205 			err = ::DSpContext_SetState( mContextRef, kDSpContextState_Active );
206 			::DSpContext_FadeGamma( mContextRef, 100, 0 );
207 
208 			if ( err && err != kDSpConfirmSwitchWarning ) {
209 				::DSpContext_Release( mContextRef );
210 				::DSpShutdown(); }
211 			else {
212 				ok = true;
213 
214 				#pragma unused( inWin )
215 				/*
216 				// Make the window cover the device
217 				::MoveWindow( inWin, 0, 0, true );
218 				::SizeWindow( inWin, ioSize.h, ioSize.v, true );
219 				::ShowWindow( inWin );
220 
221 				// Setup the window as the main grafport
222 				mFS_DC = inWin; */
223 				mFS_DC = 0;
224 			}
225 		}
226 	}
227 
228 
229 	#elif USE_DIRECTX
230 	if ( inWin ) {
231 		HRESULT err = ::DirectDrawCreate( 0, &mDDObj, 0 );
232 		if ( err == DD_OK ) {
233 			LPDIRECTDRAWSURFACE context;
234 
235 			err = mDDObj -> SetCooperativeLevel( inWin, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
236 			if ( err == DD_OK ) {
237 				err = mDDObj -> SetDisplayMode( ioSize.h, ioSize.v, inBitDepth );
238 				if ( err == DD_OK ) {
239 					mDDObj -> Compact();
240 					DDSURFACEDESC ddsd;
241 					ddsd.dwSize = sizeof(ddsd);
242 					ddsd.dwFlags = DDSD_CAPS;
243 					ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
244 					err = mDDObj -> CreateSurface( &ddsd, &context, 0);
245 				}
246 			}
247 
248 			if ( err == DD_OK ) {
249 				mContextRef = context;
250 				::SetForegroundWindow( inWin );
251 				::SetCapture( inWin );
252 				mFS_Win = inWin;
253 
254 				PALETTEENTRY pal[ 256 ];
255 				for ( int j = 0; j < 256; j++ ) {
256 					pal[ j ].peRed = j;
257 					pal[ j ].peGreen = j;
258 					pal[ j ].peBlue = j;
259 					pal[ j ].peFlags = 0;
260 				}
261 				mDDObj -> CreatePalette( DDPCAPS_8BIT, pal, &mFS_Palette, 0 );
262 				mContextRef -> SetPalette( mFS_Palette );
263 				ok = true; }
264 			else {
265 				 mDDObj -> Release();
266 				 mDDObj = 0;
267 			}
268 		}
269 	}
270 
271 
272 	#else
273 	#pragma unused( ioSize, inWin )
274 	#endif
275 
276 	if ( ok ) {
277 		#if EG_MAC
278 		::HideCursor();
279 		#elif EG_WIN
280 		::SetCursor( ::LoadCursor( 0, IDC_ARROW ) );
281 		while ( ::ShowCursor( false ) >= 0 ) { }
282 		#endif
283 		}
284 	else
285 		mContextRef = 0;
286 
287 
288 	return ok;
289 }
290 
291 
292 
293 
ExitFullscreen()294 void ScreenDevice::ExitFullscreen() {
295 
296 
297 	EndFrame();
298 	if ( ! IsFullscreen() )
299 		return;
300 
301 	#if USE_DRAW_SPROCKETS
302 	::DSpContext_FadeGamma( mContextRef, 0, 0 );
303 	::DSpContext_SetState( mContextRef, kDSpContextState_Inactive );
304 	::DSpContext_FadeGamma( mContextRef, 100, 0 );
305 	::DSpContext_Release( mContextRef );
306 	::DSpShutdown();
307 	::InitCursor();
308 	#endif
309 
310 
311 	#if USE_DISP_MGR
312 	RVSetVideoAsScreenPrefs();
313 
314 	// Make the menu bar visible again
315 	RgnHandle grayRgn;
316 	grayRgn = ::LMGetGrayRgn();
317 	::LMSetMBarHeight( mMenuBarHeight );
318 	::DiffRgn( grayRgn, mMenuBarRgn, grayRgn );	// remove the menu bar from the desktop
319 	::PaintOne( 0, mMenuBarRgn );			// redraw the menubar
320 	::DisposeRgn( mMenuBarRgn );
321 
322 	// Restore the original color table for the main device
323 	if ( sOSDepth == 8 && mBytesPerPix == 1 )
324 		::SetEntries( 0, 255, sOSPalette );
325 	::InitCursor();
326 	#endif
327 
328 
329 	#if USE_DIRECTX
330 	if ( mFS_DC ) {
331 		mContextRef -> ReleaseDC( mFS_DC );
332 		mFS_DC = 0;
333 	}
334 	if ( mContextRef ) {
335 		mContextRef -> Release();
336 		mContextRef = 0;
337 	}
338 	if ( mDDObj ) {
339 		mDDObj -> SetCooperativeLevel( mFS_Win, DDSCL_NORMAL );
340 		mDDObj -> Release();
341 		mDDObj = 0;
342 	}
343 	::ReleaseCapture();
344 	while ( ::ShowCursor( true ) < 0 ) { }
345 	#endif
346 
347 	mContextRef = 0;
348 	mFS_DC = 0;
349 }
350 
351 
352 
353 
354 
355 
356 
SetPalette(PixPalEntry inPal[256])357 void ScreenDevice::SetPalette( PixPalEntry inPal[ 256 ] ) {
358 
359 	if ( mBitDepth != 8 || ! IsFullscreen() )
360 		return;
361 
362 	#if EG_WIN
363 	PALETTEENTRY pal[ 256 ];
364 	for ( int i = 0; i < 256; i++ ) {
365 		* ( (long*) &pal[ i ] ) = inPal[ i ].rgbRed | ( inPal[ i ].rgbGreen << 8 )| ( inPal[ i ].rgbBlue << 16 ) | ( PC_RESERVED << 24 );
366 	}
367 	mFS_Palette -> SetEntries( 0, 0, 256, pal );
368 	#endif
369 
370 
371 	#if EG_MAC
372 	::SetEntries( 0, 255, inPal );
373 
374 	/*	CTabHandle myTable = (**mBM).pmTable;
375 		::BlockMove( inPalette, (**myTable).ctTable, 256 * sizeof( ColorSpec ) );
376 		::CTabChanged( myTable );  */
377 	#endif
378 
379 }
380 
381 
BeginFrame()382 GrafPtr ScreenDevice::BeginFrame() {
383 
384 	if ( IsFullscreen() ) {
385 
386 		#if USE_DRAW_SPROCKETS
387 		OSErr err;
388 	//	err = ::DSpContext_GetBackBuffer( mContextRef, kDSpBufferKind_Normal, (CGrafPtr*) &mFS_DC );
389 		//if ( ! mFS_DC ) {
390 			err = ::DSpContext_GetFrontBuffer( mContextRef, (CGrafPtr*) &mFS_DC );
391 			if ( mFS_DC )
392 				::SetPort( mFS_DC );
393 			else
394 				ExitFullscreen();
395 		//}
396 		#endif
397 
398 
399 		#if USE_DISP_MGR
400 		mBM	= ::GetGWorldPixMap( mWorld );
401 		fix me!
402 		#endif
403 
404 
405 		#if USE_DIRECTX
406 		if ( mContextRef -> GetDC( &mFS_DC ) != DD_OK )
407 			mFS_DC = 0;
408 		#endif
409 
410 	}
411 
412 	return mFS_DC;
413 }
414 
415 
416 
EndFrame()417 void ScreenDevice::EndFrame() {
418 
419 	if ( IsFullscreen() ) {
420 
421 		#if USE_DRAW_SPROCKETS
422 		//::DSpContext_SwapBuffers( mContextRef, 0, 0 );
423 		mFS_DC = 0;
424 		#endif
425 
426 		#if USE_DIRECTX
427 		if ( mFS_DC ) {
428 			mContextRef -> ReleaseDC( mFS_DC );
429 			mFS_DC = 0;
430 		}
431 		#endif
432 	}
433 }
434 
435 
436 
GetDisplayID(long inDeviceNum)437 long ScreenDevice::GetDisplayID( long inDeviceNum ) {
438 
439 
440 	#if EG_MAC
441 	OSStatus			err;
442 	DisplayIDType		id = 0;
443 	GDHandle theGDevice = DMGetFirstScreenDevice( false );
444 	while ( theGDevice && inDeviceNum ) {
445 		inDeviceNum--;
446 
447 		theGDevice = DMGetNextScreenDevice( theGDevice, false );
448 	}
449 
450 	if ( ! theGDevice )
451 		theGDevice = DMGetFirstScreenDevice( false );
452 
453 	err = DMGetDisplayIDByGDevice( theGDevice, &id, false );
454 
455 	return ( err ) ? 0 : id;
456 	#endif
457 
458 	#if EG_WIN
459 	//#pragma unused( inX, inY )
460 	return 0;
461 	#endif
462 }
463 
464 
465 
GetDisplayID(long inX,long inY)466 long ScreenDevice::GetDisplayID( long inX, long inY ) {
467 
468 	#if EG_MAC
469 	OSStatus			err;
470 	DisplayIDType		id = 0;
471 	Point				inPt;
472 
473 	inPt.h = inX;
474 	inPt.v = inY;
475 
476 	GDHandle theGDevice;
477 
478 	/*
479 	** Walk the list of display devices in the system.  DrawSprocket is
480 	** centered around the DisplayIDType, which is used by the Display
481 	** Manager.  The GDevice records are going to be in flux with future
482 	** versions of the system software, so it is best to make the change
483 	** now and make your software DisplayManager-centric.
484 	*/
485 	theGDevice = DMGetFirstScreenDevice( false );
486 	while( theGDevice && ! id ) {
487 
488 		if ( ::PtInRect( inPt, &(**theGDevice).gdRect ) ) {
489 
490 			/* get the display ID */
491 			err = DMGetDisplayIDByGDevice( theGDevice, &id, false );
492 			if ( err )
493 				id = 0;
494 		}
495 
496 		/* next device */
497 		theGDevice = DMGetNextScreenDevice( theGDevice, false );
498 	}
499 /*
500 	err = ::DSpFindContextFromPoint( inPt, &ref );
501 	if ( ! err )
502 		err = ::DSpContext_GetDisplayID( ref, &id );
503 */
504 	return ( err ) ? 0 : id;
505 	#endif
506 
507 	#if EG_WIN
508 	#pragma unused( inX, inY )
509 	return 0;
510 	#endif
511 }
512 
513