Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2012, Haiku, Inc. All Rights Reserved.
  3.  * Distributed under the terms of the MIT License.
  4.  *
  5.  * Authors:
  6.  *              Artur Wyszynski, harakash@gmail.com
  7.  *              Alexander von Gluck IV, kallisti5@unixzen.com
  8.  */
  9.  
  10.  
  11. #include "GalliumContext.h"
  12.  
  13. #include <stdio.h>
  14.  
  15. #include "GLView.h"
  16.  
  17. #include "bitmap_wrapper.h"
  18.  
  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/sw_winsys.h"
  26. #include "sw/hgl/hgl_sw_winsys.h"
  27. #include "util/u_atomic.h"
  28. #include "util/u_memory.h"
  29.  
  30. #include "target-helpers/inline_sw_helper.h"
  31. #include "target-helpers/inline_debug_helper.h"
  32.  
  33.  
  34. #ifdef DEBUG
  35. #       define TRACE(x...) printf("GalliumContext: " x)
  36. #       define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
  37. #else
  38. #       define TRACE(x...)
  39. #       define CALLED()
  40. #endif
  41. #define ERROR(x...) printf("GalliumContext: " x)
  42.  
  43.  
  44. GalliumContext::GalliumContext(ulong options)
  45.         :
  46.         fOptions(options),
  47.         fScreen(NULL),
  48.         fCurrentContext(0)
  49. {
  50.         CALLED();
  51.  
  52.         // Make all contexts a known value
  53.         for (context_id i = 0; i < CONTEXT_MAX; i++)
  54.                 fContext[i] = NULL;
  55.  
  56.         CreateScreen();
  57.  
  58.         pipe_mutex_init(fMutex);
  59. }
  60.  
  61.  
  62. GalliumContext::~GalliumContext()
  63. {
  64.         CALLED();
  65.  
  66.         // Destroy our contexts
  67.         Lock();
  68.         for (context_id i = 0; i < CONTEXT_MAX; i++)
  69.                 DestroyContext(i);
  70.         Unlock();
  71.  
  72.         pipe_mutex_destroy(fMutex);
  73.  
  74.         // TODO: Destroy fScreen
  75. }
  76.  
  77.  
  78. status_t
  79. GalliumContext::CreateScreen()
  80. {
  81.         CALLED();
  82.  
  83.         // Allocate winsys and attach callback hooks
  84.         struct sw_winsys* winsys = hgl_create_sw_winsys();
  85.  
  86.         if (!winsys) {
  87.                 ERROR("%s: Couldn't allocate sw_winsys!\n", __func__);
  88.                 return B_ERROR;
  89.         }
  90.  
  91.         fScreen = sw_screen_create(winsys);
  92.  
  93.         if (fScreen == NULL) {
  94.                 ERROR("%s: Couldn't create screen!\n", __FUNCTION__);
  95.                 FREE(winsys);
  96.                 return B_ERROR;
  97.         }
  98.  
  99.         debug_screen_wrap(fScreen);
  100.  
  101.         const char* driverName = fScreen->get_name(fScreen);
  102.         ERROR("%s: Using %s driver.\n", __func__, driverName);
  103.  
  104.         return B_OK;
  105. }
  106.  
  107.  
  108. context_id
  109. GalliumContext::CreateContext(Bitmap *bitmap)
  110. {
  111.         CALLED();
  112.  
  113.         struct hgl_context* context = CALLOC_STRUCT(hgl_context);
  114.  
  115.         if (!context) {
  116.                 ERROR("%s: Couldn't create pipe context!\n", __FUNCTION__);
  117.                 return 0;
  118.         }
  119.  
  120.         // Set up the initial things our context needs
  121.         context->bitmap = bitmap;
  122.         context->colorSpace = get_bitmap_color_space(bitmap);
  123.         context->screen = fScreen;
  124.         context->draw = NULL;
  125.         context->read = NULL;
  126.         context->st = NULL;
  127.  
  128.         // Create st_gl_api
  129.         context->api = hgl_create_st_api();
  130.         if (!context->api) {
  131.                 ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__);
  132.                 return -1;
  133.         }
  134.  
  135.         // Create state_tracker manager
  136.         context->manager = hgl_create_st_manager(context);
  137.  
  138.         // Create state tracker visual
  139.         context->stVisual = hgl_create_st_visual(fOptions);
  140.  
  141.         // Create state tracker framebuffers
  142.         context->draw = hgl_create_st_framebuffer(context);
  143.         context->read = hgl_create_st_framebuffer(context);
  144.  
  145.         if (!context->draw || !context->read) {
  146.                 ERROR("%s: Problem allocating framebuffer!\n", __func__);
  147.                 FREE(context->stVisual);
  148.                 return -1;
  149.         }
  150.  
  151.         // Build state tracker attributes
  152.         struct st_context_attribs attribs;
  153.         memset(&attribs, 0, sizeof(attribs));
  154.         attribs.options.force_glsl_extensions_warn = false;
  155.         attribs.profile = ST_PROFILE_DEFAULT;
  156.         attribs.visual = *context->stVisual;
  157.         attribs.major = 1;
  158.         attribs.minor = 0;
  159.         //attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
  160.  
  161.         // Create context using state tracker api call
  162.         enum st_context_error result;
  163.         context->st = context->api->create_context(context->api, context->manager,
  164.                 &attribs, &result, context->st);
  165.  
  166.         if (!context->st) {
  167.                 ERROR("%s: Couldn't create mesa state tracker context!\n",
  168.                         __func__);
  169.                 switch (result) {
  170.                         case ST_CONTEXT_SUCCESS:
  171.                                 ERROR("%s: State tracker error: SUCCESS?\n", __func__);
  172.                                 break;
  173.                         case ST_CONTEXT_ERROR_NO_MEMORY:
  174.                                 ERROR("%s: State tracker error: NO_MEMORY\n", __func__);
  175.                                 break;
  176.                         case ST_CONTEXT_ERROR_BAD_API:
  177.                                 ERROR("%s: State tracker error: BAD_API\n", __func__);
  178.                                 break;
  179.                         case ST_CONTEXT_ERROR_BAD_VERSION:
  180.                                 ERROR("%s: State tracker error: BAD_VERSION\n", __func__);
  181.                                 break;
  182.                         case ST_CONTEXT_ERROR_BAD_FLAG:
  183.                                 ERROR("%s: State tracker error: BAD_FLAG\n", __func__);
  184.                                 break;
  185.                         case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
  186.                                 ERROR("%s: State tracker error: BAD_ATTRIBUTE\n", __func__);
  187.                                 break;
  188.                         case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
  189.                                 ERROR("%s: State tracker error: UNKNOWN_FLAG\n", __func__);
  190.                                 break;
  191.                 }
  192.  
  193.                 hgl_destroy_st_visual(context->stVisual);
  194.                 FREE(context);
  195.                 return -1;
  196.         }
  197.  
  198.         assert(!context->st->st_manager_private);
  199.         context->st->st_manager_private = (void*)context;
  200.  
  201.         struct st_context *stContext = (struct st_context*)context->st;
  202.        
  203.         // Init Gallium3D Post Processing
  204.         // TODO: no pp filters are enabled yet through postProcessEnable
  205.         context->postProcess = pp_init(stContext->pipe, context->postProcessEnable,
  206.                 stContext->cso_context);
  207.  
  208.         context_id contextNext = -1;
  209.         Lock();
  210.         for (context_id i = 0; i < CONTEXT_MAX; i++) {
  211.                 if (fContext[i] == NULL) {
  212.                         fContext[i] = context;
  213.                         contextNext = i;
  214.                         break;
  215.                 }
  216.         }
  217.         Unlock();
  218.  
  219.         if (contextNext < 0) {
  220.                 ERROR("%s: The next context is invalid... something went wrong!\n",
  221.                         __func__);
  222.                 //st_destroy_context(context->st);
  223.                 FREE(context->stVisual);
  224.                 FREE(context);
  225.                 return -1;
  226.         }
  227.  
  228.         TRACE("%s: context #%" B_PRIu64 " is the next available context\n",
  229.                 __func__, contextNext);
  230.  
  231.         return contextNext;
  232. }
  233.  
  234.  
  235. void
  236. GalliumContext::DestroyContext(context_id contextID)
  237. {
  238.         // fMutex should be locked *before* calling DestoryContext
  239.  
  240.         // See if context is used
  241.         if (!fContext[contextID])
  242.                 return;
  243.  
  244.         if (fContext[contextID]->st) {
  245.                 fContext[contextID]->st->flush(fContext[contextID]->st, 0, NULL);
  246.                 fContext[contextID]->st->destroy(fContext[contextID]->st);
  247.         }
  248.  
  249.         if (fContext[contextID]->postProcess)
  250.                 pp_free(fContext[contextID]->postProcess);
  251.  
  252.         // Delete state tracker framebuffer objects
  253.         if (fContext[contextID]->read)
  254.                 delete fContext[contextID]->read;
  255.         if (fContext[contextID]->draw)
  256.                 delete fContext[contextID]->draw;
  257.  
  258.         if (fContext[contextID]->stVisual)
  259.                 hgl_destroy_st_visual(fContext[contextID]->stVisual);
  260.  
  261.         if (fContext[contextID]->manager)
  262.                 hgl_destroy_st_manager(fContext[contextID]->manager);
  263.  
  264.         FREE(fContext[contextID]);
  265. }
  266.  
  267.  
  268. status_t
  269. GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
  270. {
  271.         CALLED();
  272.  
  273.         if (contextID < 0 || contextID > CONTEXT_MAX) {
  274.                 ERROR("%s: Invalid context ID range!\n", __func__);
  275.                 return B_ERROR;
  276.         }
  277.  
  278.         Lock();
  279.         context_id oldContextID = fCurrentContext;
  280.         struct hgl_context* context = fContext[contextID];
  281.         Unlock();
  282.  
  283.         if (!context) {
  284.                 ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n",
  285.                         __func__, contextID);
  286.                 return B_ERROR;
  287.         }
  288.  
  289.         if (!bitmap) {
  290.                 context->api->make_current(context->api, NULL, NULL, NULL);
  291.                 return B_OK;
  292.         }
  293.  
  294.         // Everything seems valid, lets set the new context.
  295.         fCurrentContext = contextID;
  296.  
  297.         if (oldContextID > 0 && oldContextID != contextID) {
  298.                 fContext[oldContextID]->st->flush(fContext[oldContextID]->st,
  299.                         ST_FLUSH_FRONT, NULL);
  300.         }
  301.  
  302.         // We need to lock and unlock framebuffers before accessing them
  303.         context->api->make_current(context->api, context->st, context->draw->stfbi,
  304.                 context->read->stfbi);
  305.  
  306.         //if (context->textures[ST_ATTACHMENT_BACK_LEFT]
  307.         //      && context->textures[ST_ATTACHMENT_DEPTH_STENCIL]
  308.         //      && context->postProcess) {
  309.         //      TRACE("Postprocessing textures...\n");
  310.         //      pp_init_fbos(context->postProcess,
  311.         //              context->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
  312.         //              context->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
  313.         //}
  314.  
  315.         context->bitmap = bitmap;
  316.         //context->st->pipe->priv = context;
  317.  
  318.         return B_OK;
  319. }
  320.  
  321.  
  322. status_t
  323. GalliumContext::SwapBuffers(context_id contextID)
  324. {
  325.         CALLED();
  326.  
  327.         Lock();
  328.         struct hgl_context *context = fContext[contextID];
  329.         Unlock();
  330.  
  331.         if (!context) {
  332.                 ERROR("%s: context not found\n", __func__);
  333.                 return B_ERROR;
  334.         }
  335.  
  336.         // TODO: Where did st_notify_swapbuffers go?
  337.         //st_notify_swapbuffers(context->draw->stfbi);
  338.  
  339.         context->st->flush(context->st, ST_FLUSH_FRONT, NULL);
  340.  
  341.         struct st_context *stContext = (struct st_context*)context->st;
  342.  
  343.         unsigned nColorBuffers = stContext->state.framebuffer.nr_cbufs;
  344.         for (unsigned i = 0; i < nColorBuffers; i++) {
  345.                 pipe_surface* surface = stContext->state.framebuffer.cbufs[i];
  346.                 if (!surface) {
  347.                         ERROR("%s: Color buffer %d invalid!\n", __func__, i);
  348.                         continue;
  349.                 }
  350.  
  351.                 TRACE("%s: Flushing color buffer #%d\n", __func__, i);
  352.  
  353.                 // We pass our destination bitmap to flush_fronbuffer which passes it
  354.                 // to the private winsys display call.
  355.                 fScreen->flush_frontbuffer(fScreen, surface->texture, 0, 0,
  356.                         context->bitmap, NULL);
  357.         }
  358.  
  359.         #if 0
  360.         // TODO... should we flush the z stencil buffer?
  361.         pipe_surface* zSurface = stContext->state.framebuffer.zsbuf;
  362.         fScreen->flush_frontbuffer(fScreen, zSurface->texture, 0, 0,
  363.                 context->bitmap, NULL);
  364.         #endif
  365.  
  366.         return B_OK;
  367. }
  368.  
  369.  
  370. bool
  371. GalliumContext::Validate(uint32 width, uint32 height)
  372. {
  373.         CALLED();
  374.  
  375.         if (!fContext[fCurrentContext]) {
  376.                 return false;
  377.         }
  378.  
  379.         if (fContext[fCurrentContext]->width != width
  380.                 || fContext[fCurrentContext]->height != height) {
  381.                 Invalidate(width, height);
  382.                 return false;
  383.         }
  384.         return true;
  385. }
  386.  
  387.  
  388. void
  389. GalliumContext::Invalidate(uint32 width, uint32 height)
  390. {
  391.         CALLED();
  392.  
  393.         assert(fContext[fCurrentContext]);
  394.  
  395.         // Update st_context dimensions
  396.         fContext[fCurrentContext]->width = width;
  397.         fContext[fCurrentContext]->height = height;
  398.  
  399.         // Is this the best way to invalidate?
  400.         p_atomic_inc(&fContext[fCurrentContext]->read->stfbi->stamp);
  401.         p_atomic_inc(&fContext[fCurrentContext]->draw->stfbi->stamp);
  402. }
  403.  
  404.  
  405. void
  406. GalliumContext::Lock()
  407. {
  408.         CALLED();
  409.         pipe_mutex_lock(fMutex);
  410. }
  411.  
  412.  
  413. void
  414. GalliumContext::Unlock()
  415. {
  416.         CALLED();
  417.         pipe_mutex_unlock(fMutex);
  418. }
  419. /* vim: set tabstop=4: */
  420.