Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2006-2012, Haiku. All rights reserved.
  3.  * Distributed under the terms of the MIT License.
  4.  *
  5.  * Authors:
  6.  *              Jérôme Duval, korli@users.berlios.de
  7.  *              Philippe Houdoin, philippe.houdoin@free.fr
  8.  *              Stefano Ceccherini, burton666@libero.it
  9.  */
  10.  
  11. #include <kernel/image.h>
  12.  
  13. #include <GLView.h>
  14.  
  15. #include <assert.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. #include <DirectWindow.h>
  21. #include <GLRenderer.h>
  22.  
  23. #include "interface/DirectWindowPrivate.h"
  24. #include "GLDispatcher.h"
  25. #include "GLRendererRoster.h"
  26.  
  27.  
  28. struct glview_direct_info {
  29.         direct_buffer_info* direct_info;
  30.         bool direct_connected;
  31.         bool enable_direct_mode;
  32.  
  33.         glview_direct_info();
  34.         ~glview_direct_info();
  35. };
  36.  
  37.  
  38. BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
  39.         ulong options)
  40.         :
  41.         BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
  42.                 //  | B_FULL_UPDATE_ON_RESIZE)
  43.         fGc(NULL),
  44.         fOptions(options),
  45.         fDitherCount(0),
  46.         fDrawLock("BGLView draw lock"),
  47.         fDisplayLock("BGLView display lock"),
  48.         fClipInfo(NULL),
  49.         fRenderer(NULL),
  50.         fRoster(NULL),
  51.         fDitherMap(NULL)
  52. {
  53.         fRoster = new GLRendererRoster(this, options);
  54. }
  55.  
  56.  
  57. BGLView::~BGLView()
  58. {
  59.         delete fClipInfo;
  60.         if (fRenderer)
  61.                 fRenderer->Release();
  62. }
  63.  
  64.  
  65. void
  66. BGLView::LockGL()
  67. {
  68.         // TODO: acquire the OpenGL API lock it on this glview
  69.  
  70.         fDisplayLock.Lock();
  71.         if (fRenderer)
  72.                 fRenderer->LockGL();
  73. }
  74.  
  75.  
  76. void
  77. BGLView::UnlockGL()
  78. {
  79.         if (fRenderer)
  80.                 fRenderer->UnlockGL();
  81.         fDisplayLock.Unlock();
  82.  
  83.         // TODO: release the GL API lock to others glviews
  84. }
  85.  
  86.  
  87. void
  88. BGLView::SwapBuffers()
  89. {
  90.         SwapBuffers(false);
  91. }
  92.  
  93.  
  94. void
  95. BGLView::SwapBuffers(bool vSync)
  96. {
  97.         if (fRenderer) {
  98.                 _LockDraw();
  99.                 fRenderer->SwapBuffers(vSync);
  100.                 _UnlockDraw();
  101.         }
  102. }
  103.  
  104.  
  105. BView*
  106. BGLView::EmbeddedView()
  107. {
  108.         return NULL;
  109. }
  110.  
  111.  
  112. void*
  113. BGLView::GetGLProcAddress(const char* procName)
  114. {
  115.         BGLDispatcher* glDispatcher = NULL;
  116.  
  117.         if (fRenderer)
  118.                 glDispatcher = fRenderer->GLDispatcher();
  119.  
  120.         if (glDispatcher)
  121.                 return (void*)glDispatcher->AddressOf(procName);
  122.  
  123.         return NULL;
  124. }
  125.  
  126.  
  127. status_t
  128. BGLView::CopyPixelsOut(BPoint source, BBitmap* dest)
  129. {
  130.         if (!fRenderer)
  131.                 return B_ERROR;
  132.  
  133.         if (!dest || !dest->Bounds().IsValid())
  134.                 return B_BAD_VALUE;
  135.  
  136.         return fRenderer->CopyPixelsOut(source, dest);
  137. }
  138.  
  139.  
  140. status_t
  141. BGLView::CopyPixelsIn(BBitmap* source, BPoint dest)
  142. {
  143.         if (!fRenderer)
  144.                 return B_ERROR;
  145.  
  146.         if (!source || !source->Bounds().IsValid())
  147.                 return B_BAD_VALUE;
  148.  
  149.         return fRenderer->CopyPixelsIn(source, dest);
  150. }
  151.  
  152.  
  153. /*!     Mesa's GLenum is not ulong but uint, so we can't use GLenum
  154.         without breaking this method signature.
  155.         Instead, we have to use the effective BeOS's SGI OpenGL GLenum type:
  156.         unsigned long.
  157.  */
  158. void
  159. BGLView::ErrorCallback(unsigned long errorCode)
  160. {
  161.         char msg[32];
  162.         sprintf(msg, "GL: Error code $%04lx.", errorCode);
  163.         // TODO: under BeOS R5, it call debugger(msg);
  164.         fprintf(stderr, "%s\n", msg);
  165. }
  166.  
  167.  
  168. void
  169. BGLView::Draw(BRect updateRect)
  170. {
  171.         if (fRenderer) {
  172.                 _LockDraw();
  173.                 fRenderer->Draw(updateRect);
  174.                 _UnlockDraw();
  175.                 return;
  176.         }
  177.         // TODO: auto-size and center the string
  178.         MovePenTo(8, 32);
  179.         DrawString("No OpenGL renderer available!");
  180. }
  181.  
  182.  
  183. void
  184. BGLView::AttachedToWindow()
  185. {
  186.         BView::AttachedToWindow();
  187.  
  188.         fBounds = Bounds();
  189.         for (BView* view = this; view != NULL; view = view->Parent())
  190.                 view->ConvertToParent(&fBounds);
  191.  
  192.         fRenderer = fRoster->GetRenderer();
  193.         if (fRenderer != NULL) {
  194.                 // Jackburton: The following code was commented because it doesn't look
  195.                 // good in "direct" mode:
  196.                 // when the window is moved, the app_server doesn't paint the view's
  197.                 // background, and the stuff behind the window itself shows up.
  198.                 // Setting the view color to black, instead, looks a bit more elegant.
  199. #if 0
  200.                 // Don't paint white window background when resized
  201.                 SetViewColor(B_TRANSPARENT_32_BIT);
  202. #else
  203.                 SetViewColor(0, 0, 0);
  204. #endif
  205.  
  206.                 // Set default OpenGL viewport:
  207.                 LockGL();
  208.                 glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
  209.                 UnlockGL();
  210.                 fRenderer->FrameResized(Bounds().IntegerWidth(),
  211.                         Bounds().IntegerHeight());
  212.  
  213.                 if (fClipInfo) {
  214.                         fRenderer->DirectConnected(fClipInfo->direct_info);
  215.                         fRenderer->EnableDirectMode(fClipInfo->enable_direct_mode);
  216.                 }
  217.  
  218.                 return;
  219.         }
  220.  
  221.         fprintf(stderr, "no renderer found! \n");
  222.  
  223.         // No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
  224.         // context
  225.         SetFont(be_bold_font);
  226.         // SetFontSize(16);
  227. }
  228.  
  229.  
  230. void
  231. BGLView::AllAttached()
  232. {
  233.         BView::AllAttached();
  234. }
  235.  
  236.  
  237. void
  238. BGLView::DetachedFromWindow()
  239. {
  240.         if (fRenderer)
  241.                 fRenderer->Release();
  242.         fRenderer = NULL;
  243.  
  244.         BView::DetachedFromWindow();
  245. }
  246.  
  247.  
  248. void
  249. BGLView::AllDetached()
  250. {
  251.         BView::AllDetached();
  252. }
  253.  
  254.  
  255. void
  256. BGLView::FrameResized(float width, float height)
  257. {
  258.         fBounds = Bounds();
  259.         for (BView* v = this; v; v = v->Parent())
  260.                 v->ConvertToParent(&fBounds);
  261.  
  262.         if (fRenderer) {
  263.                 LockGL();
  264.                 _LockDraw();
  265.                 _CallDirectConnected();
  266.                 fRenderer->FrameResized(width, height);
  267.                 _UnlockDraw();
  268.                 UnlockGL();
  269.         }
  270.  
  271.         BView::FrameResized(width, height);
  272. }
  273.  
  274.  
  275. status_t
  276. BGLView::Perform(perform_code d, void* arg)
  277. {
  278.         return BView::Perform(d, arg);
  279. }
  280.  
  281.  
  282. status_t
  283. BGLView::Archive(BMessage* data, bool deep) const
  284. {
  285.         return BView::Archive(data, deep);
  286. }
  287.  
  288.  
  289. void
  290. BGLView::MessageReceived(BMessage* msg)
  291. {
  292.         BView::MessageReceived(msg);
  293. }
  294.  
  295.  
  296. void
  297. BGLView::SetResizingMode(uint32 mode)
  298. {
  299.         BView::SetResizingMode(mode);
  300. }
  301.  
  302.  
  303. void
  304. BGLView::GetPreferredSize(float* _width, float* _height)
  305. {
  306.         if (_width)
  307.                 *_width = 0;
  308.         if (_height)
  309.                 *_height = 0;
  310. }
  311.  
  312.  
  313. void
  314. BGLView::Show()
  315. {
  316.         BView::Show();
  317. }
  318.  
  319.  
  320. void
  321. BGLView::Hide()
  322. {
  323.         BView::Hide();
  324. }
  325.  
  326.  
  327. BHandler*
  328. BGLView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
  329.         int32 form, const char* property)
  330. {
  331.         return BView::ResolveSpecifier(msg, index, specifier, form, property);
  332. }
  333.  
  334.  
  335. status_t
  336. BGLView::GetSupportedSuites(BMessage* data)
  337. {
  338.         return BView::GetSupportedSuites(data);
  339. }
  340.  
  341.  
  342. void
  343. BGLView::DirectConnected(direct_buffer_info* info)
  344. {
  345.         if (fClipInfo == NULL) {
  346.                 fClipInfo = new (std::nothrow) glview_direct_info();
  347.                 if (fClipInfo == NULL)
  348.                         return;
  349.         }
  350.  
  351.         direct_buffer_info* localInfo = fClipInfo->direct_info;
  352.  
  353.         switch (info->buffer_state & B_DIRECT_MODE_MASK) {
  354.                 case B_DIRECT_START:
  355.                         fClipInfo->direct_connected = true;
  356.                         memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
  357.                         _UnlockDraw();
  358.                         break;
  359.  
  360.                 case B_DIRECT_MODIFY:
  361.                         _LockDraw();
  362.                         memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
  363.                         _UnlockDraw();
  364.                         break;
  365.  
  366.                 case B_DIRECT_STOP:
  367.                         fClipInfo->direct_connected = false;
  368.                         _LockDraw();
  369.                         break;
  370.         }
  371.  
  372.         if (fRenderer)
  373.                 _CallDirectConnected();
  374. }
  375.  
  376.  
  377. void
  378. BGLView::EnableDirectMode(bool enabled)
  379. {
  380.         if (fRenderer)
  381.                 fRenderer->EnableDirectMode(enabled);
  382.         if (fClipInfo == NULL) {
  383.                 fClipInfo = new (std::nothrow) glview_direct_info();
  384.                 if (fClipInfo == NULL)
  385.                         return;
  386.         }
  387.  
  388.         fClipInfo->enable_direct_mode = enabled;
  389. }
  390.  
  391.  
  392. void
  393. BGLView::_LockDraw()
  394. {
  395.         if (!fClipInfo || !fClipInfo->enable_direct_mode)
  396.                 return;
  397.  
  398.         fDrawLock.Lock();
  399. }
  400.  
  401.  
  402. void
  403. BGLView::_UnlockDraw()
  404. {
  405.         if (!fClipInfo || !fClipInfo->enable_direct_mode)
  406.                 return;
  407.  
  408.         fDrawLock.Unlock();
  409. }
  410.  
  411.  
  412. void
  413. BGLView::_CallDirectConnected()
  414. {
  415.         if (!fClipInfo)
  416.                 return;
  417.  
  418.         direct_buffer_info* localInfo = fClipInfo->direct_info;
  419.         direct_buffer_info* info = (direct_buffer_info*)malloc(
  420.                 DIRECT_BUFFER_INFO_AREA_SIZE);
  421.         if (info == NULL)
  422.                 return;
  423.  
  424.         memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE);
  425.  
  426.         // Collect the rects into a BRegion, then clip to the view's bounds
  427.         BRegion region;
  428.         for (uint32 c = 0; c < localInfo->clip_list_count; c++)
  429.                 region.Include(localInfo->clip_list[c]);
  430.         BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left,
  431.                 localInfo->window_bounds.top);
  432.         info->window_bounds = boundsRegion.RectAtInt(0);
  433.                 // window_bounds are now view bounds
  434.         region.IntersectWith(&boundsRegion);
  435.  
  436.         info->clip_list_count = region.CountRects();
  437.         info->clip_bounds = region.FrameInt();
  438.  
  439.         for (uint32 c = 0; c < info->clip_list_count; c++)
  440.                 info->clip_list[c] = region.RectAtInt(c);
  441.         fRenderer->DirectConnected(info);
  442.         free(info);
  443. }
  444.  
  445.  
  446. //---- virtual reserved methods ----------
  447.  
  448.  
  449. void BGLView::_ReservedGLView1() {}
  450. void BGLView::_ReservedGLView2() {}
  451. void BGLView::_ReservedGLView3() {}
  452. void BGLView::_ReservedGLView4() {}
  453. void BGLView::_ReservedGLView5() {}
  454. void BGLView::_ReservedGLView6() {}
  455. void BGLView::_ReservedGLView7() {}
  456. void BGLView::_ReservedGLView8() {}
  457.  
  458.  
  459. // #pragma mark -
  460.  
  461.  
  462. // BeOS compatibility: contrary to others BView's contructors,
  463. // BGLView one wants a non-const name argument.
  464. BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
  465.         ulong options)
  466.         :
  467.         BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
  468.         fGc(NULL),
  469.         fOptions(options),
  470.         fDitherCount(0),
  471.         fDrawLock("BGLView draw lock"),
  472.         fDisplayLock("BGLView display lock"),
  473.         fClipInfo(NULL),
  474.         fRenderer(NULL),
  475.         fRoster(NULL),
  476.         fDitherMap(NULL)
  477. {
  478.         fRoster = new GLRendererRoster(this, options);
  479. }
  480.  
  481.  
  482. #if 0
  483. // TODO: implement BGLScreen class...
  484.  
  485.  
  486. BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options,
  487.                 status_t* error, bool debug)
  488.         :
  489.         BWindowScreen(name, screenMode, error, debug)
  490. {
  491. }
  492.  
  493.  
  494. BGLScreen::~BGLScreen()
  495. {
  496. }
  497.  
  498.  
  499. void
  500. BGLScreen::LockGL()
  501. {
  502. }
  503.  
  504.  
  505. void
  506. BGLScreen::UnlockGL()
  507. {
  508. }
  509.  
  510.  
  511. void
  512. BGLScreen::SwapBuffers()
  513. {
  514. }
  515.  
  516.  
  517. void
  518. BGLScreen::ErrorCallback(unsigned long errorCode)
  519. {
  520.         // Mesa's GLenum is not ulong but uint!
  521.         char msg[32];
  522.         sprintf(msg, "GL: Error code $%04lx.", errorCode);
  523.         // debugger(msg);
  524.         fprintf(stderr, "%s\n", msg);
  525.         return;
  526. }
  527.  
  528.  
  529. void
  530. BGLScreen::ScreenConnected(bool enabled)
  531. {
  532. }
  533.  
  534.  
  535. void
  536. BGLScreen::FrameResized(float width, float height)
  537. {
  538.         return BWindowScreen::FrameResized(width, height);
  539. }
  540.  
  541.  
  542. status_t
  543. BGLScreen::Perform(perform_code d, void* arg)
  544. {
  545.         return BWindowScreen::Perform(d, arg);
  546. }
  547.  
  548.  
  549. status_t
  550. BGLScreen::Archive(BMessage* data, bool deep) const
  551. {
  552.         return BWindowScreen::Archive(data, deep);
  553. }
  554.  
  555.  
  556. void
  557. BGLScreen::MessageReceived(BMessage* msg)
  558. {
  559.         BWindowScreen::MessageReceived(msg);
  560. }
  561.  
  562.  
  563. void
  564. BGLScreen::Show()
  565. {
  566.         BWindowScreen::Show();
  567. }
  568.  
  569.  
  570. void
  571. BGLScreen::Hide()
  572. {
  573.         BWindowScreen::Hide();
  574. }
  575.  
  576.  
  577. BHandler*
  578. BGLScreen::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
  579.         int32 form, const char* property)
  580. {
  581.         return BWindowScreen::ResolveSpecifier(msg, index, specifier,
  582.                 form, property);
  583. }
  584.  
  585.  
  586. status_t
  587. BGLScreen::GetSupportedSuites(BMessage* data)
  588. {
  589.         return BWindowScreen::GetSupportedSuites(data);
  590. }
  591.  
  592.  
  593. //---- virtual reserved methods ----------
  594.  
  595. void BGLScreen::_ReservedGLScreen1() {}
  596. void BGLScreen::_ReservedGLScreen2() {}
  597. void BGLScreen::_ReservedGLScreen3() {}
  598. void BGLScreen::_ReservedGLScreen4() {}
  599. void BGLScreen::_ReservedGLScreen5() {}
  600. void BGLScreen::_ReservedGLScreen6() {}
  601. void BGLScreen::_ReservedGLScreen7() {}
  602. void BGLScreen::_ReservedGLScreen8() {}
  603. #endif
  604.  
  605.  
  606. const char* color_space_name(color_space space)
  607. {
  608. #define C2N(a)  case a: return #a
  609.  
  610.         switch (space) {
  611.         C2N(B_RGB24);
  612.         C2N(B_RGB32);
  613.         C2N(B_RGBA32);
  614.         C2N(B_RGB32_BIG);
  615.         C2N(B_RGBA32_BIG);
  616.         C2N(B_GRAY8);
  617.         C2N(B_GRAY1);
  618.         C2N(B_RGB16);
  619.         C2N(B_RGB15);
  620.         C2N(B_RGBA15);
  621.         C2N(B_CMAP8);
  622.         default:
  623.                 return "Unknown!";
  624.         };
  625.  
  626. #undef C2N
  627. };
  628.  
  629.  
  630. glview_direct_info::glview_direct_info()
  631. {
  632.         // TODO: See direct_window_data() in app_server's ServerWindow.cpp
  633.         direct_info = (direct_buffer_info*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE);
  634.         direct_connected = false;
  635.         enable_direct_mode = false;
  636. }
  637.  
  638.  
  639. glview_direct_info::~glview_direct_info()
  640. {
  641.         free(direct_info);
  642. }
  643.  
  644.