Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2006-2012 Haiku, Inc. All Rights Reserved.
  3.  * Distributed under the terms of the MIT License.
  4.  *
  5.  * Authors:
  6.  *              Philippe Houdoin <philippe.houdoin@free.fr>
  7.  *              Alexander von Gluck IV <kallisti5@unixzen.com>
  8.  */
  9.  
  10.  
  11. #include <driver_settings.h>
  12. #include <image.h>
  13.  
  14. #include <kernel/image.h>
  15. #include <system/safemode_defs.h>
  16.  
  17. #include <Directory.h>
  18. #include <FindDirectory.h>
  19. #include <Path.h>
  20. #include <strings.h>
  21. #include "GLDispatcher.h"
  22. #include "GLRendererRoster.h"
  23.  
  24. #include <new>
  25. #include <string.h>
  26.  
  27.  
  28. extern "C" status_t _kern_get_safemode_option(const char* parameter,
  29.         char* buffer, size_t* _bufferSize);
  30.  
  31.  
  32. GLRendererRoster::GLRendererRoster(BGLView* view, ulong options)
  33.         :
  34.         fNextID(0),
  35.         fView(view),
  36.         fOptions(options),
  37.         fSafeMode(false),
  38.         fABISubDirectory(NULL)
  39. {
  40.         char parameter[32];
  41.         size_t parameterLength = sizeof(parameter);
  42.  
  43.         if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE,
  44.                 parameter, &parameterLength) == B_OK) {
  45.                 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
  46.                         || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
  47.                         || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
  48.                         fSafeMode = true;
  49.         }
  50.  
  51.         if (_kern_get_safemode_option(B_SAFEMODE_DISABLE_USER_ADD_ONS,
  52.                 parameter, &parameterLength) == B_OK) {
  53.                 if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
  54.                         || !strcasecmp(parameter, "true") || !strcasecmp(parameter, "yes")
  55.                         || !strcasecmp(parameter, "enable") || !strcmp(parameter, "1"))
  56.                         fSafeMode = true;
  57.         }
  58.  
  59.         // We might run in compatibility mode on a system with a different ABI. The
  60.         // renderers matching our ABI can usually be found in respective
  61.         // subdirectories of the opengl add-ons directories.
  62.         system_info info;
  63.         if (get_system_info(&info) == B_OK
  64.                 && (info.abi & B_HAIKU_ABI_MAJOR)
  65.                         != (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
  66.                         switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
  67.                                 case B_HAIKU_ABI_GCC_2:
  68.                                         fABISubDirectory = "gcc2";
  69.                                         break;
  70.                                 case B_HAIKU_ABI_GCC_4:
  71.                                         fABISubDirectory = "gcc4";
  72.                                         break;
  73.                         }
  74.         }
  75.  
  76.         AddDefaultPaths();
  77. }
  78.  
  79.  
  80. GLRendererRoster::~GLRendererRoster()
  81. {
  82.  
  83. }
  84.  
  85.  
  86. BGLRenderer*
  87. GLRendererRoster::GetRenderer(int32 id)
  88. {
  89.         RendererMap::const_iterator iterator = fRenderers.find(id);
  90.         if (iterator == fRenderers.end())
  91.                 return NULL;
  92.  
  93.         struct renderer_item item = iterator->second;
  94.         return item.renderer;
  95. }
  96.  
  97.  
  98. void
  99. GLRendererRoster::AddDefaultPaths()
  100. {
  101.         // add user directories first, so that they can override system renderers
  102.         const directory_which paths[] = {
  103.                 B_USER_NONPACKAGED_ADDONS_DIRECTORY,
  104.                 B_USER_ADDONS_DIRECTORY,
  105.                 B_SYSTEM_ADDONS_DIRECTORY,
  106.         };
  107.  
  108.         for (uint32 i = fSafeMode ? 4 : 0;
  109.                 i < sizeof(paths) / sizeof(paths[0]); i++) {
  110.                 BPath path;
  111.                 status_t status = find_directory(paths[i], &path, true);
  112.                 if (status == B_OK && path.Append("opengl") == B_OK)
  113.                         AddPath(path.Path());
  114.         }
  115. }
  116.  
  117.  
  118. status_t
  119. GLRendererRoster::AddPath(const char* path)
  120. {
  121.         BDirectory directory(path);
  122.         status_t status = directory.InitCheck();
  123.         if (status < B_OK)
  124.                 return status;
  125.  
  126.         // if a subdirectory for our ABI exists, use that instead
  127.         if (fABISubDirectory != NULL) {
  128.                 BEntry entry(&directory, fABISubDirectory);
  129.                 if (entry.IsDirectory()) {
  130.                         status = directory.SetTo(&entry);
  131.                         if (status != B_OK)
  132.                                 return status;
  133.                 }
  134.         }
  135.  
  136.         node_ref nodeRef;
  137.         status = directory.GetNodeRef(&nodeRef);
  138.         if (status < B_OK)
  139.                 return status;
  140.  
  141.         int32 count = 0;
  142.         int32 files = 0;
  143.  
  144.         entry_ref ref;
  145.         BEntry entry;
  146.         while (directory.GetNextRef(&ref) == B_OK) {
  147.                 entry.SetTo(&ref, true);
  148.                 if (entry.InitCheck() == B_OK && !entry.IsFile())
  149.                         continue;
  150.  
  151.                 if (CreateRenderer(ref) == B_OK)
  152.                         count++;
  153.  
  154.                 files++;
  155.         }
  156.  
  157.         if (files != 0 && count == 0)
  158.                 return B_BAD_VALUE;
  159.  
  160.         return B_OK;
  161. }
  162.  
  163.  
  164. status_t
  165. GLRendererRoster::AddRenderer(BGLRenderer* renderer,
  166.         image_id image, const entry_ref* ref, ino_t node)
  167. {
  168.         renderer_item item;
  169.         item.renderer = renderer;
  170.         item.image = image;
  171.         item.node = node;
  172.         if (ref != NULL)
  173.                 item.ref = *ref;
  174.  
  175.         try {
  176.                 fRenderers[fNextID] = item;
  177.         } catch (...) {
  178.                 return B_NO_MEMORY;
  179.         }
  180.  
  181.         renderer->fOwningRoster = this;
  182.         renderer->fID = fNextID++;
  183.         return B_OK;
  184. }
  185.  
  186.  
  187. status_t
  188. GLRendererRoster::CreateRenderer(const entry_ref& ref)
  189. {
  190.         BEntry entry(&ref, true);
  191.         node_ref nodeRef;
  192.         status_t status = entry.GetNodeRef(&nodeRef);
  193.         if (status < B_OK)
  194.                 return status;
  195.  
  196.         BPath path(&ref);
  197.         image_id image = load_add_on(path.Path());
  198.         if (image < B_OK)
  199.                 return image;
  200.  
  201.         BGLRenderer* (*instantiate_renderer)
  202.                 (BGLView* view, ulong options, BGLDispatcher* dispatcher);
  203.  
  204.         status = get_image_symbol(image, "instantiate_gl_renderer",
  205.                 B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer);
  206.         if (status == B_OK) {
  207.                 BGLRenderer* renderer
  208.                         = instantiate_renderer(fView, fOptions, new BGLDispatcher());
  209.                 if (!renderer) {
  210.                         unload_add_on(image);
  211.                         return B_UNSUPPORTED;
  212.                 }
  213.  
  214.                 if (AddRenderer(renderer, image, &ref, nodeRef.node) != B_OK) {
  215.                         renderer->Release();
  216.                         // this will delete the renderer
  217.                         unload_add_on(image);
  218.                 }
  219.                 return B_OK;
  220.         }
  221.         unload_add_on(image);
  222.  
  223.         return status;
  224. }
  225.