Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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 
16
#include 
17
#include 
18
#include 
19
#include 
20
#include 
21
#include 
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*
38
instantiate_gl_renderer(BGLView *view, ulong opts, BGLDispatcher *dispatcher)
39
{
40
	return new SoftwareRenderer(view, opts, dispatcher);
41
}
42
 
43
SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
44
	BGLDispatcher* dispatcher)
45
	:
46
	BGLRenderer(view, options, dispatcher),
47
	fBitmap(NULL),
48
	fDirectModeEnabled(false),
49
	fInfo(NULL),
50
	fInfoLocker("info locker"),
51
	fOptions(options),
52
	fColorSpace(B_NO_COLOR_SPACE)
53
{
54
	CALLED();
55
 
56
	// Disable double buffer for the moment.
57
	//options &= ~BGL_DOUBLE;
58
 
59
	// Initialize the "Haiku Software GL Pipe"
60
	time_t beg;
61
	time_t end;
62
	beg = time(NULL);
63
	fContextObj = new GalliumContext(options);
64
	end = time(NULL);
65
	TRACE("Haiku Software GL Pipe initialization time: %f.\n",
66
		difftime(end, beg));
67
 
68
	// Allocate a bitmap
69
	BRect b = view->Bounds();
70
	fColorSpace = BScreen(view->Window()).ColorSpace();
71
	TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
72
 
73
	fWidth = (GLint)b.IntegerWidth();
74
	fHeight = (GLint)b.IntegerHeight();
75
 
76
	_AllocateBitmap();
77
 
78
	// Initialize the first "Haiku Software GL Pipe" context
79
	beg = time(NULL);
80
	fContextID = fContextObj->CreateContext(fBitmap);
81
	end = time(NULL);
82
 
83
	if (fContextID < 0)
84
		ERROR("%s: There was an error creating the context!\n", __func__);
85
	else {
86
		TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
87
			__func__, difftime(end, beg));
88
	}
89
 
90
	if (!fContextObj->GetCurrentContext())
91
		LockGL();
92
}
93
 
94
 
95
SoftwareRenderer::~SoftwareRenderer()
96
{
97
	CALLED();
98
 
99
	if (fContextObj)
100
		delete fContextObj;
101
	if (fBitmap)
102
		delete fBitmap;
103
}
104
 
105
 
106
void
107
SoftwareRenderer::LockGL()
108
{
109
//	CALLED();
110
	BGLRenderer::LockGL();
111
 
112
	color_space cs = BScreen(GLView()->Window()).ColorSpace();
113
 
114
	BAutolock lock(fInfoLocker);
115
	if (fDirectModeEnabled && fInfo != NULL) {
116
		fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
117
		fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
118
	}
119
 
120
	if (fBitmap && cs == fColorSpace && fContextObj->Validate(fWidth, fHeight)) {
121
		fContextObj->SetCurrentContext(fBitmap, fContextID);
122
		return;
123
	}
124
 
125
	fColorSpace = cs;
126
 
127
	_AllocateBitmap();
128
	fContextObj->SetCurrentContext(fBitmap, fContextID);
129
}
130
 
131
 
132
void
133
SoftwareRenderer::UnlockGL()
134
{
135
//	CALLED();
136
	if ((fOptions & BGL_DOUBLE) == 0) {
137
		SwapBuffers();
138
	}
139
	fContextObj->SetCurrentContext(NULL, fContextID);
140
	BGLRenderer::UnlockGL();
141
}
142
 
143
 
144
void
145
SoftwareRenderer::SwapBuffers(bool vsync)
146
{
147
//	CALLED();
148
	if (!fBitmap)
149
		return;
150
 
151
	BScreen screen(GLView()->Window());
152
 
153
	fContextObj->SwapBuffers(fContextID);
154
 
155
	BAutolock lock(fInfoLocker);
156
 
157
	if (!fDirectModeEnabled || fInfo == NULL) {
158
		if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
159
			GLView()->DrawBitmap(fBitmap, B_ORIGIN);
160
			GLView()->UnlockLooper();
161
			if (vsync)
162
				screen.WaitForRetrace();
163
		}
164
		return;
165
	}
166
 
167
	// check the bitmap size still matches the size
168
	if (fInfo->window_bounds.bottom - fInfo->window_bounds.top
169
			!= fBitmap->Bounds().IntegerHeight()
170
			|| fInfo->window_bounds.right - fInfo->window_bounds.left
171
			!= fBitmap->Bounds().IntegerWidth()) {
172
		ERROR("%s: Bitmap size doesn't match size!\n", __func__);
173
		return;
174
	}
175
 
176
	uint32 bytesPerRow = fBitmap->BytesPerRow();
177
	uint8 bytesPerPixel = bytesPerRow / fBitmap->Bounds().IntegerWidth();
178
 
179
	for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
180
		clipping_rect *clip = &fInfo->clip_list[i];
181
		int32 height = clip->bottom - clip->top + 1;
182
		int32 bytesWidth
183
			= (clip->right - clip->left + 1) * bytesPerPixel;
184
		bytesWidth -= bytesPerPixel;
185
		uint8 *p = (uint8 *)fInfo->bits + clip->top
186
			* fInfo->bytes_per_row + clip->left * bytesPerPixel;
187
		uint8 *b = (uint8 *)fBitmap->Bits()
188
			+ (clip->top - fInfo->window_bounds.top) * bytesPerRow
189
			+ (clip->left - fInfo->window_bounds.left) * bytesPerPixel;
190
 
