• 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 		void *source = backBuffer->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
164 		frameBuffer->flip(source, backBuffer->Surface::getInternalFormat(), backBuffer->getInternalPitchB());
165 		backBuffer->unlockInternal();
166 
167 		checkForResize();
168 	}
169 }
170 
getRenderTarget()171 Image *Surface::getRenderTarget()
172 {
173 	if(backBuffer)
174 	{
175 		backBuffer->addRef();
176 	}
177 
178 	return backBuffer;
179 }
180 
getDepthStencil()181 Image *Surface::getDepthStencil()
182 {
183 	if(mDepthStencil)
184 	{
185 		mDepthStencil->addRef();
186 	}
187 
188 	return mDepthStencil;
189 }
190 
setSwapInterval(GLint interval)191 void Surface::setSwapInterval(GLint interval)
192 {
193 	if(mSwapInterval == interval)
194 	{
195 		return;
196 	}
197 
198 	mSwapInterval = interval;
199 	mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval());
200 	mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval());
201 }
202 
getWidth() const203 GLint Surface::getWidth() const
204 {
205 	return mWidth;
206 }
207 
getHeight() const208 GLint Surface::getHeight() const
209 {
210 	return mHeight;
211 }
212 
getTextureFormat() const213 GLenum Surface::getTextureFormat() const
214 {
215 	return mTextureFormat;
216 }
217 
getTextureTarget() const218 GLenum Surface::getTextureTarget() const
219 {
220 	return mTextureTarget;
221 }
222 
checkForResize()223 bool Surface::checkForResize()
224 {
225 	#if defined(_WIN32)
226 		RECT client;
227 		if(!GetClientRect(mWindow, &client))
228 		{
229 			ASSERT(false);
230 			return false;
231 		}
232 
233 		int clientWidth = client.right - client.left;
234 		int clientHeight = client.bottom - client.top;
235 	#else
236 		XWindowAttributes windowAttributes;
237 		XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes);
238 
239 		int clientWidth = windowAttributes.width;
240 		int clientHeight = windowAttributes.height;
241 	#endif
242 
243 	bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
244 
245 	if(sizeDirty)
246 	{
247 		reset(clientWidth, clientHeight);
248 
249 		if(getCurrentDrawSurface() == this)
250 		{
251 			getContext()->makeCurrent(this);
252 		}
253 
254 		return true;
255 	}
256 
257 	return false;
258 }
259 }
260