[Mesa-dev] [PATCH] mesa: Add haiku swrast driver

Alexander von Gluck IV kallisti5 at unixzen.com
Tue Nov 12 21:46:28 PST 2013


* This is pretty small and upkeep
  should be minimal.
* Currently fully working.
---
 src/mesa/drivers/SConscript                     |    3 +
 src/mesa/drivers/haiku/swrast/SConscript        |   28 +
 src/mesa/drivers/haiku/swrast/SoftwareRast.cpp  |  707 +++++++++++++++++++++++
 src/mesa/drivers/haiku/swrast/SoftwareRast.h    |   96 +++
 src/mesa/drivers/haiku/swrast/SoftwareRast.rdef |   39 ++
 5 files changed, 873 insertions(+)
 create mode 100644 src/mesa/drivers/haiku/swrast/SConscript
 create mode 100644 src/mesa/drivers/haiku/swrast/SoftwareRast.cpp
 create mode 100644 src/mesa/drivers/haiku/swrast/SoftwareRast.h
 create mode 100644 src/mesa/drivers/haiku/swrast/SoftwareRast.rdef

diff --git a/src/mesa/drivers/SConscript b/src/mesa/drivers/SConscript
index 355e680..86aa868 100644
--- a/src/mesa/drivers/SConscript
+++ b/src/mesa/drivers/SConscript
@@ -10,3 +10,6 @@ if env['dri']:
 
 if env['platform'] == 'windows':
     SConscript('windows/gdi/SConscript')
