/*
- * Copyright (C) 2004-2006 Claudio Ciccani <klan@users.sf.net>
+ * Copyright (C) 2004-2007 Claudio Ciccani <klan@directfb.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Based on glfbdev.c, written by Brian Paul.
#include <stdlib.h>
#include <unistd.h>
+#include <pthread.h>
+
#include <directfb.h>
+#include <directfb_version.h>
+#include <directfbgl.h>
+
+#include <direct/mem.h>
#include <direct/messages.h>
#include <direct/interface.h>
-#include <direct/mem.h>
-#ifdef CLAMP
-# undef CLAMP
-#endif
-
-#include "GL/directfbgl.h"
+#undef CLAMP
#include "glheader.h"
#include "buffers.h"
#include "context.h"
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "drivers/common/driverfuncs.h"
+#define VERSION_CODE( M, m, r ) (((M) * 1000) + ((m) * 100) + ((r)))
+#define DIRECTFB_VERSION_CODE VERSION_CODE( DIRECTFB_MAJOR_VERSION, \
+ DIRECTFB_MINOR_VERSION, \
+ DIRECTFB_MICRO_VERSION )
+
+
static DFBResult
Probe( void *data );
int height;
struct {
- __u8 *start;
- __u8 *end;
+ GLubyte *start;
+ GLubyte *end;
int pitch;
} video;
struct gl_renderbuffer render;
} IDirectFBGL_data;
+/******************************************************************************/
+
+static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int global_ref = 0;
+
+static inline int directfbgl_init( void )
+{
+ pthread_mutexattr_t attr;
+ int ret;
+
+ if (global_ref++)
+ return 0;
+
+ pthread_mutexattr_init( &attr );
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK );
+ ret = pthread_mutex_init( &global_lock, &attr );
+ pthread_mutexattr_destroy( &attr );
+
+ return ret;
+}
+
+static inline void directfbgl_finish( void )
+{
+ if (--global_ref == 0)
+ pthread_mutex_destroy( &global_lock );
+}
+
+#define directfbgl_lock() pthread_mutex_lock( &global_lock )
+#define directfbgl_unlock() pthread_mutex_unlock( &global_lock )
+
+/******************************************************************************/
static bool directfbgl_init_visual ( GLvisual *visual,
DFBSurfacePixelFormat format );
static void directfbgl_destroy_context( GLcontext *context,
GLframebuffer *framebuffer );
+/******************************************************************************/
+
static void
-IDirectFBGL_Destruct( IDirectFBGL *thiz )
+IDirectFBGL_Mesa_Destruct( IDirectFBGL *thiz )
{
IDirectFBGL_data *data = (IDirectFBGL_data*) thiz->priv;
directfbgl_destroy_context( &data->context, &data->framebuffer );
- data->surface->Release( data->surface );
+ if (data->surface)
+ data->surface->Release( data->surface );
DIRECT_DEALLOCATE_INTERFACE( thiz );
+
+ directfbgl_finish();
}
static DFBResult
-IDirectFBGL_AddRef( IDirectFBGL *thiz )
+IDirectFBGL_Mesa_AddRef( IDirectFBGL *thiz )
{
DIRECT_INTERFACE_GET_DATA( IDirectFBGL );
}
static DFBResult
-IDirectFBGL_Release( IDirectFBGL *thiz )
+IDirectFBGL_Mesa_Release( IDirectFBGL *thiz )
{
DIRECT_INTERFACE_GET_DATA( IDirectFBGL )
- if (--data->ref == 0) {
- IDirectFBGL_Destruct( thiz );
- }
+ if (--data->ref == 0)
+ IDirectFBGL_Mesa_Destruct( thiz );
return DFB_OK;
}
static DFBResult
-IDirectFBGL_Lock( IDirectFBGL *thiz )
+IDirectFBGL_Mesa_Lock( IDirectFBGL *thiz )
{
IDirectFBSurface *surface;
int width = 0;
int height = 0;
- DFBResult err;
+ DFBResult ret;
DIRECT_INTERFACE_GET_DATA( IDirectFBGL );
- if (data->locked++)
+ if (data->locked) {
+ data->locked++;
return DFB_OK;
+ }
+
+ if (directfbgl_lock())
+ return DFB_LOCKED;
surface = data->surface;
surface->GetSize( surface, &width, &height );
- err = surface->Lock( surface, DSLF_READ | DSLF_WRITE,
+ ret = surface->Lock( surface, DSLF_READ | DSLF_WRITE,
(void*)&data->video.start, &data->video.pitch );
- if (err != DFB_OK) {
+ if (ret) {
D_ERROR( "DirectFBGL/Mesa: couldn't lock surface.\n" );
- return err;
+ directfbgl_unlock();
+ return ret;
}
data->video.end = data->video.start + (height-1) * data->video.pitch;
&data->framebuffer, &data->framebuffer );
if (data->width != width || data->height != height) {
+ _mesa_resize_framebuffer( &data->context,
+ &data->framebuffer, width, height );
data->width = width;
- data->height = height;
- _mesa_ResizeBuffersMESA();
+ data->height = height;
}
+
+ data->locked++;
return DFB_OK;
}
static DFBResult
-IDirectFBGL_Unlock( IDirectFBGL *thiz )
+IDirectFBGL_Mesa_Unlock( IDirectFBGL *thiz )
{
DIRECT_INTERFACE_GET_DATA( IDirectFBGL );
if (!data->locked)
return DFB_OK;
-
+
if (--data->locked == 0) {
_mesa_make_current( NULL, NULL, NULL );
+
data->surface->Unlock( data->surface );
- }
+ directfbgl_unlock();
+ }
+
return DFB_OK;
}
static DFBResult
-IDirectFBGL_GetAttributes( IDirectFBGL *thiz,
- DFBGLAttributes *attributes )
+IDirectFBGL_Mesa_GetAttributes( IDirectFBGL *thiz,
+ DFBGLAttributes *attributes )
{
DFBSurfaceCapabilities caps;
GLvisual *visual;
attributes->accum_green_size = visual->accumGreenBits;
attributes->accum_blue_size = visual->accumBlueBits;
attributes->accum_alpha_size = visual->accumAlphaBits;
- attributes->double_buffer = (caps & DSCAPS_FLIPPING) ? 1 : 0;
+ attributes->double_buffer = ((caps & DSCAPS_FLIPPING) != 0);
attributes->stereo = (visual->stereoMode != 0);
return DFB_OK;
}
+#if DIRECTFBGL_INTERFACE_VERSION >= 1
+static DFBResult
+IDirectFBGL_Mesa_GetProcAddress( IDirectFBGL *thiz,
+ const char *name,
+ void **ret_address )
+{
+ DIRECT_INTERFACE_GET_DATA( IDirectFBGL );
+
+ if (!name)
+ return DFB_INVARG;
+
+ if (!ret_address)
+ return DFB_INVARG;
+
+ *ret_address = _glapi_get_proc_address( name );
+
+ return (*ret_address) ? DFB_OK : DFB_UNSUPPORTED;
+}
+#endif
+
/* exported symbols */
}
static DFBResult
-Construct( IDirectFBGL *thiz,
- IDirectFBSurface *surface )
-{
+Construct( IDirectFBGL *thiz, IDirectFBSurface *surface )
+{
+ DFBResult ret;
+
+ /* Initialize global resources. */
+ if (directfbgl_init())
+ return DFB_INIT;
+
/* Allocate interface data. */
DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBGL );
-
+
/* Initialize interface data. */
- data->ref = 1;
- data->surface = surface;
+ data->ref = 1;
+
+ /* Duplicate destination surface. */
+ ret = surface->GetSubSurface( surface, NULL, &data->surface );
+ if (ret) {
+ IDirectFBGL_Mesa_Destruct( thiz );
+ return ret;
+ }
- surface->AddRef( surface );
- surface->GetPixelFormat( surface, &data->format );
- surface->GetSize( surface, &data->width, &data->height );
+ data->surface->GetPixelFormat( data->surface, &data->format );
+ data->surface->GetSize( data->surface, &data->width, &data->height );
/* Configure visual. */
if (!directfbgl_init_visual( &data->visual, data->format )) {
D_ERROR( "DirectFBGL/Mesa: failed to initialize visual.\n" );
- surface->Release( surface );
+ IDirectFBGL_Mesa_Destruct( thiz );
return DFB_UNSUPPORTED;
}
if (!directfbgl_create_context( &data->context, &data->framebuffer,
&data->visual, data->format, data )) {
D_ERROR( "DirectFBGL/Mesa: failed to create context.\n" );
- surface->Release( surface );
+ IDirectFBGL_Mesa_Destruct( thiz );
return DFB_UNSUPPORTED;
}
/* Assign interface pointers. */
- thiz->AddRef = IDirectFBGL_AddRef;
- thiz->Release = IDirectFBGL_Release;
- thiz->Lock = IDirectFBGL_Lock;
- thiz->Unlock = IDirectFBGL_Unlock;
- thiz->GetAttributes = IDirectFBGL_GetAttributes;
+ thiz->AddRef = IDirectFBGL_Mesa_AddRef;
+ thiz->Release = IDirectFBGL_Mesa_Release;
+ thiz->Lock = IDirectFBGL_Mesa_Lock;
+ thiz->Unlock = IDirectFBGL_Mesa_Unlock;
+ thiz->GetAttributes = IDirectFBGL_Mesa_GetAttributes;
+#if DIRECTFBGL_INTERFACE_VERSION >= 1
+ thiz->GetProcAddress = IDirectFBGL_Mesa_GetProcAddress;
+#endif
return DFB_OK;
}
static const GLubyte*
dfbGetString( GLcontext *ctx, GLenum pname )
{
- switch (pname) {
- case GL_VENDOR:
- return "Claudio Ciccani";
- default:
- return NULL;
- }
+ return NULL;
}
static void
{
_swrast_InvalidateState( ctx, new_state );
_swsetup_InvalidateState( ctx, new_state );
- _ac_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
}
*height = (GLuint) data->height;
}
+/**
+ * We only implement this function as a mechanism to check if the
+ * framebuffer size has changed (and update corresponding state).
+ */
static void
dfbSetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
{
- _mesa_ResizeBuffersMESA();
+ /* Nothing to do (the surface can't be resized while it's locked). */
+ return;
}
static void
-dfbClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
- GLint x, GLint y, GLint width, GLint height )
+dfbClear( GLcontext *ctx, GLbitfield mask )
{
IDirectFBGL_data *data = (IDirectFBGL_data*) ctx->DriverCtx;
-
- if (mask & BUFFER_BIT_FRONT_LEFT &&
- ctx->Color.ColorMask[0] &&
- ctx->Color.ColorMask[1] &&
- ctx->Color.ColorMask[2] &&
+
+#define BUFFER_BIT_MASK (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT | \
+ BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT )
+ if (mask & BUFFER_BIT_MASK &&
+ ctx->Color.ColorMask[0] &&
+ ctx->Color.ColorMask[1] &&
+ ctx->Color.ColorMask[2] &&
ctx->Color.ColorMask[3])
{
- __u8 a, r, g, b;
+ DFBRegion clip;
+ GLubyte a, r, g, b;
UNCLAMPED_FLOAT_TO_UBYTE( a, ctx->Color.ClearColor[ACOMP] );
UNCLAMPED_FLOAT_TO_UBYTE( r, ctx->Color.ClearColor[RCOMP] );
UNCLAMPED_FLOAT_TO_UBYTE( g, ctx->Color.ClearColor[GCOMP] );
UNCLAMPED_FLOAT_TO_UBYTE( b, ctx->Color.ClearColor[BCOMP] );
+ clip.x1 = ctx->DrawBuffer->_Xmin;
+ clip.y1 = ctx->DrawBuffer->_Ymin;
+ clip.x2 = ctx->DrawBuffer->_Xmax - 1;
+ clip.y2 = ctx->DrawBuffer->_Ymax - 1;
+ data->surface->SetClip( data->surface, &clip );
+
data->surface->Unlock( data->surface );
- if (all) {
- data->surface->SetClip( data->surface, NULL );
- data->surface->Clear( data->surface, r, g, b, a );
- }
- else {
- DFBRegion reg = { x1:x, y1:y, x2:x+width-1, y2:y+height-1 };
- data->surface->SetClip( data->surface, ® );
- data->surface->Clear( data->surface, r, g, b, a );
- data->surface->SetClip( data->surface, NULL );
- }
+ data->surface->Clear( data->surface, r, g, b, a );
data->surface->Lock( data->surface, DSLF_READ | DSLF_WRITE,
(void*)&data->video.start, &data->video.pitch );
+ data->video.end = data->video.start + (data->height-1) * data->video.pitch;
+ data->render.Data = data->video.start;
- mask &= ~BUFFER_BIT_FRONT_LEFT;
+ mask &= ~BUFFER_BIT_MASK;
}
+#undef BUFFER_BIT_MASK
if (mask)
- _swrast_Clear( ctx, mask, all, x, y, width, height );
-}
-
-
+ _swrast_Clear( ctx, mask );
+}
+
/************************ RenderBuffer functions *****************************/
}
_swrast_CreateContext( context );
- _ac_CreateContext( context );
+ _vbo_CreateContext( context );
_tnl_CreateContext( context );
_swsetup_CreateContext( context );
_swsetup_Wakeup( context );
data->render.GetRow = get_row_RGB332;
data->render.GetValues = get_values_RGB332;
data->render.PutRow = put_row_RGB332;
+ data->render.PutRowRGB = put_row_rgb_RGB332;
data->render.PutMonoRow = put_mono_row_RGB332;
data->render.PutValues = put_values_RGB332;
data->render.PutMonoValues = put_mono_values_RGB332;
data->render.GetRow = get_row_ARGB4444;
data->render.GetValues = get_values_ARGB4444;
data->render.PutRow = put_row_ARGB4444;
+ data->render.PutRowRGB = put_row_rgb_ARGB4444;
data->render.PutMonoRow = put_mono_row_ARGB4444;
data->render.PutValues = put_values_ARGB4444;
data->render.PutMonoValues = put_mono_values_ARGB4444;
data->render.GetRow = get_row_ARGB2554;
data->render.GetValues = get_values_ARGB2554;
data->render.PutRow = put_row_ARGB2554;
+ data->render.PutRowRGB = put_row_rgb_ARGB2554;
data->render.PutMonoRow = put_mono_row_ARGB2554;
data->render.PutValues = put_values_ARGB2554;
data->render.PutMonoValues = put_mono_values_ARGB2554;
data->render.GetRow = get_row_ARGB1555;
data->render.GetValues = get_values_ARGB1555;
data->render.PutRow = put_row_ARGB1555;
+ data->render.PutRowRGB = put_row_rgb_ARGB1555;
data->render.PutMonoRow = put_mono_row_ARGB1555;
data->render.PutValues = put_values_ARGB1555;
data->render.PutMonoValues = put_mono_values_ARGB1555;
data->render.GetRow = get_row_RGB16;
data->render.GetValues = get_values_RGB16;
data->render.PutRow = put_row_RGB16;
+ data->render.PutRowRGB = put_row_rgb_RGB16;
data->render.PutMonoRow = put_mono_row_RGB16;
data->render.PutValues = put_values_RGB16;
data->render.PutMonoValues = put_mono_values_RGB16;
data->render.GetRow = get_row_RGB24;
data->render.GetValues = get_values_RGB24;
data->render.PutRow = put_row_RGB24;
+ data->render.PutRowRGB = put_row_rgb_RGB24;
data->render.PutMonoRow = put_mono_row_RGB24;
data->render.PutValues = put_values_RGB24;
data->render.PutMonoValues = put_mono_values_RGB24;
data->render.GetRow = get_row_RGB32;
data->render.GetValues = get_values_RGB32;
data->render.PutRow = put_row_RGB32;
+ data->render.PutRowRGB = put_row_rgb_RGB32;
data->render.PutMonoRow = put_mono_row_RGB32;
data->render.PutValues = put_values_RGB32;
data->render.PutMonoValues = put_mono_values_RGB32;
data->render.GetRow = get_row_ARGB;
data->render.GetValues = get_values_ARGB;
data->render.PutRow = put_row_ARGB;
+ data->render.PutRowRGB = put_row_rgb_ARGB;
data->render.PutMonoRow = put_mono_row_ARGB;
data->render.PutValues = put_values_ARGB;
data->render.PutMonoValues = put_mono_values_ARGB;
data->render.GetRow = get_row_AiRGB;
data->render.GetValues = get_values_AiRGB;
data->render.PutRow = put_row_AiRGB;
+ data->render.PutRowRGB = put_row_rgb_AiRGB;
data->render.PutMonoRow = put_mono_row_AiRGB;
data->render.PutValues = put_values_AiRGB;
data->render.PutMonoValues = put_mono_values_AiRGB;