aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/Mesa/src/mesa/drivers/dri/fb
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/fb')
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Doxyfile232
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Makefile21
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_dri.c786
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c881
4 files changed, 1920 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Doxyfile b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Doxyfile
new file mode 100644
index 000000000..31256db83
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Doxyfile
@@ -0,0 +1,232 @@
+# Doxyfile 1.3.2-Gideon
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = fb
+PROJECT_NUMBER = $VERSION$
+OUTPUT_DIRECTORY =
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+SHORT_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES =
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SHOW_USED_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /home/temp/Mesa/src/drv/fb
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.moc \
+ *.xpm
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = yes
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+CGI_NAME = search.cgi
+CGI_URL =
+DOC_URL =
+DOC_ABSPATH =
+BIN_ABSPATH = /usr/local/bin/
+EXT_DOC_PATHS =
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Makefile b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Makefile
new file mode 100644
index 000000000..12465c9f4
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/Makefile
@@ -0,0 +1,21 @@
+# src/mesa/drivers/dri/fb/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = fb_dri.so
+
+DRIVER_SOURCES = \
+ fb_dri.c \
+ fb_egl.c
+
+C_SOURCES = \
+ $(COMMON_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+include ../Makefile.template
+
+symlinks:
+
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_dri.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_dri.c
new file mode 100644
index 000000000..e2ba66d2e
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_dri.c
@@ -0,0 +1,786 @@
+/*
+ * 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 hardwared -- 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 "array_cache/acache.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"
+
+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 );
+ _ac_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
+viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ _mesa_ResizeBuffersMESA();
+}
+
+
+static void
+init_core_functions( struct dd_function_table *functions )
+{
+ functions->GetString = get_string;
+ functions->UpdateState = update_state;
+ functions->ResizeBuffers = _mesa_resize_framebuffer;
+ 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 FORMAT GL_RGBA8
+#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 FORMAT GL_RGBA8
+#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 FORMAT GL_RGBA8
+#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 FORMAT GL_RGBA8
+#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 FORMAT GL_COLOR_INDEX8_EXT
+#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 */
+ }
+}
+
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+fbInitDriver( __DRIscreenPrivate *sPriv )
+{
+ sPriv->private = NULL;
+ return GL_TRUE;
+}
+
+static void
+fbDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+}
+
+void fbSetBuffer( GLcontext *ctx,
+ GLframebuffer *colorBuffer,
+ GLuint bufferBit )
+{
+ /* NOP until SetBuffer is fully removed */
+}
+
+/* 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 );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+ _swsetup_Wakeup( ctx );
+
+
+ /* swrast init -- need to verify these tests - I just plucked the
+ * numbers out of the air. (KW)
+ */
+ {
+ struct swrast_device_driver *swdd;
+ swdd = _swrast_GetDeviceDriverReference( ctx );
+ swdd->SetBuffer = fbSetBuffer;
+ }
+
+ /* 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 );
+ _ac_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->fbBPP / 8,
+ driScrnPriv->fbOrigin,
+ driScrnPriv->fbStride);
+ fbSetSpanFunctions(drb, mesaVis);
+ drb->Base.Data = driScrnPriv->pFB;
+ _mesa_add_renderbuffer(mesa_framebuffer,
+ BUFFER_FRONT_LEFT, &drb->Base);
+ }
+ if (mesaVis->doubleBufferMode) {
+ /* XXX what are the correct origin/stride values? */
+ driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, driScrnPriv->fbBPP /8,
+ driScrnPriv->fbOrigin,
+ driScrnPriv->fbStride);
+ fbSetSpanFunctions(drb, mesaVis);
+ drb->Base.Data = _mesa_malloc(driScrnPriv->fbStride * driScrnPriv->fbHeight);
+ _mesa_add_renderbuffer(mesa_framebuffer,
+ BUFFER_BACK_LEFT, &drb->Base);
+ }
+
+ _mesa_add_soft_renderbuffers(mesa_framebuffer,
+ GL_FALSE, /* color */
+ swDepth,
+ swStencil,
+ swAccum,
+ 0,
+ GL_FALSE /* aux */);
+
+ driDrawPriv->driverPrivate = mesa_framebuffer;
+
+ return 1;
+ }
+}
+
+
+static void
+fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)driDrawPriv->driverPrivate;
+
+ _mesa_free(mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data);
+ _mesa_destroy_framebuffer(mesa_framebuffer);
+ driDrawPriv->driverPrivate = NULL;
+}
+
+
+
+/* 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 comands */
+
+ 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;
+}
+
+static struct __DriverAPIRec fbAPI = {
+ .InitDriver = fbInitDriver,
+ .DestroyScreen = fbDestroyScreen,
+ .CreateContext = fbCreateContext,
+ .DestroyContext = fbDestroyContext,
+ .CreateBuffer = fbCreateBuffer,
+ .DestroyBuffer = fbDestroyBuffer,
+ .SwapBuffers = fbSwapBuffers,
+ .MakeCurrent = fbMakeCurrent,
+ .UnbindContext = fbUnbindContext,
+};
+
+
+
+static int
+__driValidateMode(const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+static int
+__driInitFBDev( struct DRIDriverContextRec *ctx )
+{
+ /* Note that drmOpen will try to load the kernel module, if needed. */
+ /* we need a fbdev drm driver - it will only track maps */
+ ctx->drmFD = drmOpen("radeon", NULL );
+ if (ctx->drmFD < 0) {
+ fprintf(stderr, "[drm] drmOpen failed\n");
+ return 0;
+ }
+
+ ctx->shared.SAREASize = SAREA_MAX;
+
+ if (drmAddMap( ctx->drmFD,
+ 0,
+ ctx->shared.SAREASize,
+ DRM_SHM,
+ DRM_CONTAINS_LOCK,
+ &ctx->shared.hSAREA) < 0)
+ {
+ fprintf(stderr, "[drm] drmAddMap failed\n");
+ return 0;
+ }
+ fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
+ ctx->shared.SAREASize, ctx->shared.hSAREA);
+
+ if (drmMap( ctx->drmFD,
+ ctx->shared.hSAREA,
+ ctx->shared.SAREASize,
+ (drmAddressPtr)(&ctx->pSAREA)) < 0)
+ {
+ fprintf(stderr, "[drm] drmMap failed\n");
+ return 0;
+ }
+ memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
+ fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
+ ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
+
+ /* Need to AddMap the framebuffer and mmio regions here:
+ */
+ if (drmAddMap( ctx->drmFD,
+ (drm_handle_t)ctx->FBStart,
+ ctx->FBSize,
+ DRM_FRAME_BUFFER,
+#ifndef _EMBEDDED
+ 0,
+#else
+ DRM_READ_ONLY,
+#endif
+ &ctx->shared.hFrameBuffer) < 0)
+ {
+ fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
+ return 0;
+ }
+
+ fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
+ ctx->shared.hFrameBuffer);
+
+ return 1;
+}
+
+static void
+__driHaltFBDev( struct DRIDriverContextRec *ctx )
+{
+}
+
+struct DRIDriverRec __driDriver = {
+ __driValidateMode,
+ __driValidateMode,
+ __driInitFBDev,
+ __driHaltFBDev
+};
+
+static __GLcontextModes *
+fbFillInModes( unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer )
+{
+ __GLcontextModes * modes;
+ __GLcontextModes * m;
+ unsigned num_modes;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* 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 back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
+ };
+
+ u_int8_t depth_bits_array[2];
+ u_int8_t stencil_bits_array[2];
+
+
+ depth_bits_array[0] = depth_bits;
+ depth_bits_array[1] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer. It will be a sw fallback, but some apps won't
+ * care about that.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
+ back_buffer_factor = (have_back_buffer) ? 2 : 1;
+
+ num_modes = depth_buffer_factor * back_buffer_factor * 4;
+
+ if ( pixel_bits == 16 ) {
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ else {
+ fb_format = GL_RGBA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
+ m = modes;
+ if ( ! driFillInModes( & m, fb_format, fb_type,
+ depth_bits_array, stencil_bits_array, depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ GLX_TRUE_COLOR ) ) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ if ( ! driFillInModes( & m, fb_format, fb_type,
+ depth_bits_array, stencil_bits_array, depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ GLX_DIRECT_COLOR ) ) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ /* Mark the visual as slow if there are "fake" stencil bits.
+ */
+ for ( m = modes ; m != NULL ; m = m->next ) {
+ if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
+ m->visualRating = GLX_SLOW_CONFIG;
+ }
+ }
+
+ return modes;
+}
+
+
+/**
+ * This is the bootstrap function for the driver. libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c __GLcontextModes that the driver can support for windows or
+ * pbuffers.
+ *
+ * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
+ * failure.
+ */
+PUBLIC
+void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
+ const __GLcontextModes * modes,
+ const __DRIversion * ddx_version,
+ const __DRIversion * dri_version,
+ const __DRIversion * drm_version,
+ const __DRIframebuffer * frame_buffer,
+ drmAddress pSAREA, int fd,
+ int internal_api_version,
+ __GLcontextModes ** driver_modes )
+{
+ __DRIscreenPrivate *psp;
+ static const __DRIversion ddx_expected = { 4, 0, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 1, 5, 0 };
+
+
+ if ( ! driCheckDriDdxDrmVersions2( "fb",
+ dri_version, & dri_expected,
+ ddx_version, & ddx_expected,
+ drm_version, & drm_expected ) ) {
+ return NULL;
+ }
+
+ psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+ ddx_version, dri_version, drm_version,
+ frame_buffer, pSAREA, fd,
+ internal_api_version, &fbAPI);
+ if ( psp != NULL ) {
+ *driver_modes = fbFillInModes( psp->fbBPP,
+ (psp->fbBPP == 16) ? 16 : 24,
+ (psp->fbBPP == 16) ? 0 : 8,
+ 1);
+ }
+
+ return (void *) psp;
+}
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c
new file mode 100644
index 000000000..2cea48808
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/fb/fb_egl.c
@@ -0,0 +1,881 @@
+/*
+ * Test egl driver for fb_dri.so
+ */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+
+#include "utils.h"
+#include "buffers.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "array_cache/acache.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"
+#include "drirenderbuffer.h"
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglmode.h"
+#include "eglscreen.h"
+#include "eglsurface.h"
+
+extern void
+fbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis);
+extern void
+fbSetBuffer( GLcontext *ctx, GLframebuffer *colorBuffer, GLuint bufferBit);
+
+/**
+ * fb driver-specific driver class derived from _EGLDriver
+ */
+typedef struct fb_driver
+{
+ _EGLDriver Base; /* base class/object */
+ GLuint fbStuff;
+} fbDriver;
+
+/**
+ * fb display-specific driver class derived from _EGLDisplay
+ */
+typedef struct fb_display
+{
+ _EGLDisplay Base; /* base class/object */
+ void *pFB;
+} fbDisplay;
+
+/**
+ * fb driver-specific screen class derived from _EGLScreen
+ */
+typedef struct fb_screen
+{
+ _EGLScreen Base;
+ char fb[NAME_MAX];
+} fbScreen;
+
+
+/**
+ * fb driver-specific surface class derived from _EGLSurface
+ */
+typedef struct fb_surface
+{
+ _EGLSurface Base; /* base class/object */
+ struct gl_framebuffer *mesa_framebuffer;
+} fbSurface;
+
+
+/**
+ * fb driver-specific context class derived from _EGLContext
+ */
+typedef struct fb_context
+{
+ _EGLContext Base; /* base class/object */
+ GLcontext *glCtx;
+} fbContext;
+
+
+static EGLBoolean
+fbFillInConfigs(_EGLDisplay *disp, unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer) {
+ _EGLConfig *configs;
+ _EGLConfig *c;
+ unsigned int i, num_configs;
+ unsigned int depth_buffer_factor;
+ unsigned int back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* 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 back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
+ };
+
+ u_int8_t depth_bits_array[2];
+ u_int8_t stencil_bits_array[2];
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer. It will be a sw fallback, but some apps won't
+ * care about that.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
+ back_buffer_factor = (have_back_buffer) ? 2 : 1;
+
+ num_configs = depth_buffer_factor * back_buffer_factor * 2;
+
+ if (pixel_bits == 16) {
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ } else {
+ fb_format = GL_RGBA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ configs = calloc(sizeof(*configs), num_configs);
+ c = configs;
+ if (!_eglFillInConfigs(c, fb_format, fb_type,
+ depth_bits_array, stencil_bits_array, depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ GLX_TRUE_COLOR)) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__);
+ return EGL_FALSE;
+ }
+
+ /* Mark the visual as slow if there are "fake" stencil bits.
+ */
+ for (i = 0, c = configs; i < num_configs; i++, c++) {
+ int stencil = GET_CONFIG_ATTRIB(c, EGL_STENCIL_SIZE);
+ if ((stencil != 0) && (stencil != stencil_bits)) {
+ SET_CONFIG_ATTRIB(c, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
+ }
+ }
+
+ for (i = 0, c = configs; i < num_configs; i++, c++)
+ _eglAddConfig(disp, c);
+
+ free(configs);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+fbSetupFramebuffer(fbDisplay *disp, char *fbdev)
+{
+ int fd;
+ char dev[20];
+ struct fb_var_screeninfo varInfo;
+ struct fb_fix_screeninfo fixedInfo;
+
+ snprintf(dev, sizeof(dev), "/dev/%s", fbdev);
+
+ /* open the framebuffer device */
+ fd = open(dev, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Error opening %s: %s\n", fbdev, strerror(errno));
+ return EGL_FALSE;
+ }
+
+ /* get the original variable screen info */
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &varInfo)) {
+ fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
+ strerror(errno));
+ return EGL_FALSE;
+ }
+
+ /* Turn off hw accels (otherwise mmap of mmio region will be
+ * refused)
+ */
+ if (varInfo.accel_flags) {
+ varInfo.accel_flags = 0;
+ if (ioctl(fd, FBIOPUT_VSCREENINFO, &varInfo)) {
+ fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
+ strerror(errno));
+ return EGL_FALSE;
+ }
+ }
+
+ /* Get the fixed screen info */
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &fixedInfo)) {
+ fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
+ strerror(errno));
+ return EGL_FALSE;
+ }
+
+ if (fixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
+ struct fb_cmap cmap;
+ unsigned short red[256], green[256], blue[256];
+ int rcols = 1 << varInfo.red.length;
+ int gcols = 1 << varInfo.green.length;
+ int bcols = 1 << varInfo.blue.length;
+ int i;
+
+ cmap.start = 0;
+ cmap.len = gcols;
+ cmap.red = red;
+ cmap.green = green;
+ cmap.blue = blue;
+ cmap.transp = NULL;
+
+ for (i = 0; i < rcols ; i++)
+ red[i] = (65536/(rcols-1)) * i;
+
+ for (i = 0; i < gcols ; i++)
+ green[i] = (65536/(gcols-1)) * i;
+
+ for (i = 0; i < bcols ; i++)
+ blue[i] = (65536/(bcols-1)) * i;
+
+ if (ioctl(fd, FBIOPUTCMAP, (void *) &cmap) < 0) {
+ fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
+ exit(1);
+ }
+ }
+
+ /* mmap the framebuffer into our address space */
+ if (!disp->pFB)
+ disp->pFB = (caddr_t)mmap(0, /* start */
+ fixedInfo.smem_len, /* bytes */
+ PROT_READ | PROT_WRITE, /* prot */
+ MAP_SHARED, /* flags */
+ fd, /* fd */
+ 0); /* offset */
+ if (disp->pFB == (caddr_t)-1) {
+ fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
+ strerror(errno));
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+const char *sysfs = "/sys/class/graphics";
+
+static EGLBoolean
+fbInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ fbDisplay *display;
+ fbScreen *s;
+ _EGLScreen *scrn;
+ char c;
+ unsigned int x, y, r;
+ DIR *dir;
+ FILE *file;
+ struct dirent *dirent;
+ char path[NAME_MAX];
+
+ /* Switch display structure to one with our private fields */
+ display = calloc(1, sizeof(*display));
+ display->Base = *disp;
+ _eglHashInsert(_eglGlobal.Displays, disp->Handle, display);
+ free(disp);
+
+ *major = 1;
+ *minor = 0;
+
+ dir = opendir(sysfs);
+ if (!dir) {
+ printf("EGL - %s framebuffer device not found.", sysfs);
+ return EGL_FALSE;
+ }
+
+ while ((dirent = readdir(dir))) { /* assignment! */
+
+ if (dirent->d_name[0] != 'f')
+ continue;
+ if (dirent->d_name[1] != 'b')
+ continue;
+
+ if (fbSetupFramebuffer(display, dirent->d_name) == EGL_FALSE)
+ continue;
+
+ /* Create a screen */
+ s = (fbScreen *) calloc(1, sizeof(fbScreen));
+ if (!s)
+ return EGL_FALSE;
+
+ strncpy(s->fb, dirent->d_name, NAME_MAX);
+ scrn = &s->Base;
+ _eglInitScreen(scrn);
+ _eglAddScreen(&display->Base, scrn);
+
+ snprintf(path, sizeof(path), "%s/%s/modes", sysfs, s->fb);
+ file = fopen(path, "r");
+ while (fgets(path, sizeof(path), file)) {
+ sscanf(path, "%c:%ux%u-%u", &c, &x, &y, &r);
+ _eglAddMode(scrn, x, y, r * 1000, path);
+ }
+ fclose(file);
+
+ fbFillInConfigs(&display->Base, 32, 24, 8, 1);
+
+ }
+ closedir(dir);
+
+ drv->Initialized = EGL_TRUE;
+ return EGL_TRUE;
+}
+
+
+static fbDisplay *
+Lookup_fbDisplay(EGLDisplay dpy)
+{
+ _EGLDisplay *d = _eglLookupDisplay(dpy);
+ return (fbDisplay *) d;
+}
+
+
+static fbScreen *
+Lookup_fbScreen(EGLDisplay dpy, EGLScreenMESA screen)
+{
+ _EGLScreen *s = _eglLookupScreen(dpy, screen);
+ return (fbScreen *) s;
+}
+
+
+static fbContext *
+Lookup_fbContext(EGLContext ctx)
+{
+ _EGLContext *c = _eglLookupContext(ctx);
+ return (fbContext *) c;
+}
+
+
+static fbSurface *
+Lookup_fbSurface(EGLSurface surf)
+{
+ _EGLSurface *s = _eglLookupSurface(surf);
+ return (fbSurface *) s;
+}
+
+
+static EGLBoolean
+fbTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+ fbDisplay *display = Lookup_fbDisplay(dpy);
+ _eglCleanupDisplay(&display->Base);
+ free(display);
+ free(drv);
+ return EGL_TRUE;
+}
+
+
+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 );
+ _ac_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 )
+{
+ *width = buffer->Width;
+ *height = buffer->Height;
+}
+
+
+static void
+viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ _mesa_ResizeBuffersMESA();
+}
+
+
+static void
+init_core_functions( struct dd_function_table *functions )
+{
+ functions->GetString = get_string;
+ functions->UpdateState = update_state;
+ functions->ResizeBuffers = _mesa_resize_framebuffer;
+ functions->GetBufferSize = get_buffer_size;
+ functions->Viewport = viewport;
+
+ functions->Clear = _swrast_Clear; /* could accelerate with blits */
+}
+
+
+static EGLContext
+fbCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
+{
+ GLcontext *ctx;
+ _EGLConfig *conf;
+ fbContext *c;
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct dd_function_table functions;
+ GLvisual vis;
+ int i;
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+ return EGL_NO_CONTEXT;
+ }
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs defined for now */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
+ return EGL_NO_CONTEXT;
+ }
+ }
+
+ c = (fbContext *) calloc(1, sizeof(fbContext));
+ if (!c)
+ return EGL_NO_CONTEXT;
+
+ _eglInitContext(&c->Base);
+ c->Base.Display = disp;
+ c->Base.Config = conf;
+ c->Base.DrawSurface = EGL_NO_SURFACE;
+ c->Base.ReadSurface = EGL_NO_SURFACE;
+
+ /* generate handle and insert into hash table */
+ _eglSaveContext(&c->Base);
+ assert(c->Base.Handle);
+
+ /* Init default driver functions then plug in our FBdev-specific functions
+ */
+ _mesa_init_driver_functions(&functions);
+ init_core_functions(&functions);
+
+ _eglConfigToContextModesRec(conf, &vis);
+
+ ctx = c->glCtx = _mesa_create_context(&vis, NULL, &functions, (void *)c);
+ if (!c->glCtx) {
+ _mesa_free(c);
+ return GL_FALSE;
+ }
+
+ /* Create module contexts */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+ _swsetup_Wakeup( ctx );
+
+
+ /* swrast init -- need to verify these tests - I just plucked the
+ * numbers out of the air. (KW)
+ */
+ {
+ struct swrast_device_driver *swdd;
+ swdd = _swrast_GetDeviceDriverReference( ctx );
+ swdd->SetBuffer = fbSetBuffer;
+ }
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(ctx);
+
+ return c->Base.Handle;
+}
+
+
+static EGLSurface
+fbCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
+{
+ int i;
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs at this time */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface");
+ return EGL_NO_SURFACE;
+ }
+ }
+ printf("eglCreateWindowSurface()\n");
+ /* XXX unfinished */
+
+ return EGL_NO_SURFACE;
+}
+
+
+static EGLSurface
+fbCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
+{
+ _EGLConfig *conf;
+ EGLint i;
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface");
+ return EGL_NO_SURFACE;
+ }
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs at this time */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
+ return EGL_NO_SURFACE;
+ }
+ }
+
+ if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
+ _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
+ return EGL_NO_SURFACE;
+ }
+
+ printf("eglCreatePixmapSurface()\n");
+ return EGL_NO_SURFACE;
+}
+
+
+static EGLSurface
+fbCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ fbSurface *surf;
+
+ surf = (fbSurface *) calloc(1, sizeof(fbSurface));
+ if (!surf) {
+ return EGL_NO_SURFACE;
+ }
+
+ if (_eglInitPbufferSurface(&surf->Base, drv, dpy, config, attrib_list) == EGL_NO_SURFACE) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
+
+ /* create software-based pbuffer */
+ {
+ GLcontext *ctx = NULL; /* this _should_ be OK */
+ GLvisual vis;
+ _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+ assert(conf); /* bad config should be caught earlier */
+ _eglConfigToContextModesRec(conf, &vis);
+
+ surf->mesa_framebuffer = _mesa_create_framebuffer(&vis);
+ _mesa_add_soft_renderbuffers(surf->mesa_framebuffer,
+ GL_TRUE, /* color bufs */
+ vis.haveDepthBuffer,
+ vis.haveStencilBuffer,
+ vis.haveAccumBuffer,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */ );
+
+ /* set pbuffer/framebuffer size */
+ _mesa_resize_framebuffer(ctx, surf->mesa_framebuffer,
+ surf->Base.Width, surf->Base.Height);
+ }
+
+ return surf->Base.Handle;
+}
+
+
+static EGLBoolean
+fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+ fbSurface *fs = Lookup_fbSurface(surface);
+ _eglRemoveSurface(&fs->Base);
+ if (fs->Base.IsBound) {
+ fs->Base.DeletePending = EGL_TRUE;
+ }
+ else {
+ free(fs);
+ }
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
+{
+ fbContext *fc = Lookup_fbContext(context);
+ _eglRemoveContext(&fc->Base);
+ if (fc->Base.IsBound) {
+ fc->Base.DeletePending = EGL_TRUE;
+ }
+ else {
+ free(fc);
+ }
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+fbMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
+{
+ fbSurface *readSurf = Lookup_fbSurface(read);
+ fbSurface *drawSurf = Lookup_fbSurface(draw);
+ fbContext *ctx = Lookup_fbContext(context);
+ EGLBoolean b;
+
+ b = _eglMakeCurrent(drv, dpy, draw, read, context);
+ if (!b)
+ return EGL_FALSE;
+
+ if (ctx) {
+ _mesa_make_current( ctx->glCtx,
+ drawSurf->mesa_framebuffer,
+ readSurf->mesa_framebuffer);
+ } else
+ _mesa_make_current( NULL, NULL, NULL );
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Create a drawing surface which can be directly displayed on a screen.
+ */
+static EGLSurface
+fbCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
+ const EGLint *attrib_list)
+{
+ _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg);
+ fbDisplay *display = Lookup_fbDisplay(dpy);
+ fbSurface *surface;
+ EGLSurface surf;
+ GLvisual vis;
+ GLcontext *ctx = NULL; /* this should be OK */
+ int origin, bytesPerPixel;
+ int width, height, stride;
+
+ surface = (fbSurface *) malloc(sizeof(*surface));
+ if (!surface) {
+ return EGL_NO_SURFACE;
+ }
+
+ /* init base class, error check, etc. */
+ surf = _eglInitScreenSurface(&surface->Base, drv, dpy, cfg, attrib_list);
+ if (surf == EGL_NO_SURFACE) {
+ free(surface);
+ return EGL_NO_SURFACE;
+ }
+
+ /* convert EGLConfig to GLvisual */
+ _eglConfigToContextModesRec(config, &vis);
+
+ /* create Mesa framebuffer */
+ surface->mesa_framebuffer = _mesa_create_framebuffer(&vis);
+ if (!surface->mesa_framebuffer) {
+ free(surface);
+ _eglRemoveSurface(&surface->Base);
+ return EGL_NO_SURFACE;
+ }
+
+ width = surface->Base.Width;
+ height = surface->Base.Height;
+ bytesPerPixel = vis.rgbBits / 8;
+ stride = width * bytesPerPixel;
+ origin = 0;
+
+ /* front color renderbuffer */
+ {
+ driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, bytesPerPixel,
+ origin, stride);
+ fbSetSpanFunctions(drb, &vis);
+ drb->Base.Data = display->pFB;
+ _mesa_add_renderbuffer(surface->mesa_framebuffer,
+ BUFFER_FRONT_LEFT, &drb->Base);
+ }
+
+ /* back color renderbuffer */
+ if (vis.doubleBufferMode) {
+ driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, bytesPerPixel,
+ origin, stride);
+ fbSetSpanFunctions(drb, &vis);
+ drb->Base.Data = _mesa_malloc(stride * height);
+ _mesa_add_renderbuffer(surface->mesa_framebuffer,
+ BUFFER_BACK_LEFT, &drb->Base);
+ }
+
+ /* other renderbuffers- software based */
+ _mesa_add_soft_renderbuffers(surface->mesa_framebuffer,
+ GL_FALSE, /* color */
+ vis.haveDepthBuffer,
+ vis.haveStencilBuffer,
+ vis.haveAccumBuffer,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */);
+
+ _mesa_resize_framebuffer(ctx, surface->mesa_framebuffer, width, height);
+
+ return surf;
+}
+
+
+/**
+ * Show the given surface on the named screen.
+ * If surface is EGL_NO_SURFACE, disable the screen's output.
+ */
+static EGLBoolean
+fbShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface surface, EGLModeMESA m)
+{
+ fbDisplay *display = Lookup_fbDisplay(dpy);
+ fbScreen *scrn = Lookup_fbScreen(dpy, screen);
+ fbSurface *surf = Lookup_fbSurface(surface);
+ FILE *file;
+ char buffer[NAME_MAX];
+ _EGLMode *mode = _eglLookupMode(dpy, m);
+ int bits;
+
+ if (!_eglShowSurfaceMESA(drv, dpy, screen, surface, m))
+ return EGL_FALSE;
+
+ snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb);
+
+ file = fopen(buffer, "r+");
+ if (!file) {
+err:
+ printf("chown all fb sysfs attrib to allow write - %s\n", buffer);
+ return EGL_FALSE;
+ }
+ snprintf(buffer, sizeof(buffer), "%d", (m == EGL_NO_MODE_MESA ? VESA_POWERDOWN : VESA_VSYNC_SUSPEND));
+ fputs(buffer, file);
+ fclose(file);
+
+ if (m == EGL_NO_MODE_MESA)
+ return EGL_TRUE;
+
+ snprintf(buffer, sizeof(buffer), "%s/%s/mode", sysfs, scrn->fb);
+
+ file = fopen(buffer, "r+");
+ if (!file)
+ goto err;
+ fputs(mode->Name, file);
+ fclose(file);
+
+ snprintf(buffer, sizeof(buffer), "%s/%s/bits_per_pixel", sysfs, scrn->fb);
+
+ file = fopen(buffer, "r+");
+ if (!file)
+ goto err;
+ bits = GET_CONFIG_ATTRIB(surf->Base.Config, EGL_BUFFER_SIZE);
+ snprintf(buffer, sizeof(buffer), "%d", bits);
+ fputs(buffer, file);
+ fclose(file);
+
+ fbSetupFramebuffer(display, scrn->fb);
+
+ snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb);
+
+ file = fopen(buffer, "r+");
+ if (!file)
+ goto err;
+
+ snprintf(buffer, sizeof(buffer), "%d", VESA_NO_BLANKING);
+ fputs(buffer, file);
+ fclose(file);
+
+ return EGL_TRUE;
+}
+
+
+/* If the backbuffer is on a videocard, this is extraordinarily slow!
+ */
+static EGLBoolean
+fbSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+{
+ fbContext *context = (fbContext *)_eglGetCurrentContext();
+ fbSurface *fs = Lookup_fbSurface(draw);
+ struct gl_renderbuffer * front_renderbuffer = fs->mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ void *frontBuffer = front_renderbuffer->Data;
+ int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch;
+ void *backBuffer = fs->mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data;
+
+ if (!_eglSwapBuffers(drv, dpy, draw))
+ return EGL_FALSE;
+
+ if (context) {
+ GLcontext *ctx = context->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ int i;
+ int offset = 0;
+ char *tmp = _mesa_malloc(currentPitch);
+
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
+
+ ASSERT(frontBuffer);
+ ASSERT(backBuffer);
+
+ for (i = 0; i < fs->Base.Height; 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");
+ return EGL_FALSE;
+ }
+ return EGL_TRUE;
+}
+
+
+/**
+ * The bootstrap function. Return a new fbDriver object and
+ * plug in API functions.
+ */
+_EGLDriver *
+_eglMain(_EGLDisplay *dpy)
+{
+ fbDriver *fb;
+
+ fb = (fbDriver *) calloc(1, sizeof(fbDriver));
+ if (!fb) {
+ return NULL;
+ }
+
+ /* First fill in the dispatch table with defaults */
+ _eglInitDriverFallbacks(&fb->Base);
+
+ /* then plug in our fb-specific functions */
+ fb->Base.Initialize = fbInitialize;
+ fb->Base.Terminate = fbTerminate;
+ fb->Base.CreateContext = fbCreateContext;
+ fb->Base.MakeCurrent = fbMakeCurrent;
+ fb->Base.CreateWindowSurface = fbCreateWindowSurface;
+ fb->Base.CreatePixmapSurface = fbCreatePixmapSurface;
+ fb->Base.CreatePbufferSurface = fbCreatePbufferSurface;
+ fb->Base.DestroySurface = fbDestroySurface;
+ fb->Base.DestroyContext = fbDestroyContext;
+ fb->Base.CreateScreenSurfaceMESA = fbCreateScreenSurfaceMESA;
+ fb->Base.ShowSurfaceMESA = fbShowSurfaceMESA;
+ fb->Base.SwapBuffers = fbSwapBuffers;
+
+ /* enable supported extensions */
+ fb->Base.MESA_screen_surface = EGL_TRUE;
+ fb->Base.MESA_copy_context = EGL_TRUE;
+
+ return &fb->Base;
+}