Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2012, Haiku, Inc. All Rights Reserved.
3
 * Distributed under the terms of the MIT License.
4
 *
5
 * Authors:
6
 *		Artur Wyszynski, harakash@gmail.com
7
 *		Alexander von Gluck IV, kallisti5@unixzen.com
8
 */
9
 
10
 
11
#include "GalliumContext.h"
12
 
13
#include 
14
 
15
#include "GLView.h"
16
 
17
#include "bitmap_wrapper.h"
18
 
19
#include "glapi/glapi.h"
20
#include "pipe/p_format.h"
21
//#include "state_tracker/st_cb_fbo.h"
22
//#include "state_tracker/st_cb_flush.h"
23
#include "state_tracker/st_context.h"
24
#include "state_tracker/st_gl_api.h"
25
#include "state_tracker/sw_winsys.h"
26
#include "sw/hgl/hgl_sw_winsys.h"
27
#include "util/u_atomic.h"
28
#include "util/u_memory.h"
29
 
30
#include "target-helpers/inline_sw_helper.h"
31
#include "target-helpers/inline_debug_helper.h"
32
 
33
 
34
#ifdef DEBUG
35
#	define TRACE(x...) printf("GalliumContext: " x)
36
#	define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
37
#else
38
#	define TRACE(x...)
39
#	define CALLED()
40
#endif
41
#define ERROR(x...) printf("GalliumContext: " x)
42
 
43
 
44
GalliumContext::GalliumContext(ulong options)
45
	:
46
	fOptions(options),
47
	fScreen(NULL),
48
	fCurrentContext(0)
49
{
50
	CALLED();
51
 
52
	// Make all contexts a known value
53
	for (context_id i = 0; i < CONTEXT_MAX; i++)
54
		fContext[i] = NULL;
55
 
56
	CreateScreen();
57
 
58
	pipe_mutex_init(fMutex);
59
}
60
 
61
 
62
GalliumContext::~GalliumContext()
63
{
64
	CALLED();
65
 
66
	// Destroy our contexts
67
	Lock();
68
	for (context_id i = 0; i < CONTEXT_MAX; i++)
69
		DestroyContext(i);
70
	Unlock();
71
 
72
	pipe_mutex_destroy(fMutex);
73
 
74
	// TODO: Destroy fScreen
75
}
76
 
77
 
78
status_t
79
GalliumContext::CreateScreen()
80
{
81
	CALLED();
82
 
83
	// Allocate winsys and attach callback hooks
84
	struct sw_winsys* winsys = hgl_create_sw_winsys();
85
 
86
	if (!winsys) {
87
		ERROR("%s: Couldn't allocate sw_winsys!\n", __func__);
88
		return B_ERROR;
89
	}
90
 
91
	fScreen = sw_screen_create(winsys);
92
 
93
	if (fScreen == NULL) {
94
		ERROR("%s: Couldn't create screen!\n", __FUNCTION__);
95
		FREE(winsys);
96
		return B_ERROR;
97
	}
98
 
99
	debug_screen_wrap(fScreen);
100
 
101
	const char* driverName = fScreen->get_name(fScreen);
102
	ERROR("%s: Using %s driver.\n", __func__, driverName);
103
 
104
	return B_OK;
105
}
106
 
107
 
108
context_id
109
GalliumContext::CreateContext(Bitmap *bitmap)
110
{
111
	CALLED();
112
 
113
	struct hgl_context* context = CALLOC_STRUCT(hgl_context);
114
 
115
	if (!context) {
116
		ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__);
117
		return 0;
118
	}
119
 
120
	// Set up the initial things our context needs
121
	context->bitmap = bitmap;
122
	context->colorSpace = get_bitmap_color_space(bitmap);
123
	context->screen = fScreen;
124
	context->draw = NULL;
125
	context->read = NULL;
126
	context->st = NULL;
127
 
128
	// Create st_gl_api
129
	context->api = hgl_create_st_api();
130
	if (!context->api) {
131
		ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__);
132
		return -1;
133
	}
134
 
135
	// Create state_tracker manager
136
	context->manager = hgl_create_st_manager(context);
137
 
138
	// Create state tracker visual
139
	context->stVisual = hgl_create_st_visual(fOptions);
140
 
141
	// Create state tracker framebuffers
142
	context->draw = hgl_create_st_framebuffer(context);
143
	context->read = hgl_create_st_framebuffer(context);
144
 
145
	if (!context->draw || !context->read) {
146
		ERROR("%s: Problem allocating framebuffer!\n", __func__);
147
		FREE(context->stVisual);
148
		return -1;
149
	}
