1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      BeOS fullscreen overlay gfx driver.
12  *
13  *      By Angelo Mottola.
14  *
15  *      See readme.txt for copyright information.
16  */
17 
18 #include "bealleg.h"
19 #include "allegro/internal/aintern.h"
20 #include "allegro/platform/aintbeos.h"
21 
22 #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU
23 #error something is wrong with the makefile
24 #endif
25 
26 
27 static char driver_desc[256] = EMPTY_STRING;
28 static display_mode old_display_mode;
29 
30 
31 
32 /* BeAllegroOverlay::BeAllegroOverlay:
33  *  Constructor, creates the window and the overlay bitmap to be used
34  *  as framebuffer.
35  */
BeAllegroOverlay(BRect frame,const char * title,window_look look,window_feel feel,uint32 flags,uint32 workspaces,uint32 v_w,uint32 v_h,uint32 color_depth)36 BeAllegroOverlay::BeAllegroOverlay(BRect frame, const char *title,
37    window_look look, window_feel feel, uint32 flags, uint32 workspaces,
38    uint32 v_w, uint32 v_h, uint32 color_depth)
39    : BWindow(frame, title, look, feel, flags, workspaces)
40 {
41    BRect rect = Bounds();
42    color_space space = B_NO_COLOR_SPACE;
43 
44    _be_allegro_view = new BeAllegroView(rect, "Allegro",
45       B_FOLLOW_ALL_SIDES, B_WILL_DRAW, BE_ALLEGRO_VIEW_OVERLAY);
46    AddChild(_be_allegro_view);
47 
48    switch (color_depth) {
49       case 15: space = B_RGB15; break;
50       case 16: space = B_RGB16; break;
51       case 32: space = B_RGB32; break;
52    }
53    buffer = new BBitmap(rect,
54       B_BITMAP_IS_CONTIGUOUS |
55       B_BITMAP_WILL_OVERLAY |
56       B_BITMAP_RESERVE_OVERLAY_CHANNEL,
57       space);
58 }
59 
60 
61 
62 /* BeAllegroOverlay::BeAllegroOverlay:
63  *  Deletes the overlay bitmap.
64  */
~BeAllegroOverlay()65 BeAllegroOverlay::~BeAllegroOverlay()
66 {
67    Hide();
68    _be_focus_count = 0;
69 
70    if (buffer)
71       delete buffer;
72    buffer = NULL;
73 }
74 
75 
76 
77 /* BeAllegroOverlay::MessageReceived:
78  *  System messages handler.
79  */
MessageReceived(BMessage * message)80 void BeAllegroOverlay::MessageReceived(BMessage *message)
81 {
82    switch (message->what) {
83       case B_SIMPLE_DATA:
84          break;
85 
86       case B_MOUSE_WHEEL_CHANGED:
87          float dy;
88          message->FindFloat("be:wheel_delta_y", &dy);
89          _be_mouse_z += ((int)dy > 0 ? -1 : 1);
90          break;
91 
92       default:
93          BWindow::MessageReceived(message);
94          break;
95    }
96 }
97 
98 
99 
100 /* BeAllegroOverlay::WindowActivated:
101  *  Callback for when the window gains/looses focus.
102  */
WindowActivated(bool active)103 void BeAllegroOverlay::WindowActivated(bool active)
104 {
105    _be_change_focus(active);
106    BWindow::WindowActivated(active);
107 }
108 
109 
110 
111 /* BeAllegroOverlay::QuitRequested:
112  *  User requested to close the program window.
113  */
QuitRequested(void)114 bool BeAllegroOverlay::QuitRequested(void)
115 {
116     return _be_handle_window_close(Title());
117 }
118 
119 
120 
121 /* is_overlay_supported:
122  *  Checks if the card can support hardware scaling from given
123  *  source to dest rectangles.
124  */
is_overlay_supported(BRect * src,BRect * dest)125 static bool is_overlay_supported(BRect *src, BRect *dest)
126 {
127    overlay_restrictions restrictions;
128    float src_w, src_h, dest_w, dest_h;
129 
130    if (_be_allegro_overlay->buffer->GetOverlayRestrictions(&restrictions) != B_OK)
131       return false;
132 
133    src_w = src->right - src->left + 1;
134    src_h = src->bottom - src->top + 1;
135    dest_w = dest->right - dest->left + 1;
136    dest_h = dest->bottom - dest->top + 1;
137 
138    return ((src_w * restrictions.min_width_scale <= dest_w) &&
139            (src_w * restrictions.max_width_scale >= dest_w) &&
140            (src_h * restrictions.min_height_scale <= dest_h) &&
141            (src_h * restrictions.max_height_scale >= dest_h));
142 }
143 
144 
145 
146 /* be_gfx_overlay_init:
147  *  Sets up overlay video mode.
148  */
be_gfx_overlay_init(int w,int h,int v_w,int v_h,int color_depth)149 extern "C" struct BITMAP *be_gfx_overlay_init(int w, int h, int v_w, int v_h, int color_depth)
150 {
151    BITMAP *bmp;
152    BRect src, dest;
153    int i;
154 
155    if (1
156 #ifdef ALLEGRO_COLOR16
157        && (color_depth != 15)
158        && (color_depth != 16)
159 #endif
160 #ifdef ALLEGRO_COLOR32
161        && (color_depth != 32)
162 #endif
163        ) {
164       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth"));
165       return NULL;
166    }
167 
168    if ((!v_w) && (!v_h)) {
169       v_w = w;
170       v_h = h;
171    }
172 
173    if ((w != v_w) || (h != v_h)) {
174       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution"));
175       return NULL;
176    }
177 
178    set_display_switch_mode(SWITCH_PAUSE);
179 
180    BScreen().GetMode(&old_display_mode);
181    for (i=0; _be_mode_table[i].d > 0; i++) {
182       if ((_be_mode_table[i].d == color_depth) &&
183           (_be_mode_table[i].w >= w) &&
184           (_be_mode_table[i].h >= h))
185          break;
186    }
187    if ((_be_mode_table[i].d <= 0) ||
188        (set_screen_space(0, _be_mode_table[i].mode, false) != B_OK)) {
189       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported"));
190       goto cleanup;
191    }
192 
193    src = BRect(0, 0, w - 1, h - 1);
194    dest = BScreen().Frame();
195 
196    _be_allegro_overlay = new BeAllegroOverlay(src, wnd_title,
197 			      B_NO_BORDER_WINDOW_LOOK,
198 			      B_NORMAL_WINDOW_FEEL,
199 			      B_NOT_RESIZABLE | B_NOT_ZOOMABLE,
200 			      B_CURRENT_WORKSPACE, v_w, v_h, color_depth);
201    _be_window = _be_allegro_overlay;
202 
203    if (!_be_allegro_overlay->buffer) {
204       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
205       goto cleanup;
206    }
207    if ((_be_allegro_overlay->buffer->InitCheck() != B_OK) ||
208        (!_be_allegro_overlay->buffer->IsValid()) ||
209        (!is_overlay_supported(&src, &dest))) {
210       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Overlays not supported"));
211       goto cleanup;
212    }
213 
214    _be_mouse_view = new BView(_be_allegro_overlay->Bounds(),
215 			     "allegro mouse view", B_FOLLOW_ALL_SIDES, 0);
216    _be_allegro_overlay->Lock();
217    _be_allegro_overlay->AddChild(_be_mouse_view);
218    _be_allegro_overlay->Unlock();
219 
220    _be_mouse_window = _be_allegro_overlay;
221    _be_mouse_window_mode = true;
222 
223    release_sem(_be_mouse_view_attached);
224 
225    _be_allegro_view->SetViewOverlay(_be_allegro_overlay->buffer,
226       src, dest, &_be_allegro_overlay->color_key, B_FOLLOW_ALL,
227       B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL);
228    _be_allegro_view->ClearViewOverlay();
229 
230    _be_allegro_overlay->ResizeTo(dest.right + 1, dest.bottom + 1);
231    _be_allegro_overlay->MoveTo(0, 0);
232    _be_allegro_overlay->Show();
233 
234    gfx_beos_overlay.w       = w;
235    gfx_beos_overlay.h       = h;
236    gfx_beos_overlay.linear  = TRUE;
237    gfx_beos_overlay.vid_mem = _be_allegro_overlay->buffer->BitsLength();
238 
239    bmp = _make_bitmap(v_w, v_h, (unsigned long)_be_allegro_overlay->buffer->Bits(),
240               &gfx_beos_overlay, color_depth,
241 		      _be_allegro_overlay->buffer->BytesPerRow());
242 
243    if (!bmp) {
244       ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
245       goto cleanup;
246    }
247 
248    _be_gfx_set_truecolor_shifts();
249 
250    uszprintf(driver_desc, sizeof(driver_desc), get_config_text("BWindow object, %d bit BBitmap framebuffer (overlay)"),
251              color_depth);
252    gfx_beos_overlay.desc = driver_desc;
253 
254    _be_gfx_initialized = true;
255 
256    return bmp;
257 
258 cleanup:
259    be_gfx_overlay_exit(NULL);
260    return NULL;
261 }
262 
263 
264 
265 /* be_gfx_overlay_exit:
266  *  Shuts down the driver.
267  */
be_gfx_overlay_exit(struct BITMAP * bmp)268 extern "C" void be_gfx_overlay_exit(struct BITMAP *bmp)
269 {
270    _be_gfx_initialized = false;
271 
272    if (_be_allegro_overlay) {
273       if (_be_mouse_view_attached < 1) {
274          acquire_sem(_be_mouse_view_attached);
275       }
276 
277       _be_allegro_overlay->Lock();
278       _be_allegro_overlay->Quit();
279 
280       _be_allegro_overlay = NULL;
281       _be_window = NULL;
282    }
283    _be_mouse_window   = NULL;
284    _be_mouse_view     = NULL;
285 
286    BScreen().SetMode(&old_display_mode);
287 }
288 
289