The Pedigree Project 0.1
GraphicsService.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/graphics/GraphicsService.h"
22#include "pedigree/kernel/machine/Display.h"
23#include "pedigree/kernel/process/TerminationDeferral.h"
24#include "pedigree/kernel/processor/Processor.h"
25#include "pedigree/kernel/processor/types.h"
26#include "pedigree/kernel/utilities/Iterator.h"
27#include "pedigree/kernel/utilities/String.h"
28#include "pedigree/kernel/utilities/utility.h"
29
30bool GraphicsService::serve(ServiceFeatures::Type type, void* pData, size_t dataLen) {
31 if (!pData)
32 return false;
33
34 bool mutating = false;
35 if (type & ServiceFeatures::touch) {
36 if (dataLen < sizeof(GraphicsProvider))
37 return false;
38 mutating = true;
39 } else if (type & ServiceFeatures::withdraw) {
40 if (dataLen < sizeof(GraphicsProvider))
41 return false;
42 mutating = true;
43 } else if (type & ServiceFeatures::probe) {
44 if (dataLen < sizeof(GraphicsParameters))
45 return false;
46 } else {
47 return false;
48 }
49
50 const bool interruptsEnabled = Processor::getInterrupts();
51 if (mutating && !interruptsEnabled)
52 return false;
53
54 TerminationDeferral terminationDeferral(interruptsEnabled);
55 const bool lockAcquired =
56 interruptsEnabled ? m_ProviderLock.acquire() : m_ProviderLock.tryAcquire();
57 if (!lockAcquired)
58 return false;
59
60 bool success = false;
61 if (type & ServiceFeatures::touch) {
62 GraphicsProvider* pProvider = reinterpret_cast<GraphicsProvider*>(pData);
63 bool alreadyRegistered = false;
64 for (List<GraphicsProvider*>::Iterator it = m_Providers.begin(); it != m_Providers.end();
65 ++it) {
66 if (*it == pProvider) {
67 alreadyRegistered = true;
68 break;
69 }
70 }
71
72 if (!alreadyRegistered)
73 m_Providers.pushBack(pProvider);
74
75 ProviderPair bestProvider = determineBestProvider();
76 m_pCurrentProvider = bestProvider.bestBase;
77 m_pCurrentTextProvider = bestProvider.bestText;
78 success = true;
79 } else if (type & ServiceFeatures::withdraw) {
80 GraphicsProvider* pProvider = reinterpret_cast<GraphicsProvider*>(pData);
81 for (List<GraphicsProvider*>::Iterator it = m_Providers.begin(); it != m_Providers.end();
82 ++it) {
83 if (*it != pProvider)
84 continue;
85
86 m_Providers.erase(it);
87 ProviderPair bestProvider = determineBestProvider();
88 m_pCurrentProvider = bestProvider.bestBase;
89 m_pCurrentTextProvider = bestProvider.bestText;
90 success = true;
91 break;
92 }
93 } else if (type & ServiceFeatures::probe) {
94 GraphicsParameters* params = reinterpret_cast<GraphicsParameters*>(pData);
95 params->providerFound = false;
96
97 if (params->wantTextMode) {
98 if (m_pCurrentTextProvider) {
99 MemoryCopy(&params->providerResult, m_pCurrentTextProvider, sizeof(GraphicsProvider));
100 params->providerFound = true;
101 success = true;
102 }
103 } else if (m_pCurrentProvider) {
104 MemoryCopy(&params->providerResult, m_pCurrentProvider, sizeof(GraphicsProvider));
105 params->providerFound = true;
106 success = true;
107 }
108 }
109
110 m_ProviderLock.release();
111 return success;
112}
113
114GraphicsService::ProviderPair GraphicsService::determineBestProvider() {
115 ProviderPair result;
116 result.bestBase = 0;
117 result.bestText = 0;
118
119 uint64_t bestPoints = 0;
120 uint64_t bestTextPoints = 0;
121 for (List<GraphicsProvider*>::Iterator it = m_Providers.begin(); it != m_Providers.end(); it++) {
122 if (!*it)
123 continue;
124
125 GraphicsProvider* pProvider = *it;
126
127 uint64_t points = 0;
128 uint64_t textPoints = 0;
129
130 // Hardware acceleration points
131 if (pProvider->bHardwareAccel)
132 points +=
133 (0x10000ULL * 0x10000ULL) * 32ULL; // 16384x16384x32, hard to beat if no hardware accel
134
135 // Maximums points (highest resolution in bits)
136 points += pProvider->maxWidth * pProvider->maxHeight * pProvider->maxDepth;
137 textPoints += pProvider->maxTextWidth * pProvider->maxTextHeight;
138
139 if (!pProvider->bTextModes) {
140 textPoints *= 0;
141 }
142
143 String name;
144 pProvider->pDisplay->getName(name);
145 DEBUG_LOG("GraphicsService: provider with display name '"
146 << name << "' got " << points << " points (" << textPoints << " text points)");
147
148 // Native ownership supersedes inherited scanout even without acceleration.
149 const bool preferredClass =
150 result.bestBase && result.bestBase->bFirmwareFallback && !pProvider->bFirmwareFallback;
151 const bool sameClass =
152 !result.bestBase || result.bestBase->bFirmwareFallback == pProvider->bFirmwareFallback;
153 if (preferredClass || (sameClass && points > bestPoints)) {
154 bestPoints = points;
155 result.bestBase = pProvider;
156
157 DEBUG_LOG(" => new best provider");
158 }
159
160 if (textPoints > bestTextPoints) {
161 bestTextPoints = textPoints;
162 result.bestText = pProvider;
163
164 DEBUG_LOG(" => new best text provider");
165 }
166 }
167
168 return result;
169}
bool serve(ServiceFeatures::Type type, void *pData, size_t dataLen)
::Iterator< T, node_t > Iterator
Definition List.h:67
static bool getInterrupts()
void release(size_t n=1)
Definition Semaphore.cc:549
bool tryAcquire(size_t n=1)
Definition Semaphore.cc:484
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition Semaphore.cc:355