• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006-2012, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jérôme Duval, korli@users.berlios.de
7  *		Philippe Houdoin, philippe.houdoin@free.fr
8  *		Artur Wyszynski, harakash@gmail.com
9  *		Alexander von Gluck IV, kallisti5@unixzen.com
10  */
11 
12 
13 #include "SoftwareRenderer.h"
14 
15 #include <Autolock.h>
16 #include <interface/DirectWindowPrivate.h>
17 #include <GraphicsDefs.h>
18 #include <Screen.h>
19 #include <stdio.h>
20 #include <sys/time.h>
21 #include <new>
22 
23 
24 #ifdef DEBUG
25 #	define TRACE(x...) printf("SoftwareRenderer: " x)
26 #	define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
27 #else
28 #	define TRACE(x...)
29 #	define CALLED()
30 #endif
31 #define ERROR(x...)	printf("SoftwareRenderer: " x)
32 
33 
34 extern const char* color_space_name(color_space space);
35 
36 
37 extern "C" _EXPORT BGLRenderer*
instantiate_gl_renderer(BGLView * view,ulong opts)38 instantiate_gl_renderer(BGLView *view, ulong opts)
39 {
40 	return new SoftwareRenderer(view, opts);
41 }
42 
43 struct RasBuf32
44 {
45 	int32 width, height, stride;
46 	int32 orgX, orgY;
47 	int32 *colors;
48 
RasBuf32RasBuf3249 	RasBuf32(int32 width, int32 height, int32 stride, int32 orgX, int32 orgY, int32 *colors):
50 		width(width), height(height), stride(stride), orgX(orgX), orgY(orgY), colors(colors)
51 	{}
52 
RasBuf32RasBuf3253 	RasBuf32(BBitmap *bmp)
54 	{
55 		width  = bmp->Bounds().IntegerWidth()  + 1;
56 		height = bmp->Bounds().IntegerHeight() + 1;
57 		stride = bmp->BytesPerRow()/4;
58 		orgX   = 0;
59 		orgY   = 0;
60 		colors = (int32*)bmp->Bits();
61 	}
62 
RasBuf32RasBuf3263 	RasBuf32(direct_buffer_info *info)
64 	{
65 		width  = 0x7fffffff;
66 		height = 0x7fffffff;
67 		stride = info->bytes_per_row/4;
68 		orgX   = 0;
69 		orgY   = 0;
70 		colors = (int32*)info->bits;
71 	}
72 
ClipSizeRasBuf3273 	void ClipSize(int32 x, int32 y, int32 w, int32 h)
74 	{
75 		if (x < 0) {w += x; x = 0;}
76 		if (y < 0) {h += y; y = 0;}
77 		if (x + w >  width) {w = width  - x;}
78 		if (y + h > height) {h = height - y;}
79 		if ((w > 0) && (h > 0)) {
80 			colors += y*stride + x;
81 			width  = w;
82 			height = h;
83 		} else {
84 			width = 0; height = 0; colors = NULL;
85 		}
86 		if (x + orgX > 0) {orgX += x;} else {orgX = 0;}
87 		if (y + orgY > 0) {orgY += y;} else {orgY = 0;}
88 	}
89 
ClipRectRasBuf3290 	void ClipRect(int32 l, int32 t, int32 r, int32 b)
91 	{
92 		ClipSize(l, t, r - l, b - t);
93 	}
94 
ShiftRasBuf3295 	void Shift(int32 dx, int32 dy)
96 	{
97 		orgX += dx;
98 		orgY += dy;
99 	}
100 
ClearRasBuf32101 	void Clear(int32 color)
102 	{
103 		RasBuf32 dst = *this;
104 		dst.stride -= dst.width;
105 		for (; dst.height > 0; dst.height--) {
106 			for (int32 i = dst.width; i > 0; i--)
107 				*dst.colors++ = color;
108 			dst.colors += dst.stride;
109 		}
110 	}
111 
BlitRasBuf32112 	void Blit(RasBuf32 src)
113 	{
114 		RasBuf32 dst = *this;
115 		int32 x, y;
116 		x = src.orgX - orgX;
117 		y = src.orgY - orgY;
118 		dst.ClipSize(x, y, src.width, src.height);
119 		src.ClipSize(-x, -y, width, height);
120 		for (; dst.height > 0; dst.height--) {
121 			memcpy(dst.colors, src.colors, 4*dst.width);
122 			dst.colors += dst.stride;
123 			src.colors += src.stride;
124 		}
125 	}
126 };
127 
SoftwareRenderer(BGLView * view,ulong options)128 SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options)
129 	:
130 	BGLRenderer(view, options),
131 	fDirectModeEnabled(false),
132 	fInfo(NULL),
133 	fInfoLocker("info locker"),
134 	fOptions(options),
135 	fColorSpace(B_NO_COLOR_SPACE)
136 {
137 	CALLED();
138 
139 	// Initialize the "Haiku Software GL Pipe"
140 	time_t beg;
141 	time_t end;
142 	beg = time(NULL);
143 	fContextObj = new GalliumContext(options);
144 	end = time(NULL);
145 	TRACE("Haiku Software GL Pipe initialization time: %f.\n",
146 		difftime(end, beg));
147 
148 	BRect b = view->Bounds();
149 	fColorSpace = BScreen(view->Window()).ColorSpace();
150 	TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
151 
152 	fWidth = (GLint)b.IntegerWidth();
153 	fHeight = (GLint)b.IntegerHeight();
154 
155 	// Initialize the first "Haiku Software GL Pipe" context
156 	beg = time(NULL);
157 	fContextID = fContextObj->CreateContext(this);
158 	end = time(NULL);
159 
160 	if (fContextID < 0)
161 		ERROR("%s: There was an error creating the context!\n", __func__);
162 	else {
163 		TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
164 			__func__, difftime(end, beg));
165 	}
166 
167 	if (!fContextObj->GetCurrentContext())
168 		LockGL();
169 }
170 
171 
~SoftwareRenderer()172 SoftwareRenderer::~SoftwareRenderer()
173 {
174 	CALLED();
175 
176 	if (fContextObj)
177 		delete fContextObj;
178 }
179 
180 
181 void
LockGL()182 SoftwareRenderer::LockGL()
183 {
184 //	CALLED();
185 	BGLRenderer::LockGL();
186 
187 	color_space cs = BScreen(GLView()->Window()).ColorSpace();
188 
189 	{
190 		BAutolock lock(fInfoLocker);
191 		if (fDirectModeEnabled && fInfo != NULL) {
192 			fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
193 			fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
194 		}
195 
196 		fContextObj->Validate(fWidth, fHeight);
197 		fColorSpace = cs;
198 	}
199 
200 	// do not hold fInfoLocker here to avoid deadlock
201 	fContextObj->SetCurrentContext(true, fContextID);
202 }
203 
204 
205 void
UnlockGL()206 SoftwareRenderer::UnlockGL()
207 {
208 //	CALLED();
209 	if ((fOptions & BGL_DOUBLE) == 0) {
210 		SwapBuffers();
211 	}
212 	fContextObj->SetCurrentContext(false, fContextID);
213 	BGLRenderer::UnlockGL();
214 }
215 
216 
217 void
Display(BBitmap * bitmap,BRect * updateRect)218 SoftwareRenderer::Display(BBitmap *bitmap, BRect *updateRect)
219 {
220 //	CALLED();
221 
222 	if (!fDirectModeEnabled) {
223 		// TODO: avoid timeout
224 		if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
225 			GLView()->DrawBitmap(bitmap, B_ORIGIN);
226 			GLView()->UnlockLooper();
227 		}
228 	} else {
229 		BAutolock lock(fInfoLocker);
230 		if (fInfo != NULL) {
231 			RasBuf32 srcBuf(bitmap);
232 			RasBuf32 dstBuf(fInfo);
233 			for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
234 				clipping_rect *clip = &fInfo->clip_list[i];
235 				RasBuf32 dstClip = dstBuf;
236 				dstClip.ClipRect(clip->left, clip->top, clip->right + 1, clip->bottom + 1);
237 				dstClip.Shift(-fInfo->window_bounds.left, -fInfo->window_bounds.top);
238 				dstClip.Blit(srcBuf);
239 			}
240 		}
241 	}
242 }
243 
244 
245 void
SwapBuffers(bool vsync)246 SoftwareRenderer::SwapBuffers(bool vsync)
247 {
248 	BScreen screen(GLView()->Window());
249 	fContextObj->SwapBuffers(fContextID);
250 	fContextObj->Validate(fWidth, fHeight);
251 	if (vsync)
252 		screen.WaitForRetrace();
253 }
254 
255 void
Draw(BRect updateRect)256 SoftwareRenderer::Draw(BRect updateRect)
257 {
258 //	CALLED();
259 	fContextObj->Draw(fContextID, updateRect);
260 }
261 
262 
263 status_t
CopyPixelsOut(BPoint location,BBitmap * bitmap)264 SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
265 {
266 	CALLED();
267 
268 	// TODO: implement
269 	return B_ERROR;
270 }
271 
272 
273 status_t
CopyPixelsIn(BBitmap * bitmap,BPoint location)274 SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
275 {
276 	CALLED();
277 
278 	// TODO: implement
279 	return B_ERROR;
280 }
281 
282 
283 void
EnableDirectMode(bool enabled)284 SoftwareRenderer::EnableDirectMode(bool enabled)
285 {
286 	fDirectModeEnabled = enabled;
287 }
288 
289 
290 void
DirectConnected(direct_buffer_info * info)291 SoftwareRenderer::DirectConnected(direct_buffer_info *info)
292 {
293 //	CALLED();
294 	BAutolock lock(fInfoLocker);
295 	if (info) {
296 		if (!fInfo) {
297 			fInfo = (direct_buffer_info *)calloc(1,
298 				DIRECT_BUFFER_INFO_AREA_SIZE);
299 		}
300 		memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
301 	} else if (fInfo) {
302 		free(fInfo);
303 		fInfo = NULL;
304 	}
305 }
306 
307 
308 void
FrameResized(float width,float height)309 SoftwareRenderer::FrameResized(float width, float height)
310 {
311 	TRACE("%s: %f x %f\n", __func__, width, height);
312 
313 	BAutolock lock(fInfoLocker);
314 	fWidth = (GLuint)width;
315 	fHeight = (GLuint)height;
316 }
317