+
+if env['platform'] == 'haiku':
+    SConscript('haiku/swrast/SConscript')
diff --git a/src/mesa/drivers/haiku/swrast/SConscript b/src/mesa/drivers/haiku/swrast/SConscript
new file mode 100644
index 0000000..71ce88e
--- /dev/null
+++ b/src/mesa/drivers/haiku/swrast/SConscript
@@ -0,0 +1,28 @@
+Import('*')
+
+env = env.Clone()
+
+env.Append(CPPPATH = [
+    '#/src/mapi',
+    '#/src/mesa',
+    '#/src/mesa/main',
+    '/boot/system/develop/headers/private',
+    Dir('../../../mapi'), # src/mapi build path for python-generated GL API files/headers
+])
+
+env.Prepend(LIBS = [
+    glsl,
+    mesa,
+])
+
+sources = [
+	'SoftwareRast.cpp'
+]
+
+# Disallow undefined symbols
+#env.Append(SHLINKFLAGS = ['-Wl,-z,defs'])
+
+libswrast = env.SharedLibrary(
+    target = 'swrast',
+    source = sources
+)
diff --git a/src/mesa/drivers/haiku/swrast/SoftwareRast.cpp b/src/mesa/drivers/haiku/swrast/SoftwareRast.cpp
new file mode 100644
index 0000000..52e8e5e
--- /dev/null
+++ b/src/mesa/drivers/haiku/swrast/SoftwareRast.cpp
@@ -0,0 +1,707 @@
+/*
+ * Copyright 2006-2012, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *		Jérôme Duval, korli at users.berlios.de
+ *		Philippe Houdoin, philippe.houdoin at free.fr
+ *		Artur Wyszynski, harakash at gmail.com
+ *		Alexander von Gluck, kallisti5 at unixzen.com
+ */
+
+
+#include <kernel/image.h>
+#include "SoftwareRast.h"
+
+#include <Autolock.h>
+#include <interface/DirectWindowPrivate.h>
+#include <GraphicsDefs.h>
+#include <Screen.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+#include "extensions.h"
+#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
+#include "main/api_exec.h"
+#include "main/colormac.h"
+#include "main/cpuinfo.h"
+#include "main/buffers.h"
+#include "main/formats.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/version.h"
+#include "main/vtxfmt.h"
+#include "swrast/swrast.h"
+#include "swrast/s_renderbuffer.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "vbo/vbo.h"
+
+
+#ifdef DEBUG
+#	define TRACE(x...) printf("MesaSoftwareRast: " x)
+#	define CALLED() printf("MesaSoftwareRast: %s\n", __PRETTY_FUNCTION__)
+#else
+#	define TRACE(x...)
+#	define CALLED()
+#endif
+
+#define ERROR(x...) printf("MesaSoftwareRast: " x)
+}
+
+
+extern const char* color_space_name(color_space space);
+
+
+extern "C" _EXPORT BGLRenderer*
+instantiate_gl_renderer(BGLView* view, ulong options,
+	BGLDispatcher* dispatcher)
+{
+	return new MesaSoftwareRast(view, options, dispatcher);
+}
+
+
+MesaSoftwareRast::MesaSoftwareRast(BGLView* view, ulong options,
+	BGLDispatcher* dispatcher)
+	: BGLRenderer(view, options, dispatcher),
+	fBitmap(NULL),
+	fDirectModeEnabled(false),
+	fInfo(NULL),
+	fInfoLocker("info locker"),
+	fContext(NULL),
+	fVisual(NULL),
+	fFrameBuffer(NULL),
+	fFrontRenderBuffer(NULL),
+	fBackRenderBuffer(NULL),
+	fColorSpace(B_NO_COLOR_SPACE)
+{
+	CALLED();
+
+	fColorSpace = BScreen(GLView()->Window()).ColorSpace();
+
+	// We force single buffering for the time being
+	options &= ~BGL_DOUBLE;
+
+	const GLboolean rgbFlag = ((options & BGL_INDEX) == 0);
+	const GLboolean alphaFlag = ((options & BGL_ALPHA) == BGL_ALPHA);
+	const GLboolean dblFlag = ((options & BGL_DOUBLE) == BGL_DOUBLE);
+	const GLboolean stereoFlag = false;
+	const GLint depth = (options & BGL_DEPTH) ? 16 : 0;
+	const GLint stencil = (options & BGL_STENCIL) ? 8 : 0;
+	const GLint accum = (options & BGL_ACCUM) ? 16 : 0;
+	const GLint red = rgbFlag ? 8 : 0;
+	const GLint green = rgbFlag ? 8 : 0;
+	const GLint blue = rgbFlag ? 8 : 0;
+	const GLint alpha = alphaFlag ? 8 : 0;
+
+	fOptions = options; // | BGL_INDIRECT;
+	struct dd_function_table functions;
+
+	fVisual = _mesa_create_visual(dblFlag, stereoFlag, red, green,
+		blue, alpha, depth, stencil, accum, accum, accum,
+		alpha ? accum : 0, 1);
+
+	// Initialize device driver function table
+	_mesa_init_driver_functions(&functions);
+
+	functions.GetString = _GetString;
+	functions.UpdateState = _UpdateState;
+	functions.MapRenderbuffer = _RenderBufferMap;
+	functions.Flush = _Flush;
+
+	// create core context
+	fContext = _mesa_create_context(API_OPENGL_COMPAT, fVisual, NULL,
+		&functions);
+
+	if (!fContext) {
+		ERROR("%s: Failed to create Mesa context!\n", __func__);
+		_mesa_destroy_visual(fVisual);
+		return;
+	}
+
+	fContext->DriverCtx = (void*)this;
+
+	/* Initialize the software rasterizer and helper modules. */
+	_swrast_CreateContext(fContext);
+	_vbo_CreateContext(fContext);
+	_tnl_CreateContext(fContext);
+	_swsetup_CreateContext(fContext);
+	_swsetup_Wakeup(fContext);
+
+	// Use default TCL pipeline
+	TNL_CONTEXT(fContext)->Driver.RunPipeline = _tnl_run_pipeline;
+
+	_mesa_meta_init(fContext);
+	_mesa_enable_sw_extensions(fContext);
+
+	_mesa_compute_version(fContext);
+
+	_mesa_initialize_dispatch_tables(fContext);
+	_mesa_initialize_vbo_vtxfmt(fContext);
+
+	// create core framebuffer
+	fFrameBuffer = _mesa_create_framebuffer(fVisual);
+	if (fFrameBuffer == NULL) {
+		ERROR("%s: Unable to calloc GL FrameBuffer!\n", __func__);
+		_mesa_destroy_visual(fVisual);
+		return;
+	}
+
+	// Setup front render buffer
+	fFrontRenderBuffer = _NewRenderBuffer(true);
+	if (fFrontRenderBuffer == NULL) {
+		ERROR("%s: FrontRenderBuffer is requested but unallocated!\n",
+			__func__);
+		_mesa_destroy_visual(fVisual);
+		free(fFrameBuffer);
+		return;
+	}
+	_mesa_add_renderbuffer(fFrameBuffer, BUFFER_FRONT_LEFT,
+		&fFrontRenderBuffer->Base);
+
+	// Setup back render buffer (if requested)
+	if (fVisual->doubleBufferMode) {
+		fBackRenderBuffer = _NewRenderBuffer(false);
+		if (fBackRenderBuffer == NULL) {
+			ERROR("%s: BackRenderBuffer is requested but unallocated!\n",
+				__func__);
+			_mesa_destroy_visual(fVisual);
+			free(fFrameBuffer);
+			return;
+		}
+		_mesa_add_renderbuffer(fFrameBuffer, BUFFER_BACK_LEFT,
+			&fBackRenderBuffer->Base);
+	}
+
+	_swrast_add_soft_renderbuffers(fFrameBuffer, GL_FALSE,
+		fVisual->haveDepthBuffer, fVisual->haveStencilBuffer,
+		fVisual->haveAccumBuffer, alphaFlag, GL_FALSE);
+
+	BRect bounds = view->Bounds();
+	fWidth = (GLint)bounds.Width();
+	fHeight = (GLint)bounds.Height();
+
+	// some stupid applications (Quake2) don't even think about calling LockGL()
+	// before using glGetString and its glGet*() friends...
+	// so make sure there is at least a valid context.
+
+	if (!_mesa_get_current_context()) {
+		LockGL();
+		// not needed, we don't have a looper yet: UnlockLooper();
+	}
+}
+
+
+MesaSoftwareRast::~MesaSoftwareRast()
+{
+	CALLED();
+	_swsetup_DestroyContext(fContext);
+	_swrast_DestroyContext(fContext);
+	_tnl_DestroyContext(fContext);
+	_vbo_DestroyContext(fContext);
+	_mesa_destroy_visual(fVisual);
+	_mesa_destroy_framebuffer(fFrameBuffer);
+	_mesa_destroy_context(fContext);
+
+	free(fInfo);
+	free(fFrameBuffer);
+
+	delete fBitmap;
+}
+
+
+void
+MesaSoftwareRast::LockGL()
+{
+	CALLED();
+	BGLRenderer::LockGL();
+
+	_mesa_make_current(fContext, fFrameBuffer, fFrameBuffer);
+
+	color_space colorSpace = BScreen(GLView()->Window()).ColorSpace();
+
+	GLuint width = fWidth;
+	GLuint height = fHeight;
+
+	BAutolock lock(fInfoLocker);
+	if (fDirectModeEnabled && fInfo != NULL) {
+		width = fInfo->window_bounds.right
+			- fInfo->window_bounds.left + 1;
+		height = fInfo->window_bounds.bottom
+			- fInfo->window_bounds.top + 1;
+	}
+
+	if (fColorSpace != colorSpace) {
+		fColorSpace = colorSpace;
+		_SetupRenderBuffer(&fFrontRenderBuffer->Base, fColorSpace);
+		if (fVisual->doubleBufferMode)
+			_SetupRenderBuffer(&fBackRenderBuffer->Base, fColorSpace);
+	}
+
+	_CheckResize(width, height);
+}
+
+
+void
+MesaSoftwareRast::UnlockGL()
+{
+	CALLED();
+	_mesa_make_current(fContext, NULL, NULL);
+	BGLRenderer::UnlockGL();
+}
+
+
+void
+MesaSoftwareRast::SwapBuffers(bool VSync)
+{
+	CALLED();
+
+	if (!fBitmap)
+		return;
+
+	if (fVisual->doubleBufferMode)
+		_mesa_notifySwapBuffers(fContext);
+
+	if (!fDirectModeEnabled || fInfo == NULL) {
+		if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
+			GLView()->DrawBitmap(fBitmap, B_ORIGIN);
+			GLView()->UnlockLooper();
+		}
+	} else {
+		// TODO: Here the BGLView needs to be drawlocked.
+		_CopyToDirect();
+	}
+
+	if (VSync) {
+		BScreen screen(GLView()->Window());
+		screen.WaitForRetrace();
+	}
+}
+
+
+void
+MesaSoftwareRast::Draw(BRect updateRect)
+{
+	CALLED();
+	if (fBitmap && (!fDirectModeEnabled || (fInfo == NULL)))
+		GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
+}
+
+
+status_t
+MesaSoftwareRast::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)) {
+		fprintf(stderr, "CopyPixelsOut(): incompatible color space: %s != %s\n",
+			color_space_name(scs),
+			color_space_name(dcs));
+		return B_BAD_TYPE;
+	}
+
+	BRect sr = fBitmap->Bounds();
+	BRect dr = bitmap->Bounds();
+
+	sr = sr & dr.OffsetBySelf(location);
+	dr = sr.OffsetByCopy(-location.x, -location.y);
+
+	uint8* ps = (uint8*)fBitmap->Bits();
+	uint8* pd = (uint8*)bitmap->Bits();
+	uint32* s;
+	uint32* 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
+MesaSoftwareRast::CopyPixelsIn(BBitmap* bitmap, BPoint location)
+{
+	CALLED();
+	color_space scs = bitmap->ColorSpace();
+	color_space dcs = fBitmap->ColorSpace();
+
+	if (scs != dcs && (dcs != B_RGBA32 || scs != B_RGB32)) {
+		fprintf(stderr, "CopyPixelsIn(): incompatible color space: %s != %s\n",
+			color_space_name(scs),
+			color_space_name(dcs));
+		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;
+	uint32* 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
+MesaSoftwareRast::EnableDirectMode(bool enabled)
+{
+	fDirectModeEnabled = enabled;
+}
+
+
+void
+MesaSoftwareRast::DirectConnected(direct_buffer_info* info)
+{
+	// TODO: I'm not sure we need to do this: BGLView already
+	// keeps a local copy of the direct_buffer_info passed by
+	// BDirectWindow::DirectConnected().
+	BAutolock lock(fInfoLocker);
+	if (info) {
+		if (!fInfo) {
+			fInfo = (direct_buffer_info*)malloc(DIRECT_BUFFER_INFO_AREA_SIZE);
+			if (!fInfo)
+				return;
+		}
+		memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
+	} else if (fInfo) {
+		free(fInfo);
+		fInfo = NULL;
+	}
+}
+
+
+void
+MesaSoftwareRast::FrameResized(float width, float height)
+{
+	BAutolock lock(fInfoLocker);
+	_CheckResize((GLuint)width, (GLuint)height);
+}
+
+
+void
+MesaSoftwareRast::_CheckResize(GLuint newWidth, GLuint newHeight)
+{
+	CALLED();
+
+	if (fBitmap && newWidth == fWidth
+		&& newHeight == fHeight) {
+		return;
+	}
+
+	_mesa_resize_framebuffer(fContext, fFrameBuffer, newWidth, newHeight);
+	fHeight = newHeight;
+	fWidth = newWidth;
+
+	_AllocateBitmap();
+}
+
+
+void
+MesaSoftwareRast::_AllocateBitmap()
+{
+	CALLED();
+
+	// allocate new size of back buffer bitmap
+	delete fBitmap;
+	fBitmap = NULL;
+
+	if (fWidth < 1 || fHeight < 1) {
+		TRACE("%s: Cannot allocate bitmap < 1x1!\n", __func__);
+		return;
+	}
+
+	BRect rect(0.0, 0.0, fWidth - 1, fHeight - 1);
+	fBitmap = new BBitmap(rect, fColorSpace);
+
+	#if 0
+	// Used for platform optimized drawing
+	for (uint i = 0; i < fHeight; i++) {
+		fRowAddr[fHeight - i - 1] = (GLvoid *)((GLubyte *)fBitmap->Bits()
+			+ i * fBitmap->BytesPerRow());
+	}
+	#endif
+
+	fFrameBuffer->Width = fWidth;
+	fFrameBuffer->Height = fHeight;
+	TRACE("%s: Bitmap Size: %" B_PRIu32 "\n", __func__, fBitmap->BitsLength());
+
+	fFrontRenderBuffer->Buffer = (GLubyte*)fBitmap->Bits();
+}
+
+
+// #pragma mark - static
+
+
+const GLubyte*
+MesaSoftwareRast::_GetString(gl_context* ctx, GLenum name)
+{
+	switch (name) {
+		case GL_VENDOR:
+			return (const GLubyte*) "Mesa Project";
+		case GL_RENDERER:
+			return (const GLubyte*) "Software Rasterizer";
+		default:
+			// Let core library handle all other cases
+			return NULL;
+	}
+}
+
+
+void
+MesaSoftwareRast::_UpdateState(gl_context* ctx, GLuint new_state)
+{
+	if (!ctx)
+		return;
+
+	CALLED();
+	_swrast_InvalidateState(ctx, new_state);
+	_swsetup_InvalidateState(ctx, new_state);
+	_vbo_InvalidateState(ctx, new_state);
+	_tnl_InvalidateState(ctx, new_state);
+}
+
+
+GLboolean
+MesaSoftwareRast::_RenderBufferStorage(gl_context* ctx,
+	struct gl_renderbuffer* render, GLenum internalFormat,
+	GLuint width, GLuint height)
+{
+	CALLED();
+
+	render->Width = width;
+	render->Height = height;
+
+	struct swrast_renderbuffer *swRenderBuffer = swrast_renderbuffer(render);
+
+	swRenderBuffer->RowStride = width * _mesa_get_format_bytes(render->Format);
+
+	return GL_TRUE;
+}
+
+
+GLboolean
+MesaSoftwareRast::_RenderBufferStorageMalloc(gl_context* ctx,
+	struct gl_renderbuffer* render, GLenum internalFormat,
+	GLuint width, GLuint height)
+{
+	CALLED();
+
+	render->Width = width;
+	render->Height = height;
+
+	struct swrast_renderbuffer *swRenderBuffer = swrast_renderbuffer(render);
+
+	if (swRenderBuffer != NULL) {
+		free(swRenderBuffer->Buffer);
+		swRenderBuffer->RowStride
+			= width * _mesa_get_format_bytes(render->Format);
+
+		uint32 size = swRenderBuffer->RowStride * height;
+		TRACE("%s: Allocate %" B_PRIu32 " bytes for RenderBuffer\n",
+			__func__, size);
+		swRenderBuffer->Buffer = (GLubyte*)malloc(size);
+		if (!swRenderBuffer->Buffer) {
+			ERROR("%s: Memory allocation failure!\n", __func__);
+			return GL_FALSE;
+		}
+	} else {
+		ERROR("%s: Couldn't obtain software renderbuffer!\n",
+			__func__);
+		return GL_FALSE;
+	}
+
+	return GL_TRUE;
+}
+
+
+void
+MesaSoftwareRast::_Flush(gl_context* ctx)
+{
+	CALLED();
+	// TODO: We may want to add the void* DriverCtx back into mtypes.h for
+	// gl_context someday...
+	#if 0
+	MesaSoftwareRast* driverContext = (MesaSoftwareRast*)ctx->DriverCtx;
+	if ((driverContext->fOptions & BGL_DOUBLE) == 0) {
+		// TODO: SwapBuffers() can call _CopyToDirect(), which should
+		// be always called with with the BGLView drawlocked.
+		// This is not always the case if called from here.
+		driverContext->SwapBuffers();
+	}
+	#endif
+}
+
+
+struct swrast_renderbuffer*
+MesaSoftwareRast::_NewRenderBuffer(bool front)
+{
+	CALLED();
+	struct swrast_renderbuffer *swRenderBuffer
+		= (struct swrast_renderbuffer*)calloc(1, sizeof *swRenderBuffer);
+
+	if (!swRenderBuffer) {
+		ERROR("%s: Failed calloc RenderBuffer\n", __func__);
+		return NULL;
+	}
+
+	_mesa_init_renderbuffer(&swRenderBuffer->Base, 0);
+
+	swRenderBuffer->Base.ClassID = HAIKU_SWRAST_RENDERBUFFER_CLASS;
+	swRenderBuffer->Base.RefCount = 1;
+	swRenderBuffer->Base.Delete = _RenderBufferDelete;
+
+	if (!front)
+		swRenderBuffer->Base.AllocStorage = _RenderBufferStorageMalloc;
+	else
+		swRenderBuffer->Base.AllocStorage = _RenderBufferStorage;
+
+	if (_SetupRenderBuffer(&swRenderBuffer->Base, fColorSpace) != B_OK) {
+		free(swRenderBuffer);
+		return NULL;
+	}
+
+	return swRenderBuffer;
+}
+
+
+status_t
+MesaSoftwareRast::_SetupRenderBuffer(struct gl_renderbuffer* rb,
+	color_space colorSpace)
+{
+	CALLED();
+
+	rb->InternalFormat = GL_RGBA;
+
+	switch (colorSpace) {
+		case B_RGBA32:
+			rb->_BaseFormat = GL_RGBA;
+			rb->Format = MESA_FORMAT_ARGB8888;
+			break;
+		case B_RGB32:
+			rb->_BaseFormat = GL_RGB;
+			rb->Format = MESA_FORMAT_XRGB8888;
+			break;
+		case B_RGB24:
+			rb->_BaseFormat = GL_RGB;
+			rb->Format = MESA_FORMAT_RGB888;
+			break;
+		case B_RGB16:
+			rb->_BaseFormat = GL_RGB;
+			rb->Format = MESA_FORMAT_RGB565;
+			break;
+		case B_RGB15:
+			rb->_BaseFormat = GL_RGB;
+			rb->Format = MESA_FORMAT_ARGB1555;
+			break;
+		default:
+			fprintf(stderr, "Unsupported screen color space %s\n",
+				color_space_name(fColorSpace));
+			debugger("Unsupported OpenGL color space");
+			return B_ERROR;
+	}
+	return B_OK;
+}
+
+
+/*!	Y inverted Map RenderBuffer function
+	We use a BBitmap for storage which has Y inverted.
+	If the Mesa provided Map function ever allows external
+	control of this we can omit this function.
+*/
+void
+MesaSoftwareRast::_RenderBufferMap(gl_context *ctx,
+	struct gl_renderbuffer *rb, GLuint x, GLuint y, GLuint w, GLuint h,
+	GLbitfield mode, GLubyte **mapOut, GLint *rowStrideOut)
+{
+	if (rb->ClassID == HAIKU_SWRAST_RENDERBUFFER_CLASS) {
+		struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+		const GLuint bpp = _mesa_get_format_bytes(rb->Format);
+		GLint rowStride = rb->Width * bpp; // in Bytes
+
+		y = rb->Height - y - 1;
+
+		*rowStrideOut = -rowStride;
+		*mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
+	} else {
+		_swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
+			mapOut, rowStrideOut);
+	}
+}
+
+
+void
+MesaSoftwareRast::_RenderBufferDelete(struct gl_context *ctx,
+	struct gl_renderbuffer* rb)
+{
+	CALLED();
+	if (rb != NULL) {
+		struct swrast_renderbuffer *swRenderBuffer
+			= swrast_renderbuffer(rb);
+		if (swRenderBuffer != NULL)
+			free(swRenderBuffer->Buffer);
+	}
+	free(rb);
+}
+
+
+void
+MesaSoftwareRast::_CopyToDirect()
+{
+	BAutolock lock(fInfoLocker);
+
+	// 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())
+		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;
+		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; y++) {
+			memcpy(p, b, bytesWidth);
+			p += fInfo->bytes_per_row;
+			b += bytesPerRow;
+		}
+	}
+}
diff --git a/src/mesa/drivers/haiku/swrast/SoftwareRast.h b/src/mesa/drivers/haiku/swrast/SoftwareRast.h
new file mode 100644
index 0000000..8ef8493
--- /dev/null
+++ b/src/mesa/drivers/haiku/swrast/SoftwareRast.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2006-2012, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *		Jérôme Duval, korli at users.berlios.de
+ * 		Philippe Houdoin, philippe.houdoin at free.fr
+ *		Artur Wyszynski, harakash at gmail.com
+ */
+#ifndef MESASOFTWARERENDERER_H
+#define MESASOFTWARERENDERER_H
+
+
+#define HAIKU_SWRAST_RENDERBUFFER_CLASS 0x737752 // swR
+
+
+#include "GLRenderer.h"
+
+extern "C" {
+#include "context.h"
+#include "main/version.h"
+#include "swrast/s_chan.h"
+#include "swrast/s_context.h"
+}
+
+
+class MesaSoftwareRast : public BGLRenderer {
+public:
+							MesaSoftwareRast(BGLView* view,
+								ulong bgl_options,
+								BGLDispatcher* dispatcher);
+	virtual					~MesaSoftwareRast();
+
+	virtual	void			LockGL();
+	virtual	void 			UnlockGL();
+
+	virtual	void 			SwapBuffers(bool VSync = false);
+	virtual	void			Draw(BRect updateRect);
+	virtual	status_t		CopyPixelsOut(BPoint source, BBitmap* dest);
+	virtual	status_t		CopyPixelsIn(BBitmap* source, BPoint dest);
+	virtual void			FrameResized(float width, float height);
+
+	virtual	void			EnableDirectMode(bool enabled);
+	virtual	void			DirectConnected(direct_buffer_info* info);
+
+private:
+	static	const GLubyte*	_GetString(gl_context* ctx, GLenum name);
+			void			_CheckResize(GLuint newWidth, GLuint newHeight);
+	static	void			_UpdateState(gl_context* ctx, GLuint newState);
+	static	void			_Flush(gl_context *ctx);
+
+	struct	swrast_renderbuffer* _NewRenderBuffer(bool front);
+			status_t		_SetupRenderBuffer(struct gl_renderbuffer* rb,
+								color_space colorSpace);
+
+/* Mesa callbacks */
+	static	void			_RenderBufferDelete(struct gl_context *ctx,
+								struct gl_renderbuffer* rb);
+	static	GLboolean		_RenderBufferStorage(gl_context* ctx,
+								struct gl_renderbuffer* render,
+								GLenum internalFormat,
+								GLuint width, GLuint height);
+	static	GLboolean		_RenderBufferStorageMalloc(gl_context* ctx,
+								struct gl_renderbuffer* render,
+								GLenum internalFormat,
+								GLuint width, GLuint height);
+	static	void			_RenderBufferMap(gl_context *ctx,
+								struct gl_renderbuffer *rb,
+								GLuint x, GLuint y, GLuint w, GLuint h,
+								GLbitfield mode, GLubyte **mapOut,
+								GLint *rowStrideOut);
+
+			void			_AllocateBitmap();
+			void			_CopyToDirect();
+
+			BBitmap*		fBitmap;
+			bool			fDirectModeEnabled;
+			direct_buffer_info* fInfo;
+			BLocker			fInfoLocker;
+			ulong			fOptions;
+
+			gl_context*		fContext;
+			gl_config*		fVisual;
+
+			struct gl_framebuffer* fFrameBuffer;
+			struct swrast_renderbuffer* fFrontRenderBuffer;
+			struct swrast_renderbuffer* fBackRenderBuffer;
+
+			GLuint			fWidth;
+			GLuint			fHeight;
+			color_space		fColorSpace;
+
+			void*			fRowAddr[SWRAST_MAX_HEIGHT];
+};
+
+#endif	// MESASOFTWARERENDERER_H
diff --git a/src/mesa/drivers/haiku/swrast/SoftwareRast.rdef b/src/mesa/drivers/haiku/swrast/SoftwareRast.rdef
new file mode 100644
index 0000000..cb60332
--- /dev/null
+++ b/src/mesa/drivers/haiku/swrast/SoftwareRast.rdef
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+resource app_signature "application/x-vnd.Haiku-swrast";
+
+resource app_version {
+    major  = 9,
+    middle = 0,
+    minor  = 0,
+    variety = 0,
+    internal = 0,
+    short_info = "Software Rasterizer",
+    long_info = "Haiku Mesa Software GL Rasterizer"
+};
+
+resource vector_icon {
+	$"6E6369660A0200140294A9FF18020014028DFFFF97058C0500020006023B10B7"
+	$"37F036BA1A993D466848C719BEBE2000919292FFD5D5D5020016023900000000"
+	$"000000003EE0004AE00048E0005EF884C702000203392E8D383001BAD97F3C12"
+	$"8B4786BD48B8AD0D97BBFFFF7B4168DBE9FF4168DB97020002023A0C1238D099"
+	$"BE44203F4BD14B38844678240DF56A7D9FE1EA064CC704016B0500090A044024"
+	$"2438404C5C380A044028243C40505C3C0A042438243B5C3C5C380608BFBE4D59"
+	$"4D59515957575659585560406044603C5E3A5C3CCB4FBFBA5E3ECA9DC11F564B"
+	$"584A544C504C0606AF0F2F3D2F3D393D4034BF593542324130432F42364432C0"
+	$"3FBC5A2F48354A2F480608AE9A22303EB5BD3AB42542B755422E412F3C29322D"
+	$"32223C0204263726372538263F253E263F304430443143303C313D303C02043D"
+	$"423D423C433D4A3C493D4A495049504A4F49474A484947060DAEAAAE014E445A"
+	$"3456365E325E3D5D3F5A3A5542544E4D573A4E364439463342324A2242310A0A"
+	$"0002020102403CA00C88888C8CC1401673C40D6544F2950A01010002403CA000"
+	$"0000000000401673C40D65446CF80A08020304023EC16A0000000000003EC16A"
+	$"45DD1844C6550A030105123EC16A0000000000003EC16A45DD1844C655011784"
+	$"22040A040105023EC16A0000000000003EC16A45DD1844C6550A030108123EC1"
+	$"6A0000000000003EC16A45DD1844C65501178422040A0503080706023EC16A00"
+	$"00000000003EC16A45DD1844C6550A030206071A3EC16A0000000000003EC16A"
+	$"45DD1844C65510FF0215810004178222040A060106023EC16A0000000000003E"
+	$"C16A45DD1844C6550A070107023EC16A0000000000003EC16A45DD1844C655"
+};
-- 
1.7.9.5



More information about the mesa-dev mailing list