1848b8605Smrg/* 2848b8605Smrg * Copyright 2012, Haiku, Inc. All Rights Reserved. 3848b8605Smrg * Distributed under the terms of the MIT License. 4848b8605Smrg * 5848b8605Smrg * Authors: 6848b8605Smrg * Artur Wyszynski, harakash@gmail.com 7848b8605Smrg * Alexander von Gluck IV, kallisti5@unixzen.com 8848b8605Smrg */ 9848b8605Smrg 10848b8605Smrg 11848b8605Smrg#include "GalliumContext.h" 12848b8605Smrg 13b8e80941Smrg#include <stdio.h> 14b8e80941Smrg 15848b8605Smrg#include "GLView.h" 16848b8605Smrg 17848b8605Smrg#include "bitmap_wrapper.h" 18b8e80941Smrg 19848b8605Smrg#include "glapi/glapi.h" 20848b8605Smrg#include "pipe/p_format.h" 21b8e80941Smrg//#include "state_tracker/st_cb_fbo.h" 22b8e80941Smrg//#include "state_tracker/st_cb_flush.h" 23848b8605Smrg#include "state_tracker/st_context.h" 24848b8605Smrg#include "state_tracker/st_gl_api.h" 25848b8605Smrg#include "state_tracker/sw_winsys.h" 26b8e80941Smrg#include "sw/hgl/hgl_sw_winsys.h" 27b8e80941Smrg#include "util/u_atomic.h" 28848b8605Smrg#include "util/u_memory.h" 29848b8605Smrg 30848b8605Smrg#include "target-helpers/inline_sw_helper.h" 31848b8605Smrg#include "target-helpers/inline_debug_helper.h" 32848b8605Smrg 33848b8605Smrg 34848b8605Smrg#ifdef DEBUG 35848b8605Smrg# define TRACE(x...) printf("GalliumContext: " x) 36848b8605Smrg# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) 37848b8605Smrg#else 38848b8605Smrg# define TRACE(x...) 39848b8605Smrg# define CALLED() 40848b8605Smrg#endif 41848b8605Smrg#define ERROR(x...) printf("GalliumContext: " x) 42848b8605Smrg 43848b8605Smrg 44848b8605SmrgGalliumContext::GalliumContext(ulong options) 45848b8605Smrg : 46848b8605Smrg fOptions(options), 47848b8605Smrg fScreen(NULL), 48848b8605Smrg fCurrentContext(0) 49848b8605Smrg{ 50848b8605Smrg CALLED(); 51848b8605Smrg 52848b8605Smrg // Make all contexts a known value 53848b8605Smrg for (context_id i = 0; i < CONTEXT_MAX; i++) 54848b8605Smrg fContext[i] = NULL; 55848b8605Smrg 56848b8605Smrg CreateScreen(); 57848b8605Smrg 58b8e80941Smrg (void) mtx_init(&fMutex, mtx_plain); 59848b8605Smrg} 60848b8605Smrg 61848b8605Smrg 62848b8605SmrgGalliumContext::~GalliumContext() 63848b8605Smrg{ 64848b8605Smrg CALLED(); 65848b8605Smrg 66848b8605Smrg // Destroy our contexts 67848b8605Smrg Lock(); 68848b8605Smrg for (context_id i = 0; i < CONTEXT_MAX; i++) 69848b8605Smrg DestroyContext(i); 70848b8605Smrg Unlock(); 71848b8605Smrg 72b8e80941Smrg mtx_destroy(&fMutex); 73848b8605Smrg 74848b8605Smrg // TODO: Destroy fScreen 75848b8605Smrg} 76848b8605Smrg 77848b8605Smrg 78848b8605Smrgstatus_t 79848b8605SmrgGalliumContext::CreateScreen() 80848b8605Smrg{ 81848b8605Smrg CALLED(); 82848b8605Smrg 83848b8605Smrg // Allocate winsys and attach callback hooks 84848b8605Smrg struct sw_winsys* winsys = hgl_create_sw_winsys(); 85848b8605Smrg 86848b8605Smrg if (!winsys) { 87848b8605Smrg ERROR("%s: Couldn't allocate sw_winsys!\n", __func__); 88848b8605Smrg return B_ERROR; 89848b8605Smrg } 90848b8605Smrg 91848b8605Smrg fScreen = sw_screen_create(winsys); 92848b8605Smrg 93848b8605Smrg if (fScreen == NULL) { 94848b8605Smrg ERROR("%s: Couldn't create screen!\n", __FUNCTION__); 95848b8605Smrg FREE(winsys); 96848b8605Smrg return B_ERROR; 97848b8605Smrg } 98848b8605Smrg 99848b8605Smrg debug_screen_wrap(fScreen); 100848b8605Smrg 101848b8605Smrg const char* driverName = fScreen->get_name(fScreen); 102848b8605Smrg ERROR("%s: Using %s driver.\n", __func__, driverName); 103848b8605Smrg 104848b8605Smrg return B_OK; 105848b8605Smrg} 106848b8605Smrg 107848b8605Smrg 108848b8605Smrgcontext_id 109848b8605SmrgGalliumContext::CreateContext(Bitmap *bitmap) 110848b8605Smrg{ 111848b8605Smrg CALLED(); 112848b8605Smrg 113848b8605Smrg struct hgl_context* context = CALLOC_STRUCT(hgl_context); 114848b8605Smrg 115848b8605Smrg if (!context) { 116848b8605Smrg ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__); 117848b8605Smrg return 0; 118848b8605Smrg } 119848b8605Smrg 120848b8605Smrg // Set up the initial things our context needs 121848b8605Smrg context->bitmap = bitmap; 122848b8605Smrg context->colorSpace = get_bitmap_color_space(bitmap); 123b8e80941Smrg context->screen = fScreen; 124848b8605Smrg context->draw = NULL; 125848b8605Smrg context->read = NULL; 126848b8605Smrg context->st = NULL; 127848b8605Smrg 128b8e80941Smrg // Create st_gl_api 129b8e80941Smrg context->api = hgl_create_st_api(); 130848b8605Smrg if (!context->api) { 131848b8605Smrg ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__); 132848b8605Smrg return -1; 133848b8605Smrg } 134848b8605Smrg 135b8e80941Smrg // Create state_tracker manager 136b8e80941Smrg context->manager = hgl_create_st_manager(context); 137848b8605Smrg 138b8e80941Smrg // Create state tracker visual 139b8e80941Smrg context->stVisual = hgl_create_st_visual(fOptions); 140848b8605Smrg 141b8e80941Smrg // Create state tracker framebuffers 142b8e80941Smrg context->draw = hgl_create_st_framebuffer(context); 143b8e80941Smrg context->read = hgl_create_st_framebuffer(context); 144848b8605Smrg 145848b8605Smrg if (!context->draw || !context->read) { 146848b8605Smrg ERROR("%s: Problem allocating framebuffer!\n", __func__); 147b8e80941Smrg FREE(context->stVisual); 148848b8605Smrg return -1; 149848b8605Smrg } 150848b8605Smrg 151848b8605Smrg // Build state tracker attributes 152848b8605Smrg struct st_context_attribs attribs; 153848b8605Smrg memset(&attribs, 0, sizeof(attribs)); 154848b8605Smrg attribs.options.force_glsl_extensions_warn = false; 155848b8605Smrg attribs.profile = ST_PROFILE_DEFAULT; 156848b8605Smrg attribs.visual = *context->stVisual; 157848b8605Smrg attribs.major = 1; 158848b8605Smrg attribs.minor = 0; 159848b8605Smrg //attribs.flags |= ST_CONTEXT_FLAG_DEBUG; 160848b8605Smrg 161848b8605Smrg // Create context using state tracker api call 162848b8605Smrg enum st_context_error result; 163b8e80941Smrg context->st = context->api->create_context(context->api, context->manager, 164b8e80941Smrg &attribs, &result, context->st); 165848b8605Smrg 166848b8605Smrg if (!context->st) { 167848b8605Smrg ERROR("%s: Couldn't create mesa state tracker context!\n", 168848b8605Smrg __func__); 169848b8605Smrg switch (result) { 170848b8605Smrg case ST_CONTEXT_SUCCESS: 171848b8605Smrg ERROR("%s: State tracker error: SUCCESS?\n", __func__); 172848b8605Smrg break; 173848b8605Smrg case ST_CONTEXT_ERROR_NO_MEMORY: 174848b8605Smrg ERROR("%s: State tracker error: NO_MEMORY\n", __func__); 175848b8605Smrg break; 176848b8605Smrg case ST_CONTEXT_ERROR_BAD_API: 177848b8605Smrg ERROR("%s: State tracker error: BAD_API\n", __func__); 178848b8605Smrg break; 179848b8605Smrg case ST_CONTEXT_ERROR_BAD_VERSION: 180848b8605Smrg ERROR("%s: State tracker error: BAD_VERSION\n", __func__); 181848b8605Smrg break; 182848b8605Smrg case ST_CONTEXT_ERROR_BAD_FLAG: 183848b8605Smrg ERROR("%s: State tracker error: BAD_FLAG\n", __func__); 184848b8605Smrg break; 185848b8605Smrg case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: 186848b8605Smrg ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__); 187848b8605Smrg break; 188848b8605Smrg case ST_CONTEXT_ERROR_UNKNOWN_FLAG: 189848b8605Smrg ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__); 190848b8605Smrg break; 191848b8605Smrg } 192848b8605Smrg 193b8e80941Smrg hgl_destroy_st_visual(context->stVisual); 194848b8605Smrg FREE(context); 195848b8605Smrg return -1; 196848b8605Smrg } 197848b8605Smrg 198848b8605Smrg assert(!context->st->st_manager_private); 199848b8605Smrg context->st->st_manager_private = (void*)context; 200848b8605Smrg 201848b8605Smrg struct st_context *stContext = (struct st_context*)context->st; 202848b8605Smrg 203848b8605Smrg // Init Gallium3D Post Processing 204848b8605Smrg // TODO: no pp filters are enabled yet through postProcessEnable 205848b8605Smrg context->postProcess = pp_init(stContext->pipe, context->postProcessEnable, 206848b8605Smrg stContext->cso_context); 207848b8605Smrg 208848b8605Smrg context_id contextNext = -1; 209848b8605Smrg Lock(); 210848b8605Smrg for (context_id i = 0; i < CONTEXT_MAX; i++) { 211848b8605Smrg if (fContext[i] == NULL) { 212848b8605Smrg fContext[i] = context; 213848b8605Smrg contextNext = i; 214848b8605Smrg break; 215848b8605Smrg } 216848b8605Smrg } 217848b8605Smrg Unlock(); 218848b8605Smrg 219848b8605Smrg if (contextNext < 0) { 220848b8605Smrg ERROR("%s: The next context is invalid... something went wrong!\n", 221848b8605Smrg __func__); 222848b8605Smrg //st_destroy_context(context->st); 223b8e80941Smrg FREE(context->stVisual); 224848b8605Smrg FREE(context); 225848b8605Smrg return -1; 226848b8605Smrg } 227848b8605Smrg 228848b8605Smrg TRACE("%s: context #%" B_PRIu64 " is the next available context\n", 229848b8605Smrg __func__, contextNext); 230848b8605Smrg 231848b8605Smrg return contextNext; 232848b8605Smrg} 233848b8605Smrg 234848b8605Smrg 235848b8605Smrgvoid 236848b8605SmrgGalliumContext::DestroyContext(context_id contextID) 237848b8605Smrg{ 238848b8605Smrg // fMutex should be locked *before* calling DestoryContext 239848b8605Smrg 240848b8605Smrg // See if context is used 241848b8605Smrg if (!fContext[contextID]) 242848b8605Smrg return; 243848b8605Smrg 244848b8605Smrg if (fContext[contextID]->st) { 245848b8605Smrg fContext[contextID]->st->flush(fContext[contextID]->st, 0, NULL); 246848b8605Smrg fContext[contextID]->st->destroy(fContext[contextID]->st); 247848b8605Smrg } 248848b8605Smrg 249848b8605Smrg if (fContext[contextID]->postProcess) 250848b8605Smrg pp_free(fContext[contextID]->postProcess); 251848b8605Smrg 252b8e80941Smrg // Delete state tracker framebuffer objects 253848b8605Smrg if (fContext[contextID]->read) 254848b8605Smrg delete fContext[contextID]->read; 255848b8605Smrg if (fContext[contextID]->draw) 256848b8605Smrg delete fContext[contextID]->draw; 257848b8605Smrg 258848b8605Smrg if (fContext[contextID]->stVisual) 259b8e80941Smrg hgl_destroy_st_visual(fContext[contextID]->stVisual); 260848b8605Smrg 261848b8605Smrg if (fContext[contextID]->manager) 262b8e80941Smrg hgl_destroy_st_manager(fContext[contextID]->manager); 263848b8605Smrg 264848b8605Smrg FREE(fContext[contextID]); 265848b8605Smrg} 266848b8605Smrg 267848b8605Smrg 268848b8605Smrgstatus_t 269848b8605SmrgGalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID) 270848b8605Smrg{ 271848b8605Smrg CALLED(); 272848b8605Smrg 273848b8605Smrg if (contextID < 0 || contextID > CONTEXT_MAX) { 274848b8605Smrg ERROR("%s: Invalid context ID range!\n", __func__); 275848b8605Smrg return B_ERROR; 276848b8605Smrg } 277848b8605Smrg 278848b8605Smrg Lock(); 279848b8605Smrg context_id oldContextID = fCurrentContext; 280848b8605Smrg struct hgl_context* context = fContext[contextID]; 281848b8605Smrg Unlock(); 282848b8605Smrg 283848b8605Smrg if (!context) { 284848b8605Smrg ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n", 285848b8605Smrg __func__, contextID); 286848b8605Smrg return B_ERROR; 287848b8605Smrg } 288848b8605Smrg 289848b8605Smrg if (!bitmap) { 290b8e80941Smrg context->api->make_current(context->api, NULL, NULL, NULL); 291848b8605Smrg return B_OK; 292848b8605Smrg } 293848b8605Smrg 294848b8605Smrg // Everything seems valid, lets set the new context. 295848b8605Smrg fCurrentContext = contextID; 296848b8605Smrg 297848b8605Smrg if (oldContextID > 0 && oldContextID != contextID) { 298848b8605Smrg fContext[oldContextID]->st->flush(fContext[oldContextID]->st, 299848b8605Smrg ST_FLUSH_FRONT, NULL); 300848b8605Smrg } 301848b8605Smrg 302848b8605Smrg // We need to lock and unlock framebuffers before accessing them 303b8e80941Smrg context->api->make_current(context->api, context->st, context->draw->stfbi, 304b8e80941Smrg context->read->stfbi); 305b8e80941Smrg 306b8e80941Smrg //if (context->textures[ST_ATTACHMENT_BACK_LEFT] 307b8e80941Smrg // && context->textures[ST_ATTACHMENT_DEPTH_STENCIL] 308b8e80941Smrg // && context->postProcess) { 309b8e80941Smrg // TRACE("Postprocessing textures...\n"); 310b8e80941Smrg // pp_init_fbos(context->postProcess, 311b8e80941Smrg // context->textures[ST_ATTACHMENT_BACK_LEFT]->width0, 312b8e80941Smrg // context->textures[ST_ATTACHMENT_BACK_LEFT]->height0); 313b8e80941Smrg //} 314848b8605Smrg 315848b8605Smrg context->bitmap = bitmap; 316848b8605Smrg //context->st->pipe->priv = context; 317848b8605Smrg 318848b8605Smrg return B_OK; 319848b8605Smrg} 320848b8605Smrg 321848b8605Smrg 322848b8605Smrgstatus_t 323848b8605SmrgGalliumContext::SwapBuffers(context_id contextID) 324848b8605Smrg{ 325848b8605Smrg CALLED(); 326848b8605Smrg 327848b8605Smrg Lock(); 328848b8605Smrg struct hgl_context *context = fContext[contextID]; 329848b8605Smrg Unlock(); 330848b8605Smrg 331848b8605Smrg if (!context) { 332848b8605Smrg ERROR("%s: context not found\n", __func__); 333848b8605Smrg return B_ERROR; 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg // TODO: Where did st_notify_swapbuffers go? 337b8e80941Smrg //st_notify_swapbuffers(context->draw->stfbi); 338848b8605Smrg 339848b8605Smrg context->st->flush(context->st, ST_FLUSH_FRONT, NULL); 340848b8605Smrg 341848b8605Smrg struct st_context *stContext = (struct st_context*)context->st; 342848b8605Smrg 343848b8605Smrg unsigned nColorBuffers = stContext->state.framebuffer.nr_cbufs; 344848b8605Smrg for (unsigned i = 0; i < nColorBuffers; i++) { 345848b8605Smrg pipe_surface* surface = stContext->state.framebuffer.cbufs[i]; 346848b8605Smrg if (!surface) { 347848b8605Smrg ERROR("%s: Color buffer %d invalid!\n", __func__, i); 348848b8605Smrg continue; 349848b8605Smrg } 350848b8605Smrg 351848b8605Smrg TRACE("%s: Flushing color buffer #%d\n", __func__, i); 352848b8605Smrg 353848b8605Smrg // We pass our destination bitmap to flush_fronbuffer which passes it 354848b8605Smrg // to the private winsys display call. 355848b8605Smrg fScreen->flush_frontbuffer(fScreen, surface->texture, 0, 0, 356848b8605Smrg context->bitmap, NULL); 357848b8605Smrg } 358848b8605Smrg 359848b8605Smrg #if 0 360848b8605Smrg // TODO... should we flush the z stencil buffer? 361848b8605Smrg pipe_surface* zSurface = stContext->state.framebuffer.zsbuf; 362848b8605Smrg fScreen->flush_frontbuffer(fScreen, zSurface->texture, 0, 0, 363848b8605Smrg context->bitmap, NULL); 364848b8605Smrg #endif 365848b8605Smrg 366848b8605Smrg return B_OK; 367848b8605Smrg} 368848b8605Smrg 369848b8605Smrg 370b8e80941Smrgbool 371b8e80941SmrgGalliumContext::Validate(uint32 width, uint32 height) 372848b8605Smrg{ 373848b8605Smrg CALLED(); 374b8e80941Smrg 375b8e80941Smrg if (!fContext[fCurrentContext]) { 376b8e80941Smrg return false; 377b8e80941Smrg } 378b8e80941Smrg 379b8e80941Smrg if (fContext[fCurrentContext]->width != width 380b8e80941Smrg || fContext[fCurrentContext]->height != height) { 381b8e80941Smrg Invalidate(width, height); 382b8e80941Smrg return false; 383848b8605Smrg } 384b8e80941Smrg return true; 385b8e80941Smrg} 386b8e80941Smrg 387b8e80941Smrg 388b8e80941Smrgvoid 389b8e80941SmrgGalliumContext::Invalidate(uint32 width, uint32 height) 390b8e80941Smrg{ 391b8e80941Smrg CALLED(); 392b8e80941Smrg 393b8e80941Smrg assert(fContext[fCurrentContext]); 394b8e80941Smrg 395b8e80941Smrg // Update st_context dimensions 396b8e80941Smrg fContext[fCurrentContext]->width = width; 397b8e80941Smrg fContext[fCurrentContext]->height = height; 398b8e80941Smrg 399b8e80941Smrg // Is this the best way to invalidate? 400b8e80941Smrg p_atomic_inc(&fContext[fCurrentContext]->read->stfbi->stamp); 401b8e80941Smrg p_atomic_inc(&fContext[fCurrentContext]->draw->stfbi->stamp); 402848b8605Smrg} 403848b8605Smrg 404848b8605Smrg 405848b8605Smrgvoid 406848b8605SmrgGalliumContext::Lock() 407848b8605Smrg{ 408848b8605Smrg CALLED(); 409b8e80941Smrg mtx_lock(&fMutex); 410848b8605Smrg} 411848b8605Smrg 412848b8605Smrg 413848b8605Smrgvoid 414848b8605SmrgGalliumContext::Unlock() 415848b8605Smrg{ 416848b8605Smrg CALLED(); 417b8e80941Smrg mtx_unlock(&fMutex); 418848b8605Smrg} 419848b8605Smrg/* vim: set tabstop=4: */ 420