diff options
Diffstat (limited to 'src/VBox/Additions/common/crOpenGL/vboxdri_drv.c')
-rw-r--r-- | src/VBox/Additions/common/crOpenGL/vboxdri_drv.c | 694 |
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, +}; |