Home | History | Annotate | Download | only in libGL
      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 
     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 
     48 Display::Display(NativeDisplayType displayId) : displayId(displayId)
     49 {
     50 	mMinSwapInterval = 1;
     51 	mMaxSwapInterval = 0;
     52 }
     53 
     54 Display::~Display()
     55 {
     56 	terminate();
     57 
     58 	displays.erase(displayId);
     59 }
     60 
     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 
     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 
     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 
    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 
    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 
    130 void Display::destroySurface(Surface *surface)
    131 {
    132 	delete surface;
    133 	mSurfaceSet.erase(surface);
    134 }
    135 
    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 
    148 bool Display::isInitialized() const
    149 {
    150 	return mMinSwapInterval <= mMaxSwapInterval;
    151 }
    152 
    153 bool Display::isValidContext(gl::Context *context)
    154 {
    155 	return mContextSet.find(context) != mContextSet.end();
    156 }
    157 
    158 bool Display::isValidSurface(Surface *surface)
    159 {
    160 	return mSurfaceSet.find(surface) != mSurfaceSet.end();
    161 }
    162 
    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 
    175 GLint Display::getMinSwapInterval()
    176 {
    177 	return mMinSwapInterval;
    178 }
    179 
    180 GLint Display::getMaxSwapInterval()
    181 {
    182 	return mMaxSwapInterval;
    183 }
    184 
    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 
    205 NativeDisplayType Display::getNativeDisplay() const
    206 {
    207 	return displayId;
    208 }
    209 
    210 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