1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Display.cpp: Implements the Display class, representing the abstract
16 // display on which graphics are drawn.
17
18 #include "Display.h"
19
20 #include "main.h"
21 #include "mathutil.h"
22 #include "Device.hpp"
23 #include "common/debug.h"
24
25 #include <algorithm>
26 #include <vector>
27 #include <map>
28
29 namespace gl
30 {
31 typedef std::map<NativeDisplayType, Display*> DisplayMap;
32 DisplayMap displays;
33
getDisplay(NativeDisplayType displayId)34 Display *Display::getDisplay(NativeDisplayType displayId)
35 {
36 if(displays.find(displayId) != displays.end())
37 {
38 return displays[displayId];
39 }
40
41 // FIXME: Check if displayId is a valid display device context
42 Display *display = new Display(displayId);
43
44 displays[displayId] = display;
45 return display;
46 }
47
Display(NativeDisplayType displayId)48 Display::Display(NativeDisplayType displayId) : displayId(displayId)
49 {
50 mMinSwapInterval = 1;
51 mMaxSwapInterval = 0;
52 }
53
~Display()54 Display::~Display()
55 {
56 terminate();
57
58 displays.erase(displayId);
59 }
60
cpuid(int registers[4],int info)61 static void cpuid(int registers[4], int info)
62 {
63 #if defined(_WIN32)
64 __cpuid(registers, info);
65 #else
66 __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info));
67 #endif
68 }
69
detectSSE()70 static bool detectSSE()
71 {
72 #if defined(__APPLE__)
73 int SSE = false;
74 size_t length = sizeof(SSE);
75 sysctlbyname("hw.optional.sse", &SSE, &length, 0, 0);
76 return SSE;
77 #else
78 int registers[4];
79 cpuid(registers, 1);
80 return (registers[3] & 0x02000000) != 0;
81 #endif
82 }
83
initialize()84 bool Display::initialize()
85 {
86 if(isInitialized())
87 {
88 return true;
89 }
90
91 if(!detectSSE())
92 {
93 return false;
94 }
95
96 mMinSwapInterval = 0;
97 mMaxSwapInterval = 4;
98
99 if(!isInitialized())
100 {
101 terminate();
102
103 return false;
104 }
105
106 return true;
107 }
108
terminate()109 void Display::terminate()
110 {
111 while(!mSurfaceSet.empty())
112 {
113 destroySurface(*mSurfaceSet.begin());
114 }
115
116 while(!mContextSet.empty())
117 {
118 destroyContext(*mContextSet.begin());
119 }
120 }
121
createContext(const gl::Context * shareContext)122 gl::Context *Display::createContext(const gl::Context *shareContext)
123 {
124 gl::Context *context = new gl::Context(shareContext);
125 mContextSet.insert(context);
126
127 return context;
128 }
129
destroySurface(Surface * surface)130 void Display::destroySurface(Surface *surface)
131 {
132 delete surface;
133 mSurfaceSet.erase(surface);
134 }
135
destroyContext(gl::Context * context)136 void Display::destroyContext(gl::Context *context)
137 {
138 delete context;
139
140 if(context == gl::getContext())
141 {
142 gl::makeCurrent(nullptr, nullptr, nullptr);
143 }
144
145 mContextSet.erase(context);
146 }
147
isInitialized() const148 bool Display::isInitialized() const
149 {
150 return mMinSwapInterval <= mMaxSwapInterval;
151 }
152
isValidContext(gl::Context * context)153 bool Display::isValidContext(gl::Context *context)
154 {
155 return mContextSet.find(context) != mContextSet.end();
156 }
157
isValidSurface(Surface * surface)158 bool Display::isValidSurface(Surface *surface)
159 {
160 return mSurfaceSet.find(surface) != mSurfaceSet.end();
161 }
162
isValidWindow(NativeWindowType window)163 bool Display::isValidWindow(NativeWindowType window)
164 {
165 #if defined(_WIN32)
166 return IsWindow(window) == TRUE;
167 #else
168 XWindowAttributes windowAttributes;
169 Status status = XGetWindowAttributes(displayId, window, &windowAttributes);
170
171 return status == True;
172 #endif
173 }
174
getMinSwapInterval()175 GLint Display::getMinSwapInterval()
176 {
177 return mMinSwapInterval;
178 }
179
getMaxSwapInterval()180 GLint Display::getMaxSwapInterval()
181 {
182 return mMaxSwapInterval;
183 }
184
getPrimarySurface()185 Surface *Display::getPrimarySurface()
186 {
187 if(mSurfaceSet.size() == 0)
188 {
189 Surface *surface = new Surface(this, WindowFromDC(displayId));
190
191 if(!surface->initialize())
192 {
193 delete surface;
194 return 0;
195 }
196
197 mSurfaceSet.insert(surface);
198
199 gl::setCurrentDrawSurface(surface);
200 }
201
202 return *mSurfaceSet.begin();
203 }
204
getNativeDisplay() const205 NativeDisplayType Display::getNativeDisplay() const
206 {
207 return displayId;
208 }
209
getDisplayMode() const210 DisplayMode Display::getDisplayMode() const
211 {
212 DisplayMode displayMode = {0};
213
214 #if defined(_WIN32)
215 HDC deviceContext = GetDC(0);
216
217 displayMode.width = ::GetDeviceCaps(deviceContext, HORZRES);
218 displayMode.height = ::GetDeviceCaps(deviceContext, VERTRES);
219 unsigned int bpp = ::GetDeviceCaps(deviceContext, BITSPIXEL);
220
221 switch(bpp)
222 {
223 case 32: displayMode.format = sw::FORMAT_X8R8G8B8; break;
224 case 24: displayMode.format = sw::FORMAT_R8G8B8; break;
225 case 16: displayMode.format = sw::FORMAT_R5G6B5; break;
226 default:
227 ASSERT(false); // Unexpected display mode color depth
228 }
229
230 ReleaseDC(0, deviceContext);
231 #else
232 Screen *screen = XDefaultScreenOfDisplay(displayId);
233 displayMode.width = XWidthOfScreen(screen);
234 displayMode.height = XHeightOfScreen(screen);
235 unsigned int bpp = XPlanesOfScreen(screen);
236
237 switch(bpp)
238 {
239 case 32: displayMode.format = sw::FORMAT_X8R8G8B8; break;
240 case 24: displayMode.format = sw::FORMAT_R8G8B8; break;
241 case 16: displayMode.format = sw::FORMAT_R5G6B5; break;
242 default:
243 ASSERT(false); // Unexpected display mode color depth
244 }
245 #endif
246
247 return displayMode;
248 }
249
250 }
251