150
 
151
	// Build state tracker attributes
152
	struct st_context_attribs attribs;
153
	memset(&attribs, 0, sizeof(attribs));
154
	attribs.options.force_glsl_extensions_warn = false;
155
	attribs.profile = ST_PROFILE_DEFAULT;
156
	attribs.visual = *context->stVisual;
157
	attribs.major = 1;
158
	attribs.minor = 0;
159
	//attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
160
 
161
	// Create context using state tracker api call
162
	enum st_context_error result;
163
	context->st = context->api->create_context(context->api, context->manager,
164
		&attribs, &result, context->st);
165
 
166
	if (!context->st) {
167
		ERROR("%s: Couldn't create mesa state tracker context!\n",
168
			__func__);
169
		switch (result) {
170
			case ST_CONTEXT_SUCCESS:
171
				ERROR("%s: State tracker error: SUCCESS?\n", __func__);
172
				break;
173
			case ST_CONTEXT_ERROR_NO_MEMORY:
174
				ERROR("%s: State tracker error: NO_MEMORY\n", __func__);
175
				break;
176
			case ST_CONTEXT_ERROR_BAD_API:
177
				ERROR("%s: State tracker error: BAD_API\n", __func__);
178
				break;
179
			case ST_CONTEXT_ERROR_BAD_VERSION:
180
				ERROR("%s: State tracker error: BAD_VERSION\n", __func__);
181
				break;
182
			case ST_CONTEXT_ERROR_BAD_FLAG:
183
				ERROR("%s: State tracker error: BAD_FLAG\n", __func__);
184
				break;
185
			case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
186
				ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__);
187
				break;
188
			case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
189
				ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__);
190
				break;
191
		}
192
 
193
		hgl_destroy_st_visual(context->stVisual);
194
		FREE(context);
195
		return -1;
196
	}
197
 
198
	assert(!context->st->st_manager_private);
199
	context->st->st_manager_private = (void*)context;
200
 
201
	struct st_context *stContext = (struct st_context*)context->st;
202
 
203
	// Init Gallium3D Post Processing
204
	// TODO: no pp filters are enabled yet through postProcessEnable
205
	context->postProcess = pp_init(stContext->pipe, context->postProcessEnable,
206
		stContext->cso_context);
207
 
208
	context_id contextNext = -1;
209
	Lock();
210
	for (context_id i = 0; i < CONTEXT_MAX; i++) {
211
		if (fContext[i] == NULL) {
212
			fContext[i] = context;
213
			contextNext = i;
214
			break;
215
		}
216
	}
217
	Unlock();
218
 
219
	if (contextNext < 0) {
220
		ERROR("%s: The next context is invalid... something went wrong!\n",
221
			__func__);
222
		//st_destroy_context(context->st);
223
		FREE(context->stVisual);
224
		FREE(context);
225
		return -1;
226
	}
227
 
228
	TRACE("%s: context #%" B_PRIu64 " is the next available context\n",
229
		__func__, contextNext);
230
 
231
	return contextNext;
232
}
233
 
234
 
235
void
236
GalliumContext::DestroyContext(context_id contextID)
237
{
238
	// fMutex should be locked *before* calling DestoryContext
239
 
240
	// See if context is used
241
	if (!fContext[contextID])
242
		return;
243
 
244
	if (fContext[contextID]->st) {
245
		fContext[contextID]->st->flush(fContext[contextID]->st, 0, NULL);
246
		fContext[contextID]->st->destroy(fContext[contextID]->st);
247
	}
248
 
249
	if (fContext[contextID]->postProcess)
250
		pp_free(fContext[contextID]->postProcess);
251
 
252
	// Delete state tracker framebuffer objects
253
	if (fContext[contextID]->read)
254
		delete fContext[contextID]->read;
255
	if (fContext[contextID]->draw)
256
		delete fContext[contextID]->draw;
257
 
258
	if (fContext[contextID]->stVisual)
259
		hgl_destroy_st_visual(fContext[contextID]->stVisual);
260
 
261
	if (fContext[contextID]->manager)
262
		hgl_destroy_st_manager(fContext[contextID]->manager);
263
 
264
	FREE(fContext[contextID]);
265
}
266
 
267
 
268
status_t
269
GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
270
{
271
	CALLED();
272
 
273
	if (contextID < 0 || contextID > CONTEXT_MAX) {
274
		ERROR("%s: Invalid context ID range!\n", __func__);
275
		return B_ERROR;
276
	}
277
 
278
	Lock();
279
	context_id oldContextID = fCurrentContext;
280
	struct hgl_context* context = fContext[contextID];
281
	Unlock();
282
 
283
	if (!context) {
284
		ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n",
285
			__func__, contextID);
286
		return B_ERROR;
287
	}
