11
11
#include " GalliumContext.h"
12
12
13
13
#include < stdio.h>
14
+ #include < algorithm>
14
15
15
16
#include " GLView.h"
16
17
41
42
#endif
42
43
#define ERROR (x... ) printf(" GalliumContext: " x)
43
44
45
+ int32 GalliumContext::fDisplayRefCount = 0 ;
46
+ hgl_display* GalliumContext::fDisplay = NULL ;
44
47
45
48
GalliumContext::GalliumContext (ulong options)
46
49
:
47
50
fOptions(options),
48
- fScreen(NULL ),
49
51
fCurrentContext(0 )
50
52
{
51
53
CALLED ();
@@ -54,7 +56,7 @@ GalliumContext::GalliumContext(ulong options)
54
56
for (context_id i = 0 ; i < CONTEXT_MAX; i++)
55
57
fContext [i] = NULL ;
56
58
57
- CreateScreen ();
59
+ CreateDisplay ();
58
60
59
61
(void ) mtx_init (&fMutex , mtx_plain);
60
62
}
@@ -70,17 +72,20 @@ GalliumContext::~GalliumContext()
70
72
DestroyContext (i);
71
73
Unlock ();
72
74
73
- mtx_destroy (& fMutex );
75
+ DestroyDisplay ( );
74
76
75
- // TODO: Destroy fScreen
77
+ mtx_destroy (& fMutex );
76
78
}
77
79
78
80
79
81
status_t
80
- GalliumContext::CreateScreen ()
82
+ GalliumContext::CreateDisplay ()
81
83
{
82
84
CALLED ();
83
85
86
+ if (atomic_add (&fDisplayRefCount , 1 ) > 0 )
87
+ return B_OK;
88
+
84
89
// Allocate winsys and attach callback hooks
85
90
struct sw_winsys * winsys = hgl_create_sw_winsys ();
86
91
@@ -89,25 +94,47 @@ GalliumContext::CreateScreen()
89
94
return B_ERROR;
90
95
}
91
96
92
- fScreen = sw_screen_create (winsys);
97
+ struct pipe_screen * screen = sw_screen_create (winsys);
93
98
94
- if (fScreen == NULL ) {
99
+ if (screen == NULL ) {
95
100
ERROR (" %s: Couldn't create screen!\n " , __FUNCTION__);
96
- FREE (winsys);
101
+ winsys-> destroy (winsys);
97
102
return B_ERROR;
98
103
}
99
104
100
- debug_screen_wrap (fScreen );
105
+ debug_screen_wrap (screen );
101
106
102
- const char * driverName = fScreen ->get_name (fScreen );
107
+ const char * driverName = screen ->get_name (screen );
103
108
ERROR (" %s: Using %s driver.\n " , __func__, driverName);
104
109
110
+ fDisplay = hgl_create_display (screen);
111
+
112
+ if (fDisplay == NULL ) {
113
+ ERROR (" %s: Couldn't create display!\n " , __FUNCTION__);
114
+ screen->destroy (screen); // will also destroy winsys
115
+ return B_ERROR;
116
+ }
117
+
105
118
return B_OK;
106
119
}
107
120
108
121
122
+ void
123
+ GalliumContext::DestroyDisplay ()
124
+ {
125
+ if (atomic_add (&fDisplayRefCount , -1 ) > 1 )
126
+ return ;
127
+
128
+ if (fDisplay != NULL ) {
129
+ struct pipe_screen * screen = fDisplay ->manager ->screen ;
130
+ hgl_destroy_display (fDisplay ); fDisplay = NULL ;
131
+ screen->destroy (screen); // destroy will deallocate object
132
+ }
133
+ }
134
+
135
+
109
136
context_id
110
- GalliumContext::CreateContext (Bitmap *bitmap )
137
+ GalliumContext::CreateContext (HGLWinsysContext *wsContext )
111
138
{
112
139
CALLED ();
113
140
@@ -119,31 +146,15 @@ GalliumContext::CreateContext(Bitmap *bitmap)
119
146
}
120
147
121
148
// Set up the initial things our context needs
122
- context->bitmap = bitmap;
123
- context->colorSpace = get_bitmap_color_space (bitmap);
124
- context->screen = fScreen ;
125
- context->draw = NULL ;
126
- context->read = NULL ;
127
- context->st = NULL ;
128
-
129
- // Create st_gl_api
130
- context->api = hgl_create_st_api ();
131
- if (!context->api ) {
132
- ERROR (" %s: Couldn't obtain Mesa state tracker API!\n " , __func__);
133
- return -1 ;
134
- }
135
-
136
- // Create state_tracker manager
137
- context->manager = hgl_create_st_manager (context);
149
+ context->display = fDisplay ;
138
150
139
151
// Create state tracker visual
140
152
context->stVisual = hgl_create_st_visual (fOptions );
141
153
142
154
// Create state tracker framebuffers
143
- context->draw = hgl_create_st_framebuffer (context);
144
- context->read = hgl_create_st_framebuffer (context);
155
+ context->buffer = hgl_create_st_framebuffer (context, wsContext);
145
156
146
- if (!context->draw || !context-> read ) {
157
+ if (!context->buffer ) {
147
158
ERROR (" %s: Problem allocating framebuffer!\n " , __func__);
148
159
FREE (context->stVisual );
149
160
return -1 ;
@@ -159,10 +170,17 @@ GalliumContext::CreateContext(Bitmap *bitmap)
159
170
attribs.minor = 0 ;
160
171
// attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
161
172
173
+ struct st_context_iface * shared = NULL ;
174
+
175
+ if (fOptions & BGL_SHARE_CONTEXT) {
176
+ shared = fDisplay ->api ->get_current (fDisplay ->api );
177
+ TRACE (" shared context: %p\n " , shared);
178
+ }
179
+
162
180
// Create context using state tracker api call
163
181
enum st_context_error result;
164
- context->st = context ->api ->create_context (context ->api , context ->manager ,
165
- &attribs, &result, context-> st );
182
+ context->st = fDisplay ->api ->create_context (fDisplay ->api , fDisplay ->manager ,
183
+ &attribs, &result, shared );
166
184
167
185
if (!context->st ) {
168
186
ERROR (" %s: Couldn't create mesa state tracker context!\n " ,
@@ -200,7 +218,7 @@ GalliumContext::CreateContext(Bitmap *bitmap)
200
218
context->st ->st_manager_private = (void *)context;
201
219
202
220
struct st_context *stContext = (struct st_context *)context->st ;
203
-
221
+
204
222
// Init Gallium3D Post Processing
205
223
// TODO: no pp filters are enabled yet through postProcessEnable
206
224
context->postProcess = pp_init (stContext->pipe , context->postProcessEnable ,
@@ -243,31 +261,26 @@ GalliumContext::DestroyContext(context_id contextID)
243
261
return ;
244
262
245
263
if (fContext [contextID]->st ) {
246
- fContext [contextID]->st ->flush (fContext [contextID]->st , 0 , NULL );
264
+ fContext [contextID]->st ->flush (fContext [contextID]->st , 0 , NULL , NULL , NULL );
247
265
fContext [contextID]->st ->destroy (fContext [contextID]->st );
248
266
}
249
267
250
268
if (fContext [contextID]->postProcess )
251
269
pp_free (fContext [contextID]->postProcess );
252
270
253
271
// Delete state tracker framebuffer objects
254
- if (fContext [contextID]->read )
255
- delete fContext [contextID]->read ;
256
- if (fContext [contextID]->draw )
257
- delete fContext [contextID]->draw ;
272
+ if (fContext [contextID]->buffer )
273
+ hgl_destroy_st_framebuffer (fContext [contextID]->buffer );
258
274
259
275
if (fContext [contextID]->stVisual )
260
276
hgl_destroy_st_visual (fContext [contextID]->stVisual );
261
277
262
- if (fContext [contextID]->manager )
263
- hgl_destroy_st_manager (fContext [contextID]->manager );
264
-
265
278
FREE (fContext [contextID]);
266
279
}
267
280
268
281
269
282
status_t
270
- GalliumContext::SetCurrentContext (Bitmap *bitmap , context_id contextID)
283
+ GalliumContext::SetCurrentContext (bool set , context_id contextID)
271
284
{
272
285
CALLED ();
273
286
@@ -279,16 +292,17 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
279
292
Lock ();
280
293
context_id oldContextID = fCurrentContext ;
281
294
struct hgl_context * context = fContext [contextID];
282
- Unlock ();
283
295
284
296
if (!context) {
285
297
ERROR (" %s: Invalid context provided (#%" B_PRIu64 " )!\n " ,
286
298
__func__, contextID);
299
+ Unlock ();
287
300
return B_ERROR;
288
301
}
289
302
290
- if (!bitmap) {
291
- context->api ->make_current (context->api , NULL , NULL , NULL );
303
+ if (!set) {
304
+ fDisplay ->api ->make_current (fDisplay ->api , NULL , NULL , NULL );
305
+ Unlock ();
292
306
return B_OK;
293
307
}
294
308
@@ -297,24 +311,13 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
297
311
298
312
if (oldContextID > 0 && oldContextID != contextID) {
299
313
fContext [oldContextID]->st ->flush (fContext [oldContextID]->st ,
300
- ST_FLUSH_FRONT, NULL );
314
+ ST_FLUSH_FRONT, NULL , NULL , NULL );
301
315
}
302
316
303
317
// We need to lock and unlock framebuffers before accessing them
304
- context->api ->make_current (context->api , context->st , context->draw ->stfbi ,
305
- context->read ->stfbi );
306
-
307
- // if (context->textures[ST_ATTACHMENT_BACK_LEFT]
308
- // && context->textures[ST_ATTACHMENT_DEPTH_STENCIL]
309
- // && context->postProcess) {
310
- // TRACE("Postprocessing textures...\n");
311
- // pp_init_fbos(context->postProcess,
312
- // context->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
313
- // context->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
314
- // }
315
-
316
- context->bitmap = bitmap;
317
- // context->st->pipe->priv = context;
318
+ fDisplay ->api ->make_current (fDisplay ->api , context->st , context->buffer ->stfbi ,
319
+ context->buffer ->stfbi );
320
+ Unlock ();
318
321
319
322
return B_OK;
320
323
}
@@ -326,40 +329,62 @@ GalliumContext::SwapBuffers(context_id contextID)
326
329
CALLED ();
327
330
328
331
Lock ();
329
- struct hgl_context *context = fContext [contextID];
330
- Unlock ();
332
+ struct hgl_context * context = fContext [contextID];
331
333
332
334
if (!context) {
333
335
ERROR (" %s: context not found\n " , __func__);
336
+ Unlock ();
334
337
return B_ERROR;
335
338
}
336
- context->st ->flush (context->st , ST_FLUSH_FRONT, NULL );
337
339
338
- struct hgl_buffer * buffer = hgl_st_framebuffer (context->draw ->stfbi );
339
- pipe_surface* surface = buffer->surface ;
340
- if (!surface) {
341
- ERROR (" %s: Invalid drawable surface!\n " , __func__);
342
- return B_ERROR;
343
- }
340
+ // will flush front buffer if no double buffering is used
341
+ context->st ->flush (context->st , ST_FLUSH_FRONT, NULL , NULL , NULL );
344
342
345
- fScreen ->flush_frontbuffer (fScreen , context->st ->pipe , surface->texture , 0 , 0 ,
346
- context->bitmap , NULL );
343
+ struct hgl_buffer * buffer = context->buffer ;
347
344
345
+ // flush back buffer and swap buffers if double buffering is used
346
+ if (buffer->textures [ST_ATTACHMENT_BACK_LEFT] != NULL ) {
347
+ buffer->screen ->flush_frontbuffer (buffer->screen , NULL , buffer->textures [ST_ATTACHMENT_BACK_LEFT],
348
+ 0 , 0 , buffer->winsysContext , NULL );
349
+ std::swap (buffer->textures [ST_ATTACHMENT_FRONT_LEFT], buffer->textures [ST_ATTACHMENT_BACK_LEFT]);
350
+ p_atomic_inc (&buffer->stfbi ->stamp );
351
+ }
352
+
353
+ Unlock ();
348
354
return B_OK;
349
355
}
350
356
351
357
358
+ void
359
+ GalliumContext::Draw (context_id contextID, BRect updateRect)
360
+ {
361
+ struct hgl_context *context = fContext [contextID];
362
+
363
+ if (!context) {
364
+ ERROR (" %s: context not found\n " , __func__);
365
+ return ;
366
+ }
367
+
368
+ struct hgl_buffer * buffer = context->buffer ;
369
+
370
+ if (buffer->textures [ST_ATTACHMENT_FRONT_LEFT] == NULL )
371
+ return ;
372
+
373
+ buffer->screen ->flush_frontbuffer (buffer->screen , NULL , buffer->textures [ST_ATTACHMENT_FRONT_LEFT],
374
+ 0 , 0 , buffer->winsysContext , NULL );
375
+ }
376
+
377
+
352
378
bool
353
379
GalliumContext::Validate (uint32 width, uint32 height)
354
380
{
355
381
CALLED ();
356
382
357
- if (!fContext [fCurrentContext ]) {
383
+ if (!fContext [fCurrentContext ])
358
384
return false ;
359
- }
360
385
361
- if (fContext [fCurrentContext ]->width != width
362
- || fContext [fCurrentContext ]->height != height) {
386
+ if (fContext [fCurrentContext ]->width != width + 1
387
+ || fContext [fCurrentContext ]->height != height + 1 ) {
363
388
Invalidate (width, height);
364
389
return false ;
365
390
}
@@ -375,12 +400,11 @@ GalliumContext::Invalidate(uint32 width, uint32 height)
375
400
assert (fContext [fCurrentContext ]);
376
401
377
402
// Update st_context dimensions
378
- fContext [fCurrentContext ]->width = width;
379
- fContext [fCurrentContext ]->height = height;
403
+ fContext [fCurrentContext ]->width = width + 1 ;
404
+ fContext [fCurrentContext ]->height = height + 1 ;
380
405
381
406
// Is this the best way to invalidate?
382
- p_atomic_inc (&fContext [fCurrentContext ]->read ->stfbi ->stamp );
383
- p_atomic_inc (&fContext [fCurrentContext ]->draw ->stfbi ->stamp );
407
+ p_atomic_inc (&fContext [fCurrentContext ]->buffer ->stfbi ->stamp );
384
408
}
385
409
386
410
0 commit comments