diff options
Diffstat (limited to 'src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp')
-rw-r--r-- | src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp b/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp new file mode 100644 index 00000000000..16752c6237c --- /dev/null +++ b/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp @@ -0,0 +1,363 @@ +/* + * Copyright 2006-2012, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval, [email protected] + * Philippe Houdoin, [email protected] + * Artur Wyszynski, [email protected] + * Alexander von Gluck IV, [email protected] + */ + + +#include "SoftwareRenderer.h" + +#include <Autolock.h> +#include <interface/DirectWindowPrivate.h> +#include <GraphicsDefs.h> +#include <Screen.h> +#include <stdio.h> +#include <sys/time.h> +#include <new> + + +#define TRACE_SOFTWARE +#ifdef TRACE_SOFTWARE +# define TRACE(x...) printf("SoftwareRenderer: " x) +# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) +#else +# define TRACE(x...) +# define CALLED() +#endif +#define ERROR(x...) printf("SoftwareRenderer: " x) + + +extern const char* color_space_name(color_space space); + + +extern "C" _EXPORT BGLRenderer* +instantiate_gl_renderer(BGLView *view, ulong opts, BGLDispatcher *dispatcher) +{ + return new SoftwareRenderer(view, opts, dispatcher); +} + +SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options, + BGLDispatcher* dispatcher) + : + BGLRenderer(view, options, dispatcher), + fBitmap(NULL), + fDirectModeEnabled(false), + fInfo(NULL), + fInfoLocker("info locker"), + fOptions(options), + fColorSpace(B_NO_COLOR_SPACE) +{ + CALLED(); + + // Disable double buffer for the moment. + options &= ~BGL_DOUBLE; + + // Initialize the "Haiku Software GL Pipe" + time_t beg; + time_t end; + beg = time(NULL); + fContextObj = new GalliumContext(options); + end = time(NULL); + TRACE("Haiku Software GL Pipe initialization time: %f.\n", + difftime(end, beg)); + + // Allocate a bitmap + BRect b = view->Bounds(); + fColorSpace = BScreen(view->Window()).ColorSpace(); + TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace)); + + fWidth = (GLint)b.IntegerWidth(); + fHeight = (GLint)b.IntegerHeight(); + fNewWidth = fWidth; + fNewHeight = fHeight; + + _AllocateBitmap(); + + // Initialize the first "Haiku Software GL Pipe" context + beg = time(NULL); + fContextID = fContextObj->CreateContext(fBitmap); + end = time(NULL); + + if (fContextID < 0) + ERROR("%s: There was an error creating the context!\n", __func__); + else { + TRACE("%s: Haiku Software GL Pipe context creation time: %f.\n", + __func__, difftime(end, beg)); + } + + if (!fContextObj->GetCurrentContext()) + LockGL(); +} + + +SoftwareRenderer::~SoftwareRenderer() +{ + CALLED(); + + if (fContextObj) + delete fContextObj; + if (fBitmap) + delete fBitmap; +} + + +void +SoftwareRenderer::LockGL() +{ +// CALLED(); + BGLRenderer::LockGL(); + + color_space cs = BScreen(GLView()->Window()).ColorSpace(); + + BAutolock lock(fInfoLocker); + if (fDirectModeEnabled && fInfo != NULL) { + fNewWidth = fInfo->window_bounds.right - fInfo->window_bounds.left; + // + 1; + fNewHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top; + // + 1; + } + + if (fBitmap && cs == fColorSpace && fNewWidth == fWidth + && fNewHeight == fHeight) { + fContextObj->SetCurrentContext(fBitmap, fContextID); + return; + } + + fColorSpace = cs; + fWidth = fNewWidth; + fHeight = fNewHeight; + + _AllocateBitmap(); + fContextObj->SetCurrentContext(fBitmap, fContextID); +} + + +void +SoftwareRenderer::UnlockGL() +{ +// CALLED(); + if ((fOptions & BGL_DOUBLE) == 0) { + SwapBuffers(); + } + fContextObj->SetCurrentContext(NULL, fContextID); + BGLRenderer::UnlockGL(); +} + + +void +SoftwareRenderer::SwapBuffers(bool vsync) +{ +// CALLED(); + if (!fBitmap) + return; + + BScreen screen(GLView()->Window()); + + fContextObj->SwapBuffers(fContextID); + + BAutolock lock(fInfoLocker); + + if (!fDirectModeEnabled || fInfo == NULL) { + if (GLView()->LockLooperWithTimeout(1000) == B_OK) { + GLView()->DrawBitmap(fBitmap, B_ORIGIN); + GLView()->UnlockLooper(); + if (vsync) + screen.WaitForRetrace(); + } + return; + } + + // check the bitmap size still matches the size + if (fInfo->window_bounds.bottom - fInfo->window_bounds.top + != fBitmap->Bounds().IntegerHeight() + || fInfo->window_bounds.right - fInfo->window_bounds.left + != fBitmap->Bounds().IntegerWidth()) { + ERROR("%s: Bitmap size doesn't match size!\n", __func__); + return; + } + uint8 bytesPerPixel = fInfo->bits_per_pixel / 8; + uint32 bytesPerRow = fBitmap->BytesPerRow(); + for (uint32 i = 0; i < fInfo->clip_list_count; i++) { + clipping_rect *clip = &fInfo->clip_list[i]; + int32 height = clip->bottom - clip->top + 1; + int32 bytesWidth + = (clip->right - clip->left + 1) * bytesPerPixel; + bytesWidth -= bytesPerPixel; + uint8 *p = (uint8 *)fInfo->bits + clip->top + * fInfo->bytes_per_row + clip->left * bytesPerPixel; + uint8 *b = (uint8 *)fBitmap->Bits() + + (clip->top - fInfo->window_bounds.top) * bytesPerRow + + (clip->left - fInfo->window_bounds.left) * bytesPerPixel; + + for (int y = 0; y < height - 1; y++) { + memcpy(p, b, bytesWidth); + p += fInfo->bytes_per_row; + b += bytesPerRow; + } + } + + if (vsync) + screen.WaitForRetrace(); +} + + +void +SoftwareRenderer::Draw(BRect updateRect) +{ +// CALLED(); + if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap) + GLView()->DrawBitmap(fBitmap, updateRect, updateRect); +} + + +status_t +SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap) +{ + CALLED(); + color_space scs = fBitmap->ColorSpace(); + color_space dcs = bitmap->ColorSpace(); + + if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) { + ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n", + __PRETTY_FUNCTION__, color_space_name(scs), color_space_name(dcs)); + return B_BAD_TYPE; + } + + BRect sr = fBitmap->Bounds(); + BRect dr = bitmap->Bounds(); + +// int32 w1 = sr.IntegerWidth(); +// int32 h1 = sr.IntegerHeight(); +// int32 w2 = dr.IntegerWidth(); +// int32 h2 = dr.IntegerHeight(); + + sr = sr & dr.OffsetBySelf(location); + dr = sr.OffsetByCopy(-location.x, -location.y); + + uint8 *ps = (uint8 *) fBitmap->Bits(); + uint8 *pd = (uint8 *) bitmap->Bits(); + uint32 *s, *d; + uint32 y; + for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) { + s = (uint32 *)(ps + y * fBitmap->BytesPerRow()); + s += (uint32) sr.left; + + d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top)) + * bitmap->BytesPerRow()); + d += (uint32) dr.left; + memcpy(d, s, dr.IntegerWidth() * 4); + } + + return B_OK; +} + + +status_t +SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location) +{ + CALLED(); + + color_space sourceCS = bitmap->ColorSpace(); + color_space destinationCS = fBitmap->ColorSpace(); + + if (sourceCS != destinationCS + && (sourceCS != B_RGB32 || destinationCS != B_RGBA32)) { + ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n", + __PRETTY_FUNCTION__, color_space_name(sourceCS), + color_space_name(destinationCS)); + return B_BAD_TYPE; + } + + BRect sr = bitmap->Bounds(); + BRect dr = fBitmap->Bounds(); + + sr = sr & dr.OffsetBySelf(location); + dr = sr.OffsetByCopy(-location.x, -location.y); + + uint8 *ps = (uint8 *) bitmap->Bits(); + uint8 *pd = (uint8 *) fBitmap->Bits(); + uint32 *s, *d; + uint32 y; + + for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) { + s = (uint32 *)(ps + y * bitmap->BytesPerRow()); + s += (uint32) sr.left; + + d = (uint32 *)(pd + (y + (uint32)(dr.top - sr.top)) + * fBitmap->BytesPerRow()); + d += (uint32) dr.left; + + memcpy(d, s, dr.IntegerWidth() * 4); + } + + return B_OK; +} + + +void +SoftwareRenderer::EnableDirectMode(bool enabled) +{ + fDirectModeEnabled = enabled; +} + + +void +SoftwareRenderer::DirectConnected(direct_buffer_info *info) +{ +// CALLED(); + BAutolock lock(fInfoLocker); + if (info) { + if (!fInfo) { + fInfo = (direct_buffer_info *)calloc(1, + DIRECT_BUFFER_INFO_AREA_SIZE); + } + memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); + } else if (fInfo) { + free(fInfo); + fInfo = NULL; + } +} + + +void +SoftwareRenderer::FrameResized(float width, float height) +{ +// CALLED(); + BAutolock lock(fInfoLocker); + fNewWidth = (GLuint)width; + fNewHeight = (GLuint)height; +} + + +void +SoftwareRenderer::_AllocateBitmap() +{ +// CALLED(); + + // allocate new size of back buffer bitmap + BAutolock lock(fInfoLocker); + delete fBitmap; + fBitmap = NULL; + if (fWidth < 1 || fHeight < 1) { + TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__, + fWidth, fHeight); + return; + } + BRect rect(0.0, 0.0, fWidth, fHeight); + fBitmap = new (std::nothrow) BBitmap(rect, fColorSpace); + if (fBitmap == NULL) { + TRACE("%s: Can't create bitmap!\n", __func__); + return; + } + +#if 0 + // debug.. + void *data = fBitmap->Bits(); + memset(data, 0xcc, fBitmap->BitsLength()); +#endif +} |