2 * Copyright 2012, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Artur Wyszynski, harakash@gmail.com
7 * Alexander von Gluck IV, kallisti5@unixzen.com
11 #include "GalliumContext.h"
17 #include "bitmap_wrapper.h"
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/st_manager.h"
26 #include "state_tracker/sw_winsys.h"
27 #include "sw/hgl/hgl_sw_winsys.h"
28 #include "util/u_atomic.h"
29 #include "util/u_memory.h"
31 #include "target-helpers/inline_sw_helper.h"
32 #include "target-helpers/inline_debug_helper.h"
37 # define TRACE(x...) printf("GalliumContext: " x)
38 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
43 #define ERROR(x...) printf("GalliumContext: " x)
46 GalliumContext::GalliumContext(ulong options
)
54 // Make all contexts a known value
55 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
60 pipe_mutex_init(fMutex
);
64 GalliumContext::~GalliumContext()
68 // Destroy our contexts
70 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
74 pipe_mutex_destroy(fMutex
);
76 // TODO: Destroy fScreen
81 GalliumContext::CreateScreen()
85 // Allocate winsys and attach callback hooks
86 struct sw_winsys
* winsys
= hgl_create_sw_winsys();
89 ERROR("%s: Couldn't allocate sw_winsys!\n", __func__
);
93 fScreen
= sw_screen_create(winsys
);
95 if (fScreen
== NULL
) {
96 ERROR("%s: Couldn't create screen!\n", __FUNCTION__
);
101 debug_screen_wrap(fScreen
);
103 const char* driverName
= fScreen
->get_name(fScreen
);
104 ERROR("%s: Using %s driver.\n", __func__
, driverName
);
111 GalliumContext::CreateContext(Bitmap
*bitmap
)
115 struct hgl_context
* context
= CALLOC_STRUCT(hgl_context
);
118 ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__
);
122 // Set up the initial things our context needs
123 context
->bitmap
= bitmap
;
124 context
->colorSpace
= get_bitmap_color_space(bitmap
);
125 context
->screen
= fScreen
;
126 context
->draw
= NULL
;
127 context
->read
= NULL
;
130 context
->api
= st_gl_api_create();
132 ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__
);
136 // Create state_tracker manager
137 context
->manager
= hgl_create_st_manager(context
);
139 // Create state tracker visual
140 context
->stVisual
= hgl_create_st_visual(fOptions
);
142 // Create state tracker framebuffers
143 context
->draw
= hgl_create_st_framebuffer(context
);
144 context
->read
= hgl_create_st_framebuffer(context
);
146 if (!context
->draw
|| !context
->read
) {
147 ERROR("%s: Problem allocating framebuffer!\n", __func__
);
148 FREE(context
->stVisual
);
152 // Build state tracker attributes
153 struct st_context_attribs attribs
;
154 memset(&attribs
, 0, sizeof(attribs
));
155 attribs
.options
.force_glsl_extensions_warn
= false;
156 attribs
.profile
= ST_PROFILE_DEFAULT
;
157 attribs
.visual
= *context
->stVisual
;
160 //attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
162 struct st_api
* api
= context
->api
;
164 // Create context using state tracker api call
165 enum st_context_error result
;
166 context
->st
= api
->create_context(api
, context
->manager
, &attribs
,
167 &result
, context
->st
);
170 ERROR("%s: Couldn't create mesa state tracker context!\n",
173 case ST_CONTEXT_SUCCESS
:
174 ERROR("%s: State tracker error: SUCCESS?\n", __func__
);
176 case ST_CONTEXT_ERROR_NO_MEMORY
:
177 ERROR("%s: State tracker error: NO_MEMORY\n", __func__
);
179 case ST_CONTEXT_ERROR_BAD_API
:
180 ERROR("%s: State tracker error: BAD_API\n", __func__
);
182 case ST_CONTEXT_ERROR_BAD_VERSION
:
183 ERROR("%s: State tracker error: BAD_VERSION\n", __func__
);
185 case ST_CONTEXT_ERROR_BAD_FLAG
:
186 ERROR("%s: State tracker error: BAD_FLAG\n", __func__
);
188 case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE
:
189 ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__
);
191 case ST_CONTEXT_ERROR_UNKNOWN_FLAG
:
192 ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__
);
196 hgl_destroy_st_visual(context
->stVisual
);
201 assert(!context
->st
->st_manager_private
);
202 context
->st
->st_manager_private
= (void*)context
;
204 struct st_context
*stContext
= (struct st_context
*)context
->st
;
206 // Init Gallium3D Post Processing
207 // TODO: no pp filters are enabled yet through postProcessEnable
208 context
->postProcess
= pp_init(stContext
->pipe
, context
->postProcessEnable
,
209 stContext
->cso_context
);
211 context_id contextNext
= -1;
213 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++) {
214 if (fContext
[i
] == NULL
) {
215 fContext
[i
] = context
;
222 if (contextNext
< 0) {
223 ERROR("%s: The next context is invalid... something went wrong!\n",
225 //st_destroy_context(context->st);
226 FREE(context
->stVisual
);
231 TRACE("%s: context #%" B_PRIu64
" is the next available context\n",
232 __func__
, contextNext
);
239 GalliumContext::DestroyContext(context_id contextID
)
241 // fMutex should be locked *before* calling DestoryContext
243 // See if context is used
244 if (!fContext
[contextID
])
247 if (fContext
[contextID
]->st
) {
248 fContext
[contextID
]->st
->flush(fContext
[contextID
]->st
, 0, NULL
);
249 fContext
[contextID
]->st
->destroy(fContext
[contextID
]->st
);
252 if (fContext
[contextID
]->postProcess
)
253 pp_free(fContext
[contextID
]->postProcess
);
255 // Delete state tracker framebuffer objects
256 if (fContext
[contextID
]->read
)
257 delete fContext
[contextID
]->read
;
258 if (fContext
[contextID
]->draw
)
259 delete fContext
[contextID
]->draw
;
261 if (fContext
[contextID
]->stVisual
)
262 hgl_destroy_st_visual(fContext
[contextID
]->stVisual
);
264 if (fContext
[contextID
]->manager
)
265 hgl_destroy_st_manager(fContext
[contextID
]->manager
);
267 FREE(fContext
[contextID
]);
272 GalliumContext::SetCurrentContext(Bitmap
*bitmap
, context_id contextID
)
276 if (contextID
< 0 || contextID
> CONTEXT_MAX
) {
277 ERROR("%s: Invalid context ID range!\n", __func__
);
282 context_id oldContextID
= fCurrentContext
;
283 struct hgl_context
* context
= fContext
[contextID
];
287 ERROR("%s: Invalid context provided (#%" B_PRIu64
")!\n",
288 __func__
, contextID
);
292 struct st_api
* api
= context
->api
;
295 api
->make_current(context
->api
, NULL
, NULL
, NULL
);
299 // Everything seems valid, lets set the new context.
300 fCurrentContext
= contextID
;
302 if (oldContextID
> 0 && oldContextID
!= contextID
) {
303 fContext
[oldContextID
]->st
->flush(fContext
[oldContextID
]->st
,
304 ST_FLUSH_FRONT
, NULL
);
307 // We need to lock and unlock framebuffers before accessing them
308 api
->make_current(context
->api
, context
->st
, context
->draw
->stfbi
,
309 context
->read
->stfbi
);
311 //if (context->textures[ST_ATTACHMENT_BACK_LEFT]
312 // && context->textures[ST_ATTACHMENT_DEPTH_STENCIL]
313 // && context->postProcess) {
314 // TRACE("Postprocessing textures...\n");
315 // pp_init_fbos(context->postProcess,
316 // context->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
317 // context->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
320 context
->bitmap
= bitmap
;
321 //context->st->pipe->priv = context;
328 GalliumContext::SwapBuffers(context_id contextID
)
333 struct hgl_context
*context
= fContext
[contextID
];
337 ERROR("%s: context not found\n", __func__
);
341 // TODO: Where did st_notify_swapbuffers go?
342 //st_notify_swapbuffers(context->draw->stfbi);
344 context
->st
->flush(context
->st
, ST_FLUSH_FRONT
, NULL
);
346 struct st_context
*stContext
= (struct st_context
*)context
->st
;
348 unsigned nColorBuffers
= stContext
->state
.framebuffer
.nr_cbufs
;
349 for (unsigned i
= 0; i
< nColorBuffers
; i
++) {
350 pipe_surface
* surface
= stContext
->state
.framebuffer
.cbufs
[i
];
352 ERROR("%s: Color buffer %d invalid!\n", __func__
, i
);
356 TRACE("%s: Flushing color buffer #%d\n", __func__
, i
);
358 // We pass our destination bitmap to flush_fronbuffer which passes it
359 // to the private winsys display call.
360 fScreen
->flush_frontbuffer(fScreen
, surface
->texture
, 0, 0,
361 context
->bitmap
, NULL
);
365 // TODO... should we flush the z stencil buffer?
366 pipe_surface
* zSurface
= stContext
->state
.framebuffer
.zsbuf
;
367 fScreen
->flush_frontbuffer(fScreen
, zSurface
->texture
, 0, 0,
368 context
->bitmap
, NULL
);
376 GalliumContext::Validate(uint32 width
, uint32 height
)
380 if (!fContext
[fCurrentContext
]) {
384 if (fContext
[fCurrentContext
]->width
!= width
385 || fContext
[fCurrentContext
]->height
!= height
) {
386 Invalidate(width
, height
);
394 GalliumContext::Invalidate(uint32 width
, uint32 height
)
398 assert(fContext
[fCurrentContext
]);
400 // Update st_context dimensions
401 fContext
[fCurrentContext
]->width
= width
;
402 fContext
[fCurrentContext
]->height
= height
;
404 // Is this the best way to invalidate?
405 p_atomic_inc(&fContext
[fCurrentContext
]->read
->stfbi
->stamp
);
406 p_atomic_inc(&fContext
[fCurrentContext
]->draw
->stfbi
->stamp
);
411 GalliumContext::Lock()
414 pipe_mutex_lock(fMutex
);
419 GalliumContext::Unlock()
422 pipe_mutex_unlock(fMutex
);
424 /* vim: set tabstop=4: */