source: abuse/branches/pd/imlib/port/mac/MacFull.cpp @ 528

Last change on this file since 528 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 11.7 KB
Line 
1/*****************************************************************************
2        Full-Screen Access Demo
3        Macintosh DisplayManager 2.0 implementation
4
5        This code is Copyright (c) 1996 by Jon Blossom. All Rights Reserved.
6 ****************************************************************************/
7
8#ifndef _WINDOWS
9
10//****************************************************************************
11// System includes
12
13#include <QDOffscreen.h>
14#include <Video.h>
15#include <Displays.h>
16#include <Palettes.h>
17#include <Timer.h>
18
19//****************************************************************************
20// Internal functions
21
22void StealMenuBar(void);
23void RestoreMenuBar(void);
24
25void DemoMain(void);
26
27long unsigned GetMillisecondTime(void)
28{
29        // Get a microsecond-accurate time from the Time Manager
30        UnsignedWide Microsecs;
31        Microseconds(&Microsecs);
32
33        // TODO: Do this right! And don't use doubles!
34        double Time;
35        Time = (double)Microsecs.hi * (double)0xFFFFFFFF;
36        Time = Time + (double)Microsecs.lo;
37        Time = Time / 1000.0;
38        while (Time > (double)0xFFFFFFFF)
39                Time = Time - (double)0xFFFFFFFF;
40        return (long unsigned)Time;
41}
42
43//****************************************************************************
44// Internal globals
45
46static WindowPtr Window =0;
47static PaletteHandle hPalette =0;
48static GWorldPtr pOffscreenGWorld =0;
49static GDHandle DisplayDevice;
50
51static unsigned short csPreviousMode;
52static unsigned long csPreviousData;
53
54static char unsigned *pBits =0;
55static long Stride =0;
56
57//****************************************************************************
58// Application entry point
59
60int main()
61{
62        // Initialize the Mac
63        MaxApplZone();
64        MoreMasters();
65        InitGraf(&qd.thePort);
66        InitFonts();
67        FlushEvents(everyEvent, 0);
68        InitWindows();
69        InitMenus();
70        InitDialogs(0L);
71        InitCursor();
72
73        // Check for Display Manager using Gestalt
74        long GestaltValue = 0;
75        long DisplayManagerVersion = 0;
76        Gestalt(gestaltDisplayMgrAttr, &GestaltValue);
77        if (GestaltValue & (1<<gestaltDisplayMgrPresent))
78                Gestalt(gestaltDisplayMgrVers, &DisplayManagerVersion);
79
80        // If Display Manager 2.x is available, proceed
81        if (DisplayManagerVersion >= 0x00020000)
82                DemoMain();
83
84        return 0;
85}
86
87//****************************************************************************
88// Offscreen access
89
90char unsigned *GetOffscreenBits(void)
91{
92        return pBits;
93}
94
95long GetOffscreenStride(void)
96{
97        return Stride;
98}
99
100int OffscreenLock(void)
101{
102        int ReturnValue = 0;
103
104        pBits = 0;
105        Stride = 0;
106
107        // Get the PixMap structure of the offscreen GWorld
108        PixMapHandle OffscreenPixMap = GetGWorldPixMap(pOffscreenGWorld);
109        if (OffscreenPixMap)
110        {
111                // Lock the PixMap memory and pull info off the PixMap
112                LockPixels(OffscreenPixMap);
113                pBits = (char unsigned *)GetPixBaseAddr(OffscreenPixMap);
114                Stride = (*OffscreenPixMap)->rowBytes & 0x3FFF;
115
116                ReturnValue = 1;
117        }
118
119        return ReturnValue;
120}
121
122int OffscreenUnlock(void)
123{
124        int ReturnValue = 0;
125
126        // Get the PixMap structure of the offscreen GWorld
127        PixMapHandle OffscreenPixMap = GetGWorldPixMap(pOffscreenGWorld);
128        if (OffscreenPixMap)
129        {
130                // Unlock the offscreen PixMap and reset the bits and stride
131                UnlockPixels(OffscreenPixMap);
132                pBits = 0;
133                Stride = 0;
134
135                ReturnValue = 1;
136        }
137
138        return ReturnValue;
139}
140
141//****************************************************************************
142// Buffer swapping
143
144void SwapBuffer(void)
145{
146        // Make sure ctSeed matches so we get a 1:1 blt, even though we
147        // have set up everything correctly when creating the GWorld in the
148        // first place.
149        // Basically, if QuickDraw knows the color tables are the same
150        // it will ignore any translation and just copy the bits. This
151        // is an extra trick to make sure it's satisfied.
152        PixMapHandle OffscreenPixMap = pOffscreenGWorld->portPixMap;
153        CTabHandle OffscreenCtab = (*OffscreenPixMap)->pmTable;
154
155        PixMapHandle OnscreenPixMap = ((CWindowPtr)Window)->portPixMap;
156        CTabHandle OnscreenCtab = (*OnscreenPixMap)->pmTable;
157
158        (*OffscreenCtab)->ctSeed = (*OnscreenCtab)->ctSeed;
159
160        // Do the blt
161        CopyBits(&((GrafPtr)pOffscreenGWorld)->portBits,
162                &Window->portBits,
163                &Window->portRect, &Window->portRect,
164                srcCopy, 0);
165}
166
167void SwapRect(int Left, int Top, int Right, int Bottom)
168{
169        // Make sure ctSeed matches so we get a 1:1 blt, as above
170        PixMapHandle OffscreenPixMap = pOffscreenGWorld->portPixMap;
171        CTabHandle OffscreenCtab = (*OffscreenPixMap)->pmTable;
172
173        PixMapHandle OnscreenPixMap = ((CWindowPtr)Window)->portPixMap;
174        CTabHandle OnscreenCtab = (*OnscreenPixMap)->pmTable;
175
176        (*OffscreenCtab)->ctSeed = (*OnscreenCtab)->ctSeed;
177
178        Rect BltRect = { Top, Left, Bottom, Right };
179
180        // Do the blt
181        CopyBits(&((GrafPtr)pOffscreenGWorld)->portBits,
182                &Window->portBits,
183                &BltRect, &BltRect,
184                srcCopy, 0);
185}
186
187//****************************************************************************
188// Full Screen initialization
189
190// This structure encapsulates the data sent to the Display Manager list
191// enumeration callback function. We fill in the desired values, pass this
192// on through the enumeration, and it fills in the csMode and csData info
193// we need.
194struct DisplayModeRequest
195{
196        // Returned values
197        unsigned short csMode;
198        unsigned long csData;
199
200        // Provided values
201        long DesiredWidth;
202        long DesiredHeight;
203        long DesiredDepth;
204};
205
206// This function filters through the display modes reported by the Display
207// Manager, looking for one that matches the requested resolution. The
208// userData pointer will point to a DisplayModeRequest structure.
209pascal void DisplayModeCallback(void* userData, DMListIndexType,
210        DMDisplayModeListEntryPtr pModeInfo)
211{
212        DisplayModeRequest *pRequest = (DisplayModeRequest*)userData;
213
214        // Get timing info and make sure this is an OK display mode
215        VDTimingInfoRec TimingInfo = *(pModeInfo->displayModeTimingInfo);
216        if (TimingInfo.csTimingFlags & 1<<kModeValid)
217        {
218                // How many modes are being enumerated here?
219                unsigned long DepthCount =
220                        pModeInfo->displayModeDepthBlockInfo->depthBlockCount;
221
222                // Filter through each of the modes provided here
223                VDSwitchInfoRec *pSwitchInfo;
224                VPBlock *pVPBlockInfo;
225                for (short Count = 0; Count < DepthCount; ++Count)
226                {
227                        // This provides the csMode and csData information
228                        pSwitchInfo =
229                                pModeInfo->displayModeDepthBlockInfo->
230                                depthVPBlock[Count].depthSwitchInfo;
231
232                        // This tells us the resolution and pixel depth
233                        pVPBlockInfo =
234                                pModeInfo->displayModeDepthBlockInfo->
235                                depthVPBlock[Count].depthVPBlock;
236
237                        if (pVPBlockInfo->vpPixelSize == pRequest->DesiredDepth &&
238                                pVPBlockInfo->vpBounds.right == pRequest->DesiredWidth &&
239                                pVPBlockInfo->vpBounds.bottom == pRequest->DesiredHeight)
240                        {
241                                // Found a mode that matches the request!
242                                pRequest->csMode = pSwitchInfo->csMode;
243                                pRequest->csData = pSwitchInfo->csData;
244                        }
245                }
246        }
247}
248
249int BeginFullScreen(int Width, int Height, int Depth)
250{
251        // Hide the menu bar
252        StealMenuBar();
253
254        // Create a window of the requested size
255        Rect WindowRect = { 0, 0, Height, Width };
256        Window = NewCWindow(0, &WindowRect, "\pFullScreen",
257                TRUE, plainDBox,
258                WindowPtr(-1), FALSE, 0);
259        if (!Window)
260                goto Failure;
261
262        // Set up a palette with a gray wash
263        hPalette = NewPalette(256, 0, pmExplicit | pmAnimated, 0);
264        if (!hPalette)
265                goto Failure;
266
267        RGBColor Color;
268        int i;
269        for (i=0; i<256; ++i)
270        {
271                Color.red= i << 8;
272                Color.green = i << 8;
273                Color.blue = i << 8;
274
275                SetEntryColor(hPalette, i, &Color);
276        }
277
278        // Force 0 and 255 to White and Black
279        SetEntryUsage(hPalette, 0, pmExplicit | pmAnimated | pmWhite, 0);
280        SetEntryUsage(hPalette, 255, pmExplicit | pmAnimated | pmBlack, 0);
281
282        SetPalette(Window, hPalette, TRUE);
283
284        // Store information about the current display settings
285        DisplayDevice = GetMainDevice();
286        if (!DisplayDevice)
287                goto Failure;
288
289        csPreviousMode = -1;
290        csPreviousData = -1;
291
292        VDSwitchInfoRec DisplayInfo;
293        OSErr MacError = DMGetDisplayMode(DisplayDevice, &DisplayInfo);
294        if (MacError != noErr)
295                goto Failure;
296
297        csPreviousMode = DisplayInfo.csMode;
298        csPreviousData = DisplayInfo.csData;
299
300        // Get the display ID for the main display
301        DisplayIDType DisplayID;
302        DMGetDisplayIDByGDevice(DisplayDevice, &DisplayID, FALSE);
303
304        // Use it to get a list of available modes from the Display Manager
305        DMListIndexType DisplayModeCount = 0;
306        DMListType DisplayModeList;
307        MacError = DMNewDisplayModeList(DisplayID, 0, 0,
308                &DisplayModeCount, &DisplayModeList);
309        if (MacError != noErr)
310                goto Failure;
311
312        // Create a callback function pointer to filter available modes
313        DMDisplayModeListIteratorUPP uppDisplayModeCallback =
314                NewDMDisplayModeListIteratorProc(DisplayModeCallback);
315        if (!uppDisplayModeCallback)
316        {
317                // Aborting - let go of the mode list
318                DMDisposeList(DisplayModeList);
319                goto Failure;
320        }
321
322        // Go through the list, comparing each available mode with
323        // this mode request
324        DisplayModeRequest ModeRequest;
325        ModeRequest.csMode = -1;
326        ModeRequest.csData = -1;
327        ModeRequest.DesiredWidth = Width;
328        ModeRequest.DesiredHeight = Height;
329        ModeRequest.DesiredDepth = Depth;
330
331        for (short Count = 0; Count < DisplayModeCount; ++Count)
332        {
333                DMGetIndexedDisplayModeFromList(DisplayModeList, Count,
334                        0, uppDisplayModeCallback, (void*)&ModeRequest);
335        }
336
337        // Done with the list
338        DMDisposeList(DisplayModeList);
339
340        // Done with the callback
341        DisposeRoutineDescriptor(uppDisplayModeCallback);
342
343        // If we found a mode fitting the request, switch to it!
344        if (ModeRequest.csMode == -1 || ModeRequest.csData == -1)
345                goto Failure;
346
347        DisplayInfo.csMode = ModeRequest.csMode;
348        DisplayInfo.csData = ModeRequest.csData;
349
350        unsigned long Mode = DisplayInfo.csMode;
351        MacError = DMSetDisplayMode(DisplayDevice,
352                DisplayInfo.csData, &Mode,
353                (unsigned long)&DisplayInfo,
354                0);
355        if (MacError != noErr)
356                goto Failure;
357
358        // Create a matching GWorld using current device and window
359        CGrafPtr CurrentPort = (CWindowPtr)Window;
360       
361        PixMapHandle CurrentPixMap = CurrentPort->portPixMap;
362        CTabHandle ColorTable = (*CurrentPixMap)->pmTable;
363
364        NewGWorld(&pOffscreenGWorld, (short)Depth,
365                &CurrentPort->portRect, ColorTable,
366                DisplayDevice, noNewDevice);
367        if (!pOffscreenGWorld)
368                goto Failure;
369
370        // Success!
371        return 1;
372
373Failure:
374        RestoreMenuBar();
375        return 0;
376}
377
378//****************************************************************************
379// Full Screen clean-up
380
381void EndFullScreen(void)
382{
383        if (Window)
384        {
385                DisposeWindow(Window);
386                Window = 0;
387        }
388       
389        if (pOffscreenGWorld)
390        {
391                DisposeGWorld(pOffscreenGWorld);
392                pOffscreenGWorld = 0;
393        }
394
395        if (csPreviousMode != -1 && csPreviousData != -1)
396        {
397                // Set the display back to its starting place
398                VDSwitchInfoRec OriginalInfo;
399                OriginalInfo.csMode = csPreviousMode;
400                OriginalInfo.csData = csPreviousData;
401
402                unsigned long Mode = csPreviousMode;
403                DMSetDisplayMode(DisplayDevice,
404                        csPreviousData, &Mode,
405                        (unsigned long)&OriginalInfo,
406                        0);
407        }
408
409        RestoreMenuBar();
410}
411
412//****************************************************************************
413// Menu bar manipulation functions
414
415static short _OldMBarHeight = 0;
416static RgnHandle _OldDesktopRgn = 0;
417
418void StealMenuBar(void)
419{
420        RgnHandle DesktopRgn;
421
422        if (_OldMBarHeight == 0)
423        {
424                // Get and copy the current gray region
425                DesktopRgn = LMGetGrayRgn();
426                _OldDesktopRgn = NewRgn();
427                CopyRgn(DesktopRgn, _OldDesktopRgn);
428               
429                // Fudge the menu bar height
430                _OldMBarHeight = GetMBarHeight();
431                LMSetMBarHeight(0);
432
433                // Turn the gray into the old gray region plus the menu bar region
434                Rect MenuRect;
435                MenuRect.left = 0;
436                MenuRect.top = 0;
437                MenuRect.right = qd.screenBits.bounds.right;
438                MenuRect.bottom = _OldMBarHeight;
439                RgnHandle MenuRgn = NewRgn();
440                RectRgn(MenuRgn, &MenuRect);
441
442                UnionRgn(_OldDesktopRgn, MenuRgn, DesktopRgn);
443                DisposeRgn(MenuRgn);
444        }
445}
446
447void RestoreMenuBar(void)
448{
449        if (_OldMBarHeight && _OldDesktopRgn)
450        {
451                // Restore the menu bar height
452                LMSetMBarHeight(_OldMBarHeight);
453                _OldMBarHeight = 0;
454
455                // Restore the old desktop region
456                CopyRgn(_OldDesktopRgn, LMGetGrayRgn());
457                DisposeRgn(_OldDesktopRgn);
458                _OldDesktopRgn = 0;
459               
460                // Redraw the menu bar
461                HiliteMenu(0);
462                DrawMenuBar();
463        }
464}
465
466#endif // not _WINDOWS
Note: See TracBrowser for help on using the repository browser.