2 * Copyright 2001-2013, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
6 * Adi Oanca <adioanca@myrealbox.com>
7 * Axel Dörfler, axeld@pinc-software.de
8 * Stephan Aßmus, <superstippi@gmx.de>
14 #include "BitmapManager.h"
15 #include "DrawingEngine.h"
16 #include "HWInterface.h"
18 #include <Accelerant.h>
20 #include <GraphicsDefs.h>
27 get_mode_frequency(const display_mode
& mode
)
29 // Taken from Screen preferences
30 float timing
= float(mode
.timing
.h_total
* mode
.timing
.v_total
);
34 return rint(10 * float(mode
.timing
.pixel_clock
* 1000)
42 Screen::Screen(::HWInterface
*interface
, int32 id
)
45 fDriver(interface
? interface
->CreateDrawingEngine() : NULL
),
46 fHWInterface(interface
)
68 /*! Finds the mode in the mode list that is closest to the mode specified.
69 As long as the mode list is not empty, this method will always succeed.
75 // init the graphics hardware
76 return fHWInterface
->Initialize();
87 fHWInterface
->Shutdown();
92 Screen::SetMode(const display_mode
& mode
)
96 if (!memcmp(&mode
, ¤t
, sizeof(display_mode
)))
99 gBitmapManager
->SuspendOverlays();
101 status_t status
= fHWInterface
->SetMode(mode
);
102 // any attached DrawingEngines will be notified
104 gBitmapManager
->ResumeOverlays();
111 Screen::SetMode(uint16 width
, uint16 height
, uint32 colorSpace
,
112 const display_timing
& timing
)
115 mode
.timing
= timing
;
116 mode
.space
= colorSpace
;
117 mode
.virtual_width
= width
;
118 mode
.virtual_height
= height
;
119 mode
.h_display_start
= 0;
120 mode
.v_display_start
= 0;
123 return SetMode(mode
);
128 Screen::SetBestMode(uint16 width
, uint16 height
, uint32 colorSpace
,
129 float frequency
, bool strict
)
131 // search for a matching mode
132 display_mode
* modes
= NULL
;
134 status_t status
= fHWInterface
->GetModeList(&modes
, &count
);
140 int32 index
= _FindBestMode(modes
, count
, width
, height
, colorSpace
,
143 debug_printf("app_server: Finding best mode for %ux%u (%" B_PRIu32
144 ", %g Hz%s) failed\n", width
, height
, colorSpace
, frequency
,
145 strict
? ", strict" : "");
152 // Just use the first mode in the list
153 debug_printf("app_server: Use %ux%u (%" B_PRIu32
") instead.\n",
154 modes
[0].timing
.h_total
, modes
[0].timing
.v_total
, modes
[0].space
);
158 display_mode mode
= modes
[index
];
161 float modeFrequency
= get_mode_frequency(mode
);
162 display_mode originalMode
= mode
;
163 bool adjusted
= false;
165 if (modeFrequency
!= frequency
) {
166 // adjust timing to fit the requested frequency if needed
167 // (taken from Screen preferences application)
168 mode
.timing
.pixel_clock
= ((uint32
)mode
.timing
.h_total
169 * mode
.timing
.v_total
/ 10 * int32(frequency
* 10)) / 1000;
172 status
= SetMode(mode
);
173 if (status
!= B_OK
&& adjusted
) {
174 // try again with the unchanged mode
175 status
= SetMode(originalMode
);
183 Screen::SetPreferredMode()
186 status_t status
= fHWInterface
->GetPreferredMode(&mode
);
190 return SetMode(mode
);
195 Screen::GetMode(display_mode
& mode
) const
197 fHWInterface
->GetMode(&mode
);
202 Screen::GetMode(uint16
&width
, uint16
&height
, uint32
&colorspace
,
203 float &frequency
) const
206 fHWInterface
->GetMode(&mode
);
208 width
= mode
.virtual_width
;
209 height
= mode
.virtual_height
;
210 colorspace
= mode
.space
;
211 frequency
= get_mode_frequency(mode
);
216 Screen::GetMonitorInfo(monitor_info
& info
) const
218 return fHWInterface
->GetMonitorInfo(&info
);
223 Screen::SetFrame(const BRect
& rect
)
225 // TODO: multi-monitor support...
230 Screen::Frame() const
233 fHWInterface
->GetMode(&mode
);
235 return BRect(0, 0, mode
.virtual_width
- 1, mode
.virtual_height
- 1);
240 Screen::ColorSpace() const
243 fHWInterface
->GetMode(&mode
);
245 return (color_space
)mode
.space
;
249 /*! \brief Returns the mode that matches the given criteria best.
250 The "width" argument is the only hard argument, the rest will be adapted
254 Screen::_FindBestMode(const display_mode
* modes
, uint32 count
,
255 uint16 width
, uint16 height
, uint32 colorSpace
, float frequency
) const
258 int32 bestIndex
= -1;
259 for (uint32 i
= 0; i
< count
; i
++) {
260 const display_mode
& mode
= modes
[i
];
261 if (mode
.virtual_width
!= width
)
264 // compute some random equality score
265 // TODO: check if these scores make sense
266 int32 diff
= 1000 * abs(mode
.timing
.v_display
- height
)
267 + int32(fabs(get_mode_frequency(mode
) - frequency
) * 10)
268 + 100 * abs(mode
.space
- colorSpace
);
270 if (bestIndex
== -1 || diff
< bestDiff
) {