summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/common/crOpenGL/vboxdri_drv.c')
-rw-r--r--src/VBox/Additions/common/crOpenGL/vboxdri_drv.c694
1 files changed, 694 insertions, 0 deletions
diff --git a/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c b/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c
new file mode 100644
index 00000000..e82975e3
--- /dev/null
+++ b/src/VBox/Additions/common/crOpenGL/vboxdri_drv.c
@@ -0,0 +1,694 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Minimal swrast-based dri loadable driver.
+ *
+ * Todo:
+ * -- Use malloced (rather than framebuffer) memory for backbuffer
+ * -- 32bpp is hardwired -- fix
+ *
+ * NOTES:
+ * -- No mechanism for cliprects or resize notification --
+ * assumes this is a fullscreen device.
+ * -- No locking -- assumes this is the only driver accessing this
+ * device.
+ * -- Doesn't (yet) make use of any acceleration or other interfaces
+ * provided by fb. Would be entirely happy working against any
+ * fullscreen interface.
+ * -- HOWEVER: only a small number of pixelformats are supported, and
+ * the mechanism for choosing between them makes some assumptions
+ * that may not be valid everywhere.
+ */
+
+#include "driver.h"
+#include "drm.h"
+#include "utils.h"
+#include "drirenderbuffer.h"
+
+#include "buffers.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+
+#define need_GL_VERSION_1_3
+#define need_GL_VERSION_1_4
+#define need_GL_VERSION_1_5
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+
+/* sw extensions for imaging */
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_convolution
+#define need_GL_EXT_histogram
+#define need_GL_SGI_color_table
+
+/* sw extensions not associated with some GL version */
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_vertex_program
+#define need_GL_APPLE_vertex_array_object
+#define need_GL_ATI_fragment_shader
+#define need_GL_EXT_depth_bounds_test
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_paletted_texture
+#define need_GL_IBM_multimode_draw_arrays
+#define need_GL_MESA_resize_buffers
+#define need_GL_NV_vertex_program
+#define need_GL_NV_fragment_program
+
+#include "extension_helper.h"
+
+const struct dri_extension card_extensions[] =
+{
+ { "GL_VERSION_1_3", GL_VERSION_1_3_functions },
+ { "GL_VERSION_1_4", GL_VERSION_1_4_functions },
+ { "GL_VERSION_1_5", GL_VERSION_1_5_functions },
+ { "GL_VERSION_2_0", GL_VERSION_2_0_functions },
+ { "GL_VERSION_2_1", GL_VERSION_2_1_functions },
+
+ { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
+ { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
+ { "GL_EXT_convolution", GL_EXT_convolution_functions },
+ { "GL_EXT_histogram", GL_EXT_histogram_functions },
+ { "GL_SGI_color_table", GL_SGI_color_table_functions },
+
+ { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
+ { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
+ { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+ { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
+ { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
+ { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
+ { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { "GL_NV_fragment_program", GL_NV_fragment_program_functions },
+ { NULL, NULL }
+};
+
+void fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis);
+
+typedef struct {
+ GLcontext *glCtx; /* Mesa context */
+
+ struct {
+ __DRIcontextPrivate *context;
+ __DRIscreenPrivate *screen;
+ __DRIdrawablePrivate *drawable; /* drawable bound to this ctx */
+ } dri;
+
+} fbContext, *fbContextPtr;
+
+#define FB_CONTEXT(ctx) ((fbContextPtr)(ctx->DriverCtx))
+
+
+static const GLubyte *
+get_string(GLcontext *ctx, GLenum pname)
+{
+ (void) ctx;
+ switch (pname) {
+ case GL_RENDERER:
+ return (const GLubyte *) "Mesa dumb framebuffer";
+ default:
+ return NULL;
+ }
+}
+
+
+static void
+update_state( GLcontext *ctx, GLuint new_state )
+{
+ /* not much to do here - pass it on */
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+
+/**
+ * Called by ctx->Driver.GetBufferSize from in core Mesa to query the
+ * current framebuffer size.
+ */
+static void
+get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ fbContextPtr fbmesa = FB_CONTEXT(ctx);
+
+ *width = fbmesa->dri.drawable->w;
+ *height = fbmesa->dri.drawable->h;
+}
+
+
+static void
+updateFramebufferSize(GLcontext *ctx)
+{
+ fbContextPtr fbmesa = FB_CONTEXT(ctx);
+ struct gl_framebuffer *fb = ctx->WinSysDrawBuffer;
+ if (fbmesa->dri.drawable->w != fb->Width ||
+ fbmesa->dri.drawable->h != fb->Height) {
+ driUpdateFramebufferSize(ctx, fbmesa->dri.drawable);
+ }
+}
+
+static void
+viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ /* XXX this should be called after we acquire the DRI lock, not here */
+ updateFramebufferSize(ctx);
+}
+
+
+static void
+init_core_functions( struct dd_function_table *functions )
+{
+ functions->GetString = get_string;
+ functions->UpdateState = update_state;
+ functions->GetBufferSize = get_buffer_size;
+ functions->Viewport = viewport;
+
+ functions->Clear = _swrast_Clear; /* could accelerate with blits */
+}
+
+
+/*
+ * Generate code for span functions.
+ */
+
+/* 24-bit BGR */
+#define NAME(PREFIX) PREFIX##_B8G8R8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ driRenderbuffer *drb = (driRenderbuffer *) rb;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 3;
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = VALUE[BCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[RCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = 0xff
+
+#include "swrast/s_spantemp.h"
+
+
+/* 32-bit BGRA */
+#define NAME(PREFIX) PREFIX##_B8G8R8A8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ driRenderbuffer *drb = (driRenderbuffer *) rb;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 4;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = VALUE[BCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[0] = VALUE[BCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[3] = 0xff
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = SRC[3]
+
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G6R5
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ driRenderbuffer *drb = (driRenderbuffer *) rb;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2;
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = ( (((SRC[0]) >> 8) & 0xf8) | (((SRC[0]) >> 11) & 0x7) ); \
+ DST[GCOMP] = ( (((SRC[0]) >> 3) & 0xfc) | (((SRC[0]) >> 5) & 0x3) ); \
+ DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
+ DST[ACOMP] = 0xff
+
+#include "swrast/s_spantemp.h"
+
+
+/* 15-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G5R5
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ driRenderbuffer *drb = (driRenderbuffer *) rb;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X) * 2;
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = ( (((VALUE[RCOMP]) & 0xf8) << 7) | (((VALUE[GCOMP]) & 0xf8) << 2) | ((VALUE[BCOMP]) >> 3) )
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = ( (((SRC[0]) >> 7) & 0xf8) | (((SRC[0]) >> 10) & 0x7) ); \
+ DST[GCOMP] = ( (((SRC[0]) >> 2) & 0xf8) | (((SRC[0]) >> 5) & 0x7) ); \
+ DST[BCOMP] = ( (((SRC[0]) << 3) & 0xf8) | (((SRC[0]) ) & 0x7) ); \
+ DST[ACOMP] = 0xff
+
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit color index */
+#define NAME(PREFIX) PREFIX##_CI8
+#define CI_MODE
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ driRenderbuffer *drb = (driRenderbuffer *) rb;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)drb->Base.Data + (drb->Base.Height - (Y)) * drb->pitch + (X);
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ *DST = VALUE[0]
+#define FETCH_PIXEL(DST, SRC) \
+ DST = SRC[0]
+
+#include "swrast/s_spantemp.h"
+
+
+
+void
+fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
+{
+ ASSERT(drb->Base.InternalFormat == GL_RGBA);
+ if (drb->Base.InternalFormat == GL_RGBA) {
+ if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
+ drb->Base.GetRow = get_row_B5G6R5;
+ drb->Base.GetValues = get_values_B5G6R5;
+ drb->Base.PutRow = put_row_B5G6R5;
+ drb->Base.PutMonoRow = put_mono_row_B5G6R5;
+ drb->Base.PutRowRGB = put_row_rgb_B5G6R5;
+ drb->Base.PutValues = put_values_B5G6R5;
+ drb->Base.PutMonoValues = put_mono_values_B5G6R5;
+ }
+ else if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) {
+ drb->Base.GetRow = get_row_B5G5R5;
+ drb->Base.GetValues = get_values_B5G5R5;
+ drb->Base.PutRow = put_row_B5G5R5;
+ drb->Base.PutMonoRow = put_mono_row_B5G5R5;
+ drb->Base.PutRowRGB = put_row_rgb_B5G5R5;
+ drb->Base.PutValues = put_values_B5G5R5;
+ drb->Base.PutMonoValues = put_mono_values_B5G5R5;
+ }
+ else if (vis->redBits == 8 && vis->greenBits == 8 && vis->blueBits == 8
+ && vis->alphaBits == 8) {
+ drb->Base.GetRow = get_row_B8G8R8A8;
+ drb->Base.GetValues = get_values_B8G8R8A8;
+ drb->Base.PutRow = put_row_B8G8R8A8;
+ drb->Base.PutMonoRow = put_mono_row_B8G8R8A8;
+ drb->Base.PutRowRGB = put_row_rgb_B8G8R8A8;
+ drb->Base.PutValues = put_values_B8G8R8A8;
+ drb->Base.PutMonoValues = put_mono_values_B8G8R8A8;
+ }
+ else if (vis->redBits == 8 && vis->greenBits == 8 && vis->blueBits == 8
+ && vis->alphaBits == 0) {
+ drb->Base.GetRow = get_row_B8G8R8;
+ drb->Base.GetValues = get_values_B8G8R8;
+ drb->Base.PutRow = put_row_B8G8R8;
+ drb->Base.PutMonoRow = put_mono_row_B8G8R8;
+ drb->Base.PutRowRGB = put_row_rgb_B8G8R8;
+ drb->Base.PutValues = put_values_B8G8R8;
+ drb->Base.PutMonoValues = put_mono_values_B8G8R8;
+ }
+ else if (vis->indexBits == 8) {
+ drb->Base.GetRow = get_row_CI8;
+ drb->Base.GetValues = get_values_CI8;
+ drb->Base.PutRow = put_row_CI8;
+ drb->Base.PutMonoRow = put_mono_row_CI8;
+ drb->Base.PutValues = put_values_CI8;
+ drb->Base.PutMonoValues = put_mono_values_CI8;
+ }
+ }
+ else {
+ /* hardware z/stencil/etc someday */
+ }
+}
+
+
+static void
+fbDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+}
+
+
+static const __DRIconfig **fbFillInModes(unsigned pixel_bits,
+ unsigned depth_bits,
+ unsigned stencil_bits,
+ GLboolean have_back_buffer)
+{
+ unsigned deep = (depth_bits > 17);
+
+ /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
+ * enough to add support. Basically, if a context is created with an
+ * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
+ * will never be used.
+ */
+
+ static const GLenum db_modes[2] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML };
+ uint8_t depth_bits_array[4];
+ uint8_t stencil_bits_array[4];
+ if(deep) {
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = 24;
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 8;
+ } else {
+ depth_bits_array[0] = depth_bits;
+ depth_bits_array[1] = 0;
+ depth_bits_array[2] = depth_bits;
+ depth_bits_array[3] = 0;
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 0;
+ stencil_bits_array[2] = 8;
+ stencil_bits_array[3] = 8;
+ }
+
+ return driCreateConfigs(
+ deep ? GL_RGBA : GL_RGB,
+ deep ? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array,
+ stencil_bits_array,
+ deep ? 2 : 4,
+ db_modes, 2);
+}
+
+/**
+ * This is the driver specific part of the createNewScreen entry point.
+ * Called when using legacy DRI.
+ *
+ * return the __GLcontextModes supported by this driver
+ */
+static const __DRIconfig **fbInitScreen(__DRIscreenPrivate *psp)
+{
+ static const __DRIversion ddx_expected = { 1, 0, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 1, 0, 0 };
+
+
+ if ( ! driCheckDriDdxDrmVersions2( "vboxvideo",
+ & psp->dri_version, & dri_expected,
+ & psp->ddx_version, & ddx_expected,
+ & psp->drm_version, & drm_expected ) ) {
+ return NULL;
+ }
+
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+
+ return fbFillInModes( psp->fbBPP,
+ (psp->fbBPP == 16) ? 16 : 24,
+ (psp->fbBPP == 16) ? 0 : 8,
+ 1);
+}
+
+/* Create the device specific context.
+ */
+static GLboolean
+fbCreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate)
+{
+ fbContextPtr fbmesa;
+ GLcontext *ctx, *shareCtx;
+ struct dd_function_table functions;
+
+ assert(glVisual);
+ assert(driContextPriv);
+
+ /* Allocate the Fb context */
+ fbmesa = (fbContextPtr) _mesa_calloc( sizeof(*fbmesa) );
+ if ( !fbmesa )
+ return GL_FALSE;
+
+ /* Init default driver functions then plug in our FBdev-specific functions
+ */
+ _mesa_init_driver_functions(&functions);
+ init_core_functions(&functions);
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((fbContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+
+ ctx = fbmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
+ &functions, (void *) fbmesa);
+ if (!fbmesa->glCtx) {
+ _mesa_free(fbmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = fbmesa;
+
+ /* Create module contexts */
+ _swrast_CreateContext( ctx );
+ _vbo_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+ _swsetup_Wakeup( ctx );
+
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(ctx);
+
+ return GL_TRUE;
+}
+
+
+static void
+fbDestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ fbContextPtr fbmesa = (fbContextPtr) driContextPriv->driverPrivate;
+ fbContextPtr current = ctx ? FB_CONTEXT(ctx) : NULL;
+
+ /* check if we're deleting the currently bound context */
+ if (fbmesa == current) {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+
+ /* Free fb context resources */
+ if ( fbmesa ) {
+ _swsetup_DestroyContext( fbmesa->glCtx );
+ _tnl_DestroyContext( fbmesa->glCtx );
+ _vbo_DestroyContext( fbmesa->glCtx );
+ _swrast_DestroyContext( fbmesa->glCtx );
+
+ /* free the Mesa context */
+ fbmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context( fbmesa->glCtx );
+
+ _mesa_free( fbmesa );
+ }
+}
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+fbCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ struct gl_framebuffer *mesa_framebuffer;
+
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ const GLboolean swDepth = mesaVis->depthBits > 0;
+ const GLboolean swAlpha = mesaVis->alphaBits > 0;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0;
+
+ mesa_framebuffer = _mesa_create_framebuffer(mesaVis);
+ if (!mesa_framebuffer)
+ return 0;
+
+ /* XXX double-check these parameters (bpp vs cpp, etc) */
+ {
+ driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA,
+ driScrnPriv->pFB,
+ driScrnPriv->fbBPP / 8,
+ driScrnPriv->fbOrigin,
+ driScrnPriv->fbStride,
+ driDrawPriv);
+ fbSetSpanFunctions(drb, mesaVis);
+ _mesa_add_renderbuffer(mesa_framebuffer,
+ BUFFER_FRONT_LEFT, &drb->Base);
+ }
+ if (mesaVis->doubleBufferMode) {
+ /* XXX what are the correct origin/stride values? */
+ GLvoid *backBuf = _mesa_malloc(driScrnPriv->fbStride
+ * driScrnPriv->fbHeight);
+ driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA,
+ backBuf,
+ driScrnPriv->fbBPP /8,
+ driScrnPriv->fbOrigin,
+ driScrnPriv->fbStride,
+ driDrawPriv);
+ fbSetSpanFunctions(drb, mesaVis);
+ _mesa_add_renderbuffer(mesa_framebuffer,
+ BUFFER_BACK_LEFT, &drb->Base);
+ }
+
+ _mesa_add_soft_renderbuffers(mesa_framebuffer,
+ GL_FALSE, /* color */
+ swDepth,
+ swStencil,
+ swAccum,
+ swAlpha, /* or always zero? */
+ GL_FALSE /* aux */);
+
+ driDrawPriv->driverPrivate = mesa_framebuffer;
+
+ return 1;
+ }
+}
+
+
+static void
+fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+}
+
+
+
+/* If the backbuffer is on a videocard, this is extraordinarily slow!
+ */
+static void
+fbSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+ struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)dPriv->driverPrivate;
+ struct gl_renderbuffer * front_renderbuffer = mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ void *frontBuffer = front_renderbuffer->Data;
+ int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch;
+ void *backBuffer = mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data;
+
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ fbContextPtr fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate;
+ GLcontext *ctx = fbmesa->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ int i;
+ int offset = 0;
+ char *tmp = _mesa_malloc(currentPitch);
+
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering commands */
+
+ ASSERT(frontBuffer);
+ ASSERT(backBuffer);
+
+ for (i = 0; i < dPriv->h; i++) {
+ _mesa_memcpy(tmp, (char *) backBuffer + offset,
+ currentPitch);
+ _mesa_memcpy((char *) frontBuffer + offset, tmp,
+ currentPitch);
+ offset += currentPitch;
+ }
+
+ _mesa_free(tmp);
+ }
+ }
+ else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n");
+ }
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+static GLboolean
+fbMakeCurrent( __DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv )
+{
+ if ( driContextPriv ) {
+ fbContextPtr newFbCtx =
+ (fbContextPtr) driContextPriv->driverPrivate;
+
+ newFbCtx->dri.drawable = driDrawPriv;
+
+ _mesa_make_current( newFbCtx->glCtx,
+ driDrawPriv->driverPrivate,
+ driReadPriv->driverPrivate);
+ } else {
+ _mesa_make_current( NULL, NULL, NULL );
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+static GLboolean
+fbUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
+
+const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = fbInitScreen,
+ .DestroyScreen = fbDestroyScreen,
+ .CreateContext = fbCreateContext,
+ .DestroyContext = fbDestroyContext,
+ .CreateBuffer = fbCreateBuffer,
+ .DestroyBuffer = fbDestroyBuffer,
+ .SwapBuffers = fbSwapBuffers,
+ .MakeCurrent = fbMakeCurrent,
+ .UnbindContext = fbUnbindContext,
+};