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"
15 #include "bitmap_wrapper.h"
17 #include "glapi/glapi.h"
18 #include "main/context.h"
19 #include "main/framebuffer.h"
20 #include "main/renderbuffer.h"
21 #include "main/viewport.h"
22 #include "pipe/p_format.h"
23 #include "state_tracker/st_cb_fbo.h"
24 #include "state_tracker/st_cb_flush.h"
25 #include "state_tracker/st_context.h"
26 #include "state_tracker/st_gl_api.h"
27 #include "state_tracker/st_manager.h"
28 #include "state_tracker/sw_winsys.h"
29 #include "hgl_sw_winsys.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)
47 hgl_viewport(struct gl_context
* glContext
, GLint x
, GLint y
,
48 GLsizei width
, GLsizei height
)
50 TRACE("%s(glContext: %p, x: %d, y: %d, w: %d, h: %d\n", __func__
,
51 glContext
, x
, y
, width
, height
);
53 _mesa_check_init_viewport(glContext
, width
, height
);
55 struct gl_framebuffer
*draw
= glContext
->WinSysDrawBuffer
;
56 struct gl_framebuffer
*read
= glContext
->WinSysReadBuffer
;
59 _mesa_resize_framebuffer(glContext
, draw
, width
, height
);
61 _mesa_resize_framebuffer(glContext
, read
, width
, height
);
66 hgl_fill_st_visual(gl_config
* glVisual
)
68 struct st_visual
* stVisual
= CALLOC_STRUCT(st_visual
);
70 ERROR("%s: Couldn't allocate st_visual\n", __func__
);
74 // Determine color format
75 if (glVisual
->redBits
== 8) {
76 if (glVisual
->alphaBits
== 8)
77 stVisual
->color_format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
79 stVisual
->color_format
= PIPE_FORMAT_X8R8G8B8_UNORM
;
81 // TODO: I think this should be RGB vs BGR
82 stVisual
->color_format
= PIPE_FORMAT_B5G6R5_UNORM
;
85 // Determine depth stencil format
86 switch (glVisual
->depthBits
) {
89 stVisual
->depth_stencil_format
= PIPE_FORMAT_NONE
;
92 stVisual
->depth_stencil_format
= PIPE_FORMAT_Z16_UNORM
;
95 if (glVisual
->stencilBits
== 0) {
96 stVisual
->depth_stencil_format
= PIPE_FORMAT_X8Z24_UNORM
;
98 stVisual
->depth_stencil_format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
102 stVisual
->depth_stencil_format
= PIPE_FORMAT_Z32_UNORM
;
106 stVisual
->accum_format
= (glVisual
->haveAccumBuffer
)
107 ? PIPE_FORMAT_R16G16B16A16_SNORM
: PIPE_FORMAT_NONE
;
109 stVisual
->buffer_mask
|= ST_ATTACHMENT_FRONT_LEFT_MASK
;
110 stVisual
->render_buffer
= ST_ATTACHMENT_FRONT_LEFT
;
111 if (glVisual
->doubleBufferMode
) {
112 stVisual
->buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
113 stVisual
->render_buffer
= ST_ATTACHMENT_BACK_LEFT
;
116 if (glVisual
->stereoMode
) {
117 stVisual
->buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
118 if (glVisual
->doubleBufferMode
)
119 stVisual
->buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
122 if (glVisual
->haveDepthBuffer
|| glVisual
->haveStencilBuffer
)
123 stVisual
->buffer_mask
|= ST_ATTACHMENT_DEPTH_STENCIL_MASK
;
130 hook_stm_get_param(struct st_manager
*smapi
, enum st_manager_param param
)
135 case ST_MANAGER_BROKEN_INVALIDATE
:
136 TRACE("%s: TODO: How should we handle BROKEN_INVALIDATE calls?\n",
138 // For now we force validation of the framebuffer.
146 GalliumContext::GalliumContext(ulong options
)
154 // Make all contexts a known value
155 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
160 pipe_mutex_init(fMutex
);
164 GalliumContext::~GalliumContext()
168 // Destroy our contexts
170 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
174 pipe_mutex_destroy(fMutex
);
176 // TODO: Destroy fScreen
181 GalliumContext::CreateScreen()
185 // Allocate winsys and attach callback hooks
186 struct sw_winsys
* winsys
= hgl_create_sw_winsys();
189 ERROR("%s: Couldn't allocate sw_winsys!\n", __func__
);
193 fScreen
= sw_screen_create(winsys
);
195 if (fScreen
== NULL
) {
196 ERROR("%s: Couldn't create screen!\n", __FUNCTION__
);
201 debug_screen_wrap(fScreen
);
203 const char* driverName
= fScreen
->get_name(fScreen
);
204 ERROR("%s: Using %s driver.\n", __func__
, driverName
);
211 GalliumContext::CreateContext(Bitmap
*bitmap
)
215 struct hgl_context
* context
= CALLOC_STRUCT(hgl_context
);
218 ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__
);
222 // Set up the initial things our context needs
223 context
->bitmap
= bitmap
;
224 context
->colorSpace
= get_bitmap_color_space(bitmap
);
225 context
->draw
= NULL
;
226 context
->read
= NULL
;
229 context
->api
= st_gl_api_create();
231 ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__
);
235 context
->manager
= CALLOC_STRUCT(st_manager
);
236 if (!context
->manager
) {
237 ERROR("%s: Couldn't allocate Mesa state tracker manager!\n", __func__
);
240 context
->manager
->get_param
= hook_stm_get_param
;
242 // Calculate visual configuration
243 const GLboolean rgbFlag
= ((fOptions
& BGL_INDEX
) == 0);
244 const GLboolean alphaFlag
= ((fOptions
& BGL_ALPHA
) == BGL_ALPHA
);
245 const GLboolean dblFlag
= ((fOptions
& BGL_DOUBLE
) == BGL_DOUBLE
);
246 const GLboolean stereoFlag
= false;
247 const GLint depth
= (fOptions
& BGL_DEPTH
) ? 24 : 0;
248 const GLint stencil
= (fOptions
& BGL_STENCIL
) ? 8 : 0;
249 const GLint accum
= (fOptions
& BGL_ACCUM
) ? 16 : 0;
250 const GLint red
= rgbFlag
? 8 : 5;
251 const GLint green
= rgbFlag
? 8 : 5;
252 const GLint blue
= rgbFlag
? 8 : 5;
253 const GLint alpha
= alphaFlag
? 8 : 0;
255 TRACE("rgb :\t%d\n", (bool)rgbFlag
);
256 TRACE("alpha :\t%d\n", (bool)alphaFlag
);
257 TRACE("dbl :\t%d\n", (bool)dblFlag
);
258 TRACE("stereo :\t%d\n", (bool)stereoFlag
);
259 TRACE("depth :\t%d\n", depth
);
260 TRACE("stencil :\t%d\n", stencil
);
261 TRACE("accum :\t%d\n", accum
);
262 TRACE("red :\t%d\n", red
);
263 TRACE("green :\t%d\n", green
);
264 TRACE("blue :\t%d\n", blue
);
265 TRACE("alpha :\t%d\n", alpha
);
267 gl_config
* glVisual
= _mesa_create_visual(dblFlag
, stereoFlag
, red
, green
,
268 blue
, alpha
, depth
, stencil
, accum
, accum
, accum
, alpha
? accum
: 0, 1);
271 ERROR("%s: Couldn't create Mesa visual!\n", __func__
);
275 TRACE("depthBits :\t%d\n", glVisual
->depthBits
);
276 TRACE("stencilBits :\t%d\n", glVisual
->stencilBits
);
278 // Convert Mesa calculated visual into state tracker visual
279 context
->stVisual
= hgl_fill_st_visual(glVisual
);
281 context
->draw
= new GalliumFramebuffer(context
->stVisual
, (void*)this);
282 context
->read
= new GalliumFramebuffer(context
->stVisual
, (void*)this);
284 if (!context
->draw
|| !context
->read
) {
285 ERROR("%s: Problem allocating framebuffer!\n", __func__
);
286 _mesa_destroy_visual(glVisual
);
290 // We need to assign the screen *before* calling st_api create_context
291 context
->manager
->screen
= fScreen
;
293 // Build state tracker attributes
294 struct st_context_attribs attribs
;
295 memset(&attribs
, 0, sizeof(attribs
));
296 attribs
.options
.force_glsl_extensions_warn
= false;
297 attribs
.profile
= ST_PROFILE_DEFAULT
;
298 attribs
.visual
= *context
->stVisual
;
301 //attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
303 struct st_api
* api
= context
->api
;
305 // Create context using state tracker api call
306 enum st_context_error result
;
307 context
->st
= api
->create_context(api
, context
->manager
, &attribs
,
308 &result
, context
->st
);
311 ERROR("%s: Couldn't create mesa state tracker context!\n",
314 case ST_CONTEXT_SUCCESS
:
315 ERROR("%s: State tracker error: SUCCESS?\n", __func__
);
317 case ST_CONTEXT_ERROR_NO_MEMORY
:
318 ERROR("%s: State tracker error: NO_MEMORY\n", __func__
);
320 case ST_CONTEXT_ERROR_BAD_API
:
321 ERROR("%s: State tracker error: BAD_API\n", __func__
);
323 case ST_CONTEXT_ERROR_BAD_VERSION
:
324 ERROR("%s: State tracker error: BAD_VERSION\n", __func__
);
326 case ST_CONTEXT_ERROR_BAD_FLAG
:
327 ERROR("%s: State tracker error: BAD_FLAG\n", __func__
);
329 case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE
:
330 ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__
);
332 case ST_CONTEXT_ERROR_UNKNOWN_FLAG
:
333 ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__
);
341 assert(!context
->st
->st_manager_private
);
342 context
->st
->st_manager_private
= (void*)context
;
344 struct st_context
*stContext
= (struct st_context
*)context
->st
;
346 stContext
->ctx
->Driver
.Viewport
= hgl_viewport
;
348 // Init Gallium3D Post Processing
349 // TODO: no pp filters are enabled yet through postProcessEnable
350 context
->postProcess
= pp_init(stContext
->pipe
, context
->postProcessEnable
,
351 stContext
->cso_context
);
353 context_id contextNext
= -1;
355 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++) {
356 if (fContext
[i
] == NULL
) {
357 fContext
[i
] = context
;
364 if (contextNext
< 0) {
365 ERROR("%s: The next context is invalid... something went wrong!\n",
367 //st_destroy_context(context->st);
369 _mesa_destroy_visual(glVisual
);
373 TRACE("%s: context #%" B_PRIu64
" is the next available context\n",
374 __func__
, contextNext
);
381 GalliumContext::DestroyContext(context_id contextID
)
383 // fMutex should be locked *before* calling DestoryContext
385 // See if context is used
386 if (!fContext
[contextID
])
389 if (fContext
[contextID
]->st
) {
390 fContext
[contextID
]->st
->flush(fContext
[contextID
]->st
, 0, NULL
);
391 fContext
[contextID
]->st
->destroy(fContext
[contextID
]->st
);
394 if (fContext
[contextID
]->postProcess
)
395 pp_free(fContext
[contextID
]->postProcess
);
397 // Delete framebuffer objects
398 if (fContext
[contextID
]->read
)
399 delete fContext
[contextID
]->read
;
400 if (fContext
[contextID
]->draw
)
401 delete fContext
[contextID
]->draw
;
403 if (fContext
[contextID
]->stVisual
)
404 FREE(fContext
[contextID
]->stVisual
);
406 if (fContext
[contextID
]->manager
)
407 FREE(fContext
[contextID
]->manager
);
409 FREE(fContext
[contextID
]);
414 GalliumContext::SetCurrentContext(Bitmap
*bitmap
, context_id contextID
)
418 if (contextID
< 0 || contextID
> CONTEXT_MAX
) {
419 ERROR("%s: Invalid context ID range!\n", __func__
);
424 context_id oldContextID
= fCurrentContext
;
425 struct hgl_context
* context
= fContext
[contextID
];
429 ERROR("%s: Invalid context provided (#%" B_PRIu64
")!\n",
430 __func__
, contextID
);
434 struct st_api
* api
= context
->api
;
437 api
->make_current(context
->api
, NULL
, NULL
, NULL
);
441 // Everything seems valid, lets set the new context.
442 fCurrentContext
= contextID
;
444 if (oldContextID
> 0 && oldContextID
!= contextID
) {
445 fContext
[oldContextID
]->st
->flush(fContext
[oldContextID
]->st
,
446 ST_FLUSH_FRONT
, NULL
);
449 // We need to lock and unlock framebuffers before accessing them
450 context
->draw
->Lock();
451 context
->read
->Lock();
452 api
->make_current(context
->api
, context
->st
, context
->draw
->fBuffer
,
453 context
->read
->fBuffer
);
454 context
->draw
->Unlock();
455 context
->read
->Unlock();
457 if (context
->textures
[ST_ATTACHMENT_BACK_LEFT
]
458 && context
->textures
[ST_ATTACHMENT_DEPTH_STENCIL
]
459 && context
->postProcess
) {
460 TRACE("Postprocessing textures...\n");
461 pp_init_fbos(context
->postProcess
,
462 context
->textures
[ST_ATTACHMENT_BACK_LEFT
]->width0
,
463 context
->textures
[ST_ATTACHMENT_BACK_LEFT
]->height0
);
466 context
->bitmap
= bitmap
;
467 //context->st->pipe->priv = context;
474 GalliumContext::SwapBuffers(context_id contextID
)
479 struct hgl_context
*context
= fContext
[contextID
];
483 ERROR("%s: context not found\n", __func__
);
487 // TODO: Where did st_notify_swapbuffers go?
488 //st_notify_swapbuffers(context->draw->stfb);
490 context
->st
->flush(context
->st
, ST_FLUSH_FRONT
, NULL
);
492 struct st_context
*stContext
= (struct st_context
*)context
->st
;
494 unsigned nColorBuffers
= stContext
->state
.framebuffer
.nr_cbufs
;
495 for (unsigned i
= 0; i
< nColorBuffers
; i
++) {
496 pipe_surface
* surface
= stContext
->state
.framebuffer
.cbufs
[i
];
498 ERROR("%s: Color buffer %d invalid!\n", __func__
, i
);
502 TRACE("%s: Flushing color buffer #%d\n", __func__
, i
);
504 // We pass our destination bitmap to flush_fronbuffer which passes it
505 // to the private winsys display call.
506 fScreen
->flush_frontbuffer(fScreen
, surface
->texture
, 0, 0,
507 context
->bitmap
, NULL
);
511 // TODO... should we flush the z stencil buffer?
512 pipe_surface
* zSurface
= stContext
->state
.framebuffer
.zsbuf
;
513 fScreen
->flush_frontbuffer(fScreen
, zSurface
->texture
, 0, 0,
514 context
->bitmap
, NULL
);
522 GalliumContext::ResizeViewport(int32 width
, int32 height
)
525 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++) {
526 if (fContext
[i
] && fContext
[i
]->st
) {
527 struct st_context
*stContext
= (struct st_context
*)fContext
[i
]->st
;
528 _mesa_set_viewport(stContext
->ctx
, 0, 0, width
, height
);
529 st_manager_validate_framebuffers(stContext
);
536 GalliumContext::Lock()
539 pipe_mutex_lock(fMutex
);
544 GalliumContext::Unlock()
547 pipe_mutex_unlock(fMutex
);
549 /* vim: set tabstop=4: */