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.  *              Jérôme Duval, korli@users.berlios.de
  7.  *              Philippe Houdoin, philippe.houdoin@free.fr
  8.  *              Artur Wyszynski, harakash@gmail.com
  9.  *              Alexander von Gluck IV, kallisti5@unixzen.com
  10.  */
  11.  
  12.  
  13. #include "SoftwareRenderer.h"
  14.  
  15. #include <Autolock.h>
  16. #include <interface/DirectWindowPrivate.h>
  17. #include <GraphicsDefs.h>
  18. #include <Screen.h>
  19. #include <stdio.h>
  20. #include <sys/time.h>
  21. #include <new>
  22.  
  23.  
  24. #ifdef DEBUG
  25. #       define TRACE(x...) printf("SoftwareRenderer: " x)
  26. #       define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
  27. #else
  28. #       define TRACE(x...)
  29. #       define CALLED()
  30. #endif
  31. #define ERROR(x...)     printf("SoftwareRenderer: " x)
  32.  
  33.  
  34. extern const char* color_space_name(color_space space);
  35.  
  36.  
  37. extern "C" _EXPORT BGLRenderer*
  38. instantiate_gl_renderer(BGLView *view, ulong opts, BGLDispatcher *dispatcher)
  39. {
  40.         return new SoftwareRenderer(view, opts, dispatcher);
  41. }
  42.  
  43. SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
  44.         BGLDispatcher* dispatcher)
  45.         :
  46.         BGLRenderer(view, options, dispatcher),
  47.         fBitmap(NULL),
  48.         fDirectModeEnabled(false),
  49.         fInfo(NULL),
  50.         fInfoLocker("info locker"),
  51.         fOptions(options),
  52.         fColorSpace(B_NO_COLOR_SPACE)
  53. {
  54.         CALLED();
  55.  
  56.         // Disable double buffer for the moment.
  57.         //options &= ~BGL_DOUBLE;
  58.  
  59.         // Initialize the "Haiku Software GL Pipe"
  60.         time_t beg;
  61.         time_t end;
  62.         beg = time(NULL);
  63.         fContextObj = new GalliumContext(options);
  64.         end = time(NULL);
  65.         TRACE("Haiku Software GL Pipe initialization time: %f.\n",
  66.                 difftime(end, beg));
  67.  
  68.         // Allocate a bitmap
  69.         BRect b = view->Bounds();
  70.         fColorSpace = BScreen(view->Window()).ColorSpace();
  71.         TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
  72.  
  73.         fWidth = (GLint)b.IntegerWidth();
  74.         fHeight = (GLint)b.IntegerHeight();
  75.  
  76.         _AllocateBitmap();
  77.  
  78.         // Initialize the first "Haiku Software GL Pipe" context
  79.         beg = time(NULL);
  80.         fContextID = fContextObj->CreateContext(fBitmap);
  81.         end = time(NULL);
  82.  
  83.         if (fContextID < 0)
  84.                 ERROR("%s: There was an error creating the context!\n", __func__);
  85.         else {
  86.                 TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n",
  87.                         __func__, difftime(end, beg));
  88.         }
  89.  
  90.         if (!fContextObj->GetCurrentContext())
  91.                 LockGL();
  92. }
  93.  
  94.  
  95. SoftwareRenderer::~SoftwareRenderer()
  96. {
  97.         CALLED();
  98.  
  99.         if (fContextObj)
  100.                 delete fContextObj;
  101.         if (fBitmap)
  102.                 delete fBitmap;
  103. }
  104.  
  105.  
  106. void
  107. SoftwareRenderer::LockGL()
  108. {
  109. //      CALLED();
  110.         BGLRenderer::LockGL();
  111.  
  112.         color_space cs = BScreen(GLView()->Window()).ColorSpace();
  113.  
  114.         BAutolock lock(fInfoLocker);
  115.         if (fDirectModeEnabled && fInfo != NULL) {
  116.                 fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
  117.                 fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
  118.         }
  119.  
  120.         if (fBitmap && cs == fColorSpace && fContextObj->Validate(fWidth, fHeight)) {
  121.                 fContextObj->SetCurrentContext(fBitmap, fContextID);
  122.                 return;
  123.         }
  124.  
  125.         fColorSpace = cs;
  126.  
  127.         _AllocateBitmap();
  128.         fContextObj->SetCurrentContext(fBitmap, fContextID);
  129. }
  130.  
  131.  
  132. void
  133. SoftwareRenderer::UnlockGL()
  134. {
  135. //      CALLED();
  136.         if ((fOptions & BGL_DOUBLE) == 0) {
  137.                 SwapBuffers();
  138.         }
  139.         fContextObj->SetCurrentContext(NULL, fContextID);
  140.         BGLRenderer::UnlockGL();
  141. }
  142.  
  143.  
  144. void
  145. SoftwareRenderer::SwapBuffers(bool vsync)
  146. {
  147. //      CALLED();
  148.         if (!fBitmap)
  149.                 return;
  150.  
  151.         BScreen screen(GLView()->Window());
  152.  
  153.         fContextObj->SwapBuffers(fContextID);
  154.  
  155.         BAutolock lock(fInfoLocker);
  156.  
  157.         if (!fDirectModeEnabled || fInfo == NULL) {
  158.                 if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
  159.                         GLView()->DrawBitmap(fBitmap, B_ORIGIN);
  160.                         GLView()->UnlockLooper();
  161.                         if (vsync)
  162.                                 screen.WaitForRetrace();
  163.                 }
  164.                 return;
  165.         }
  166.  
  167.         // check the bitmap size still matches the size
  168.         if (fInfo->window_bounds.bottom - fInfo->window_bounds.top
  169.                         != fBitmap->Bounds().IntegerHeight()
  170.                         || fInfo->window_bounds.right - fInfo->window_bounds.left
  171.                         != fBitmap->Bounds().IntegerWidth()) {
  172.                 ERROR("%s: Bitmap size doesn't match size!\n", __func__);
  173.                 return;
  174.         }
  175.  
  176.         uint32 bytesPerRow = fBitmap->BytesPerRow();
  177.         uint8 bytesPerPixel = bytesPerRow / fBitmap->Bounds().IntegerWidth();
  178.  
  179.         for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
  180.                 clipping_rect *clip = &fInfo->clip_list[i];
  181.                 int32 height = clip->bottom - clip->top + 1;
  182.                 int32 bytesWidth
  183.                         = (clip->right - clip->left + 1) * bytesPerPixel;
  184.                 bytesWidth -= bytesPerPixel;
  185.                 uint8 *p = (uint8 *)fInfo->bits + clip->top
  186.                         * fInfo->bytes_per_row + clip->left * bytesPerPixel;
  187.                 uint8 *b = (uint8 *)fBitmap->Bits()
  188.                         + (clip->top - fInfo->window_bounds.top) * bytesPerRow
  189.                         + (clip->left - fInfo->window_bounds.left) * bytesPerPixel;
  190.  
  191.                 for (int y = 0; y < height - 1; y++) {
  192.                         memcpy(p, b, bytesWidth);
  193.                         p += fInfo->bytes_per_row;
  194.                         b += bytesPerRow;
  195.                 }
  196.         }
  197.  
  198.         if (vsync)
  199.                 screen.WaitForRetrace();
  200. }
  201.  
  202.  
  203. void
  204. SoftwareRenderer::Draw(BRect updateRect)
  205. {
  206. //      CALLED();
  207.         if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap)
  208.                 GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
  209. }
  210.  
  211.  
  212. status_t
  213. SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
  214. {
  215.         CALLED();
  216.         color_space scs = fBitmap->ColorSpace();
  217.         color_space dcs = bitmap->ColorSpace();
  218.  
  219.         if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) {
  220.                 ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
  221.                         __PRETTY_FUNCTION__, color_space_name(scs), color_space_name(dcs));
  222.                 return B_BAD_TYPE;
  223.         }
  224.  
  225.         BRect sr = fBitmap->Bounds();
  226.         BRect dr = bitmap->Bounds();
  227.  
  228. //      int32 w1 = sr.IntegerWidth();
  229. //      int32 h1 = sr.IntegerHeight();
  230. //      int32 w2 = dr.IntegerWidth();
  231. //      int32 h2 = dr.IntegerHeight();
  232.  
  233.         sr = sr & dr.OffsetBySelf(location);
  234.         dr = sr.OffsetByCopy(-location.x, -location.y);
  235.  
  236.         uint8 *ps = (uint8 *) fBitmap->Bits();
  237.         uint8 *pd = (uint8 *) bitmap->Bits();
  238.         uint32 *s, *d;
  239.         uint32 y;
  240.         for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
  241.                 s = (uint32 *)(ps + y * fBitmap->BytesPerRow());
  242.                 s += (uint32) sr.left;
  243.  
  244.                 d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
  245.                         * bitmap->BytesPerRow());
  246.                 d += (uint32) dr.left;
  247.                 memcpy(d, s, dr.IntegerWidth() * 4);
  248.         }
  249.  
  250.         return B_OK;
  251. }
  252.  
  253.  
  254. status_t
  255. SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
  256. {
  257.         CALLED();
  258.  
  259.         color_space sourceCS = bitmap->ColorSpace();
  260.         color_space destinationCS = fBitmap->ColorSpace();
  261.  
  262.         if (sourceCS != destinationCS
  263.                 && (sourceCS != B_RGB32 || destinationCS != B_RGBA32)) {
  264.                 ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
  265.                         __PRETTY_FUNCTION__, color_space_name(sourceCS),
  266.                         color_space_name(destinationCS));
  267.                 return B_BAD_TYPE;
  268.         }
  269.  
  270.         BRect sr = bitmap->Bounds();
  271.         BRect dr = fBitmap->Bounds();
  272.  
  273.         sr = sr & dr.OffsetBySelf(location);
  274.         dr = sr.OffsetByCopy(-location.x, -location.y);
  275.  
  276.         uint8 *ps = (uint8 *) bitmap->Bits();
  277.         uint8 *pd = (uint8 *) fBitmap->Bits();
  278.         uint32 *s, *d;
  279.         uint32 y;
  280.  
  281.         for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) {
  282.                 s = (uint32 *)(ps + y * bitmap->BytesPerRow());
  283.                 s += (uint32) sr.left;
  284.  
  285.                 d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top))
  286.                         * fBitmap->BytesPerRow());
  287.                 d += (uint32) dr.left;
  288.  
  289.                 memcpy(d, s, dr.IntegerWidth() * 4);
  290.         }
  291.  
  292.         return B_OK;
  293. }
  294.  
  295.  
  296. void
  297. SoftwareRenderer::EnableDirectMode(bool enabled)
  298. {
  299.         fDirectModeEnabled = enabled;
  300. }
  301.  
  302.  
  303. void
  304. SoftwareRenderer::DirectConnected(direct_buffer_info *info)
  305. {
  306. //      CALLED();
  307.         BAutolock lock(fInfoLocker);
  308.         if (info) {
  309.                 if (!fInfo) {
  310.                         fInfo = (direct_buffer_info *)calloc(1,
  311.                                 DIRECT_BUFFER_INFO_AREA_SIZE);
  312.                 }
  313.                 memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
  314.         } else if (fInfo) {
  315.                 free(fInfo);
  316.                 fInfo = NULL;
  317.         }
  318. }
  319.  
  320.  
  321. void
  322. SoftwareRenderer::FrameResized(float width, float height)
  323. {
  324.         TRACE("%s: %f x %f\n", __func__, width, height);
  325.  
  326.         BAutolock lock(fInfoLocker);
  327.         fWidth = (GLuint)width;
  328.         fHeight = (GLuint)height;
  329. }
  330.  
  331.  
  332. void
  333. SoftwareRenderer::_AllocateBitmap()
  334. {
  335. //      CALLED();
  336.  
  337.         // allocate new size of back buffer bitmap
  338.         BAutolock lock(fInfoLocker);
  339.         if (fBitmap)
  340.                 delete fBitmap;
  341.  
  342.         if (fWidth < 1 || fHeight < 1) {
  343.                 TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__,
  344.                         fWidth, fHeight);
  345.                 return;
  346.         }
  347.         BRect rect(0.0, 0.0, fWidth, fHeight);
  348.         fBitmap = new (std::nothrow) BBitmap(rect, fColorSpace);
  349.         if (fBitmap == NULL) {
  350.                 TRACE("%s: Can't create bitmap!\n", __func__);
  351.                 return;
  352.         }
  353.  
  354.         TRACE("%s: New bitmap size: %" B_PRId32 " x %" B_PRId32 "\n", __func__,
  355.                 fBitmap->Bounds().IntegerWidth(), fBitmap->Bounds().IntegerHeight());
  356.  
  357. #if 0
  358.         // debug..
  359.         void *data = fBitmap->Bits();
  360.         memset(data, 0xcc, fBitmap->BitsLength());
  361. #endif
  362. }
  363.