288
 
289
	if (!bitmap) {
290
		context->api->make_current(context->api, NULL, NULL, NULL);
291
		return B_OK;
292
	}
293
 
294
	// Everything seems valid, lets set the new context.
295
	fCurrentContext = contextID;
296
 
297
	if (oldContextID > 0 && oldContextID != contextID) {
298
		fContext[oldContextID]->st->flush(fContext[oldContextID]->st,
299
			ST_FLUSH_FRONT, NULL);
300
	}
301
 
302
	// We need to lock and unlock framebuffers before accessing them
303
	context->api->make_current(context->api, context->st, context->draw->stfbi,
304
		context->read->stfbi);
305
 
306
	//if (context->textures[ST_ATTACHMENT_BACK_LEFT]
307
	//	&& context->textures[ST_ATTACHMENT_DEPTH_STENCIL]
308
	//	&& context->postProcess) {
309
	//	TRACE("Postprocessing textures...\n");
310
	//	pp_init_fbos(context->postProcess,
311
	//		context->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
312
	//		context->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
313
	//}
314
 
315
	context->bitmap = bitmap;
316
	//context->st->pipe->priv = context;
317
 
318
	return B_OK;
319
}
320
 
321
 
322
status_t
323
GalliumContext::SwapBuffers(context_id contextID)
324
{
325
	CALLED();
326
 
327
	Lock();
328
	struct hgl_context *context = fContext[contextID];
329
	Unlock();
330
 
331
	if (!context) {
332
		ERROR("%s: context not found\n", __func__);
333
		return B_ERROR;
334
	}
335
 
336
	// TODO: Where did st_notify_swapbuffers go?
337
	//st_notify_swapbuffers(context->draw->stfbi);
338
 
339
	context->st->flush(context->st, ST_FLUSH_FRONT, NULL);
340
 
341
	struct st_context *stContext = (struct st_context*)context->st;
342
 
343
	unsigned nColorBuffers = stContext->state.framebuffer.nr_cbufs;
344
	for (unsigned i = 0; i < nColorBuffers; i++) {
345
		pipe_surface* surface = stContext->state.framebuffer.cbufs[i];
346
		if (!surface) {
347
			ERROR("%s: Color buffer %d invalid!\n", __func__, i);
348
			continue;
349
		}
350
 
351
		TRACE("%s: Flushing color buffer #%d\n", __func__, i);
352
 
353
		// We pass our destination bitmap to flush_fronbuffer which passes it
354
		// to the private winsys display call.
355
		fScreen->flush_frontbuffer(fScreen, surface->texture, 0, 0,
356
			context->bitmap, NULL);
357
	}
358
 
359
	#if 0
360
	// TODO... should we flush the z stencil buffer?
361
	pipe_surface* zSurface = stContext->state.framebuffer.zsbuf;
362
	fScreen->flush_frontbuffer(fScreen, zSurface->texture, 0, 0,
363
		context->bitmap, NULL);
364
	#endif
365
 
366
	return B_OK;
367
}
368
 
369
 
370
bool
371
GalliumContext::Validate(uint32 width, uint32 height)
372
{
373
	CALLED();
374
 
375
	if (!fContext[fCurrentContext]) {
376
		return false;
377
	}
378
 
379
	if (fContext[fCurrentContext]->width != width
380
		|| fContext[fCurrentContext]->height != height) {
381
		Invalidate(width, height);
382
		return false;
383
	}
384
	return true;
385
}
386
 
387
 
388
void
389
GalliumContext::Invalidate(uint32 width, uint32 height)
390
{
391
	CALLED();
392
 
393
	assert(fContext[fCurrentContext]);
394
 
395
	// Update st_context dimensions
396
	fContext[fCurrentContext]->width = width;
397
	fContext[fCurrentContext]->height = height;
398
 
399
	// Is this the best way to invalidate?
400
	p_atomic_inc(&fContext[fCurrentContext]->read->stfbi->stamp);
401
	p_atomic_inc(&fContext[fCurrentContext]->draw->stfbi->stamp);
402
}
403
 
404
 
405
void
406
GalliumContext::Lock()
407
{
408
	CALLED();
409
	pipe_mutex_lock(fMutex);
410
}
411
 
412
 
413
void
414
GalliumContext::Unlock()
415
{
416
	CALLED();
417
	pipe_mutex_unlock(fMutex);
418
}
419
/* vim: set tabstop=4: */