/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * BeOS fullscreen overlay gfx driver. * * By Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #ifndef ALLEGRO_BEOS #error something is wrong with the makefile #endif static char driver_desc[256] = EMPTY_STRING; static display_mode old_display_mode; /* BeAllegroOverlay::BeAllegroOverlay: * Constructor, creates the window and the overlay bitmap to be used * as framebuffer. */ BeAllegroOverlay::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) : BWindow(frame, title, look, feel, flags, workspaces) { BRect rect = Bounds(); color_space space = B_NO_COLOR_SPACE; _be_allegro_view = new BeAllegroView(rect, "Allegro", B_FOLLOW_ALL_SIDES, B_WILL_DRAW, BE_ALLEGRO_VIEW_OVERLAY); AddChild(_be_allegro_view); switch (color_depth) { case 15: space = B_RGB15; break; case 16: space = B_RGB16; break; case 32: space = B_RGB32; break; } buffer = new BBitmap(rect, B_BITMAP_IS_CONTIGUOUS | B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, space); } /* BeAllegroOverlay::BeAllegroOverlay: * Deletes the overlay bitmap. */ BeAllegroOverlay::~BeAllegroOverlay() { Hide(); _be_focus_count = 0; if (buffer) delete buffer; buffer = NULL; } /* BeAllegroOverlay::MessageReceived: * System messages handler. */ void BeAllegroOverlay::MessageReceived(BMessage *message) { switch (message->what) { case B_SIMPLE_DATA: break; case B_MOUSE_WHEEL_CHANGED: float dy; message->FindFloat("be:wheel_delta_y", &dy); _be_mouse_z += ((int)dy > 0 ? -1 : 1); break; default: BWindow::MessageReceived(message); break; } } /* BeAllegroOverlay::WindowActivated: * Callback for when the window gains/looses focus. */ void BeAllegroOverlay::WindowActivated(bool active) { _be_change_focus(active); BWindow::WindowActivated(active); } /* BeAllegroOverlay::QuitRequested: * User requested to close the program window. */ bool BeAllegroOverlay::QuitRequested(void) { return _be_handle_window_close(Title()); } /* is_overlay_supported: * Checks if the card can support hardware scaling from given * source to dest rectangles. */ static bool is_overlay_supported(BRect *src, BRect *dest) { overlay_restrictions restrictions; float src_w, src_h, dest_w, dest_h; if (_be_allegro_overlay->buffer->GetOverlayRestrictions(&restrictions) != B_OK) return false; src_w = src->right - src->left + 1; src_h = src->bottom - src->top + 1; dest_w = dest->right - dest->left + 1; dest_h = dest->bottom - dest->top + 1; return ((src_w * restrictions.min_width_scale <= dest_w) && (src_w * restrictions.max_width_scale >= dest_w) && (src_h * restrictions.min_height_scale <= dest_h) && (src_h * restrictions.max_height_scale >= dest_h)); } /* be_gfx_overlay_init: * Sets up overlay video mode. */ extern "C" struct BITMAP *be_gfx_overlay_init(int w, int h, int v_w, int v_h, int color_depth) { BITMAP *bmp; BRect src, dest; int i; if (1 #ifdef ALLEGRO_COLOR16 && (color_depth != 15) && (color_depth != 16) #endif #ifdef ALLEGRO_COLOR32 && (color_depth != 32) #endif ) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported color depth")); return NULL; } if ((!v_w) && (!v_h)) { v_w = w; v_h = h; } if ((w != v_w) || (h != v_h)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported virtual resolution")); return NULL; } set_display_switch_mode(SWITCH_PAUSE); BScreen().GetMode(&old_display_mode); for (i=0; _be_mode_table[i].d > 0; i++) { if ((_be_mode_table[i].d == color_depth) && (_be_mode_table[i].w >= w) && (_be_mode_table[i].h >= h)) break; } if ((_be_mode_table[i].d <= 0) || (set_screen_space(0, _be_mode_table[i].mode, false) != B_OK)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported")); goto cleanup; } src = BRect(0, 0, w - 1, h - 1); dest = BScreen().Frame(); _be_allegro_overlay = new BeAllegroOverlay(src, wnd_title, B_NO_BORDER_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_CURRENT_WORKSPACE, v_w, v_h, color_depth); _be_window = _be_allegro_overlay; if (!_be_allegro_overlay->buffer) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } if ((_be_allegro_overlay->buffer->InitCheck() != B_OK) || (!_be_allegro_overlay->buffer->IsValid()) || (!is_overlay_supported(&src, &dest))) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Overlays not supported")); goto cleanup; } _be_mouse_view = new BView(_be_allegro_overlay->Bounds(), "allegro mouse view", B_FOLLOW_ALL_SIDES, 0); _be_allegro_overlay->Lock(); _be_allegro_overlay->AddChild(_be_mouse_view); _be_allegro_overlay->Unlock(); _be_mouse_window = _be_allegro_overlay; _be_mouse_window_mode = true; release_sem(_be_mouse_view_attached); _be_allegro_view->SetViewOverlay(_be_allegro_overlay->buffer, src, dest, &_be_allegro_overlay->color_key, B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL); _be_allegro_view->ClearViewOverlay(); _be_allegro_overlay->ResizeTo(dest.right + 1, dest.bottom + 1); _be_allegro_overlay->MoveTo(0, 0); _be_allegro_overlay->Show(); gfx_beos_overlay.w = w; gfx_beos_overlay.h = h; gfx_beos_overlay.linear = TRUE; gfx_beos_overlay.vid_mem = _be_allegro_overlay->buffer->BitsLength(); bmp = _make_bitmap(v_w, v_h, (unsigned long)_be_allegro_overlay->buffer->Bits(), &gfx_beos_overlay, color_depth, _be_allegro_overlay->buffer->BytesPerRow()); if (!bmp) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory")); goto cleanup; } _be_gfx_set_truecolor_shifts(); uszprintf(driver_desc, sizeof(driver_desc), get_config_text("BWindow object, %d bit BBitmap framebuffer (overlay)"), color_depth); gfx_beos_overlay.desc = driver_desc; _be_gfx_initialized = true; return bmp; cleanup: be_gfx_overlay_exit(NULL); return NULL; } /* be_gfx_overlay_exit: * Shuts down the driver. */ extern "C" void be_gfx_overlay_exit(struct BITMAP *bmp) { _be_gfx_initialized = false; if (_be_allegro_overlay) { if (_be_mouse_view_attached < 1) { acquire_sem(_be_mouse_view_attached); } _be_allegro_overlay->Lock(); _be_allegro_overlay->Quit(); _be_allegro_overlay = NULL; _be_window = NULL; } _be_mouse_window = NULL; _be_mouse_view = NULL; BScreen().SetMode(&old_display_mode); }