From 280bf89bd4a6bb7977abb00b88d59234d2c80844 Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Sun, 11 May 2008 14:43:40 +0300 Subject: [PATCH] Add DRI driver that uses the mesa swrast module. --- configure.ac | 8 +- include/GL/internal/dri_interface.h | 57 ++ src/mesa/drivers/dri/swrast/Makefile | 74 ++ src/mesa/drivers/dri/swrast/swrast.c | 714 ++++++++++++++++++ src/mesa/drivers/dri/swrast/swrast_priv.h | 126 ++++ src/mesa/drivers/dri/swrast/swrast_span.c | 271 +++++++ src/mesa/drivers/dri/swrast/swrast_spantemp.h | 328 ++++++++ 7 files changed, 1574 insertions(+), 4 deletions(-) create mode 100644 src/mesa/drivers/dri/swrast/Makefile create mode 100644 src/mesa/drivers/dri/swrast/swrast.c create mode 100644 src/mesa/drivers/dri/swrast/swrast_priv.h create mode 100644 src/mesa/drivers/dri/swrast/swrast_span.c create mode 100644 src/mesa/drivers/dri/swrast/swrast_spantemp.h diff --git a/configure.ac b/configure.ac index 6aac482e1a8..6f05108f344 100644 --- a/configure.ac +++ b/configure.ac @@ -537,14 +537,14 @@ if test "$mesa_driver" = dri; then # be used. if test "x$DRI_DIRS" = x; then DRI_DIRS="i915 i965 mach64 mga r128 r200 r300 radeon \ - savage tdfx unichrome" + savage tdfx unichrome swrast" fi ;; powerpc*) # Build only the drivers for cards that exist on PowerPC. # At some point MGA will be added, but not yet. if test "x$DRI_DIRS" = x; then - DRI_DIRS="mach64 r128 r200 r300 radeon tdfx" + DRI_DIRS="mach64 r128 r200 r300 radeon tdfx swrast" fi ;; esac @@ -564,7 +564,7 @@ if test "$mesa_driver" = dri; then # to use the new interface. if test "x$DRI_DIRS" = x; then DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 radeon tdfx \ - unichrome savage sis" + unichrome savage sis swrast" fi ;; esac @@ -572,7 +572,7 @@ if test "$mesa_driver" = dri; then # default drivers if test "x$DRI_DIRS" = x; then DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 radeon s3v \ - savage sis tdfx trident unichrome ffb" + savage sis tdfx trident unichrome ffb swrast" fi DRI_DIRS=`echo "$DRI_DIRS" | $SED 's/ */ /g'` diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 1bfb5efb2c8..033d7a4ae44 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -67,6 +67,7 @@ typedef struct __DRImediaStreamCounterExtensionRec __DRImediaStreamCounterExtens typedef struct __DRItexOffsetExtensionRec __DRItexOffsetExtension; typedef struct __DRItexBufferExtensionRec __DRItexBufferExtension; typedef struct __DRIlegacyExtensionRec __DRIlegacyExtension; +typedef struct __DRIswrastExtensionRec __DRIswrastExtension; /*@}*/ @@ -256,6 +257,7 @@ typedef struct __DRIgetDrawableInfoExtensionRec __DRIgetDrawableInfoExtension; typedef struct __DRIsystemTimeExtensionRec __DRIsystemTimeExtension; typedef struct __DRIdamageExtensionRec __DRIdamageExtension; typedef struct __DRIloaderExtensionRec __DRIloaderExtension; +typedef struct __DRIswrastLoaderExtensionRec __DRIswrastLoaderExtension; /** @@ -357,6 +359,40 @@ struct __DRIloaderExtensionRec { int num_rects, void *loaderPrivate); }; +#define __DRI_SWRAST_IMAGE_OP_DRAW 1 +#define __DRI_SWRAST_IMAGE_OP_CLEAR 2 +#define __DRI_SWRAST_IMAGE_OP_SWAP 3 + +/** + * SWRast Loader extension. + */ +#define __DRI_SWRAST_LOADER "DRI_SWRastLoader" +#define __DRI_SWRAST_LOADER_VERSION 1 +struct __DRIswrastLoaderExtensionRec { + __DRIextension base; + + /* + * Drawable position and size + */ + void (*getDrawableInfo)(__DRIdrawable *drawable, + int *x, int *y, int *width, int *height, + void *loaderPrivate); + + /** + * Put image to drawable + */ + void (*putImage)(__DRIdrawable *drawable, int op, + int x, int y, int width, int height, char *data, + void *loaderPrivate); + + /** + * Get image from drawable + */ + void (*getImage)(__DRIdrawable *drawable, + int x, int y, int width, int height, char *data, + void *loaderPrivate); +}; + /** * The remaining extensions describe driver extensions, immediately * available interfaces provided by the driver. To start using the @@ -569,4 +605,25 @@ struct __DRIlegacyExtensionRec { void *loaderPrivate); }; +/** + * This extension provides alternative screen, drawable and context + * constructors for swrast DRI functionality. This is used in + * conjunction with the core extension. + */ +#define __DRI_SWRAST "DRI_SWRast" +#define __DRI_SWRAST_VERSION 1 + +struct __DRIswrastExtensionRec { + __DRIextension base; + + __DRIscreen *(*createNewScreen)(int screen, + const __DRIextension **extensions, + const __DRIconfig ***driver_configs, + void *loaderPrivate); + + __DRIdrawable *(*createNewDrawable)(__DRIscreen *screen, + const __DRIconfig *config, + void *loaderPrivate); +}; + #endif diff --git a/src/mesa/drivers/dri/swrast/Makefile b/src/mesa/drivers/dri/swrast/Makefile new file mode 100644 index 00000000000..eb58f4c7338 --- /dev/null +++ b/src/mesa/drivers/dri/swrast/Makefile @@ -0,0 +1,74 @@ +# src/mesa/drivers/dri/swrast/Makefile + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = swrast_dri.so + +DRIVER_SOURCES = \ + swrast.c \ + swrast_span.c + +C_SOURCES = \ + $(COMMON_SOURCES) \ + $(DRIVER_SOURCES) + +######################################## + +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + +COMMON_SOURCES = \ + ../../common/driverfuncs.c + +ifeq ($(WINDOW_SYSTEM),dri) +COMMON_SOURCES += \ + ../common/utils.c +endif + +OBJECTS = $(C_SOURCES:.c=.o) + +### Include directories +INCLUDES = \ + -I. \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi + +ifeq ($(WINDOW_SYSTEM),dri) +INCLUDES += \ + -I$(TOP)/src/mesa/drivers/dri/common \ + $(LIBDRM_CFLAGS) +endif + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@ + + +##### TARGETS ##### + +default: depend $(LIBNAME) + + +$(LIBNAME): $(OBJECTS) $(MESA_MODULES) Makefile + $(TOP)/bin/mklib -ldflags '$(LDFLAGS)' -noprefix -o $@ \ + $(OBJECTS) $(MESA_MODULES) $(GLCORE_LIB_DEPS) + + +depend: $(C_SOURCES) + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) \ + > /dev/null + + +clean: + -rm -f *.o *.so + -rm -f depend depend.bak + +install: $(LIBNAME) + $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + $(INSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + +include depend 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 + * + * 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 +#include +#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 +}; diff --git a/src/mesa/drivers/dri/swrast/swrast_priv.h b/src/mesa/drivers/dri/swrast/swrast_priv.h new file mode 100644 index 00000000000..d801f88f072 --- /dev/null +++ b/src/mesa/drivers/dri/swrast/swrast_priv.h @@ -0,0 +1,126 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 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. + */ + +/* + * Authors: + * George Sapountzis + */ + + +#ifndef _SWRAST_PRIV_H +#define _SWRAST_PRIV_H + +#include +#include +#include "mtypes.h" + +#define DEBUG_CORE 0 +#define DEBUG_SPAN 1 + +#if DEBUG_CORE +#define TRACE _mesa_printf("--> %s\n", __FUNCTION__) +#else +#define TRACE +#endif + +#if DEBUG_SPAN +#define TRACE_SPAN _mesa_printf("--> %s\n", __FUNCTION__) +#else +#define TRACE_SPAN +#endif + + +/** + * Data types + */ +struct __DRIscreenRec { + int num; + + const __DRIextension **extensions; + + const __DRIswrastLoaderExtension *swrast_loader; +}; + +struct __DRIcontextRec { + GLcontext Base; + + void *loaderPrivate; + + __DRIscreen *driScreenPriv; +}; + +struct __DRIdrawableRec { + GLframebuffer Base; + + void *loaderPrivate; + + __DRIscreen *driScreenPriv; + + char *row; +}; + +struct swrast_renderbuffer { + struct gl_renderbuffer Base; + + GLuint pitch; +}; + +static inline __DRIcontext * +swrast_context(GLcontext *ctx) +{ + return (__DRIcontext *) ctx; +} + +static inline __DRIdrawable * +swrast_drawable(GLframebuffer *fb) +{ + return (__DRIdrawable *) fb; +} + +static inline struct swrast_renderbuffer * +swrast_renderbuffer(struct gl_renderbuffer *rb) +{ + return (struct swrast_renderbuffer *) rb; +} + + +/** + * Pixel formats we support + */ +#define PF_CI8 1 /**< Color Index mode */ +#define PF_A8R8G8B8 2 /**< 32-bit TrueColor: 8-A, 8-R, 8-G, 8-B bits */ +#define PF_R5G6B5 3 /**< 16-bit TrueColor: 5-R, 6-G, 5-B bits */ + + +/* swrast_span.c */ + +extern void +swrast_set_span_funcs_ximage(struct swrast_renderbuffer *xrb, + GLuint pixel_format); + +extern void +swrast_set_span_funcs_pixmap(struct swrast_renderbuffer *xrb, + GLuint pixel_format); + +#endif /* _SWRAST_PRIV_H_ */ diff --git a/src/mesa/drivers/dri/swrast/swrast_span.c b/src/mesa/drivers/dri/swrast/swrast_span.c new file mode 100644 index 00000000000..fd11f2866e8 --- /dev/null +++ b/src/mesa/drivers/dri/swrast/swrast_span.c @@ -0,0 +1,271 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 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. + */ + +/* + * Authors: + * George Sapountzis + */ + +#include "swrast_priv.h" + +#define YFLIP(_xrb, Y) ((_xrb)->Base.Height - (Y) - 1) + +/* + * Generate code for image span functions. + */ + +/* 32-bit BGRA */ +#define NAME(FUNC) FUNC##_A8R8G8B8 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 4; +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[3] = VALUE[ACOMP]; \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[3] = 0xff; \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[ACOMP] = SRC[3]; \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0] + +#include "swrast/s_spantemp.h" + + +/* 16-bit BGR */ +#define NAME(FUNC) FUNC##_R5G6B5 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 2; +#define INC_PIXEL_PTR(P) P += 2 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + do { \ + GLushort *p = (GLushort *)DST; \ + *p = ( (((VALUE[RCOMP]) & 0xf8) << 8) | \ + (((VALUE[GCOMP]) & 0xfc) << 3) | \ + (((VALUE[BCOMP]) & 0xf8) >> 3) ); \ + } while(0) +#define FETCH_PIXEL(DST, SRC) \ + do { \ + GLushort p = *(GLushort *)SRC; \ + DST[ACOMP] = 0xff; \ + DST[RCOMP] = ((p >> 8) & 0xf8) * 255 / 0xf8; \ + DST[GCOMP] = ((p >> 3) & 0xfc) * 255 / 0xfc; \ + DST[BCOMP] = ((p << 3) & 0xf8) * 255 / 0xf8; \ + } while(0) + +#include "swrast/s_spantemp.h" + + +/* 8-bit color index */ +#define NAME(FUNC) FUNC##_CI8 +#define CI_MODE +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->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" + + +/* + * Generate code for pixmap span functions. + */ + +/* 32-bit BGRA */ +#define NAME(FUNC) FUNC##_A8R8G8B8_pixmap +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)row; +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[3] = VALUE[ACOMP]; \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[3] = 0xff; \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[ACOMP] = SRC[3]; \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0] + +#include "swrast_spantemp.h" + + +/* 16-bit BGR */ +#define NAME(FUNC) FUNC##_R5G6B5_pixmap +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)row; +#define INC_PIXEL_PTR(P) P += 2 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + do { \ + GLushort *p = (GLushort *)DST; \ + *p = ( (((VALUE[RCOMP]) & 0xf8) << 8) | \ + (((VALUE[GCOMP]) & 0xfc) << 3) | \ + (((VALUE[BCOMP]) & 0xf8) >> 3) ); \ + } while(0) +#define FETCH_PIXEL(DST, SRC) \ + do { \ + GLushort p = *(GLushort *)SRC; \ + DST[ACOMP] = 0xff; \ + DST[RCOMP] = ((p >> 8) & 0xf8) * 255 / 0xf8; \ + DST[GCOMP] = ((p >> 3) & 0xfc) * 255 / 0xfc; \ + DST[BCOMP] = ((p << 3) & 0xf8) * 255 / 0xf8; \ + } while(0) + +#include "swrast_spantemp.h" + + +/* 8-bit color index */ +#define NAME(FUNC) FUNC##_CI8_pixmap +#define CI_MODE +#define RB_TYPE GLubyte +#define SPAN_VARS \ + struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *)row; +#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_spantemp.h" + + +/* + * Images are malloced memory used for private back-buffers. + * + * BACK_PIXMAP (not supported) + * BACK_XIMAGE + */ +void +swrast_set_span_funcs_ximage(struct swrast_renderbuffer *xrb, + GLuint pixel_format) +{ + switch (pixel_format) { + case PF_A8R8G8B8: + xrb->Base.GetRow = get_row_A8R8G8B8; + xrb->Base.GetValues = get_values_A8R8G8B8; + xrb->Base.PutRow = put_row_A8R8G8B8; + xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8; + xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8; + xrb->Base.PutValues = put_values_A8R8G8B8; + xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8; + break; + case PF_R5G6B5: + xrb->Base.GetRow = get_row_R5G6B5; + xrb->Base.GetValues = get_values_R5G6B5; + xrb->Base.PutRow = put_row_R5G6B5; + xrb->Base.PutRowRGB = put_row_rgb_R5G6B5; + xrb->Base.PutMonoRow = put_mono_row_R5G6B5; + xrb->Base.PutValues = put_values_R5G6B5; + xrb->Base.PutMonoValues = put_mono_values_R5G6B5; + break; + case PF_CI8: + xrb->Base.GetRow = get_row_CI8; + xrb->Base.GetValues = get_values_CI8; + xrb->Base.PutRow = put_row_CI8; + xrb->Base.PutMonoRow = put_mono_row_CI8; + xrb->Base.PutValues = put_values_CI8; + xrb->Base.PutMonoValues = put_mono_values_CI8; + break; + default: + assert(0); + return; + } +} + + +/* + * Pixmaps are used for front-buffers. + * + * WINDOW, An X window + * GLXWINDOW, GLX window + * PIXMAP, GLX pixmap + * PBUFFER GLX Pbuffer + */ +void +swrast_set_span_funcs_pixmap(struct swrast_renderbuffer *xrb, + GLuint pixel_format) +{ + switch (pixel_format) { + case PF_A8R8G8B8: + xrb->Base.GetRow = get_row_A8R8G8B8_pixmap; + xrb->Base.GetValues = get_values_A8R8G8B8_pixmap; + xrb->Base.PutRow = put_row_A8R8G8B8_pixmap; + xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8_pixmap; + xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8_pixmap; + xrb->Base.PutValues = put_values_A8R8G8B8_pixmap; + xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8_pixmap; + break; + case PF_R5G6B5: + xrb->Base.GetRow = get_row_R5G6B5_pixmap; + xrb->Base.GetValues = get_values_R5G6B5_pixmap; + xrb->Base.PutRow = put_row_R5G6B5_pixmap; + xrb->Base.PutRowRGB = put_row_rgb_R5G6B5_pixmap; + xrb->Base.PutMonoRow = put_mono_row_R5G6B5_pixmap; + xrb->Base.PutValues = put_values_R5G6B5_pixmap; + xrb->Base.PutMonoValues = put_mono_values_R5G6B5_pixmap; + break; + case PF_CI8: + xrb->Base.GetRow = get_row_CI8_pixmap; + xrb->Base.GetValues = get_values_CI8_pixmap; + xrb->Base.PutRow = put_row_CI8_pixmap; + xrb->Base.PutMonoRow = put_mono_row_CI8_pixmap; + xrb->Base.PutValues = put_values_CI8_pixmap; + xrb->Base.PutMonoValues = put_mono_values_CI8_pixmap; + break; + default: + assert(0); + return; + } +} diff --git a/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/src/mesa/drivers/dri/swrast/swrast_spantemp.h new file mode 100644 index 00000000000..7c60c15974f --- /dev/null +++ b/src/mesa/drivers/dri/swrast/swrast_spantemp.h @@ -0,0 +1,328 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 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. + */ + + +/* + * This is a modified version of swrast/s_spantemp.h for rendering to X11 + * drawables. The no-mask paths use a scratch row to avoid repeated calls + * to xserver. + * + * For the mask paths we always use an array of 4 elements of RB_TYPE because + * we should pad "image" pitch to 32 bits. + */ + + +#ifndef _SWRAST_SPANTEMP_ONCE +#define _SWRAST_SPANTEMP_ONCE + +static inline void +PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) +{ + __DRIcontext *ctx = swrast_context(glCtx); + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW, + x, y, 1, 1, (char *)p, + draw->loaderPrivate); +} + + +static inline void +GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) +{ + __DRIcontext *ctx = swrast_context(glCtx); + __DRIdrawable *draw = swrast_drawable(glCtx->ReadBuffer); + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->getImage(draw, x, y, 1, 1, (char *)p, + draw->loaderPrivate); +} + +static inline void +PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) +{ + __DRIcontext *ctx = swrast_context(glCtx); + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW, + x, y, n, 1, row, + draw->loaderPrivate); +} + +static inline void +GET_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) +{ + __DRIcontext *ctx = swrast_context(glCtx); + __DRIdrawable *draw = swrast_drawable(glCtx->ReadBuffer); + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->getImage(draw, x, y, n, 1, row, + draw->loaderPrivate); +} + +#endif /* _SWRAST_SPANTEMP_ONCE */ + + +/* + * Templates for the span/pixel-array write/read functions called via + * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues + * and PutMonoValues functions. + * + * Define the following macros before including this file: + * NAME(BASE) to generate the function name (i.e. add prefix or suffix) + * RB_TYPE the renderbuffer DataType + * CI_MODE if set, color index mode, else RGBA + * SPAN_VARS to declare any local variables + * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel + * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel + * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer + * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer + * + * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates + * for the pixels to be stored. This is useful when dithering and probably + * ignored otherwise. + */ + +#include "macros.h" + + +#ifdef CI_MODE +#define RB_COMPONENTS 1 +#elif !defined(RB_COMPONENTS) +#define RB_COMPONENTS 4 +#endif + + +static void +NAME(get_row)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif +#ifdef CI_MODE + RB_TYPE *dest = (RB_TYPE *) values; +#else + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; +#endif + GLuint i; + char *row = swrast_drawable(ctx->DrawBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + GET_ROW( ctx, x, YFLIP(xrb, y), count, row ); + for (i = 0; i < count; i++) { + FETCH_PIXEL(dest[i], pixel); + INC_PIXEL_PTR(pixel); + } + (void) rb; +} + + +static void +NAME(get_values)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif +#ifdef CI_MODE + RB_TYPE *dest = (RB_TYPE *) values; +#else + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; +#endif + GLuint i; + for (i = 0; i < count; i++) { + RB_TYPE pixel[4]; + GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel); + FETCH_PIXEL(dest[i], pixel); + } + (void) rb; +} + + +static void +NAME(put_row)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE pixel[4]; + STORE_PIXEL(pixel, x + i, y, src[i]); + PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel); + } + } + } + else { + char *row = swrast_drawable(ctx->DrawBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { + STORE_PIXEL(pixel, x + i, y, src[i]); + INC_PIXEL_PTR(pixel); + } + PUT_ROW( ctx, x, YFLIP(xrb, y), count, row ); + } + (void) rb; +} + + +#if !defined(CI_MODE) +static void +NAME(put_row_rgb)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values; + GLuint i; + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE pixel[4]; +#ifdef STORE_PIXEL_RGB + STORE_PIXEL_RGB(pixel, x + i, y, src[i]); +#else + STORE_PIXEL(pixel, x + i, y, src[i]); +#endif + PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel); + } + } + } + else { + char *row = swrast_drawable(ctx->DrawBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { +#ifdef STORE_PIXEL_RGB + STORE_PIXEL_RGB(pixel, x + i, y, src[i]); +#else + STORE_PIXEL(pixel, x + i, y, src[i]); +#endif + INC_PIXEL_PTR(pixel); + } + PUT_ROW( ctx, x, YFLIP(xrb, y), count, row ); + } + (void) rb; +} +#endif + + +static void +NAME(put_mono_row)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *value, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE *src = (const RB_TYPE *) value; + GLuint i; + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE pixel[4]; + STORE_PIXEL(pixel, x + i, y, src); + PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel); + } + } + } + else { + char *row = swrast_drawable(ctx->DrawBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { + STORE_PIXEL(pixel, x + i, y, src); + INC_PIXEL_PTR(pixel); + } + PUT_ROW( ctx, x, YFLIP(xrb, y), count, row ); + } + (void) rb; +} + + +static void +NAME(put_values)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + ASSERT(mask); + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE pixel[4]; + STORE_PIXEL(pixel, x[i], y[i], src[i]); + PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel); + } + } + (void) rb; +} + + +static void +NAME(put_mono_values)( GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE *src = (const RB_TYPE *) value; + GLuint i; + ASSERT(mask); + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE pixel[4]; + STORE_PIXEL(pixel, x[i], y[i], src); + PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel); + } + } + (void) rb; +} + + +#undef NAME +#undef RB_TYPE +#undef RB_COMPONENTS +#undef CI_MODE +#undef SPAN_VARS +#undef INIT_PIXEL_PTR +#undef INC_PIXEL_PTR +#undef STORE_PIXEL +#undef STORE_PIXEL_RGB +#undef FETCH_PIXEL