Marcus' change had a point, though: we now handle the first mode switch differently

in that we try really hard to let it succeed. If setting the desired mode failed,
we now try almost anything to get a working mode.
Since the kernel also knows the VESA mode, maybe we should better ask that one for
the current mode, as most drivers probably haven't got B_GET_DISPLAY_MODE implemented
in the we're using it.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17355 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-05-07 18:07:37 +00:00
parent aa8265a5be
commit 4eb16023d1
2 changed files with 93 additions and 13 deletions

View File

@ -103,6 +103,8 @@ AccelerantHWInterface::AccelerantHWInterface()
fBackBuffer(NULL),
fFrontBuffer(new (nothrow) AccelerantBuffer()),
fInitialModeSwitch(true),
fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]),
fRectParamsCount(kDefaultParamsCount),
fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]),
@ -359,9 +361,65 @@ AccelerantHWInterface::Shutdown()
return B_OK;
}
// SetMode
/*!
This method is used for the initial mode set only - because that one
should really not fail.
Basically we try to set all modes as found in the mode list the driver
returned, but we start with the one that best fits the originally
desired mode.
*/
status_t
AccelerantHWInterface::SetMode(const display_mode &mode)
AccelerantHWInterface::_SetFallbackMode(display_mode& newMode) const
{
if (fModeList == NULL)
return B_ERROR;
// At first, we search the closest display mode from the list of
// supported modes - if that fails, we just take one
int32 bestDiff = 0;
int32 bestIndex = -1;
for (int32 i = 0; i < fModeCount; i++) {
display_mode& mode = fModeList[i];
// compute some random equality score
int32 diff = abs(mode.virtual_width - newMode.virtual_width)
+ abs(mode.virtual_height - newMode.virtual_height)
+ 10 * abs(mode.space - newMode.space);
if (bestIndex == -1 || diff < bestDiff) {
bestDiff = diff;
bestIndex = i;
}
}
if (bestIndex < 0)
return B_ERROR;
newMode = fModeList[bestIndex];
status_t status = fAccSetDisplayMode(&newMode);
if (status == B_OK)
return B_OK;
// That failed as well, this looks like a bug in the graphics
// driver, but we have to try to be as forgiving as possible
// here - just take the first mode that fits!
for (int32 i = 0; i < fModeCount; i++) {
newMode = fModeList[i];
status = fAccSetDisplayMode(&newMode);
if (status == B_OK)
return B_OK;
}
// Well, we tried.
return B_ERROR;
}
status_t
AccelerantHWInterface::SetMode(const display_mode& mode)
{
AutoWriteLocker _(this);
// TODO: There are places this function can fail,
@ -386,21 +444,41 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
display_mode newMode = mode;
if (fAccSetDisplayMode(&newMode) != B_OK) {
status_t status = fAccSetDisplayMode(&newMode);
if (status != B_OK) {
ATRACE(("setting display mode failed\n"));
// We just keep the current mode and continue.
// Note, on startup, this may be different from
// what we think is the current display mode
if (!fInitialModeSwitch)
return status;
// If this is the initial mode switch, we try a number of fallback
// modes first, before we have to fail
status = _SetFallbackMode(newMode);
if (status != B_OK) {
// The driver doesn't allow us the mode switch - this usually
// means we have a driver that doesn't allow mode switches at
// all.
// All we can do now is to ask the driver which mode we can
// use - this is always necessary for VESA mode, for example.
if (fAccGetDisplayMode(&newMode) != B_OK)
return B_ERROR;
// TODO: if the mode switch before fails as well, we must forbid
// any uses of this class!
status = B_OK;
}
}
fDisplayMode = newMode;
fInitialModeSwitch = false;
// update frontbuffer
fFrontBuffer->SetDisplayMode(fDisplayMode);
if (_UpdateFrameBufferConfig() != B_OK)
if (_UpdateFrameBufferConfig() != B_OK) {
// TODO: if this fails, we're basically toasted - we need to handle this
// differently to crashing later on!
return B_ERROR;
}
// Update the frame buffer used by the on-screen KDL
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
@ -435,11 +513,11 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width,
fDisplayMode.virtual_height);
status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
if (ret < B_OK) {
status = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
if (status < B_OK) {
delete fBackBuffer;
fBackBuffer = NULL;
return ret;
return status;
}
// clear out backbuffer, alpha is 255 this way
memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
@ -456,7 +534,7 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT,
(void *)&fDisplayMode);
return B_OK;
return status;
}

View File

@ -103,6 +103,7 @@ private:
void _RegionToRectParams(/*const*/ BRegion* region,
uint32* count) const;
uint32 _NativeColor(const RGBColor& color) const;
status_t _SetFallbackMode(display_mode& mode) const;
void _SetSystemPalette();
int fCardFD;
@ -156,6 +157,7 @@ private:
AccelerantBuffer* fFrontBuffer;
display_mode fDisplayMode;
bool fInitialModeSwitch;
mutable fill_rect_params* fRectParams;
mutable uint32 fRectParamsCount;