* Renamed the "simple" mode setter Screen::SetMode() variant to SetBestMode();
it can also no longer create a default mode. * This SetBestMode() function now follows a similar logic than the boot loader, that is, only the width must not deviate, all other values are chosen as close to the original as possible. * VirtualScreen::AddScreen() now follows the same logic as the boot loader in case no configuration was found, and the current screen has no preferred mode (for example via EDID). That is, it will first try 1024x768, and then 800x600. * This means there is no mode change anymore when switching from the boot loader to the app_server in Qemu and VMware. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25782 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+54
-82
@@ -64,6 +64,9 @@ Screen::~Screen()
|
|||||||
delete fHWInterface;
|
delete fHWInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Finds the mode in the mode list that is closest to the mode specified.
|
||||||
|
As long as the mode list is not empty, this method will always succeed.
|
||||||
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Screen::Initialize()
|
Screen::Initialize()
|
||||||
@@ -120,33 +123,45 @@ Screen::SetMode(uint16 width, uint16 height, uint32 colorSpace,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Screen::SetMode(uint16 width, uint16 height, uint32 colorSpace,
|
Screen::SetBestMode(uint16 width, uint16 height, uint32 colorSpace,
|
||||||
float frequency, bool makeDefault)
|
float frequency)
|
||||||
{
|
{
|
||||||
// search for a matching mode
|
// search for a matching mode
|
||||||
display_mode mode;
|
display_mode* modes = NULL;
|
||||||
status_t status = _FindMode(width, height, colorSpace, frequency, &mode);
|
uint32 count;
|
||||||
|
status_t status = fHWInterface->GetModeList(&modes, &count);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
if (count <= 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
if (status >= B_OK) {
|
int32 index = _FindBestMode(modes, count, width, height, colorSpace,
|
||||||
float modeFrequency = get_mode_frequency(mode);
|
frequency);
|
||||||
display_mode originalMode = mode;
|
if (index < 0) {
|
||||||
bool adjusted = false;
|
debug_printf("Finding best mode failed");
|
||||||
|
delete[] modes;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (modeFrequency != frequency) {
|
display_mode mode = modes[index];
|
||||||
// adjust timing to fit the requested frequency if needed
|
delete[] modes;
|
||||||
// (taken from Screen preferences application)
|
|
||||||
mode.timing.pixel_clock = ((uint32)mode.timing.h_total
|
|
||||||
* mode.timing.v_total / 10 * int32(frequency * 10)) / 1000;
|
|
||||||
adjusted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = SetMode(mode, makeDefault);
|
float modeFrequency = get_mode_frequency(mode);
|
||||||
if (status < B_OK) {
|
display_mode originalMode = mode;
|
||||||
// try again with the unchanged mode
|
bool adjusted = false;
|
||||||
status = SetMode(originalMode, makeDefault);
|
|
||||||
}
|
if (modeFrequency != frequency) {
|
||||||
|
// adjust timing to fit the requested frequency if needed
|
||||||
|
// (taken from Screen preferences application)
|
||||||
|
mode.timing.pixel_clock = ((uint32)mode.timing.h_total
|
||||||
|
* mode.timing.v_total / 10 * int32(frequency * 10)) / 1000;
|
||||||
|
adjusted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = SetMode(mode, false);
|
||||||
|
if (status < B_OK && adjusted) {
|
||||||
|
// try again with the unchanged mode
|
||||||
|
status = SetMode(originalMode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -213,75 +228,32 @@ Screen::ColorSpace() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
/*! \brief Returns the mode that matches the given criteria best.
|
||||||
Screen::_FindMode(uint16 width, uint16 height, uint32 colorspace,
|
The "width" argument is the only hard argument, the rest will be adapted
|
||||||
float frequency, display_mode* mode) const
|
as needed.
|
||||||
{
|
|
||||||
display_mode* modes = NULL;
|
|
||||||
uint32 count;
|
|
||||||
|
|
||||||
status_t status = fHWInterface->GetModeList(&modes, &count);
|
|
||||||
if (status < B_OK || count <= 0) {
|
|
||||||
// We've run into quite a problem here! This is a function which is a requirement
|
|
||||||
// for a graphics module. The best thing that we can hope for is 640x480x8 without
|
|
||||||
// knowing anything else. While even this seems like insanity to assume that we
|
|
||||||
// can support this, the only lower mode supported is 640x400, but we shouldn't even
|
|
||||||
// bother with such a pathetic possibility.
|
|
||||||
if (width == 640 && height == 480 && colorspace == B_CMAP8)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 index = _FindMode(modes, count, width, height, colorspace, frequency);
|
|
||||||
if (index < 0) {
|
|
||||||
fprintf(stderr, "mode not found (%d, %d, %f) -> using first mode from list!\n",
|
|
||||||
width, height, frequency);
|
|
||||||
// fallback to first mode from list - TODO: ?!?
|
|
||||||
// NOTE: count > 0 is checked above
|
|
||||||
*mode = modes[0];
|
|
||||||
} else {
|
|
||||||
*mode = modes[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] modes;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Returns the mode that matches the given criteria. The frequency
|
|
||||||
doesn't have to match, though - the closest one found is used.
|
|
||||||
*/
|
*/
|
||||||
int32
|
int32
|
||||||
Screen::_FindMode(const display_mode* modes, uint32 count,
|
Screen::_FindBestMode(const display_mode* modes, uint32 count,
|
||||||
uint16 width, uint16 height, uint32 colorspace,
|
uint16 width, uint16 height, uint32 colorSpace, float frequency) const
|
||||||
float frequency) const
|
|
||||||
{
|
{
|
||||||
// we always try to choose the mode with the closest frequency
|
int32 bestDiff = 0;
|
||||||
float bestFrequencyDiff = 0.0f;
|
int32 bestIndex = -1;
|
||||||
int32 index = -1;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < count; i++) {
|
for (uint32 i = 0; i < count; i++) {
|
||||||
if (modes[i].virtual_width == width
|
const display_mode& mode = modes[i];
|
||||||
&& modes[i].virtual_height == height
|
if (mode.virtual_width != width)
|
||||||
&& modes[i].space == colorspace) {
|
continue;
|
||||||
// we have found a mode with the correct width, height and format
|
|
||||||
// now see if the frequency matches
|
|
||||||
float modeFrequency = get_mode_frequency(modes[i]);
|
|
||||||
float frequencyDiff = fabs(modeFrequency - frequency);
|
|
||||||
|
|
||||||
if (index == -1 || bestFrequencyDiff > frequencyDiff) {
|
// compute some random equality score
|
||||||
index = i;
|
// TODO: check if these scores make sense
|
||||||
if (frequencyDiff == 0.0f)
|
int32 diff = 1000 * abs(mode.timing.v_display - height)
|
||||||
break;
|
+ int32(fabs(get_mode_frequency(mode) - frequency) * 10)
|
||||||
|
+ 100 * abs(mode.space - colorSpace);
|
||||||
|
|
||||||
bestFrequencyDiff = frequencyDiff;
|
if (bestIndex == -1 || diff < bestDiff) {
|
||||||
}
|
bestDiff = diff;
|
||||||
|
bestIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return bestIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2007, Haiku, Inc.
|
* Copyright (c) 2001-2008, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT license.
|
* Distributed under the terms of the MIT license.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -33,14 +33,13 @@ class Screen {
|
|||||||
|
|
||||||
status_t SetMode(const display_mode& mode,
|
status_t SetMode(const display_mode& mode,
|
||||||
bool makeDefault);
|
bool makeDefault);
|
||||||
status_t SetMode(uint16 width, uint16 height,
|
|
||||||
uint32 colorspace, float frequency,
|
|
||||||
bool makeDefault);
|
|
||||||
status_t SetMode(uint16 width, uint16 height,
|
status_t SetMode(uint16 width, uint16 height,
|
||||||
uint32 colorspace,
|
uint32 colorspace,
|
||||||
const display_timing& timing,
|
const display_timing& timing,
|
||||||
bool makeDefault);
|
bool makeDefault);
|
||||||
status_t SetPreferredMode();
|
status_t SetPreferredMode();
|
||||||
|
status_t SetBestMode(uint16 width, uint16 height,
|
||||||
|
uint32 colorspace, float frequency);
|
||||||
|
|
||||||
void GetMode(display_mode* mode) const;
|
void GetMode(display_mode* mode) const;
|
||||||
void GetMode(uint16 &width, uint16 &height,
|
void GetMode(uint16 &width, uint16 &height,
|
||||||
@@ -56,11 +55,7 @@ class Screen {
|
|||||||
{ return fHWInterface; }
|
{ return fHWInterface; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _FindMode(uint16 width, uint16 height,
|
int32 _FindBestMode(const display_mode* modeList,
|
||||||
uint32 colorspace, float frequency,
|
|
||||||
display_mode* mode) const;
|
|
||||||
|
|
||||||
int32 _FindMode(const display_mode* modeList,
|
|
||||||
uint32 count, uint16 width, uint16 height,
|
uint32 count, uint16 width, uint16 height,
|
||||||
uint32 colorspace, float frequency) const;
|
uint32 colorspace, float frequency) const;
|
||||||
|
|
||||||
|
|||||||
@@ -156,8 +156,11 @@ VirtualScreen::AddScreen(Screen* screen)
|
|||||||
}
|
}
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// TODO: more intelligent standard mode (monitor preference, desktop default, ...)
|
// TODO: more intelligent standard mode (monitor preference, desktop default, ...)
|
||||||
if (screen->SetPreferredMode() != B_OK)
|
status_t status = screen->SetPreferredMode();
|
||||||
screen->SetMode(800, 600, B_RGB32, 60.f, false);
|
if (status != B_OK)
|
||||||
|
status = screen->SetBestMode(1024, 768, B_RGB32, 60.f);
|
||||||
|
if (status != B_OK)
|
||||||
|
screen->SetBestMode(800, 600, B_RGB32, 60.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this works only for single screen configurations
|
// TODO: this works only for single screen configurations
|
||||||
|
|||||||
Reference in New Issue
Block a user