191
		for (int y = 0; y < height - 1; y++) {
192
			memcpy(p, b, bytesWidth);
193
			p += fInfo->bytes_per_row;
194
			b += bytesPerRow;
195
		}
196
	}
197
 
198
	if (vsync)
199
		screen.WaitForRetrace();
200
}
201
 
202
 
203
void
204
SoftwareRenderer::Draw(BRect updateRect)
205
{
206
//	CALLED();
207
	if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap)
208
		GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
209
}
210
 
211
 
212
status_t
213
SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
214
{
215
	CALLED();
216
	color_space scs = fBitmap->ColorSpace();
217
	color_space dcs = bitmap->ColorSpace();
218
 
219
	if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) {
220
		ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
221
			__PRETTY_FUNCTION__, color_space_name(scs), color_space_name(dcs));
222
		return B_BAD_TYPE;
223
	}
224
 
225
	BRect sr = fBitmap->Bounds();
226
	BRect dr = bitmap->Bounds();
227
 
228
//	int32 w1 = sr.IntegerWidth();
229
//	int32 h1 = sr.IntegerHeight();
230
//	int32 w2 = dr.IntegerWidth();
231
//	int32 h2 = dr.IntegerHeight();
232
 
233
	sr = sr & dr.OffsetBySelf(location);
234
	dr = sr.OffsetByCopy(-location.x, -location.y);
235
 
236
	uint8 *ps = (uint8 *) fBitmap->Bits();
237
	uint8 *pd = (uint8 *) bitmap->Bits();
238
	uint32 *s, *d;
239
	uint32 y;
240
	for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
241
		s = (uint32 *)(ps + y * fBitmap->BytesPerRow());
242
		s += (uint32) sr.left;
243
 
244
		d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
245
			* bitmap->BytesPerRow());
246
		d += (uint32) dr.left;
247
		memcpy(d, s, dr.IntegerWidth() * 4);
248
	}
249
 
250
	return B_OK;
251
}
252
 
253
 
254
status_t
255
SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
256
{
257
	CALLED();
258
 
259
	color_space sourceCS = bitmap->ColorSpace();
260
	color_space destinationCS = fBitmap->ColorSpace();
261
 
262
	if (sourceCS != destinationCS
263
		&& (sourceCS != B_RGB32 || destinationCS != B_RGBA32)) {
264
		ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
265
			__PRETTY_FUNCTION__, color_space_name(sourceCS),
266
			color_space_name(destinationCS));
267
		return B_BAD_TYPE;
268
	}
269
 
270
	BRect sr = bitmap->Bounds();
271
	BRect dr = fBitmap->Bounds();
272
 
273
	sr = sr & dr.OffsetBySelf(location);
274
	dr = sr.OffsetByCopy(-location.x, -location.y);
275
 
276
	uint8 *ps = (uint8 *) bitmap->Bits();
277
	uint8 *pd = (uint8 *) fBitmap->Bits();
278
	uint32 *s, *d;
279
	uint32 y;
280
 
281
	for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
282
		s = (uint32 *)(ps + y * bitmap->BytesPerRow());
283
		s += (uint32) sr.left;
284
 
285
		d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
286
			* fBitmap->BytesPerRow());
287
		d += (uint32) dr.left;
288
 
289
		memcpy(d, s, dr.IntegerWidth() * 4);
290
	}
291
 
292
	return B_OK;
293
}
294
 
295
 
296
void
297
SoftwareRenderer::EnableDirectMode(bool enabled)
298
{
299
	fDirectModeEnabled = enabled;
300
}
301
 
302
 
303
void
304
SoftwareRenderer::DirectConnected(direct_buffer_info *info)
305
{
306
//	CALLED();
307
	BAutolock lock(fInfoLocker);
308
	if (info) {
309
		if (!fInfo) {
310
			fInfo = (direct_buffer_info *)calloc(1,
311
				DIRECT_BUFFER_INFO_AREA_SIZE);
312
		}
313
		memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
314
	} else if (fInfo) {
315
		free(fInfo);
316
		fInfo = NULL;
317
	}
318
}
319
 
320
 
321
void
322
SoftwareRenderer::FrameResized(float width, float height)
323
{
324
	TRACE("%s: %f x %f\n", __func__, width, height);
325
 
326
	BAutolock lock(fInfoLocker);
327
	fWidth = (GLuint)width;
328
	fHeight = (GLuint)height;
329
}
330
 
331
 
332
void
333
SoftwareRenderer::_AllocateBitmap()
334
{
335
//	CALLED();
336
 
337
	// allocate new size of back buffer bitmap
338
	BAutolock lock(fInfoLocker);
339
	if (fBitmap)
340
		delete fBitmap;
341
 
342
	if (fWidth < 1 || fHeight < 1) {
343
		TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__,
344
			fWidth, fHeight);
345
		return;
346
	}
347
	BRect rect(0.0, 0.0, fWidth, fHeight);
348
	fBitmap = new (std::nothrow) BBitmap(rect, fColorSpace);
349
	if (fBitmap == NULL) {
350
		TRACE("%s: Can't create bitmap!\n", __func__);
351
		return;
352
	}
353
 
354
	TRACE("%s: New bitmap size: %" B_PRId32 " x %" B_PRId32 "\n", __func__,
355
		fBitmap->Bounds().IntegerWidth(), fBitmap->Bounds().IntegerHeight());
356
 
357
#if 0
358
	// debug..
359
	void *data = fBitmap->Bits();
360
	memset(data, 0xcc, fBitmap->BitsLength());
361
#endif
362
}