btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / servers / app / Screen.cpp
blob0fc58008bdc8dd14904f512a807266857bfa6d77
1 /*
2 * Copyright 2001-2013, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * Adi Oanca <adioanca@myrealbox.com>
7 * Axel Dörfler, axeld@pinc-software.de
8 * Stephan Aßmus, <superstippi@gmx.de>
9 */
12 #include "Screen.h"
14 #include "BitmapManager.h"
15 #include "DrawingEngine.h"
16 #include "HWInterface.h"
18 #include <Accelerant.h>
19 #include <Point.h>
20 #include <GraphicsDefs.h>
22 #include <stdlib.h>
23 #include <stdio.h>
26 static float
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);
31 if (timing == 0.0f)
32 return 0.0f;
34 return rint(10 * float(mode.timing.pixel_clock * 1000)
35 / timing) / 10.0;
39 // #pragma mark -
42 Screen::Screen(::HWInterface *interface, int32 id)
44 fID(id),
45 fDriver(interface ? interface->CreateDrawingEngine() : NULL),
46 fHWInterface(interface)
51 Screen::Screen()
53 fID(-1),
54 fDriver(NULL),
55 fHWInterface(NULL)
60 Screen::~Screen()
62 Shutdown();
63 delete fDriver;
64 delete fHWInterface;
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.
71 status_t
72 Screen::Initialize()
74 if (fHWInterface) {
75 // init the graphics hardware
76 return fHWInterface->Initialize();
79 return B_NO_INIT;
83 void
84 Screen::Shutdown()
86 if (fHWInterface)
87 fHWInterface->Shutdown();
91 status_t
92 Screen::SetMode(const display_mode& mode)
94 display_mode current;
95 GetMode(current);
96 if (!memcmp(&mode, &current, sizeof(display_mode)))
97 return B_OK;
99 gBitmapManager->SuspendOverlays();
101 status_t status = fHWInterface->SetMode(mode);
102 // any attached DrawingEngines will be notified
104 gBitmapManager->ResumeOverlays();
106 return status;
110 status_t
111 Screen::SetMode(uint16 width, uint16 height, uint32 colorSpace,
112 const display_timing& timing)
114 display_mode mode;
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;
121 mode.flags = 0;
123 return SetMode(mode);
127 status_t
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;
133 uint32 count;
134 status_t status = fHWInterface->GetModeList(&modes, &count);
135 if (status < B_OK)
136 return status;
137 if (count <= 0)
138 return B_ERROR;
140 int32 index = _FindBestMode(modes, count, width, height, colorSpace,
141 frequency);
142 if (index < 0) {
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" : "");
147 if (strict) {
148 delete[] modes;
149 return B_ERROR;
150 } else {
151 index = 0;
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];
159 delete[] modes;
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;
170 adjusted = true;
172 status = SetMode(mode);
173 if (status != B_OK && adjusted) {
174 // try again with the unchanged mode
175 status = SetMode(originalMode);
178 return status;
182 status_t
183 Screen::SetPreferredMode()
185 display_mode mode;
186 status_t status = fHWInterface->GetPreferredMode(&mode);
187 if (status != B_OK)
188 return status;
190 return SetMode(mode);
194 void
195 Screen::GetMode(display_mode& mode) const
197 fHWInterface->GetMode(&mode);
201 void
202 Screen::GetMode(uint16 &width, uint16 &height, uint32 &colorspace,
203 float &frequency) const
205 display_mode mode;
206 fHWInterface->GetMode(&mode);
208 width = mode.virtual_width;
209 height = mode.virtual_height;
210 colorspace = mode.space;
211 frequency = get_mode_frequency(mode);
215 status_t
216 Screen::GetMonitorInfo(monitor_info& info) const
218 return fHWInterface->GetMonitorInfo(&info);
222 void
223 Screen::SetFrame(const BRect& rect)
225 // TODO: multi-monitor support...
229 BRect
230 Screen::Frame() const
232 display_mode mode;
233 fHWInterface->GetMode(&mode);
235 return BRect(0, 0, mode.virtual_width - 1, mode.virtual_height - 1);
239 color_space
240 Screen::ColorSpace() const
242 display_mode mode;
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
251 as needed.
253 int32
254 Screen::_FindBestMode(const display_mode* modes, uint32 count,
255 uint16 width, uint16 height, uint32 colorSpace, float frequency) const
257 int32 bestDiff = 0;
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)
262 continue;
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) {
271 bestDiff = diff;
272 bestIndex = i;
276 return bestIndex;