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:
parent
aa8265a5be
commit
4eb16023d1
@ -103,6 +103,8 @@ AccelerantHWInterface::AccelerantHWInterface()
|
|||||||
fBackBuffer(NULL),
|
fBackBuffer(NULL),
|
||||||
fFrontBuffer(new (nothrow) AccelerantBuffer()),
|
fFrontBuffer(new (nothrow) AccelerantBuffer()),
|
||||||
|
|
||||||
|
fInitialModeSwitch(true),
|
||||||
|
|
||||||
fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]),
|
fRectParams(new (nothrow) fill_rect_params[kDefaultParamsCount]),
|
||||||
fRectParamsCount(kDefaultParamsCount),
|
fRectParamsCount(kDefaultParamsCount),
|
||||||
fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]),
|
fBlitParams(new (nothrow) blit_params[kDefaultParamsCount]),
|
||||||
@ -359,9 +361,65 @@ AccelerantHWInterface::Shutdown()
|
|||||||
return B_OK;
|
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
|
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);
|
AutoWriteLocker _(this);
|
||||||
// TODO: There are places this function can fail,
|
// TODO: There are places this function can fail,
|
||||||
@ -386,21 +444,41 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
|
|||||||
|
|
||||||
display_mode newMode = 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"));
|
ATRACE(("setting display mode failed\n"));
|
||||||
// We just keep the current mode and continue.
|
if (!fInitialModeSwitch)
|
||||||
// Note, on startup, this may be different from
|
return status;
|
||||||
// what we think is the current display mode
|
|
||||||
if (fAccGetDisplayMode(&newMode) != B_OK)
|
// If this is the initial mode switch, we try a number of fallback
|
||||||
return B_ERROR;
|
// 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;
|
fDisplayMode = newMode;
|
||||||
|
fInitialModeSwitch = false;
|
||||||
|
|
||||||
// update frontbuffer
|
// update frontbuffer
|
||||||
fFrontBuffer->SetDisplayMode(fDisplayMode);
|
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;
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the frame buffer used by the on-screen KDL
|
// Update the frame buffer used by the on-screen KDL
|
||||||
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||||
@ -435,11 +513,11 @@ AccelerantHWInterface::SetMode(const display_mode &mode)
|
|||||||
fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width,
|
fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width,
|
||||||
fDisplayMode.virtual_height);
|
fDisplayMode.virtual_height);
|
||||||
|
|
||||||
status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
|
status = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
|
||||||
if (ret < B_OK) {
|
if (status < B_OK) {
|
||||||
delete fBackBuffer;
|
delete fBackBuffer;
|
||||||
fBackBuffer = NULL;
|
fBackBuffer = NULL;
|
||||||
return ret;
|
return status;
|
||||||
}
|
}
|
||||||
// clear out backbuffer, alpha is 255 this way
|
// clear out backbuffer, alpha is 255 this way
|
||||||
memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
|
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,
|
fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT,
|
||||||
(void *)&fDisplayMode);
|
(void *)&fDisplayMode);
|
||||||
|
|
||||||
return B_OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ private:
|
|||||||
void _RegionToRectParams(/*const*/ BRegion* region,
|
void _RegionToRectParams(/*const*/ BRegion* region,
|
||||||
uint32* count) const;
|
uint32* count) const;
|
||||||
uint32 _NativeColor(const RGBColor& color) const;
|
uint32 _NativeColor(const RGBColor& color) const;
|
||||||
|
status_t _SetFallbackMode(display_mode& mode) const;
|
||||||
void _SetSystemPalette();
|
void _SetSystemPalette();
|
||||||
|
|
||||||
int fCardFD;
|
int fCardFD;
|
||||||
@ -156,6 +157,7 @@ private:
|
|||||||
AccelerantBuffer* fFrontBuffer;
|
AccelerantBuffer* fFrontBuffer;
|
||||||
|
|
||||||
display_mode fDisplayMode;
|
display_mode fDisplayMode;
|
||||||
|
bool fInitialModeSwitch;
|
||||||
|
|
||||||
mutable fill_rect_params* fRectParams;
|
mutable fill_rect_params* fRectParams;
|
||||||
mutable uint32 fRectParamsCount;
|
mutable uint32 fRectParamsCount;
|
||||||
|
Loading…
Reference in New Issue
Block a user