source: abuse/branches/pd/imlib/port/mac/video.c @ 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: 13.4 KB
Line 
1#include <QDOffscreen.h>
2#include <Palettes.h>
3#include <Displays.h>
4#include <Video.h>
5#include <Menus.h>
6
7#include "video.hpp"
8
9#include "filter.hpp"
10#include "globals.hpp"
11#include "system.h"
12#include "dos.h"
13#include "macs.hpp"
14#include "bitmap.h"
15#include "image.hpp"
16#include "jmalloc.hpp"
17#include <GUSI.h>
18
19#include "RequestVideo.h"
20
21// Resource id for crack window
22#define         WIND_CRACK      1000
23
24#define PAL_DIRECT    // direct palette routines - yes!
25#define VIDEO_DIRECT  // direct video routines - yes!
26
27unsigned char current_background;
28extern unsigned int xres,yres;
29
30// Some number for jollies
31int vmode;
32image *screen;
33
34Rect Bounds;
35CWindowPtr mainwin,backwin;
36CTabHandle MacCT,saved_pal;
37#ifndef PAL_DIRECT
38PaletteHandle MacPal;
39#endif
40int PixMult;
41
42// Menu Globals
43short OldMBarHeight = 0;
44RgnHandle OldVisRgn = 0;
45
46// DM stuff
47VideoRequestRec requestRec;
48VideoRequestRec originalRec;
49short           currentDepth;
50short           currentHorizontal;
51short           currentVertical;
52
53// Direct Video globals
54GDHandle gd;
55short gVideoRowBytes;
56char *gVideoMem;
57Rect *gRect;
58
59#ifdef VIDEO_DIRECT
60void (*SpeedCopyBits)(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy);
61void SpeedCopyBits1(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy);
62void SpeedCopyBits2(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy);
63#endif
64
65struct DisplayModeRequest
66{
67        // Returned values
68        unsigned short csMode;
69        unsigned long csData;
70
71        // Provided values
72        long DesiredWidth;
73        long DesiredHeight;
74        long DesiredDepth;
75};
76
77pascal void DisplayModeCallback(void* userData, DMListIndexType,
78        DMDisplayModeListEntryPtr pModeInfo)
79{
80        DisplayModeRequest *pRequest = (DisplayModeRequest*)userData;
81
82        // Get timing info and make sure this is an OK display mode
83        VDTimingInfoRec TimingInfo = *(pModeInfo->displayModeTimingInfo);
84        if (TimingInfo.csTimingFlags & 1<<kModeValid)
85        {
86                // How many modes are being enumerated here?
87                unsigned long DepthCount =
88                        pModeInfo->displayModeDepthBlockInfo->depthBlockCount;
89
90                // Filter through each of the modes provided here
91                VDSwitchInfoRec *pSwitchInfo;
92                VPBlock *pVPBlockInfo;
93                for (short Count = 0; Count < DepthCount; ++Count)
94                {
95                        // This provides the csMode and csData information
96                        pSwitchInfo =
97                                pModeInfo->displayModeDepthBlockInfo->
98                                depthVPBlock[Count].depthSwitchInfo;
99
100                        // This tells us the resolution and pixel depth
101                        pVPBlockInfo =
102                                pModeInfo->displayModeDepthBlockInfo->
103                                depthVPBlock[Count].depthVPBlock;
104
105                        if (pVPBlockInfo->vpPixelSize == pRequest->DesiredDepth &&
106                                pVPBlockInfo->vpBounds.right == pRequest->DesiredWidth &&
107                                pVPBlockInfo->vpBounds.bottom == pRequest->DesiredHeight)
108                        {
109                                // Found a mode that matches the request!
110                                pRequest->csMode = pSwitchInfo->csMode;
111                                pRequest->csData = pSwitchInfo->csData;
112                        }
113                }
114        }
115}
116
117class CMacStartup {
118public:
119        CMacStartup()
120        {
121                // Initialize mac toolboxes
122                InitGraf(&qd.thePort);
123    InitFonts();
124    FlushEvents(everyEvent - osMask - diskMask, 0);
125    InitWindows();
126    InitMenus();
127//    TEInit();
128    InitDialogs(0L);
129    InitCursor();
130
131                GUSIDefaultSetup();
132
133    MaxApplZone();
134    MoreMasters();
135
136                requestRec.screenDevice = nil;                                  // find any screen
137                requestRec.reqBitDepth = 8;                                                     // bit depth request
138                requestRec.reqHorizontal = 640;                                 // H request
139                requestRec.reqVertical = 480;                                           // V request
140                requestRec.displayMode = nil;                                           // must init to nil
141                requestRec.depthMode = nil;                                                     // must init to nil
142                requestRec.requestFlags = 1<<kAllValidModesBit;                                         
143                                                                                                                                                                                // give me the HxV over bit depth, and only safe video modes
144
145                // make the request and set it if we have one....
146                RVRequestVideoSetting(&requestRec);
147
148                if (requestRec.screenDevice == nil)             // make sure we found a device...possible if there are no "safe" video modes
149                {
150                        fprintf(stderr,"Can't get current video mode\n");
151                        exit(1);
152                }
153
154                // Get current setting
155                originalRec.screenDevice = requestRec.screenDevice;             // this screen
156                RVGetCurrentVideoSetting(&originalRec);
157               
158                RVSetVideoRequest (&requestRec);
159//              if (noErr != RVConfirmVideoRequest (&requestRec))
160//                      RVSetVideoRequest (&originalRec);
161               
162                PixMapHandle PMH;
163
164                gd = requestRec.screenDevice;
165                PMH = (*gd)->gdPMap;
166                LockPixels(PMH);
167                gVideoRowBytes = (*PMH)->rowBytes & 0x3FFF;
168                gVideoMem = GetPixBaseAddr(PMH);
169                gRect = &(*gd)->gdRect;
170
171#if 0
172
173                for (int y=gRect->top; y<gRect->bottom; y++)
174                        for (int x=gRect->left; x<gRect->right; x++)
175                                *(gVideoMem + (y*gVideoRowBytes+x)) = 0;
176#endif
177
178                // set color table for 8 bit mode
179               
180#ifdef PAL_DIRECT
181                MacCT = (**((**gd).gdPMap)).pmTable;
182#else
183                MacCT = GetCTable(8);
184                MacPal = NewPalette(256,nil,pmTolerant,0);
185                (**MacCT).ctSeed = GetCTSeed();
186#endif
187               
188                PixMult = 1;
189        }
190       
191        ~CMacStartup()
192        {
193                FlushEvents(everyEvent, 0);
194                RVSetVideoRequest (&originalRec);
195                RVSetVideoAsScreenPrefs ();
196        }
197} MacStartup;
198
199int get_vmode()
200{
201        return vmode;
202}
203
204void image::make_page(short width, short height, unsigned char *page_buffer)
205//  creates memory that will be touched externally, for routines to copy to
206//  something will copy this memory to video memory
207{
208  if (special && !special->static_mem)
209  {
210#ifdef VIDEO_DIRECT
211    data=(unsigned char *)jmalloc(width*height,"image::direct_data");
212#else
213                GWorldPtr gw;
214                PixMapHandle pixmaph;
215                QDErr err;
216                Rect r;
217
218        r.left = 0;
219        r.top = 0;
220        r.right = width;
221        r.bottom = height;
222        // use mac image, but set
223                err = NewGWorld( &gw, 8, &r, MacCT, nil, 0 );
224        special->extended_descriptor = gw;
225                pixmaph = GetGWorldPixMap(gw);
226                HLockHi((Handle)pixmaph);
227                LockPixels(pixmaph);
228        data = (unsigned char *)GetPixBaseAddr(pixmaph);
229        (**pixmaph).pmTable = MacCT;
230       
231        // yikes! hack the row bytes
232        (**pixmaph).rowBytes = 0x8000 | width;
233        w = (**pixmaph).rowBytes & 0x3fffl;
234        h = height;
235 #endif
236  }
237  else
238  {
239    if (!page_buffer)
240        // no preallocated image, so allocate some
241      data=(unsigned char *)jmalloc(width*height,"image::data");
242    else
243        // we want to use a preallocated image as this image's memory
244        data=page_buffer;
245  }
246
247  if (special)
248        // set clipping area
249    special->resize(width,height);
250}
251
252void image::delete_page()
253//  frees page memory
254{
255        if (special && !special->static_mem) {
256#ifdef VIDEO_DIRECT
257                jfree(data);
258#else
259                GWorldPtr gw;
260       
261                gw = (GWorldPtr)special->extended_descriptor;
262               
263                if (gw)
264                        DisposeGWorld(gw);
265#endif
266                special->extended_descriptor = 0;
267        }
268        else if (!special)
269                jfree(data);
270}
271
272void HideMenu()
273{
274        RgnHandle DesktopRgn;
275
276        if (OldMBarHeight == 0)
277        {
278                // Get and copy the current gray region
279                DesktopRgn = LMGetGrayRgn();
280                OldVisRgn = NewRgn();
281                CopyRgn(DesktopRgn, OldVisRgn);
282               
283                // Fudge the menu bar height
284                OldMBarHeight = GetMBarHeight();
285                LMSetMBarHeight(0);
286
287                // Turn the gray into the old gray region plus the menu bar region
288                Rect MenuRect;
289                MenuRect.left = 0;
290                MenuRect.top = 0;
291                MenuRect.right = qd.screenBits.bounds.right;
292                MenuRect.bottom = OldMBarHeight;
293                RgnHandle MenuRgn = NewRgn();
294                RectRgn(MenuRgn, &MenuRect);
295
296                UnionRgn(OldVisRgn, MenuRgn, DesktopRgn);
297                DisposeRgn(MenuRgn);
298        }
299}
300
301void RestoreMenu()
302{
303        if (OldMBarHeight && OldVisRgn)
304        {
305                // Restore the menu bar height
306                LMSetMBarHeight(OldMBarHeight);
307                OldMBarHeight = 0;
308
309                // Restore the old desktop region
310                CopyRgn(OldVisRgn, LMGetGrayRgn());
311                DisposeRgn(OldVisRgn);
312                OldVisRgn = 0;
313               
314                // Redraw the menu bar
315                HiliteMenu(0);
316                DrawMenuBar();
317        }
318}
319
320void set_mode(int mode, int argc, char **argv)
321{
322        Rect CurBounds;
323        GrafPtr savePort;
324
325#ifdef VIDEO_DIRECT
326  // select copy routine
327  switch (PixMult)
328  {
329        case 1:  SpeedCopyBits = &SpeedCopyBits1; break;
330        case 2:  SpeedCopyBits = &SpeedCopyBits2; break;
331        default:
332                fprintf(stderr,"Aiiieee!  Can't set direct video copier.. it's gonna blow!\n");
333                break;
334  }
335#endif
336
337        HideMenu();     
338
339        Bounds = *gRect;
340
341        backwin = (CWindowPtr)NewCWindow(nil, &Bounds, "\p", TRUE, 2, (WindowPtr)-1L, FALSE, 0);
342
343        Bounds.left = (gRect->left+gRect->right)/2 - xres/2 * PixMult;
344        Bounds.right = (gRect->left+gRect->right)/2 + xres/2 * PixMult;
345        Bounds.top = (gRect->top+gRect->bottom)/2 - yres/2 * PixMult;
346        Bounds.bottom = (gRect->top+gRect->bottom)/2 + yres/2 * PixMult;
347        mainwin = (CWindowPtr)NewCWindow(nil, &Bounds, "\p", TRUE, 2, (WindowPtr)-1L, FALSE, 0);
348        SetGWorld((GWorldPtr)mainwin,gd);
349        CurBounds = mainwin->portRect;
350
351        xres = (Bounds.right - Bounds.left)/PixMult;
352        yres = (Bounds.bottom - Bounds.top)/PixMult;
353
354        // save old palette
355        saved_pal = (**((**gd).gdPMap)).pmTable;
356        HandToHand((Handle*)&saved_pal);
357       
358        // erase cursor
359        ShieldCursor(&CurBounds,topLeft((**(mainwin->portPixMap)).bounds));
360
361        // create screen memory
362  screen=new image(xres,yres,NULL,2); 
363
364        // clear screen
365  screen->clear();
366  update_dirty(screen);
367 
368}
369
370void close_graphics()
371{
372  delete screen;
373
374#ifdef PAL_DIRECT
375        ColorSpec *spec,*spec2;
376        VDSetEntryRecord setEntriesRec;
377        Ptr                              csPtr;
378        QDErr                   error;
379        RgnHandle junkRgn;
380
381        spec = (**MacCT).ctTable;
382        spec2 = (**saved_pal).ctTable;
383        for (int i=0; i<(**MacCT).ctSize; i++)
384        {
385                spec[i].rgb.red = spec2[i].rgb.red;
386                spec[i].rgb.green = spec2[i].rgb.green;
387                spec[i].rgb.blue = spec2[i].rgb.blue;
388                spec[i].value = spec2[i].value;
389        }
390        setEntriesRec.csTable = (ColorSpec *)&(**MacCT).ctTable;
391        setEntriesRec.csStart = 0;
392        setEntriesRec.csCount = (**MacCT).ctSize;
393        csPtr = (Ptr) &setEntriesRec;
394        error = Control ((**gd).gdRefNum, cscSetEntries, (Ptr) &csPtr);
395        if (error)
396                fprintf(stderr,"aieee! palette problem!\n");
397#else
398        // restore palette
399        MacPal = NewPalette((**saved_pal).ctSize,saved_pal,pmTolerant,0);
400        NSetPalette((WindowPtr)mainwin,MacPal,pmAllUpdates);
401        ActivatePalette((WindowPtr)mainwin);
402#endif
403        // restore cursor
404        ShowCursor();
405
406        CloseWindow((WindowPtr)mainwin);
407        CloseWindow((WindowPtr)backwin);
408       
409        RestoreMenu();
410}
411
412#ifdef VIDEO_DIRECT
413
414void SpeedCopyBits1(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy)
415{
416        int x,y;
417        unsigned char *p,*q,*pp,*qq;
418        unsigned long srclen = im->width();
419       
420        p = (unsigned char *)im->scan_line(sy1) + sx1;
421        q = (unsigned char *)gVideoMem + gVideoRowBytes*(dy+Bounds.top) + (dx+Bounds.left);
422        for (y=sy1; y<=sy2; y++)
423        {
424                pp = p;
425                qq = q;
426                for (x=sx1; x<=sx2; x++)
427                        *(qq++) = *(pp++);
428                p += srclen;
429                q += gVideoRowBytes;
430        }
431}
432
433void SpeedCopyBits2(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy)
434{
435        int x,y;
436        unsigned char *p,*pp;
437        unsigned short *q,*qq,*qq2,dat;
438        unsigned long srclen = im->width();
439       
440        p = (unsigned char *)im->scan_line(sy1) + sx1;
441        q = (unsigned short*)((unsigned char *)gVideoMem +
442                                                                                                gVideoRowBytes*(dy*2+Bounds.top) + (dx*2+Bounds.left));
443        for (y=sy1; y<=sy2; y++)
444        {
445                pp = p;
446                qq = q;
447                qq2 = (unsigned short*)((unsigned char*)q + gVideoRowBytes);
448                for (x=sx1; x<=sx2; x++) {
449                        dat = *(pp++);
450                        dat |= dat<<8;
451                        *(qq++) = dat;
452                        *(qq2++) = dat;
453                }
454                p += srclen;
455                q += gVideoRowBytes;
456        }
457}
458
459#endif
460
461void update_dirty(image *im, int xoff, int yoff)
462// go through list of dirty rects & display
463{
464  int count;
465  dirty_rect *dr,*q;
466  image *Xim;
467  CHECK(im->special);  // make sure the image has the ablity to contain dirty areas
468  if (im->special->keep_dirt==0)
469//    put_image(im,xoff,yoff);
470                q = 0;
471  else
472  {
473    count=im->special->dirties.number_nodes();
474    if (!count) return;  // if nothing to update, return
475    dr= (dirty_rect *) (im->special->dirties.first());
476    while (count>0)
477    {
478#ifdef VIDEO_DIRECT
479                        (*SpeedCopyBits)(im, dr->dx1,dr->dy1, dr->dx2,dr->dy2,
480                                                                                xoff + dr->dx1, yoff + dr->dy1);
481#else
482                GWorldPtr gw;
483                Rect src,dst;
484
485        gw = (GWorldPtr)im->special->extended_descriptor;
486
487        dst.left = (xoff + dr->dx1)*PixMult;
488        dst.top = (yoff + dr->dy1)*PixMult;
489        dst.right = (xoff + dr->dx2 + 1)*PixMult;
490        dst.bottom = (yoff + dr->dy2 + 1)*PixMult;
491        src.left = dr->dx1;
492        src.top = dr->dy1;
493        src.right = dr->dx2 + 1;
494        src.bottom = dr->dy2 + 1;
495                        CopyBits((BitMap *) (*(gw->portPixMap)),
496                                        (BitMap*) (*(mainwin->portPixMap)),
497                                        &src,
498                                        &dst,
499                                        srcCopy, nil);
500//      put_part_image(win,im,xoff+dr->dx1,yoff+dr->dy1,dr->dx1,dr->dy1,dr->dx2,dr->dy2);     
501//      XDrawRectangle(display,mainwin,gc,xoff+dr->dx1,yoff+dr->dy1,
502//                   xoff+dr->dx2-dr->dx1+1,yoff+dr->dy2-dr->dy1+1);
503#endif
504      q=dr;
505      dr=(dirty_rect *) (dr->next());
506      im->special->dirties.unlink((linked_node *)q);
507      delete q;
508      count--;
509    }
510  }
511//  XFlush(display);
512}
513
514void fill_image(image *im, int x1, int y1, int x2, int y2);
515void clear_put_image(image *im, int x, int y);
516
517void palette::load()
518{
519#ifdef PAL_DIRECT
520        ColorSpec *spec;
521        VDSetEntryRecord setEntriesRec;
522        Ptr                              csPtr;
523        QDErr                   error;
524
525        spec = (**MacCT).ctTable;
526        for (int i=0; i<(**MacCT).ctSize; i++)
527        {
528                spec[i].rgb.red = red(i) * 256;
529                spec[i].rgb.green = green(i) * 256;
530                spec[i].rgb.blue = blue(i) * 256;
531                spec[i].value = i;
532        }
533        setEntriesRec.csTable = (ColorSpec *)&(**MacCT).ctTable;
534        setEntriesRec.csStart = 0;
535        setEntriesRec.csCount = (**MacCT).ctSize;
536        csPtr = (Ptr) &setEntriesRec;
537        error = Control ((**gd).gdRefNum, cscSetEntries, (Ptr) &csPtr);
538        if (error)
539                fprintf(stderr,"aieee! palette problem!\n");
540#else
541        ColorSpec *spec;
542        spec = (**MacCT).ctTable;
543        for (int i=0; i<pal_size(); i++)
544        {
545                spec[i].rgb.red = red(i) * 256;
546                spec[i].rgb.green = green(i) * 256;
547                spec[i].rgb.blue = blue(i) * 256;
548                spec[i].value = i;
549        }
550//      (**MacCT).ctSeed = GetCTSeed();
551        CTab2Palette(MacCT,MacPal,pmTolerant,0);
552        NSetPalette((WindowPtr)mainwin,MacPal,pmAllUpdates);
553//              HLockHi((Handle)mainwin->portPixMap);
554//              LockPixels(mainwin->portPixMap);
555//      (**mainwin->portPixMap).pmTable = MacCT;
556        ActivatePalette((WindowPtr)mainwin);
557#endif
558}
559
560void palette::load_nice()
561{
562        // adapt palette to system's
563        load();
564}
565
Note: See TracBrowser for help on using the repository browser.