diff options
author | Alan Hourihane <[email protected]> | 2003-12-04 13:38:06 +0000 |
---|---|---|
committer | Alan Hourihane <[email protected]> | 2003-12-04 13:38:06 +0000 |
commit | 13e6a4849c6800eac454fd1010cb2320874f2ed6 (patch) | |
tree | c311173244771131a63ba18318be645b4534521c /src | |
parent | 15af25aca0ed6a2390fe9e0d91055cfc01134ce2 (diff) |
add SPARC ffb DRI driver
Diffstat (limited to 'src')
38 files changed, 6958 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/ffb/Makefile.X11 b/src/mesa/drivers/dri/ffb/Makefile.X11 new file mode 100644 index 00000000000..3e87f9bbcc7 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/Makefile.X11 @@ -0,0 +1,130 @@ + +# Mesa 3-D graphics library +# Version: 5.0 +# Copyright (C) 1995-2002 Brian Paul + +TOP = ../../../../.. + +default: linux-solo + +SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver +MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini + +DEFINES += \ + -D_HAVE_SWRAST=1 \ + -D_HAVE_SWTNL=1 \ + -D_HAVE_SANITY=1 \ + -D_HAVE_CODEGEN=1 \ + -D_HAVE_LIGHTING=1 \ + -D_HAVE_TEXGEN=1 \ + -D_HAVE_USERCLIP=1 \ + -DGLX_DIRECT_RENDERING + +# not yet +# MINIGLX_SOURCES = server/ffb_dri.c + +DRIVER_SOURCES = ffb_bitmap.c \ + ../common/mm.c \ + ../common/utils.c \ + ../common/texmem.c \ + ../common/vblank.c \ + ../common/xmlconfig.c \ + ffb_clear.c \ + ffb_dd.c \ + ffb_depth.c \ + ffb_fog.c \ + ffb_lines.c \ + ffb_points.c \ + ffb_span.c \ + ffb_state.c \ + ffb_stencil.c \ + ffb_tex.c \ + ffb_tris.c \ + ffb_vb.c \ + ffb_vtxfmt.c \ + ffb_xmesa.c + +INCLUDES = $(MINIGLX_INCLUDES) \ + $(SHARED_INCLUDES) + + +C_SOURCES = $(DRIVER_SOURCES) \ + $(MINIGLX_SOURCES) + +MESA_MODULES = $(TOP)/src/mesa/mesa.a + + +ifeq ($(WINDOW_SYSTEM),dri) +WINOBJ=$(MESABUILDDIR)/dri/dri.a +WINLIB= +else +WINOBJ= +WINLIB=-L$(MESA)/src/glx/mini +endif + +ASM_SOURCES = +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) + +$(SYMLINKS): + mkdir -p server + cd server + rm -f $@ && ln -s ../../radeon/$@ $@ + + +### Include directories + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/mesa/math \ + -I$(TOP)/src/mesa/transform \ + -I$(TOP)/src/mesa/swrast \ + -I$(TOP)/src/mesa/swrast_setup + + +##### RULES ##### + +.c.o: + $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +targets: depend ffb_dri.so + +ffb_dri.so: $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11 + rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS) + rm -f $(TOP)/lib/ffb_dri.so && \ + install ffb_dri.so $(TOP)/lib/ffb_dri.so + +$(TOP)/lib/ffb_dri.so: ffb_dri.so + rm -f $(TOP)/lib/ffb_dri.so && \ + install ffb_dri.so $(TOP)/lib/ffb_dri.so + +# Run 'make -f Makefile.X11 dep' to update the dependencies if you change +# what's included by any source file. +depend: $(C_SOURCES) $(ASM_SOURCES) + makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \ + $(C_SOURCES) $(ASM_SOURCES) + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + + +# Remove .o and backup files +clean: + -rm -f *.o */*.o *~ *.o *~ *.so server/*.o + -rm -f $(SYMLINKS) + + +include $(TOP)/Make-config + +include depend diff --git a/src/mesa/drivers/dri/ffb/ffb_bitmap.c b/src/mesa/drivers/dri/ffb/ffb_bitmap.c new file mode 100644 index 00000000000..8c94bde36fa --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_bitmap.c @@ -0,0 +1,156 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_bitmap.c,v 1.1 2002/02/22 21:32:58 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "ffb_context.h" +#include "ffb_state.h" +#include "ffb_lock.h" +#include "ffb_bitmap.h" +#include "swrast/swrast.h" +#include "image.h" +#include "macros.h" + +#undef FFB_BITMAP_TRACE + +static void +ffb_bitmap(GLcontext *ctx, GLint px, GLint py, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_fbcPtr ffb = fmesa->regs; + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + unsigned int ppc, pixel; + GLint row, col, row_stride; + const GLubyte *src; + char *buf; + + if (fmesa->bad_fragment_attrs != 0) + _swrast_Bitmap(ctx, px, py, width, + height, unpack, bitmap); + + pixel = (((((GLuint)(ctx->Current.RasterColor[0] * 255.0f)) & 0xff) << 0) | + ((((GLuint)(ctx->Current.RasterColor[1] * 255.0f)) & 0xff) << 8) | + ((((GLuint)(ctx->Current.RasterColor[2] * 255.0f)) & 0xff) << 16) | + ((((GLuint)(ctx->Current.RasterColor[3] * 255.0f)) & 0xff) << 24)); + +#ifdef FFB_BITMAP_TRACE + fprintf(stderr, "ffb_bitmap: ppc(%08x) fbc(%08x) cmp(%08x) pixel(%08x)\n", + fmesa->ppc, fmesa->fbc, fmesa->cmp, pixel); +#endif + + LOCK_HARDWARE(fmesa); + fmesa->hw_locked = 1; + + if (fmesa->state_dirty) + ffbSyncHardware(fmesa); + + ppc = fmesa->ppc; + + FFBFifo(fmesa, 4); + ffb->ppc = ((ppc & + ~(FFB_PPC_TBE_MASK | FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK)) + | (FFB_PPC_TBE_TRANSPARENT | FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST | + (ctx->Color.BlendEnabled ? FFB_PPC_XS_CONST : FFB_PPC_XS_WID))); + ffb->constz = ((GLuint) (ctx->Current.RasterPos[2] * 0x0fffffff)); + ffb->fg = pixel; + ffb->fontinc = (0 << 16) | 32; + + buf = (char *)(fmesa->sfb32 + (dPriv->x << 2) + (dPriv->y << 13)); + + row_stride = (unpack->Alignment * CEILING(width, 8 * unpack->Alignment)); + src = (const GLubyte *) (bitmap + + (unpack->SkipRows * row_stride) + + (unpack->SkipPixels / 8)); + if (unpack->LsbFirst == GL_TRUE) { + for (row = 0; row < height; row++, src += row_stride) { + const GLubyte *row_src = src; + GLuint base_x, base_y; + + base_x = dPriv->x + px; + base_y = dPriv->y + (dPriv->h - (py + row)); + + FFBFifo(fmesa, 1); + ffb->fontxy = (base_y << 16) | base_x; + + for (col = 0; col < width; col += 32, row_src += 4) { + GLint bitnum, font_w = (width - col); + GLuint font_data; + + if (font_w > 32) + font_w = 32; + font_data = 0; + for (bitnum = 0; bitnum < 32; bitnum++) { + const GLubyte val = row_src[bitnum >> 3]; + + if (val & (1 << (bitnum & (8 - 1)))) + font_data |= (1 << (31 - bitnum)); + } + + FFBFifo(fmesa, 2); + ffb->fontw = font_w; + ffb->font = font_data; + } + } + } else { + for (row = 0; row < height; row++, src += row_stride) { + const GLubyte *row_src = src; + GLuint base_x, base_y; + + base_x = dPriv->x + px; + base_y = dPriv->y + (dPriv->h - (py + row)); + + FFBFifo(fmesa, 1); + ffb->fontxy = (base_y << 16) | base_x; + + for (col = 0; col < width; col += 32, row_src += 4) { + GLint font_w = (width - col); + + if (font_w > 32) + font_w = 32; + FFBFifo(fmesa, 2); + ffb->fontw = font_w; + ffb->font = (((unsigned int)row_src[0]) << 24 | + ((unsigned int)row_src[1]) << 16 | + ((unsigned int)row_src[2]) << 8 | + ((unsigned int)row_src[3]) << 0); + } + } + } + + FFBFifo(fmesa, 1); + ffb->ppc = ppc; + fmesa->ffbScreen->rp_active = 1; + + UNLOCK_HARDWARE(fmesa); + fmesa->hw_locked = 0; +} + +void ffbDDInitBitmapFuncs(GLcontext *ctx) +{ + ctx->Driver.Bitmap = ffb_bitmap; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_bitmap.h b/src/mesa/drivers/dri/ffb/ffb_bitmap.h new file mode 100644 index 00000000000..4f8d2ea2a6a --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_bitmap.h @@ -0,0 +1,8 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_bitmap.h,v 1.1 2002/02/22 21:32:58 dawes Exp $ */ + +#ifndef _FFB_BITMAP_H +#define _FFB_BITMAP_H + +extern void ffbDDInitBitmapFuncs(GLcontext *); + +#endif /* !(_FFB_BITMAP_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_clear.c b/src/mesa/drivers/dri/ffb/ffb_clear.c new file mode 100644 index 00000000000..5285774f6f2 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_clear.c @@ -0,0 +1,354 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.c,v 1.2 2002/02/22 21:32:58 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "extensions.h" + +#include "mm.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_depth.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "ffb_tris.h" +#include "ffb_clear.h" +#include "ffb_lock.h" + +#undef CLEAR_TRACE + +#define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h)) + +/* Compute the page aligned box for a page mode fast fill. + * In 'ework' this returns greater than zero if there are some odd + * edges to take care of which are outside of the page aligned area. + * It will place less than zero there if the box is too small, + * indicating that a different method must be used to fill it. + */ +#define CreatorPageFillParms(ffp, x, y, w, h, px, py, pw, ph, ework) \ +do { int xdiff, ydiff; \ + int pf_bh = ffp->pagefill_height; \ + int pf_bw = ffp->pagefill_width; \ + py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \ + ydiff = py - y; \ + px = ffp->Pf_AlignTab[x + (pf_bw - 1)]; \ + xdiff = px - x; \ + ph = ((h - ydiff) & ~(pf_bh - 1)); \ + if(ph <= 0) \ + ework = -1; \ + else { \ + pw = ffp->Pf_AlignTab[w - xdiff]; \ + if(pw <= 0) { \ + ework = -1; \ + } else { \ + ework = (((xdiff > 0) || \ + (ydiff > 0) || \ + ((w - pw) > 0) || \ + ((h - ph) > 0))) ? 1 : 0; \ + } \ + } \ +} while(0); + +struct ff_fixups { + int x, y, width, height; +}; + +/* Compute fixups of non-page aligned areas after a page fill. + * Return the number of fixups needed. + */ +static __inline__ int +CreatorComputePageFillFixups(struct ff_fixups *fixups, + int x, int y, int w, int h, + int paligned_x, int paligned_y, + int paligned_w, int paligned_h) +{ + int nfixups = 0; + + /* FastFill Left */ + if(paligned_x != x) { + fixups[nfixups].x = x; + fixups[nfixups].y = paligned_y; + fixups[nfixups].width = paligned_x - x; + fixups[nfixups].height = paligned_h; + nfixups++; + } + /* FastFill Top */ + if(paligned_y != y) { + fixups[nfixups].x = x; + fixups[nfixups].y = y; + fixups[nfixups].width = w; + fixups[nfixups].height = paligned_y - y; + nfixups++; + } + /* FastFill Right */ + if((x+w) != (paligned_x+paligned_w)) { + fixups[nfixups].x = (paligned_x+paligned_w); + fixups[nfixups].y = paligned_y; + fixups[nfixups].width = (x+w) - fixups[nfixups].x; + fixups[nfixups].height = paligned_h; + nfixups++; + } + /* FastFill Bottom */ + if((y+h) != (paligned_y+paligned_h)) { + fixups[nfixups].x = x; + fixups[nfixups].y = (paligned_y+paligned_h); + fixups[nfixups].width = w; + fixups[nfixups].height = (y+h) - fixups[nfixups].y; + nfixups++; + } + return nfixups; +} + +static void +ffb_do_clear(ffbContextPtr fmesa, __DRIdrawablePrivate *dPriv, + GLboolean all, GLint cx, GLint cy, GLint cwidth, + GLint cheight) +{ + FFBDRIPtr gDRIPriv = (FFBDRIPtr) fmesa->driScreen->pDevPriv; + ffb_fbcPtr ffb = fmesa->regs; + XF86DRIClipRectPtr box = dPriv->pClipRects; + int nc = dPriv->numClipRects; + + cy = dPriv->h - cy - cheight; + cx += dPriv->x; + cy += dPriv->y; + + while (nc--) { + GLint x = box[nc].x1; + GLint y = box[nc].y1; + GLint width = box[nc].x2 - x; + GLint height = box[nc].y2 - y; + int paligned_y, paligned_x; + int paligned_h, paligned_w = 0; + int extra_work; + + if (!all) { + if (x < cx) { + width -= cx - x; + x = cx; + } + if (y < cy) { + height -= cy - y; + y = cy; + } + if (x + width > cx + cwidth) + width = cx + cwidth - x; + if (y + height > cy + cheight) + height = cy + cheight - y; + if (width <= 0) + continue; + if (height <= 0) + continue; + } + + if (BOX_AREA(width, height) < gDRIPriv->fastfill_small_area) { + FFBFifo(fmesa, 5); + ffb->drawop = FFB_DRAWOP_RECTANGLE; + ffb->by = y; + ffb->bx = x; + ffb->bh = height; + ffb->bw = width; + continue; + } + + FFBFifo(fmesa, 1); + ffb->drawop = FFB_DRAWOP_FASTFILL; + + if (gDRIPriv->disable_pagefill || + (width < (gDRIPriv->pagefill_width<<1)) || + (height < (gDRIPriv->pagefill_height<<1))) + goto do_fastfill; + + CreatorPageFillParms(gDRIPriv, + x, y, width, height, + paligned_x, paligned_y, + paligned_w, paligned_h, extra_work); + + if (extra_work < 0 || + BOX_AREA(paligned_w, paligned_h) < gDRIPriv->pagefill_small_area) { + do_fastfill: + FFBFifo(fmesa, 10); + ffb->by = FFB_FASTFILL_COLOR_BLK; + ffb->dy = 0; + ffb->dx = 0; + ffb->bh = gDRIPriv->fastfill_height; + ffb->bw = (gDRIPriv->fastfill_width * 4); + ffb->by = FFB_FASTFILL_BLOCK; + ffb->dy = y; + ffb->dx = x; + ffb->bh = (height + (y & (gDRIPriv->fastfill_height - 1))); + ffb->bx = (width + (x & (gDRIPriv->fastfill_width - 1))); + continue; + } + + /* Ok, page fill is possible and worth it. */ + FFBFifo(fmesa, 15); + ffb->by = FFB_FASTFILL_COLOR_BLK; + ffb->dy = 0; + ffb->dx = 0; + ffb->bh = gDRIPriv->fastfill_height; + ffb->bw = gDRIPriv->fastfill_width * 4; + ffb->by = FFB_FASTFILL_BLOCK_X; + ffb->dy = 0; + ffb->dx = 0; + ffb->bh = gDRIPriv->pagefill_height; + ffb->bw = gDRIPriv->pagefill_width * 4; + ffb->by = FFB_FASTFILL_PAGE; + ffb->dy = paligned_y; + ffb->dx = paligned_x; + ffb->bh = paligned_h; + ffb->bx = paligned_w; + + if (extra_work) { + struct ff_fixups local_fixups[4]; + int nfixups; + + nfixups = CreatorComputePageFillFixups(local_fixups, + x, y, width, height, + paligned_x, paligned_y, + paligned_w, paligned_h); + FFBFifo(fmesa, 5 + (nfixups * 5)); + ffb->by = FFB_FASTFILL_COLOR_BLK; + ffb->dy = 0; + ffb->dx = 0; + ffb->bh = gDRIPriv->fastfill_height; + ffb->bw = gDRIPriv->fastfill_width * 4; + + while (--nfixups >= 0) { + int xx, yy, ww, hh; + + xx = local_fixups[nfixups].x; + yy = local_fixups[nfixups].y; + ffb->dy = yy; + ffb->dx = xx; + ww = (local_fixups[nfixups].width + + (xx & (gDRIPriv->fastfill_width - 1))); + hh = (local_fixups[nfixups].height + + (yy & (gDRIPriv->fastfill_height - 1))); + if (nfixups != 0) { + ffb->by = FFB_FASTFILL_BLOCK; + ffb->bh = hh; + ffb->bw = ww; + } else { + ffb->bh = hh; + ffb->by = FFB_FASTFILL_BLOCK; + ffb->bx = ww; + } + } + } + } +} + +void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cwidth, GLint cheight) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + unsigned int stcmask = DD_STENCIL_BIT; + +#ifdef CLEAR_TRACE + fprintf(stderr, "ffbDDClear: mask(%08x) all(%d) " + "[x(%x)y(%x)w(%x)h(%x)]\n", + mask, (int) all, cx, cy, cwidth, cheight); +#endif + if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) + stcmask = 0; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT | stcmask)) { + ffb_fbcPtr ffb = fmesa->regs; + unsigned int fbc, ppc; + + fbc = (FFB_FBC_XE_ON); + ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE | + FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_DISABLE | + FFB_PPC_APE_DISABLE | FFB_PPC_XS_WID | + FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST); + + /* Y/X enables must be both on or both off. */ + if (mask & (DD_DEPTH_BIT | stcmask)) { + fbc |= (FFB_FBC_ZE_ON | FFB_FBC_YE_ON | FFB_FBC_WB_C); + } else + fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF; + + /* All RGB enables must be both on or both off. */ + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + if (mask & DD_FRONT_LEFT_BIT) { + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_WB_B; + else + fbc |= FFB_FBC_WB_A; + } + if (mask & DD_BACK_LEFT_BIT) { + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_WB_A; + else + fbc |= FFB_FBC_WB_B; + } + fbc |= FFB_FBC_RGBE_ON; + } else + fbc |= FFB_FBC_RGBE_OFF; + + LOCK_HARDWARE(fmesa); + + if (dPriv->numClipRects) { + FFBFifo(fmesa, 8); + ffb->fbc = fbc; + ffb->ppc = ppc; + ffb->xclip = FFB_XCLIP_TEST_ALWAYS; + ffb->cmp = 0x80808080; + ffb->rop = FFB_ROP_NEW; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) + ffb->fg = fmesa->clear_pixel; + if (mask & DD_DEPTH_BIT) + ffb->constz = fmesa->clear_depth; + if (mask & stcmask) + ffb->consty = fmesa->clear_stencil; + + ffb_do_clear(fmesa, dPriv, all, cx, cy, cwidth, cheight); + + FFBFifo(fmesa, 6); + ffb->ppc = fmesa->ppc; + ffb->fbc = fmesa->fbc; + ffb->xclip = fmesa->xclip; + ffb->cmp = fmesa->cmp; + ffb->rop = fmesa->rop; + ffb->drawop = fmesa->drawop; + if (mask & stcmask) + ffb->consty = fmesa->consty; + fmesa->ffbScreen->rp_active = 1; + } + + UNLOCK_HARDWARE(fmesa); + + mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | + DD_DEPTH_BIT | stcmask); + } + + if (mask) + _swrast_Clear(ctx, mask, all, cx, cy, cwidth, cheight); +} + diff --git a/src/mesa/drivers/dri/ffb/ffb_clear.h b/src/mesa/drivers/dri/ffb/ffb_clear.h new file mode 100644 index 00000000000..4b707f19b2a --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_clear.h @@ -0,0 +1,9 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */ + +#ifndef _FFB_CLEAR_H +#define _FFB_CLEAR_H + +extern void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cwidth, GLint cheight); + +#endif /* !(_FFB_CLEAR_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_context.h b/src/mesa/drivers/dri/ffb/ffb_context.h new file mode 100644 index 00000000000..6e68b6dd28f --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_context.h @@ -0,0 +1,309 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_context.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */ + +#ifndef _FFB_CONTEXT_H +#define _FFB_CONTEXT_H + +#include "dri_util.h" + +#include "mtypes.h" + +#include "ffb_xmesa.h" + +typedef struct { + GLfloat alpha; + GLfloat red; + GLfloat green; + GLfloat blue; +} ffb_color; + +#define FFB_GET_ALPHA(VTX) \ + FFB_COLOR_FROM_FLOAT((VTX)->color[0].alpha) +#define FFB_GET_RED(VTX) \ + FFB_COLOR_FROM_FLOAT((VTX)->color[0].red) +#define FFB_GET_GREEN(VTX) \ + FFB_COLOR_FROM_FLOAT((VTX)->color[0].green) +#define FFB_GET_BLUE(VTX) \ + FFB_COLOR_FROM_FLOAT((VTX)->color[0].blue) + +typedef struct { + GLfloat x, y, z; + ffb_color color[2]; +} ffb_vertex; + +#define FFB_DELAYED_VIEWPORT_VARS \ + GLfloat VP_SX = fmesa->hw_viewport[MAT_SX]; \ + GLfloat VP_TX = fmesa->hw_viewport[MAT_TX]; \ + GLfloat VP_SY = fmesa->hw_viewport[MAT_SY]; \ + GLfloat VP_TY = fmesa->hw_viewport[MAT_TY]; \ + GLfloat VP_SZ = fmesa->hw_viewport[MAT_SZ]; \ + GLfloat VP_TZ = fmesa->hw_viewport[MAT_TZ]; \ + (void) VP_SX; (void) VP_SY; (void) VP_SZ; \ + (void) VP_TX; (void) VP_TY; (void) VP_TZ + +#define FFB_GET_Z(VTX) \ + FFB_Z_FROM_FLOAT(VP_SZ * (VTX)->z + VP_TZ) +#define FFB_GET_Y(VTX) \ + FFB_XY_FROM_FLOAT(VP_SY * (VTX)->y + VP_TY) +#define FFB_GET_X(VTX) \ + FFB_XY_FROM_FLOAT(VP_SX * (VTX)->x + VP_TX) + +typedef void (*ffb_point_func)(GLcontext *, ffb_vertex *); +typedef void (*ffb_line_func)(GLcontext *, ffb_vertex *, ffb_vertex *); +typedef void (*ffb_tri_func)(GLcontext *, ffb_vertex *, ffb_vertex *, + ffb_vertex *); +typedef void (*ffb_quad_func)(GLcontext *, ffb_vertex *, ffb_vertex *, + ffb_vertex *, ffb_vertex *); + +/* Immediate mode fast-path support. */ +typedef struct { + GLfloat obj[4]; + GLfloat normal[4]; + GLfloat clip[4]; + GLuint mask; + GLfloat color[4]; + GLfloat win[4]; + GLfloat eye[4]; +} ffbTnlVertex, *ffbTnlVertexPtr; + +typedef void (*ffb_interp_func)(GLfloat t, + ffbTnlVertex *O, + const ffbTnlVertex *I, + const ffbTnlVertex *J); + +struct ffb_current_state { + GLfloat color[4]; + GLfloat normal[4]; + GLfloat specular[4]; +}; + +struct ffb_light_state { + GLfloat base_color[3]; + GLfloat base_alpha; +}; + +struct ffb_vertex_state { + struct ffb_current_state current; + struct ffb_light_state light; +}; + +struct ffb_imm_vertex { + ffbTnlVertex vertices[8]; + ffbTnlVertex *v0; + ffbTnlVertex *v1; + ffbTnlVertex *v2; + ffbTnlVertex *v3; + + void (*save_vertex)(GLcontext *ctx, ffbTnlVertex *v); + void (*flush_vertex)(GLcontext *ctx, ffbTnlVertex *v); + + ffb_interp_func interp; + + GLuint prim, format; + + GLvertexformat vtxfmt; +}; + +typedef struct ffb_context_t { + GLcontext *glCtx; + GLframebuffer *glBuffer; + + /* Temporaries for translating to float colors. */ + struct gl_client_array FloatColor; + struct gl_client_array FloatSecondaryColor; + + ffb_fbcPtr regs; + volatile char *sfb32; + + int hw_locked; + + int back_buffer; /* 0 = bufferA, 1 = bufferB */ + + /* Viewport matrix. */ + GLfloat hw_viewport[16]; +#define SUBPIXEL_X (-0.5F) +#define SUBPIXEL_Y (-0.5F + 0.125) + + /* Vertices in driver format. */ + ffb_vertex *verts; + + /* Rasterization functions. */ + ffb_point_func draw_point; + ffb_line_func draw_line; + ffb_tri_func draw_tri; + ffb_quad_func draw_quad; + + GLenum raster_primitive; + GLenum render_primitive; + + GLfloat backface_sign; + GLfloat depth_scale; + + GLfloat ffb_2_30_fixed_scale; + GLfloat ffb_one_over_2_30_fixed_scale; + GLfloat ffb_16_16_fixed_scale; + GLfloat ffb_one_over_16_16_fixed_scale; + GLfloat ffb_ubyte_color_scale; + GLfloat ffb_zero; + + /* Immediate mode state. */ + struct ffb_vertex_state vtx_state; + struct ffb_imm_vertex imm; + + /* Debugging knobs. */ + GLboolean debugFallbacks; + + /* This records state bits when a per-fragment attribute has + * been set which prevents us from rendering in hardware. + * + * As attributes change, some of these bits may clear as + * we move back within the chips capabilities. If they + * all clear, we return to full hw rendering. + */ + unsigned int bad_fragment_attrs; +#define FFB_BADATTR_FOG 0x00000001 /* Bad fog possible only when < FFB2 */ +#define FFB_BADATTR_BLENDFUNC 0x00000002 /* Any non-const func based upon dst alpha */ +#define FFB_BADATTR_BLENDROP 0x00000004 /* Blend enabled and LogicOP != GL_COPY */ +#define FFB_BADATTR_BLENDEQN 0x00000008 /* Blend equation other than ADD */ +#define FFB_BADATTR_STENCIL 0x00000010 /* Stencil enabled when < FFB2+ */ +#define FFB_BADATTR_TEXTURE 0x00000020 /* Texture enabled */ +#define FFB_BADATTR_SWONLY 0x00000040 /* Environment var set */ + + unsigned int state_dirty; + unsigned int state_fifo_ents; +#define FFB_STATE_FBC 0x00000001 +#define FFB_STATE_PPC 0x00000002 +#define FFB_STATE_DRAWOP 0x00000004 +#define FFB_STATE_ROP 0x00000008 +#define FFB_STATE_LPAT 0x00000010 +#define FFB_STATE_PMASK 0x00000020 +#define FFB_STATE_XPMASK 0x00000040 +#define FFB_STATE_YPMASK 0x00000080 +#define FFB_STATE_ZPMASK 0x00000100 +#define FFB_STATE_XCLIP 0x00000200 +#define FFB_STATE_CMP 0x00000400 +#define FFB_STATE_MATCHAB 0x00000800 +#define FFB_STATE_MAGNAB 0x00001000 +#define FFB_STATE_MATCHC 0x00002000 +#define FFB_STATE_MAGNC 0x00004000 +#define FFB_STATE_DCUE 0x00008000 +#define FFB_STATE_BLEND 0x00010000 +#define FFB_STATE_CLIP 0x00020000 +#define FFB_STATE_STENCIL 0x00040000 +#define FFB_STATE_APAT 0x00080000 +#define FFB_STATE_WID 0x00100000 +#define FFB_STATE_ALL 0x001fffff + + unsigned int state_all_fifo_ents; + +#define FFB_MAKE_DIRTY(FMESA, STATE_MASK, FIFO_ENTS) \ +do { if ((STATE_MASK) & ~((FMESA)->state_dirty)) { \ + (FMESA)->state_dirty |= (STATE_MASK); \ + (FMESA)->state_fifo_ents += FIFO_ENTS; \ + } \ +} while (0) + + /* General hw reg state. */ + unsigned int fbc; + unsigned int ppc; + unsigned int drawop; + unsigned int rop; + + unsigned int lpat; +#define FFB_LPAT_BAD 0xffffffff + + unsigned int wid; + unsigned int pmask; + unsigned int xpmask; + unsigned int ypmask; + unsigned int zpmask; + unsigned int xclip; + unsigned int cmp; + unsigned int matchab; + unsigned int magnab; + unsigned int matchc; + unsigned int magnc; + + /* Depth cue unit hw reg state. */ + unsigned int dcss; /* All FFB */ + unsigned int dcsf; /* All FFB */ + unsigned int dcsb; /* All FFB */ + unsigned int dczf; /* All FFB */ + unsigned int dczb; /* All FFB */ + unsigned int dcss1; /* >=FFB2 only */ + unsigned int dcss2; /* >=FFB2 only */ + unsigned int dcss3; /* >=FFB2 only */ + unsigned int dcs2; /* >=FFB2 only */ + unsigned int dcs3; /* >=FFB2 only */ + unsigned int dcs4; /* >=FFB2 only */ + unsigned int dcd2; /* >=FFB2 only */ + unsigned int dcd3; /* >=FFB2 only */ + unsigned int dcd4; /* >=FFB2 only */ + + /* Blend unit hw reg state. */ + unsigned int blendc; + unsigned int blendc1; + unsigned int blendc2; + + /* ViewPort clipping hw reg state. */ + unsigned int vclipmin; + unsigned int vclipmax; + unsigned int vclipzmin; + unsigned int vclipzmax; + struct { + unsigned int min; + unsigned int max; + } aux_clips[4]; + + /* Stencil control hw reg state. >=FFB2+ only. */ + unsigned int stencil; + unsigned int stencilctl; + unsigned int consty; /* Stencil Ref */ + + /* Area pattern (used for polygon stipples). */ + unsigned int pattern[32]; + + /* Fog state. */ + float Znear, Zfar; + + drmContext hHWContext; + drmLock *driHwLock; + int driFd; + + unsigned int clear_pixel; + unsigned int clear_depth; + unsigned int clear_stencil; + + unsigned int setupindex; + unsigned int setupnewinputs; + unsigned int new_gl_state; + + __DRIdrawablePrivate *driDrawable; + __DRIscreenPrivate *driScreen; + ffbScreenPrivate *ffbScreen; + ffb_dri_state_t *ffb_sarea; +} ffbContextRec, *ffbContextPtr; + +#define FFB_CONTEXT(ctx) ((ffbContextPtr)((ctx)->DriverCtx)) + +/* We want the depth values written during software rendering + * to match what the hardware is going to put there when we + * hw render. + * + * The Z buffer is 28 bits deep. Smooth shaded primitives + * specify a 2:30 signed fixed point Z value in the range 0.0 + * to 1.0 inclusive. + * + * So for example, when hw rendering, the largest Z value of + * 1.0 would produce a value of 0x0fffffff in the actual Z + * buffer, which is the maximum value. + * + * Mesa's depth type is a 32-bit int, so we use the following macro + * to convert to/from FFB hw Z values. Note we also have to clear + * out the top bits as that is where the Y (stencil) buffer is stored + * and during hw Z buffer reads it is always there. (During writes + * we tell the hw to discard those top 4 bits). + */ +#define Z_TO_MESA(VAL) ((GLdepth)(((VAL) & 0x0fffffff) << (32 - 28))) +#define Z_FROM_MESA(VAL) (((GLuint)((GLdouble)(VAL))) >> (32 - 28)) + +#endif /* !(_FFB_CONTEXT_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_dd.c b/src/mesa/drivers/dri/ffb/ffb_dd.c new file mode 100644 index 00000000000..d0137000f7c --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_dd.c @@ -0,0 +1,116 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_dd.c,v 1.4 2002/09/11 19:49:07 tsi Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "mm.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_depth.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "ffb_tris.h" +#include "ffb_clear.h" +#include "ffb_lock.h" +#include "extensions.h" + +#define FFB_DATE "20021125" + +/* Mesa's Driver Functions */ + +static const GLubyte *ffbDDGetString(GLcontext *ctx, GLenum name) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + static char buffer[128]; + + switch (name) { + case GL_VENDOR: + return (GLubyte *) "David S. Miller"; + + case GL_RENDERER: + sprintf(buffer, "Mesa DRI FFB " FFB_DATE); + + if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2) + strncat(buffer, " FFB2", 5); + if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) + strncat(buffer, " FFB2PLUS", 9); + if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) + strncat(buffer, " PAC1", 5); + if (fmesa->ffb_sarea->flags & FFB_DRI_PAC2) + strncat(buffer, " PAC2", 5); + +#ifdef USE_SPARC_ASM + strncat(buffer, " Sparc", 6); +#endif + + return (GLubyte *) buffer; + + default: + return NULL; + }; +} + + +static void ffbBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height) +{ + GET_CURRENT_CONTEXT(ctx); + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + LOCK_HARDWARE(fmesa); + *width = fmesa->driDrawable->w; + *height = fmesa->driDrawable->h; + UNLOCK_HARDWARE(fmesa); +} + +void ffbDDExtensionsInit(GLcontext *ctx) +{ + /* Nothing for now until we start to add + * real acceleration. -DaveM + */ + + /* XXX Need to turn off GL_EXT_blend_func_separate for one. + * XXX Also BlendEquation should be turned off too, what + * XXX EXT is that assosciated with? + */ +} + +static void ffbDDFinish(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + LOCK_HARDWARE(fmesa); + FFBWait(fmesa, fmesa->regs); + UNLOCK_HARDWARE(fmesa); +} + +void ffbDDInitDriverFuncs(GLcontext *ctx) +{ + ctx->Driver.GetBufferSize = ffbBufferSize; + ctx->Driver.GetString = ffbDDGetString; + ctx->Driver.Clear = ffbDDClear; + + ctx->Driver.Finish = ffbDDFinish; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_dd.h b/src/mesa/drivers/dri/ffb/ffb_dd.h new file mode 100644 index 00000000000..4ffcbe6666c --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_dd.h @@ -0,0 +1,36 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_dd.h,v 1.1 2000/06/20 05:08:38 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D. + * Copyright (C) 2000 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#ifndef _FFB_DD_H +#define _FFB_DD_H + +#include "context.h" + +void ffbDDInitDriverFuncs(GLcontext *ctx); +void ffbDDExtensionsInit(GLcontext *ctx); + +#endif /* !(_FFB_DD_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_depth.c b/src/mesa/drivers/dri/ffb/ffb_depth.c new file mode 100644 index 00000000000..27f3589d104 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_depth.c @@ -0,0 +1,214 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_depth.c,v 1.2 2002/02/22 21:32:58 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "swrast/swrast.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_context.h" +#include "ffb_depth.h" +#include "ffb_lock.h" + +#include "swrast/swrast.h" + +#undef DEPTH_TRACE + +static void +FFBWriteDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLdepth depth[], const GLubyte mask[]) +{ +#ifdef DEPTH_TRACE + fprintf(stderr, "FFBWriteDepthSpan: n(%d) x(%d) y(%d)\n", + (int) n, x, y); +#endif + if (ctx->Depth.Mask) { + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + GLuint *zptr; + GLuint i; + + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 2); + fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_ON | + FFB_FBC_YE_OFF | FFB_FBC_RGBE_OFF); + fmesa->regs->ppc = FFB_PPC_ZS_VAR; + FFBWait(fmesa, fmesa->regs); + + y = (dPriv->h - y); + zptr = (GLuint *) + ((char *)fmesa->sfb32 + + ((dPriv->x + x) << 2) + + ((dPriv->y + y) << 13)); + + for (i = 0; i < n; i++) { + if (mask[i]) { + *zptr = Z_FROM_MESA(depth[i]); + } + zptr++; + } + + FFBFifo(fmesa, 2); + fmesa->regs->fbc = fmesa->fbc; + fmesa->regs->ppc = fmesa->ppc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); + } +} + +static void +FFBWriteDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], + const GLdepth depth[], const GLubyte mask[]) +{ +#ifdef DEPTH_TRACE + fprintf(stderr, "FFBWriteDepthPixels: n(%d)\n", (int) n); +#endif + if (ctx->Depth.Mask) { + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + char *zbase; + GLuint i; + + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 2); + fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_ON | + FFB_FBC_YE_OFF | FFB_FBC_RGBE_OFF); + fmesa->regs->ppc = FFB_PPC_ZS_VAR; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + zbase = ((char *)fmesa->sfb32 + + (dPriv->x << 2) + (dPriv->y << 13)); + + for (i = 0; i < n; i++) { + GLint y1 = (dPriv->h - y[i]); + GLint x1 = x[i]; + GLuint *zptr; + + zptr = (GLuint *) + (zbase + (x1 << 2) + (y1 << 13)); + if (mask[i]) + *zptr = Z_FROM_MESA(depth[i]); + } + + FFBFifo(fmesa, 2); + fmesa->regs->fbc = fmesa->fbc; + fmesa->regs->ppc = fmesa->ppc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); + } +} + +static void +FFBReadDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[]) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + GLuint *zptr; + GLuint i; + +#ifdef DEPTH_TRACE + fprintf(stderr, "FFBReadDepthSpan: n(%d) x(%d) y(%d)\n", + (int) n, x, y); +#endif + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 1); + fmesa->regs->fbc = FFB_FBC_RB_C; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + y = (dPriv->h - y); + zptr = (GLuint *) + ((char *)fmesa->sfb32 + + ((dPriv->x + x) << 2) + + ((dPriv->y + y) << 13)); + + for (i = 0; i < n; i++) { + depth[i] = Z_TO_MESA(*zptr); + zptr++; + } + + FFBFifo(fmesa, 1); + fmesa->regs->fbc = fmesa->fbc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); +} + +static void +FFBReadDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], + GLdepth depth[]) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + char *zbase; + GLuint i; + +#ifdef DEPTH_TRACE + fprintf(stderr, "FFBReadDepthPixels: n(%d)\n", (int) n); +#endif + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 1); + fmesa->regs->fbc = FFB_FBC_RB_C; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + zbase = ((char *)fmesa->sfb32 + + (dPriv->x << 2) + (dPriv->y << 13)); + + for (i = 0; i < n; i++) { + GLint y1 = (dPriv->h - y[i]); + GLint x1 = x[i]; + GLuint *zptr; + + zptr = (GLuint *) + (zbase + (x1 << 2) + (y1 << 13)); + depth[i] = Z_TO_MESA(*zptr); + } + + FFBFifo(fmesa, 1); + fmesa->regs->fbc = fmesa->fbc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); +} + +void ffbDDInitDepthFuncs(GLcontext *ctx) +{ + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + + swdd->WriteDepthSpan = FFBWriteDepthSpan; + swdd->ReadDepthSpan = FFBReadDepthSpan; + swdd->WriteDepthPixels = FFBWriteDepthPixels; + swdd->ReadDepthPixels = FFBReadDepthPixels; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_depth.h b/src/mesa/drivers/dri/ffb/ffb_depth.h new file mode 100644 index 00000000000..a098bfcc2a2 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_depth.h @@ -0,0 +1,8 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_depth.h,v 1.1 2000/06/20 05:08:38 dawes Exp $ */ + +#ifndef _FFB_DEPTH_H +#define _FFB_DEPTH_H + +extern void ffbDDInitDepthFuncs(GLcontext *ctx); + +#endif /* !(_FFB_DEPTH_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_fifo.h b/src/mesa/drivers/dri/ffb/ffb_fifo.h new file mode 100644 index 00000000000..886d71b76e6 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_fifo.h @@ -0,0 +1,28 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_fifo.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */ + +#ifndef _FFB_FIFO_H +#define _FFB_FIFO_H + +#define FFBFifo(__fmesa, __n) \ +do { ffbScreenPrivate *__fScrn = (__fmesa)->ffbScreen; \ + int __cur_slots = __fScrn->fifo_cache; \ + if ((__cur_slots - (__n)) < 0) { \ + ffb_fbcPtr __ffb = __fmesa->regs; \ + do { __cur_slots = (((int)__ffb->ucsr & FFB_UCSR_FIFO_MASK) - 4); \ + } while ((__cur_slots - (__n)) < 0); \ + } (__fScrn)->fifo_cache = (__cur_slots - (__n)); \ +} while(0) + +#define FFBWait(__fmesa, __ffb) \ +do { ffbScreenPrivate *__fScrn = (__fmesa)->ffbScreen; \ + if (__fScrn->rp_active) { \ + unsigned int __regval = (__ffb)->ucsr; \ + while((__regval & FFB_UCSR_ALL_BUSY) != 0) { \ + __regval = (__ffb)->ucsr; \ + } \ + __fScrn->fifo_cache = ((int)(__regval & FFB_UCSR_FIFO_MASK)) - 4; \ + __fScrn->rp_active = 0; \ + } \ +} while(0) + +#endif /* !(_FFB_FIFO_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_fog.c b/src/mesa/drivers/dri/ffb/ffb_fog.c new file mode 100644 index 00000000000..e6eca2390ee --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_fog.c @@ -0,0 +1,73 @@ + +/* FFB fog support: + * + * There are two levels of support for FOG in the Creator3D series. + * Both involve a depth cue unit and 1 or 4 slope factors and scales + * for varying the pixel intensity. + * + * Chips prior to FFB2 only have a single set of such settings, FFB2 + * and later have 4 settings. + * + * The basic depth cueing equation is: + * + * C_final = dcsf(z) * C_orig + (1 - dcsf(z)) * C_fog + * + * C_final -- The final color passed to blend unit or frame + * buffer (if blending is disabled). + * + * C_orig -- The color we start with, which comes either from + * the raster processor or cpu writes to the smart + * framebuffer aperture. + * + * C_fog -- This is the "fog" color, ie. the desired color + * at the deepest Z. + * + * dcsf(z) -- The depth cue scale as a function of Z. + * + * With pre-FFB2 chips there are four parameters to control the depth + * cue scaling. Here is a diagram: + * + * 1.0 ------------- + * | | | | + * | | | | + * Sfront XXXXX---+---+ + * | |X | | + * dcsf(z) | | X | | + * | | X| | + * Sback +---+---XXXXX + * | | | | + * 0.0 ------------- + * 0.0 Zf Zb 1.0 + * + * z + * Therefore: + * + * for Zf < z < Zb + * + * dcsf(z) = Sback + ((Sfront - Sback) / (Zf - Zb)) * (Zb - z) + * + * for z <= Zf + * + * dcsf(z) = Sfront + * + * for z >= Zb + * + * dcsf(z) = Sback + * + * With FFB2 and later, 3 more slope regions are provided, the first of + * them starts at the end of the region defined above and ends at a + * specified depth value, the next slop region starts there and ends + * at the next specified depth value, and so on. Each of the 3 slope + * regions also have scale and slope settings of their own. + * + * The C_fog color is programmed into the alpha blending unit color1 + * and color2 registers as follows: + * + * color1: -(C_fog) + * color2: C_fog - bg + * + * If alpha blending is disabled, the bg factor is zero. Note that + * the alpha blending color registers specify each of the RGB values + * as 9 bit 1:8 signed numbers in the range -1.00 to 0.ff inclusive. + * (ie. 0x100 == -1.00 and 0x0ff == +0.ff) + */ diff --git a/src/mesa/drivers/dri/ffb/ffb_lines.c b/src/mesa/drivers/dri/ffb/ffb_lines.c new file mode 100644 index 00000000000..fec6b9306f2 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_lines.c @@ -0,0 +1,112 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lines.c,v 1.2 2002/02/22 21:32:58 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "mm.h" +#include "mmath.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_depth.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "ffb_lines.h" +#include "ffb_tris.h" +#include "ffb_lock.h" +#include "extensions.h" + +#undef FFB_LINE_TRACE + +#define FFB_LINE_FLAT_BIT 0x01 +#define FFB_LINE_ALPHA_BIT 0x02 +#define MAX_FFB_LINE_FUNCS 0x04 + +static ffb_line_func ffb_line_tab[MAX_FFB_LINE_FUNCS]; + +/* If the line is not wide, we can support all of the line + * patterning and smooth shading features of OpenGL fully. + */ + +#define IND (0) +#define TAG(x) x +#include "ffb_linetmp.h" + +#define IND (FFB_LINE_FLAT_BIT) +#define TAG(x) x##_flat +#include "ffb_linetmp.h" + +#define IND (FFB_LINE_ALPHA_BIT) +#define TAG(x) x##_alpha +#include "ffb_linetmp.h" + +#define IND (FFB_LINE_ALPHA_BIT|FFB_LINE_FLAT_BIT) +#define TAG(x) x##_alpha_flat +#include "ffb_linetmp.h" + +void ffbDDLinefuncInit(void) +{ + init(); + init_flat(); + init_alpha(); + init_alpha_flat(); +} + +static void ffb_dd_line( GLcontext *ctx, GLuint e0, GLuint e1 ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_vertex *v0 = &fmesa->verts[e0]; + ffb_vertex *v1 = &fmesa->verts[e1]; + fmesa->draw_line( ctx, v0, v1 ); +} + +void ffbChooseLineState(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint ind = 0; + + tnl->Driver.Render.Line = ffb_dd_line; + + if (flags & DD_FLATSHADE) + ind |= FFB_LINE_FLAT_BIT; + + if ((flags & DD_LINE_STIPPLE) != 0 && + fmesa->lpat == FFB_LPAT_BAD) { + fmesa->draw_line = ffb_fallback_line; + return; + } + + /* If blending or the alpha test is enabled we need to + * provide alpha components to the chip, else we can + * do without it and thus feed vertex data to the chip + * more efficiently. + */ + if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled) + ind |= FFB_LINE_ALPHA_BIT; + + fmesa->draw_line = ffb_line_tab[ind]; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_lines.h b/src/mesa/drivers/dri/ffb/ffb_lines.h new file mode 100644 index 00000000000..d508c243ea2 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_lines.h @@ -0,0 +1,18 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lines.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */ + +#ifndef _FFB_LINES_H +#define _FFB_LINES_H + +#include "ffb_context.h" + +#define _FFB_NEW_LINE (_DD_NEW_FLATSHADE | \ + _DD_NEW_LINE_WIDTH | \ + _DD_NEW_LINE_STIPPLE | \ + _DD_NEW_LINE_SMOOTH | \ + _NEW_COLOR) + +extern void ffbDDLinefuncInit(void); +extern void ffbChooseLineState(GLcontext *); +extern void ffb_fallback_line( GLcontext *ctx, ffb_vertex *v0, ffb_vertex *v1 ); + +#endif /* !(_FFB_LINES_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_linetmp.h b/src/mesa/drivers/dri/ffb/ffb_linetmp.h new file mode 100644 index 00000000000..0951513ca12 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_linetmp.h @@ -0,0 +1,81 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_linetmp.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */ + +static __inline void TAG(ffb_line)(GLcontext *ctx, ffb_vertex *v0, + ffb_vertex *v1 ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_fbcPtr ffb = fmesa->regs; +#if (IND & FFB_LINE_FLAT_BIT) + const GLuint const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v1->color[0] ); +#endif + FFB_DELAYED_VIEWPORT_VARS; + +#ifdef FFB_LINE_TRACE + fprintf(stderr, "FFB: ffb_line [" +#if (IND & FFB_LINE_FLAT_BIT) + " FLAT" +#endif +#if (IND & FFB_LINE_ALPHA_BIT) + " ALPHA" +#endif + " ]\n"); +#endif + +#if (IND & FFB_LINE_FLAT_BIT) + FFBFifo(fmesa, 1); + ffb->fg = const_fg; +#ifdef FFB_LINE_TRACE + fprintf(stderr, "FFB: ffb_line confg_fg[%08x]\n", const_fg); +#endif +#endif + +#if (IND & FFB_LINE_FLAT_BIT) + /* (2 * 3) + 1 */ + FFBFifo(fmesa, 7); +#else +#if (IND & FFB_LINE_ALPHA_BIT) + /* (2 * 7) + 1 */ + FFBFifo(fmesa, 15); +#else + /* (2 * 6) + 1 */ + FFBFifo(fmesa, 13); +#endif +#endif + + /* Using DDLINE or AALINE, init the line pattern state. */ + ffb->lpat = fmesa->lpat; + +#if !(IND & FFB_LINE_FLAT_BIT) +#if (IND & FFB_LINE_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v0); +#endif + ffb->red = FFB_GET_RED(v0); + ffb->green = FFB_GET_GREEN(v0); + ffb->blue = FFB_GET_BLUE(v0); +#endif + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + +#if !(IND & FFB_LINE_FLAT_BIT) +#if (IND & FFB_LINE_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v1); +#endif + ffb->red = FFB_GET_RED(v1); + ffb->green = FFB_GET_GREEN(v1); + ffb->blue = FFB_GET_BLUE(v1); +#endif + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(init)(void) +{ + ffb_line_tab[IND] = TAG(ffb_line); +} + +#undef IND +#undef TAG diff --git a/src/mesa/drivers/dri/ffb/ffb_lock.h b/src/mesa/drivers/dri/ffb/ffb_lock.h new file mode 100644 index 00000000000..e6295dc0645 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_lock.h @@ -0,0 +1,33 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lock.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_LOCK_H +#define _FFB_LOCK_H + +#include "ffb_context.h" + +extern void ffbXMesaUpdateState(ffbContextPtr fmesa); +#define FFB_UPDATE_STATE(fmesa) ffbXMesaUpdateState(fmesa) + +/* Lock the hardware and validate our state. */ +#if defined(__i386__) +#define LOCK_HARDWARE(fmesa) +#define UNLOCK_HARDWARE(fmesa) +#else +#define LOCK_HARDWARE(fmesa) \ + do { \ + int __ret=0; \ + DRM_CAS(fmesa->driHwLock, fmesa->hHWContext, \ + (DRM_LOCK_HELD | fmesa->hHWContext), __ret);\ + if (__ret) { \ + drmGetLock(fmesa->driFd, fmesa->hHWContext, 0); \ + FFB_UPDATE_STATE(fmesa); \ + } \ + } while (0) + + +/* Unlock the hardware. */ +#define UNLOCK_HARDWARE(fmesa) \ + DRM_UNLOCK(fmesa->driFd, fmesa->driHwLock, fmesa->hHWContext); +#endif + +#endif /* !(_FFB_LOCK_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_points.c b/src/mesa/drivers/dri/ffb/ffb_points.c new file mode 100644 index 00000000000..6505530c788 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_points.c @@ -0,0 +1,94 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_points.c,v 1.2 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "mmath.h" +#include "ffb_dd.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "ffb_points.h" +#include "ffb_tris.h" +#include "ffb_lock.h" + + +#undef FFB_POINT_TRACE + +#define FFB_POINT_AA_BIT 0x01 + +static ffb_point_func ffb_point_tab[0x08]; + +#define IND (0) +#define TAG(x) x +#include "ffb_pointtmp.h" + +#define IND (FFB_POINT_AA_BIT) +#define TAG(x) x##_aa +#include "ffb_pointtmp.h" + +void ffbDDPointfuncInit(void) +{ + init(); + init_aa(); +} + +static void ffb_dd_points( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_vertex *fverts = fmesa->verts; + int i; + + if (VB->Elts == 0) { + for ( i = first ; i < last ; i++ ) { + if ( VB->ClipMask[i] == 0 ) { + fmesa->draw_point( ctx, &fverts[i] ); + } + } + } else { + for ( i = first ; i < last ; i++ ) { + GLuint e = VB->Elts[i]; + if ( VB->ClipMask[e] == 0 ) { + fmesa->draw_point( ctx, &fverts[e] ); + } + } + } +} + +void ffbChoosePointState(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint ind = 0; + + tnl->Driver.Render.Points = ffb_dd_points; + + if (flags & DD_POINT_SMOOTH) + ind |= FFB_POINT_AA_BIT; + + fmesa->draw_point = ffb_point_tab[ind]; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_points.h b/src/mesa/drivers/dri/ffb/ffb_points.h new file mode 100644 index 00000000000..7d5c1f8a034 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_points.h @@ -0,0 +1,15 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_points.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_POINTS_H +#define _FFB_POINTS_H + +extern void ffbDDPointfuncInit(void); + +#define _FFB_NEW_POINT (_DD_NEW_POINT_SIZE | \ + _DD_NEW_POINT_SMOOTH | \ + _NEW_COLOR) + +extern void ffbChoosePointState(GLcontext *); +extern void ffb_fallback_point( GLcontext *ctx, ffb_vertex *v0 ); + +#endif /* !(_FFB_POINTS_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_pointtmp.h b/src/mesa/drivers/dri/ffb/ffb_pointtmp.h new file mode 100644 index 00000000000..310c95d89bd --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_pointtmp.h @@ -0,0 +1,55 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_pointtmp.h,v 1.3 2002/02/22 21:32:59 dawes Exp $ */ + +static __inline void TAG(ffb_draw_point)(GLcontext *ctx, ffb_vertex *tmp ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_fbcPtr ffb = fmesa->regs; + FFB_DELAYED_VIEWPORT_VARS; + +#ifdef FFB_POINT_TRACE + fprintf(stderr, "FFB: ffb_point [" +#if (IND & FFB_POINT_AA_BIT) + "AA" +#endif + "] X(%f) Y(%f) Z(%f)\n", + tmp->x, tmp->y, tmp->z); +#endif + +#if (IND & FFB_POINT_AA_BIT) + FFBFifo(fmesa, 4); + + ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( tmp->color[0] ); + ffb->z = FFB_GET_Z(tmp); + ffb->y = FFB_GET_Y(tmp) + 0x8000 /* FIX ME */; + ffb->x = FFB_GET_X(tmp) + 0x8000 /* FIX ME */; +#else + { + unsigned int const_fg, const_z, h, w; + + const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( tmp->color[0] ); + const_z = Z_FROM_MESA(FFB_Z_TO_FLOAT(FFB_GET_Z(tmp))); + h = FFB_GET_Y(tmp) >> 16; + w = FFB_GET_X(tmp) >> 16; +#ifdef FFB_POINT_TRACE + fprintf(stderr, "FFB: ffb_point fg(%08x) z(%08x) h(%08x) w(%08x)\n", + const_fg, const_z, h, w); +#endif + FFBFifo(fmesa, 4); + ffb->fg = const_fg; + ffb->constz = const_z; + ffb->bh = h; + ffb->bw = w; + } +#endif + + fmesa->ffbScreen->rp_active = 1; +} + + +static void TAG(init)(void) +{ + ffb_point_tab[IND] = TAG(ffb_draw_point); +} + +#undef IND +#undef TAG diff --git a/src/mesa/drivers/dri/ffb/ffb_rendertmp.h b/src/mesa/drivers/dri/ffb/ffb_rendertmp.h new file mode 100644 index 00000000000..9d18db5fdad --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_rendertmp.h @@ -0,0 +1,648 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_rendertmp.h,v 1.2 2003/01/29 23:00:40 dawes Exp $ */ + +#define IMPL_LOCAL_VARS \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ + ffb_fbcPtr ffb = fmesa->regs; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + FFB_DELAYED_VIEWPORT_VARS; \ + (void) fmesa; (void) ffb; (void) elt + +#if (IND & FFB_FLAT_BIT) +#define FFB_DECLARE_CACHED_COLOR(NAME) \ + unsigned int NAME; +#define FFB_COMPUTE_CACHED_COLOR(NAME, VTX) \ + NAME = FFB_PACK_CONST_UBYTE_ARGB_COLOR((VTX)->color[0]) +#define FFB_CACHED_COLOR_SAME(NAME1, NAME2) \ + ((NAME1) == (NAME2)) +#define FFB_CACHED_COLOR_SET(NAME) \ + ffb->fg = (NAME) +#define FFB_CACHED_COLOR_UPDATE(NAME1, NAME2) \ + ffb->fg = (NAME1) = (NAME2) +#define FFB_SET_PRIM_COLOR(COLOR_VERTEX) \ + ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR((COLOR_VERTEX)->color[0]) +#define FFB_PRIM_COLOR_COST 1 +#define FFB_SET_VERTEX_COLOR(VTX) /**/ +#define FFB_VERTEX_COLOR_COST 0 +#else +#define FFB_DECLARE_CACHED_COLOR(NAME) /**/ +#define FFB_COMPUTE_CACHED_COLOR(NAME, VTX) /**/ +#define FFB_CACHED_COLOR_SAME(NAME1, NAME2) 0 +#define FFB_CACHED_COLOR_SET(NAME1) /**/ +#define FFB_CACHED_COLOR_UPDATE(NAME1, NAME2) /**/ +#define FFB_SET_PRIM_COLOR(COLOR_VERTEX) /**/ +#define FFB_PRIM_COLOR_COST 0 +#if (IND & FFB_ALPHA_BIT) +#define FFB_SET_VERTEX_COLOR(VTX) \ + ffb->alpha = FFB_GET_ALPHA(VTX); \ + ffb->red = FFB_GET_RED(VTX); \ + ffb->green = FFB_GET_GREEN(VTX); \ + ffb->blue = FFB_GET_BLUE(VTX) +#define FFB_VERTEX_COLOR_COST 4 +#else +#define FFB_SET_VERTEX_COLOR(VTX) \ + ffb->red = FFB_GET_RED(VTX); \ + ffb->green = FFB_GET_GREEN(VTX); \ + ffb->blue = FFB_GET_BLUE(VTX) +#define FFB_VERTEX_COLOR_COST 3 +#endif +#endif + +#define RESET_STIPPLE ffb->lpat = fmesa->lpat; + +#if !(IND & (FFB_TRI_CULL_BIT)) +static void TAG(ffb_vb_points)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_POINTS); + if (ctx->_TriangleCaps & DD_POINT_SMOOTH) { + for (i = start; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(i)]; + + FFBFifo(fmesa, 4); + ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR(v0->color[0]); + ffb->z = FFB_GET_Z(v0); + ffb->y = FFB_GET_Y(v0) + 0x8000 /* FIX ME */; + ffb->x = FFB_GET_X(v0) + 0x8000 /* FIX ME */; + } + } else { + for (i = start; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(i)]; + FFBFifo(fmesa, 4); + ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR(v0->color[0]); + ffb->constz = Z_FROM_MESA(FFB_Z_TO_FLOAT(FFB_GET_Z(v0))); + ffb->bh = FFB_GET_Y(v0) >> 16; + ffb->bw = FFB_GET_X(v0) >> 16; + } + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_lines)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_LINES); + for (i = start + 1; i < count; i += 2) { + ffb_vertex *v0 = &fmesa->verts[i - 1]; + ffb_vertex *v1 = &fmesa->verts[i - 0]; + + FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 2) + 6)); + + RESET_STIPPLE; + + FFB_SET_PRIM_COLOR(v1); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + } +} + +static void TAG(ffb_vb_line_loop)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_LINE_LOOP); + if ((flags & PRIM_BEGIN) != 0) { + ffb_vertex *v0 = &fmesa->verts[ELT(start + 0)]; + ffb_vertex *v1 = &fmesa->verts[ELT(start + 1)]; + + FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST + + ((FFB_VERTEX_COLOR_COST * 2) + (3 * 2)))); + + RESET_STIPPLE; + + FFB_SET_PRIM_COLOR(v1); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + } + for (i = start + 2; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(i)]; + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST + 3))); + + FFB_SET_PRIM_COLOR(v0); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->y = FFB_GET_Y(v0); + ffb->x = FFB_GET_X(v0); + } + if ((flags & PRIM_END) != 0) { + ffb_vertex *v0 = &fmesa->verts[ELT(start)]; + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST + 3))); + + FFB_SET_PRIM_COLOR(v0); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->y = FFB_GET_Y(v0); + ffb->x = FFB_GET_X(v0); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_line_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + FFB_DECLARE_CACHED_COLOR(cached_fg) + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_LINE_STRIP); + FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST + + ((FFB_VERTEX_COLOR_COST * 2) + (3 * 2)))); + + RESET_STIPPLE; + + { + ffb_vertex *v0 = &fmesa->verts[ELT(start + 0)]; + ffb_vertex *v1 = &fmesa->verts[ELT(start + 1)]; + + FFB_COMPUTE_CACHED_COLOR(cached_fg, v0); + FFB_CACHED_COLOR_SET(cached_fg); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + } + + for (i = start + 2; i < count; i++) { + ffb_vertex *v1 = &fmesa->verts[ELT(i - 0)]; + FFB_DECLARE_CACHED_COLOR(new_fg) + + FFB_COMPUTE_CACHED_COLOR(new_fg, v1); + if (FFB_CACHED_COLOR_SAME(cached_fg, new_fg)) { + FFBFifo(fmesa, ((FFB_VERTEX_COLOR_COST * 1) + (3 * 1))); + } else { + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 1) + (3 * 1))); + FFB_CACHED_COLOR_UPDATE(cached_fg, new_fg); + } + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + } + + fmesa->ffbScreen->rp_active = 1; +} +#endif /* !(IND & (FFB_TRI_CULL_BIT)) */ + +/* OK, now things start getting fun :-) */ +#if (IND & (FFB_TRI_CULL_BIT)) +#define FFB_AREA_DECLARE GLfloat cc, ex, ey, fx, fy; +#define FFB_COMPUTE_AREA_TRI(V0, V1, V2) \ +{ ex = (V1)->x - (V0)->x; \ + ey = (V1)->y - (V0)->y; \ + fx = (V2)->x - (V0)->x; \ + fy = (V2)->y - (V0)->y; \ + cc = ex*fy-ey*fx; \ +} +#define FFB_COMPUTE_AREA_QUAD(V0, V1, V2, V3) \ +{ ex = (V2)->x - (V0)->x; \ + ey = (V2)->y - (V0)->y; \ + fx = (V3)->x - (V1)->x; \ + fy = (V3)->y - (V1)->y; \ + cc = ex*fy-ey*fx; \ +} +#else +#define FFB_AREA_DECLARE /**/ +#define FFB_COMPUTE_AREA_TRI(V0, V1, V2) do { } while(0) +#define FFB_COMPUTE_AREA_QUAD(V0, V1, V2, V3) do { } while(0) +#endif + +#if (IND & FFB_TRI_CULL_BIT) +#define FFB_CULL_TRI(CULL_ACTION) \ + if (cc * fmesa->backface_sign > fmesa->ffb_zero) { \ + CULL_ACTION \ + } +#define FFB_CULL_QUAD(CULL_ACTION) \ + if (cc * fmesa->backface_sign > fmesa->ffb_zero) { \ + CULL_ACTION \ + } +#else +#define FFB_CULL_TRI(CULL_ACTION) do { } while (0) +#define FFB_CULL_QUAD(CULL_ACTION) do { } while (0) +#endif + +static void TAG(ffb_vb_triangles)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_TRIANGLES); + for (i = start + 2; i < count; i += 3) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 2)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 3) + 9)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_tri_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + GLint parity = 0; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_TRIANGLE_STRIP); + if ((flags & PRIM_PARITY) != 0) + parity = 1; + + i = start + 2; + goto something_clipped; + + something_clipped: + for (; i < count; i++, parity ^= 1) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 2 + parity)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 1 - parity)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 3) + 9)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + i++; + parity ^= 1; + break; + } + + for (; i < count; i++, parity ^= 1) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 2 + parity)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 1 - parity)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + (void) v0; (void) v1; + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(i++; parity^=1; goto something_clipped;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 1) + 3)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_tri_fan)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_TRIANGLE_FAN); + + i = start + 2; + goto something_clipped; + + something_clipped: + for ( ; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(start)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 3) + 9)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + i++; + break; + } + + for (; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(start)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + (void) v0; (void) v1; + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(i++; goto something_clipped;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 1) + 3)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->dmyf = FFB_GET_Y(v2); + ffb->dmxf = FFB_GET_X(v2); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_poly)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_POLYGON); + + /* XXX Optimize XXX */ + for (i = start + 2; i < count; i++) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i)]; + ffb_vertex *v2 = &fmesa->verts[ELT(start)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_TRI(v0, v1, v2); + FFB_CULL_TRI(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 3) + 9)); + FFB_SET_PRIM_COLOR(v2); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_quads)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_QUADS); + + for (i = start + 3; i < count; i += 4) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 3)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 2)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v3 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_QUAD(v0, v1, v2, v3); + FFB_CULL_QUAD(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 4) + 12)); + FFB_SET_PRIM_COLOR(v3); + + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + FFB_SET_VERTEX_COLOR(v3); + ffb->z = FFB_GET_Z(v3); + ffb->dmyf = FFB_GET_Y(v3); + ffb->dmxf = FFB_GET_X(v3); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_vb_quad_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + GLint i; + IMPL_LOCAL_VARS; + +#ifdef FFB_RENDER_TRACE + fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n", + __FUNCTION__, start, count, flags); +#endif + ffbRenderPrimitive(ctx, GL_QUAD_STRIP); + + /* XXX Optimize XXX */ + for (i = start + 3; i < count; i += 2) { + ffb_vertex *v0 = &fmesa->verts[ELT(i - 1)]; + ffb_vertex *v1 = &fmesa->verts[ELT(i - 3)]; + ffb_vertex *v2 = &fmesa->verts[ELT(i - 2)]; + ffb_vertex *v3 = &fmesa->verts[ELT(i - 0)]; + FFB_AREA_DECLARE + + FFB_COMPUTE_AREA_QUAD(v0, v1, v2, v3); + FFB_CULL_QUAD(continue;); + + FFBFifo(fmesa, (FFB_PRIM_COLOR_COST + + (FFB_VERTEX_COLOR_COST * 4) + 12)); + FFB_SET_PRIM_COLOR(v3); + + FFB_DUMP_VERTEX(v0); + FFB_SET_VERTEX_COLOR(v0); + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_DUMP_VERTEX(v1); + FFB_SET_VERTEX_COLOR(v1); + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_DUMP_VERTEX(v2); + FFB_SET_VERTEX_COLOR(v2); + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + FFB_DUMP_VERTEX(v3); + FFB_SET_VERTEX_COLOR(v3); + ffb->z = FFB_GET_Z(v3); + ffb->dmyf = FFB_GET_Y(v3); + ffb->dmxf = FFB_GET_X(v3); + } + + fmesa->ffbScreen->rp_active = 1; +} + +static void (*TAG(render_tab)[GL_POLYGON + 2])(GLcontext *, GLuint, GLuint, GLuint) = +{ +#if !(IND & (FFB_TRI_CULL_BIT)) + TAG(ffb_vb_points), + TAG(ffb_vb_lines), + TAG(ffb_vb_line_loop), + TAG(ffb_vb_line_strip), +#else + NULL, + NULL, + NULL, + NULL, +#endif + TAG(ffb_vb_triangles), + TAG(ffb_vb_tri_strip), + TAG(ffb_vb_tri_fan), + TAG(ffb_vb_quads), + TAG(ffb_vb_quad_strip), + TAG(ffb_vb_poly), + ffb_vb_noop, +}; + +#undef IND +#undef TAG + +#undef IMPL_LOCAL_VARS +#undef FFB_DECLARE_CACHED_COLOR +#undef FFB_COMPUTE_CACHED_COLOR +#undef FFB_CACHED_COLOR_SAME +#undef FFB_CACHED_COLOR_SET +#undef FFB_CACHED_COLOR_UPDATE +#undef FFB_SET_PRIM_COLOR +#undef FFB_PRIM_COLOR_COST +#undef FFB_SET_VERTEX_COLOR +#undef FFB_VERTEX_COLOR_COST +#undef RESET_STIPPLE +#undef FFB_AREA_DECLARE +#undef FFB_COMPUTE_AREA_TRI +#undef FFB_COMPUTE_AREA_QUAD +#undef FFB_CULL_TRI +#undef FFB_CULL_QUAD diff --git a/src/mesa/drivers/dri/ffb/ffb_span.c b/src/mesa/drivers/dri/ffb/ffb_span.c new file mode 100644 index 00000000000..6927945226b --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_span.c @@ -0,0 +1,142 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_span.c,v 1.2 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_context.h" +#include "ffb_lock.h" + +#include "swrast/swrast.h" + +#define DBG 0 + +#define HW_LOCK() \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ + if (!fmesa->hw_locked) \ + LOCK_HARDWARE(fmesa); + +#define HW_UNLOCK() \ + if (!fmesa->hw_locked) \ + UNLOCK_HARDWARE(fmesa); \ + +#define LOCAL_VARS \ + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; \ + GLuint height = dPriv->h; \ + GLuint p; \ + char *buf; \ + (void) p + +#define INIT_MONO_PIXEL(p, color) \ + p = ((color[0] << 0) | \ + (color[1] << 8) | \ + (color[2] << 16)) + +/* We use WID clipping, so this test always passes. */ +#define CLIPPIXEL(__x, __y) (1) + +/* And also, due to WID clipping, we need not do anything + * special here. + */ +#define CLIPSPAN(__x,__y,__n,__x1,__n1,__i) \ + __n1 = __n; \ + __x1 = __x; \ + +#define HW_CLIPLOOP() \ +do { unsigned int fbc, ppc, cmp; \ + FFBWait(fmesa, fmesa->regs); \ + fbc = fmesa->regs->fbc; ppc = fmesa->regs->ppc; cmp = fmesa->regs->cmp; \ + fmesa->regs->fbc = ((fbc & \ + ~(FFB_FBC_WB_C | FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK)) \ + | (FFB_FBC_ZE_OFF | FFB_FBC_RGBE_MASK)); \ + fmesa->regs->ppc = ((ppc & \ + ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK | FFB_PPC_DCE_MASK | \ + FFB_PPC_APE_MASK | FFB_PPC_CS_MASK)) \ + | (FFB_PPC_XS_WID | FFB_PPC_ABE_DISABLE | \ + FFB_PPC_DCE_DISABLE | FFB_PPC_APE_DISABLE | \ + FFB_PPC_CS_VAR)); \ + fmesa->regs->cmp = ((cmp & ~(0xff << 16)) | (0x80 << 16)); \ + fmesa->ffbScreen->rp_active = 1; \ + FFBWait(fmesa, fmesa->regs); \ + buf = (char *)(fmesa->sfb32 + (dPriv->x << 2) + (dPriv->y << 13));\ + if (dPriv->numClipRects) { + +#define HW_ENDCLIPLOOP() \ + } \ + fmesa->regs->fbc = fbc; \ + fmesa->regs->ppc = ppc; \ + fmesa->regs->cmp = cmp; \ + fmesa->ffbScreen->rp_active = 1; \ +} while(0) + +#define Y_FLIP(__y) (height - __y) + +#define READ_RGBA(rgba,__x,__y) \ +do { GLuint p = *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)); \ + rgba[0] = (p >> 0) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 16) & 0xff; \ + rgba[3] = 0xff; \ +} while(0) + +#define WRITE_RGBA(__x, __y, __r, __g, __b, __a) \ + *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)) = \ + ((((__r) & 0xff) << 0) | \ + (((__g) & 0xff) << 8) | \ + (((__b) & 0xff) << 16)) + +#define WRITE_PIXEL(__x, __y, __p) \ + *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)) = (__p) + +#define TAG(x) ffb##x##_888 + +#include <spantmp.h> + +void ffbDDInitSpanFuncs(GLcontext *ctx) +{ + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + + swdd->WriteRGBASpan = ffbWriteRGBASpan_888; + swdd->WriteRGBSpan = ffbWriteRGBSpan_888; + swdd->WriteRGBAPixels = ffbWriteRGBAPixels_888; + swdd->WriteMonoRGBASpan = ffbWriteMonoRGBASpan_888; + swdd->WriteMonoRGBAPixels = ffbWriteMonoRGBAPixels_888; + swdd->ReadRGBASpan = ffbReadRGBASpan_888; + swdd->ReadRGBAPixels = ffbReadRGBAPixels_888; + + /* We don't support color index mode yet, but it will be + * very easy to do. -DaveM + */ + swdd->WriteCI8Span = NULL; + swdd->WriteCI32Span = NULL; + swdd->WriteMonoCISpan = NULL; + swdd->WriteCI32Pixels = NULL; + swdd->WriteMonoCIPixels = NULL; + swdd->ReadCI32Span = NULL; + swdd->ReadCI32Pixels = NULL; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_span.h b/src/mesa/drivers/dri/ffb/ffb_span.h new file mode 100644 index 00000000000..00501e8230c --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_span.h @@ -0,0 +1,8 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_span.h,v 1.1 2000/06/20 05:08:39 dawes Exp $ */ + +#ifndef _FFB_SPAN_H +#define _FFB_SPAN_H + +extern void ffbDDInitSpanFuncs(GLcontext *ctx); + +#endif /* !(_FFB_SPAN_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_state.c b/src/mesa/drivers/dri/ffb/ffb_state.c new file mode 100644 index 00000000000..ba9bab9886a --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_state.c @@ -0,0 +1,1247 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.5 2002/10/30 12:51:27 alanh Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "colormac.h" +#include "mm.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_depth.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "ffb_tris.h" +#include "ffb_state.h" +#include "ffb_lock.h" +#include "extensions.h" +#include "enums.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" + +#undef STATE_TRACE + +static unsigned int ffbComputeAlphaFunc(GLcontext *ctx) +{ + unsigned int xclip; + GLubyte alphaRef; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDAlphaFunc: func(%s) ref(%02x)\n", + _mesa_lookup_enum_by_nr(ctx->Color.AlphaFunc), + ctx->Color.AlphaRef & 0xff); +#endif + + switch (ctx->Color.AlphaFunc) { + case GL_NEVER: xclip = FFB_XCLIP_TEST_NEVER; break; + case GL_LESS: xclip = FFB_XCLIP_TEST_LT; break; + case GL_EQUAL: xclip = FFB_XCLIP_TEST_EQ; break; + case GL_LEQUAL: xclip = FFB_XCLIP_TEST_LE; break; + case GL_GREATER: xclip = FFB_XCLIP_TEST_GT; break; + case GL_NOTEQUAL: xclip = FFB_XCLIP_TEST_NE; break; + case GL_GEQUAL: xclip = FFB_XCLIP_TEST_GE; break; + case GL_ALWAYS: xclip = FFB_XCLIP_TEST_ALWAYS; break; + + default: + return FFB_XCLIP_TEST_ALWAYS | 0x00; + } + + CLAMPED_FLOAT_TO_UBYTE(alphaRef, ctx->Color.AlphaRef); + xclip |= (alphaRef & 0xff); + + return xclip; +} + +static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + if (ctx->Color.AlphaEnabled) { + unsigned int xclip = ffbComputeAlphaFunc(ctx); + + if (fmesa->xclip != xclip) { + fmesa->xclip = xclip; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1); + } + } +} + +static void ffbDDBlendEquation(GLcontext *ctx, GLenum mode) +{ + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", _mesa_lookup_enum_by_nr(mode)); +#endif + FALLBACK( ctx, (mode != GL_FUNC_ADD_EXT), FFB_BADATTR_BLENDEQN); +} + +static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int blendc = 1 << 4; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDBlendFunc: sfactor(%s) dfactor(%s)\n", + _mesa_lookup_enum_by_nr(sfactor), _mesa_lookup_enum_by_nr(dfactor)); +#endif + switch (ctx->Color.BlendSrcRGB) { + case GL_ZERO: + blendc |= (0 << 0); + break; + + case GL_ONE: + blendc |= (1 << 0); + break; + + case GL_ONE_MINUS_SRC_ALPHA: + blendc |= (2 << 0); + break; + + case GL_SRC_ALPHA: + blendc |= (3 << 0); + break; + + default: + if (ctx->Color.BlendEnabled) + FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE ); + return; + }; + + switch (ctx->Color.BlendDstRGB) { + case GL_ZERO: + blendc |= (0 << 2); + break; + + case GL_ONE: + blendc |= (1 << 2); + break; + + case GL_ONE_MINUS_SRC_ALPHA: + blendc |= (2 << 2); + break; + + case GL_SRC_ALPHA: + blendc |= (3 << 2); + break; + + default: + if (ctx->Color.BlendEnabled) + FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE ); + return; + }; + + if (ctx->Color.BlendEnabled && + ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY) { + /* We could avoid this if sfactor is GL_ONE and + * dfactor is GL_ZERO. I do not think that is even + * worthwhile to check because if someone is using + * blending they use more interesting settings and + * also it would add more state tracking to a lot + * of the code in this file. + */ + FALLBACK(ctx, FFB_BADATTR_BLENDROP, GL_TRUE); + return; + } + + FALLBACK( ctx, (FFB_BADATTR_BLENDFUNC|FFB_BADATTR_BLENDROP), GL_FALSE ); + + if (blendc != fmesa->blendc) { + fmesa->blendc = blendc; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_BLEND, 1); + } +} + +static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA) +{ +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n", + _mesa_lookup_enum_by_nr(sfactorRGB), + _mesa_lookup_enum_by_nr(dfactorRGB), + _mesa_lookup_enum_by_nr(sfactorA), + _mesa_lookup_enum_by_nr(dfactorA)); +#endif + + ffbDDBlendFunc(ctx, sfactorRGB, dfactorRGB); +} + +static void ffbDDDepthFunc(GLcontext *ctx, GLenum func) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint cmp; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDDepthFunc: func(%s)\n", + _mesa_lookup_enum_by_nr(func)); +#endif + + switch (func) { + case GL_NEVER: + cmp = FFB_CMP_MAGN_NEVER; + break; + case GL_ALWAYS: + cmp = FFB_CMP_MAGN_ALWAYS; + break; + case GL_LESS: + cmp = FFB_CMP_MAGN_LT; + break; + case GL_LEQUAL: + cmp = FFB_CMP_MAGN_LE; + break; + case GL_EQUAL: + cmp = FFB_CMP_MAGN_EQ; + break; + case GL_GREATER: + cmp = FFB_CMP_MAGN_GT; + break; + case GL_GEQUAL: + cmp = FFB_CMP_MAGN_GE; + break; + case GL_NOTEQUAL: + cmp = FFB_CMP_MAGN_NE; + break; + default: + return; + }; + + if (! ctx->Depth.Test) + cmp = FFB_CMP_MAGN_ALWAYS; + + cmp <<= 16; + cmp = (fmesa->cmp & ~(0xff<<16)) | cmp; + if (cmp != fmesa->cmp) { + fmesa->cmp = cmp; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_CMP, 1); + } +} + +static void ffbDDDepthMask(GLcontext *ctx, GLboolean flag) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint fbc = fmesa->fbc; + GLboolean enabled_now; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDDepthMask: flag(%d)\n", flag); +#endif + + if ((fbc & FFB_FBC_ZE_MASK) == FFB_FBC_ZE_OFF) + enabled_now = GL_FALSE; + else + enabled_now = GL_TRUE; + + if (flag != enabled_now) { + fbc &= ~FFB_FBC_ZE_MASK; + if (flag) { + fbc |= FFB_FBC_WB_C | FFB_FBC_ZE_ON; + } else { + fbc |= FFB_FBC_ZE_OFF; + fbc &= ~FFB_FBC_WB_C; + } + fmesa->fbc = fbc; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); + } +} + +static void ffbDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int stencil, stencilctl, consty; + + /* We will properly update sw/hw state when stenciling is + * enabled. + */ + if (! ctx->Stencil.Enabled) + return; + + stencilctl = fmesa->stencilctl; + stencilctl &= ~(7 << 16); + + switch (func) { + case GL_ALWAYS: stencilctl |= (0 << 16); break; + case GL_GREATER: stencilctl |= (1 << 16); break; + case GL_EQUAL: stencilctl |= (2 << 16); break; + case GL_GEQUAL: stencilctl |= (3 << 16); break; + case GL_NEVER: stencilctl |= (4 << 16); break; + case GL_LEQUAL: stencilctl |= (5 << 16); break; + case GL_NOTEQUAL: stencilctl |= (6 << 16); break; + case GL_LESS: stencilctl |= (7 << 16); break; + + default: + return; + }; + + consty = ref & 0xf; + + stencil = fmesa->stencil; + stencil &= ~(0xf << 20); + stencil |= (mask & 0xf) << 20; + + if (fmesa->stencil != stencil || + fmesa->stencilctl != stencilctl || + fmesa->consty != consty) { + fmesa->stencil = stencil; + fmesa->stencilctl = stencilctl; + fmesa->consty = consty; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); + } +} + +static void ffbDDStencilMask(GLcontext *ctx, GLuint mask) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + mask &= 0xf; + if (fmesa->ypmask != mask) { + fmesa->ypmask = mask; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_YPMASK, 1); + } +} + +static void ffbDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int stencilctl; + + /* We will properly update sw/hw state when stenciling is + * enabled. + */ + if (! ctx->Stencil.Enabled) + return; + + stencilctl = fmesa->stencilctl; + stencilctl &= ~(0xfff00000); + + switch (fail) { + case GL_ZERO: stencilctl |= (0 << 28); break; + case GL_KEEP: stencilctl |= (1 << 28); break; + case GL_INVERT: stencilctl |= (2 << 28); break; + case GL_REPLACE: stencilctl |= (3 << 28); break; + case GL_INCR: stencilctl |= (4 << 28); break; + case GL_DECR: stencilctl |= (5 << 28); break; + + default: + return; + }; + + switch (zfail) { + case GL_ZERO: stencilctl |= (0 << 24); break; + case GL_KEEP: stencilctl |= (1 << 24); break; + case GL_INVERT: stencilctl |= (2 << 24); break; + case GL_REPLACE: stencilctl |= (3 << 24); break; + case GL_INCR: stencilctl |= (4 << 24); break; + case GL_DECR: stencilctl |= (5 << 24); break; + + default: + return; + }; + + switch (zpass) { + case GL_ZERO: stencilctl |= (0 << 20); break; + case GL_KEEP: stencilctl |= (1 << 20); break; + case GL_INVERT: stencilctl |= (2 << 20); break; + case GL_REPLACE: stencilctl |= (3 << 20); break; + case GL_INCR: stencilctl |= (4 << 20); break; + case GL_DECR: stencilctl |= (5 << 20); break; + + default: + return; + }; + + if (fmesa->stencilctl != stencilctl) { + fmesa->stencilctl = stencilctl; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); + } +} + +static void ffbCalcViewportRegs(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + GLuint xmin, xmax, ymin, ymax, zmin, zmax; + unsigned int vcmin, vcmax; + + xmin = ctx->Viewport.X + dPriv->x; + xmax = xmin + ctx->Viewport.Width; + ymax = dPriv->y + dPriv->h - ctx->Viewport.Y; + ymin = ymax - ctx->Viewport.Height; + if (ctx->Scissor.Enabled) { + GLuint sc_xmin, sc_xmax, sc_ymin, sc_ymax; + + sc_xmin = ctx->Viewport.X + dPriv->x; + sc_xmax = sc_xmin + ctx->Viewport.Width; + sc_ymax = dPriv->y + dPriv->h - ctx->Viewport.Y; + sc_ymin = sc_ymax - ctx->Viewport.Height; + if (sc_xmin > xmin) + xmin = sc_xmin; + if (sc_xmax < xmax) + xmax = sc_xmax; + if (sc_ymin > ymin) + ymin = sc_ymin; + if (sc_ymax < ymax) + ymax = sc_ymax; + } + zmin = ((GLdouble)ctx->Viewport.Near * 0x0fffffff); + zmax = ((GLdouble)ctx->Viewport.Far * 0x0fffffff); + + vcmin = ((ymin & 0xffff) << 16) | (xmin & 0xffff); + vcmax = ((ymax & 0xffff) << 16) | (xmax & 0xffff); + if (fmesa->vclipmin != vcmin || + fmesa->vclipmax != vcmax || + fmesa->vclipzmin != zmin || + fmesa->vclipzmax != zmax) { + fmesa->vclipmin = vcmin; + fmesa->vclipmax = vcmax; + fmesa->vclipzmin = zmin; + fmesa->vclipzmax = zmax; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_CLIP, (4 + (4 * 2))); + } +} + +void ffbCalcViewport(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = fmesa->hw_viewport; + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + dPriv->x + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = - v[MAT_TY] + dPriv->h + dPriv->y + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff); + m[MAT_TZ] = v[MAT_TZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff); + + fmesa->depth_scale = ((GLdouble)1.0 / (GLdouble)0x0fffffff); + + ffbCalcViewportRegs(ctx); + + fmesa->setupnewinputs |= VERT_BIT_CLIP; +} + +static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy, + GLsizei cw, GLsizei ch) +{ + ffbCalcViewport(ctx); +} + +static void ffbDDDrawBuffer(GLcontext *ctx, GLenum buffer) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int fbc = fmesa->fbc; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDDrawBuffer: mode(%s)\n", + _mesa_lookup_enum_by_nr(buffer)); +#endif + fbc &= ~(FFB_FBC_WB_AB | FFB_FBC_RB_MASK); + switch (buffer) { + case FRONT_LEFT_BIT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B; + else + fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A; + break; + + case BACK_LEFT_BIT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A; + else + fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B; + break; + + case BACK_LEFT_BIT | FRONT_LEFT_BIT: + fbc |= FFB_FBC_WB_AB; + break; + + default: + return; + }; + + if (fbc != fmesa->fbc) { + fmesa->fbc = fbc; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); + } +} + + +static void ffbDDReadBuffer(GLcontext *ctx, GLenum buffer) +{ + /* no-op, unless you implement h/w glRead/CopyPixels */ +} + + +/* + * Specifies buffer for sw fallbacks (spans) + */ +static void ffbDDSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, + GLuint bufferBit) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int fbc = fmesa->fbc; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDSetReadBuffer: mode(%s)\n", + _mesa_lookup_enum_by_nr(buffer)); +#endif + fbc &= ~(FFB_FBC_RB_MASK); + switch (bufferBit) { + case FRONT_LEFT_BIT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_RB_B; + else + fbc |= FFB_FBC_RB_A; + break; + + case BACK_LEFT_BIT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_RB_A; + else + fbc |= FFB_FBC_RB_B; + break; + + default: + return; + }; + + if (fbc != fmesa->fbc) { + fmesa->fbc = fbc; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); + } +} + +static void ffbDDClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLubyte c[4]; + CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); + + fmesa->clear_pixel = ((c[0] << 0) | + (c[1] << 8) | + (c[2] << 16)); +} + +static void ffbDDClearDepth(GLcontext *ctx, GLclampd depth) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + fmesa->clear_depth = Z_FROM_MESA(depth * 4294967295.0f); +} + +static void ffbDDClearStencil(GLcontext *ctx, GLint stencil) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + fmesa->clear_stencil = stencil & 0xf; +} + +/* XXX Actually, should I be using FBC controls for this? -DaveM */ +static void ffbDDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int new_pmask = 0x0; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n", + r, g, b, a); +#endif + if (r) + new_pmask |= 0x000000ff; + if (g) + new_pmask |= 0x0000ff00; + if (b) + new_pmask |= 0x00ff0000; + + if (fmesa->pmask != new_pmask) { + fmesa->pmask = new_pmask; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_PMASK, 1); + } +} + +static void ffbDDLogicOp(GLcontext *ctx, GLenum op) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int rop; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDLogicOp: op(%s)\n", + _mesa_lookup_enum_by_nr(op)); +#endif + switch (op) { + case GL_CLEAR: rop = FFB_ROP_ZERO; break; + case GL_SET: rop = FFB_ROP_ONES; break; + case GL_COPY: rop = FFB_ROP_NEW; break; + case GL_AND: rop = FFB_ROP_NEW_AND_OLD; break; + case GL_NAND: rop = FFB_ROP_NEW_AND_NOLD; break; + case GL_OR: rop = FFB_ROP_NEW_OR_OLD; break; + case GL_NOR: rop = FFB_ROP_NEW_OR_NOLD; break; + case GL_XOR: rop = FFB_ROP_NEW_XOR_OLD; break; + case GL_NOOP: rop = FFB_ROP_OLD; break; + case GL_COPY_INVERTED: rop = FFB_ROP_NNEW; break; + case GL_INVERT: rop = FFB_ROP_NOLD; break; + case GL_EQUIV: rop = FFB_ROP_NNEW_XOR_NOLD; break; + case GL_AND_REVERSE: rop = FFB_ROP_NEW_AND_NOLD; break; + case GL_AND_INVERTED: rop = FFB_ROP_NNEW_AND_OLD; break; + case GL_OR_REVERSE: rop = FFB_ROP_NEW_OR_NOLD; break; + case GL_OR_INVERTED: rop = FFB_ROP_NNEW_OR_OLD; break; + + default: + return; + }; + + rop |= fmesa->rop & ~0xff; + if (rop != fmesa->rop) { + fmesa->rop = rop; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_ROP, 1); + + if (op == GL_COPY) + FALLBACK( ctx, FFB_BADATTR_BLENDROP, GL_FALSE ); + } +} + +#if 0 +/* XXX Also need to track near/far just like 3dfx driver. + * XXX + * XXX Actually, that won't work, because the 3dfx chip works by + * XXX having 1/w coordinates fed to it for each primitive, and + * XXX it uses this to index it's 64 entry fog table. + */ +static void ffb_fog_linear(GLcontext *ctx, ffbContextPtr fmesa) +{ + GLfloat c = ctx->ProjectionMatrix.m[10]; + GLfloat d = ctx->ProjectionMatrix.m[14]; + GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ]; + GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ]; + GLfloat fogEnd = ctx->Fog.End; + GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + GLfloat ndcz; + GLfloat eyez; + GLfloat Zzero, Zone; + unsigned int zb, zf; + + /* Compute the Z at which f reaches 0.0, this is the full + * saturation point. + * + * Thus compute Z (as seen by the chip during rendering), + * such that: + * + * 0.0 = (fogEnd - eyez) * fogScale + * + * fogScale is usually not zero, thus we are looking for: + * + * fogEnd = eyez + * + * fogEnd = -d / (c + ((Z - tz) * szInv)) + * fogEnd * (c + ((Z - tz) * szInv)) = -d + * (c + ((Z - tz) * szInv)) = -d / fogEnd + * (Z - tz) * szInv = (-d / fogEnd) - c + * (Z - tz) = ((-d / fogEnd) - c) / szInv + * Z = (((-d / fogEnd) - c) / szInv) + tz + */ + Zzero = (((-d / fogEnd) - c) / szInv) + tz; + + /* Compute the Z at which f reaches 1.0, this is where + * the incoming frag's full intensity is shown. This + * equation is: + * + * 1.0 = (fogEnd - eyez) + * + * We are looking for: + * + * 1.0 + eyez = fogEnd + * + * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd + * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0 + * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv)) + * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv) + * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz) + * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z + */ + Zone = (((-d / (fogEnd - 1.0)) - c) / szInv) + tz; + + /* FFB's Zfront must be less than Zback, thus we may have + * to invert Sf/Sb to satisfy this constraint. + */ + if (Zzero < Zone) { + sf = 0.0; + sb = 1.0; + zf = Z_FROM_MESA(Zzero); + zb = Z_FROM_MESA(Zone); + } else { + sf = 1.0; + sb = 0.0; + zf = Z_FROM_MESA(Zone); + zb = Z_FROM_MESA(Zzero); + } +} +#endif + +static void ffbDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) +{ +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname)); +#endif +} + +static void ffbDDLineStipple(GLcontext *ctx, GLint factor, GLushort pattern) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDLineStipple: factor(%d) pattern(%04x)\n", + factor, pattern); +#endif + if (ctx->Line.StippleFlag) { + factor = ctx->Line.StippleFactor; + pattern = ctx->Line.StipplePattern; + if ((GLuint) factor > 15) { + fmesa->lpat = FFB_LPAT_BAD; + } else { + fmesa->lpat = ((factor << FFB_LPAT_SCALEVAL_SHIFT) | + (0 << FFB_LPAT_PATLEN_SHIFT) | + ((pattern & 0xffff) << FFB_LPAT_PATTERN_SHIFT)); + } + } else { + fmesa->lpat = 0; + } +} + +void ffbXformAreaPattern(ffbContextPtr fmesa, const GLubyte *mask) +{ + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + int i, lines, xoff; + + lines = 0; + i = (dPriv->y + dPriv->h) & (32 - 1); + xoff = dPriv->x & (32 - 1); + while (lines++ < 32) { + GLuint raw = + (((GLuint)mask[0] << 24) | + ((GLuint)mask[1] << 16) | + ((GLuint)mask[2] << 8) | + ((GLuint)mask[3] << 0)); + + fmesa->pattern[i] = + (raw << xoff) | (raw >> (32 - xoff)); + i = (i - 1) & (32 - 1); + mask += 4; + } + + FFB_MAKE_DIRTY(fmesa, FFB_STATE_APAT, 32); +} + +static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDPolygonStipple: state(%d)\n", + ctx->Polygon.StippleFlag); +#endif + ffbXformAreaPattern(fmesa, mask); +} + +static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int tmp; + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDEnable: %s state(%d)\n", + _mesa_lookup_enum_by_nr(cap), state); +#endif + switch (cap) { + case GL_ALPHA_TEST: + if (state) + tmp = ffbComputeAlphaFunc(ctx); + else + tmp = FFB_XCLIP_TEST_ALWAYS; + + if (tmp != fmesa->xclip) { + fmesa->xclip = tmp; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1); + } + break; + + case GL_BLEND: + tmp = (fmesa->ppc & ~FFB_PPC_ABE_MASK); + if (state) { + tmp |= FFB_PPC_ABE_ENABLE; + } else { + tmp |= FFB_PPC_ABE_DISABLE; + } + if (fmesa->ppc != tmp) { + fmesa->ppc = tmp; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_PPC, 1); + ffbDDBlendFunc(ctx, 0, 0); + } + break; + + case GL_DEPTH_TEST: + if (state) + tmp = 0x0fffffff; + else + tmp = 0x00000000; + if (tmp != fmesa->magnc) { + unsigned int fbc = fmesa->fbc; + fbc &= ~FFB_FBC_ZE_MASK; + if (state) + fbc |= FFB_FBC_ZE_ON; + else + fbc |= FFB_FBC_ZE_OFF; + fmesa->fbc = fbc; + ffbDDDepthFunc(ctx, ctx->Depth.Func); + fmesa->magnc = tmp; + FFB_MAKE_DIRTY(fmesa, (FFB_STATE_MAGNC | FFB_STATE_FBC), 2); + } + break; + + case GL_SCISSOR_TEST: + ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); + break; + + case GL_STENCIL_TEST: + if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) { + FALLBACK( ctx, FFB_BADATTR_STENCIL, state ); + } + + tmp = fmesa->fbc & ~FFB_FBC_YE_MASK; + if (state) { + ffbDDStencilFunc(ctx, + ctx->Stencil.Function[0], + ctx->Stencil.Ref[0], + ctx->Stencil.ValueMask[0]); + ffbDDStencilMask(ctx, ctx->Stencil.WriteMask[0]); + ffbDDStencilOp(ctx, + ctx->Stencil.FailFunc[0], + ctx->Stencil.ZFailFunc[0], + ctx->Stencil.ZPassFunc[0]); + tmp |= FFB_FBC_YE_MASK; + } else { + fmesa->stencil = 0xf0000000; + fmesa->stencilctl = 0x33300000; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6); + tmp |= FFB_FBC_YE_OFF; + } + if (tmp != fmesa->fbc) { + fmesa->fbc = tmp; + FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1); + } + break; + + case GL_FOG: + /* Until I implement the fog support... */ + FALLBACK( ctx, FFB_BADATTR_FOG, state ); + break; + + case GL_LINE_STIPPLE: + if (! state) + fmesa->lpat = 0; + else + ffbDDLineStipple(ctx, + ctx->Line.StippleFactor, + ctx->Line.StipplePattern); + break; + + case GL_POLYGON_STIPPLE: + /* Do nothing, we interrogate the state during + * reduced primitive changes. Since our caller + * will set NEW_POLYGON in the ctx NewState this + * will cause the driver rasterization functions + * to be reevaluated, which will cause us to force + * a reduced primitive change next rendering pass + * and it all works out. + */ + break; + + default: + break; + }; +} + +void ffbSyncHardware(ffbContextPtr fmesa) +{ + ffb_fbcPtr ffb = fmesa->regs; + unsigned int dirty; + int i; + + FFBFifo(fmesa, fmesa->state_fifo_ents); + + dirty = fmesa->state_dirty; + if (dirty & (FFB_STATE_FBC | FFB_STATE_PPC | FFB_STATE_DRAWOP | + FFB_STATE_ROP | FFB_STATE_LPAT | FFB_STATE_WID)) { + if (dirty & FFB_STATE_FBC) + ffb->fbc = fmesa->fbc; + if (dirty & FFB_STATE_PPC) + ffb->ppc = fmesa->ppc; + if (dirty & FFB_STATE_DRAWOP) + ffb->drawop = fmesa->drawop; + if (dirty & FFB_STATE_ROP) + ffb->rop = fmesa->rop; + if (dirty & FFB_STATE_LPAT) + ffb->rop = fmesa->lpat; + if (dirty & FFB_STATE_WID) + ffb->wid = fmesa->wid; + } + if (dirty & (FFB_STATE_PMASK | FFB_STATE_XPMASK | FFB_STATE_YPMASK | + FFB_STATE_ZPMASK | FFB_STATE_XCLIP | FFB_STATE_CMP | + FFB_STATE_MATCHAB | FFB_STATE_MAGNAB | FFB_STATE_MATCHC | + FFB_STATE_MAGNC)) { + if (dirty & FFB_STATE_PMASK) + ffb->pmask = fmesa->pmask; + if (dirty & FFB_STATE_XPMASK) + ffb->xpmask = fmesa->xpmask; + if (dirty & FFB_STATE_YPMASK) + ffb->ypmask = fmesa->ypmask; + if (dirty & FFB_STATE_ZPMASK) + ffb->zpmask = fmesa->zpmask; + if (dirty & FFB_STATE_XCLIP) + ffb->xclip = fmesa->xclip; + if (dirty & FFB_STATE_CMP) + ffb->cmp = fmesa->cmp; + if (dirty & FFB_STATE_MATCHAB) + ffb->matchab = fmesa->matchab; + if (dirty & FFB_STATE_MAGNAB) + ffb->magnab = fmesa->magnab; + if (dirty & FFB_STATE_MATCHC) + ffb->matchc = fmesa->matchc; + if (dirty & FFB_STATE_MAGNC) + ffb->magnc = fmesa->magnc; + } + + if (dirty & FFB_STATE_DCUE) { + ffb->dcss = fmesa->dcss; + ffb->dcsf = fmesa->dcsf; + ffb->dcsb = fmesa->dcsb; + ffb->dczf = fmesa->dczf; + ffb->dczb = fmesa->dczb; + if (fmesa->ffb_sarea->flags & (FFB_DRI_FFB2 | FFB_DRI_FFB2PLUS)) { + ffb->dcss1 = fmesa->dcss1; + ffb->dcss2 = fmesa->dcss2; + ffb->dcss3 = fmesa->dcss3; + ffb->dcs2 = fmesa->dcs2; + ffb->dcs3 = fmesa->dcs3; + ffb->dcs4 = fmesa->dcs4; + ffb->dcd2 = fmesa->dcd2; + ffb->dcd3 = fmesa->dcd3; + ffb->dcd4 = fmesa->dcd4; + } + } + + if (dirty & FFB_STATE_BLEND) { + ffb->blendc = fmesa->blendc; + ffb->blendc1 = fmesa->blendc1; + ffb->blendc2 = fmesa->blendc2; + } + + if (dirty & FFB_STATE_CLIP) { + ffb->vclipmin = fmesa->vclipmin; + ffb->vclipmax = fmesa->vclipmax; + ffb->vclipzmin = fmesa->vclipzmin; + ffb->vclipzmax = fmesa->vclipzmax; + for (i = 0; i < 4; i++) { + ffb->auxclip[i].min = fmesa->aux_clips[i].min; + ffb->auxclip[i].max = fmesa->aux_clips[i].max; + } + } + + if ((dirty & FFB_STATE_STENCIL) && + (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) { + ffb->stencil = fmesa->stencil; + ffb->stencilctl = fmesa->stencilctl; + ffb->fbc = FFB_FBC_WB_C; + ffb->rawstencilctl = (fmesa->stencilctl | (1 << 19)); + ffb->fbc = fmesa->fbc; + ffb->consty = fmesa->consty; + } + + if (dirty & FFB_STATE_APAT) { + for (i = 0; i < 32; i++) + ffb->pattern[i] = fmesa->pattern[i]; + } + + fmesa->state_dirty = 0; + fmesa->state_fifo_ents = 0; + fmesa->ffbScreen->rp_active = 1; +} + +static void ffbDDUpdateState(GLcontext *ctx, GLuint newstate) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + /* When we are hw rendering, changing certain kinds of + * state does not require flushing all of our context. + */ + if (fmesa->bad_fragment_attrs == 0 && + (newstate & ~_NEW_COLOR) == 0) + return; + + _swrast_InvalidateState( ctx, newstate ); + _swsetup_InvalidateState( ctx, newstate ); + _ac_InvalidateState( ctx, newstate ); + _tnl_InvalidateState( ctx, newstate ); + + if (newstate & _NEW_TEXTURE) + FALLBACK( ctx, FFB_BADATTR_TEXTURE, + (ctx->Texture._EnabledUnits != 0)); + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDUpdateState: newstate(%08x)\n", newstate); +#endif + + fmesa->new_gl_state |= newstate; + + /* Force a reduced primitive change next rendering + * pass. + */ + fmesa->raster_primitive = GL_POLYGON + 1; + +#if 0 + /* When the modelview matrix changes, this changes what + * the eye coordinates will be so we have to recompute + * the depth cueing parameters. + * + * XXX DD_HAVE_HARDWARE_FOG. + */ + if (ctx->Fog.Enabled && (newstate & _NEW_MODELVIEW)) + ffb_update_fog(); +#endif +} + + +void ffbDDInitStateFuncs(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + ctx->Driver.UpdateState = ffbDDUpdateState; + + ctx->Driver.Enable = ffbDDEnable; + ctx->Driver.LightModelfv = NULL; + ctx->Driver.AlphaFunc = ffbDDAlphaFunc; + ctx->Driver.BlendEquation = ffbDDBlendEquation; + ctx->Driver.BlendFunc = ffbDDBlendFunc; + ctx->Driver.BlendFuncSeparate = ffbDDBlendFuncSeparate; + ctx->Driver.DepthFunc = ffbDDDepthFunc; + ctx->Driver.DepthMask = ffbDDDepthMask; + ctx->Driver.Fogfv = ffbDDFogfv; + ctx->Driver.LineStipple = ffbDDLineStipple; + ctx->Driver.PolygonStipple = ffbDDPolygonStipple; + ctx->Driver.Scissor = ffbDDScissor; + ctx->Driver.CullFace = NULL; + ctx->Driver.FrontFace = NULL; + ctx->Driver.ColorMask = ffbDDColorMask; + ctx->Driver.LogicOpcode = ffbDDLogicOp; + ctx->Driver.Viewport = ffbDDViewport; + ctx->Driver.DepthRange = ffbDDDepthRange; + + if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) { + ctx->Driver.StencilFunc = ffbDDStencilFunc; + ctx->Driver.StencilMask = ffbDDStencilMask; + ctx->Driver.StencilOp = ffbDDStencilOp; + } else { + ctx->Driver.StencilFunc = NULL; + ctx->Driver.StencilMask = NULL; + ctx->Driver.StencilOp = NULL; + } + + ctx->Driver.DrawBuffer = ffbDDDrawBuffer; + ctx->Driver.ReadBuffer = ffbDDReadBuffer; + ctx->Driver.ClearColor = ffbDDClearColor; + ctx->Driver.ClearDepth = ffbDDClearDepth; + ctx->Driver.ClearStencil = ffbDDClearStencil; + + /* We will support color index modes later... -DaveM */ + ctx->Driver.ClearIndex = 0; + ctx->Driver.IndexMask = 0; + + + + /* Pixel path fallbacks. + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + { + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + swdd->SetBuffer = ffbDDSetBuffer; + } + + +} + +void ffbDDInitContextHwState(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + int fifo_count = 0; + int i; + + fmesa->hw_locked = 0; + + fmesa->bad_fragment_attrs = 0; + fmesa->state_dirty = FFB_STATE_ALL; + fmesa->new_gl_state = ~0; + + fifo_count = 1; + fmesa->fbc = (FFB_FBC_WE_FORCEON | FFB_FBC_WM_COMBINED | + FFB_FBC_SB_BOTH | FFB_FBC_ZE_MASK | + FFB_FBC_YE_OFF | FFB_FBC_XE_OFF | + FFB_FBC_RGBE_MASK); + if (ctx->Visual.doubleBufferMode) { + /* Buffer B is the initial back buffer. */ + fmesa->back_buffer = 1; + fmesa->fbc |= FFB_FBC_WB_BC | FFB_FBC_RB_B; + } else { + fmesa->back_buffer = 0; + fmesa->fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A; + } + + fifo_count += 1; + fmesa->ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE | + FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_3D | + FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE | + FFB_PPC_ZS_CONST | FFB_PPC_YS_CONST | + FFB_PPC_XS_WID | FFB_PPC_CS_VAR); + + fifo_count += 3; + fmesa->drawop = FFB_DRAWOP_RECTANGLE; + + /* GL_COPY is the default LogicOp. */ + fmesa->rop = (FFB_ROP_NEW << 16) | (FFB_ROP_NEW << 8) | FFB_ROP_NEW; + + /* No line patterning enabled. */ + fmesa->lpat = 0x00000000; + + /* We do not know the WID value until the first context switch. */ + fifo_count += 1; + fmesa->wid = ~0; + + fifo_count += 5; + + /* ColorMask, all enabled. */ + fmesa->pmask = 0xffffffff; + + fmesa->xpmask = 0x000000ff; + fmesa->ypmask = 0x0000000f; + fmesa->zpmask = 0x0fffffff; + + /* AlphaFunc GL_ALWAYS, AlphaRef 0 */ + fmesa->xclip = FFB_XCLIP_TEST_ALWAYS | 0x00; + + /* This sets us up to use WID clipping (so the DRI clipping + * rectangle is unneeded by us). All other match and magnitude + * tests are set to pass. + */ + fifo_count += 5; + fmesa->cmp = ((FFB_CMP_MATCH_ALWAYS << 24) | /* MATCH C */ + (FFB_CMP_MAGN_ALWAYS << 16) | /* MAGN C */ + (FFB_CMP_MATCH_EQ << 8) | /* MATCH AB */ + (FFB_CMP_MAGN_ALWAYS << 0)); /* MAGN AB */ + fmesa->matchab = 0xff000000; + fmesa->magnab = 0x00000000; + fmesa->matchc = 0x00000000; + fmesa->magnc = 0x00000000; + + /* Depth cue parameters, all zeros to start. */ + fifo_count += 14; + fmesa->dcss = 0x00000000; + fmesa->dcsf = 0x00000000; + fmesa->dcsb = 0x00000000; + fmesa->dczf = 0x00000000; + fmesa->dczb = 0x00000000; + fmesa->dcss1 = 0x00000000; + fmesa->dcss2 = 0x00000000; + fmesa->dcss3 = 0x00000000; + fmesa->dcs2 = 0x00000000; + fmesa->dcs3 = 0x00000000; + fmesa->dcs4 = 0x00000000; + fmesa->dcd2 = 0x00000000; + fmesa->dcd3 = 0x00000000; + fmesa->dcd4 = 0x00000000; + + /* Alpha blending unit state. */ + fifo_count += 3; + fmesa->blendc = (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */ + fmesa->blendc1 = 0x00000000; + fmesa->blendc2 = 0x00000000; + + /* ViewPort clip state. */ + fifo_count += 4 + (4 * 2); + fmesa->vclipmin = 0x00000000; + fmesa->vclipmax = 0xffffffff; + fmesa->vclipzmin = 0x00000000; + fmesa->vclipzmax = 0x0fffffff; + for (i = 0; i < 4; i++) { + fmesa->aux_clips[0].min = 0x00000000; + fmesa->aux_clips[0].max = 0x00000000; + } + + /* Stenciling state. */ + fifo_count += 6; + fmesa->stencil = 0xf0000000; /* Stencil MASK, Y plane */ + fmesa->stencilctl = 0x33300000; /* All stencil tests disabled */ + fmesa->consty = 0x0; + + /* Area pattern, used for polygon stipples. */ + fifo_count += 32; + for (i = 0; i < 32; i++) + fmesa->pattern[i] = 0x00000000; + + fmesa->state_fifo_ents = fifo_count; + fmesa->state_all_fifo_ents = fifo_count; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_state.h b/src/mesa/drivers/dri/ffb/ffb_state.h new file mode 100644 index 00000000000..17b6fa20ab0 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_state.h @@ -0,0 +1,13 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_STATE_H +#define _FFB_STATE_H + +extern void ffbDDInitStateFuncs(GLcontext *); +extern void ffbDDInitContextHwState(GLcontext *); + +extern void ffbCalcViewport(GLcontext *); +extern void ffbXformAreaPattern(ffbContextPtr, const GLubyte *); +extern void ffbSyncHardware(ffbContextPtr fmesa); + +#endif /* !(_FFB_STATE_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_stencil.c b/src/mesa/drivers/dri/ffb/ffb_stencil.c new file mode 100644 index 00000000000..a00eb3602ab --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_stencil.c @@ -0,0 +1,221 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_stencil.c,v 1.2 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "mtypes.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_context.h" +#include "ffb_stencil.h" +#include "ffb_lock.h" + +#include "swrast/swrast.h" + +#undef STENCIL_TRACE + +static void +FFBWriteStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLstencil stencil[], const GLubyte mask[]) +{ +#ifdef STENCIL_TRACE + fprintf(stderr, "FFBWriteStencilSpan: n(%d) x(%d) y(%d)\n", + (int) n, x, y); +#endif + if (ctx->Depth.Mask) { + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + GLuint *zptr; + GLuint i; + + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 2); + fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_OFF | + FFB_FBC_YE_ON | FFB_FBC_RGBE_OFF); + fmesa->regs->ppc = FFB_PPC_YS_VAR; + FFBWait(fmesa, fmesa->regs); + + y = (dPriv->h - y); + zptr = (GLuint *) + ((char *)fmesa->sfb32 + + ((dPriv->x + x) << 2) + + ((dPriv->y + y) << 13)); + + for (i = 0; i < n; i++) { + if (mask[i]) + *zptr = (stencil[i] & 0xf) << 28; + zptr++; + } + + FFBFifo(fmesa, 2); + fmesa->regs->fbc = fmesa->fbc; + fmesa->regs->ppc = fmesa->ppc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); + } +} + +static void +FFBWriteStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], + const GLstencil stencil[], const GLubyte mask[]) +{ +#ifdef STENCIL_TRACE + fprintf(stderr, "FFBWriteStencilPixels: n(%d)\n", (int) n); +#endif + if (ctx->Depth.Mask) { + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + char *zbase; + GLuint i; + + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 2); + fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_OFF | + FFB_FBC_YE_ON | FFB_FBC_RGBE_OFF); + fmesa->regs->ppc = FFB_PPC_YS_VAR; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + zbase = ((char *)fmesa->sfb32 + + (dPriv->x << 2) + (dPriv->y << 13)); + + for (i = 0; i < n; i++) { + GLint y1 = (dPriv->h - y[i]); + GLint x1 = x[i]; + GLuint *zptr; + + zptr = (GLuint *) + (zbase + (x1 << 2) + (y1 << 13)); + if (mask[i]) + *zptr = (stencil[i] & 0xf) << 28; + } + + FFBFifo(fmesa, 2); + fmesa->regs->fbc = fmesa->fbc; + fmesa->regs->ppc = fmesa->ppc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); + } +} + +static void +FFBReadStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLstencil stencil[]) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + GLuint *zptr; + GLuint i; + +#ifdef STENCIL_TRACE + fprintf(stderr, "FFBReadStencilSpan: n(%d) x(%d) y(%d)\n", + (int) n, x, y); +#endif + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 1); + fmesa->regs->fbc = FFB_FBC_RB_C; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + y = (dPriv->h - y); + zptr = (GLuint *) + ((char *)fmesa->sfb32 + + ((dPriv->x + x) << 2) + + ((dPriv->y + y) << 13)); + + for (i = 0; i < n; i++) { + stencil[i] = (*zptr >> 28) & 0xf; + zptr++; + } + + FFBFifo(fmesa, 1); + fmesa->regs->fbc = fmesa->fbc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); +} + +static void +FFBReadStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], + GLstencil stencil[]) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + char *zbase; + GLuint i; + +#ifdef STENCIL_TRACE + fprintf(stderr, "FFBReadStencilPixels: n(%d)\n", (int) n); +#endif + if (!fmesa->hw_locked) + LOCK_HARDWARE(fmesa); + FFBFifo(fmesa, 1); + fmesa->regs->fbc = FFB_FBC_RB_C; + fmesa->ffbScreen->rp_active = 1; + FFBWait(fmesa, fmesa->regs); + + zbase = ((char *)fmesa->sfb32 + + (dPriv->x << 2) + (dPriv->y << 13)); + + for (i = 0; i < n; i++) { + GLint y1 = (dPriv->h - y[i]); + GLint x1 = x[i]; + GLuint *zptr; + + zptr = (GLuint *) + (zbase + (x1 << 2) + (y1 << 13)); + stencil[i] = (*zptr >> 28) & 0xf; + } + + FFBFifo(fmesa, 1); + fmesa->regs->fbc = fmesa->fbc; + fmesa->ffbScreen->rp_active = 1; + if (!fmesa->hw_locked) + UNLOCK_HARDWARE(fmesa); +} + +void ffbDDInitStencilFuncs(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + struct swrast_device_driver *swdd = + _swrast_GetDeviceDriverReference(ctx); + + if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) { + swdd->WriteStencilSpan = FFBWriteStencilSpan; + swdd->ReadStencilSpan = FFBReadStencilSpan; + swdd->WriteStencilPixels = FFBWriteStencilPixels; + swdd->ReadStencilPixels = FFBReadStencilPixels; + } else { + swdd->WriteStencilSpan = NULL; + swdd->ReadStencilSpan = NULL; + swdd->WriteStencilPixels = NULL; + swdd->ReadStencilPixels = NULL; + } +} diff --git a/src/mesa/drivers/dri/ffb/ffb_stencil.h b/src/mesa/drivers/dri/ffb/ffb_stencil.h new file mode 100644 index 00000000000..af161e7c1d1 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_stencil.h @@ -0,0 +1,8 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_stencil.h,v 1.1 2000/06/20 05:08:39 dawes Exp $ */ + +#ifndef _FFB_STENCIL_H +#define _FFB_STENCIL_H + +extern void ffbDDInitStencilFuncs(GLcontext *ctx); + +#endif /* !(_FFB_STENCIL_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_tex.c b/src/mesa/drivers/dri/ffb/ffb_tex.c new file mode 100644 index 00000000000..ba1103e2e52 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_tex.c @@ -0,0 +1,51 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tex.c,v 1.1 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include <GL/gl.h> +#include "texformat.h" +#include "texstore.h" +#include "swrast/swrast.h" + +#include "ffb_tex.h" + +/* No texture unit, all software. */ +void ffbDDInitTexFuncs(GLcontext *ctx) +{ + ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_tex.h b/src/mesa/drivers/dri/ffb/ffb_tex.h new file mode 100644 index 00000000000..dba0e08af68 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_tex.h @@ -0,0 +1,34 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tex.h,v 1.1 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D. + * Copyright (C) 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#ifndef _FFB_TEX_H +#define _FFB_TEX_H + +extern void ffbDDInitTexFuncs(GLcontext *ctx); + +#endif /* !(_FFB_DD_H) */ + diff --git a/src/mesa/drivers/dri/ffb/ffb_tris.c b/src/mesa/drivers/dri/ffb/ffb_tris.c new file mode 100644 index 00000000000..63113f09ce7 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_tris.c @@ -0,0 +1,946 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tris.c,v 1.3 2002/10/30 12:51:28 alanh Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "glheader.h" +#include "mtypes.h" +#include "macros.h" +#include "mmath.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast/s_context.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "ffb_context.h" +#include "ffb_tris.h" +#include "ffb_lines.h" +#include "ffb_lock.h" +#include "ffb_points.h" +#include "ffb_state.h" +#include "ffb_vb.h" + +#undef TRI_DEBUG +#undef FFB_RENDER_TRACE +#undef STATE_TRACE + +#ifdef TRI_DEBUG +static void ffb_print_vertex(const ffb_vertex *v) +{ + fprintf(stderr, "Vertex @(%p): " + "X[%f] Y[%f] Z[%f]\n", + v, v->x, v->y, v->z); + fprintf(stderr, "Vertex @(%p): " + "A[%f] R[%f] G[%f] B[%f]\n", + v, + v->color[0].alpha, + v->color[0].red, + v->color[0].green, + v->color[0].blue); +} +#define FFB_DUMP_VERTEX(V) ffb_print_vertex(V) +#else +#define FFB_DUMP_VERTEX(V) do { } while(0) +#endif + +#define FFB_ALPHA_BIT 0x01 +#define FFB_FLAT_BIT 0x02 +#define FFB_TRI_CULL_BIT 0x04 +#define MAX_FFB_RENDER_FUNCS 0x08 + +/*********************************************************************** + * Build low-level triangle/quad rasterize functions * + ***********************************************************************/ + +#define FFB_TRI_FLAT_BIT 0x01 +#define FFB_TRI_ALPHA_BIT 0x02 +/*#define FFB_TRI_CULL_BIT 0x04*/ + +static ffb_tri_func ffb_tri_tab[0x8]; +static ffb_quad_func ffb_quad_tab[0x8]; + +#define IND (0) +#define TAG(x) x +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_FLAT_BIT) +#define TAG(x) x##_flat +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_CULL_BIT) +#define TAG(x) x##_cull +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT) +#define TAG(x) x##_cull_flat +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_ALPHA_BIT) +#define TAG(x) x##_alpha +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_FLAT_BIT) +#define TAG(x) x##_alpha_flat +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT) +#define TAG(x) x##_alpha_cull +#include "ffb_tritmp.h" + +#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT) +#define TAG(x) x##_alpha_cull_flat +#include "ffb_tritmp.h" + +static void init_tri_tab(void) +{ + ffb_init(); + ffb_init_flat(); + ffb_init_cull(); + ffb_init_cull_flat(); + ffb_init_alpha(); + ffb_init_alpha_flat(); + ffb_init_alpha_cull(); + ffb_init_alpha_cull_flat(); +} + +/* Build a SWvertex from a hardware vertex. */ +static void ffb_translate_vertex(GLcontext *ctx, const ffb_vertex *src, + SWvertex *dst) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLfloat *m = ctx->Viewport._WindowMap.m; + const GLfloat sx = m[0]; + const GLfloat sy = m[5]; + const GLfloat sz = m[10]; + const GLfloat tx = m[12]; + const GLfloat ty = m[13]; + const GLfloat tz = m[14]; + + dst->win[0] = sx * src->x + tx; + dst->win[1] = sy * src->y + ty; + dst->win[2] = sz * src->z + tz; + dst->win[3] = 1.0; + + dst->color[0] = FFB_UBYTE_FROM_COLOR(src->color[0].red); + dst->color[1] = FFB_UBYTE_FROM_COLOR(src->color[0].green); + dst->color[2] = FFB_UBYTE_FROM_COLOR(src->color[0].blue); + dst->color[3] = FFB_UBYTE_FROM_COLOR(src->color[0].alpha); +} + +/*********************************************************************** + * Build fallback triangle/quad rasterize functions * + ***********************************************************************/ + +static void ffb_fallback_triangle(GLcontext *ctx, ffb_vertex *v0, + ffb_vertex *v1, ffb_vertex *v2) +{ + SWvertex v[3]; + + ffb_translate_vertex(ctx, v0, &v[0]); + ffb_translate_vertex(ctx, v1, &v[1]); + ffb_translate_vertex(ctx, v2, &v[2]); + + _swrast_Triangle(ctx, &v[0], &v[1], &v[2]); +} + +static void ffb_fallback_quad(GLcontext *ctx, + ffb_vertex *v0, ffb_vertex *v1, + ffb_vertex *v2, ffb_vertex *v3) +{ + SWvertex v[4]; + + ffb_translate_vertex(ctx, v0, &v[0]); + ffb_translate_vertex(ctx, v1, &v[1]); + ffb_translate_vertex(ctx, v2, &v[2]); + ffb_translate_vertex(ctx, v3, &v[3]); + + _swrast_Quad(ctx, &v[0], &v[1], &v[2], &v[3]); +} + +void ffb_fallback_line(GLcontext *ctx, ffb_vertex *v0, ffb_vertex *v1) +{ + SWvertex v[2]; + + ffb_translate_vertex(ctx, v0, &v[0]); + ffb_translate_vertex(ctx, v1, &v[1]); + + _swrast_Line(ctx, &v[0], &v[1]); +} + +void ffb_fallback_point(GLcontext *ctx, ffb_vertex *v0) +{ + SWvertex v[1]; + + ffb_translate_vertex(ctx, v0, &v[0]); + + _swrast_Point(ctx, &v[0]); +} + +/*********************************************************************** + * Rasterization functions for culled tris/quads * + ***********************************************************************/ + +static void ffb_nodraw_triangle(GLcontext *ctx, ffb_vertex *v0, + ffb_vertex *v1, ffb_vertex *v2) +{ + (void) (ctx && v0 && v1 && v2); +} + +static void ffb_nodraw_quad(GLcontext *ctx, + ffb_vertex *v0, ffb_vertex *v1, + ffb_vertex *v2, ffb_vertex *v3) +{ + (void) (ctx && v0 && v1 && v2 && v3); +} + +static void ffb_update_cullsign(GLcontext *ctx) +{ + GLfloat backface_sign = 1; + + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace==GL_CCW) + backface_sign = -1; + break; + + case GL_FRONT: + if (ctx->Polygon.FrontFace!=GL_CCW) + backface_sign = -1; + break; + + default: + break; + }; + + FFB_CONTEXT(ctx)->backface_sign = backface_sign; +} + +/*********************************************************************** + * Choose triangle/quad rasterize functions * + ***********************************************************************/ + +void ffbChooseTriangleState(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint ind = 0; + + if (flags & DD_TRI_SMOOTH) { + fmesa->draw_tri = ffb_fallback_triangle; + fmesa->draw_quad = ffb_fallback_quad; + return; + } + + if (flags & DD_FLATSHADE) + ind |= FFB_TRI_FLAT_BIT; + + if (ctx->Polygon.CullFlag) { + if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { + fmesa->draw_tri = ffb_nodraw_triangle; + fmesa->draw_quad = ffb_nodraw_quad; + return; + } + + ind |= FFB_TRI_CULL_BIT; + ffb_update_cullsign(ctx); + } else + FFB_CONTEXT(ctx)->backface_sign = 0; + + /* If blending or the alpha test is enabled we need to + * provide alpha components to the chip, else we can + * do without it and thus feed vertex data to the chip + * more efficiently. + */ + if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled) + ind |= FFB_TRI_ALPHA_BIT; + + fmesa->draw_tri = ffb_tri_tab[ind]; + fmesa->draw_quad = ffb_quad_tab[ind]; +} + +static const GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + +static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim); +static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim); + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define FFB_OFFSET_BIT 0x01 +#define FFB_TWOSIDE_BIT 0x02 +#define FFB_UNFILLED_BIT 0x04 +#define FFB_MAX_TRIFUNC 0x08 + +static struct { + triangle_func triangle; + quad_func quad; +} rast_tab[FFB_MAX_TRIFUNC]; + +#define DO_OFFSET (IND & FFB_OFFSET_BIT) +#define DO_UNFILLED (IND & FFB_UNFILLED_BIT) +#define DO_TWOSIDE (IND & FFB_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_QUAD 1 +#define DO_FULL_QUAD 1 +#define DO_TRI 1 +#define DO_LINE 0 +#define DO_POINTS 0 + +#define QUAD( a, b, c, d ) fmesa->draw_quad( ctx, a, b, c, d ) +#define TRI( a, b, c ) fmesa->draw_tri( ctx, a, b, c ) +#define LINE( a, b ) fmesa->draw_line( ctx, a, b ) +#define POINT( a ) fmesa->draw_point( ctx, a ) + +#define HAVE_BACK_COLORS 1 +#define HAVE_RGBA 1 +#define HAVE_SPEC 0 +#define HAVE_HW_FLATSHADE 1 +#define VERTEX ffb_vertex +#define TAB rast_tab + +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define DEPTH_SCALE (fmesa->depth_scale) +#define VERT_X(_v) (_v->x) +#define VERT_Y(_v) (_v->y) +#define VERT_Z(_v) (_v->z) +#define AREA_IS_CCW( a ) (a < fmesa->ffb_zero) +#define GET_VERTEX(e) (&fmesa->verts[e]) +#define INSANE_VERTICES +#define VERT_SET_Z(v,val) ((v)->z = (val)) +#define VERT_Z_ADD(v,val) ((v)->z += (val)) + +#define VERT_COPY_RGBA1( _v ) _v->color[0] = _v->color[1] +#define VERT_COPY_RGBA( v0, v1 ) v0->color[0] = v1->color[0] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->color[0] +#define VERT_RESTORE_RGBA( idx ) v[idx]->color[0] = color[idx] + +#define LOCAL_VARS(n) \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; \ + ffb_color color[n]; \ + (void) color; (void) dPriv; + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +#define RASTERIZE(x) if (fmesa->raster_primitive != reduced_prim[x]) \ + ffbRasterPrimitive( ctx, reduced_prim[x] ) +#define RENDER_PRIMITIVE fmesa->render_primitive +#define TAG(x) x +#include "tnl_dd/t_dd_unfilled.h" + +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_OFFSET_BIT|FFB_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_TWOSIDE_BIT|FFB_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT|FFB_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +static void init_rast_tab( void ) +{ + init(); + init_offset(); + init_twoside(); + init_twoside_offset(); + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); +} + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + +static void ffbRenderClippedPolygon(GLcontext *ctx, const GLuint *elts, GLuint n) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint prim = fmesa->render_primitive; + + /* Render the new vertices as an unclipped polygon. */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n, PRIM_BEGIN|PRIM_END); + VB->Elts = tmp; + } + + /* Restore the render primitive. */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify(ctx, prim); +} + +static void ffbRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line(ctx, ii, jj); +} + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +static void ffb_vb_noop(GLcontext *ctx, GLuint start, GLuint count, GLuint flags) +{ + (void)(ctx && start && count && flags); +} + +#define ELT(x) x + +#define IND 0 +#define TAG(x) x +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT) +#define TAG(x) x##_flat +#include "ffb_rendertmp.h" + +#define IND (FFB_ALPHA_BIT) +#define TAG(x) x##_alpha +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT) +#define TAG(x) x##_flat_alpha +#include "ffb_rendertmp.h" + +#define IND (FFB_TRI_CULL_BIT) +#define TAG(x) x##_tricull +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_flat_tricull +#include "ffb_rendertmp.h" + +#define IND (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_alpha_tricull +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_flat_alpha_tricull +#include "ffb_rendertmp.h" + +#undef ELT +#define ELT(x) elt[x] + +#define IND 0 +#define TAG(x) x##_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT) +#define TAG(x) x##_flat_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_ALPHA_BIT) +#define TAG(x) x##_alpha_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT) +#define TAG(x) x##_flat_alpha_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_TRI_CULL_BIT) +#define TAG(x) x##_tricull_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_flat_tricull_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_alpha_tricull_elt +#include "ffb_rendertmp.h" + +#define IND (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT) +#define TAG(x) x##_flat_alpha_tricull_elt +#include "ffb_rendertmp.h" + +static void *render_tabs[MAX_FFB_RENDER_FUNCS]; +static void *render_tabs_elt[MAX_FFB_RENDER_FUNCS]; + +static void init_render_tab(void) +{ + int i; + + render_tabs[0] = render_tab; + render_tabs[FFB_FLAT_BIT] = render_tab_flat; + render_tabs[FFB_ALPHA_BIT] = render_tab_alpha; + render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha; + render_tabs[FFB_TRI_CULL_BIT] = render_tab_tricull; + render_tabs[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull; + render_tabs[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull; + render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = + render_tab_flat_alpha_tricull; + + render_tabs_elt[0] = render_tab_elt; + render_tabs_elt[FFB_FLAT_BIT] = render_tab_flat_elt; + render_tabs_elt[FFB_ALPHA_BIT] = render_tab_alpha_elt; + render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha_elt; + render_tabs_elt[FFB_TRI_CULL_BIT] = render_tab_tricull_elt; + render_tabs_elt[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull_elt; + render_tabs_elt[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull_elt; + render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = + render_tab_flat_alpha_tricull_elt; + + for (i = 0; i < MAX_FFB_RENDER_FUNCS; i++) { + render_func *rf = render_tabs[i]; + render_func *rfe = render_tabs_elt[i]; + + if (i & FFB_TRI_CULL_BIT) { + int from_idx = (i & ~FFB_TRI_CULL_BIT); + render_func *rf_from = render_tabs[from_idx]; + render_func *rfe_from = render_tabs_elt[from_idx]; + int j; + + for (j = GL_POINTS; j < GL_TRIANGLES; j++) { + rf[j] = rf_from[j]; + rfe[j] = rfe_from[j]; + } + } + } +} + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + +#ifdef FFB_RENDER_TRACE +static void ffbPrintRenderFlags(GLuint index, GLuint render_index) +{ + fprintf(stderr, + "ffbChooseRenderState: " + "index(%s%s%s) " + "render_index(%s%s%s)\n", + ((index & FFB_TWOSIDE_BIT) ? "twoside " : ""), + ((index & FFB_OFFSET_BIT) ? "offset " : ""), + ((index & FFB_UNFILLED_BIT) ? "unfilled " : ""), + ((render_index & FFB_FLAT_BIT) ? "flat " : ""), + ((render_index & FFB_ALPHA_BIT) ? "alpha " : ""), + ((render_index & FFB_TRI_CULL_BIT) ? "tricull " : "")); +} +#endif + +void ffbChooseRenderState(GLcontext *ctx) +{ + GLuint flags = ctx->_TriangleCaps; + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint index = 0; + + /* Per-primitive fallbacks and the selection of fmesa->draw_* are + * handled elsewhere. + */ + if (flags & DD_TRI_LIGHT_TWOSIDE) + index |= FFB_TWOSIDE_BIT; + + if (flags & DD_TRI_OFFSET) + index |= FFB_OFFSET_BIT; + + if (flags & DD_TRI_UNFILLED) + index |= FFB_UNFILLED_BIT; + + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + GLuint render_index = 0; + + if (flags & DD_FLATSHADE) + render_index |= FFB_FLAT_BIT; + + if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled) + render_index |= FFB_ALPHA_BIT; + + if (ctx->Polygon.CullFlag) + render_index |= FFB_TRI_CULL_BIT; + +#ifdef FFB_RENDER_TRACE + ffbPrintRenderFlags(index, render_index); +#endif + tnl->Driver.Render.PrimTabVerts = render_tabs[render_index]; + tnl->Driver.Render.PrimTabElts = render_tabs_elt[render_index]; + } else { +#ifdef FFB_RENDER_TRACE + ffbPrintRenderFlags(index, 0); +#endif + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + } + + tnl->Driver.Render.ClippedPolygon = ffbRenderClippedPolygon; + tnl->Driver.Render.ClippedLine = ffbRenderClippedLine; +} + +static void ffbRunPipeline(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + if (fmesa->bad_fragment_attrs == 0 && + fmesa->new_gl_state) { + if (fmesa->new_gl_state & _FFB_NEW_TRIANGLE) + ffbChooseTriangleState(ctx); + if (fmesa->new_gl_state & _FFB_NEW_LINE) + ffbChooseLineState(ctx); + if (fmesa->new_gl_state & _FFB_NEW_POINT) + ffbChoosePointState(ctx); + if (fmesa->new_gl_state & _FFB_NEW_RENDER) + ffbChooseRenderState(ctx); + if (fmesa->new_gl_state & _FFB_NEW_VERTEX) + ffbChooseVertexState(ctx); + + fmesa->new_gl_state = 0; + } + + _tnl_run_pipeline(ctx); +} + +static void ffbRenderStart(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + LOCK_HARDWARE(fmesa); + fmesa->hw_locked = 1; + + if (fmesa->state_dirty != 0) + ffbSyncHardware(fmesa); +} + +static void ffbRenderFinish(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + UNLOCK_HARDWARE(fmesa); + fmesa->hw_locked = 0; +} + +/* Even when doing full software rendering we need to + * wrap render{start,finish} so that the hardware is kept + * in sync (because multipass rendering changes the write + * buffer etc.) + */ +static void ffbSWRenderStart(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + LOCK_HARDWARE(fmesa); + fmesa->hw_locked = 1; + + if (fmesa->state_dirty != 0) + ffbSyncHardware(fmesa); +} + +static void ffbSWRenderFinish(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + UNLOCK_HARDWARE(fmesa); + fmesa->hw_locked = 0; +} + +static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint drawop, fbc, ppc; + int do_sw = 0; + + fmesa->raster_primitive = rprim; + + drawop = fmesa->drawop; + fbc = fmesa->fbc; + ppc = fmesa->ppc & ~(FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK); + +#ifdef STATE_TRACE + fprintf(stderr, + "ffbReducedPrimitiveChange: rprim(%d) ", rprim); +#endif + switch(rprim) { + case GL_POINTS: +#ifdef STATE_TRACE + fprintf(stderr, "GL_POINTS "); +#endif + if (fmesa->draw_point == ffb_fallback_point) { + do_sw = 1; + break; + } + + if (ctx->Point.SmoothFlag) { + ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST); + drawop = FFB_DRAWOP_AADOT; + } else { + ppc |= (FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST); + drawop = FFB_DRAWOP_DOT; + } + break; + + case GL_LINES: +#ifdef STATE_TRACE + fprintf(stderr, "GL_LINES "); +#endif + if (fmesa->draw_line == ffb_fallback_line) { + do_sw = 1; + break; + } + + if (ctx->_TriangleCaps & DD_FLATSHADE) { + ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST; + } else { + ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR; + } + if (ctx->Line.SmoothFlag) + drawop = FFB_DRAWOP_AALINE; + else + drawop = FFB_DRAWOP_DDLINE; + break; + + case GL_TRIANGLES: +#ifdef STATE_TRACE + fprintf(stderr, "GL_POLYGON "); +#endif + if (fmesa->draw_tri == ffb_fallback_triangle) { + do_sw = 1; + break; + } + + ppc &= ~FFB_PPC_APE_MASK; + if (ctx->Polygon.StippleFlag) + ppc |= FFB_PPC_APE_ENABLE; + else + ppc |= FFB_PPC_APE_DISABLE; + + if (ctx->_TriangleCaps & DD_FLATSHADE) { + ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST; + } else { + ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR; + } + drawop = FFB_DRAWOP_TRIANGLE; + break; + + default: +#ifdef STATE_TRACE + fprintf(stderr, "unknown %d!\n", rprim); +#endif + return; + }; + +#ifdef STATE_TRACE + fprintf(stderr, "do_sw(%d) ", do_sw); +#endif + if (do_sw != 0) { + fbc &= ~(FFB_FBC_WB_C); + fbc &= ~(FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK); + fbc |= FFB_FBC_ZE_OFF | FFB_FBC_RGBE_MASK; + ppc &= ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK | + FFB_PPC_DCE_MASK | FFB_PPC_APE_MASK); + ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR | FFB_PPC_XS_WID | + FFB_PPC_ABE_DISABLE | FFB_PPC_DCE_DISABLE | + FFB_PPC_APE_DISABLE); + } else { + fbc |= FFB_FBC_WB_C; + fbc &= ~(FFB_FBC_RGBE_MASK); + fbc |= FFB_FBC_RGBE_MASK; + ppc &= ~(FFB_PPC_ABE_MASK | FFB_PPC_XS_MASK); + if (ctx->Color.BlendEnabled) { + if ((rprim == GL_POINTS && !ctx->Point.SmoothFlag) || + (rprim != GL_POINTS && ctx->_TriangleCaps & DD_FLATSHADE)) + ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_CONST; + else + ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_VAR; + } else { + ppc |= FFB_PPC_ABE_DISABLE | FFB_PPC_XS_WID; + } + } +#ifdef STATE_TRACE + fprintf(stderr, "fbc(%08x) ppc(%08x)\n", fbc, ppc); +#endif + + FFBFifo(fmesa, 4); + if (fmesa->drawop != drawop) + fmesa->regs->drawop = fmesa->drawop = drawop; + if (fmesa->fbc != fbc) + fmesa->regs->fbc = fmesa->fbc = fbc; + if (fmesa->ppc != ppc) + fmesa->regs->ppc = fmesa->ppc = ppc; + if (do_sw != 0) { + fmesa->regs->cmp = + (fmesa->cmp & ~(0xff<<16)) | (0x80 << 16); + } else + fmesa->regs->cmp = fmesa->cmp; +} + +static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + fmesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (fmesa->raster_primitive != rprim) { + ffbRasterPrimitive( ctx, rprim ); + } +} + + + + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ + +static char *fallbackStrings[] = { + "Fog enabled", + "Blend function", + "Blend ROP", + "Blend equation", + "Stencil", + "Texture", + "LIBGL_SOFTWARE_RENDERING" +}; + +static char *getFallbackString(GLuint bit) +{ + int i = 0; + + while (bit > 1) { + i++; + bit >>= 1; + } + return fallbackStrings[i]; +} + +void ffbFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldfallback = fmesa->bad_fragment_attrs; + + if (mode) { + fmesa->bad_fragment_attrs |= bit; + if (oldfallback == 0) { +/* FFB_FIREVERTICES(fmesa); */ + _swsetup_Wakeup( ctx ); + if (fmesa->debugFallbacks) + fprintf(stderr, "FFB begin software fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } else { + fmesa->bad_fragment_attrs &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + + tnl->Driver.Render.Start = ffbRenderStart; + tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive; + tnl->Driver.Render.Finish = ffbRenderFinish; + fmesa->new_gl_state = ~0; + + /* Just re-choose everything: + */ + ffbChooseVertexState(ctx); + ffbChooseRenderState(ctx); + ffbChooseTriangleState(ctx); + ffbChooseLineState(ctx); + ffbChoosePointState(ctx); + + if (fmesa->debugFallbacks) + fprintf(stderr, "FFB end software fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } +} + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + +void ffbDDInitRenderFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + init_tri_tab(); + init_render_tab(); + firsttime = 0; + } + + tnl->Driver.RunPipeline = ffbRunPipeline; + tnl->Driver.Render.Start = ffbRenderStart; + tnl->Driver.Render.Finish = ffbRenderFinish; + tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + + swrast->Driver.SpanRenderStart = ffbSWRenderStart; + swrast->Driver.SpanRenderFinish = ffbSWRenderFinish; +} diff --git a/src/mesa/drivers/dri/ffb/ffb_tris.h b/src/mesa/drivers/dri/ffb/ffb_tris.h new file mode 100644 index 00000000000..1b1a00738f4 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_tris.h @@ -0,0 +1,29 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tris.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_TRIS_H +#define _FFB_TRIS_H + +extern void ffbDDInitRenderFuncs( GLcontext *ctx ); + + +#define _FFB_NEW_RENDER (_DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_UNFILLED) + +extern void ffbChooseRenderState(GLcontext *ctx); + + +#define _FFB_NEW_TRIANGLE (_DD_NEW_TRI_SMOOTH | \ + _DD_NEW_FLATSHADE | \ + _NEW_POLYGON | \ + _NEW_COLOR) + +extern void ffbChooseTriangleState(GLcontext *ctx); + +extern void ffbFallback( GLcontext *ctx, GLuint bit, GLboolean mode ); +#define FALLBACK( ctx, bit, mode ) ffbFallback( ctx, bit, mode ) + +extern void ffb_fallback_line(GLcontext *, ffb_vertex *, ffb_vertex *); +extern void ffb_fallback_point(GLcontext *, ffb_vertex *); + +#endif /* !(_FFB_TRIS_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_tritmp.h b/src/mesa/drivers/dri/ffb/ffb_tritmp.h new file mode 100644 index 00000000000..612ef2433f0 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_tritmp.h @@ -0,0 +1,239 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tritmp.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +static void TAG(ffb_triangle)( GLcontext *ctx, + ffb_vertex *v0, + ffb_vertex *v1, + ffb_vertex *v2 ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_fbcPtr ffb = fmesa->regs; +#if (IND & FFB_TRI_FLAT_BIT) + GLuint const_fg; +#endif + FFB_DELAYED_VIEWPORT_VARS; + +#ifdef TRI_DEBUG + fprintf(stderr, "FFB: ffb_triangle [" +#if (IND & FFB_TRI_CULL_BIT) + " CULL" +#endif +#if (IND & FFB_TRI_FLAT_BIT) + " FLAT" +#endif +#if (IND & FFB_TRI_ALPHA_BIT) + " ALPHA" +#endif + " ]\n"); +#endif + +#if (IND & FFB_TRI_CULL_BIT) + { /* NOTE: These are not viewport transformed yet. */ + GLfloat ex = v1->x - v0->x; + GLfloat ey = v1->y - v0->y; + GLfloat fx = v2->x - v0->x; + GLfloat fy = v2->y - v0->y; + GLfloat c = ex*fy-ey*fx; + + /* Culled... */ + if (c * fmesa->backface_sign > fmesa->ffb_zero) + return; + } +#endif + +#if (IND & FFB_TRI_FLAT_BIT) + const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v2->color[0] ); +#ifdef TRI_DEBUG + fprintf(stderr, "FFB_tri: const_fg %08x (B[%f] G[%f] R[%f])\n", + const_fg, + FFB_2_30_FIXED_TO_FLOAT(v2->color[0].blue), + FFB_2_30_FIXED_TO_FLOAT(v2->color[0].green), + FFB_2_30_FIXED_TO_FLOAT(v2->color[0].red)); +#endif +#endif + + +#if (IND & FFB_TRI_FLAT_BIT) + FFBFifo(fmesa, 1); + ffb->fg = const_fg; +#endif + +#if (IND & FFB_TRI_FLAT_BIT) + FFBFifo(fmesa, 9); +#else +#if (IND & FFB_TRI_ALPHA_BIT) + FFBFifo(fmesa, 21); +#else + FFBFifo(fmesa, 18); +#endif +#endif + + FFB_DUMP_VERTEX(v0); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v0); +#endif + ffb->red = FFB_GET_RED(v0); + ffb->green = FFB_GET_GREEN(v0); + ffb->blue = FFB_GET_BLUE(v0); +#endif + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_DUMP_VERTEX(v1); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v1); +#endif + ffb->red = FFB_GET_RED(v1); + ffb->green = FFB_GET_GREEN(v1); + ffb->blue = FFB_GET_BLUE(v1); +#endif + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_DUMP_VERTEX(v2); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v2); +#endif + ffb->red = FFB_GET_RED(v2); + ffb->green = FFB_GET_GREEN(v2); + ffb->blue = FFB_GET_BLUE(v2); +#endif + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + fmesa->ffbScreen->rp_active = 1; +} + + +static void TAG(ffb_quad)(GLcontext *ctx, + ffb_vertex *v0, + ffb_vertex *v1, + ffb_vertex *v2, + ffb_vertex *v3 ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_fbcPtr ffb = fmesa->regs; +#if (IND & FFB_TRI_FLAT_BIT) + GLuint const_fg; +#endif + FFB_DELAYED_VIEWPORT_VARS; + +#ifdef TRI_DEBUG + fprintf(stderr, "FFB: ffb_quad [" +#if (IND & FFB_TRI_CULL_BIT) + " CULL" +#endif +#if (IND & FFB_TRI_FLAT_BIT) + " FLAT" +#endif +#if (IND & FFB_TRI_ALPHA_BIT) + " ALPHA" +#endif + " ]\n"); +#endif /* TRI_DEBUG */ + +#if (IND & FFB_TRI_CULL_BIT) + { /* NOTE: These are not viewport transformed yet. */ + GLfloat ex = v2->x - v0->x; + GLfloat ey = v2->y - v0->y; + GLfloat fx = v3->x - v1->x; + GLfloat fy = v3->y - v1->y; + GLfloat c = ex*fy-ey*fx; + + /* Culled... */ + if (c * fmesa->backface_sign > fmesa->ffb_zero) + return; + } +#endif + +#if (IND & FFB_TRI_FLAT_BIT) + const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v3->color[0] ); +#ifdef TRI_DEBUG + fprintf(stderr, "FFB_quad: const_fg %08x (B[%f] G[%f] R[%f])\n", + const_fg, + FFB_2_30_FIXED_TO_FLOAT(v3->color[0].blue), + FFB_2_30_FIXED_TO_FLOAT(v3->color[0].green), + FFB_2_30_FIXED_TO_FLOAT(v3->color[0].red)); +#endif +#endif + + +#if (IND & FFB_TRI_FLAT_BIT) + FFBFifo(fmesa, 13); + ffb->fg = const_fg; +#else +#if (IND & FFB_TRI_ALPHA_BIT) + FFBFifo(fmesa, 28); +#else + FFBFifo(fmesa, 24); +#endif +#endif + + FFB_DUMP_VERTEX(v0); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v0); +#endif + ffb->red = FFB_GET_RED(v0); + ffb->green = FFB_GET_GREEN(v0); + ffb->blue = FFB_GET_BLUE(v0); +#endif + ffb->z = FFB_GET_Z(v0); + ffb->ryf = FFB_GET_Y(v0); + ffb->rxf = FFB_GET_X(v0); + + FFB_DUMP_VERTEX(v1); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v1); +#endif + ffb->red = FFB_GET_RED(v1); + ffb->green = FFB_GET_GREEN(v1); + ffb->blue = FFB_GET_BLUE(v1); +#endif + ffb->z = FFB_GET_Z(v1); + ffb->y = FFB_GET_Y(v1); + ffb->x = FFB_GET_X(v1); + + FFB_DUMP_VERTEX(v2); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v2); +#endif + ffb->red = FFB_GET_RED(v2); + ffb->green = FFB_GET_GREEN(v2); + ffb->blue = FFB_GET_BLUE(v2); +#endif + ffb->z = FFB_GET_Z(v2); + ffb->y = FFB_GET_Y(v2); + ffb->x = FFB_GET_X(v2); + + FFB_DUMP_VERTEX(v3); +#if !(IND & FFB_TRI_FLAT_BIT) +#if (IND & FFB_TRI_ALPHA_BIT) + ffb->alpha = FFB_GET_ALPHA(v3); +#endif + ffb->red = FFB_GET_RED(v3); + ffb->green = FFB_GET_GREEN(v3); + ffb->blue = FFB_GET_BLUE(v3); +#endif + ffb->z = FFB_GET_Z(v3); + ffb->dmyf = FFB_GET_Y(v3); + ffb->dmxf = FFB_GET_X(v3); + + fmesa->ffbScreen->rp_active = 1; +} + +static void TAG(ffb_init)(void) +{ + ffb_tri_tab[IND] = TAG(ffb_triangle); + ffb_quad_tab[IND] = TAG(ffb_quad); +} + +#undef IND +#undef TAG diff --git a/src/mesa/drivers/dri/ffb/ffb_vb.c b/src/mesa/drivers/dri/ffb/ffb_vb.c new file mode 100644 index 00000000000..40820c64143 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_vb.c @@ -0,0 +1,241 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.c,v 1.4 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "ffb_xmesa.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "mmath.h" +#include "imports.h" +#include "tnl/t_context.h" +#include "swrast_setup/swrast_setup.h" +#include "math/m_translate.h" + +#undef VB_DEBUG + +static void ffb_copy_pv_oneside(GLcontext *ctx, GLuint edst, GLuint esrc) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_vertex *dst = &fmesa->verts[edst]; + ffb_vertex *src = &fmesa->verts[esrc]; + +#ifdef VB_DEBUG + fprintf(stderr, "ffb_copy_pv_oneside: edst(%d) esrc(%d)\n", edst, esrc); +#endif + dst->color[0].alpha = src->color[0].alpha; + dst->color[0].red = src->color[0].red; + dst->color[0].green = src->color[0].green; + dst->color[0].blue = src->color[0].blue; +} + +static void ffb_copy_pv_twoside(GLcontext *ctx, GLuint edst, GLuint esrc) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + ffb_vertex *dst = &fmesa->verts[edst]; + ffb_vertex *src = &fmesa->verts[esrc]; + +#ifdef VB_DEBUG + fprintf(stderr, "ffb_copy_pv_twoside: edst(%d) esrc(%d)\n", edst, esrc); +#endif + dst->color[0].alpha = src->color[0].alpha; + dst->color[0].red = src->color[0].red; + dst->color[0].green = src->color[0].green; + dst->color[0].blue = src->color[0].blue; + dst->color[1].alpha = src->color[1].alpha; + dst->color[1].red = src->color[1].red; + dst->color[1].green = src->color[1].green; + dst->color[1].blue = src->color[1].blue; +} + +#define FFB_VB_RGBA_BIT 0x01 +#define FFB_VB_XYZ_BIT 0x02 +#define FFB_VB_TWOSIDE_BIT 0x04 +#define FFB_VB_MAX 0x08 + +typedef void (*emit_func)(GLcontext *, GLuint, GLuint); + +static struct { + emit_func emit; + interp_func interp; +} setup_tab[FFB_VB_MAX]; + +static void do_import(struct vertex_buffer *VB, + struct gl_client_array *to, + struct gl_client_array *from) +{ + GLuint count = VB->Count; + + if (!to->Ptr) { + to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 ); + to->Type = GL_FLOAT; + } + + /* No need to transform the same value 3000 times. */ + if (!from->StrideB) { + to->StrideB = 0; + count = 1; + } else + to->StrideB = 4 * sizeof(GLfloat); + + _math_trans_4f((GLfloat (*)[4]) to->Ptr, + from->Ptr, from->StrideB, + from->Type, from->Size, + 0, count); +} + +static __inline__ void ffbImportColors(ffbContextPtr fmesa, GLcontext *ctx, int index) +{ + struct gl_client_array *to = &fmesa->FloatColor; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + do_import(VB, to, VB->ColorPtr[index]); + VB->ColorPtr[index] = to; +} + +#define IND (FFB_VB_XYZ_BIT) +#define TAG(x) x##_w +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_RGBA_BIT) +#define TAG(x) x##_g +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT) +#define TAG(x) x##_wg +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_TWOSIDE_BIT) +#define TAG(x) x##_t +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_XYZ_BIT | FFB_VB_TWOSIDE_BIT) +#define TAG(x) x##_wt +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT) +#define TAG(x) x##_gt +#include "ffb_vbtmp.h" + +#define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT) +#define TAG(x) x##_wgt +#include "ffb_vbtmp.h" + +static void init_setup_tab( void ) +{ + init_w(); + init_g(); + init_wg(); + init_t(); + init_wt(); + init_gt(); + init_wgt(); +} + +#ifdef VB_DEBUG +static void ffbPrintSetupFlags(char *msg, GLuint flags) +{ + fprintf(stderr, "%s(%x): %s%s%s\n", + msg, + (int)flags, + (flags & FFB_VB_XYZ_BIT) ? " xyz," : "", + (flags & FFB_VB_RGBA_BIT) ? " rgba," : "", + (flags & FFB_VB_TWOSIDE_BIT) ? " twoside," : ""); +} +#endif + +static void ffbDDBuildVertices(GLcontext *ctx, GLuint start, GLuint count, + GLuint newinputs) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + newinputs |= fmesa->setupnewinputs; + fmesa->setupnewinputs = 0; + + if (!newinputs) + return; + + if (newinputs & VERT_BIT_CLIP) { + setup_tab[fmesa->setupindex].emit(ctx, start, count); + } else { + GLuint ind = 0; + + if (newinputs & VERT_BIT_COLOR0) + ind |= (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT); + + ind &= fmesa->setupindex; + + if (ind) + setup_tab[ind].emit(ctx, start, count); + } +} + +void ffbChooseVertexState( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + int ind = FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT; + + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) + ind |= FFB_VB_TWOSIDE_BIT; + +#ifdef VB_DEBUG + ffbPrintSetupFlags("ffb: full setup function", ind); +#endif + + fmesa->setupindex = ind; + + tnl->Driver.Render.BuildVertices = ffbDDBuildVertices; + tnl->Driver.Render.Interp = setup_tab[ind].interp; + if (ind & FFB_VB_TWOSIDE_BIT) + tnl->Driver.Render.CopyPV = ffb_copy_pv_twoside; + else + tnl->Driver.Render.CopyPV = ffb_copy_pv_oneside; +} + +void ffbInitVB( GLcontext *ctx ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + + fmesa->verts = (ffb_vertex *)ALIGN_MALLOC(size * sizeof(ffb_vertex), 32); + + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } + } +} + + +void ffbFreeVB( GLcontext *ctx ) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + if (fmesa->verts) { + ALIGN_FREE(fmesa->verts); + fmesa->verts = 0; + } +} diff --git a/src/mesa/drivers/dri/ffb/ffb_vb.h b/src/mesa/drivers/dri/ffb/ffb_vb.h new file mode 100644 index 00000000000..9eb6759f613 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_vb.h @@ -0,0 +1,45 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_VB_H +#define _FFB_VB_H + +#include "mtypes.h" +#include "macros.h" +#include "tnl/t_context.h" +#include "swrast/swrast.h" + +#define __FFB_2_30_FIXED_SCALE 1073741824.0f +#define FFB_2_30_FLOAT_TO_FIXED(X) \ + (IROUND((X) * fmesa->ffb_2_30_fixed_scale)) +#define FFB_2_30_FIXED_TO_FLOAT(X) \ + (((GLfloat)(X)) * fmesa->ffb_one_over_2_30_fixed_scale) + +#define __FFB_16_16_FIXED_SCALE 65536.0f +#define FFB_16_16_FLOAT_TO_FIXED(X) \ + (IROUND((X) * fmesa->ffb_16_16_fixed_scale)) +#define FFB_16_16_FIXED_TO_FLOAT(X) \ + (((GLfloat)(X)) * fmesa->ffb_one_over_16_16_fixed_scale) + +#define FFB_Z_FROM_FLOAT(VAL) FFB_2_30_FLOAT_TO_FIXED(VAL) +#define FFB_Z_TO_FLOAT(VAL) FFB_2_30_FIXED_TO_FLOAT(VAL) +#define FFB_XY_FROM_FLOAT(VAL) FFB_16_16_FLOAT_TO_FIXED(VAL) +#define FFB_XY_TO_FLOAT(VAL) FFB_16_16_FIXED_TO_FLOAT(VAL) + +#define FFB_UBYTE_FROM_COLOR(VAL) ((IROUND((VAL) * fmesa->ffb_ubyte_color_scale))) + +#define FFB_PACK_CONST_UBYTE_ARGB_COLOR(C) \ + ((FFB_UBYTE_FROM_COLOR(C.alpha) << 24) | \ + (FFB_UBYTE_FROM_COLOR(C.blue) << 16) | \ + (FFB_UBYTE_FROM_COLOR(C.green) << 8) | \ + (FFB_UBYTE_FROM_COLOR(C.red) << 0)) + +#define FFB_COLOR_FROM_FLOAT(VAL) FFB_2_30_FLOAT_TO_FIXED(VAL) + +#define _FFB_NEW_VERTEX (_DD_NEW_TRI_LIGHT_TWOSIDE) + +extern void ffbDDSetupInit(void); +extern void ffbChooseVertexState(GLcontext *); +extern void ffbInitVB( GLcontext *ctx ); +extern void ffbFreeVB( GLcontext *ctx ); + +#endif /* !(_FFB_VB_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_vbtmp.h b/src/mesa/drivers/dri/ffb/ffb_vbtmp.h new file mode 100644 index 00000000000..ac0c6f0a8b3 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_vbtmp.h @@ -0,0 +1,177 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vbtmp.h,v 1.1 2002/02/22 21:32:59 dawes Exp $ */ + +static void TAG(emit)(GLcontext *ctx, GLuint start, GLuint end) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; +#if (IND & (FFB_VB_RGBA_BIT)) + GLfloat (*col0)[4]; + GLuint col0_stride; +#if (IND & (FFB_VB_TWOSIDE_BIT)) + GLfloat (*col1)[4]; + GLuint col1_stride; +#endif +#endif +#if (IND & FFB_VB_XYZ_BIT) + GLfloat (*proj)[4] = VB->NdcPtr->data; + GLuint proj_stride = VB->NdcPtr->stride; + const GLubyte *mask = VB->ClipMask; +#endif + ffb_vertex *v = &fmesa->verts[start]; + int i; + +#ifdef VB_DEBUG + fprintf(stderr, "FFB: ffb_emit [" +#if (IND & (FFB_VB_XYZ_BIT)) + " XYZ" +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + " RGBA" +#endif +#if (IND & (FFB_VB_TWOSIDE_BIT)) + " TWOSIDE" +#endif + "] start(%d) end(%d) import(%d)\n", + start, end, + VB->importable_data); +#endif + +#if (IND & (FFB_VB_RGBA_BIT)) + if (VB->ColorPtr[0]->Type != GL_FLOAT) + ffbImportColors(fmesa, ctx, 0); +#if (IND & (FFB_VB_TWOSIDE_BIT)) + if (VB->ColorPtr[1]->Type != GL_FLOAT) + ffbImportColors(fmesa, ctx, 1); +#endif + col0 = (GLfloat (*)[4]) VB->ColorPtr[0]->Ptr; + col0_stride = VB->ColorPtr[0]->StrideB; +#if (IND & (FFB_VB_TWOSIDE_BIT)) + col1 = (GLfloat (*)[4]) VB->ColorPtr[1]->Ptr; + col1_stride = VB->ColorPtr[1]->StrideB; +#endif +#endif + + if (VB->importable_data) { + if (start) { +#if (IND & (FFB_VB_XYZ_BIT)) + proj = (GLfloat (*)[4])((GLubyte *)proj + start * proj_stride); +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + col0 = (GLfloat (*)[4])((GLubyte *)col0 + start * col0_stride); +#if (IND & (FFB_VB_TWOSIDE_BIT)) + col1 = (GLfloat (*)[4])((GLubyte *)col1 + start * col1_stride); +#endif +#endif + } + for (i = start; i < end; i++, v++) { +#if (IND & (FFB_VB_XYZ_BIT)) + if (mask[i] == 0) { + v->x = proj[0][0]; + v->y = proj[0][1]; + v->z = proj[0][2]; + } + proj = (GLfloat (*)[4])((GLubyte *)proj + proj_stride); +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + v->color[0].alpha = CLAMP(col0[0][3], 0.0f, 1.0f); + v->color[0].red = CLAMP(col0[0][0], 0.0f, 1.0f); + v->color[0].green = CLAMP(col0[0][1], 0.0f, 1.0f); + v->color[0].blue = CLAMP(col0[0][2], 0.0f, 1.0f); + col0 = (GLfloat (*)[4])((GLubyte *)col0 + col0_stride); +#if (IND & (FFB_VB_TWOSIDE_BIT)) + v->color[1].alpha = CLAMP(col1[0][3], 0.0f, 1.0f); + v->color[1].red = CLAMP(col1[0][0], 0.0f, 1.0f); + v->color[1].green = CLAMP(col1[0][1], 0.0f, 1.0f); + v->color[1].blue = CLAMP(col1[0][2], 0.0f, 1.0f); + col1 = (GLfloat (*)[4])((GLubyte *)col1 + col1_stride); +#endif +#endif + } + } else { + for (i = start; i < end; i++, v++) { +#if (IND & (FFB_VB_XYZ_BIT)) + if (mask[i] == 0) { + v->x = proj[i][0]; + v->y = proj[i][1]; + v->z = proj[i][2]; + } +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + v->color[0].alpha = CLAMP(col0[i][3], 0.0f, 1.0f); + v->color[0].red = CLAMP(col0[i][0], 0.0f, 1.0f); + v->color[0].green = CLAMP(col0[i][1], 0.0f, 1.0f); + v->color[0].blue = CLAMP(col0[i][2], 0.0f, 1.0f); +#if (IND & (FFB_VB_TWOSIDE_BIT)) + v->color[1].alpha = CLAMP(col1[i][3], 0.0f, 1.0f); + v->color[1].red = CLAMP(col1[i][0], 0.0f, 1.0f); + v->color[1].green = CLAMP(col1[i][1], 0.0f, 1.0f); + v->color[1].blue = CLAMP(col1[i][2], 0.0f, 1.0f); +#endif +#endif + } + } +} + +static void TAG(interp)(GLcontext *ctx, GLfloat t, + GLuint edst, GLuint eout, GLuint ein, + GLboolean force_boundary) +{ +#if (IND & (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT)) + ffbContextPtr fmesa = FFB_CONTEXT(ctx); +#endif +#if (IND & (FFB_VB_XYZ_BIT)) + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + const GLfloat *dstclip = VB->ClipPtr->data[edst]; + GLfloat oow = 1.0 / dstclip[3]; +#endif +#if (IND & (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT)) + ffb_vertex *dst = &fmesa->verts[edst]; +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + ffb_vertex *in = &fmesa->verts[eout]; + ffb_vertex *out = &fmesa->verts[ein]; +#endif + +#ifdef VB_DEBUG + fprintf(stderr, "FFB: ffb_interp [" +#if (IND & (FFB_VB_XYZ_BIT)) + " XYZ" +#endif +#if (IND & (FFB_VB_RGBA_BIT)) + " RGBA" +#endif +#if (IND & (FFB_VB_TWOSIDE_BIT)) + " TWOSIDE" +#endif + "] edst(%d) eout(%d) ein(%d)\n", + edst, eout, ein); +#endif + +#if (IND & (FFB_VB_XYZ_BIT)) + dst->x = dstclip[0] * oow; + dst->y = dstclip[1] * oow; + dst->z = dstclip[2] * oow; +#endif + +#if (IND & (FFB_VB_RGBA_BIT)) + INTERP_F(t, dst->color[0].alpha, out->color[0].alpha, in->color[0].alpha); + INTERP_F(t, dst->color[0].red, out->color[0].red, in->color[0].red); + INTERP_F(t, dst->color[0].green, out->color[0].green, in->color[0].green); + INTERP_F(t, dst->color[0].blue, out->color[0].blue, in->color[0].blue); +#if (IND & (FFB_VB_TWOSIDE_BIT)) + INTERP_F(t, dst->color[1].alpha, out->color[1].alpha, in->color[1].alpha); + INTERP_F(t, dst->color[1].red, out->color[1].red, in->color[1].red); + INTERP_F(t, dst->color[1].green, out->color[1].green, in->color[1].green); + INTERP_F(t, dst->color[1].blue, out->color[1].blue, in->color[1].blue); +#endif +#endif +} + +static void TAG(init)(void) +{ + setup_tab[IND].emit = TAG(emit); + setup_tab[IND].interp = TAG(interp); +} + +#undef IND +#undef TAG diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c new file mode 100644 index 00000000000..5f6d5c902dd --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c @@ -0,0 +1,429 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vtxfmt.c,v 1.1 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#include "glheader.h" +#include "api_noop.h" +#include "context.h" +#include "light.h" +#include "macros.h" +#include "imports.h" +#include "mmath.h" +#include "mtypes.h" +#include "simple_list.h" +#include "vtxfmt.h" +#include "ffb_xmesa.h" +#include "ffb_context.h" +#include "ffb_vb.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +#include "ffb_vtxfmt.h" + +#ifndef __GNUC__ +#define __inline /**/ +#endif + +#define TNL_VERTEX ffbTnlVertex + +#define LINTERP( T, A, B ) ((A) + (T) * ((B) - (A))) + +#define INTERP_RGBA(t, out, a, b) \ +do { \ + GLint i; \ + for ( i = 0 ; i < 4 ; i++ ) { \ + GLfloat fa = a[i]; \ + GLfloat fb = b[i]; \ + out[i] = LINTERP( t, fa, fb ); \ + } \ +} while (0) + +/* Color functions: */ + +static __inline void ffb_recalc_base_color(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + struct gl_light *light; + + COPY_3V(fmesa->vtx_state.light.base_color, ctx->Light._BaseColor[0]); + foreach (light, &ctx->Light.EnabledList) { + ACC_3V(fmesa->vtx_state.light.base_color, + light->_MatAmbient[0]); + } + + fmesa->vtx_state.light.base_alpha = ctx->Light._BaseAlpha[0]; +} + +#define GET_CURRENT \ + GET_CURRENT_CONTEXT(ctx); \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx) + +#define CURRENT_COLOR(COMP) fmesa->vtx_state.current.color[COMP] +#define CURRENT_SPECULAR(COMP) fmesa->vtx_state.current.specular[COMP] +#define COLOR_IS_FLOAT +#define RECALC_BASE_COLOR(ctx) ffb_recalc_base_color(ctx) + +#define TAG(x) ffb_##x +#include "tnl_dd/t_dd_imm_capi.h" + +/* Normal functions: */ + +struct ffb_norm_tab { + void (*normal3f_multi)(GLfloat x, GLfloat y, GLfloat z); + void (*normal3fv_multi)(const GLfloat *v); + void (*normal3f_single)(GLfloat x, GLfloat y, GLfloat z); + void (*normal3fv_single)(const GLfloat *v); +}; + +static struct ffb_norm_tab norm_tab[0x4]; + +#define HAVE_HW_LIGHTING 0 +#define GET_CURRENT_VERTEX \ + GET_CURRENT_CONTEXT(ctx); \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ + ffbTnlVertexPtr v = fmesa->imm.v0 + +#define CURRENT_NORMAL fmesa->vtx_state.current.normal +#define BASE_COLOR fmesa->vtx_state.light.base_color +#define BASE_ALPHA fmesa->vtx_state.light.base_alpha +#define VERT_COLOR( COMP ) v->color[COMP] +#define VERT_COLOR_IS_FLOAT + +#define IND (0) +#define TAG(x) ffb_##x +#define PRESERVE_NORMAL_DEFS +#include "tnl_dd/t_dd_imm_napi.h" + +#define IND (NORM_RESCALE) +#define TAG(x) ffb_##x##_rescale +#define PRESERVE_NORMAL_DEFS +#include "tnl_dd/t_dd_imm_napi.h" + +#define IND (NORM_NORMALIZE) +#define TAG(x) ffb_##x##_normalize +#include "tnl_dd/t_dd_imm_napi.h" + +static void ffb_init_norm_funcs(void) +{ + ffb_init_norm(); + ffb_init_norm_rescale(); + ffb_init_norm_normalize(); +} + +static void choose_normals(void) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint index; + + if (ctx->Light.Enabled) { + if (ctx->Transform.Normalize) { + index = NORM_NORMALIZE; + } else if (!ctx->Transform.RescaleNormals && + ctx->_ModelViewInvScale != 1.0) { + index = NORM_RESCALE; + } else { + index = 0; + } + + if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) { + ctx->Exec->Normal3f = norm_tab[index].normal3f_single; + ctx->Exec->Normal3fv = norm_tab[index].normal3fv_single; + } else { + ctx->Exec->Normal3f = norm_tab[index].normal3f_multi; + ctx->Exec->Normal3fv = norm_tab[index].normal3fv_multi; + } + } else { + ctx->Exec->Normal3f = _mesa_noop_Normal3f; + ctx->Exec->Normal3fv = _mesa_noop_Normal3fv; + } +} + +static void ffb_choose_Normal3f(GLfloat x, GLfloat y, GLfloat z) +{ + choose_normals(); + glNormal3f(x, y, z); +} + +static void ffb_choose_Normal3fv(const GLfloat *v) +{ + choose_normals(); + glNormal3fv(v); +} + +/* Vertex functions: */ + +#define GET_CURRENT_VERTEX \ + GET_CURRENT_CONTEXT(ctx); \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ + ffbTnlVertexPtr v = fmesa->imm.v0 + +#define CURRENT_VERTEX v->obj +#define SAVE_VERTEX fmesa->imm.save_vertex(ctx, v) + +#define TAG(x) ffb_##x +#include "tnl_dd/t_dd_imm_vapi.h" + +struct ffb_vert_tab { + void (*save_vertex)(GLcontext *ctx, ffbTnlVertexPtr v); + void (*interpolate_vertex)(GLfloat t, + ffbTnlVertex *O, + const ffbTnlVertex *I, + const ffbTnlVertex *J); +}; + +static struct ffb_vert_tab vert_tab[0xf]; + +#define VTX_NORMAL 0x0 +#define VTX_RGBA 0x1 + +#define LOCAL_VARS \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx) + +#define CURRENT_COLOR fmesa->vtx_state.current.color +#define COLOR_IS_FLOAT +#define FLUSH_VERTEX fmesa->imm.flush_vertex( ctx, v ); + +#define IND (VTX_NORMAL) +#define TAG(x) ffb_##x##_NORMAL +#define PRESERVE_VERTEX_DEFS +#include "tnl_dd/t_dd_imm_vertex.h" + +#define IND (VTX_RGBA) +#define TAG(x) ffb_##x##_RGBA +#include "tnl_dd/t_dd_imm_vertex.h" + +static void ffb_init_vert_funcs( void ) +{ + ffb_init_vert_NORMAL(); + ffb_init_vert_RGBA(); +} + +#define LOCAL_VARS \ + ffbContextPtr fmesa = FFB_CONTEXT(ctx) + +#define GET_INTERP_FUNC \ + ffb_interp_func interp = fmesa->imm.interp + +#define FLUSH_VERTEX fmesa->imm.flush_vertex +#define IMM_VERTEX( V ) fmesa->imm.V +#define IMM_VERTICES( n ) fmesa->imm.vertices[n] + +#define EMIT_VERTEX_USES_HWREGS + +/* XXX Implement me XXX */ +#define EMIT_VERTEX_TRI(VTX0, VTX1, VTX2) \ + do { } while (0) +#define EMIT_VERTEX_LINE(VTX0, VTX1) \ + do { } while (0) +#define EMIT_VERTEX_POINT(VTX0) \ + do { } while (0) + +#define TAG(x) ffb_##x +#include "tnl_dd/t_dd_imm_primtmp.h" + +/* Bzzt: Material changes are lost on fallback. */ +static void ffb_Materialfv(GLenum face, GLenum pname, + const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + + _mesa_noop_Materialfv( face, pname, params ); + ffb_recalc_base_color( ctx ); +} + +/* Fallback functions: */ + +static void ffb_do_fallback(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + struct ffb_current_state *current = &fmesa->vtx_state.current; + + /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks + * and revive internal state that depended on those callbacks: + */ + _tnl_wakeup_exec(ctx); + + /* Replay enough vertices that the current primitive is continued + * correctly: + */ + if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) + glBegin(fmesa->imm.prim); + + if (ctx->Light.Enabled) { + glColor4fv(ctx->Current.Color); /* Catch ColorMaterial */ + glNormal3fv(current->normal); + } else { + glColor4fv(current->color); + } +} + +#define PRE_LOOPBACK( FUNC ) do { \ + GET_CURRENT_CONTEXT(ctx); \ + ffb_do_fallback( ctx ); \ +} while (0) + +#define TAG(x) ffb_fallback_##x +#include "vtxfmt_tmp.h" + +static void ffb_Begin(GLenum prim) +{ + GET_CURRENT_CONTEXT(ctx); + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + if (prim > GL_POLYGON) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); + return; + } + + if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + return; + } + + ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES | + FLUSH_UPDATE_CURRENT); + + fmesa->imm.prim = prim; + fmesa->imm.v0 = &fmesa->imm.vertices[0]; + fmesa->imm.save_vertex = ffb_save_vertex_RGBA; + fmesa->imm.flush_vertex = ffb_flush_tab[prim]; + + /* XXX Lock hardware, update FBC, PPC, DRAWOP, etc. XXX */ +} + +static void ffb_End(void) +{ + GET_CURRENT_CONTEXT(ctx); + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + + if (fmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); + return; + } + + fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; + + ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES | + FLUSH_UPDATE_CURRENT); + + /* XXX Unlock hardware, etc. */ +} + +void ffbInitTnlModule(GLcontext *ctx) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + GLvertexformat *vfmt = &(fmesa->imm.vtxfmt); + + /* Work in progress... */ + return; + + ffb_init_norm_funcs(); + ffb_init_vert_funcs(); + + MEMSET(vfmt, 0, sizeof(GLvertexformat)); + + /* Handled fully in supported states: */ + vfmt->ArrayElement = NULL; /* FIXME: ... */ + vfmt->Color3f = ffb_choose_Color3f; + vfmt->Color3fv = ffb_choose_Color3fv; + vfmt->Color3ub = ffb_choose_Color3ub; + vfmt->Color3ubv = ffb_choose_Color3ubv; + vfmt->Color4f = ffb_choose_Color4f; + vfmt->Color4fv = ffb_choose_Color4fv; + vfmt->Color4ub = ffb_choose_Color4ub; + vfmt->Color4ubv = ffb_choose_Color4ubv; + vfmt->FogCoordfvEXT = ffb_FogCoordfvEXT; + vfmt->FogCoordfEXT = ffb_FogCoordfEXT; + vfmt->Materialfv = ffb_Materialfv; + vfmt->MultiTexCoord1fARB = ffb_fallback_MultiTexCoord1fARB; + vfmt->MultiTexCoord1fvARB = ffb_fallback_MultiTexCoord1fvARB; + vfmt->MultiTexCoord2fARB = ffb_fallback_MultiTexCoord2fARB; + vfmt->MultiTexCoord2fvARB = ffb_fallback_MultiTexCoord2fvARB; + vfmt->MultiTexCoord3fARB = ffb_fallback_MultiTexCoord3fARB; + vfmt->MultiTexCoord3fvARB = ffb_fallback_MultiTexCoord3fvARB; + vfmt->MultiTexCoord4fARB = ffb_fallback_MultiTexCoord4fARB; + vfmt->MultiTexCoord4fvARB = ffb_fallback_MultiTexCoord4fvARB; + vfmt->Normal3f = ffb_choose_Normal3f; + vfmt->Normal3fv = ffb_choose_Normal3fv; + vfmt->SecondaryColor3ubEXT = ffb_SecondaryColor3ubEXT; + vfmt->SecondaryColor3ubvEXT = ffb_SecondaryColor3ubvEXT; + vfmt->SecondaryColor3fEXT = ffb_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = ffb_SecondaryColor3fvEXT; + vfmt->TexCoord1f = ffb_fallback_TexCoord1f; + vfmt->TexCoord1fv = ffb_fallback_TexCoord1fv; + vfmt->TexCoord2f = ffb_fallback_TexCoord2f; + vfmt->TexCoord2fv = ffb_fallback_TexCoord2fv; + vfmt->TexCoord3f = ffb_fallback_TexCoord3f; + vfmt->TexCoord3fv = ffb_fallback_TexCoord3fv; + vfmt->TexCoord4f = ffb_fallback_TexCoord4f; + vfmt->TexCoord4fv = ffb_fallback_TexCoord4fv; + + vfmt->Vertex2f = ffb_Vertex2f; + vfmt->Vertex2fv = ffb_Vertex2fv; + vfmt->Vertex3f = ffb_Vertex3f; + vfmt->Vertex3fv = ffb_Vertex3fv; + vfmt->Vertex4f = ffb_Vertex4f; + vfmt->Vertex4fv = ffb_Vertex4fv; + + vfmt->Begin = ffb_Begin; + vfmt->End = ffb_End; + + vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ + + vfmt->DrawArrays = NULL; + vfmt->DrawElements = NULL; + vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */ + + + /* Not active in supported states; just keep ctx->Current uptodate: */ + vfmt->EdgeFlag = _mesa_noop_EdgeFlag; + vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; + vfmt->Indexi = _mesa_noop_Indexi; + vfmt->Indexiv = _mesa_noop_Indexiv; + + /* Active but unsupported -- fallback if we receive these: + * + * All of these fallbacks can be fixed with additional code, except + * CallList, unless we build a play_immediate_noop() command which + * turns an immediate back into glBegin/glEnd commands... + */ + vfmt->CallList = ffb_fallback_CallList; + vfmt->EvalCoord1f = ffb_fallback_EvalCoord1f; + vfmt->EvalCoord1fv = ffb_fallback_EvalCoord1fv; + vfmt->EvalCoord2f = ffb_fallback_EvalCoord2f; + vfmt->EvalCoord2fv = ffb_fallback_EvalCoord2fv; + vfmt->EvalMesh1 = ffb_fallback_EvalMesh1; + vfmt->EvalMesh2 = ffb_fallback_EvalMesh2; + vfmt->EvalPoint1 = ffb_fallback_EvalPoint1; + vfmt->EvalPoint2 = ffb_fallback_EvalPoint2; + + vfmt->prefer_float_colors = GL_TRUE; + + fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; + + /* THIS IS A HACK! */ + _mesa_install_exec_vtxfmt( ctx, vfmt ); +} diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.h b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.h new file mode 100644 index 00000000000..063bb4923ef --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.h @@ -0,0 +1,8 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vtxfmt.h,v 1.1 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_VTXFMT_H +#define _FFB_VTXFMT_H + +extern void ffbInitTnlModule(GLcontext *); + +#endif /* !(_FFB_VTXFMT_H) */ diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c new file mode 100644 index 00000000000..caca9d4384a --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.c @@ -0,0 +1,593 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.c,v 1.4 2002/02/22 21:32:59 dawes Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller <[email protected]> + */ + +#ifdef GLX_DIRECT_RENDERING + +#include "ffb_xmesa.h" +#include "context.h" +#include "matrix.h" +#include "simple_list.h" +#include "imports.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "array_cache/acache.h" + +#include "ffb_context.h" +#include "ffb_dd.h" +#include "ffb_span.h" +#include "ffb_depth.h" +#include "ffb_stencil.h" +#include "ffb_clear.h" +#include "ffb_vb.h" +#include "ffb_tris.h" +#include "ffb_lines.h" +#include "ffb_points.h" +#include "ffb_state.h" +#include "ffb_tex.h" +#include "ffb_lock.h" +#include "ffb_vtxfmt.h" +#include "ffb_bitmap.h" + +static GLboolean +ffbInitDriver(__DRIscreenPrivate *sPriv) +{ + ffbScreenPrivate *ffbScreen; + FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv; + + if (getenv("LIBGL_FORCE_XSERVER")) + return GL_FALSE; + + /* Allocate the private area. */ + ffbScreen = (ffbScreenPrivate *) Xmalloc(sizeof(ffbScreenPrivate)); + if (!ffbScreen) + return GL_FALSE; + + /* Map FBC registers. */ + if (drmMap(sPriv->fd, + gDRIPriv->hFbcRegs, + gDRIPriv->sFbcRegs, + &gDRIPriv->mFbcRegs)) { + Xfree(ffbScreen); + return GL_FALSE; + } + ffbScreen->regs = (ffb_fbcPtr) gDRIPriv->mFbcRegs; + + /* Map ramdac registers. */ + if (drmMap(sPriv->fd, + gDRIPriv->hDacRegs, + gDRIPriv->sDacRegs, + &gDRIPriv->mDacRegs)) { + drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs); + Xfree(ffbScreen); + return GL_FALSE; + } + ffbScreen->dac = (ffb_dacPtr) gDRIPriv->mDacRegs; + + /* Map "Smart" framebuffer views. */ + if (drmMap(sPriv->fd, + gDRIPriv->hSfb8r, + gDRIPriv->sSfb8r, + &gDRIPriv->mSfb8r)) { + drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs); + drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs); + Xfree(ffbScreen); + return GL_FALSE; + } + ffbScreen->sfb8r = (volatile char *) gDRIPriv->mSfb8r; + + if (drmMap(sPriv->fd, + gDRIPriv->hSfb32, + gDRIPriv->sSfb32, + &gDRIPriv->mSfb32)) { + drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs); + drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs); + drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r); + Xfree(ffbScreen); + return GL_FALSE; + } + ffbScreen->sfb32 = (volatile char *) gDRIPriv->mSfb32; + + if (drmMap(sPriv->fd, + gDRIPriv->hSfb64, + gDRIPriv->sSfb64, + &gDRIPriv->mSfb64)) { + drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs); + drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs); + drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r); + drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32); + Xfree(ffbScreen); + return GL_FALSE; + } + ffbScreen->sfb64 = (volatile char *) gDRIPriv->mSfb64; + + ffbScreen->fifo_cache = 0; + ffbScreen->rp_active = 0; + + ffbScreen->sPriv = sPriv; + sPriv->private = (void *) ffbScreen; + + ffbDDLinefuncInit(); + ffbDDPointfuncInit(); + + return GL_TRUE; +} + + +static void +ffbDestroyScreen(__DRIscreenPrivate *sPriv) +{ + ffbScreenPrivate *ffbScreen = sPriv->private; + FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv; + + drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs); + drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs); + drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r); + drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32); + drmUnmap(gDRIPriv->mSfb64, gDRIPriv->sSfb64); + + Xfree(ffbScreen); +} + +static const struct gl_pipeline_stage *ffb_pipeline[] = { + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + /* REMOVE: fog coord stage */ + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + /* REMOVE: point attenuation stage */ + &_tnl_render_stage, + 0, +}; + +/* Create and initialize the Mesa and driver specific context data */ +static GLboolean +ffbCreateContext(const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + ffbContextPtr fmesa; + GLcontext *ctx, *shareCtx; + __DRIscreenPrivate *sPriv; + ffbScreenPrivate *ffbScreen; + char *debug; + + /* Allocate ffb context */ + fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec)); + if (!fmesa) + return GL_FALSE; + + /* Allocate Mesa context */ + if (sharedContextPrivate) + shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, fmesa, GL_TRUE); + if (!fmesa->glCtx) { + FREE(fmesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = fmesa; + ctx = fmesa->glCtx; + + sPriv = driContextPriv->driScreenPriv; + ffbScreen = (ffbScreenPrivate *) sPriv->private; + + /* Dri stuff. */ + fmesa->hHWContext = driContextPriv->hHWContext; + fmesa->driFd = sPriv->fd; + fmesa->driHwLock = &sPriv->pSAREA->lock; + + fmesa->ffbScreen = ffbScreen; + fmesa->driScreen = sPriv; + fmesa->ffb_sarea = FFB_DRISHARE(sPriv->pSAREA); + + /* Register and framebuffer hw pointers. */ + fmesa->regs = ffbScreen->regs; + fmesa->sfb32 = ffbScreen->sfb32; + + ffbDDInitContextHwState(ctx); + + /* Default clear and depth colors. */ + { + GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F); + GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F); + GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F); + + fmesa->clear_pixel = ((r << 0) | + (g << 8) | + (b << 16)); + } + fmesa->clear_depth = Z_FROM_MESA(ctx->Depth.Clear * 4294967295.0f); + fmesa->clear_stencil = ctx->Stencil.Clear & 0xf; + + /* No wide points. */ + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = 1.0; + ctx->Const.MaxPointSizeAA = 1.0; + + /* Disable wide lines as we can't antialias them correctly in + * hardware. + */ + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 1.0; + ctx->Const.MaxLineWidthAA = 1.0; + ctx->Const.LineWidthGranularity = 1.0; + + /* Instead of having GCC emit these constants a zillion times + * everywhere in the driver, put them here. + */ + fmesa->ffb_2_30_fixed_scale = __FFB_2_30_FIXED_SCALE; + fmesa->ffb_one_over_2_30_fixed_scale = (1.0 / __FFB_2_30_FIXED_SCALE); + fmesa->ffb_16_16_fixed_scale = __FFB_16_16_FIXED_SCALE; + fmesa->ffb_one_over_16_16_fixed_scale = (1.0 / __FFB_16_16_FIXED_SCALE); + fmesa->ffb_ubyte_color_scale = 255.0f; + fmesa->ffb_zero = 0.0f; + + fmesa->debugFallbacks = GL_FALSE; + debug = getenv("LIBGL_DEBUG"); + if (debug && strstr(debug, "fallbacks")) + fmesa->debugFallbacks = GL_TRUE; + + /* Initialize the software rasterizer and helper modules. */ + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + /* All of this need only be done once for a new context. */ + ffbDDExtensionsInit(ctx); + ffbDDInitDriverFuncs(ctx); + ffbDDInitStateFuncs(ctx); + ffbDDInitSpanFuncs(ctx); + ffbDDInitDepthFuncs(ctx); + ffbDDInitStencilFuncs(ctx); + ffbDDInitRenderFuncs(ctx); + ffbDDInitTexFuncs(ctx); + ffbDDInitBitmapFuncs(ctx); + ffbInitVB(ctx); + + ffbInitTnlModule(ctx); + + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, ffb_pipeline); + + return GL_TRUE; +} + +static void +ffbDestroyContext(__DRIcontextPrivate *driContextPriv) +{ + ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate; + + if (fmesa) { + ffbFreeVB(fmesa->glCtx); + + _swsetup_DestroyContext( fmesa->glCtx ); + _tnl_DestroyContext( fmesa->glCtx ); + _ac_DestroyContext( fmesa->glCtx ); + _swrast_DestroyContext( fmesa->glCtx ); + + /* free the Mesa context */ + fmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context(fmesa->glCtx); + + FREE(fmesa); + } +} + +/* Create and initialize the Mesa and driver specific pixmap buffer data */ +static GLboolean +ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } + else { + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + mesaVis->stencilBits > 0, + mesaVis->accumRedBits > 0, + mesaVis->alphaBits > 0); + return (driDrawPriv->driverPrivate != NULL); + } +} + + +static void +ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); +} + + +#define USE_FAST_SWAP + +static void +ffbSwapBuffers( __DRIdrawablePrivate *dPriv ) +{ + ffbContextPtr fmesa = (ffbContextPtr) dPriv->driContextPriv->driverPrivate; + unsigned int fbc, wid, wid_reg_val, dac_db_bit; + unsigned int shadow_dac_addr, active_dac_addr; + ffb_fbcPtr ffb; + ffb_dacPtr dac; + + if (fmesa == NULL || + fmesa->glCtx->Visual.doubleBufferMode == 0) + return; + + /* Flush pending rendering commands */ + _mesa_notifySwapBuffers(fmesa->glCtx); + + ffb = fmesa->regs; + dac = fmesa->ffbScreen->dac; + + fbc = fmesa->fbc; + wid = fmesa->wid; + + /* Swap the buffer we render into and read pixels from. */ + fmesa->back_buffer ^= 1; + + /* If we are writing into both buffers, don't mess with + * the WB setting. + */ + if ((fbc & FFB_FBC_WB_AB) != FFB_FBC_WB_AB) { + if ((fbc & FFB_FBC_WB_A) != 0) + fbc = (fbc & ~FFB_FBC_WB_A) | FFB_FBC_WB_B; + else + fbc = (fbc & ~FFB_FBC_WB_B) | FFB_FBC_WB_A; + } + + /* But either way, we must flip the read buffer setting. */ + if ((fbc & FFB_FBC_RB_A) != 0) + fbc = (fbc & ~FFB_FBC_RB_A) | FFB_FBC_RB_B; + else + fbc = (fbc & ~FFB_FBC_RB_B) | FFB_FBC_RB_A; + + LOCK_HARDWARE(fmesa); + + if (fmesa->fbc != fbc) { + FFBFifo(fmesa, 1); + ffb->fbc = fmesa->fbc = fbc; + fmesa->ffbScreen->rp_active = 1; + } + + /* And swap the buffer displayed in the WID. */ + if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) { + shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid); + active_dac_addr = FFBDAC_PAC1_APWLUT(wid); + dac_db_bit = FFBDAC_PAC1_WLUT_DB; + } else { + shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid); + active_dac_addr = FFBDAC_PAC2_APWLUT(wid); + dac_db_bit = FFBDAC_PAC2_WLUT_DB; + } + + FFBWait(fmesa, ffb); + + wid_reg_val = DACCFG_READ(dac, active_dac_addr); + if (fmesa->back_buffer == 0) + wid_reg_val |= dac_db_bit; + else + wid_reg_val &= ~dac_db_bit; +#ifdef USE_FAST_SWAP + DACCFG_WRITE(dac, active_dac_addr, wid_reg_val); +#else + DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val); + + /* Schedule the window transfer. */ + DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL, + (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE)); + + { + int limit = 1000000; + while (limit--) { + unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL); + + if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0) + break; + } + } +#endif + + UNLOCK_HARDWARE(fmesa); +} + +static void ffb_init_wid(ffbContextPtr fmesa, unsigned int wid) +{ + ffb_dacPtr dac = fmesa->ffbScreen->dac; + unsigned int wid_reg_val, dac_db_bit, active_dac_addr; + unsigned int shadow_dac_addr; + + if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) { + shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid); + active_dac_addr = FFBDAC_PAC1_APWLUT(wid); + dac_db_bit = FFBDAC_PAC1_WLUT_DB; + } else { + shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid); + active_dac_addr = FFBDAC_PAC2_APWLUT(wid); + dac_db_bit = FFBDAC_PAC2_WLUT_DB; + } + + wid_reg_val = DACCFG_READ(dac, active_dac_addr); + wid_reg_val &= ~dac_db_bit; +#ifdef USE_FAST_SWAP + DACCFG_WRITE(dac, active_dac_addr, wid_reg_val); +#else + DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val); + + /* Schedule the window transfer. */ + DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL, + (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE)); + + { + int limit = 1000000; + while (limit--) { + unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL); + + if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0) + break; + } + } +#endif +} + +/* Force the context `c' to be the current context and associate with it + buffer `b' */ +static GLboolean +ffbMakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (driContextPriv) { + ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate; + int first_time; + + fmesa->driDrawable = driDrawPriv; + + _mesa_make_current2(fmesa->glCtx, + (GLframebuffer *) driDrawPriv->driverPrivate, + (GLframebuffer *) driReadPriv->driverPrivate); + + if (!fmesa->glCtx->Viewport.Width) + _mesa_set_viewport(fmesa->glCtx, + 0, 0, + driDrawPriv->w, + driDrawPriv->h); + + first_time = 0; + if (fmesa->wid == ~0) { + first_time = 1; + if (getenv("LIBGL_SOFTWARE_RENDERING")) + FALLBACK( fmesa->glCtx, FFB_BADATTR_SWONLY, GL_TRUE ); + } + + LOCK_HARDWARE(fmesa); + if (first_time) { + fmesa->wid = fmesa->ffb_sarea->wid_table[driDrawPriv->index]; + ffb_init_wid(fmesa, fmesa->wid); + } + + fmesa->state_dirty |= FFB_STATE_ALL; + fmesa->state_fifo_ents = fmesa->state_all_fifo_ents; + ffbSyncHardware(fmesa); + UNLOCK_HARDWARE(fmesa); + + if (first_time) { + /* Also, at the first switch to a new context, + * we need to clear all the hw buffers. + */ + ffbDDClear(fmesa->glCtx, + (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | + DD_DEPTH_BIT | DD_STENCIL_BIT), + 1, 0, 0, 0, 0); + } + } else { + _mesa_make_current(NULL, NULL); + } + + return GL_TRUE; +} + +/* Force the context `c' to be unbound from its buffer */ +static GLboolean +ffbUnbindContext(__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +static GLboolean +ffbOpenFullScreen(__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +static GLboolean +ffbCloseFullScreen(__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +void ffbXMesaUpdateState(ffbContextPtr fmesa) +{ + __DRIdrawablePrivate *dPriv = fmesa->driDrawable; + __DRIscreenPrivate *sPriv = fmesa->driScreen; + int stamp = dPriv->lastStamp; + + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + + if (dPriv->lastStamp != stamp) { + GLcontext *ctx = fmesa->glCtx; + + ffbCalcViewport(ctx); + if (ctx->Polygon.StippleFlag) + ffbXformAreaPattern(fmesa, + (const GLubyte *)ctx->PolygonStipple); + } +} + + +static struct __DriverAPIRec ffbAPI = { + ffbInitDriver, + ffbDestroyScreen, + ffbCreateContext, + ffbDestroyContext, + ffbCreateBuffer, + ffbDestroyBuffer, + ffbSwapBuffers, + ffbMakeCurrent, + ffbUnbindContext, + ffbOpenFullScreen, + ffbCloseFullScreen +}; + + + +/* + * This is the bootstrap function for the driver. + * The __driCreateScreen name is the symbol that libGL.so fetches. + * Return: pointer to a __DRIscreenPrivate. + */ +void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, + int numConfigs, __GLXvisualConfig *config) +{ + __DRIscreenPrivate *psp; + psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &ffbAPI); + return (void *) psp; +} + + +#endif /* GLX_DIRECT_RENDERING */ diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.h b/src/mesa/drivers/dri/ffb/ffb_xmesa.h new file mode 100644 index 00000000000..5569bd86624 --- /dev/null +++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.h @@ -0,0 +1,30 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */ + +#ifndef _FFB_XMESA_H_ +#define _FFB_XMESA_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include <sys/time.h> +#include "dri_util.h" +#include "mtypes.h" +#include "ffb_drishare.h" +#include "ffb_regs.h" +#include "ffb_dac.h" +#include "ffb_fifo.h" + +typedef struct { + __DRIscreenPrivate *sPriv; + ffb_fbcPtr regs; + ffb_dacPtr dac; + volatile char *sfb8r; + volatile char *sfb32; + volatile char *sfb64; + + int fifo_cache; + int rp_active; +} ffbScreenPrivate; + +#endif /* GLX_DIRECT_RENDERING */ + +#endif /* !(_FFB_XMESA_H) */ |