1054 lines
21 KiB
C++
1054 lines
21 KiB
C++
/*
|
|
* Copyright 2002-2009, Haiku. All Rights Reserved.
|
|
* Copyright 2002-2005,
|
|
* Marcus Overhagen,
|
|
* Stefano Ceccherini (stefano.ceccherini@gmail.com),
|
|
* Carwyn Jones (turok2@currantbun.com)
|
|
* All rights reserved.
|
|
*
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include <WindowScreen.h>
|
|
|
|
#include <new>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <Application.h>
|
|
#include <Screen.h>
|
|
#include <String.h>
|
|
|
|
#include <AppServerLink.h>
|
|
#include <input_globals.h>
|
|
#include <InputServerTypes.h>
|
|
#include <InterfacePrivate.h>
|
|
#include <ServerProtocol.h>
|
|
#include <WindowPrivate.h>
|
|
|
|
|
|
using BPrivate::AppServerLink;
|
|
|
|
|
|
//#define TRACE_WINDOWSCREEN 1
|
|
#if TRACE_WINDOWSCREEN
|
|
# define CALLED() printf("%s\n", __PRETTY_FUNCTION__);
|
|
#else
|
|
# define CALLED() ;
|
|
#endif
|
|
|
|
|
|
// Acceleration hooks pointers
|
|
static fill_rectangle sFillRectHook;
|
|
static screen_to_screen_blit sBlitRectHook;
|
|
static screen_to_screen_transparent_blit sTransparentBlitHook;
|
|
static screen_to_screen_scaled_filtered_blit sScaledFilteredBlitHook;
|
|
static wait_engine_idle sWaitIdleHook;
|
|
static acquire_engine sAcquireEngineHook;
|
|
static release_engine sReleaseEngineHook;
|
|
|
|
static engine_token *sEngineToken;
|
|
|
|
|
|
// Helper methods which translates the pre r5 graphics methods to r5 ones
|
|
static int32
|
|
card_sync()
|
|
{
|
|
sWaitIdleHook();
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int32
|
|
blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width, int32 height)
|
|
{
|
|
blit_params param;
|
|
param.src_left = sx;
|
|
param.src_top = sy;
|
|
param.dest_left = dx;
|
|
param.dest_top = dy;
|
|
param.width = width;
|
|
param.height = height;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
|
|
sBlitRectHook(sEngineToken, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// TODO: This function seems not to be exported through CardHookAt().
|
|
// At least, nothing I've tried uses it.
|
|
#if 0
|
|
static int32
|
|
transparent_blit(int32 sx, int32 sy, int32 dx, int32 dy, int32 width,
|
|
int32 height, uint32 transparent_color)
|
|
{
|
|
blit_params param;
|
|
param.src_left = sx;
|
|
param.src_top = sy;
|
|
param.dest_left = dx;
|
|
param.dest_top = dy;
|
|
param.width = width;
|
|
param.height = height;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, 0, &sEngineToken);
|
|
sTransparentBlitHook(sEngineToken, transparent_color, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, 0);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
static int32
|
|
scaled_filtered_blit(int32 sx, int32 sy, int32 sw, int32 sh, int32 dx, int32 dy,
|
|
int32 dw, int32 dh)
|
|
{
|
|
scaled_blit_params param;
|
|
param.src_left = sx;
|
|
param.src_top = sy;
|
|
param.src_width = sw;
|
|
param.src_height = sh;
|
|
param.dest_left = dx;
|
|
param.dest_top = dy;
|
|
param.dest_width = dw;
|
|
param.dest_height = dh;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
|
|
sScaledFilteredBlitHook(sEngineToken, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int32
|
|
draw_rect_8(int32 sx, int32 sy, int32 sw, int32 sh, uint8 color_index)
|
|
{
|
|
fill_rect_params param;
|
|
param.left = sx;
|
|
param.top = sy;
|
|
param.right = sw;
|
|
param.bottom = sh;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
|
|
sFillRectHook(sEngineToken, color_index, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int32
|
|
draw_rect_16(int32 sx, int32 sy, int32 sw, int32 sh, uint16 color)
|
|
{
|
|
fill_rect_params param;
|
|
param.left = sx;
|
|
param.top = sy;
|
|
param.right = sw;
|
|
param.bottom = sh;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
|
|
sFillRectHook(sEngineToken, color, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int32
|
|
draw_rect_32(int32 sx, int32 sy, int32 sw, int32 sh, uint32 color)
|
|
{
|
|
fill_rect_params param;
|
|
param.left = sx;
|
|
param.top = sy;
|
|
param.right = sw;
|
|
param.bottom = sh;
|
|
|
|
sAcquireEngineHook(B_2D_ACCELERATION, 0xff, NULL, &sEngineToken);
|
|
sFillRectHook(sEngineToken, color, ¶m, 1);
|
|
sReleaseEngineHook(sEngineToken, NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// #pragma mark - public API calls
|
|
|
|
|
|
void
|
|
set_mouse_position(int32 x, int32 y)
|
|
{
|
|
BMessage command(IS_SET_MOUSE_POSITION);
|
|
BMessage reply;
|
|
|
|
command.AddPoint("where", BPoint(x, y));
|
|
_control_input_server_(&command, &reply);
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
BWindowScreen::BWindowScreen(const char *title, uint32 space, status_t *error,
|
|
bool debugEnable)
|
|
:
|
|
BWindow(BScreen().Frame(), title, B_NO_BORDER_WINDOW_LOOK,
|
|
kWindowScreenFeel, kWindowScreenFlag | B_NOT_MINIMIZABLE
|
|
| B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
|
|
B_CURRENT_WORKSPACE)
|
|
{
|
|
CALLED();
|
|
uint32 attributes = 0;
|
|
if (debugEnable)
|
|
attributes |= B_ENABLE_DEBUGGER;
|
|
|
|
status_t status = _InitData(space, attributes);
|
|
if (error)
|
|
*error = status;
|
|
}
|
|
|
|
|
|
BWindowScreen::BWindowScreen(const char *title, uint32 space,
|
|
uint32 attributes, status_t *error)
|
|
:
|
|
BWindow(BScreen().Frame(), title, B_NO_BORDER_WINDOW_LOOK,
|
|
kWindowScreenFeel, kWindowScreenFlag | B_NOT_MINIMIZABLE
|
|
| B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MOVABLE | B_NOT_RESIZABLE,
|
|
B_CURRENT_WORKSPACE)
|
|
{
|
|
CALLED();
|
|
status_t status = _InitData(space, attributes);
|
|
if (error)
|
|
*error = status;
|
|
}
|
|
|
|
|
|
BWindowScreen::~BWindowScreen()
|
|
{
|
|
CALLED();
|
|
_DisposeData();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::Quit(void)
|
|
{
|
|
CALLED();
|
|
Disconnect();
|
|
BWindow::Quit();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::ScreenConnected(bool active)
|
|
{
|
|
// Implemented in subclasses
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::Disconnect()
|
|
{
|
|
CALLED();
|
|
if (fLockState == 1) {
|
|
if (fDebugState)
|
|
fDebugFirst = true;
|
|
_Deactivate();
|
|
}
|
|
|
|
be_app->ShowCursor();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::WindowActivated(bool active)
|
|
{
|
|
CALLED();
|
|
fWindowState = active;
|
|
if (active && fLockState == 0 && fWorkState)
|
|
_Activate();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::WorkspaceActivated(int32 workspace, bool state)
|
|
{
|
|
CALLED();
|
|
fWorkState = state;
|
|
|
|
if (state) {
|
|
if (fLockState == 0 && fWindowState) {
|
|
_Activate();
|
|
if (!IsHidden()) {
|
|
Activate(true);
|
|
WindowActivated(true);
|
|
}
|
|
}
|
|
} else if (fLockState)
|
|
_Deactivate();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::ScreenChanged(BRect screenFrame, color_space depth)
|
|
{
|
|
// Implemented in subclasses
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::Hide()
|
|
{
|
|
CALLED();
|
|
|
|
Disconnect();
|
|
BWindow::Hide();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::Show()
|
|
{
|
|
CALLED();
|
|
|
|
BWindow::Show();
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::SetColorList(rgb_color *list, int32 firstIndex, int32 lastIndex)
|
|
{
|
|
CALLED();
|
|
if (firstIndex < 0 || lastIndex > 255 || firstIndex > lastIndex)
|
|
return;
|
|
|
|
if (!Lock())
|
|
return;
|
|
|
|
if (!fActivateState) {
|
|
// If we aren't active, we just change our local palette
|
|
for (int32 x = firstIndex; x <= lastIndex; x++) {
|
|
fPalette[x] = list[x - firstIndex];
|
|
}
|
|
} else {
|
|
uint8 colors[3 * 256];
|
|
// the color table has 3 bytes per color
|
|
int32 j = 0;
|
|
|
|
for (int32 x = firstIndex; x <= lastIndex; x++) {
|
|
fPalette[x] = list[x - firstIndex];
|
|
// update our local palette as well
|
|
|
|
colors[j++] = fPalette[x].red;
|
|
colors[j++] = fPalette[x].green;
|
|
colors[j++] = fPalette[x].blue;
|
|
}
|
|
|
|
if (fAddonImage >= 0) {
|
|
set_indexed_colors setIndexedColors
|
|
= (set_indexed_colors)fGetAccelerantHook(B_SET_INDEXED_COLORS,
|
|
NULL);
|
|
if (setIndexedColors != NULL) {
|
|
setIndexedColors(255, 0,
|
|
colors, 0);
|
|
}
|
|
}
|
|
|
|
// TODO: Tell the app_server about our changes
|
|
|
|
BScreen screen(this);
|
|
screen.WaitForRetrace();
|
|
}
|
|
|
|
Unlock();
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::SetSpace(uint32 space)
|
|
{
|
|
CALLED();
|
|
|
|
display_mode mode;
|
|
status_t status = _GetModeFromSpace(space, &mode);
|
|
if (status == B_OK)
|
|
status = _AssertDisplayMode(&mode);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
bool
|
|
BWindowScreen::CanControlFrameBuffer()
|
|
{
|
|
return (fCardInfo.flags & B_FRAME_BUFFER_CONTROL) != 0;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::SetFrameBuffer(int32 width, int32 height)
|
|
{
|
|
CALLED();
|
|
display_mode highMode = *fDisplayMode;
|
|
highMode.flags |= B_SCROLL;
|
|
|
|
highMode.virtual_height = (int16)height;
|
|
highMode.virtual_width = (int16)width;
|
|
|
|
display_mode lowMode = highMode;
|
|
display_mode mode = highMode;
|
|
|
|
BScreen screen(this);
|
|
status_t status = screen.ProposeMode(&mode, &lowMode, &highMode);
|
|
if (status == B_OK)
|
|
status = _AssertDisplayMode(&mode);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::MoveDisplayArea(int32 x, int32 y)
|
|
{
|
|
CALLED();
|
|
move_display_area moveDisplayArea
|
|
= (move_display_area)fGetAccelerantHook(B_MOVE_DISPLAY, NULL);
|
|
if (moveDisplayArea && moveDisplayArea((int16)x, (int16)y) == B_OK) {
|
|
fFrameBufferInfo.display_x = x;
|
|
fFrameBufferInfo.display_y = y;
|
|
fDisplayMode->h_display_start = x;
|
|
fDisplayMode->v_display_start = y;
|
|
return B_OK;
|
|
}
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
#if 0
|
|
void *
|
|
BWindowScreen::IOBase()
|
|
{
|
|
// Not supported
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
rgb_color *
|
|
BWindowScreen::ColorList()
|
|
{
|
|
CALLED();
|
|
return fPalette;
|
|
}
|
|
|
|
|
|
frame_buffer_info *
|
|
BWindowScreen::FrameBufferInfo()
|
|
{
|
|
CALLED();
|
|
return &fFrameBufferInfo;
|
|
}
|
|
|
|
|
|
graphics_card_hook
|
|
BWindowScreen::CardHookAt(int32 index)
|
|
{
|
|
CALLED();
|
|
if (fAddonImage < 0)
|
|
return NULL;
|
|
|
|
graphics_card_hook hook = NULL;
|
|
|
|
switch (index) {
|
|
case 5: // 8 bit fill rect
|
|
if (sFillRectHook)
|
|
hook = (graphics_card_hook)draw_rect_8;
|
|
break;
|
|
case 6: // 32 bit fill rect
|
|
if (sFillRectHook)
|
|
hook = (graphics_card_hook)draw_rect_32;
|
|
break;
|
|
case 7: // screen to screen blit
|
|
if (sBlitRectHook)
|
|
hook = (graphics_card_hook)blit;
|
|
break;
|
|
case 8: // screen to screen scaled filtered blit
|
|
if (sScaledFilteredBlitHook)
|
|
hook = (graphics_card_hook)scaled_filtered_blit;
|
|
break;
|
|
case 10: // sync aka wait for graphics card idle
|
|
if (sWaitIdleHook)
|
|
hook = (graphics_card_hook)card_sync;
|
|
break;
|
|
case 13: // 16 bit fill rect
|
|
if (sFillRectHook)
|
|
hook = (graphics_card_hook)draw_rect_16;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return hook;
|
|
}
|
|
|
|
|
|
graphics_card_info *
|
|
BWindowScreen::CardInfo()
|
|
{
|
|
CALLED();
|
|
return &fCardInfo;
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::RegisterThread(thread_id thread)
|
|
{
|
|
CALLED();
|
|
|
|
status_t status;
|
|
do {
|
|
status = acquire_sem(fDebugSem);
|
|
} while (status == B_INTERRUPTED);
|
|
|
|
if (status < B_OK)
|
|
return;
|
|
|
|
void *newDebugList = realloc(fDebugThreads,
|
|
(fDebugThreadCount + 1) * sizeof(thread_id));
|
|
if (newDebugList != NULL) {
|
|
fDebugThreads = (thread_id *)newDebugList;
|
|
fDebugThreads[fDebugThreadCount] = thread;
|
|
fDebugThreadCount++;
|
|
}
|
|
release_sem(fDebugSem);
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::SuspensionHook(bool active)
|
|
{
|
|
// Implemented in subclasses
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::Suspend(char* label)
|
|
{
|
|
CALLED();
|
|
if (fDebugState) {
|
|
fprintf(stderr, "## Debugger(\"%s\").", label);
|
|
fprintf(stderr, " Press Alt-F%" B_PRId32 " or Cmd-F%" B_PRId32 " to resume.\n",
|
|
fWorkspaceIndex + 1, fWorkspaceIndex + 1);
|
|
|
|
if (IsLocked())
|
|
Unlock();
|
|
|
|
activate_workspace(fDebugWorkspace);
|
|
|
|
// Suspend ourself
|
|
suspend_thread(find_thread(NULL));
|
|
|
|
Lock();
|
|
}
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::Perform(perform_code d, void* arg)
|
|
{
|
|
return inherited::Perform(d, arg);
|
|
}
|
|
|
|
|
|
// Reserved for future binary compatibility
|
|
void BWindowScreen::_ReservedWindowScreen1() {}
|
|
void BWindowScreen::_ReservedWindowScreen2() {}
|
|
void BWindowScreen::_ReservedWindowScreen3() {}
|
|
void BWindowScreen::_ReservedWindowScreen4() {}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_InitData(uint32 space, uint32 attributes)
|
|
{
|
|
CALLED();
|
|
|
|
fDebugState = attributes & B_ENABLE_DEBUGGER;
|
|
fDebugThreadCount = 0;
|
|
fDebugThreads = NULL;
|
|
fDebugFirst = true;
|
|
|
|
fAttributes = attributes;
|
|
// TODO: not really used right now, but should probably be known by
|
|
// the app_server
|
|
|
|
fWorkspaceIndex = fDebugWorkspace = current_workspace();
|
|
fLockState = 0;
|
|
fAddonImage = -1;
|
|
fWindowState = 0;
|
|
fOriginalDisplayMode = NULL;
|
|
fDisplayMode = NULL;
|
|
fModeList = NULL;
|
|
fModeCount = 0;
|
|
fDebugSem = -1;
|
|
fActivateState = false;
|
|
fWorkState = false;
|
|
|
|
status_t status = B_ERROR;
|
|
try {
|
|
fOriginalDisplayMode = new display_mode;
|
|
fDisplayMode = new display_mode;
|
|
|
|
BScreen screen(this);
|
|
status = screen.GetMode(fOriginalDisplayMode);
|
|
if (status < B_OK)
|
|
throw status;
|
|
|
|
status = screen.GetModeList(&fModeList, &fModeCount);
|
|
if (status < B_OK)
|
|
throw status;
|
|
|
|
status = _GetModeFromSpace(space, fDisplayMode);
|
|
if (status < B_OK)
|
|
throw status;
|
|
|
|
status = _GetCardInfo();
|
|
if (status < B_OK)
|
|
throw status;
|
|
|
|
fDebugSem = create_sem(1, "WindowScreen debug sem");
|
|
if (fDebugSem < B_OK)
|
|
throw (status_t)fDebugSem;
|
|
|
|
memcpy((void*)fPalette, screen.ColorMap()->color_list, sizeof(fPalette));
|
|
fActivateState = false;
|
|
fWorkState = true;
|
|
|
|
status = B_OK;
|
|
} catch (std::bad_alloc&) {
|
|
status = B_NO_MEMORY;
|
|
} catch (status_t error) {
|
|
status = error;
|
|
} catch (...) {
|
|
status = B_ERROR;
|
|
}
|
|
|
|
if (status != B_OK)
|
|
_DisposeData();
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::_DisposeData()
|
|
{
|
|
CALLED();
|
|
Disconnect();
|
|
if (fAddonImage >= 0) {
|
|
unload_add_on(fAddonImage);
|
|
fAddonImage = -1;
|
|
}
|
|
|
|
delete_sem(fDebugSem);
|
|
fDebugSem = -1;
|
|
|
|
if (fDebugState)
|
|
activate_workspace(fDebugWorkspace);
|
|
|
|
delete fDisplayMode;
|
|
fDisplayMode = NULL;
|
|
delete fOriginalDisplayMode;
|
|
fOriginalDisplayMode = NULL;
|
|
free(fModeList);
|
|
fModeList = NULL;
|
|
fModeCount = 0;
|
|
|
|
fLockState = 0;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_LockScreen(bool lock)
|
|
{
|
|
if (fActivateState == lock)
|
|
return B_OK;
|
|
|
|
// TODO: the BWindowScreen should use the same mechanism as BDirectWindows!
|
|
BPrivate::AppServerLink link;
|
|
|
|
link.StartMessage(AS_DIRECT_SCREEN_LOCK);
|
|
link.Attach<bool>(lock);
|
|
|
|
status_t status = B_ERROR;
|
|
if (link.FlushWithReply(status) == B_OK && status == B_OK)
|
|
fActivateState = lock;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_Activate()
|
|
{
|
|
CALLED();
|
|
status_t status = _AssertDisplayMode(fDisplayMode);
|
|
if (status < B_OK)
|
|
return status;
|
|
|
|
status = _SetupAccelerantHooks();
|
|
if (status < B_OK)
|
|
return status;
|
|
|
|
if (!fActivateState) {
|
|
status = _LockScreen(true);
|
|
if (status != B_OK)
|
|
return status;
|
|
}
|
|
|
|
be_app->HideCursor();
|
|
|
|
SetColorList(fPalette);
|
|
if (fDebugState && !fDebugFirst) {
|
|
SuspensionHook(true);
|
|
_Resume();
|
|
} else {
|
|
fDebugFirst = true;
|
|
ScreenConnected(true);
|
|
}
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_Deactivate()
|
|
{
|
|
CALLED();
|
|
|
|
if (fDebugState && !fDebugFirst) {
|
|
_Suspend();
|
|
SuspensionHook(false);
|
|
} else
|
|
ScreenConnected(false);
|
|
|
|
if (fActivateState) {
|
|
status_t status = _LockScreen(false);
|
|
if (status != B_OK)
|
|
return status;
|
|
|
|
BScreen screen(this);
|
|
SetColorList((rgb_color *)screen.ColorMap()->color_list);
|
|
}
|
|
|
|
_AssertDisplayMode(fOriginalDisplayMode);
|
|
_ResetAccelerantHooks();
|
|
|
|
be_app->ShowCursor();
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_SetupAccelerantHooks()
|
|
{
|
|
CALLED();
|
|
|
|
status_t status = B_OK;
|
|
if (fAddonImage < 0)
|
|
status = _InitClone();
|
|
else
|
|
_ResetAccelerantHooks();
|
|
|
|
if (status == B_OK) {
|
|
sWaitIdleHook = fWaitEngineIdle = (wait_engine_idle)
|
|
fGetAccelerantHook(B_WAIT_ENGINE_IDLE, NULL);
|
|
sReleaseEngineHook
|
|
= (release_engine)fGetAccelerantHook(B_RELEASE_ENGINE, NULL);
|
|
sAcquireEngineHook
|
|
= (acquire_engine)fGetAccelerantHook(B_ACQUIRE_ENGINE, NULL);
|
|
sFillRectHook
|
|
= (fill_rectangle)fGetAccelerantHook(B_FILL_RECTANGLE, NULL);
|
|
sBlitRectHook = (screen_to_screen_blit)
|
|
fGetAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, NULL);
|
|
sTransparentBlitHook = (screen_to_screen_transparent_blit)
|
|
fGetAccelerantHook(B_SCREEN_TO_SCREEN_TRANSPARENT_BLIT, NULL);
|
|
sScaledFilteredBlitHook = (screen_to_screen_scaled_filtered_blit)
|
|
fGetAccelerantHook(B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT, NULL);
|
|
|
|
if (fWaitEngineIdle)
|
|
fWaitEngineIdle();
|
|
|
|
fLockState = 1;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::_ResetAccelerantHooks()
|
|
{
|
|
CALLED();
|
|
if (fWaitEngineIdle)
|
|
fWaitEngineIdle();
|
|
|
|
sFillRectHook = NULL;
|
|
sBlitRectHook = NULL;
|
|
sTransparentBlitHook = NULL;
|
|
sScaledFilteredBlitHook = NULL;
|
|
sWaitIdleHook = NULL;
|
|
sEngineToken = NULL;
|
|
sAcquireEngineHook = NULL;
|
|
sReleaseEngineHook = NULL;
|
|
|
|
fWaitEngineIdle = NULL;
|
|
|
|
fLockState = 0;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_GetCardInfo()
|
|
{
|
|
CALLED();
|
|
|
|
BScreen screen(this);
|
|
display_mode mode;
|
|
status_t status = screen.GetMode(&mode);
|
|
if (status < B_OK)
|
|
return status;
|
|
|
|
uint32 bitsPerPixel;
|
|
switch(mode.space & 0x0fff) {
|
|
case B_CMAP8:
|
|
bitsPerPixel = 8;
|
|
break;
|
|
case B_RGB15:
|
|
bitsPerPixel = 15;
|
|
break;
|
|
case B_RGB16:
|
|
bitsPerPixel = 16;
|
|
break;
|
|
case B_RGB32:
|
|
bitsPerPixel = 32;
|
|
break;
|
|
default:
|
|
bitsPerPixel = 0;
|
|
break;
|
|
}
|
|
|
|
fCardInfo.version = 2;
|
|
fCardInfo.id = screen.ID().id;
|
|
fCardInfo.bits_per_pixel = bitsPerPixel;
|
|
fCardInfo.width = mode.virtual_width;
|
|
fCardInfo.height = mode.virtual_height;
|
|
|
|
if (mode.space & 0x10)
|
|
memcpy(fCardInfo.rgba_order, "rgba", 4);
|
|
else
|
|
memcpy(fCardInfo.rgba_order, "bgra", 4);
|
|
|
|
fCardInfo.flags = 0;
|
|
if (mode.flags & B_SCROLL)
|
|
fCardInfo.flags |= B_FRAME_BUFFER_CONTROL;
|
|
if (mode.flags & B_PARALLEL_ACCESS)
|
|
fCardInfo.flags |= B_PARALLEL_BUFFER_ACCESS;
|
|
|
|
AppServerLink link;
|
|
link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
|
|
link.Attach<screen_id>(screen.ID());
|
|
|
|
status_t result = B_ERROR;
|
|
if (link.FlushWithReply(result) < B_OK || result < B_OK)
|
|
return result;
|
|
|
|
frame_buffer_config config;
|
|
link.Read<frame_buffer_config>(&config);
|
|
|
|
fCardInfo.frame_buffer = config.frame_buffer;
|
|
fCardInfo.bytes_per_row = config.bytes_per_row;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::_Suspend()
|
|
{
|
|
CALLED();
|
|
|
|
status_t status;
|
|
do {
|
|
status = acquire_sem(fDebugSem);
|
|
} while (status == B_INTERRUPTED);
|
|
|
|
if (status != B_OK)
|
|
return;
|
|
|
|
// Suspend all the registered threads
|
|
for (int32 i = 0; i < fDebugThreadCount; i++) {
|
|
snooze(10000);
|
|
suspend_thread(fDebugThreads[i]);
|
|
}
|
|
|
|
graphics_card_info *info = CardInfo();
|
|
size_t fbSize = info->bytes_per_row * info->height;
|
|
|
|
// Save the content of the frame buffer into the local buffer
|
|
fDebugFrameBuffer = (char *)malloc(fbSize);
|
|
memcpy(fDebugFrameBuffer, info->frame_buffer, fbSize);
|
|
}
|
|
|
|
|
|
void
|
|
BWindowScreen::_Resume()
|
|
{
|
|
CALLED();
|
|
graphics_card_info *info = CardInfo();
|
|
|
|
// Copy the content of the debug_buffer back into the frame buffer.
|
|
memcpy(info->frame_buffer, fDebugFrameBuffer,
|
|
info->bytes_per_row * info->height);
|
|
free(fDebugFrameBuffer);
|
|
fDebugFrameBuffer = NULL;
|
|
|
|
// Resume all the registered threads
|
|
for (int32 i = 0; i < fDebugThreadCount; i++) {
|
|
resume_thread(fDebugThreads[i]);
|
|
}
|
|
|
|
release_sem(fDebugSem);
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_GetModeFromSpace(uint32 space, display_mode *dmode)
|
|
{
|
|
CALLED();
|
|
|
|
int32 width, height;
|
|
uint32 colorSpace;
|
|
if (!BPrivate::get_mode_parameter(space, width, height, colorSpace))
|
|
return B_BAD_VALUE;
|
|
|
|
for (uint32 i = 0; i < fModeCount; i++) {
|
|
if (fModeList[i].space == colorSpace
|
|
&& fModeList[i].virtual_width == width
|
|
&& fModeList[i].virtual_height == height) {
|
|
memcpy(dmode, &fModeList[i], sizeof(display_mode));
|
|
return B_OK;
|
|
}
|
|
}
|
|
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_InitClone()
|
|
{
|
|
CALLED();
|
|
|
|
if (fAddonImage >= 0)
|
|
return B_OK;
|
|
|
|
BScreen screen(this);
|
|
|
|
AppServerLink link;
|
|
link.StartMessage(AS_GET_ACCELERANT_PATH);
|
|
link.Attach<screen_id>(screen.ID());
|
|
|
|
status_t status = B_ERROR;
|
|
if (link.FlushWithReply(status) < B_OK || status < B_OK)
|
|
return status;
|
|
|
|
BString accelerantPath;
|
|
link.ReadString(accelerantPath);
|
|
|
|
link.StartMessage(AS_GET_DRIVER_PATH);
|
|
link.Attach<screen_id>(screen.ID());
|
|
|
|
status = B_ERROR;
|
|
if (link.FlushWithReply(status) < B_OK || status < B_OK)
|
|
return status;
|
|
|
|
BString driverPath;
|
|
link.ReadString(driverPath);
|
|
|
|
fAddonImage = load_add_on(accelerantPath.String());
|
|
if (fAddonImage < B_OK) {
|
|
fprintf(stderr, "InitClone: cannot load accelerant image\n");
|
|
return fAddonImage;
|
|
}
|
|
|
|
status = get_image_symbol(fAddonImage, B_ACCELERANT_ENTRY_POINT,
|
|
B_SYMBOL_TYPE_TEXT, (void**)&fGetAccelerantHook);
|
|
if (status < B_OK) {
|
|
fprintf(stderr, "InitClone: cannot get accelerant entry point\n");
|
|
unload_add_on(fAddonImage);
|
|
fAddonImage = -1;
|
|
return B_NOT_SUPPORTED;
|
|
}
|
|
|
|
clone_accelerant cloneHook
|
|
= (clone_accelerant)fGetAccelerantHook(B_CLONE_ACCELERANT, NULL);
|
|
if (cloneHook == NULL) {
|
|
fprintf(stderr, "InitClone: cannot get clone hook\n");
|
|
unload_add_on(fAddonImage);
|
|
fAddonImage = -1;
|
|
return B_NOT_SUPPORTED;
|
|
}
|
|
|
|
status = cloneHook((void*)driverPath.String());
|
|
if (status < B_OK) {
|
|
fprintf(stderr, "InitClone: cannot clone accelerant\n");
|
|
unload_add_on(fAddonImage);
|
|
fAddonImage = -1;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BWindowScreen::_AssertDisplayMode(display_mode* displayMode)
|
|
{
|
|
CALLED();
|
|
|
|
BScreen screen(this);
|
|
|
|
display_mode currentMode;
|
|
status_t status = screen.GetMode(¤tMode);
|
|
if (status != B_OK)
|
|
return status;
|
|
|
|
if (currentMode.virtual_height != displayMode->virtual_height
|
|
|| currentMode.virtual_width != displayMode->virtual_width
|
|
|| currentMode.space != displayMode->space
|
|
|| currentMode.flags != displayMode->flags) {
|
|
status = screen.SetMode(displayMode);
|
|
if (status != B_OK) {
|
|
fprintf(stderr, "AssertDisplayMode: Setting mode failed: %s\n",
|
|
strerror(status));
|
|
return status;
|
|
}
|
|
|
|
memcpy(fDisplayMode, displayMode, sizeof(display_mode));
|
|
}
|
|
|
|
status = _GetCardInfo();
|
|
if (status != B_OK)
|
|
return status;
|
|
|
|
fFrameBufferInfo.bits_per_pixel = fCardInfo.bits_per_pixel;
|
|
fFrameBufferInfo.bytes_per_row = fCardInfo.bytes_per_row;
|
|
fFrameBufferInfo.width = fCardInfo.width;
|
|
fFrameBufferInfo.height = fCardInfo.height;
|
|
fFrameBufferInfo.display_width = fCardInfo.width;
|
|
fFrameBufferInfo.display_height = fCardInfo.height;
|
|
fFrameBufferInfo.display_x = 0;
|
|
fFrameBufferInfo.display_y = 0;
|
|
|
|
return B_OK;
|
|
}
|