1/*         ______   ___    ___
2 *        /\  _  \ /\_ \  /\_ \
3 *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4 *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5 *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6 *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 *                                           /\____/
9 *                                           \_/__/
10 *
11 *      MacOS X common quartz (quickdraw) gfx driver functions.
12 *
13 *      By Angelo Mottola, based on similar QNX code by Eric Botcazou.
14 *
15 *      See readme.txt for copyright information.
16 */
17
18
19#include "allegro.h"
20#include "allegro/internal/aintern.h"
21#include "allegro/platform/aintosx.h"
22
23#ifndef ALLEGRO_MACOSX
24   #error something is wrong with the makefile
25#endif
26
27
28
29/* setup_direct_shifts
30 *  Setups direct color shifts.
31 */
32void setup_direct_shifts(void)
33{
34   _rgb_r_shift_15 = 10;
35   _rgb_g_shift_15 = 5;
36   _rgb_b_shift_15 = 0;
37
38   _rgb_r_shift_16 = 11;
39   _rgb_g_shift_16 = 5;
40   _rgb_b_shift_16 = 0;
41
42   _rgb_r_shift_24 = 16;
43   _rgb_g_shift_24 = 8;
44   _rgb_b_shift_24 = 0;
45
46   _rgb_a_shift_32 = 24;
47   _rgb_r_shift_32 = 16;
48   _rgb_g_shift_32 = 8;
49   _rgb_b_shift_32 = 0;
50}
51
52
53
54/* osx_qz_write_line:
55 *  Line switcher for video bitmaps.
56 */
57unsigned long osx_qz_write_line(BITMAP *bmp, int line)
58{
59   if (!(bmp->id & BMP_ID_LOCKED)) {
60      bmp->id |= BMP_ID_LOCKED;
61      if (bmp->extra) {
62         while (!QDDone(BMP_EXTRA(bmp)->port));
63         LockPortBits(BMP_EXTRA(bmp)->port);
64      }
65   }
66
67   return (unsigned long)(bmp->line[line]);
68}
69
70
71
72/* osx_qz_unwrite_line:
73 *  Line updater for video bitmaps.
74 */
75void osx_qz_unwrite_line(BITMAP *bmp)
76{
77   if (bmp->id & BMP_ID_AUTOLOCK) {
78      bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK);
79      if (bmp->extra)
80         UnlockPortBits(BMP_EXTRA(bmp)->port);
81   }
82}
83
84
85
86/* osx_qz_acquire:
87 *  Bitmap locking for video bitmaps.
88 */
89void osx_qz_acquire(BITMAP *bmp)
90{
91   if (!(bmp->id & BMP_ID_LOCKED)) {
92      bmp->id |= BMP_ID_LOCKED;
93      if (bmp->extra) {
94         while (!QDDone(BMP_EXTRA(bmp)->port));
95         while (LockPortBits(BMP_EXTRA(bmp)->port));
96      }
97   }
98}
99
100
101
102/* osx_qz_release:
103 *  Bitmap unlocking for video bitmaps.
104 */
105void osx_qz_release(BITMAP *bmp)
106{
107   bmp->id &= ~BMP_ID_LOCKED;
108   if (bmp->extra)
109      UnlockPortBits(BMP_EXTRA(bmp)->port);
110}
111
112
113
114/* osx_qz_created_sub_bitmap:
115 *  Makes a sub bitmap to inherit the GWorld of its parent.
116 */
117void osx_qz_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
118{
119   bmp->extra = parent->extra;
120}
121
122
123
124/* _make_quickdraw_bitmap:
125 *  Creates a BITMAP using a QuickDraw GWorld as backing store.
126 */
127static BITMAP *_make_quickdraw_bitmap(int width, int height, int flags)
128{
129   BITMAP *bmp;
130   GWorldPtr gworld;
131   Rect rect;
132   char *addr;
133   int pitch;
134   int i, size;
135
136   /* create new GWorld */
137   SetRect(&rect, 0, 0, width, height);
138   if (NewGWorld(&gworld, screen->vtable->color_depth, &rect, NULL, NULL, flags))
139      return NULL;
140
141   LockPortBits(gworld);
142   addr = GetPixBaseAddr(GetPortPixMap(gworld));
143   pitch = GetPixRowBytes(GetPortPixMap(gworld));
144   UnlockPortBits(gworld);
145   if (!addr) {
146      DisposeGWorld(gworld);
147      return NULL;
148   }
149
150   /* create Allegro bitmap */
151   size = sizeof(BITMAP) + sizeof(char *) * height;
152
153   bmp = (BITMAP *) malloc(size);
154   if (!bmp) {
155      DisposeGWorld(gworld);
156      return NULL;
157   }
158
159   bmp->w = bmp->cr = width;
160   bmp->h = bmp->cb = height;
161   bmp->clip = TRUE;
162   bmp->cl = bmp->ct = 0;
163   bmp->vtable = &_screen_vtable;
164   bmp->write_bank = bmp->read_bank = osx_qz_write_line;
165   bmp->dat = NULL;
166   bmp->id = BMP_ID_VIDEO;
167   bmp->extra = NULL;
168   bmp->x_ofs = 0;
169   bmp->y_ofs = 0;
170   bmp->seg = _video_ds();
171
172   bmp->line[0] = (unsigned char *)addr;
173
174   for (i = 1; i < height; i++)
175      bmp->line[i] = bmp->line[i - 1] + pitch;
176
177   /* setup surface info structure to store additional information */
178   bmp->extra = malloc(sizeof(struct BMP_EXTRA_INFO));
179   if (!bmp->extra) {
180      free(bmp);
181      DisposeGWorld(gworld);
182      return NULL;
183   }
184   BMP_EXTRA(bmp)->port = gworld;
185
186   return bmp;
187}
188
189
190
191/* osx_qz_create_video_bitmap:
192 *  Tries to allocate a BITMAP in video memory.
193 */
194BITMAP *osx_qz_create_video_bitmap(int width, int height)
195{
196   if ((gfx_driver->w == width) && (gfx_driver->h == height) && (!osx_screen_used)) {
197      osx_screen_used = TRUE;
198      return screen;
199   }
200   return _make_quickdraw_bitmap(width, height, useDistantHdwrMem);
201}
202
203
204
205/* osx_qz_create_system_bitmap:
206 *  Tries to allocates a BITMAP in AGP memory.
207 */
208BITMAP *osx_qz_create_system_bitmap(int width, int height)
209{
210   return _make_quickdraw_bitmap(width, height, useLocalHdwrMem);
211}
212
213
214
215/* osx_qz_destroy_video_bitmap:
216 *  Frees memory used by bitmap structure and releases associated GWorld.
217 */
218void osx_qz_destroy_video_bitmap(BITMAP *bmp)
219{
220   if (bmp) {
221     if (bmp == screen) {
222        osx_screen_used = FALSE;
223        return;
224     }
225     if (bmp->extra) {
226         if (BMP_EXTRA(bmp)->port)
227            DisposeGWorld(BMP_EXTRA(bmp)->port);
228         free(bmp->extra);
229      }
230      free(bmp);
231   }
232}
233
234
235
236/* osx_qz_blit_to_self:
237 *  Accelerated vram -> vram blitting routine.
238 */
239void osx_qz_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
240{
241   Rect source_rect, dest_rect;
242
243   SetRect(&source_rect, source_x + source->x_ofs, source_y + source->y_ofs,
244      source_x + source->x_ofs + width, source_y + source->y_ofs + height);
245   SetRect(&dest_rect, dest_x + dest->x_ofs, dest_y + dest->y_ofs,
246      dest_x + dest->x_ofs + width, dest_y + dest->y_ofs + height);
247
248   while (!QDDone(BMP_EXTRA(dest)->port));
249   if (!(dest->id & BMP_ID_LOCKED))
250      LockPortBits(BMP_EXTRA(dest)->port);
251   CopyBits(GetPortBitMapForCopyBits(BMP_EXTRA(source)->port),
252            GetPortBitMapForCopyBits(BMP_EXTRA(dest)->port),
253	    &source_rect, &dest_rect, srcCopy, NULL);
254   if (!(dest->id & BMP_ID_LOCKED))
255      UnlockPortBits(BMP_EXTRA(dest)->port);
256}
257