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