• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Surface.cpp: Implements the Surface class, representing a drawing surface
16 // such as the client area of a window, including any back buffers.
17 
18 #include "Surface.h"
19 
20 #include "main.h"
21 #include "Display.h"
22 #include "Image.hpp"
23 #include "Context.h"
24 #include "common/debug.h"
25 #include "Main/FrameBuffer.hpp"
26 
27 #if defined(_WIN32)
28 #include <tchar.h>
29 #endif
30 
31 #include <algorithm>
32 
33 namespace gl
34 {
35 
Surface(Display * display,NativeWindowType window)36 Surface::Surface(Display *display, NativeWindowType window)
37 	: mDisplay(display), mWindow(window)
38 {
39 	frameBuffer = 0;
40 	backBuffer = 0;
41 
42 	mDepthStencil = nullptr;
43 	mTextureFormat = GL_NONE;
44 	mTextureTarget = GL_NONE;
45 
46 	mSwapInterval = -1;
47 	setSwapInterval(1);
48 }
49 
Surface(Display * display,GLint width,GLint height,GLenum textureFormat,GLenum textureType)50 Surface::Surface(Display *display, GLint width, GLint height, GLenum textureFormat, GLenum textureType)
51 	: mDisplay(display), mWindow(nullptr), mWidth(width), mHeight(height)
52 {
53 	frameBuffer = 0;
54 	backBuffer = 0;
55 
56 	mDepthStencil = nullptr;
57 	mWindowSubclassed = false;
58 	mTextureFormat = textureFormat;
59 	mTextureTarget = textureType;
60 
61 	mSwapInterval = -1;
62 	setSwapInterval(1);
63 }
64 
~Surface()65 Surface::~Surface()
66 {
67 	release();
68 }
69 
initialize()70 bool Surface::initialize()
71 {
72 	ASSERT(!frameBuffer && !backBuffer && !mDepthStencil);
73 
74 	return reset();
75 }
76 
release()77 void Surface::release()
78 {
79 	if(mDepthStencil)
80 	{
81 		mDepthStencil->release();
82 		mDepthStencil = nullptr;
83 	}
84 
85 	if(backBuffer)
86 	{
87 		backBuffer->release();
88 		backBuffer = 0;
89 	}
90 
91 	delete frameBuffer;
92 	frameBuffer = 0;
93 }
94 
reset()95 bool Surface::reset()
96 {
97 	if(!mWindow)
98 	{
99 		return reset(mWidth, mHeight);
100 	}
101 
102 	// FIXME: Wrap into an abstract Window class
103 	#if defined(_WIN32)
104 		RECT windowRect;
105 		GetClientRect(mWindow, &windowRect);
106 
107 		return reset(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
108 	#else
109 		XWindowAttributes windowAttributes;
110 		XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);
111 
112 		return reset(windowAttributes.width, windowAttributes.height);
113 	#endif
114 }
115 
reset(int backBufferWidth,int backBufferHeight)116 bool Surface::reset(int backBufferWidth, int backBufferHeight)
117 {
118 	release();
119 
120 	if(mWindow)
121 	{
122 		frameBuffer = ::createFrameBuffer(mDisplay->getNativeDisplay(), mWindow, backBufferWidth, backBufferHeight);
123 
124 		if(!frameBuffer)
125 		{
126 			ERR("Could not create frame buffer");
127 			release();
128 			return error(GL_OUT_OF_MEMORY, false);
129 		}
130 	}
131 
132 	backBuffer = new Image(0, backBufferWidth, backBufferHeight, GL_RGB, GL_UNSIGNED_BYTE);
133 
134 	if(!backBuffer)
135 	{
136 		ERR("Could not create back buffer");
137 		release();
138 		return error(GL_OUT_OF_MEMORY, false);
139 	}
140 
141 	if(true)   // Always provide a depth/stencil buffer
142 	{
143 		mDepthStencil = new Image(0, backBufferWidth, backBufferHeight, sw::FORMAT_D24S8, 1, false, true);
144 
145 		if(!mDepthStencil)
146 		{
147 			ERR("Could not create depth/stencil buffer for surface");
148 			release();
149 			return error(GL_OUT_OF_MEMORY, false);
150 		}
151 	}
152 
153 	mWidth = backBufferWidth;
154 	mHeight = backBufferHeight;
155 
156 	return true;
157 }
158 
swap()159 void Surface::swap()
160 {
161 	if(backBuffer)
162 	{
163 		frameBuffer->flip(backBuffer);
164 
165 		checkForResize();
166 	}
167 }
168 
getRenderTarget()169 Image *Surface::getRenderTarget()
170 {
171 	if(backBuffer)
172 	{
173 		backBuffer->addRef();
174 	}
175 
176 	return backBuffer;
177 }
178 
getDepthStencil()179 Image *Surface::getDepthStencil()
180 {
181 	if(mDepthStencil)
182 	{
183 		mDepthStencil->addRef();
184 	}
185 
186 	return mDepthStencil;
187 }
188 
setSwapInterval(GLint interval)189 void Surface::setSwapInterval(GLint interval)
190 {
191 	if(mSwapInterval == interval)
192 	{
193 		return;
194 	}
195 
196 	mSwapInterval = interval;
197 	mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
198 	mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
199 }
200 
getWidth() const201 GLint Surface::getWidth() const
202 {
203 	return mWidth;
204 }
205 
getHeight() const206 GLint Surface::getHeight() const
207 {
208 	return mHeight;
209 }
210 
getTextureFormat() const211 GLenum Surface::getTextureFormat() const
212 {
213 	return mTextureFormat;
214 }
215 
getTextureTarget() const216 GLenum Surface::getTextureTarget() const
217 {
218 	return mTextureTarget;
219 }
220 
checkForResize()221 bool Surface::checkForResize()
222 {
223 	#if defined(_WIN32)
224 		RECT client;
225 		if(!GetClientRect(mWindow, &client))
226 		{
227 			ASSERT(false);
228 			return false;
229 		}
230 
231 		int clientWidth = client.right - client.left;
232 		int clientHeight = client.bottom - client.top;
233 	#else
234 		XWindowAttributes windowAttributes;
235 		XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);
236 
237 		int clientWidth = windowAttributes.width;
238 		int clientHeight = windowAttributes.height;
239 	#endif
240 
241 	bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
242 
243 	if(sizeDirty)
244 	{
245 		reset(clientWidth, clientHeight);
246 
247 		if(getCurrentDrawSurface() == this)
248 		{
249 			getContext()->makeCurrent(this);
250 		}
251 
252 		return true;
253 	}
254 
255 	return false;
256 }
257 }
258