summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/swrast/swrast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/swrast/swrast.c')
-rw-r--r--src/mesa/drivers/dri/swrast/swrast.c714
1 files changed, 714 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
new file mode 100644
index 00000000000..5c2b346e3e9
--- /dev/null
+++ b/src/mesa/drivers/dri/swrast/swrast.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2008 George Sapountzis <[email protected]>
+ *
+ * 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.
+ */
+
+/* TODO:
+ * - depth 8 (ci8, r3g3b2 ?)
+ * - XMesaResizeBuffers() ?
+ * add it to __DRIcoreExtension or own extension (GL_MESA_resize_buffers) ?
+ * - GLX_MESA_copy_sub_buffer
+ * - GLX_EXT_texture_from_pixmap
+ *
+ * BUGS:
+ * - winpos, glxpixmap: draw half width only with xorg at depth 16,
+ * they somehow manage to get a wrong drawable with depth 32,
+ * the "depth 32" visual is the composite overlay visual which is the
+ * only available single-buffer visual with glx_visuals "min" ...
+ *
+ * there is clearly something wrong with GLX visual setup, the assumption
+ * that GLX runs before composite no longer holds ...
+ *
+ * at depth 16:
+ * with glx_visuals "min", the composite overlay visual is added
+ * with glx_visuals "all", segfaults when moving cursor over glx window
+ *
+ * - texobj: loses textures at depth 32
+ * - texcyl: crashes mesa with "Linear Filtrered"
+ *
+ * DONE:
+ * - round image (i.e. backbuffer) pitch to 32 bits
+ * - depth 16
+ * - front-buffer rendering - depths, wincopy
+ * - GLX_SGI_make_current_read (wincopy with front)
+ */
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "imports.h"
+#include "renderbuffer.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 "vbo/vbo.h"
+#include "drivers/common/driverfuncs.h"
+
+#include "swrast_priv.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
+
+/* 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"
+#include "utils.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_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 }
+};
+
+static void
+setupLoaderExtensions(__DRIscreen *psp,
+ const __DRIextension **extensions)
+{
+ int i;
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
+ psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
+ }
+}
+
+static __DRIconfig **
+swrastFillInModes(__DRIscreen *psp,
+ unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer)
+{
+ __DRIconfig **configs;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML
+ };
+
+ u_int8_t depth_bits_array[3];
+ u_int8_t stencil_bits_array[3];
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = depth_bits;
+ depth_bits_array[2] = depth_bits;
+
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 0;
+ stencil_bits_array[2] = stencil_bits;
+
+ depth_buffer_factor = 3;
+ back_buffer_factor = 2;
+
+ if (pixel_bits == 16) {
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ else {
+ fb_format = GL_BGRA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ configs = driCreateConfigs(fb_format, fb_type,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor);
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return configs;
+}
+
+static __DRIscreen *
+driCreateNewScreen(int scrn, const __DRIextension **extensions,
+ const __DRIconfig ***driver_configs, void *data)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+
+ (void) data;
+
+ TRACE;
+
+ psp = _mesa_calloc(sizeof(*psp));
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ psp->num = scrn;
+ psp->extensions = emptyExtensionList;
+
+ *driver_configs = driConcatConfigs(swrastFillInModes(psp, 16, 16, 0, 1),
+ swrastFillInModes(psp, 32, 24, 8, 1));
+
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+
+ return psp;
+}
+
+static void driDestroyScreen(__DRIscreen *psp)
+{
+ TRACE;
+
+ if (psp) {
+ _mesa_free(psp);
+ }
+}
+
+static const __DRIextension **driGetExtensions(__DRIscreen *psp)
+{
+ TRACE;
+
+ return psp->extensions;
+}
+
+
+/**
+ * swrast_buffer.c
+ */
+
+static GLuint
+choose_pixel_format(const GLvisual *v)
+{
+ if (v->rgbMode) {
+ /* XXX 24bpp packed, 8bpp, xmesa gets bitsPerPixel from xserver */
+ int bpp = v->rgbBits;
+ if (bpp == 24)
+ bpp = 32;
+
+ if (bpp == 32
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_A8R8G8B8;
+ else if (bpp == 16
+ && v->redMask == 0xf800
+ && v->greenMask == 0x07e0
+ && v->blueMask == 0x001f)
+ return PF_R5G6B5;
+ }
+ else {
+ if (v->indexBits == 8)
+ return PF_CI8;
+ }
+
+ _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
+ return 0;
+}
+
+static void
+swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ TRACE;
+
+ _mesa_free(rb->Data);
+ _mesa_free(rb);
+}
+
+static GLboolean
+swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+ int bpp;
+
+ TRACE;
+
+ rb->Data = NULL;
+ rb->Width = width;
+ rb->Height = height;
+
+ switch (internalFormat) {
+ case GL_RGB:
+ bpp = rb->RedBits + rb->GreenBits + rb->BlueBits;
+ break;
+ case GL_RGBA:
+ bpp = rb->RedBits + rb->GreenBits + rb->BlueBits + rb->AlphaBits;
+ break;
+ case GL_COLOR_INDEX8_EXT:
+ bpp = rb->IndexBits;
+ break;
+ default:
+ _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
+ return GL_FALSE;
+ }
+
+ /* always pad to 32 bits */
+ xrb->pitch = ((width * bpp + 0x1f) & ~0x1f) / 8;
+
+ return GL_TRUE;
+}
+
+static GLboolean
+swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+
+ TRACE;
+
+ _mesa_free(rb->Data);
+
+ (void) swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
+
+ rb->Data = _mesa_malloc(height * xrb->pitch);
+
+ return GL_TRUE;
+}
+
+static struct swrast_renderbuffer *
+swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
+{
+ struct swrast_renderbuffer *xrb = _mesa_calloc(sizeof *xrb);
+ GLuint pixel_format;
+
+ TRACE;
+
+ if (xrb) {
+ _mesa_init_renderbuffer(&xrb->Base, 0);
+
+ pixel_format = choose_pixel_format(visual);
+
+ xrb->Base.Delete = swrast_delete_renderbuffer;
+ if (front) {
+ xrb->Base.AllocStorage = swrast_alloc_front_storage;
+ swrast_set_span_funcs_pixmap(xrb, pixel_format);
+ }
+ else {
+ xrb->Base.AllocStorage = swrast_alloc_back_storage;
+ swrast_set_span_funcs_ximage(xrb, pixel_format);
+ }
+
+ switch (pixel_format) {
+ case PF_A8R8G8B8:
+ xrb->Base.InternalFormat = GL_RGBA;
+ xrb->Base._BaseFormat = GL_RGBA;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 8 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 8 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 8 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
+ break;
+ case PF_R5G6B5:
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 5 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 6 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 5 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 0;
+ break;
+ case PF_CI8:
+ xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
+ xrb->Base._BaseFormat = GL_COLOR_INDEX;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.IndexBits = 8 * sizeof(GLubyte);
+ break;
+ default:
+ return NULL;
+ }
+ }
+ return xrb;
+}
+
+static __DRIdrawable *
+driCreateNewDrawable(__DRIscreen *screen,
+ const __DRIconfig *config, void *data)
+{
+ __DRIdrawable *buf;
+ struct swrast_renderbuffer *frontrb, *backrb;
+
+ TRACE;
+
+ buf = _mesa_calloc(sizeof *buf);
+ if (!buf)
+ return NULL;
+
+ buf->loaderPrivate = data;
+
+ buf->driScreenPriv = screen;
+
+ buf->row = _mesa_malloc(MAX_WIDTH * 4);
+
+ /* basic framebuffer setup */
+ _mesa_initialize_framebuffer(&buf->Base, &config->modes);
+
+ /* add front renderbuffer */
+ frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE);
+ _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base);
+
+ /* add back renderbuffer */
+ if (config->modes.doubleBufferMode) {
+ backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE);
+ _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base);
+ }
+
+ /* add software renderbuffers */
+ _mesa_add_soft_renderbuffers(&buf->Base,
+ GL_FALSE, /* color */
+ config->modes.haveDepthBuffer,
+ config->modes.haveStencilBuffer,
+ config->modes.haveAccumBuffer,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux bufs */);
+
+ return buf;
+}
+
+static void
+driDestroyDrawable(__DRIdrawable *buf)
+{
+ TRACE;
+
+ if (buf) {
+ struct gl_framebuffer *fb = &buf->Base;
+
+ _mesa_free(buf->row);
+
+ fb->DeletePending = GL_TRUE;
+ _mesa_unreference_framebuffer(&fb);
+ }
+}
+
+static void driSwapBuffers(__DRIdrawable *buf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct swrast_renderbuffer *frontrb =
+ swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ struct swrast_renderbuffer *backrb =
+ swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+
+ __DRIscreen *screen = buf->driScreenPriv;
+
+ TRACE;
+
+ /* check for signle-buffered */
+ if (backrb == NULL)
+ return;
+
+ /* check if swapping currently bound buffer */
+ if (ctx && ctx->DrawBuffer == &(buf->Base)) {
+ /* flush pending rendering */
+ _mesa_notifySwapBuffers(ctx);
+ }
+
+ screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP,
+ 0, 0,
+ frontrb->Base.Width,
+ frontrb->Base.Height,
+ backrb->Base.Data,
+ buf->loaderPrivate);
+}
+
+
+/**
+ * swrast_dd.c
+ */
+
+static void
+get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h )
+{
+ __DRIdrawable *buf = swrast_drawable(fb);
+ __DRIscreen *screen = buf->driScreenPriv;
+ int x, y;
+
+ screen->swrast_loader->getDrawableInfo(buf,
+ &x, &y, w, h,
+ buf->loaderPrivate);
+}
+
+static void
+swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb )
+{
+ GLsizei width, height;
+
+ get_window_size(fb, &width, &height);
+ if (fb->Width != width || fb->Height != height) {
+ _mesa_resize_framebuffer(ctx, fb, width, height);
+ }
+}
+
+static const GLubyte *
+get_string(GLcontext *ctx, GLenum pname)
+{
+ (void) ctx;
+ switch (pname) {
+ case GL_VENDOR:
+ return (const GLubyte *) "Mesa Project";
+ case GL_RENDERER:
+ return (const GLubyte *) "X.Org";
+ 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 );
+}
+
+static void
+viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ GLframebuffer *draw = ctx->WinSysDrawBuffer;
+ GLframebuffer *read = ctx->WinSysReadBuffer;
+
+ swrast_check_and_update_window_size(ctx, draw);
+ swrast_check_and_update_window_size(ctx, read);
+}
+
+static void
+swrast_init_driver_functions(struct dd_function_table *driver)
+{
+ driver->GetString = get_string;
+ driver->UpdateState = update_state;
+ driver->GetBufferSize = NULL;
+ driver->Viewport = viewport;
+}
+
+
+/**
+ * swrast_context.c
+ */
+
+static __DRIcontext *
+driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+ __DRIcontext *shared, void *data)
+{
+ __DRIcontext *ctx;
+ GLcontext *mesaCtx;
+ struct dd_function_table functions;
+
+ TRACE;
+
+ ctx = _mesa_calloc(sizeof *ctx);
+ if (!ctx)
+ return NULL;
+
+ ctx->loaderPrivate = data;
+
+ ctx->driScreenPriv = screen;
+
+ /* build table of device driver functions */
+ _mesa_init_driver_functions(&functions);
+ swrast_init_driver_functions(&functions);
+
+ if (!_mesa_initialize_context(&ctx->Base, &config->modes,
+ shared ? &shared->Base : NULL,
+ &functions, (void *) ctx)) {
+ _mesa_free(ctx);
+ return NULL;
+ }
+
+ mesaCtx = &ctx->Base;
+
+ /* do bounds checking to prevent segfaults and server crashes! */
+ mesaCtx->Const.CheckArrayBounds = GL_TRUE;
+
+ /* create module contexts */
+ _swrast_CreateContext( mesaCtx );
+ _vbo_CreateContext( mesaCtx );
+ _tnl_CreateContext( mesaCtx );
+ _swsetup_CreateContext( mesaCtx );
+ _swsetup_Wakeup( mesaCtx );
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(mesaCtx);
+ _mesa_enable_1_3_extensions(mesaCtx);
+ _mesa_enable_1_4_extensions(mesaCtx);
+ _mesa_enable_1_5_extensions(mesaCtx);
+ _mesa_enable_2_0_extensions(mesaCtx);
+ _mesa_enable_2_1_extensions(mesaCtx);
+
+ return ctx;
+}
+
+static void
+driDestroyContext(__DRIcontext *ctx)
+{
+ GLcontext *mesaCtx;
+ TRACE;
+
+ if (ctx) {
+ mesaCtx = &ctx->Base;
+ _swsetup_DestroyContext( mesaCtx );
+ _swrast_DestroyContext( mesaCtx );
+ _tnl_DestroyContext( mesaCtx );
+ _vbo_DestroyContext( mesaCtx );
+ _mesa_destroy_context( mesaCtx );
+ }
+}
+
+static int
+driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
+{
+ TRACE;
+
+ _mesa_copy_context(&src->Base, &dst->Base, mask);
+ return GL_TRUE;
+}
+
+static int driBindContext(__DRIcontext *ctx,
+ __DRIdrawable *draw,
+ __DRIdrawable *read)
+{
+ GLcontext *mesaCtx;
+ GLframebuffer *mesaDraw;
+ GLframebuffer *mesaRead;
+ TRACE;
+
+ if (ctx) {
+ if (!draw || !read)
+ return GL_FALSE;
+
+ /* check for same context and buffer */
+ mesaCtx = &ctx->Base;
+ mesaDraw = &draw->Base;
+ mesaRead = &read->Base;
+ if (mesaCtx == _mesa_get_current_context()
+ && mesaCtx->DrawBuffer == mesaDraw
+ && mesaCtx->ReadBuffer == mesaRead) {
+ return GL_TRUE;
+ }
+
+ _glapi_check_multithread();
+
+ swrast_check_and_update_window_size(mesaCtx, mesaDraw);
+ if (read != draw)
+ swrast_check_and_update_window_size(mesaCtx, mesaRead);
+
+ _mesa_make_current( mesaCtx,
+ mesaDraw,
+ mesaRead );
+ }
+ else {
+ /* unbind */
+ _mesa_make_current( NULL, NULL, NULL );
+ }
+
+ return GL_TRUE;
+}
+
+static int driUnbindContext(__DRIcontext *ctx)
+{
+ TRACE;
+ (void) ctx;
+ _mesa_make_current(NULL, NULL, NULL);
+ return GL_TRUE;
+}
+
+
+static const __DRIcoreExtension driCoreExtension = {
+ { __DRI_CORE, __DRI_CORE_VERSION },
+ NULL,
+ driDestroyScreen,
+ driGetExtensions,
+ driGetConfigAttrib,
+ driIndexConfigAttrib,
+ NULL,
+ driDestroyDrawable,
+ driSwapBuffers,
+ driCreateNewContext,
+ driCopyContext,
+ driDestroyContext,
+ driBindContext,
+ driUnbindContext
+};
+
+static const __DRIswrastExtension driSWRastExtension = {
+ { __DRI_SWRAST, __DRI_SWRAST_VERSION },
+ driCreateNewScreen,
+ driCreateNewDrawable,
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+ &driCoreExtension.base,
+ &driSWRastExtension.base,
+ NULL
+};