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