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 "util/u_memory.h"
30 #include "hgl_sw_winsys.h"
32 #include "target-helpers/inline_sw_helper.h"
33 #include "target-helpers/inline_debug_helper.h"
38 # define TRACE(x...) printf("GalliumContext: " x)
39 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
44 #define ERROR(x...) printf("GalliumContext: " x)
48 hgl_viewport(struct gl_context
* glContext
)
50 // TODO: We should try to eliminate this function
52 GLint x
= glContext
->ViewportArray
[0].X
;
53 GLint y
= glContext
->ViewportArray
[0].Y
;
54 GLint width
= glContext
->ViewportArray
[0].Width
;
55 GLint height
= glContext
->ViewportArray
[0].Height
;
57 TRACE("%s(glContext: %p, x: %d, y: %d, w: %d, h: %d\n", __func__
,
58 glContext
, x
, y
, width
, height
);
60 _mesa_check_init_viewport(glContext
, width
, height
);
62 struct gl_framebuffer
*draw
= glContext
->WinSysDrawBuffer
;
63 struct gl_framebuffer
*read
= glContext
->WinSysReadBuffer
;
66 _mesa_resize_framebuffer(glContext
, draw
, width
, height
);
68 _mesa_resize_framebuffer(glContext
, read
, width
, height
);
73 hook_stm_get_param(struct st_manager
*smapi
, enum st_manager_param param
)
78 case ST_MANAGER_BROKEN_INVALIDATE
:
79 TRACE("%s: TODO: How should we handle BROKEN_INVALIDATE calls?\n",
81 // For now we force validation of the framebuffer.
89 GalliumContext::GalliumContext(ulong options
)
97 // Make all contexts a known value
98 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
103 pipe_mutex_init(fMutex
);
107 GalliumContext::~GalliumContext()
111 // Destroy our contexts
113 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++)
117 pipe_mutex_destroy(fMutex
);
119 // TODO: Destroy fScreen
124 GalliumContext::CreateVisual()
126 struct st_visual
* visual
= CALLOC_STRUCT(st_visual
);
128 ERROR("%s: Couldn't allocate st_visual\n", __func__
);
132 // Calculate visual configuration
133 const GLboolean rgbFlag
= ((fOptions
& BGL_INDEX
) == 0);
134 const GLboolean alphaFlag
= ((fOptions
& BGL_ALPHA
) == BGL_ALPHA
);
135 const GLboolean dblFlag
= ((fOptions
& BGL_DOUBLE
) == BGL_DOUBLE
);
136 const GLboolean stereoFlag
= false;
137 const GLint depth
= (fOptions
& BGL_DEPTH
) ? 24 : 0;
138 const GLint stencil
= (fOptions
& BGL_STENCIL
) ? 8 : 0;
139 const GLint accum
= (fOptions
& BGL_ACCUM
) ? 16 : 0;
140 const GLint red
= rgbFlag
? 8 : 5;
141 const GLint green
= rgbFlag
? 8 : 5;
142 const GLint blue
= rgbFlag
? 8 : 5;
143 const GLint alpha
= alphaFlag
? 8 : 0;
145 TRACE("rgb :\t%d\n", (bool)rgbFlag
);
146 TRACE("alpha :\t%d\n", (bool)alphaFlag
);
147 TRACE("dbl :\t%d\n", (bool)dblFlag
);
148 TRACE("stereo :\t%d\n", (bool)stereoFlag
);
149 TRACE("depth :\t%d\n", depth
);
150 TRACE("stencil :\t%d\n", stencil
);
151 TRACE("accum :\t%d\n", accum
);
152 TRACE("red :\t%d\n", red
);
153 TRACE("green :\t%d\n", green
);
154 TRACE("blue :\t%d\n", blue
);
155 TRACE("alpha :\t%d\n", alpha
);
157 // Determine color format
160 visual
->color_format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
162 visual
->color_format
= PIPE_FORMAT_X8R8G8B8_UNORM
;
164 // TODO: I think this should be RGB vs BGR
165 visual
->color_format
= PIPE_FORMAT_B5G6R5_UNORM
;
168 // Determine depth stencil format
172 visual
->depth_stencil_format
= PIPE_FORMAT_NONE
;
175 visual
->depth_stencil_format
= PIPE_FORMAT_Z16_UNORM
;
178 if ((fOptions
& BGL_STENCIL
) != 0)
179 visual
->depth_stencil_format
= PIPE_FORMAT_S8_UINT_Z24_UNORM
;
181 visual
->depth_stencil_format
= PIPE_FORMAT_X8Z24_UNORM
;
184 visual
->depth_stencil_format
= PIPE_FORMAT_Z32_UNORM
;
188 visual
->accum_format
= (fOptions
& BGL_ACCUM
)
189 ? PIPE_FORMAT_R16G16B16A16_SNORM
: PIPE_FORMAT_NONE
;
191 visual
->buffer_mask
|= ST_ATTACHMENT_FRONT_LEFT_MASK
;
192 visual
->render_buffer
= ST_ATTACHMENT_FRONT_LEFT
;
195 visual
->buffer_mask
|= ST_ATTACHMENT_BACK_LEFT_MASK
;
196 visual
->render_buffer
= ST_ATTACHMENT_BACK_LEFT
;
200 visual
->buffer_mask
|= ST_ATTACHMENT_FRONT_RIGHT_MASK
;
202 visual
->buffer_mask
|= ST_ATTACHMENT_BACK_RIGHT_MASK
;
205 if ((fOptions
& BGL_DEPTH
) || (fOptions
& BGL_STENCIL
))
206 visual
->buffer_mask
|= ST_ATTACHMENT_DEPTH_STENCIL_MASK
;
213 GalliumContext::CreateScreen()
217 // Allocate winsys and attach callback hooks
218 struct sw_winsys
* winsys
= hgl_create_sw_winsys();
221 ERROR("%s: Couldn't allocate sw_winsys!\n", __func__
);
225 fScreen
= sw_screen_create(winsys
);
227 if (fScreen
== NULL
) {
228 ERROR("%s: Couldn't create screen!\n", __FUNCTION__
);
233 debug_screen_wrap(fScreen
);
235 const char* driverName
= fScreen
->get_name(fScreen
);
236 ERROR("%s: Using %s driver.\n", __func__
, driverName
);
243 GalliumContext::CreateContext(Bitmap
*bitmap
)
247 struct hgl_context
* context
= CALLOC_STRUCT(hgl_context
);
250 ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__
);
254 // Set up the initial things our context needs
255 context
->bitmap
= bitmap
;
256 context
->colorSpace
= get_bitmap_color_space(bitmap
);
257 context
->draw
= NULL
;
258 context
->read
= NULL
;
261 context
->api
= st_gl_api_create();
263 ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__
);
267 context
->manager
= CALLOC_STRUCT(st_manager
);
268 if (!context
->manager
) {
269 ERROR("%s: Couldn't allocate Mesa state tracker manager!\n", __func__
);
272 context
->manager
->get_param
= hook_stm_get_param
;
274 // Create state tracker visual
275 context
->stVisual
= CreateVisual();
276 if (context
->stVisual
== NULL
) {
277 ERROR("%s: Couldn't create state_tracker visual!\n", __func__
);
281 context
->draw
= hgl_create_st_framebuffer(context
);
282 context
->read
= hgl_create_st_framebuffer(context
);
284 if (!context
->draw
|| !context
->read
) {
285 ERROR("%s: Problem allocating framebuffer!\n", __func__
);
286 FREE(context
->stVisual
);
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__
);
337 FREE(context
->stVisual
);
342 assert(!context
->st
->st_manager_private
);
343 context
->st
->st_manager_private
= (void*)context
;
345 struct st_context
*stContext
= (struct st_context
*)context
->st
;
347 stContext
->ctx
->Driver
.Viewport
= hgl_viewport
;
349 // Init Gallium3D Post Processing
350 // TODO: no pp filters are enabled yet through postProcessEnable
351 context
->postProcess
= pp_init(stContext
->pipe
, context
->postProcessEnable
,
352 stContext
->cso_context
);
354 context_id contextNext
= -1;
356 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++) {
357 if (fContext
[i
] == NULL
) {
358 fContext
[i
] = context
;
365 if (contextNext
< 0) {
366 ERROR("%s: The next context is invalid... something went wrong!\n",
368 //st_destroy_context(context->st);
369 FREE(context
->stVisual
);
374 TRACE("%s: context #%" B_PRIu64
" is the next available context\n",
375 __func__
, contextNext
);
382 GalliumContext::DestroyContext(context_id contextID
)
384 // fMutex should be locked *before* calling DestoryContext
386 // See if context is used
387 if (!fContext
[contextID
])
390 if (fContext
[contextID
]->st
) {
391 fContext
[contextID
]->st
->flush(fContext
[contextID
]->st
, 0, NULL
);
392 fContext
[contextID
]->st
->destroy(fContext
[contextID
]->st
);
395 if (fContext
[contextID
]->postProcess
)
396 pp_free(fContext
[contextID
]->postProcess
);
398 // Delete framebuffer objects
399 if (fContext
[contextID
]->read
)
400 delete fContext
[contextID
]->read
;
401 if (fContext
[contextID
]->draw
)
402 delete fContext
[contextID
]->draw
;
404 if (fContext
[contextID
]->stVisual
)
405 FREE(fContext
[contextID
]->stVisual
);
407 if (fContext
[contextID
]->manager
)
408 FREE(fContext
[contextID
]->manager
);
410 FREE(fContext
[contextID
]);
415 GalliumContext::SetCurrentContext(Bitmap
*bitmap
, context_id contextID
)
419 if (contextID
< 0 || contextID
> CONTEXT_MAX
) {
420 ERROR("%s: Invalid context ID range!\n", __func__
);
425 context_id oldContextID
= fCurrentContext
;
426 struct hgl_context
* context
= fContext
[contextID
];
430 ERROR("%s: Invalid context provided (#%" B_PRIu64
")!\n",
431 __func__
, contextID
);
435 struct st_api
* api
= context
->api
;
438 api
->make_current(context
->api
, NULL
, NULL
, NULL
);
442 // Everything seems valid, lets set the new context.
443 fCurrentContext
= contextID
;
445 if (oldContextID
> 0 && oldContextID
!= contextID
) {
446 fContext
[oldContextID
]->st
->flush(fContext
[oldContextID
]->st
,
447 ST_FLUSH_FRONT
, NULL
);
450 // We need to lock and unlock framebuffers before accessing them
451 api
->make_current(context
->api
, context
->st
, context
->draw
->stfbi
,
452 context
->read
->stfbi
);
454 if (context
->textures
[ST_ATTACHMENT_BACK_LEFT
]
455 && context
->textures
[ST_ATTACHMENT_DEPTH_STENCIL
]
456 && context
->postProcess
) {
457 TRACE("Postprocessing textures...\n");
458 pp_init_fbos(context
->postProcess
,
459 context
->textures
[ST_ATTACHMENT_BACK_LEFT
]->width0
,
460 context
->textures
[ST_ATTACHMENT_BACK_LEFT
]->height0
);
463 context
->bitmap
= bitmap
;
464 //context->st->pipe->priv = context;
471 GalliumContext::SwapBuffers(context_id contextID
)
476 struct hgl_context
*context
= fContext
[contextID
];
480 ERROR("%s: context not found\n", __func__
);
484 // TODO: Where did st_notify_swapbuffers go?
485 //st_notify_swapbuffers(context->draw->stfbi);
487 context
->st
->flush(context
->st
, ST_FLUSH_FRONT
, NULL
);
489 struct st_context
*stContext
= (struct st_context
*)context
->st
;
491 unsigned nColorBuffers
= stContext
->state
.framebuffer
.nr_cbufs
;
492 for (unsigned i
= 0; i
< nColorBuffers
; i
++) {
493 pipe_surface
* surface
= stContext
->state
.framebuffer
.cbufs
[i
];
495 ERROR("%s: Color buffer %d invalid!\n", __func__
, i
);
499 TRACE("%s: Flushing color buffer #%d\n", __func__
, i
);
501 // We pass our destination bitmap to flush_fronbuffer which passes it
502 // to the private winsys display call.
503 fScreen
->flush_frontbuffer(fScreen
, surface
->texture
, 0, 0,
504 context
->bitmap
, NULL
);
508 // TODO... should we flush the z stencil buffer?
509 pipe_surface
* zSurface
= stContext
->state
.framebuffer
.zsbuf
;
510 fScreen
->flush_frontbuffer(fScreen
, zSurface
->texture
, 0, 0,
511 context
->bitmap
, NULL
);
519 GalliumContext::ResizeViewport(int32 width
, int32 height
)
522 for (context_id i
= 0; i
< CONTEXT_MAX
; i
++) {
523 if (fContext
[i
] && fContext
[i
]->st
) {
524 struct st_context
*stContext
= (struct st_context
*)fContext
[i
]->st
;
525 _mesa_set_viewport(stContext
->ctx
, 0, 0, 0, width
, height
);
526 st_manager_validate_framebuffers(stContext
);
533 GalliumContext::Lock()
536 pipe_mutex_lock(fMutex
);
541 GalliumContext::Unlock()
544 pipe_mutex_unlock(fMutex
);
546 /* vim: set tabstop=4: */